From 00a09284efa406c1f704a5a22048eeffe3f28505 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:28:23 +0100 Subject: [PATCH 001/106] lib: Add NonEmptyFileIterator Add iterator for iterating over non-empty files. --- library/Icinga/File/NonEmptyFileIterator.php | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 library/Icinga/File/NonEmptyFileIterator.php diff --git a/library/Icinga/File/NonEmptyFileIterator.php b/library/Icinga/File/NonEmptyFileIterator.php new file mode 100644 index 000000000..c5c7fda45 --- /dev/null +++ b/library/Icinga/File/NonEmptyFileIterator.php @@ -0,0 +1,49 @@ + + * + */ +class NonEmptyFileIterator extends FilterIterator +{ + /** + * Accept non-empty files + * + * @return bool Whether the current element of the iterator is acceptable + * through this filter + */ + public function accept() + { + $current = $this->current(); + /** @type $current \SplFileInfo */ + if (! $current->isFile() + || $current->getSize() === 0 + ) { + return false; + } + return true; + } +} From 1afc2a0b1dd86469c124d90b9913fd72a3c5ff94 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:28:49 +0100 Subject: [PATCH 002/106] lib: Add FileExtensionFilterIterator Add iterator for iterating over files having a specific file extension. --- .../File/FileExtensionFilterIterator.php | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 library/Icinga/File/FileExtensionFilterIterator.php diff --git a/library/Icinga/File/FileExtensionFilterIterator.php b/library/Icinga/File/FileExtensionFilterIterator.php new file mode 100644 index 000000000..909156749 --- /dev/null +++ b/library/Icinga/File/FileExtensionFilterIterator.php @@ -0,0 +1,71 @@ + + * + */ +class FileExtensionFilterIterator extends FilterIterator +{ + /** + * The extension to filter for + * + * @type string + */ + protected $extension; + + /** + * Create a new FileExtensionFilterIterator + * + * @param Iterator $iterator Apply filter to this iterator + * @param string $extension The file extension to filter for. The file extension may not contain the leading dot + */ + public function __construct(Iterator $iterator, $extension) + { + $this->extension = '.' . ltrim(strtolower((string) $extension), '.'); + parent::__construct($iterator); + } + + /** + * Accept files which match the file extension to filter for + * + * @return bool Whether the current element of the iterator is acceptable + * through this filter + */ + public function accept() + { + $current = $this->current(); + /* @var $current \SplFileInfo */ + if (! $current->isFile()) { + return false; + } + // SplFileInfo::getExtension() is only available since PHP 5 >= 5.3.6 + $filename = $current->getFilename(); + $sfx = substr($filename, -strlen($this->extension)); + return $sfx === false ? false : strtolower($sfx) === $this->extension; + } +} From 5f772c36202422162ab4e40884f0b9a79759c040 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:29:48 +0100 Subject: [PATCH 003/106] doc: Use Icinga Web 2's iterators --- modules/doc/library/Doc/DocIterator.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/doc/library/Doc/DocIterator.php b/modules/doc/library/Doc/DocIterator.php index 43a9c7727..3045b6309 100644 --- a/modules/doc/library/Doc/DocIterator.php +++ b/modules/doc/library/Doc/DocIterator.php @@ -9,6 +9,8 @@ use Countable; use IteratorAggregate; use RecursiveIteratorIterator; use RecursiveDirectoryIterator; +use Icinga\File\NonEmptyFileIterator; +use Icinga\File\FileExtensionFilterIterator; /** * Iterator over non-empty Markdown files ordered by the case insensitive "natural order" of file names @@ -29,12 +31,14 @@ class DocIterator implements Countable, IteratorAggregate */ public function __construct($path) { - $it = new RecursiveIteratorIterator( + $it = new FileExtensionFilterIterator( new NonEmptyFileIterator( - new MarkdownFileIterator( - new RecursiveDirectoryIterator($path) + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path), + RecursiveIteratorIterator::SELF_FIRST ) - ) + ), + 'md' ); // Unfortunately we have no chance to sort the iterator $fileInfo = iterator_to_array($it); From 001eba73e73e83b53ac5ff344f3ab64622834109 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:30:08 +0100 Subject: [PATCH 004/106] doc: Remove iterators because they are superseded by iterators from Icinga Web 2's library --- .../doc/library/Doc/MarkdownFileIterator.php | 31 ------------------- .../doc/library/Doc/NonEmptyFileIterator.php | 31 ------------------- 2 files changed, 62 deletions(-) delete mode 100644 modules/doc/library/Doc/MarkdownFileIterator.php delete mode 100644 modules/doc/library/Doc/NonEmptyFileIterator.php diff --git a/modules/doc/library/Doc/MarkdownFileIterator.php b/modules/doc/library/Doc/MarkdownFileIterator.php deleted file mode 100644 index 6f317ce6a..000000000 --- a/modules/doc/library/Doc/MarkdownFileIterator.php +++ /dev/null @@ -1,31 +0,0 @@ -getInnerIterator()->current(); - /* @var $current \SplFileInfo */ - if (! $current->isFile()) { - return false; - } - $filename = $current->getFilename(); - $sfx = substr($filename, -3); - return $sfx === false ? false : strtolower($sfx) === '.md'; - } -} diff --git a/modules/doc/library/Doc/NonEmptyFileIterator.php b/modules/doc/library/Doc/NonEmptyFileIterator.php deleted file mode 100644 index 71bf5acfa..000000000 --- a/modules/doc/library/Doc/NonEmptyFileIterator.php +++ /dev/null @@ -1,31 +0,0 @@ -getInnerIterator()->current(); - /* @var $current \SplFileInfo */ - if (! $current->isFile() - || $current->getSize() === 0 - ) { - return false; - } - return true; - } -} From ca8dbdb9386e8a23ae246eac3f532039c31dd31c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:50:29 +0100 Subject: [PATCH 005/106] doc: Make path to Icinga Web 2's doc configureable refs #7196 --- .../controllers/IcingawebController.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index 5740f50a9..d052d8268 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -8,12 +8,20 @@ use Icinga\Module\Doc\DocController; class Doc_IcingawebController extends DocController { + /** + * Get the path to Icinga Web 2's documentation + */ + protected function getDocPath() + { + return $this->Config()->get('documentation', 'path', Icinga::app()->getBaseDir('doc')); + } + /** * View the toc of Icinga Web 2's documentation */ public function tocAction() { - return $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter'); + return $this->renderToc($this->getDocPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } /** @@ -31,7 +39,7 @@ class Doc_IcingawebController extends DocController ); } return $this->renderChapter( - Icinga::app()->getApplicationDir('/../doc'), + $this->getDocPath(), $chapterId, 'doc/icingaweb/toc', 'doc/icingaweb/chapter' @@ -43,6 +51,6 @@ class Doc_IcingawebController extends DocController */ public function pdfAction() { - return $this->renderPdf(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter'); + return $this->renderPdf($this->getDocPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } } From cc619e0a7b8c1d27d14ababa3f5cc6d921b8f59e Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:53:44 +0100 Subject: [PATCH 006/106] doc/configuration.php: Prefer @type over @var --- modules/doc/configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/configuration.php b/modules/doc/configuration.php index 87e5da77a..6e924e964 100644 --- a/modules/doc/configuration.php +++ b/modules/doc/configuration.php @@ -2,7 +2,7 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -/* @var $this \Icinga\Application\Modules\Module */ +/** @type $this \Icinga\Application\Modules\Module */ $section = $this->menuSection($this->translate('Documentation'), array( 'title' => 'Documentation', From da575910e6c844067adb37c6bccb143266ea029f Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:54:41 +0100 Subject: [PATCH 007/106] doc/run.php: Remove superfluous newline --- modules/doc/run.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/doc/run.php b/modules/doc/run.php index 7392e4c22..31aff8ff0 100644 --- a/modules/doc/run.php +++ b/modules/doc/run.php @@ -47,4 +47,3 @@ $this->addRoute('doc/module/chapter', $docModuleChapter); $this->addRoute('doc/icingaweb/chapter', $docIcingaWebChapter); $this->addRoute('doc/module/toc', $docModuleToc); $this->addRoute('doc/module/pdf', $docModulePdf); - From 19d89f0a67de95ce5314dd6a15d39b0917d05597 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:55:12 +0100 Subject: [PATCH 008/106] monitoring/configuration.php: Prefer @type over @var --- modules/monitoring/configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/configuration.php b/modules/monitoring/configuration.php index d61e32858..b1cdee2de 100644 --- a/modules/monitoring/configuration.php +++ b/modules/monitoring/configuration.php @@ -2,7 +2,7 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -/** @var $this \Icinga\Application\Modules\Module */ +/** @type $this \Icinga\Application\Modules\Module */ $this->providePermission( 'monitoring/command/*', From 51b47df4c5bb67337e333a505e330e59ac878fe3 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:55:29 +0100 Subject: [PATCH 009/106] doc: Set version to 2.0.0 --- modules/doc/module.info | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/module.info b/modules/doc/module.info index 2826d72de..1689fd940 100644 --- a/modules/doc/module.info +++ b/modules/doc/module.info @@ -1,4 +1,4 @@ Module: doc -Version: 2.0.0~alpha4 +Version: 2.0.0 Description: Documentation module Extracts, shows and exports documentation for Icinga Web 2 and it's modules. From 7edb1217c6ac936e1a351eb2a76caaa44404aa0d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 12:57:16 +0100 Subject: [PATCH 010/106] doc: Use sprintf for "Missing parameter x" exceptions --- modules/doc/application/controllers/ModuleController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index 1e9cf43b1..adc46a991 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -37,7 +37,7 @@ class Doc_ModuleController extends DocController { if (empty($moduleName)) { throw new Zend_Controller_Action_Exception( - $this->translate('Missing parameter \'moduleName\''), + sprintf($this->translate('Missing parameter \'%s\''), 'moduleName'), 404 ); } From 40b709848005098f6a0e20db27392f2326101f9d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:24:11 +0100 Subject: [PATCH 011/106] doc/parser: Fix PHPDoc indentation --- modules/doc/library/Doc/DocParser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index c63532dc1..6cfeca418 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -31,7 +31,7 @@ class DocParser /** * Create a new documentation parser for the given path * - * @param string $path Path to the documentation + * @param string $path Path to the documentation * * @throws DocException If the documentation directory does not exist * @throws NotReadableError If the documentation directory is not readable From 823d338f73cd1470315bffb5c4d83f8728e2de93 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:24:45 +0100 Subject: [PATCH 012/106] doc/Controller: Do not use 'void' results --- modules/doc/library/Doc/DocController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php index bc782953f..0d12f58df 100644 --- a/modules/doc/library/Doc/DocController.php +++ b/modules/doc/library/Doc/DocController.php @@ -28,7 +28,7 @@ class DocController extends ModuleActionController $urlParams ); $this->view->title = $chapterId; - return $this->render('chapter', null, true); + $this->render('chapter', null, true); } /** @@ -46,7 +46,7 @@ class DocController extends ModuleActionController $name = ucfirst($name); $this->view->docName = $name; $this->view->title = sprintf($this->translate('%s Documentation'), $name); - return $this->render('toc', null, true); + $this->render('toc', null, true); } /** @@ -71,6 +71,6 @@ class DocController extends ModuleActionController ); $this->view->docName = $name; $this->_request->setParam('format', 'pdf'); - return $this->render('pdf', null, true); + $this->render('pdf', null, true); } } From 08bbe596790285aa7eee78a75f0b8df05a774e3d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:27:02 +0100 Subject: [PATCH 013/106] doc: Throw an exception if Icinga Web 2's documentation is not avaiable refs #7196 --- .../controllers/IcingawebController.php | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index d052d8268..b989bc883 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -10,10 +10,26 @@ class Doc_IcingawebController extends DocController { /** * Get the path to Icinga Web 2's documentation + * + * @return string + * + * @throws Zend_Controller_Action_Exception If Icinga Web 2's documentation is not available */ - protected function getDocPath() + protected function getPath() { - return $this->Config()->get('documentation', 'path', Icinga::app()->getBaseDir('doc')); + if (($path = $this->Config()->get('documentation', 'icingaweb2')) !== null) { + if (is_dir($path)) { + return $path; + } + } + $path = Icinga::app()->getBaseDir('doc'); + if (is_dir($path)) { + return $path; + } + throw new Zend_Controller_Action_Exception( + $this->translate('Documentation for Icinga Web 2 is not available'), + 404 + ); } /** @@ -21,7 +37,7 @@ class Doc_IcingawebController extends DocController */ public function tocAction() { - return $this->renderToc($this->getDocPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); + return $this->renderToc($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } /** @@ -39,7 +55,7 @@ class Doc_IcingawebController extends DocController ); } return $this->renderChapter( - $this->getDocPath(), + $this->getPath(), $chapterId, 'doc/icingaweb/toc', 'doc/icingaweb/chapter' @@ -51,6 +67,6 @@ class Doc_IcingawebController extends DocController */ public function pdfAction() { - return $this->renderPdf($this->getDocPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); + return $this->renderPdf($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } } From 7605076dc525832eea119eb2520abe22f8cf7a64 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:28:10 +0100 Subject: [PATCH 014/106] doc/IcingawebController: Use sprintf for "Missing parameter x" exceptions --- modules/doc/application/controllers/IcingawebController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index b989bc883..b51c126ae 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -50,7 +50,7 @@ class Doc_IcingawebController extends DocController $chapterId = $this->getParam('chapterId'); if ($chapterId === null) { throw new Zend_Controller_Action_Exception( - $this->translate('Missing parameter \'chapterId\''), + sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'), 404 ); } From e901e545c3b78e376bb653dcf446b0415ed56100 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:28:58 +0100 Subject: [PATCH 015/106] doc/IcingawebController: Do not use 'void' results --- modules/doc/application/controllers/IcingawebController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index b51c126ae..c07b65798 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -37,7 +37,7 @@ class Doc_IcingawebController extends DocController */ public function tocAction() { - return $this->renderToc($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); + $this->renderToc($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } /** @@ -54,7 +54,7 @@ class Doc_IcingawebController extends DocController 404 ); } - return $this->renderChapter( + $this->renderChapter( $this->getPath(), $chapterId, 'doc/icingaweb/toc', @@ -67,6 +67,6 @@ class Doc_IcingawebController extends DocController */ public function pdfAction() { - return $this->renderPdf($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); + $this->renderPdf($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } } From c7e6252acab649bb0a2f21a296cb13255b36dfa5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:30:10 +0100 Subject: [PATCH 016/106] doc: Make path to module documentations configureable refs #7196 --- .../controllers/ModuleController.php | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index adc46a991..12c4a9246 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -9,6 +9,40 @@ use Icinga\Module\Doc\Exception\DocException; class Doc_ModuleController extends DocController { + /** + * Get the path to a module documentation + * + * @param string $module The name of the module + * @param string $default The default path + * @param bool $suppressErrors Whether to not throw an exception if the module documentation is not + * available + * + * @return string|null Path to the documentation or null if the module documentation is not + * available and errors are suppressed + * + * @throws Zend_Controller_Action_Exception If the module documentation is not available and errors are not + * suppressed + */ + protected function getPath($module, $default, $suppressErrors = false) + { + if (($path = $this->Config()->get('documentation', 'modules')) !== null) { + $path = str_replace('{module}', $module, $path); + if (is_dir($path)) { + return $path; + } + } + if (is_dir($default)) { + return $default; + } + if ($suppressErrors) { + return null; + } + throw new Zend_Controller_Action_Exception( + sprintf($this->translate('Documentation for module \'%s\' is not available'), $module), + 404 + ); + } + /** * List modules which are enabled and having the 'doc' directory */ @@ -16,10 +50,10 @@ class Doc_ModuleController extends DocController { $moduleManager = Icinga::app()->getModuleManager(); $modules = array(); - foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $enabledModule) { - $docDir = $moduleManager->getModuleDir($enabledModule, '/doc'); - if (is_dir($docDir)) { - $modules[] = $enabledModule; + foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $module) { + $path = $this->getPath($module, $moduleManager->getModuleDir($module, '/doc'), true); + if ($path !== null) { + $modules[] = $module; } } $this->view->modules = $modules; @@ -63,16 +97,15 @@ class Doc_ModuleController extends DocController */ public function tocAction() { - $moduleName = $this->getParam('moduleName'); - $this->assertModuleEnabled($moduleName); - $this->view->moduleName = $moduleName; - $moduleManager = Icinga::app()->getModuleManager(); + $module = $this->getParam('moduleName'); + $this->assertModuleEnabled($module); + $this->view->moduleName = $module; try { return $this->renderToc( - $moduleManager->getModuleDir($moduleName, '/doc'), - $moduleName, + $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), + $module, 'doc/module/chapter', - array('moduleName' => $moduleName) + array('moduleName' => $module) ); } catch (DocException $e) { throw new Zend_Controller_Action_Exception($e->getMessage(), 404); @@ -88,24 +121,23 @@ class Doc_ModuleController extends DocController */ public function chapterAction() { - $moduleName = $this->getParam('moduleName'); - $this->assertModuleEnabled($moduleName); + $module = $this->getParam('moduleName'); + $this->assertModuleEnabled($module); $chapterId = $this->getParam('chapterId'); if ($chapterId === null) { throw new Zend_Controller_Action_Exception( - $this->translate('Missing parameter \'chapterId\''), + sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'), 404 ); } - $this->view->moduleName = $moduleName; - $moduleManager = Icinga::app()->getModuleManager(); + $this->view->moduleName = $module; try { return $this->renderChapter( - $moduleManager->getModuleDir($moduleName, '/doc'), + $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), $chapterId, - $this->_helper->url->url(array('moduleName' => $moduleName), 'doc/module/toc'), + $this->_helper->url->url(array('moduleName' => $module), 'doc/module/toc'), 'doc/module/chapter', - array('moduleName' => $moduleName) + array('moduleName' => $module) ); } catch (DocException $e) { throw new Zend_Controller_Action_Exception($e->getMessage(), 404); @@ -119,14 +151,13 @@ class Doc_ModuleController extends DocController */ public function pdfAction() { - $moduleName = $this->getParam('moduleName'); - $this->assertModuleEnabled($moduleName); - $moduleManager = Icinga::app()->getModuleManager(); + $module = $this->getParam('moduleName'); + $this->assertModuleEnabled($module); return $this->renderPdf( - $moduleManager->getModuleDir($moduleName, '/doc'), - $moduleName, + $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), + $module, 'doc/module/chapter', - array('moduleName' => $moduleName) + array('moduleName' => $module) ); } } From 3120a0c090b7d54775cef12d93c772e2835fc122 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:30:57 +0100 Subject: [PATCH 017/106] doc/ModuleController: Do not use 'void' results --- modules/doc/application/controllers/ModuleController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index 12c4a9246..cf9ddea16 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -101,7 +101,7 @@ class Doc_ModuleController extends DocController $this->assertModuleEnabled($module); $this->view->moduleName = $module; try { - return $this->renderToc( + $this->renderToc( $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), $module, 'doc/module/chapter', @@ -132,7 +132,7 @@ class Doc_ModuleController extends DocController } $this->view->moduleName = $module; try { - return $this->renderChapter( + $this->renderChapter( $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), $chapterId, $this->_helper->url->url(array('moduleName' => $module), 'doc/module/toc'), @@ -153,7 +153,7 @@ class Doc_ModuleController extends DocController { $module = $this->getParam('moduleName'); $this->assertModuleEnabled($module); - return $this->renderPdf( + $this->renderPdf( $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), $module, 'doc/module/chapter', From d2a7254a37ebdeefd3b176d69f66fc54582591a6 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:55:24 +0100 Subject: [PATCH 018/106] doc: Prefer "root" doc path over configured path If the "root" doc path, i.e. application/doc exists, it is preferred over the configured one. refs #4075 --- .../doc/application/controllers/IcingawebController.php | 8 ++++---- modules/doc/application/controllers/ModuleController.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index c07b65798..60c5da5ee 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -17,15 +17,15 @@ class Doc_IcingawebController extends DocController */ protected function getPath() { + $path = Icinga::app()->getBaseDir('doc'); + if (is_dir($path)) { + return $path; + } if (($path = $this->Config()->get('documentation', 'icingaweb2')) !== null) { if (is_dir($path)) { return $path; } } - $path = Icinga::app()->getBaseDir('doc'); - if (is_dir($path)) { - return $path; - } throw new Zend_Controller_Action_Exception( $this->translate('Documentation for Icinga Web 2 is not available'), 404 diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index cf9ddea16..a4d14cf61 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -25,15 +25,15 @@ class Doc_ModuleController extends DocController */ protected function getPath($module, $default, $suppressErrors = false) { + if (is_dir($default)) { + return $default; + } if (($path = $this->Config()->get('documentation', 'modules')) !== null) { $path = str_replace('{module}', $module, $path); if (is_dir($path)) { return $path; } } - if (is_dir($default)) { - return $default; - } if ($suppressErrors) { return null; } From bca2335aa341836f1c102a8ba7e3bcf90755590c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:58:18 +0100 Subject: [PATCH 019/106] doc: Add module documentation --- modules/doc/doc/1-module-documentation.md | 59 ++++++++++++++++++++++ modules/doc/public/img/doc/markdown.png | Bin 0 -> 2180 bytes 2 files changed, 59 insertions(+) create mode 100644 modules/doc/doc/1-module-documentation.md create mode 100644 modules/doc/public/img/doc/markdown.png diff --git a/modules/doc/doc/1-module-documentation.md b/modules/doc/doc/1-module-documentation.md new file mode 100644 index 000000000..968dd32d7 --- /dev/null +++ b/modules/doc/doc/1-module-documentation.md @@ -0,0 +1,59 @@ +# Writing Module Documentation + +![Markdown](/img/doc/doc/markdown.png) + +Icinga Web 2 is capable of viewing your module's documentation, if the documentation is written in +[Markdown](http://en.wikipedia.org/wiki/Markdown). Please refer to +[Markdown Syntax Documentation](http://daringfireball.net/projects/markdown/syntax) for Markdown's formatting syntax. + +## Where to Put Module Documentation? + +By default, your module's Markdown documentation files must be placed in the `doc` directory beneath your module's root +directory, e.g.: + + example-module/doc + +## Chapters + +Each Markdown documentation file represents a chapter of your module's documentation. The first found heading inside +each file is the chapter's title. The order of chapters is based on the case insensitive "Natural Order" of your files' +names. Natural Order means that the file names are ordered in the way which seems natural to humans. +It is best practice to prefix Markdown documentation file names with numbers to ensure that they appear in the correct +order, e.g.: + + 1-about.md + 2-installation.md + 3-configuration.md + +## Table Of Contents + +The table of contents for your module's documentation is auto-generated based on all found headings inside each +Markdown documentation file. + +## Linking Between Headings + +For linking between headings, place an anchor where you want to link to, e.g.: + + # Heading + +Now you can reference the anchor either in the same or **in another** Markdown documentation file, e.g.: + + This is a link to [Heading](#heading). + +## Including Images + +Images must placed in the `img` directory beneath your module's `public` directory, e.g.: + + example-module/public/img/doc + +Module images can be accessed using the following URL: + + {baseURL}/img/{moduleName}/{file} e.g. icingaweb/img/example-module/doc/example.png + +Markdown's image syntax is very similar to Markdown's link syntax, but prefixed with an exclamation mark, e.g.: + + ![Alt text](http://path/to/img.png "Optional Title") + +URLs to images inside your Markdown documentation files must be specified without the base URL, e.g.: + + ![Example](/img/example-module/doc/example.png) diff --git a/modules/doc/public/img/doc/markdown.png b/modules/doc/public/img/doc/markdown.png new file mode 100644 index 0000000000000000000000000000000000000000..93e729bc77ca37a36b97509e4cd552e1033973f9 GIT binary patch literal 2180 zcmaJ@3pCSxAD^wcY}Rs*WtD5G;fWbxQ?n;Z>?w^%R6I%eyW|avwnDTzlpgZBtwM^W z$&fc$p0XlZVkGpJ%9=})+uYyj>FGV^J@0wX@BDth^Z8yr-|z2ozQ11@)qNKVp@)D# zAShQC=Y8^7DDMnqMfn(SHgsM-DIVRk%Neq~(%AL4Ga(RVJ6Go&p0RnOeIBWSURr{2 zV9NH=6SaIdWsU6zYpF*>w^r?SPJ8+5^CpE~4C*p6D4tIbHc`%DUNAB?veYywr;e#^ zaz?4Cq&-PC+*Haouxvm2{sx1AYzT)DwFiqExY&4%=43HC+dds?#|>&h%xi^ zx;6p^oiWdh=I8VE`M9QZo$(Po7!aOhnQsZFP=G)5(%X|~By~=Fx_lO@0(H6fcjZ<{(!+q{M7 zL%a|jm|;W^eX>Z+2pb&>WxVuf6&!N%q75st9Gx}3Q_&xzMt`HSqJro z=%-qo`Uky~8XXLd8(}89bD>p%pY+T+uzIl$FBBc8OCTI?yA%ZPf+E(Vaz}doW~Y<1 zX6lV+Kiz{{drp-KLw>pkdUMIiS$`+v#&ciXRrd?z5=^O#DOo^RZ*8I8 zn39t$x64;()pZw=%nK<6kNl+3e3*sOdh~bFR-Jm$nF9xz(E1$M5aT54{a2{h_-um5 z*pMM*Y^a?KloXT@o!8nscnXD1qV_Gq*X9~?3AHgBx5Uc)<1OEMZGZ>U<7{6jW}-44 zCu#gV*-1_ISDtx5^4Dr}r{*u8E_V#_k#Hg)i9hn2Z#rPJI({T93Mgt*{`&UNvsduX z6>9z0^WO{=g$R!UnR$(^OeBApgWT8=!K7xMD$lkUSUqunHu{krPhb%(-@D)M@dS_^ z@79xSB?80v@7rlJ3*qURsglq4EH>5lf{`b91>MqLwvo{Ig8SE?`z7|U5gl1g7AGMK zAaY(;bgIhSlLfb?=4^7&MlWBHFPm;H=6B4EDTZsxW}1eZKD-a_G zBF7ze){N?3Hl+mm>0)){4D%{1oTXPnaSEa(MUgXqnTs6JD&A;X7-0p&3b zTyyPGyO}!gaytCE(LYMpSXr-~5CY`_WJmr<$HVsl1IhJM3_j5_RbTH?+!sPh7ml>q z_f)wiTRH2-PKn=R$0^L8@3IOzaNB7JYS965^17O&NfDrG;hPv0`kK3sVSvM!g>IL# zihy#FTo|?@w6VmR6{(_{9Hud4omqvB691u{3OzzgPnVT2qXgP0j`Xlb?7i7Z<*~~W zvV}fIpmA^{_iLNcbN<{eUE^ z&}U^G8;+L%=m6x--fhz~VUtnK@2uGsJ9%{8-hkkt7G3QtF>2{~K{ucQ2 zoI6vwN`gZ# zKMW;V<~MuSy6m~FJT&>>Y0$tit47L`8RomPY+Pl%{Qa=!pJkY0bPOxQ%wd4)#8@WZ zpK0IIX;_J$X3oI6E)e$l!yk9t!(QQh3j((zbGSW7u-de3;TBTxpAw02RWW#WF@b|}A1v5Hkbm`Ii v0@|%qBtaQNUf$8&Gpzv{H;#JK<}AKdSfrDxI5YBZ1;mx&?tE`&z`1_|&HV@> literal 0 HcmV?d00001 From 28f08078f05e6f422d72a55d14b5a7373aa35ed8 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 14:58:39 +0100 Subject: [PATCH 020/106] doc: Add module config.ini for packaging resolves #7196 --- packages/files/modules/doc/config.ini | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/files/modules/doc/config.ini diff --git a/packages/files/modules/doc/config.ini b/packages/files/modules/doc/config.ini new file mode 100644 index 000000000..80df20784 --- /dev/null +++ b/packages/files/modules/doc/config.ini @@ -0,0 +1,3 @@ +[documentation] +icingaweb2 = /usr/share/doc/icingaweb2/markdown +modules = /usr/share/doc/icingaweb2/modules/{module}/markdown From 7d00f68660af4f54652e1f7bfd7941c9ca9a20d2 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 16:27:04 +0100 Subject: [PATCH 021/106] Revert "Load core modules also when bootstrapping the CLI" This reverts commit f12473d34bf55b2acea2a196d5455ad851dbf86b. The CLI must not load core modules, i.e. setup. --- library/Icinga/Application/Cli.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/Icinga/Application/Cli.php b/library/Icinga/Application/Cli.php index abf46262f..7d1a98eec 100644 --- a/library/Icinga/Application/Cli.php +++ b/library/Icinga/Application/Cli.php @@ -43,8 +43,7 @@ class Cli extends ApplicationBootstrap ->parseBasicParams() ->setupLogger() ->setupResourceFactory() - ->setupModuleManager() - ->loadCoreModules(); + ->setupModuleManager(); } protected function setupLogging() From 916868a051755bdacc899c9d61557b1d11e54014 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 16:28:05 +0100 Subject: [PATCH 022/106] Revert "Add support for "core" modules and make the setup module such a module" This reverts commit 8af13f564b3f8e69c2c1abcda5d7e2e5266c3c7d. The setup module must only be loaded when necessary not always. --- .../Application/ApplicationBootstrap.php | 15 --------- .../Icinga/Application/Modules/Manager.php | 32 ++----------------- library/Icinga/Application/Web.php | 1 - .../Util/GettextTranslationHelper.php | 2 +- 4 files changed, 3 insertions(+), 47 deletions(-) diff --git a/library/Icinga/Application/ApplicationBootstrap.php b/library/Icinga/Application/ApplicationBootstrap.php index 7f1667e5b..733cdbf83 100644 --- a/library/Icinga/Application/ApplicationBootstrap.php +++ b/library/Icinga/Application/ApplicationBootstrap.php @@ -378,21 +378,6 @@ abstract class ApplicationBootstrap return $this; } - /** - * Load all core modules - * - * @return self - */ - protected function loadCoreModules() - { - try { - $this->moduleManager->loadCoreModules(); - } catch (NotReadableError $e) { - Logger::error(new IcingaException('Cannot load core modules. An exception was thrown:', $e)); - } - return $this; - } - /** * Load all enabled modules * diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php index 6469d3929..7ee2461f9 100644 --- a/library/Icinga/Application/Modules/Manager.php +++ b/library/Icinga/Application/Modules/Manager.php @@ -68,18 +68,6 @@ class Manager */ private $modulePaths = array(); - /** - * The core modules - * - * Core modules do not need to be enabled to load and cannot be disabled - * by the user. This must not be writable programmatically! - * - * @var array - */ - private $coreModules = array( - 'setup' - ); - /** * Create a new instance of the module manager * @@ -170,21 +158,7 @@ class Manager } /** - * Try to set all core modules in loaded state - * - * @return self - * @see Manager::loadModule() - */ - public function loadCoreModules() - { - foreach ($this->coreModules as $name) { - $this->loadModule($name); - } - return $this; - } - - /** - * Try to set all enabled modules in loaded state + * Try to set all enabled modules in loaded sate * * @return self * @see Manager::loadModule() @@ -239,8 +213,6 @@ class Manager 'Cannot enable module "%s". Module is not installed.', $name ); - } elseif (in_array($name, $this->coreModules)) { - return $this; } clearstatcache(true); @@ -458,7 +430,7 @@ class Manager } $installed = $this->listInstalledModules(); - foreach (array_diff($installed, $this->coreModules) as $name) { + foreach ($installed as $name) { $info[$name] = (object) array( 'name' => $name, 'path' => $this->installedBaseDirs[$name], diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php index 37ec5138a..a21f21025 100644 --- a/library/Icinga/Application/Web.php +++ b/library/Icinga/Application/Web.php @@ -104,7 +104,6 @@ class Web extends ApplicationBootstrap ->setupZendMvc() ->setupFormNamespace() ->setupModuleManager() - ->loadCoreModules() ->loadEnabledModules() ->setupRoute() ->setupPagination(); diff --git a/modules/translation/library/Translation/Util/GettextTranslationHelper.php b/modules/translation/library/Translation/Util/GettextTranslationHelper.php index 0d5a950e1..5702def85 100644 --- a/modules/translation/library/Translation/Util/GettextTranslationHelper.php +++ b/modules/translation/library/Translation/Util/GettextTranslationHelper.php @@ -101,7 +101,7 @@ class GettextTranslationHelper */ public function __construct(ApplicationBootstrap $bootstrap, $locale) { - $this->moduleMgr = $bootstrap->getModuleManager()->loadCoreModules()->loadEnabledModules(); + $this->moduleMgr = $bootstrap->getModuleManager()->loadEnabledModules(); $this->appDir = $bootstrap->getApplicationDir(); $this->locale = $locale; } From d0e8718d619f7a6671e23aa23a6cc9c7e2d348e4 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 9 Dec 2014 16:56:06 +0100 Subject: [PATCH 023/106] packages: Rename icingaweb.conf to icingaweb2.conf --- packages/files/apache/{icingaweb.conf => icingaweb2.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/files/apache/{icingaweb.conf => icingaweb2.conf} (100%) diff --git a/packages/files/apache/icingaweb.conf b/packages/files/apache/icingaweb2.conf similarity index 100% rename from packages/files/apache/icingaweb.conf rename to packages/files/apache/icingaweb2.conf From ef00765ff0828c9225c97f353fbcb57b20245c8e Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 10 Dec 2014 09:29:38 +0100 Subject: [PATCH 024/106] packages: Use 'icingaweb2' as the web path refs #4075 --- packages/files/apache/icingaweb2.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/files/apache/icingaweb2.conf b/packages/files/apache/icingaweb2.conf index 2c52b73e3..6bf0b7a66 100644 --- a/packages/files/apache/icingaweb2.conf +++ b/packages/files/apache/icingaweb2.conf @@ -1,4 +1,4 @@ -Alias /icingaweb "/usr/share/icingaweb2/public" +Alias /icingaweb2 "/usr/share/icingaweb2/public" Options SymLinksIfOwnerMatch @@ -23,7 +23,7 @@ Alias /icingaweb "/usr/share/icingaweb2/public" RewriteEngine on - RewriteBase /icingaweb/ + RewriteBase /icingaweb2/ RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d From 2b5fe7baf4a8e0cd50eefe834e061c8dd5696d87 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 10 Dec 2014 09:30:12 +0100 Subject: [PATCH 025/106] Set default config dir to '/etc/icingaweb2' --- library/Icinga/Application/ApplicationBootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Application/ApplicationBootstrap.php b/library/Icinga/Application/ApplicationBootstrap.php index 733cdbf83..5e2a787c7 100644 --- a/library/Icinga/Application/ApplicationBootstrap.php +++ b/library/Icinga/Application/ApplicationBootstrap.php @@ -133,7 +133,7 @@ abstract class ApplicationBootstrap if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) { $configDir = $_SERVER['ICINGAWEB_CONFIGDIR']; } else { - $configDir = '/etc/icingaweb'; + $configDir = '/etc/icingaweb2'; } } $canonical = realpath($configDir); From 613cbae5bfc7d278da24923ab3970c43a289cf95 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 10 Dec 2014 09:30:35 +0100 Subject: [PATCH 026/106] packages: Fix base dir path in the icingacli refs #4075 --- packages/files/bin/icingacli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/files/bin/icingacli b/packages/files/bin/icingacli index 10b4857aa..5b41e4e8c 100755 --- a/packages/files/bin/icingacli +++ b/packages/files/bin/icingacli @@ -3,4 +3,4 @@ require_once '/usr/share/php/Icinga/Application/Cli.php'; -Icinga\Application\Cli::start('/usr/share/icingaweb')->dispatch(); +Icinga\Application\Cli::start('/usr/share/icingaweb2')->dispatch(); From 888fa90fe209edcd19b278ced262e70c5a638f6a Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 10 Dec 2014 09:31:37 +0100 Subject: [PATCH 027/106] Fix typo in PHPDoc in EmbeddedWeb --- library/Icinga/Application/EmbeddedWeb.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Application/EmbeddedWeb.php b/library/Icinga/Application/EmbeddedWeb.php index 23cb365f0..72a4ec919 100644 --- a/library/Icinga/Application/EmbeddedWeb.php +++ b/library/Icinga/Application/EmbeddedWeb.php @@ -9,7 +9,7 @@ require_once dirname(__FILE__) . '/ApplicationBootstrap.php'; use Icinga\Exception\ProgrammingError; /** - * Use this if you want to make use of Icinga funtionality in other web projects + * Use this if you want to make use of Icinga functionality in other web projects * * Usage example: * From 68e460b5d12e468e95ad058f649153fa96a59cdd Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 10 Dec 2014 09:32:02 +0100 Subject: [PATCH 028/106] Remove unused use in EmbeddedWeb --- library/Icinga/Application/EmbeddedWeb.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/Icinga/Application/EmbeddedWeb.php b/library/Icinga/Application/EmbeddedWeb.php index 72a4ec919..b9ed067a2 100644 --- a/library/Icinga/Application/EmbeddedWeb.php +++ b/library/Icinga/Application/EmbeddedWeb.php @@ -6,8 +6,6 @@ namespace Icinga\Application; require_once dirname(__FILE__) . '/ApplicationBootstrap.php'; -use Icinga\Exception\ProgrammingError; - /** * Use this if you want to make use of Icinga functionality in other web projects * From 2f3667aa3dba85224483ed48e324b4a27f09844a Mon Sep 17 00:00:00 2001 From: Carlos Cesario Date: Wed, 17 Dec 2014 10:00:15 -0200 Subject: [PATCH 029/106] Use hosts link instead services link Use hosts link instead services link to show hosts group. refs #7259 --- .../monitoring/application/views/scripts/list/hostgroups.phtml | 2 +- .../application/views/scripts/show/components/hostgroups.phtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/application/views/scripts/list/hostgroups.phtml b/modules/monitoring/application/views/scripts/list/hostgroups.phtml index a15b5be7e..0e21dc3ee 100644 --- a/modules/monitoring/application/views/scripts/list/hostgroups.phtml +++ b/modules/monitoring/application/views/scripts/list/hostgroups.phtml @@ -79,7 +79,7 @@ - + hostgroup; ?> diff --git a/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml index 40db3e5c4..165df627a 100644 --- a/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml +++ b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml @@ -4,7 +4,7 @@ if (empty($object->hostgroups)) return; $list = array(); foreach ($object->hostgroups as $name => $alias) { - $list[] = $this->qlink($alias, 'monitoring/list/services', array( + $list[] = $this->qlink($alias, 'monitoring/list/hosts', array( 'hostgroup' => $name )); } From ec3466e1ed37cfc65b3d6aa3abbdb7dd74d4c5c8 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 13:53:22 +0100 Subject: [PATCH 030/106] Vagrant: Bump required version to 1.5.0 We require the Vagrant Cloud from now on for downloading base boxes. --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 02c92f214..28b69cab9 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -2,7 +2,7 @@ # vi: set ft=ruby : VAGRANTFILE_API_VERSION = "2" -VAGRANT_REQUIRED_VERSION = "1.2.0" +VAGRANT_REQUIRED_VERSION = "1.5.0" # Require 1.2.x at least if ! defined? Vagrant.require_version From 9e2de4308959f13664c0653fe362930d0f420033 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 14:28:58 +0100 Subject: [PATCH 031/106] Remove etc/license_header.txt This file is not in use. --- etc/license_header.txt | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 etc/license_header.txt diff --git a/etc/license_header.txt b/etc/license_header.txt deleted file mode 100644 index db19a8436..000000000 --- a/etc/license_header.txt +++ /dev/null @@ -1,5 +0,0 @@ -Icinga Web 2 - -@link https://www.icinga.org/icingaweb2/ -@copyright Copyright (c) 2013-%(YEAR)s Icinga Development Team (https://www.icinga.org) -@license http://www.gnu.org/licenses/gpl-2.0.txt, or any later version \ No newline at end of file From b3994f1099d51e6e1b3e9d9bca657c80972ccda2 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 15:24:06 +0100 Subject: [PATCH 032/106] doc: Add chapter IDs to authentication.md --- doc/authentication.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/doc/authentication.md b/doc/authentication.md index 994d44e48..a4fdc2fcc 100644 --- a/doc/authentication.md +++ b/doc/authentication.md @@ -2,21 +2,23 @@ **Choosing the Authentication Method** -With Icinga Web 2 you can authenticate against Active Directory, LDAP, a MySQL or PostgreSQL database or delegate -authentication to the web server. Authentication methods can be chained to set up fallback authentication methods +With Icinga Web 2 you can authenticate against Active Directory, LDAP, a MySQL or a PostgreSQL database or delegate +authentication to the web server. + +Authentication methods can be chained to set up fallback authentication methods or if users are spread over multiple places. -## Configuration +## Configuration Authentication methods are configured in the INI file **config/authentication.ini**. Each section in the authentication configuration represents a single authentication method. The order of entries in the authentication configuration determines the order of the authentication methods. -If the current authentication method errors or the current authentication method does not know the account being +If the current authentication method errors or if the current authentication method does not know the account being authenticated, the next authentication method will be used. -## External Authentication +### External Authentication For delegating authentication to the web server simply add `autologin` to your authentication configuration: @@ -27,13 +29,13 @@ backend = autologin If your web server is not configured for authentication though the `autologin` section has no effect. -## Active Directory or LDAP Authentication +### Active Directory or LDAP Authentication If you want to authenticate against Active Directory or LDAP, you have to define a -[LDAP resource](#resources-configuration-ldap) first which will be referenced as data source for the Active Directory +[LDAP resource](#resources-configuration-ldap) which will be referenced as data source for the Active Directory or LDAP configuration method. -### LDAP +#### LDAP Directive | Description ------------------------|------------ @@ -52,7 +54,7 @@ user_class = inetOrgPerson user_name_attribute = uid ``` -### Active Directory +#### Active Directory Directive | Description ------------------------|------------ @@ -67,10 +69,10 @@ backend = ad resource = my_ad ``` -## Database Authentication +### Database Authentication -If you want to authenticate against a MySQL or PostgreSQL database, you have to define a -[database resource](#resources-configuration-database) first which will be referenced as data source for the database +If you want to authenticate against a MySQL or a PostgreSQL database, you have to define a +[database resource](#resources-configuration-database) which will be referenced as data source for the database authentication method. Directive | Description From 53179981d62b1f05951ed70031e5497dbb9dc50c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 15:37:08 +0100 Subject: [PATCH 033/106] doc: Add section 'Database Setup' to authentication.md fixes #7672 --- doc/authentication.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/authentication.md b/doc/authentication.md index a4fdc2fcc..d36051e8f 100644 --- a/doc/authentication.md +++ b/doc/authentication.md @@ -85,13 +85,31 @@ Directive | Description ``` [auth_ad] backend = ad -resource = my_db +resource = icingaweb-mysql ``` +#### Database Setup + +For authenticating against a database, you have to import one of the following database schemas: + +* **etc/schema/preferences.mysql.sql** (for **MySQL** database) +* **etc/schema/preferences.pgsql.sql** (for **PostgreSQL** databases) + +After that you have to define the [database resource](#resources-configuration-database). + **Manually Creating Users** +Icinga Web 2 uses the MD5 based BSD password algorithm. For generating a password hash, please use the following +command: + ```` openssl passwd -1 "password" +```` +> Note: The switch to `openssl passwd` is the **number one** (`-1`) for using the MD5 based BSD password algorithm. + +Insert the user into the database using the generated password hash: + +```` INSERT INTO icingaweb_user (name, active, password_hash) VALUES ('icingaadmin', 1, 'hash from openssl'); ```` From 0bcda60dab4ce7c14a1a2b0b5da60be5aec6cad2 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 15:40:26 +0100 Subject: [PATCH 034/106] doc: Remove developer information from preferences.md --- doc/preferences.md | 118 ++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 83 deletions(-) diff --git a/doc/preferences.md b/doc/preferences.md index 0ac15034e..4ece5edf6 100644 --- a/doc/preferences.md +++ b/doc/preferences.md @@ -1,101 +1,53 @@ -# Preferences +# Preferences -Preferences are user based configuration for Icinga Web 2. For example max page -items, languages or date time settings can controlled by users. +Preferences are settings a user can set for his account only, for example his language and time zone. -# Architecture +**Choosing Where to Store Preferences** -Preferences are initially loaded from a provider (ini files or database) and -stored into session at login time. After this step preferences are only -persisted to the configured backend, but never reloaded from them. +Preferences can be stored either in INI files or in a MySQL or in a PostgreSQL database. By default, Icinga Web 2 stores +preferences in INI files beneath Icinga Web 2's configuration directory. -# Configuration +## Configuration -Preferences can be configured in config.ini in **preferences** section, default -settings are this: +Where to store preferences is defined in the INI file **config/config.ini** in the *preferences* section. - [preferences] - type=ini +### Store Preferences in INI Files -The ini provider uses the directory **config/preferences** to create one ini -file per user and persists the data into a single file. If you want to drop your -preferences just drop the file from disk and you'll start with a new profile. +If preferences are stored in INI Files, Icinga Web 2 automatically creates one file per user using the username as +file name for storing preferences. A INI file is created once a user saves changed preferences the first time. +The files are located beneath the `preferences` directory beneath Icinga Web 2's configuration directory. -## Database Provider +For storing preferences in INI files you have to add the following section to the INI file **config/config.ini**: -To be more flexible in distributed setups you can store preferences in a -database (pgsql or mysql), a typical configuration looks like the following -example: +``` +[preferences] +type = ini +```` - [preferences] - type=db - resource=icingaweb-pgsql +### Store Preferences in a Database -## Null Provider +In order to be more flexible in distributed setups you can store preferences in a MySQL or in a PostgreSQL database. +For storing preferences in a database, you have to define a [database resource](#resources-configuration-database) +which will be referenced as resource for the preferences storage. -The Null Provider discards all preferences and is mainly used as a fallback when no provider could be -created (due to permission errors, database outtakes, etc.). +Directive | Description +------------------------|------------ +**type** | `db` +**resource** | The name of the database resource defined in [resources.ini](resources). - [preferences] - type=null +**Example:** -If your preferences aren't stored it's best to take a look into the logfiles - errors during the preference setup -are displayed as warnings here. +``` +[preferences] +type = db +resource = icingaweb-mysql +``` -### Settings +#### Database Setup -* **resource**: A reference to a database declared in *resources.ini*. Please read the chapter about - resources for a detailed description about how to set up resources. +For storing preferences in a database, you have to import one of the following database schemas: -### Preparation +* **etc/schema/preferences.mysql.sql** (for **MySQL** database) +* **etc/schema/preferences.pgsql.sql** (for **PostgreSQL** databases) -To use this feature you need a running database environment. After creating a -database and a writable user you need to import the initial table file: - -* etc/schema/preferences.mysql.sql (for mysql database) -* etc/schema/preferemces.pgsql.sql (for postgres databases) - -#### Example for mysql - - # mysql -u root -p - mysql> create database icingaweb; - mysql> GRANT SELECT,INSERT,UPDATE,DELETE ON icingaweb.* TO \ - 'icingaweb'@'localhost' IDENTIFIED BY 'icingaweb'; - mysql> exit - # mysql -u root -p icingaweb < /path/to/icingaweb/etc/schema/preferences.mysql.sql - -After following these steps above you can configure your preferences provider. - -## Coding API - -You can set, update or remove preferences using the Preference data object -which is bound to the user. Here are some simple examples how to work with -that: - - $preferences = $user->getPreferences(); - // Get language with en_US as fallback - $preferences->get('app.language', 'en_US'); - $preferences->set('app.language', 'de_DE'); - $preferences->remove('app.language'); - - // Using transactional mode - $preferences->startTransaction(); - $preferences->set('test.pref1', 'pref1'); - $preferences->set('test.pref2', 'pref2'); - $preferences->remove('test.pref3'); - $preferemces->commit(); // Stores 3 changes in one operation - -More information can be found in the api docs. - -## Namespaces and behaviour - -If you are using this API please obey the following rules: - -* Use dotted notation for preferences -* Namespaces starting with one context identifier - * **app** as global identified (e.g. app.language) - * **mymodule** for your module - * **monitoring** for the monitoring module -* Use preferences wisely (set only when needed and write small settings) -* Use only simple data types, e.g. strings or numbers - * If you need complex types you have to do it your self (e.g. serialization) +After that you have to define the [database resource](#resources-configuration-database). From 5b1e9be3169f77de36694bf3ce9887b28e37129f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 18 Dec 2014 15:41:26 +0100 Subject: [PATCH 035/106] Make command parameters with multiple lines work, again fixes #6088 --- .../IcingaCommandFileCommandRenderer.php | 4 +- .../test/php/regression/Bug6088Test.php | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 modules/monitoring/test/php/regression/Bug6088Test.php diff --git a/modules/monitoring/library/Monitoring/Command/Renderer/IcingaCommandFileCommandRenderer.php b/modules/monitoring/library/Monitoring/Command/Renderer/IcingaCommandFileCommandRenderer.php index 2843974ea..651383255 100644 --- a/modules/monitoring/library/Monitoring/Command/Renderer/IcingaCommandFileCommandRenderer.php +++ b/modules/monitoring/library/Monitoring/Command/Renderer/IcingaCommandFileCommandRenderer.php @@ -30,7 +30,7 @@ class IcingaCommandFileCommandRenderer implements IcingaCommandRendererInterface * * @return string */ - public function escape($commandString) + protected function escape($commandString) { return str_replace(array("\r", "\n"), array('\r', '\n'), $commandString); } @@ -52,7 +52,7 @@ class IcingaCommandFileCommandRenderer implements IcingaCommandRendererInterface if ($now === null) { $now = time(); } - return sprintf('[%u] %s', $now, $this->$renderMethod($command)); + return sprintf('[%u] %s', $now, $this->escape($this->$renderMethod($command))); } public function renderAddComment(AddCommentCommand $command) diff --git a/modules/monitoring/test/php/regression/Bug6088Test.php b/modules/monitoring/test/php/regression/Bug6088Test.php new file mode 100644 index 000000000..0a4f60a58 --- /dev/null +++ b/modules/monitoring/test/php/regression/Bug6088Test.php @@ -0,0 +1,63 @@ +getBug() . ';' . $command->getParameterWithCarriageReturnAndLineFeed(); + } +} + + +/** + * Class Bug6088 + * + * Multi-line comments don't work + * + * @see https://dev.icinga.org/issues/6088 + */ +class Bug6088Test extends BaseTestCase +{ + public function testWhetherCommandParametersWithMultipleLinesAreProperlyEscaped() + { + $command = new Bug6088Command(); + $renderer = new Bug6088CommandFileCommandRenderer(); + $commandString = $renderer->render($command); + + $this->assertEquals( + 'SOLVE_BUG;6088;foo\r\nbar', + substr($commandString, strpos($commandString, ' ') + 1), + 'Command parameters with multiple lines are not properly escaped' + ); + } +} From 7710fd7b0e3a6fe0501492be2acbd7b5b661c1ff Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 18 Dec 2014 16:20:41 +0100 Subject: [PATCH 036/106] Hide unsupported export formats refs #8112 --- .../Web/Widget/Tabextension/OutputFormat.php | 72 +++++++++++-------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/library/Icinga/Web/Widget/Tabextension/OutputFormat.php b/library/Icinga/Web/Widget/Tabextension/OutputFormat.php index b5426ea47..0b533fd82 100644 --- a/library/Icinga/Web/Widget/Tabextension/OutputFormat.php +++ b/library/Icinga/Web/Widget/Tabextension/OutputFormat.php @@ -4,6 +4,7 @@ namespace Icinga\Web\Widget\Tabextension; +use Icinga\Application\Platform; use Icinga\Web\Url; use Icinga\Web\Widget\Tab; use Icinga\Web\Widget\Tabs; @@ -28,35 +29,6 @@ class OutputFormat implements Tabextension */ const TYPE_CSV = 'csv'; - /** - * An array containing the tab definitions for all supported types - * - * Using array_keys on this array or isset allows to check whether a - * requested type is supported - * - * @var array - */ - private $supportedTypes = array( - self::TYPE_PDF => array( - 'name' => 'pdf', - 'title' => 'PDF', - 'icon' => 'file-pdf', - 'urlParams' => array('format' => 'pdf'), - ), - self::TYPE_CSV => array( - 'name' => 'csv', - 'title' => 'CSV', - 'icon' => 'file-excel', - 'urlParams' => array('format' => 'csv') - ), - self::TYPE_JSON => array( - 'name' => 'json', - 'title' => 'JSON', - 'icon' => 'img/icons/json.png', - 'urlParams' => array('format' => 'json') - ) - ); - /** * An array of tabs to be added to the dropdown area * @@ -74,7 +46,7 @@ class OutputFormat implements Tabextension */ public function __construct(array $disabled = array()) { - foreach ($this->supportedTypes as $type => $tabConfig) { + foreach ($this->getSupportedTypes() as $type => $tabConfig) { if (!in_array($type, $disabled)) { $tabConfig['url'] = Url::fromRequest(); $tabConfig['tagParams'] = array( @@ -98,4 +70,44 @@ class OutputFormat implements Tabextension $tabs->addAsDropdown($tab->getName(), $tab); } } + + /** + * Return an array containing the tab definitions for all supported types + * + * Using array_keys on this array or isset allows to check whether a + * requested type is supported + * + * @return array + */ + public function getSupportedTypes() + { + $supportedTypes = array(); + + if (Platform::extensionLoaded('gd')) { + $supportedTypes[self::TYPE_PDF] = array( + 'name' => 'pdf', + 'title' => 'PDF', + 'icon' => 'file-pdf', + 'urlParams' => array('format' => 'pdf'), + ); + } + + $supportedTypes[self::TYPE_CSV] = array( + 'name' => 'csv', + 'title' => 'CSV', + 'icon' => 'file-excel', + 'urlParams' => array('format' => 'csv') + ); + + if (Platform::extensionLoaded('json')) { + $supportedTypes[self::TYPE_JSON] = array( + 'name' => 'json', + 'title' => 'JSON', + 'icon' => 'img/icons/json.png', + 'urlParams' => array('format' => 'json') + ); + } + + return $supportedTypes; + } } From cc9ee93311972cf275925ed51d10c9c291a99923 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 18 Dec 2014 16:21:25 +0100 Subject: [PATCH 037/106] Clarify that php-gd is mandatory to export views to PDF refs #8112 --- modules/setup/library/Setup/WebWizard.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php index 53a6bb8a8..faa123fe8 100644 --- a/modules/setup/library/Setup/WebWizard.php +++ b/modules/setup/library/Setup/WebWizard.php @@ -461,8 +461,8 @@ class WebWizard extends Wizard implements SetupWizard mt('setup', 'PHP Module: GD'), mt( 'setup', - 'In case you want icons being exported to PDF as' - . ' well, you\'ll need the GD extension for PHP.' + 'In case you want views being exported to PDF,' + . ' you\'ll need the GD extension for PHP.' ), Platform::extensionLoaded('gd'), Platform::extensionLoaded('gd') ? mt('setup', 'The PHP module GD is available') : ( From 0b95892764b76025efae8c2dccb494a4bbf7defc Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 17:09:28 +0100 Subject: [PATCH 038/106] puppet: Add note to the icingacli module that it's not reuseable --- .puppet/modules/icingacli/manifests/init.pp | 1 + 1 file changed, 1 insertion(+) diff --git a/.puppet/modules/icingacli/manifests/init.pp b/.puppet/modules/icingacli/manifests/init.pp index 7eef7833a..701cb6e14 100644 --- a/.puppet/modules/icingacli/manifests/init.pp +++ b/.puppet/modules/icingacli/manifests/init.pp @@ -1,3 +1,4 @@ +# TODO(el): This module is not reuseable because it relies on vagrant paths class icingacli { file { '/usr/local/bin/icingacli': ensure => link, From 8728b3f12596f7ee4315d26c7cd670a91ce336bf Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 17:17:59 +0100 Subject: [PATCH 039/106] puppet: Add user 'vagrant' to group 'icingaweb' --- .puppet/manifests/site.pp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.puppet/manifests/site.pp b/.puppet/manifests/site.pp index 77ebfa0a7..08120d911 100644 --- a/.puppet/manifests/site.pp +++ b/.puppet/manifests/site.pp @@ -12,4 +12,6 @@ node default { file { '/etc/profile.d/env.sh': source => 'puppet:////vagrant/.puppet/files/etc/profile.d/env.sh' } + @user { vagrant: ensure => present } + User <| title == vagrant |> { groups +> icingaweb } } From 4dfac2839303178a101d43488dd57d846988471d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 17:21:06 +0100 Subject: [PATCH 040/106] lib: Fix PHPDoc of Form::setOnSuccess() --- library/Icinga/Web/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 37d8789fe..647be721d 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -147,7 +147,7 @@ class Form extends Zend_Form /** * Set a callback that is called instead of this form's onSuccess method * - * It is called using the following signature: (Request $request, Form $form). + * It is called using the following signature: (Form $this). * * @param callable $onSuccess Callback * From 1468ed0a1979574ff20d859cd7f4f6128b93d2b2 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 18 Dec 2014 17:23:54 +0100 Subject: [PATCH 041/106] lib: Add separator parameter to String::cname() --- library/Icinga/Util/String.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/Icinga/Util/String.php b/library/Icinga/Util/String.php index 0bebb06e7..248ab0d34 100644 --- a/library/Icinga/Util/String.php +++ b/library/Icinga/Util/String.php @@ -23,16 +23,17 @@ class String } /** - * Uppercase the first character of each word in a string assuming and removing the underscore as word separator + * Uppercase the first character of each word in a string * * Converts 'first_name' to 'firstName' for example. * * @param string $name + * @param string $separator Word separator * * @return string */ - public static function cname($name) + public static function cname($name, $separator = '_') { - return str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($name)))); + return str_replace(' ', '', ucwords(str_replace($separator, ' ', strtolower($name)))); } } From b0ab6c3a768f4a20a01676eff8520bc9aaf593ce Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 19 Dec 2014 10:43:14 +0100 Subject: [PATCH 042/106] monitoring: Remove css class 'control-group' from the expire time element This CSS class does no longer exist. --- .../forms/Command/Object/AcknowledgeProblemCommandForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php index 3456e1bfb..25ac76c25 100644 --- a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php @@ -104,7 +104,7 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm array( 'decorators' => array( 'FormElements', - array('HtmlTag', array('tag' => 'div', 'class' => 'control-group')) + array('HtmlTag', array('tag' => 'div')) ) ) ); From fa226f261e1d1f3094fd7299d136afab45eb2e3b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 19 Dec 2014 10:45:23 +0100 Subject: [PATCH 043/106] monitoring: Remove css class 'control-group' from date and time elements in the schedule downtime command form This CSS class does no longer exist. --- .../Command/Object/ScheduleServiceDowntimeCommandForm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php index 9fd86a82b..9961d4b65 100644 --- a/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php @@ -130,7 +130,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm array( 'decorators' => array( 'FormElements', - array('HtmlTag', array('tag' => 'div', 'class' => 'control-group')) + array('HtmlTag', array('tag' => 'div')) ) ) ); @@ -169,7 +169,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm ), 'decorators' => array( 'FormElements', - array('HtmlTag', array('tag' => 'div', 'class' => 'control-group')), + array('HtmlTag', array('tag' => 'div')), array( 'Description', array('tag' => 'span', 'class' => 'description', 'placement' => 'prepend') From e5d2d4cec2f5941a3092ef5884cfae0cc9ac2c42 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 19 Dec 2014 11:29:24 +0100 Subject: [PATCH 044/106] Add module-aware Form::translate and Form::translatePlural refs #7551 --- library/Icinga/Util/Translator.php | 7 +++--- library/Icinga/Web/Form.php | 35 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/library/Icinga/Util/Translator.php b/library/Icinga/Util/Translator.php index 52a84bd62..87d9e4c88 100644 --- a/library/Icinga/Util/Translator.php +++ b/library/Icinga/Util/Translator.php @@ -4,7 +4,6 @@ namespace Icinga\Util; -use Exception; use Icinga\Exception\IcingaException; /** @@ -34,8 +33,8 @@ class Translator * * Falls back to the default domain in case the string cannot be translated using the given domain * - * @param string $text The string to translate - * @param string $domain The primary domain to use + * @param string $text The string to translate + * @param string $domain The primary domain to use * @param string|null $context Optional parameter for context based translation * * @return string The translated string @@ -64,7 +63,7 @@ class Translator * * @param string $textSingular The string in singular form to translate * @param string $textPlural The string in plural form to translate - * @param integer $number The number to get the plural or singular string + * @param integer $number The amount to determine from whether to return singular or plural * @param string $domain The primary domain to use * @param string|null $context Optional parameter for context based translation * diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 647be721d..205c4e238 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -9,6 +9,7 @@ use Zend_Config; use Zend_Form; use Zend_View_Interface; use Icinga\Application\Icinga; +use Icinga\Util\Translator; use Icinga\Web\Form\Decorator\NoScriptApply; use Icinga\Web\Form\Element\CsrfCounterMeasure; @@ -804,6 +805,40 @@ class Form extends Zend_Form return array(); } + /** + * Translate a string + * + * @param string $text The string to translate + * @param string|null $context Optional parameter for context based translation + * + * @return string The translated string + */ + protected function translate($text, $context = null) + { + return Translator::translate($text, $this->request->getModuleName(), $context); + } + + /** + * Translate a plural string + * + * @param string $textSingular The string in singular form to translate + * @param string $textPlural The string in plural form to translate + * @param integer $number The amount to determine from whether to return singular or plural + * @param string|null $context Optional parameter for context based translation + * + * @return string The translated string + */ + protected function translatePlural($textSingular, $textPlural, $number, $context = null) + { + return Translator::translatePlural( + $textSingular, + $textPlural, + $number, + $this->request->getModuleName(), + $context + ); + } + /** * Render this form * From cf43b814009c2109c3990e4743ef0738bce5b459 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 19 Dec 2014 12:08:54 +0100 Subject: [PATCH 045/106] Use the class namespace instead of the request in Form::translate(Plural) refs #7551 --- library/Icinga/Web/Form.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 205c4e238..f3810903c 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -805,6 +805,20 @@ class Form extends Zend_Form return array(); } + /** + * Return the translation domain for this form + * + * @return string + */ + protected function getTranslationDomain() + { + if (preg_match('@^Icinga\\\\Module\\\\([A-z]+)\\\\.*$@', get_called_class(), $matches) === 1) { + return strtolower($matches[0]); + } + + return $this->getRequest()->getModuleName(); + } + /** * Translate a string * @@ -815,7 +829,7 @@ class Form extends Zend_Form */ protected function translate($text, $context = null) { - return Translator::translate($text, $this->request->getModuleName(), $context); + return Translator::translate($text, $this->getTranslationDomain(), $context); } /** @@ -834,7 +848,7 @@ class Form extends Zend_Form $textSingular, $textPlural, $number, - $this->request->getModuleName(), + $this->getTranslationDomain(), $context ); } From 6d263ae316f24d3e27abf42bde15f4f43bff27df Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 19 Dec 2014 13:07:51 +0100 Subject: [PATCH 046/106] Do NOT fetch the translation domain from the request in Form::translate(..) It might be the case that a module is using a library form... refs #7551 --- library/Icinga/Web/Form.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index f3810903c..850285baa 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -808,6 +808,9 @@ class Form extends Zend_Form /** * Return the translation domain for this form * + * The returned translation domain is either determined based on + * this form's class path or it is the default `icinga' domain + * * @return string */ protected function getTranslationDomain() @@ -816,7 +819,7 @@ class Form extends Zend_Form return strtolower($matches[0]); } - return $this->getRequest()->getModuleName(); + return 'icinga'; } /** From 4c4c0c97a5de5ed09d3a6cef9364712e140bad5b Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 22 Dec 2014 08:30:08 +0100 Subject: [PATCH 047/106] Fix incorrect token generation example on the wizard's welcome page fixes #8135 --- .../setup/application/views/scripts/form/setup-welcome.phtml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/setup/application/views/scripts/form/setup-welcome.phtml b/modules/setup/application/views/scripts/form/setup-welcome.phtml index 6c8228541..9aad09dbc 100644 --- a/modules/setup/application/views/scripts/form/setup-welcome.phtml +++ b/modules/setup/application/views/scripts/form/setup-welcome.phtml @@ -51,9 +51,7 @@ $cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');

- su && mkdir -m 2770 ; - head -c 12 /dev/urandom | base64 | tee ; - chmod 0660 ; + su -c "mkdir -m 2770 ; head -c 12 /dev/urandom | base64 | tee ; chmod 0660 ;";

Date: Mon, 22 Dec 2014 09:14:19 +0100 Subject: [PATCH 048/106] Fix the config warning's grammar on the login screen --- application/views/scripts/authentication/login.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/views/scripts/authentication/login.phtml b/application/views/scripts/authentication/login.phtml index 584d8ad16..416e651d1 100644 --- a/application/views/scripts/authentication/login.phtml +++ b/application/views/scripts/authentication/login.phtml @@ -18,7 +18,7 @@

Date: Mon, 22 Dec 2014 09:37:01 +0100 Subject: [PATCH 049/106] There is no copy-on-write for objects in PHP fixes #8088 --- application/views/scripts/roles/index.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/views/scripts/roles/index.phtml b/application/views/scripts/roles/index.phtml index 0f40f8279..79eda5dac 100644 --- a/application/views/scripts/roles/index.phtml +++ b/application/views/scripts/roles/index.phtml @@ -30,7 +30,7 @@ without(...) or $role->shift(...) would be nice! - $restrictions = $role; + $restrictions = clone $role; unset($restrictions['users']); unset($restrictions['groups']); unset($restrictions['permissions']); From 706e5504e651e63b7fee1e5a116f924452bf33d3 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 22 Dec 2014 10:46:29 +0100 Subject: [PATCH 050/106] Escape restriction names manually in Forms\Security\RoleForm fixes #8086 --- application/forms/Security/RoleForm.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php index 0fb53e858..4edb33d07 100644 --- a/application/forms/Security/RoleForm.php +++ b/application/forms/Security/RoleForm.php @@ -93,7 +93,7 @@ class RoleForm extends ConfigForm foreach ($this->providedRestrictions as $name => $description) { $this->addElement( 'text', - $name, + str_replace('/', '_', $name), array( 'label' => $name, 'description' => $description @@ -129,6 +129,12 @@ class RoleForm extends ConfigForm ? String::trimSplit($role['permissions']) : null; $role['name'] = $name; + foreach (array_keys($role) as $key) { + // Slashes are not allowed in a form's element name + $value = $role[$key]; + unset($role[$key]); + $role[str_replace('/', '_', $key)] = $value; + } $this->populate($role); return $this; } @@ -230,6 +236,12 @@ class RoleForm extends ConfigForm if (isset($values['permissions'])) { $values['permissions'] = implode(', ', $values['permissions']); } + foreach (array_keys($values) as $key) { + // Slashes are not allowed in a form's element name + $value = $values[$key]; + unset($values[$key]); + $values[str_replace('/', '_', $key)] = $value; + } return $values; } } From f7d11ce11f82b8e2716ed065ecdb0f4109ddd25a Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 22 Dec 2014 11:02:48 +0100 Subject: [PATCH 051/106] Relax session storage check to the `files' save handler fixes #8053 --- library/Icinga/Web/Session/PhpSession.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/Session/PhpSession.php b/library/Icinga/Web/Session/PhpSession.php index bef978c0b..094685fe4 100644 --- a/library/Icinga/Web/Session/PhpSession.php +++ b/library/Icinga/Web/Session/PhpSession.php @@ -78,7 +78,7 @@ class PhpSession extends Session } } - if (!is_writable(session_save_path())) { + if (ini_get('session.save_handler') === 'files' && !is_writable(session_save_path())) { throw new ConfigurationError('Can\'t save session'); } From 086334c8618ce218f5df872b1bca5de33604dbc6 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 22 Dec 2014 13:59:03 +0100 Subject: [PATCH 052/106] Properly build the unhandled action links when showing multiple objects The links designated to acknowledge unhandled problems or to schedule a downtime for them were generated based on the full list of objects and limited by non-supported filter parameters. As we are already aware of the exact "unhandled" objects this list is now used to generate proper links. (Btw applying filters to URLs is a mess...) fixes #8017 --- .../controllers/HostsController.php | 12 ++++++------ .../controllers/ServicesController.php | 18 ++++++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/modules/monitoring/application/controllers/HostsController.php b/modules/monitoring/application/controllers/HostsController.php index 4944cc237..37611a001 100644 --- a/modules/monitoring/application/controllers/HostsController.php +++ b/modules/monitoring/application/controllers/HostsController.php @@ -108,12 +108,12 @@ class Monitoring_HostsController extends Controller $this->view->hostStates = $hostStates; $this->view->objects = $this->hostList; $this->view->unhandledObjects = $unhandledObjects; - $this->view->acknowledgeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/hosts/acknowledge-problem') - ->addParams(array('host_problem' => 1, 'host_handled' => 0)); - $this->view->downtimeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/hosts/schedule-downtime') - ->addParams(array('host_problem' => 1, 'host_handled' => 0)); + $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/hosts/acknowledge-problem')->setQueryString( + Filter::where('host', array_map(function ($h) { return $h->host; }, $unhandledObjects))->toQueryString() + ); + $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/hosts/schedule-downtime')->setQueryString( + Filter::where('host', array_map(function ($h) { return $h->host; }, $unhandledObjects))->toQueryString() + ); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; $this->view->inDowntimeLink = Url::fromRequest() diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php index cdf86f460..f859f6790 100644 --- a/modules/monitoring/application/controllers/ServicesController.php +++ b/modules/monitoring/application/controllers/ServicesController.php @@ -125,12 +125,18 @@ class Monitoring_ServicesController extends Controller $this->view->serviceStates = $serviceStates; $this->view->objects = $this->serviceList; $this->view->unhandledObjects = $unhandledObjects; - $this->view->acknowledgeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/services/acknowledge-problem') - ->addParams(array('service_problem' => 1, 'service_handled' => 0)); - $this->view->downtimeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/services/schedule-downtime') - ->addParams(array('service_problem' => 1, 'service_handled' => 0)); + $unhandledFilterExpressions = array(); + foreach ($unhandledObjects as $service) { + $unhandledFilterExpressions[] = Filter::matchAll( + Filter::expression('host', '=', $service->getHost()->getName()), + Filter::expression('service', '=', $service->getName()) + ); + } + $queryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString(); + $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/services/acknowledge-problem'); + $this->view->acknowledgeUnhandledLink->setQueryString($queryString); + $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/services/schedule-downtime'); + $this->view->downtimeUnhandledLink->setQueryString($queryString); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; $this->view->inDowntimeLink = Url::fromRequest() From c5915f24cc4f1ae3846cac0ac129b3e61d8e644e Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 22 Dec 2014 14:44:09 +0100 Subject: [PATCH 053/106] Make it easier to distinguish host and service downtimes Added an icon to the left of a host's or service's label and an additional textual indicator. refs #8008 --- .../views/scripts/list/downtimes.phtml | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/modules/monitoring/application/views/scripts/list/downtimes.phtml b/modules/monitoring/application/views/scripts/list/downtimes.phtml index 37b34fe5e..8a8e5576c 100644 --- a/modules/monitoring/application/views/scripts/list/downtimes.phtml +++ b/modules/monitoring/application/views/scripts/list/downtimes.phtml @@ -53,7 +53,7 @@ use Icinga\Module\Monitoring\Object\Service; service)): ?> - href('monitoring/service/show', array( 'host' => $downtime->host, 'service' => $downtime->service )); ?>"> @@ -63,7 +63,7 @@ use Icinga\Module\Monitoring\Object\Service; translate('on'); ?> host; ?> - href('monitoring/host/show', array( 'host' => $downtime->host )); ?>"> host; ?> @@ -76,7 +76,9 @@ use Icinga\Module\Monitoring\Object\Service; is_flexible): ?> is_in_effect): ?> translate('This flexible downtime was started on %s at %s and lasts for %s until %s at %s.'), + isset($downtime->service) + ? $this->translate('This flexible service downtime was started on %s at %s and lasts for %s until %s at %s.') + : $this->translate('This flexible host downtime was started on %s at %s and lasts for %s until %s at %s.'), date('d.m.y', $downtime->start), date('H:i', $downtime->start), $this->format()->duration($downtime->duration), @@ -85,7 +87,9 @@ use Icinga\Module\Monitoring\Object\Service; ); ?> translate('This flexible downtime has been scheduled to start between %s - %s and to last for %s.'), + isset($downtime->service) + ? $this->translate('This flexible service downtime has been scheduled to start between %s - %s and to last for %s.') + : $this->translate('This flexible host downtime has been scheduled to start between %s - %s and to last for %s.'), date('d.m.y H:i', $downtime->scheduled_start), date('d.m.y H:i', $downtime->scheduled_end), $this->format()->duration($downtime->duration) @@ -94,7 +98,9 @@ use Icinga\Module\Monitoring\Object\Service; is_in_effect): ?> translate('This fixed downtime was started on %s at %s and expires on %s at %s.'), + isset($downtime->service) + ? $this->translate('This fixed service downtime was started on %s at %s and expires on %s at %s.') + : $this->translate('This fixed host downtime was started on %s at %s and expires on %s at %s.'), date('d.m.y', $downtime->start), date('H:i', $downtime->start), date('d.m.y', $downtime->end), @@ -102,7 +108,9 @@ use Icinga\Module\Monitoring\Object\Service; ); ?> translate('This fixed downtime has been scheduled to start on %s at %s and to end on %s at %s.'), + isset($downtime->service) + ? $this->translate('This fixed service downtime has been scheduled to start on %s at %s and to end on %s at %s.') + : $this->translate('This fixed host downtime has been scheduled to start on %s at %s and to end on %s at %s.'), date('d.m.y', $downtime->scheduled_start), date('H:i', $downtime->scheduled_start), date('d.m.y', $downtime->scheduled_end), From 5b0c8763620a474fe8bfb173490f27283f426375 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 22 Dec 2014 16:18:39 +0100 Subject: [PATCH 054/106] Use the service_handled column instead of acknowledged and in_downtime Only service_handled takes the host's state into consideration. refs #8013 --- .../monitoring/application/views/scripts/list/hosts.phtml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml index debef375c..2f339b1bf 100644 --- a/modules/monitoring/application/views/scripts/list/hosts.phtml +++ b/modules/monitoring/application/views/scripts/list/hosts.phtml @@ -108,10 +108,9 @@ if ($hosts->count() === 0) { $host->host_unhandled_services), 'monitoring/show/services', array( - 'host' => $host->host_name, - 'service_problem' => 1, - 'service_acknowledged' => 0, - 'service_in_downtime' => 0 + 'host' => $host->host_name, + 'service_problem' => 1, + 'service_handled' => 0 ), array('style' => 'font-weight: normal') ) ?>) From f513e7959e1c2c515fe0304571ea1d154a108fd5 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 22 Dec 2014 16:20:12 +0100 Subject: [PATCH 055/106] Consider also the host's state when counting its service problems refs #8013 --- .../library/Monitoring/Backend/Ido/Query/StatusQuery.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index e390aa114..28b06dc80 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -518,12 +518,14 @@ class StatusQuery extends IdoQuery protected function joinServiceproblemsummary() { $sub = new Zend_Db_Expr('(SELECT' - . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth) > 0 THEN 0 ELSE 1 END) AS unhandled_services_count,' - . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END) AS handled_services_count,' + . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 0 ELSE 1 END) AS unhandled_services_count,' + . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END) AS handled_services_count,' . ' s.host_object_id FROM icinga_servicestatus ss' . ' JOIN icinga_services s' . ' ON s.service_object_id = ss.service_object_id' . ' AND ss.current_state > 0' + . ' JOIN icinga_hoststatus hs' + . ' ON hs.host_object_id = s.host_object_id' . ' GROUP BY s.host_object_id)'); $this->select->joinLeft( array('sps' => $sub), From 64a2acd12eb84f6d62d577b7a49b637efa11a418 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Thu, 18 Dec 2014 16:44:55 +0100 Subject: [PATCH 056/106] Do not display labels for single data sets in perfdata piecharts Display generic chart titles for the whole piechart that only contain title and percentage and don't style perfdata piecharts using HTML properties. refs #7077 refs #6200 refs #7304 --- library/Icinga/Web/Widget/Chart/InlinePie.php | 210 +++++------------- .../controllers/MultiController.php | 2 +- .../controllers/ServicesController.php | 3 +- .../application/views/helpers/Perfdata.php | 14 +- public/css/icinga/widgets.less | 12 + public/js/icinga/behavior/sparkline.js | 51 ++--- 6 files changed, 107 insertions(+), 185 deletions(-) diff --git a/library/Icinga/Web/Widget/Chart/InlinePie.php b/library/Icinga/Web/Widget/Chart/InlinePie.php index 618d2903b..3acb83f5c 100644 --- a/library/Icinga/Web/Widget/Chart/InlinePie.php +++ b/library/Icinga/Web/Widget/Chart/InlinePie.php @@ -34,30 +34,20 @@ class InlinePie extends AbstractWidget * @var string */ private $template =<<<'EOD' - - + + +{noscript} EOD; + private $noscript =<<<'EOD' + +EOD; + + /** * @var Url */ @@ -70,34 +60,6 @@ EOD; */ private $colors = array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd'); - /** - * The width of the rendered chart - * - * @var int The value in px - */ - private $width = 16; - - /** - * The height of the rendered chart - * - * @var int The value in px - */ - private $height = 16; - - /** - * PieChart border width - * - * @var float - */ - private $borderWidth = 1; - - /** - * The color of the border - * - * @var string - */ - private $borderColor = '#fff'; - /** * The title of the chart * @@ -106,11 +68,9 @@ EOD; private $title; /** - * The style for the HtmlElement - * - * @var string + * @var */ - private $style = ''; + private $size; /** * The data displayed by the pie-chart @@ -126,19 +86,17 @@ EOD; */ private $labels = array(); - /** - * If the tooltip for the "empty" area should be hidden - * - * @var bool - */ - private $hideEmptyLabel = false; - /** * The format string used to display tooltips * * @var string */ - private $tooltipFormat = '{{title}}
{{label}}: {{formatted}} ({{percent}}%)'; + private $tooltipFormat = '{{title}}
{{label}} {{formatted}} ({{percent}}%)'; + + /** + * @var string + */ + private $disableTooltips = ''; /** * The number format used to render numeric values in tooltips @@ -147,19 +105,6 @@ EOD; */ private $format = self::NUMBER_FORMAT_NONE; - /** - * Set if the tooltip for the empty area should be hidden - * - * @param bool $hide Whether to hide the empty area - * - * @return $this - */ - public function setHideEmptyLabel($hide = true) - { - $this->hideEmptyLabel = $hide; - return $this; - } - /** * Set the data to be displayed. * @@ -174,6 +119,27 @@ EOD; return $this; } + /** + * Set the size of the inline pie + * + * @param int $size Sets both, the height and width + * + * @return $this + */ + public function setSize($size = null) + { + $this->size = $size; + return $this; + } + + /** + * Do not display the NoScript fallback html + */ + public function disableNoScript() + { + $this->noscript = ''; + } + /** * The labels to be displayed in the pie-chart * @@ -186,7 +152,7 @@ EOD; if (is_array($label)) { $this->url->setParam('labels', implode(',', array_keys($label))); } elseif ($label != null) { - $labelArr = array($label, $label, $label, ''); + $labelArr = array($label, $label, $label, $label); $this->url->setParam('labels', implode(',', $labelArr)); $label = $labelArr; } else { @@ -250,69 +216,6 @@ EOD; return $this; } - /** - * Set the height - * - * @param $height - * - * @return $this - */ - public function setHeight($height) - { - $this->height = $height; - return $this; - } - - /** - * Set the border width of the pie chart - * - * @param float $width Width in px - * - * @return $this - */ - public function setBorderWidth($width) - { - $this->borderWidth = $width; - return $this; - } - - /** - * Set the color of the pie chart border - * - * @param string $col The color string - * - * @return $this - */ - public function setBorderColor($col) - { - $this->borderColor = $col; - } - - /** - * Set the width - * - * @param $width - * - * @return $this - */ - public function setWidth($width) - { - $this->width = $width; - return $this; - } - - /** - * Set the styling of the created HtmlElement - * - * @param string $style - * - * @return $this - */ - public function setStyle($style) - { - $this->style = $style; - } - /** * Set the title of the displayed Data * @@ -322,10 +225,20 @@ EOD; */ public function setTitle($title) { - $this->title = $title; + $this->title = 'title="' . htmlspecialchars($title) . '"'; return $this; } + /** + * Whether to display tooltips for the InlinePie + * + * @param bool $val + */ + public function setDisableTooltip($val = true) + { + $this->disableTooltips = $val !== true ? '' : 'sparkDisableTooltips="true"'; + } + /** * Create a new InlinePie * @@ -335,7 +248,7 @@ EOD; */ public function __construct(array $data, $title, $colors = null) { - $this->title = $title; + $this->setTitle($title); $this->url = Url::fromPath('svg/chart.php'); if (array_key_exists('data', $data)) { $this->data = $data['data']; @@ -386,7 +299,7 @@ EOD; )); try { - $png = $pie->toPng($this->width, $this->height); + $png = $pie->toPng($this->size, $this->size); return ''; } catch (IcingaException $_) { return ''; @@ -394,17 +307,15 @@ EOD; } $template = $this->template; + // TODO: Check whether we are XHR and don't send + $template = str_replace('{noscript}', $this->noscript, $template); $template = str_replace('{url}', $this->url, $template); // style - $template = str_replace('{width}', $this->width, $template); - $template = str_replace('{height}', $this->height, $template); - $template = str_replace('{title}', htmlspecialchars($this->title), $template); - $template = str_replace('{style}', $this->style, $template); + $template = str_replace('{size}', + isset($this->size) ? 'sparkWidth="' . $this->size . '" sparkHeight="' . $this->size . '" ' : '', $template); + $template = str_replace('{title}', $this->title, $template); $template = str_replace('{colors}', implode(',', $this->colors), $template); - $template = str_replace('{borderWidth}', $this->borderWidth, $template); - $template = str_replace('{borderColor}', $this->borderColor, $template); - $template = str_replace('{hideEmptyLabel}', $this->hideEmptyLabel ? 'true' : 'false', $template); // Locale-ignorant string cast. Please. Do. NOT. Remove. This. Again. // Problem is that implode respects locales when casting floats. This means @@ -423,6 +334,7 @@ EOD; $template = str_replace('{formatted}', htmlspecialchars(implode('|', $formatted)), $template); $template = str_replace('{labels}', htmlspecialchars($this->createLabelString()), $template); $template = str_replace('{tooltipFormat}', $this->tooltipFormat, $template); + $template = str_replace('{disableTooltips}', $this->disableTooltips, $template); return $template; } diff --git a/modules/monitoring/application/controllers/MultiController.php b/modules/monitoring/application/controllers/MultiController.php index 52d927ffb..6deff2fc3 100644 --- a/modules/monitoring/application/controllers/MultiController.php +++ b/modules/monitoring/application/controllers/MultiController.php @@ -221,7 +221,7 @@ class Monitoring_MultiController extends Controller private function createPie($states, $colors, $title) { $chart = new InlinePie(array_values($states), $title, $colors); - $chart->setLabel(array_keys($states))->setHeight(100)->setWidth(100); + $chart->setLabel(array_keys($states))->setSize(100); $chart->setTitle($title); return $chart; } diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php index f859f6790..a7b2d0294 100644 --- a/modules/monitoring/application/controllers/ServicesController.php +++ b/modules/monitoring/application/controllers/ServicesController.php @@ -160,8 +160,7 @@ class Monitoring_ServicesController extends Controller $chart = new InlinePie(array_values($states), $title, $colors); return $chart ->setLabel(array_map('strtoupper', array_keys($states))) - ->setHeight(100) - ->setWidth(100) + ->setSize(100) ->setTitle($title); } diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php index eb649e77d..6e168c90f 100644 --- a/modules/monitoring/application/views/helpers/Perfdata.php +++ b/modules/monitoring/application/views/helpers/Perfdata.php @@ -84,21 +84,19 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract protected function createInlinePie(Perfdata $perfdata) { - $pieChart = new InlinePie($this->calculatePieChartData($perfdata), $perfdata->getLabel()); - $pieChart->setLabel(htmlspecialchars($perfdata->getLabel())); - $pieChart->setHideEmptyLabel(); + $pieChart = new InlinePie($this->calculatePieChartData($perfdata), + $perfdata->getLabel() . ' ' . (int)$perfdata->getPercentage() . '%'); + $pieChart->setDisableTooltip(); + if (Zend_Controller_Front::getInstance()->getRequest()->isXmlHttpRequest()) { + $pieChart->disableNoScript(); + } - //$pieChart->setHeight(32)->setWidth(32); if ($perfdata->isBytes()) { - $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)'); $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_BYTES); } else if ($perfdata->isSeconds()) { - $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)'); $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_TIME); } else { - $pieChart->setTooltipFormat('{{label}}: {{formatted}}%'); $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_RATIO); - $pieChart->setHideEmptyLabel(); } return $pieChart; } diff --git a/public/css/icinga/widgets.less b/public/css/icinga/widgets.less index 93625b0dc..87941157c 100644 --- a/public/css/icinga/widgets.less +++ b/public/css/icinga/widgets.less @@ -285,3 +285,15 @@ li li .badge { .widgetFilter li.active { background-color: #eee; } + +.sparkline { + width: 12px; + height: 12px; +} + +.inlinepie { + width: 12px; + height: 12px; + position: relative; + top: 10px; +} \ No newline at end of file diff --git a/public/js/icinga/behavior/sparkline.js b/public/js/icinga/behavior/sparkline.js index 33cc0d34b..1992bae0a 100644 --- a/public/js/icinga/behavior/sparkline.js +++ b/public/js/icinga/behavior/sparkline.js @@ -21,31 +21,32 @@ var $spark = $(element); var labels = $spark.attr('labels').split('|'); var formatted = $spark.attr('formatted').split('|'); - var tooltipChartTitle = $spark.attr('sparkTooltipChartTitle') || ''; - var format = $spark.attr('tooltipformat'); - var hideEmpty = $spark.attr('hideEmptyLabel') === 'true'; - $spark.sparkline( - 'html', - { - enableTagOptions: true, - tooltipFormatter: function (sparkline, options, fields) { - var out = format; - if (hideEmpty && fields.offset === 3) { - return ''; - } - var replace = { - title: tooltipChartTitle, - label: labels[fields.offset] ? labels[fields.offset] : fields.offset, - formatted: formatted[fields.offset] ? formatted[fields.offset] : '', - value: fields.value, - percent: Math.round(fields.percent * 100) / 100 - }; - $.each(replace, function(key, value) { - out = out.replace('{{' + key + '}}', value); - }); - return out; - } - }); + var title = $spark.attr('title'); + var format = $spark.attr('tooltipFormat'); + + if ($spark.attr('labels')) { + $spark.removeAttr('original-title'); + } + var options = { + enableTagOptions: true, + width: $spark.attr('sparkWidth') || 12, + height: $spark.attr('sparkHeight') || 12, + tooltipFormatter: function (sparkline, options, fields) { + var out = format; + var replace = { + title: title, + label: labels[fields.offset] ? labels[fields.offset] : fields.offset, + formatted: formatted[fields.offset] ? formatted[fields.offset] : '', + value: fields.value, + percent: Math.round(fields.percent * 100) / 100 + }; + $.each(replace, function(key, value) { + out = out.replace('{{' + key + '}}', value); + }); + return out; + } + }; + $spark.sparkline('html', options); }); }; From cda5a6a9034cd961cc6b6faeed732e55ab4cce5a Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Tue, 23 Dec 2014 15:26:45 +0100 Subject: [PATCH 057/106] Streamline chart implementation Define sparkline layout through CSS class and remove label/tooltip formatting. fixes #7077 --- library/Icinga/Web/Widget/Chart/InlinePie.php | 150 ++---------------- .../controllers/HostsController.php | 3 - .../controllers/ServicesController.php | 7 +- public/js/icinga/behavior/sparkline.js | 48 +++--- 4 files changed, 39 insertions(+), 169 deletions(-) diff --git a/library/Icinga/Web/Widget/Chart/InlinePie.php b/library/Icinga/Web/Widget/Chart/InlinePie.php index 3acb83f5c..69de8ebd5 100644 --- a/library/Icinga/Web/Widget/Chart/InlinePie.php +++ b/library/Icinga/Web/Widget/Chart/InlinePie.php @@ -5,6 +5,7 @@ namespace Icinga\Web\Widget\Chart; use Icinga\Chart\PieChart; +use Icinga\Module\Monitoring\Plugin\PerfdataSet; use Icinga\Web\Widget\AbstractWidget; use Icinga\Web\Url; use Icinga\Util\Format; @@ -28,15 +29,12 @@ class InlinePie extends AbstractWidget const NUMBER_FORMAT_RATIO = 'ratio'; /** - * The template string used for rendering this widget * The template string used for rendering this widget * * @var string */ private $template =<<<'EOD' - + {noscript} EOD; @@ -80,30 +78,9 @@ EOD; private $data; /** - * The labels to display for each data set - * - * @var array + * @var */ - private $labels = array(); - - /** - * The format string used to display tooltips - * - * @var string - */ - private $tooltipFormat = '{{title}}
{{label}} {{formatted}} ({{percent}}%)'; - - /** - * @var string - */ - private $disableTooltips = ''; - - /** - * The number format used to render numeric values in tooltips - * - * @var array - */ - private $format = self::NUMBER_FORMAT_NONE; + private $class = ''; /** * Set the data to be displayed. @@ -141,24 +118,15 @@ EOD; } /** - * The labels to be displayed in the pie-chart + * Set the class to define the * - * @param mixed $label The label of the displayed value, or null for no labels + * @param $class * - * @return $this + * @return $this */ - public function setLabel($label) + public function setSparklineClass($class) { - if (is_array($label)) { - $this->url->setParam('labels', implode(',', array_keys($label))); - } elseif ($label != null) { - $labelArr = array($label, $label, $label, $label); - $this->url->setParam('labels', implode(',', $labelArr)); - $label = $labelArr; - } else { - $this->url->removeKey('labels'); - } - $this->labels = $label; + $this->class = $class; return $this; } @@ -180,42 +148,6 @@ EOD; return $this; } - /** - * Set the used number format - * - * @param $format string 'bytes' or 'time' - * - * @return $this - */ - public function setNumberFormat($format) - { - $this->format = $format; - return $this; - } - - /** - * A format string used to render the content of the piechart tooltips - * - * Placeholders using curly braces '{FOO}' are replace with their specific values. The format - * String may contain HTML-Markup. The available replaceable values are: - *
    - *
  • label: The description for the current value
  • - *
  • formatted: A string representing the formatted value
  • - *
  • value: The raw (non-formatted) value used to render the piechart
  • - *
  • percent: The percentage of the current value
  • - *
- * Note: Changes will only affect JavaScript sparklines and not the SVG charts used for fallback - * - * @param $format - * - * @return $this - */ - public function setTooltipFormat($format) - { - $this->tooltipFormat = $format; - return $this; - } - /** * Set the title of the displayed Data * @@ -229,16 +161,6 @@ EOD; return $this; } - /** - * Whether to display tooltips for the InlinePie - * - * @param bool $val - */ - public function setDisableTooltip($val = true) - { - $this->disableTooltips = $val !== true ? '' : 'sparkDisableTooltips="true"'; - } - /** * Create a new InlinePie * @@ -252,9 +174,6 @@ EOD; $this->url = Url::fromPath('svg/chart.php'); if (array_key_exists('data', $data)) { $this->data = $data['data']; - if (array_key_exists('labels', $data)) { - $this->labels = $data['labels']; - } if (array_key_exists('colors', $data)) { $this->colors = $data['colors']; } @@ -267,21 +186,6 @@ EOD; $this->setColors($this->colors); } } - - /** - * Create a serialization containing the current label array - * - * @return string A serialized array of labels - */ - private function createLabelString () - { - $labels = $this->labels; - foreach ($labels as $key => $label) { - $labels[$key] = str_replace('|', '', $label); - } - return isset($this->labels) && is_array($this->labels) ? implode('|', $this->labels) : ''; - } - /** * Renders this widget via the given view and returns the * HTML as a string @@ -295,7 +199,7 @@ EOD; $pie->alignTopLeft(); $pie->disableLegend(); $pie->drawPie(array( - 'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels + 'data' => $this->data, 'colors' => $this->colors )); try { @@ -310,11 +214,13 @@ EOD; // TODO: Check whether we are XHR and don't send $template = str_replace('{noscript}', $this->noscript, $template); $template = str_replace('{url}', $this->url, $template); + $template = str_replace('{class}', $this->class, $template); // style $template = str_replace('{size}', isset($this->size) ? 'sparkWidth="' . $this->size . '" sparkHeight="' . $this->size . '" ' : '', $template); $template = str_replace('{title}', $this->title, $template); + $template = str_replace('{colors}', implode(',', $this->colors), $template); // Locale-ignorant string cast. Please. Do. NOT. Remove. This. Again. @@ -325,39 +231,7 @@ EOD; $data[] = sprintf('%F', $dat); } - // values - $formatted = array(); - foreach ($this->data as $key => $value) { - $formatted[$key] = $this->formatValue($value); - } $template = str_replace('{data}', htmlspecialchars(implode(',', $data)), $template); - $template = str_replace('{formatted}', htmlspecialchars(implode('|', $formatted)), $template); - $template = str_replace('{labels}', htmlspecialchars($this->createLabelString()), $template); - $template = str_replace('{tooltipFormat}', $this->tooltipFormat, $template); - $template = str_replace('{disableTooltips}', $this->disableTooltips, $template); return $template; } - - /** - * Format the given value depending on the current value of numberFormat - * - * @param float $value The value to format - * - * @return string The formatted value - */ - private function formatValue($value) - { - if ($this->format === self::NUMBER_FORMAT_NONE) { - return (string)$value; - } elseif ($this->format === self::NUMBER_FORMAT_BYTES) { - return Format::bytes($value); - } elseif ($this->format === self::NUMBER_FORMAT_TIME) { - return Format::duration($value); - } elseif ($this->format === self::NUMBER_FORMAT_RATIO) { - return $value; - } else { - Logger::warning('Unknown format string "' . $this->format . '" for InlinePie, value not formatted.'); - return $value; - } - } } diff --git a/modules/monitoring/application/controllers/HostsController.php b/modules/monitoring/application/controllers/HostsController.php index 37611a001..451f6e44d 100644 --- a/modules/monitoring/application/controllers/HostsController.php +++ b/modules/monitoring/application/controllers/HostsController.php @@ -131,9 +131,6 @@ class Monitoring_HostsController extends Controller { $chart = new InlinePie(array_values($states), $title, $colors); return $chart - ->setLabel(array_map('strtoupper', array_keys($states))) - ->setHeight(100) - ->setWidth(100) ->setTitle($title); } diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php index a7b2d0294..315737b31 100644 --- a/modules/monitoring/application/controllers/ServicesController.php +++ b/modules/monitoring/application/controllers/ServicesController.php @@ -159,9 +159,10 @@ class Monitoring_ServicesController extends Controller { $chart = new InlinePie(array_values($states), $title, $colors); return $chart - ->setLabel(array_map('strtoupper', array_keys($states))) - ->setSize(100) - ->setTitle($title); + // ->setLabel(array_map('strtoupper', array_keys($states))) + ->setSize(50) + ->setTitle($title) + ->setSparklineClass('sparkline-multi'); } /** diff --git a/public/js/icinga/behavior/sparkline.js b/public/js/icinga/behavior/sparkline.js index 1992bae0a..e0d0fb0c7 100644 --- a/public/js/icinga/behavior/sparkline.js +++ b/public/js/icinga/behavior/sparkline.js @@ -18,35 +18,33 @@ $('span.sparkline', el).each(function(i, element) { // read custom options - var $spark = $(element); - var labels = $spark.attr('labels').split('|'); - var formatted = $spark.attr('formatted').split('|'); - var title = $spark.attr('title'); - var format = $spark.attr('tooltipFormat'); + var $spark = $(element); + var title = $spark.attr('title'); if ($spark.attr('labels')) { $spark.removeAttr('original-title'); } - var options = { - enableTagOptions: true, - width: $spark.attr('sparkWidth') || 12, - height: $spark.attr('sparkHeight') || 12, - tooltipFormatter: function (sparkline, options, fields) { - var out = format; - var replace = { - title: title, - label: labels[fields.offset] ? labels[fields.offset] : fields.offset, - formatted: formatted[fields.offset] ? formatted[fields.offset] : '', - value: fields.value, - percent: Math.round(fields.percent * 100) / 100 - }; - $.each(replace, function(key, value) { - out = out.replace('{{' + key + '}}', value); - }); - return out; - } - }; - $spark.sparkline('html', options); + + var options; + if ($spark.hasClass('sparkline-perfdata')) { + options = { + enableTagOptions: true, + width: 12, + height: 12, + title: title, + disableTooltips: true + }; + $spark.sparkline('html', options); + } else if ($spark.hasClass('sparkline-multi')) { + options = { + width: 100, + height: 100, + title: title, + enableTagOptions: true + }; + $spark.sparkline('html', options); + } + }); }; From c93b13b1387c1017d4ef4e58d7b9e078a2d4e0bb Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Tue, 23 Dec 2014 15:45:45 +0100 Subject: [PATCH 058/106] Rework behavior of perfdata visualization Determine perfdata pie color from host or service state, display zero percent piecharts, only render displayabl PieCharts with min and max values, move perfdata to piechart conversion functions into the Perfdata object. fixes #6423 fixes #6200 fixes #7170 fixes #7304 --- .../application/views/helpers/Perfdata.php | 89 ++++++------------- .../library/Monitoring/Plugin/Perfdata.php | 63 +++++++++++++ public/css/icinga/widgets.less | 7 +- 3 files changed, 90 insertions(+), 69 deletions(-) diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php index 6e168c90f..ada99da9f 100644 --- a/modules/monitoring/application/views/helpers/Perfdata.php +++ b/modules/monitoring/application/views/helpers/Perfdata.php @@ -9,33 +9,36 @@ use Icinga\Module\Monitoring\Plugin\PerfdataSet; class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract { - public function perfdata($perfdataStr, $compact = false) + + /** + * Display the given perfdata string to the user + * + * @param $perfdataStr The perfdata string + * @param bool $compact Whether to display the perfdata in compact mode + * @param $color The color indicating the perfdata state + * + * @return string + */ + public function perfdata($perfdataStr, $compact = false, $color = Perfdata::PERFDATA_GREEN) { - $pset = PerfdataSet::fromString($perfdataStr)->asArray(); - $onlyPieChartData = array_filter($pset, function ($e) { return $e->getPercentage() > 0; }); - if ($compact) { - $onlyPieChartData = array_slice($onlyPieChartData, 0, 5); - } else { - $nonPieChartData = array_filter($pset, function ($e) { return $e->getPercentage() == 0; }); - } + $pieChartData = PerfdataSet::fromString($perfdataStr)->asArray(); $result = ''; $table = array(); - foreach ($onlyPieChartData as $perfdata) { - $pieChart = $this->createInlinePie($perfdata); - if ($compact) { - $result .= $pieChart->render(); - } else { - if (! $perfdata->isPercentage()) { - // TODO: Should we trust sprintf-style placeholders in perfdata titles? - $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)'); + foreach ($pieChartData as $perfdata) { + if ($perfdata->isVisualizable()) { + $pieChart = $perfdata->asInlinePie($color); + if ($compact) { + $result .= $pieChart->render(); + } else { + $table[] = '' . $pieChart->render() + . htmlspecialchars($perfdata->getLabel()) + . ' ' + . htmlspecialchars($this->formatPerfdataValue($perfdata)) . + ' '; } - // $pieChart->setStyle('margin: 0.2em 0.5em 0.2em 0.5em;'); - $table[] = '' . $pieChart->render() - . htmlspecialchars($perfdata->getLabel()) - . ' ' - . htmlspecialchars($this->formatPerfdataValue($perfdata)) . - ' '; + } else { + $table[] = (string)$perfdata; } } @@ -43,32 +46,10 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract return $result; } else { $pieCharts = empty($table) ? '' : '' . implode("\n", $table) . '
'; - return $pieCharts . "\n" . implode("
\n", $nonPieChartData); + return $pieCharts; } } - protected function calculatePieChartData(Perfdata $perfdata) - { - $rawValue = $perfdata->getValue(); - $minValue = $perfdata->getMinimumValue() !== null ? $perfdata->getMinimumValue() : 0; - $maxValue = $perfdata->getMaximumValue(); - $usedValue = ($rawValue - $minValue); - $unusedValue = ($maxValue - $minValue) - $usedValue; - - $gray = $unusedValue; - $green = $orange = $red = 0; - // TODO(#6122): Add proper treshold parsing. - if ($perfdata->getCriticalThreshold() && $perfdata->getValue() > $perfdata->getCriticalThreshold()) { - $red = $usedValue; - } elseif ($perfdata->getWarningThreshold() && $perfdata->getValue() > $perfdata->getWarningThreshold()) { - $orange = $usedValue; - } else { - $green = $usedValue; - } - - return array($green, $orange, $red, $gray); - } - protected function formatPerfdataValue(Perfdata $perfdata) { if ($perfdata->isBytes()) { @@ -82,22 +63,4 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract return $perfdata->getValue(); } - protected function createInlinePie(Perfdata $perfdata) - { - $pieChart = new InlinePie($this->calculatePieChartData($perfdata), - $perfdata->getLabel() . ' ' . (int)$perfdata->getPercentage() . '%'); - $pieChart->setDisableTooltip(); - if (Zend_Controller_Front::getInstance()->getRequest()->isXmlHttpRequest()) { - $pieChart->disableNoScript(); - } - - if ($perfdata->isBytes()) { - $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_BYTES); - } else if ($perfdata->isSeconds()) { - $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_TIME); - } else { - $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_RATIO); - } - return $pieChart; - } } diff --git a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php index 6af3cde17..1b687d243 100644 --- a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php +++ b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php @@ -5,9 +5,16 @@ namespace Icinga\Module\Monitoring\Plugin; use InvalidArgumentException; +use Icinga\Exception\ProgrammingError; +use Icinga\Web\Widget\Chart\InlinePie; +use Zend_Controller_Front; class Perfdata { + const PERFDATA_GREEN = 'green'; + const PERFDATA_ORANGE = 'orange'; + const PERFDATA_RED = 'red'; + /** * The performance data value being parsed * @@ -159,6 +166,16 @@ class Perfdata return $this->unit === 'c'; } + /** + * Returns whether it is possible to display a visual representation + * + * @return bool True when the perfdata is visualizable + */ + public function isVisualizable() + { + return isset($this->minValue) && isset($this->maxValue) && isset($this->value); + } + /** * Return this perfomance data's label */ @@ -316,4 +333,50 @@ class Perfdata } } } + + protected function calculatePieChartData( $color) + { + $rawValue = $this->getValue(); + $minValue = $this->getMinimumValue() !== null ? $this->getMinimumValue() : 0; + $maxValue = $this->getMaximumValue(); + $usedValue = ($rawValue - $minValue); + $unusedValue = ($maxValue - $minValue) - $usedValue; + + $gray = $unusedValue; + $green = $orange = $red = 0; + + switch ($color) { + case self::PERFDATA_GREEN: + $green = $usedValue; + break; + + case self::PERFDATA_RED: + $red = $usedValue; + break; + + case self::PERFDATA_ORANGE: + $orange = $usedValue; + break; + } + // TODO(#6122): Add proper treshold parsing. + + return array($green, $orange, $red, $gray); + } + + + public function asInlinePie($color) + { + if (! $this->isVisualizable()) { + throw new ProgrammingError('Cannot calculate piechart data for unvisualizable perfdata entry.'); + } + + $data = $this->calculatePieChartData($color); + $pieChart = new InlinePie($data, $this->getLabel() . ' ' . number_format($this->getPercentage(), 2) . '%'); + $pieChart->setSparklineClass('sparkline-perfdata'); + + if (Zend_Controller_Front::getInstance()->getRequest()->isXmlHttpRequest()) { + $pieChart->disableNoScript(); + } + return $pieChart; + } } diff --git a/public/css/icinga/widgets.less b/public/css/icinga/widgets.less index 87941157c..e2e37d7ab 100644 --- a/public/css/icinga/widgets.less +++ b/public/css/icinga/widgets.less @@ -289,11 +289,6 @@ li li .badge { .sparkline { width: 12px; height: 12px; -} - -.inlinepie { - width: 12px; - height: 12px; position: relative; - top: 10px; + top: 4px; } \ No newline at end of file From 41c101d99fa8ec161b211b851bbf234907333feb Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Tue, 23 Dec 2014 16:12:25 +0100 Subject: [PATCH 059/106] Use neutral default color in perfdata piecharts If nothing is known about the state of the monitoring object, the piecharts should neither indicate OK nor Critical. --- library/Icinga/Web/Widget/Chart/InlinePie.php | 2 +- modules/monitoring/application/views/helpers/Perfdata.php | 2 +- .../monitoring/application/views/scripts/list/services.phtml | 1 + modules/monitoring/library/Monitoring/Plugin/Perfdata.php | 5 ++--- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/Icinga/Web/Widget/Chart/InlinePie.php b/library/Icinga/Web/Widget/Chart/InlinePie.php index 69de8ebd5..04e3e7318 100644 --- a/library/Icinga/Web/Widget/Chart/InlinePie.php +++ b/library/Icinga/Web/Widget/Chart/InlinePie.php @@ -56,7 +56,7 @@ EOD; * * @var array */ - private $colors = array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd'); + private $colors = array('#049BAF', '#ffaa44', '#ff5566', '#ddccdd'); /** * The title of the chart diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php index ada99da9f..47c34d156 100644 --- a/modules/monitoring/application/views/helpers/Perfdata.php +++ b/modules/monitoring/application/views/helpers/Perfdata.php @@ -19,7 +19,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract * * @return string */ - public function perfdata($perfdataStr, $compact = false, $color = Perfdata::PERFDATA_GREEN) + public function perfdata($perfdataStr, $compact = false, $color = Perfdata::PERFDATA_DEFAULT) { $pieChartData = PerfdataSet::fromString($perfdataStr)->asArray(); diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index 994304f08..8ef6f7fe8 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -1,6 +1,7 @@ getHelper('MonitoringState'); diff --git a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php index 1b687d243..7da4559fd 100644 --- a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php +++ b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php @@ -11,8 +11,7 @@ use Zend_Controller_Front; class Perfdata { - const PERFDATA_GREEN = 'green'; - const PERFDATA_ORANGE = 'orange'; + const PERFDATA_DEFAULT = 'green'; const PERFDATA_RED = 'red'; /** @@ -346,7 +345,7 @@ class Perfdata $green = $orange = $red = 0; switch ($color) { - case self::PERFDATA_GREEN: + case self::PERFDATA_DEFAULT: $green = $usedValue; break; From 7f5ba135eee69a1ec3378e02131fff624e9138e3 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 09:25:30 +0100 Subject: [PATCH 060/106] Revert "Relax session storage check to the `files' save handler" This reverts commit f7d11ce11f82b8e2716ed065ecdb0f4109ddd25a. Sorry mate but a guy on GitHub was faster ;) refs #8053 --- library/Icinga/Web/Session/PhpSession.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/Session/PhpSession.php b/library/Icinga/Web/Session/PhpSession.php index 094685fe4..bef978c0b 100644 --- a/library/Icinga/Web/Session/PhpSession.php +++ b/library/Icinga/Web/Session/PhpSession.php @@ -78,7 +78,7 @@ class PhpSession extends Session } } - if (ini_get('session.save_handler') === 'files' && !is_writable(session_save_path())) { + if (!is_writable(session_save_path())) { throw new ConfigurationError('Can\'t save session'); } From 5e40ce2088ed1a0ae8da5ab4a6148d9e8528387c Mon Sep 17 00:00:00 2001 From: Boden Garman Date: Mon, 15 Dec 2014 13:24:18 +1100 Subject: [PATCH 061/106] Only check the session save path is writable if the session handler is 'files' fixes #8053 Signed-off-by: Eric Lippmann --- library/Icinga/Web/Session/PhpSession.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) mode change 100644 => 100755 library/Icinga/Web/Session/PhpSession.php diff --git a/library/Icinga/Web/Session/PhpSession.php b/library/Icinga/Web/Session/PhpSession.php old mode 100644 new mode 100755 index bef978c0b..fa545fd8d --- a/library/Icinga/Web/Session/PhpSession.php +++ b/library/Icinga/Web/Session/PhpSession.php @@ -78,8 +78,9 @@ class PhpSession extends Session } } - if (!is_writable(session_save_path())) { - throw new ConfigurationError('Can\'t save session'); + $sessionSavePath = session_save_path(); + if (session_module_name() === 'files' && !is_writable($sessionSavePath)) { + throw new ConfigurationError("Can't save session, path '$sessionSavePath' is not writable."); } if ($this->exists()) { From 6960a08de04bedc1594dbfdef57d58505bcc13cc Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 09:39:23 +0100 Subject: [PATCH 062/106] Revert "Escape restriction names manually in Forms\Security\RoleForm" This reverts commit 706e5504e651e63b7fee1e5a116f924452bf33d3. HTML5 does allow any non-empty value for the name attribute but Zend only permits alphanumerics, the underscore, the circumflex and any ASCII character in range \x7f to \xff (127 to 255). Thus only escaping the slash (/) is wrong. refs #8086 --- application/forms/Security/RoleForm.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php index 4edb33d07..0fb53e858 100644 --- a/application/forms/Security/RoleForm.php +++ b/application/forms/Security/RoleForm.php @@ -93,7 +93,7 @@ class RoleForm extends ConfigForm foreach ($this->providedRestrictions as $name => $description) { $this->addElement( 'text', - str_replace('/', '_', $name), + $name, array( 'label' => $name, 'description' => $description @@ -129,12 +129,6 @@ class RoleForm extends ConfigForm ? String::trimSplit($role['permissions']) : null; $role['name'] = $name; - foreach (array_keys($role) as $key) { - // Slashes are not allowed in a form's element name - $value = $role[$key]; - unset($role[$key]); - $role[str_replace('/', '_', $key)] = $value; - } $this->populate($role); return $this; } @@ -236,12 +230,6 @@ class RoleForm extends ConfigForm if (isset($values['permissions'])) { $values['permissions'] = implode(', ', $values['permissions']); } - foreach (array_keys($values) as $key) { - // Slashes are not allowed in a form's element name - $value = $values[$key]; - unset($values[$key]); - $values[str_replace('/', '_', $key)] = $value; - } return $values; } } From 2c1a37afa3a5be52af78fd1a395a5671df5fc54b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 10:51:12 +0100 Subject: [PATCH 063/106] Use Zend_Form_Element::filterName() for translating restriction names to element names fixes #8086 --- application/forms/Security/RoleForm.php | 39 ++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php index 0fb53e858..a45ca16ac 100644 --- a/application/forms/Security/RoleForm.php +++ b/application/forms/Security/RoleForm.php @@ -6,6 +6,7 @@ namespace Icinga\Forms\Security; use InvalidArgumentException; use LogicException; +use Zend_Form_Element; use Icinga\Application\Icinga; use Icinga\Forms\ConfigForm; use Icinga\Util\String; @@ -35,6 +36,7 @@ class RoleForm extends ConfigForm */ public function init() { + $helper = new Zend_Form_Element('bogus'); foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) { foreach ($module->getProvidedPermissions() as $permission) { /** @var object $permission */ @@ -42,7 +44,18 @@ class RoleForm extends ConfigForm } foreach ($module->getProvidedRestrictions() as $restriction) { /** @var object $restriction */ - $this->providedRestrictions[$restriction->name] = $restriction->description; + $name = $helper->filterName($restriction->name); // Zend only permits alphanumerics, the underscore, + // the circumflex and any ASCII character in range + // \x7f to \xff (127 to 255) + while (isset($this->providedRestrictions[$name])) { + // Because Zend_Form_Element::filterName() replaces any not permitted character with the empty + // string we may have duplicate names, e.g. 're/striction' and 'restriction' + $name .= '_'; + } + $this->providedRestrictions[$name] = array( + 'description' => $restriction->description, + 'name' => $restriction->name + ); } } } @@ -90,13 +103,13 @@ class RoleForm extends ConfigForm ) ) )); - foreach ($this->providedRestrictions as $name => $description) { + foreach ($this->providedRestrictions as $name => $spec) { $this->addElement( 'text', $name, array( - 'label' => $name, - 'description' => $description + 'label' => $spec['name'], + 'description' => $spec['description'] ) ); } @@ -129,6 +142,15 @@ class RoleForm extends ConfigForm ? String::trimSplit($role['permissions']) : null; $role['name'] = $name; + $restrictions = array(); + foreach ($this->providedRestrictions as $name => $spec) { + if (isset($role[$spec['name']])) { + // Translate restriction names to filtered element names + $restrictions[$name] = $role[$spec['name']]; + unset($role[$spec['name']]); + } + } + $role = array_merge($role, $restrictions); $this->populate($role); return $this; } @@ -230,6 +252,15 @@ class RoleForm extends ConfigForm if (isset($values['permissions'])) { $values['permissions'] = implode(', ', $values['permissions']); } + $restrictions = array(); + foreach ($this->providedRestrictions as $name => $spec) { + if (isset($values[$name])) { + // Translate filtered element names to restriction names + $restrictions[$spec['name']] = $values[$name]; + unset($values[$name]); + } + } + $values = array_merge($values, $restrictions); return $values; } } From 49dad43a0affbab49285b80ba5e0de668cedad24 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 11:53:06 +0100 Subject: [PATCH 064/106] Use @type instead of @var in Security/RoleForm.php --- application/forms/Security/RoleForm.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php index a45ca16ac..eed9ea441 100644 --- a/application/forms/Security/RoleForm.php +++ b/application/forms/Security/RoleForm.php @@ -19,14 +19,14 @@ class RoleForm extends ConfigForm /** * Provided permissions by currently loaded modules * - * @var array + * @type array */ protected $providedPermissions = array(); /** * Provided restrictions by currently loaded modules * - * @var array + * @type array */ protected $providedRestrictions = array(); @@ -39,11 +39,11 @@ class RoleForm extends ConfigForm $helper = new Zend_Form_Element('bogus'); foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) { foreach ($module->getProvidedPermissions() as $permission) { - /** @var object $permission */ + /** @type object $permission */ $this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description; } foreach ($module->getProvidedRestrictions() as $restriction) { - /** @var object $restriction */ + /** @type object $restriction */ $name = $helper->filterName($restriction->name); // Zend only permits alphanumerics, the underscore, // the circumflex and any ASCII character in range // \x7f to \xff (127 to 255) From 4441c1d4de54295ade7fc57ff290534a33da2189 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 11:53:55 +0100 Subject: [PATCH 065/106] Allow to grant every permission --- application/forms/Security/RoleForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php index eed9ea441..b27a4ec8b 100644 --- a/application/forms/Security/RoleForm.php +++ b/application/forms/Security/RoleForm.php @@ -21,7 +21,7 @@ class RoleForm extends ConfigForm * * @type array */ - protected $providedPermissions = array(); + protected $providedPermissions = array('*' => '*'); /** * Provided restrictions by currently loaded modules From 2db286543385f569f18c0901ee59608ed560a2b5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 12:11:49 +0100 Subject: [PATCH 066/106] Do not use an extra loop for generating the unhandled objects filter in ServicesController.php --- .../controllers/ServicesController.php | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php index 315737b31..fdc040d29 100644 --- a/modules/monitoring/application/controllers/ServicesController.php +++ b/modules/monitoring/application/controllers/ServicesController.php @@ -74,6 +74,7 @@ class Monitoring_ServicesController extends Controller 'service_obsessing'*/ )); $unhandledObjects = array(); + $unhandledFilterExpressions = array(); $acknowledgedObjects = array(); $objectsInDowntime = array(); $serviceStates = array( @@ -94,6 +95,10 @@ class Monitoring_ServicesController extends Controller /** @var Service $service */ if ((bool) $service->problem === true && (bool) $service->handled === false) { $unhandledObjects[] = $service; + $unhandledFilterExpressions[] = Filter::matchAll( + Filter::where('host', $service->getHost()->getName()), + Filter::where('service', $service->getName()) + ); } if ((bool) $service->acknowledged === true) { $acknowledgedObjects[] = $service; @@ -125,18 +130,11 @@ class Monitoring_ServicesController extends Controller $this->view->serviceStates = $serviceStates; $this->view->objects = $this->serviceList; $this->view->unhandledObjects = $unhandledObjects; - $unhandledFilterExpressions = array(); - foreach ($unhandledObjects as $service) { - $unhandledFilterExpressions[] = Filter::matchAll( - Filter::expression('host', '=', $service->getHost()->getName()), - Filter::expression('service', '=', $service->getName()) - ); - } - $queryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString(); - $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/services/acknowledge-problem'); - $this->view->acknowledgeUnhandledLink->setQueryString($queryString); - $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/services/schedule-downtime'); - $this->view->downtimeUnhandledLink->setQueryString($queryString); + $unhandledFilterQueryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString(); + $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/services/acknowledge-problem') + ->setQueryString($unhandledFilterQueryString); + $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/services/schedule-downtime') + ->setQueryString($unhandledFilterQueryString); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; $this->view->inDowntimeLink = Url::fromRequest() From f1f808b7a3d820eaf8a004954dfc41a7e799d798 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 12:17:17 +0100 Subject: [PATCH 067/106] Do not use array_map for generating the unhandled objects filter in HostsController.php --- .../application/controllers/HostsController.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/monitoring/application/controllers/HostsController.php b/modules/monitoring/application/controllers/HostsController.php index 451f6e44d..8fe431ca2 100644 --- a/modules/monitoring/application/controllers/HostsController.php +++ b/modules/monitoring/application/controllers/HostsController.php @@ -72,6 +72,7 @@ class Monitoring_HostsController extends Controller 'host_obsessing'*/ )); $unhandledObjects = array(); + $unhandledFilterExpressions = array(); $acknowledgedObjects = array(); $objectsInDowntime = array(); $hostStates = array( @@ -81,9 +82,10 @@ class Monitoring_HostsController extends Controller Host::getStateText(Host::STATE_PENDING) => 0, ); foreach ($this->hostList as $host) { - /** @var Service $host */ + /** @var Host $host */ if ((bool) $host->problem === true && (bool) $host->handled === false) { $unhandledObjects[] = $host; + $unhandledFilterExpressions[] = Filter::where('host', $host->getName()); } if ((bool) $host->acknowledged === true) { $acknowledgedObjects[] = $host; @@ -108,12 +110,11 @@ class Monitoring_HostsController extends Controller $this->view->hostStates = $hostStates; $this->view->objects = $this->hostList; $this->view->unhandledObjects = $unhandledObjects; - $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/hosts/acknowledge-problem')->setQueryString( - Filter::where('host', array_map(function ($h) { return $h->host; }, $unhandledObjects))->toQueryString() - ); - $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/hosts/schedule-downtime')->setQueryString( - Filter::where('host', array_map(function ($h) { return $h->host; }, $unhandledObjects))->toQueryString() - ); + $unhandledFilterQueryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString(); + $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/hosts/acknowledge-problem') + ->setQueryString($unhandledFilterQueryString); + $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/hosts/schedule-downtime') + ->setQueryString($unhandledFilterQueryString); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; $this->view->inDowntimeLink = Url::fromRequest() From 26bc56e9df306cea1e1937720d07c1dc5b6f519b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 12:19:37 +0100 Subject: [PATCH 068/106] monitoring: Fix the link to hosts in downtime when multiple hosts are selected --- .../monitoring/application/controllers/HostsController.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/application/controllers/HostsController.php b/modules/monitoring/application/controllers/HostsController.php index 8fe431ca2..09957a4a0 100644 --- a/modules/monitoring/application/controllers/HostsController.php +++ b/modules/monitoring/application/controllers/HostsController.php @@ -75,6 +75,7 @@ class Monitoring_HostsController extends Controller $unhandledFilterExpressions = array(); $acknowledgedObjects = array(); $objectsInDowntime = array(); + $downtimeFilterExpressions = array(); $hostStates = array( Host::getStateText(Host::STATE_UP) => 0, Host::getStateText(Host::STATE_DOWN) => 0, @@ -92,6 +93,7 @@ class Monitoring_HostsController extends Controller } if ((bool) $host->in_downtime === true) { $objectsInDowntime[] = $host; + $downtimeFilterExpressions[] = Filter::where('downtime_host', $host->getName()); } ++$hostStates[$host::getStateText($host->state)]; } @@ -117,8 +119,8 @@ class Monitoring_HostsController extends Controller ->setQueryString($unhandledFilterQueryString); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; - $this->view->inDowntimeLink = Url::fromRequest() - ->setPath('monitoring/list/downtimes'); + $this->view->inDowntimeLink = Url::fromPath('monitoring/list/downtimes') + ->setQueryString(Filter::matchAny($downtimeFilterExpressions)->toQueryString()); $this->view->havingCommentsLink = Url::fromRequest() ->setPath('monitoring/list/comments'); $this->view->hostStatesPieChart = $this->createPieChart( From bf92f9fa85476450e898333293da3c49575f2e0b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 12:25:41 +0100 Subject: [PATCH 069/106] monitoring: Fix the link to services in downtime when multiple services are selected --- .../application/controllers/ServicesController.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php index fdc040d29..4d08622c2 100644 --- a/modules/monitoring/application/controllers/ServicesController.php +++ b/modules/monitoring/application/controllers/ServicesController.php @@ -77,6 +77,7 @@ class Monitoring_ServicesController extends Controller $unhandledFilterExpressions = array(); $acknowledgedObjects = array(); $objectsInDowntime = array(); + $downtimeFilterExpressions = array(); $serviceStates = array( Service::getStateText(Service::STATE_OK) => 0, Service::getStateText(Service::STATE_WARNING) => 0, @@ -105,6 +106,10 @@ class Monitoring_ServicesController extends Controller } if ((bool) $service->in_downtime === true) { $objectsInDowntime[] = $service; + $downtimeFilterExpressions[] = Filter::matchAll( + Filter::where('downtime_host', $service->getHost()->getName()), + Filter::where('downtime_service', $service->getName()) + ); } ++$serviceStates[$service::getStateText($service->state)]; if (! isset($knownHostStates[$service->getHost()->getName()])) { @@ -137,8 +142,8 @@ class Monitoring_ServicesController extends Controller ->setQueryString($unhandledFilterQueryString); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; - $this->view->inDowntimeLink = Url::fromRequest() - ->setPath('monitoring/list/downtimes'); + $this->view->inDowntimeLink = Url::fromPath('monitoring/list/downtimes') + ->setQueryString(Filter::matchAny($downtimeFilterExpressions)->toQueryString()); $this->view->havingCommentsLink = Url::fromRequest() ->setPath('monitoring/list/comments'); $this->view->serviceStatesPieChart = $this->createPieChart( From a48adb5e4bea9fd72ddc2f39be60ec1b671cda7f Mon Sep 17 00:00:00 2001 From: root Date: Wed, 24 Dec 2014 16:30:30 +0000 Subject: [PATCH 070/106] doc: Fix typo in installation.md Signed-off-by: Eric Lippmann --- doc/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/installation.md b/doc/installation.md index 88c9c3650..6eb6737ec 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -26,7 +26,7 @@ repository either via git or http protocol using the following URLs: * http://git.icinga.org/icingaweb2.git There is also a browsable version available at -[gi.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository"). +[git.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository"). This version also offers snapshots for easy download which you can use if you do not have git present on your system. ```` From 7d36a59c67dba7b177f53361f479929c5e19ccd5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:01:19 +0100 Subject: [PATCH 071/106] Use '@return $this' instead of '@return self' for document fluent interfaces in ApplicationBootstrap.php --- .../Icinga/Application/ApplicationBootstrap.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/Icinga/Application/ApplicationBootstrap.php b/library/Icinga/Application/ApplicationBootstrap.php index 81230a7fb..86dcef8c4 100644 --- a/library/Icinga/Application/ApplicationBootstrap.php +++ b/library/Icinga/Application/ApplicationBootstrap.php @@ -333,7 +333,7 @@ abstract class ApplicationBootstrap /** * Setup Icinga auto loader * - * @return self + * @return $this */ public function setupAutoloader() { @@ -366,7 +366,7 @@ abstract class ApplicationBootstrap /** * Setup module manager * - * @return self + * @return $this */ protected function setupModuleManager() { @@ -381,7 +381,7 @@ abstract class ApplicationBootstrap /** * Load all enabled modules * - * @return self + * @return $this */ protected function loadEnabledModules() { @@ -396,7 +396,7 @@ abstract class ApplicationBootstrap /** * Setup default logging * - * @return self + * @return $this */ protected function setupLogging() { @@ -413,7 +413,7 @@ abstract class ApplicationBootstrap /** * Load Configuration * - * @return self + * @return $this */ protected function loadConfig() { @@ -432,7 +432,7 @@ abstract class ApplicationBootstrap /** * Error handling configuration * - * @return self + * @return $this */ protected function setupErrorHandling() { @@ -458,7 +458,7 @@ abstract class ApplicationBootstrap /** * Set up logger * - * @return self + * @return $this */ protected function setupLogger() { @@ -475,7 +475,7 @@ abstract class ApplicationBootstrap /** * Set up the resource factory * - * @return self + * @return $this */ protected function setupResourceFactory() { From 611d01788f787bd4c2451bb75c05f224174ff984 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:29:31 +0100 Subject: [PATCH 072/106] Add setup related utility functions to ApplicationBootstrap.php --- .../Application/ApplicationBootstrap.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/library/Icinga/Application/ApplicationBootstrap.php b/library/Icinga/Application/ApplicationBootstrap.php index 86dcef8c4..92e97ba39 100644 --- a/library/Icinga/Application/ApplicationBootstrap.php +++ b/library/Icinga/Application/ApplicationBootstrap.php @@ -113,6 +113,13 @@ abstract class ApplicationBootstrap */ protected $isWeb = false; + /** + * Whether Icinga Web 2 requires setup + * + * @type bool + */ + protected $requiresSetup = false; + /** * Constructor * @@ -393,6 +400,40 @@ abstract class ApplicationBootstrap return $this; } + /** + * Load the setup module if Icinga Web 2 requires setup + * + * @return $this + */ + protected function loadSetupModuleIfNecessary() + { + if (! @file_exists($this->config->resolvePath('config.ini'))) { + $this->requiresSetup = true; + $this->moduleManager->loadModule('setup'); + } + return $this; + } + + /** + * Get whether Icinga Web 2 requires setup + * + * @return bool + */ + public function requiresSetup() + { + return $this->requiresSetup; + } + + /** + * Get whether the setup token exists + * + * @return bool + */ + public function setupTokenExists() + { + return @file_exists($this->config->resolvePath('setup.token')); + } + /** * Setup default logging * From 9d8fab51b1c4f147d70cef111c5cdd360b66fe6f Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:30:06 +0100 Subject: [PATCH 073/106] Use the setup related utility functions in AuthenticationController.php --- application/controllers/AuthenticationController.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php index 00dae1c6d..d2c9d4873 100644 --- a/application/controllers/AuthenticationController.php +++ b/application/controllers/AuthenticationController.php @@ -15,6 +15,7 @@ use Icinga\Exception\NotReadableError; use Icinga\Exception\ConfigurationError; use Icinga\User; use Icinga\Web\Url; +use Icinga\Application\Icinga; /** * Application wide controller for authentication @@ -33,7 +34,8 @@ class AuthenticationController extends ActionController */ public function loginAction() { - if (@file_exists(Config::resolvePath('setup.token')) && !@file_exists(Config::resolvePath('config.ini'))) { + $icinga = Icinga::app(); + if ($icinga->setupTokenExists() && $icinga->requiresSetup()) { $this->redirectNow(Url::fromPath('setup')); } @@ -139,7 +141,7 @@ class AuthenticationController extends ActionController $this->view->errorInfo = $e->getMessage(); } - $this->view->configMissing = is_dir(Config::$configDir) === false; + $this->view->requiresSetup = Icinga::app()->requiresSetup(); } /** From 250e05f2e81d448f9f03e6e20fbbfd42331038dd Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:30:47 +0100 Subject: [PATCH 074/106] Optimize imports in AuthenticationController.php --- .../controllers/AuthenticationController.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php index d2c9d4873..2d7926819 100644 --- a/application/controllers/AuthenticationController.php +++ b/application/controllers/AuthenticationController.php @@ -4,18 +4,18 @@ # namespace Icinga\Application\Controllers; -use Icinga\Authentication\Backend\AutoLoginBackend; -use Icinga\Web\Controller\ActionController; -use Icinga\Forms\Authentication\LoginForm; -use Icinga\Authentication\AuthChain; use Icinga\Application\Config; -use Icinga\Application\Logger; -use Icinga\Exception\AuthenticationException; -use Icinga\Exception\NotReadableError; -use Icinga\Exception\ConfigurationError; -use Icinga\User; -use Icinga\Web\Url; use Icinga\Application\Icinga; +use Icinga\Application\Logger; +use Icinga\Authentication\AuthChain; +use Icinga\Authentication\Backend\AutoLoginBackend; +use Icinga\Exception\AuthenticationException; +use Icinga\Exception\ConfigurationError; +use Icinga\Exception\NotReadableError; +use Icinga\Forms\Authentication\LoginForm; +use Icinga\User; +use Icinga\Web\Controller\ActionController; +use Icinga\Web\Url; /** * Application wide controller for authentication From 74ce666cd85a4ca3b1abf38874cf78b686986a19 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:31:07 +0100 Subject: [PATCH 075/106] Use the requiresSetup variable instead of configMissing in login.phtml --- application/views/scripts/authentication/login.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/views/scripts/authentication/login.phtml b/application/views/scripts/authentication/login.phtml index 416e651d1..a3d8fcfa9 100644 --- a/application/views/scripts/authentication/login.phtml +++ b/application/views/scripts/authentication/login.phtml @@ -15,7 +15,7 @@ form ?>
- +
Date: Mon, 29 Dec 2014 14:31:34 +0100 Subject: [PATCH 076/106] Web: Load setup module if necessary --- library/Icinga/Application/Web.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php index a21f21025..5b18f1be8 100644 --- a/library/Icinga/Application/Web.php +++ b/library/Icinga/Application/Web.php @@ -104,6 +104,7 @@ class Web extends ApplicationBootstrap ->setupZendMvc() ->setupFormNamespace() ->setupModuleManager() + ->loadSetupModuleIfNecessary() ->loadEnabledModules() ->setupRoute() ->setupPagination(); From 19387b24ab726529d3a7fb7cd25b7bfc83c44f55 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:32:20 +0100 Subject: [PATCH 077/106] Do not use a new function for getting the configuration directory in our web wizard --- modules/setup/library/Setup/WebWizard.php | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php index faa123fe8..8dff112f5 100644 --- a/modules/setup/library/Setup/WebWizard.php +++ b/modules/setup/library/Setup/WebWizard.php @@ -9,6 +9,7 @@ use Icinga\Web\Form; use Icinga\Web\Wizard; use Icinga\Web\Request; use Icinga\Application\Config; +use Icinga\Application\Icinga; use Icinga\Application\Platform; use Icinga\Module\Setup\Forms\ModulePage; use Icinga\Module\Setup\Forms\WelcomePage; @@ -343,7 +344,7 @@ class WebWizard extends Wizard implements SetupWizard ); } - $configDir = $this->getConfigDir(); + $configDir = Icinga::app()->getConfigDir(); $setup->addStep( new MakeDirStep( array( @@ -528,7 +529,7 @@ class WebWizard extends Wizard implements SetupWizard ) ); - $configDir = $this->getConfigDir(); + $configDir = Icinga::app()->getConfigDir(); $requirements->addMandatory( mt('setup', 'Writable Config Directory'), mt( @@ -551,21 +552,4 @@ class WebWizard extends Wizard implements SetupWizard return $requirements; } - - /** - * Return the configuration directory of Icinga Web 2 - * - * @return string - */ - protected function getConfigDir() - { - if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) { - $configDir = $_SERVER['ICINGAWEB_CONFIGDIR']; - } else { - $configDir = '/etc/icingaweb'; - } - - $canonical = realpath($configDir); - return $canonical ? $canonical : $configDir; - } } From daaf242145fb2d75209d0917e528fedc526421dc Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:33:07 +0100 Subject: [PATCH 078/106] Fix the default configuration path in our web wizard --- modules/setup/library/Setup/WebWizard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php index 8dff112f5..e4d61dfd7 100644 --- a/modules/setup/library/Setup/WebWizard.php +++ b/modules/setup/library/Setup/WebWizard.php @@ -534,7 +534,7 @@ class WebWizard extends Wizard implements SetupWizard mt('setup', 'Writable Config Directory'), mt( 'setup', - 'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb", if' . + 'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb2", if' . ' not explicitly set in the environment variable "ICINGAWEB_CONFIGDIR".' ), is_writable($configDir), From 2bd9d27e054fcf86970e07f59127b19bf676688a Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 14:33:37 +0100 Subject: [PATCH 079/106] Do not validate the mode of the setup.token Relying on the mode of the configuration directory must be sufficient. --- .../Setup/Web/Form/Validator/TokenValidator.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php b/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php index 7dc2ea2f9..fa858f531 100644 --- a/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php +++ b/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php @@ -38,10 +38,6 @@ class TokenValidator extends Zend_Validate_Abstract mt('setup', 'Cannot validate token, file "%s" is empty. Please define a token.'), $tokenPath ), - 'TOKEN_FILE_PUBLIC' => sprintf( - mt('setup', 'Cannot validate token, file "%s" must only be accessible by the webserver\'s user.'), - $tokenPath - ), 'TOKEN_INVALID' => mt('setup', 'Invalid token supplied.') ); } @@ -56,12 +52,6 @@ class TokenValidator extends Zend_Validate_Abstract */ public function isValid($value, $context = null) { - $tokenStats = @stat($this->tokenPath); - if (($tokenStats['mode'] & 4) === 4) { - $this->_error('TOKEN_FILE_PUBLIC'); - return false; - } - try { $file = new File($this->tokenPath); $expectedToken = trim($file->fgets()); From 94a4b4425f82412dead4a26c57af9763b53d12cd Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 15:42:24 +0100 Subject: [PATCH 080/106] puppet: Use icingaweb2 instead of icingaweb in paths and database setup --- .puppet/hiera/common.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.puppet/hiera/common.yaml b/.puppet/hiera/common.yaml index 0a85ba63a..c76b904bf 100644 --- a/.puppet/hiera/common.yaml +++ b/.puppet/hiera/common.yaml @@ -1,7 +1,7 @@ --- -icingaweb2::config: /etc/icingaweb -icingaweb2::log: /var/log/icingaweb/icingaweb.log -icingaweb2::web_path: icingaweb -icingaweb2::db_user: icingaweb -icingaweb2::db_pass: icingaweb -icingaweb2::db_name: icingaweb +icingaweb2::config: /etc/icingaweb2 +icingaweb2::log: /var/log/icingaweb2/icingaweb2.log +icingaweb2::web_path: icingaweb2 +icingaweb2::db_user: icingaweb2 +icingaweb2::db_pass: icingaweb2 +icingaweb2::db_name: icingaweb2 From e1bedc9afedfa163268f8cb536e18f4f26ad54ca Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 15:55:57 +0100 Subject: [PATCH 081/106] Use Icinga 2's default Livestatus socket path as default when configuring a livestatus resource --- application/forms/Config/Resource/LivestatusResourceForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/forms/Config/Resource/LivestatusResourceForm.php b/application/forms/Config/Resource/LivestatusResourceForm.php index d90600370..2262cf583 100644 --- a/application/forms/Config/Resource/LivestatusResourceForm.php +++ b/application/forms/Config/Resource/LivestatusResourceForm.php @@ -44,7 +44,7 @@ class LivestatusResourceForm extends Form 'required' => true, 'label' => t('Socket'), 'description' => t('The path to your livestatus socket used for querying monitoring data'), - 'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus') + 'value' => '/var/run/icinga2/cmd/livestatus' ) ); From cfb52eeadb1c0a0404d47bf5b74a9a48cff68ad0 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 15:56:32 +0100 Subject: [PATCH 082/106] Do not use a default regular expression for stripping off parts of a username when configuring an auto-login backend There's no safe default for this. --- .../forms/Config/Authentication/AutologinBackendForm.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/application/forms/Config/Authentication/AutologinBackendForm.php b/application/forms/Config/Authentication/AutologinBackendForm.php index a21d2c006..97b5dfed7 100644 --- a/application/forms/Config/Authentication/AutologinBackendForm.php +++ b/application/forms/Config/Authentication/AutologinBackendForm.php @@ -53,8 +53,10 @@ class AutologinBackendForm extends Form 'strip_username_regexp', array( 'label' => t('Filter Pattern'), - 'description' => t('The regular expression to use to strip specific parts off from usernames. Leave empty if you do not want to strip off anything'), - 'value' => '/\@[^$]+$/', + 'description' => t( + 'The regular expression to use to strip specific parts off from usernames.' + . ' Leave empty if you do not want to strip off anything' + ), 'validators' => array( new Zend_Validate_Callback(function ($value) { return @preg_match($value, '') !== false; From 5bc2144b18670fdc98756b87ecfc979be97c5808 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 16:01:07 +0100 Subject: [PATCH 083/106] Use 'icingaweb2' as default application prefix for logging to syslog --- application/forms/Config/General/LoggingConfigForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/forms/Config/General/LoggingConfigForm.php b/application/forms/Config/General/LoggingConfigForm.php index deed06011..bb9bea33a 100644 --- a/application/forms/Config/General/LoggingConfigForm.php +++ b/application/forms/Config/General/LoggingConfigForm.php @@ -67,7 +67,7 @@ class LoggingConfigForm extends Form 'required' => true, 'label' => t('Application Prefix'), 'description' => t('The name of the application by which to prefix syslog messages.'), - 'value' => 'icingaweb', + 'value' => 'icingaweb2', 'validators' => array( array( 'Regex', From f0fe6246acf8e3b1c0d1b9c8b7524ac450b7d99c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 16:02:40 +0100 Subject: [PATCH 084/106] Use '/var/log/icingaweb2/icingaweb2.log' as default path when logging to file --- .../forms/Config/General/LoggingConfigForm.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/application/forms/Config/General/LoggingConfigForm.php b/application/forms/Config/General/LoggingConfigForm.php index bb9bea33a..759c2a6e3 100644 --- a/application/forms/Config/General/LoggingConfigForm.php +++ b/application/forms/Config/General/LoggingConfigForm.php @@ -106,7 +106,7 @@ class LoggingConfigForm extends Form 'required' => true, 'label' => t('File path'), 'description' => t('The full path to the log file to write messages to.'), - 'value' => $this->getDefaultLogDir(), + 'value' => '/var/log/icingaweb2/icingaweb2.log', 'validators' => array(new WritablePathValidator()) ) ); @@ -114,14 +114,4 @@ class LoggingConfigForm extends Form return $this; } - - /** - * Return the default logging directory for type 'file' - * - * @return string - */ - protected function getDefaultLogDir() - { - return realpath(Icinga::app()->getApplicationDir('../var/log/icingaweb.log')); - } } From ff17c3729cfa1b073277f8f5c4278c554a5c26a5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 16:06:34 +0100 Subject: [PATCH 085/106] setup: Use 'icingaweb2' as default authentication backend name --- modules/setup/application/forms/AuthBackendPage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setup/application/forms/AuthBackendPage.php b/modules/setup/application/forms/AuthBackendPage.php index fac2a7bbd..bd820d352 100644 --- a/modules/setup/application/forms/AuthBackendPage.php +++ b/modules/setup/application/forms/AuthBackendPage.php @@ -112,7 +112,7 @@ class AuthBackendPage extends Form } $this->addElements($backendForm->getElements()); - $this->getElement('name')->setValue('icingaweb'); + $this->getElement('name')->setValue('icingaweb2'); } /** From 4cf8da4bb9bd0bf09cb80ac82b79852126e7ba0c Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Mon, 29 Dec 2014 13:30:54 +0100 Subject: [PATCH 086/106] Do not focus logout menu item after a recurring login Implement new MenuItemRenderer made for pages that are not part of the regular site navigation and should trigger a complete site reload instead of handling it via XHR. --- library/Icinga/Web/Menu.php | 3 ++- .../Web/Menu/ForeignMenuItemRenderer.php | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 library/Icinga/Web/Menu/ForeignMenuItemRenderer.php diff --git a/library/Icinga/Web/Menu.php b/library/Icinga/Web/Menu.php index 18a17ea67..a74112dc4 100644 --- a/library/Icinga/Web/Menu.php +++ b/library/Icinga/Web/Menu.php @@ -248,7 +248,8 @@ class Menu implements RecursiveIterator $section->add(t('Logout'), array( 'url' => 'authentication/logout', - 'priority' => 700 + 'priority' => 700, + 'renderer' => 'ForeignMenuItemRenderer' )); } } diff --git a/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php b/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php new file mode 100644 index 000000000..659709868 --- /dev/null +++ b/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php @@ -0,0 +1,24 @@ +%s%s', + $menu->getUrl() ?: '#', + $menu->getIcon() ? ' ' : '', + htmlspecialchars($menu->getTitle()) + ); + } +} From 3d07049fbfc863f28969afd0b16c6bfe9a2ab15f Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Mon, 29 Dec 2014 16:14:12 +0100 Subject: [PATCH 087/106] Re-render menu item after setting class to active Force the browser to re-render the menu item, to update the link layout immediately by recreting the content html. fixes #7897 --- public/js/icinga/behavior/navigation.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/public/js/icinga/behavior/navigation.js b/public/js/icinga/behavior/navigation.js index fde043c01..53fc5c8af 100644 --- a/public/js/icinga/behavior/navigation.js +++ b/public/js/icinga/behavior/navigation.js @@ -32,6 +32,15 @@ if ($outerMenu.size()) { $outerMenu.addClass('active'); } + + /* + Recreate the html content of the menu item to force the browser to update the layout, or else + the link would only be visible as active after another click or page reload in Gecko and WebKit. + + fixes #7897 + */ + $selectedMenu.html($selectedMenu.html()); + } else { // store menu state var $menus = $('#menu li.active', el); From a1950aabbac1699136d1567583bc58a42e52b290 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Mon, 29 Dec 2014 16:27:28 +0100 Subject: [PATCH 088/106] Fix some obsolete or wrong docstrings --- library/Icinga/Web/Controller/ActionController.php | 2 +- library/Icinga/Web/Menu.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index 400803dce..013f31099 100644 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -270,7 +270,7 @@ class ActionController extends Zend_Controller_Action /** * Redirect to the login path * - * @param string $afterLogin The action to call when the login was successful. Defaults to '/index/welcome' + * @param Url $afterLogin The action to call when the login was successful. Defaults to '/index/welcome' * * @throws \Exception */ diff --git a/library/Icinga/Web/Menu.php b/library/Icinga/Web/Menu.php index a74112dc4..f0279ea9c 100644 --- a/library/Icinga/Web/Menu.php +++ b/library/Icinga/Web/Menu.php @@ -367,7 +367,7 @@ class Menu implements RecursiveIterator /** * Return the url of this menu * - * @return string + * @return Url */ public function getUrl() { From 0b8ab18243da17af6c128da18ad691491013a144 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 16:30:44 +0100 Subject: [PATCH 089/106] Parsedown: Rename LICENSE.txt to LICENSE --- library/vendor/Parsedown/{LICENSE.txt => LICENSE} | 0 library/vendor/Parsedown/SOURCE | 1 + 2 files changed, 1 insertion(+) rename library/vendor/Parsedown/{LICENSE.txt => LICENSE} (100%) diff --git a/library/vendor/Parsedown/LICENSE.txt b/library/vendor/Parsedown/LICENSE similarity index 100% rename from library/vendor/Parsedown/LICENSE.txt rename to library/vendor/Parsedown/LICENSE diff --git a/library/vendor/Parsedown/SOURCE b/library/vendor/Parsedown/SOURCE index c5a2c7c28..43ee6c61c 100644 --- a/library/vendor/Parsedown/SOURCE +++ b/library/vendor/Parsedown/SOURCE @@ -4,3 +4,4 @@ DESTINATION=. wget -O ${FILENAME}.tar.gz https://github.com/erusev/parsedown/archive/${RELEASE}.tar.gz tar xfz ${FILENAME}.tar.gz -C $DESTINATION/ --strip-components 1 $FILENAME/Parsedown.php $FILENAME/LICENSE.txt chmod 644 $DESTINATION/Parsedown.php +mv LICENSE.txt LICENSE From 57121bf0ea1ddfb099e80286a2d8a65d7316f3a5 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 16:31:21 +0100 Subject: [PATCH 090/106] dompdf: Rename LICENSE.LGPL to LICENSE --- library/vendor/dompdf/{LICENSE.LGPL => LICENSE} | 0 library/vendor/dompdf/SOURCE | 1 + 2 files changed, 1 insertion(+) rename library/vendor/dompdf/{LICENSE.LGPL => LICENSE} (100%) diff --git a/library/vendor/dompdf/LICENSE.LGPL b/library/vendor/dompdf/LICENSE similarity index 100% rename from library/vendor/dompdf/LICENSE.LGPL rename to library/vendor/dompdf/LICENSE diff --git a/library/vendor/dompdf/SOURCE b/library/vendor/dompdf/SOURCE index 9343b58cf..c26253e30 100644 --- a/library/vendor/dompdf/SOURCE +++ b/library/vendor/dompdf/SOURCE @@ -1,6 +1,7 @@ curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.6.1 -o dompdf-0.6.1.tar.gz tar xzf dompdf-0.6.1.tar.gz --strip-components 1 dompdf-0.6.1/{include/*.php,lib,dompdf*.php,LICENSE.LGPL} rm dompdf-0.6.1.tar.gz +mv LICENSE.LGPL LICENSE curl https://codeload.github.com/PhenX/php-font-lib/tar.gz/0.3.1 -o php-font-lib-0.3.1.tar.gz mkdir lib/php-font-lib/classes From 2d0153464d20ebf3bbb43b1c486757ad33616201 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 16:48:18 +0100 Subject: [PATCH 091/106] Add spec file for RHEL (CentOS and Fedora) packages refs #6401 fixes #6894 --- icingaweb2.spec | 398 ++++++++++++++++++++++++------------------------ 1 file changed, 198 insertions(+), 200 deletions(-) diff --git a/icingaweb2.spec b/icingaweb2.spec index fb628f995..0b4813bc4 100644 --- a/icingaweb2.spec +++ b/icingaweb2.spec @@ -1,237 +1,235 @@ -#/** -# * This file is part of Icinga Web 2. -# * -# * Icinga Web 2 - Head for multiple monitoring backends. -# * Copyright (C) 2014 Icinga Development Team -# * -# * This program is free software; you can redistribute it and/or -# * modify it under the terms of the GNU General Public License -# * as published by the Free Software Foundation; either version 2 -# * of the License, or (at your option) any later version. -# * -# * This program is distributed in the hope that it will be useful, -# * but WITHOUT ANY WARRANTY; without even the implied warranty of -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# * GNU General Public License for more details. -# * -# * You should have received a copy of the GNU General Public License -# * along with this program; if not, write to the Free Software -# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# * -# * @copyright 2014 Icinga Development Team -# * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 -# * @author Icinga Development Team -# * -# */ - -%define revision 1 - -%define configdir %{_sysconfdir}/%{name} -%define sharedir %{_datadir}/%{name} -%define prefixdir %{_datadir}/%{name} -%define usermodparam -a -G -%define logdir %{_localstatedir}/log/%{name} -%define docdir %{sharedir}/doc - -%if "%{_vendor}" == "suse" -%define phpname php5 -%define phpzendname php5-ZendFramework -%define apache2modphpname apache2-mod_php5 -%endif -# SLE 11 = 1110 -%if 0%{?suse_version} == 1110 -%define phpname php53 -%define apache2modphpname apache2-mod_php53 -%define usermodparam -A -%endif - -%if "%{_vendor}" == "redhat" -%define phpname php -%define phpzendname php-ZendFramework -%endif - -# el5 requires newer php53 rather than php (5.1) -%if 0%{?el5} || 0%{?rhel} == 5 || "%{?dist}" == ".el5" -%define phpname php53 -%endif - -%if "%{_vendor}" == "suse" -%define apacheconfdir %{_sysconfdir}/apache2/conf.d -%define apacheuser wwwrun -%define apachegroup www -%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd -%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus -%endif -%if "%{_vendor}" == "redhat" -%define apacheconfdir %{_sysconfdir}/httpd/conf.d -%define apacheuser apache -%define apachegroup apache -%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd -%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus -%endif - -Summary: Open Source host, service and network monitoring Web UI Name: icingaweb2 -Version: 0.0.1 -Release: %{revision}%{?dist} -License: GPLv2 +Version: 2.0.0 +Release: 1.beta2%{?dist} +Summary: Icinga Web 2 Group: Applications/System -URL: http://www.icinga.org +License: GPL +URL: https://icinga.org +Source0: https://github.com/Icinga/%{name}/archive/v%{version}.tar.gz BuildArch: noarch +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release} +Packager: Icinga Team -%if "%{_vendor}" == "suse" -AutoReqProv: Off +%if 0%{?fedora} || 0%{?rhel} +%define wwwconfigdir %{_sysconfdir}/httpd/conf.d +%define wwwuser apache +%if 0%{?rhel} == 5 +%define php php53 +%define php_cli php53-cli +%else +%define php php +%define php_cli php-cli +%endif +%if 0%{rhel} == 6 +%define zend php-ZendFramework +%else +%define zend %{name}-vendor-Zend +%endif %endif -Source: icingaweb2-%{version}.tar.gz - -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root - -BuildRequires: %{phpname} >= 5.3.0 -BuildRequires: %{phpname}-devel >= 5.3.0 -BuildRequires: %{phpname}-ldap -BuildRequires: %{phpname}-pdo -BuildRequires: %{phpzendname} -%if "%{_vendor}" != "suse" -BuildRequires: %{phpzendname}-Db-Adapter-Pdo -BuildRequires: %{phpzendname}-Db-Adapter-Pdo-Mysql -BuildRequires: %{phpzendname}-Db-Adapter-Pdo-Pgsql -%endif - -%if "%{_vendor}" == "redhat" -%endif -%if "%{_vendor}" == "suse" -Requires: %{phpname}-devel >= 5.3.0 -BuildRequires: %{phpname}-json -BuildRequires: %{phpname}-sockets -BuildRequires: %{phpname}-dom -%endif - -Requires: %{phpname} >= 5.3.0 -Requires: %{phpzendname} -Requires: %{phpname}-ldap -Requires: %{phpname}-pdo -%if "%{_vendor}" == "redhat" -Requires: %{phpname}-common -Requires: %{phpzendname}-Db-Adapter-Pdo -Requires: %{phpzendname}-Db-Adapter-Pdo-Mysql -Requires: php-pear -%endif -%if "%{_vendor}" == "suse" -Requires: %{phpname}-pear -Requires: %{phpname}-dom -Requires: %{phpname}-tokenizer -Requires: %{phpname}-gettext -Requires: %{phpname}-ctype -Requires: %{phpname}-json -Requires: %{apache2modphpname} -%endif - -Requires: php-Icinga +Requires(pre): shadow-utils +Requires: %{name}-common = %{version}-%{release} +Requires: php-Icinga = %{version}-%{release} +Requires: %{name}-vendor-dompdf +Requires: %{name}-vendor-HTMLPurifier +Requires: %{name}-vendor-JShrink +Requires: %{name}-vendor-lessphp +Requires: %{name}-vendor-Parsedown +Requires: %{zend} %description -Icinga Web 2 for Icinga 2 or Icinga 1.x using multiple backends -for example DB IDO. +Icinga Web 2 + + +%define basedir %{_datadir}/%{name} +%define bindir %{_bindir} +%define configdir %{_sysconfdir}/%{name} +%define logdir %{_localstatedir}/log/%{name} +%define phpdir %{_datadir}/php +%define icingawebgroup icingaweb2 + + +%package common +Summary: Common files for Icinga Web 2 and the Icinga CLI +Group: Applications/System + +%description common +Common files for Icinga Web 2 and the Icinga CLI + + +%package -n php-Icinga +Summary: Icinga Web 2 PHP library +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description -n php-Icinga +Icinga Web 2 PHP library + %package -n icingacli Summary: Icinga CLI Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: php-Icinga +Requires: %{name}-common = %{version}-%{release} +Requires: php-Icinga = %{version}-%{release} +Requires: %{php_cli} >= 5.3.0 %description -n icingacli -Icinga CLI using php-Icinga Icinga Web 2 backend. - -%package -n php-Icinga -Summary: Icinga Web 2 PHP Libraries -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: %{phpname} >= 5.3.0 -Requires: %{phpzendname} +Icinga CLI -%description -n php-Icinga -Icinga Web 2 PHP Libraries required by the web frontend and cli tool. +%package vendor-dompdf +Version: 0.6.1 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library dompdf +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-dompdf +Icinga Web 2 vendor library dompdf + + +%package vendor-HTMLPurifier +Version: 4.6.0 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library HTMLPurifier +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-HTMLPurifier +Icinga Web 2 vendor library HTMLPurifier + + +%package vendor-JShrink +Version: 1.0.1 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library JShrink +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-JShrink +Icinga Web 2 vendor library JShrink + + +%package vendor-lessphp +Version: 0.4.0 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library lessphp +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-lessphp +Icinga Web 2 vendor library lessphp + + +%package vendor-Parsedown +Version: 1.0.0 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library Parsedown +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-Parsedown +Icinga Web 2 vendor library Parsedown + + +%package vendor-Zend +Version: 1.12.9 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library Zend Framework +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-Zend +Icinga Web 2 vendor library Zend %prep -#VERSION=0.0.1; git archive --format=tar --prefix=icingaweb2-$VERSION/ HEAD | gzip >icingaweb2-$VERSION.tar.gz -%setup -q -n %{name}-%{version} +%setup -q %build %install -[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot} - -# prepare configuration for sub packages - -# install rhel apache config -install -D -m0644 packages/files/apache/icingaweb.conf %{buildroot}/%{apacheconfdir}/icingaweb.conf - -# install public, library, modules -%{__mkdir} -p %{buildroot}/%{sharedir} -%{__mkdir} -p %{buildroot}/%{logdir} -%{__mkdir} -p %{buildroot}/%{docdir} -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name} -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/dashboard -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules/monitoring -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/enabledModules - -# make sure to install local icingacli for setup wizard token generation & webserver config -%{__cp} -r application doc library modules public bin %{buildroot}/%{sharedir}/ - -# enable the monitoring module by default -ln -s %{sharedir}/modules/monitoring %{buildroot}/%{_sysconfdir}/%{name}/enabledModules/monitoring -## config - -# symlink icingacli -mkdir -p %{buildroot}/usr/bin -ln -sf %{sharedir}/bin/icingacli %{buildroot}/usr/bin/icingacli +rm -rf %{buildroot} +mkdir -p %{buildroot}/{%{basedir}/{modules,library,public},%{bindir},%{configdir},%{logdir},%{phpdir},%{wwwconfigdir}} +cp -prv application doc var %{buildroot}/%{basedir} +cp -prv modules/{monitoring,setup} %{buildroot}/%{basedir}/modules +cp -prv library/Icinga %{buildroot}/%{phpdir} +cp -prv library/vendor %{buildroot}/%{basedir}/library +cp -prv public/{css,img,js,error_norewrite.html} %{buildroot}/%{basedir}/public +cp -pv packages/files/apache/icingaweb2.conf %{buildroot}/%{wwwconfigdir}/icingaweb2.conf +cp -pv packages/files/bin/icingacli %{buildroot}/%{bindir} +cp -pv packages/files/public/index.php %{buildroot}/%{basedir}/public %pre -# Add apacheuser in the icingacmd group -# If the group exists, add the apacheuser in the icingacmd group. -# It is not neccessary that icinga2-web is installed on the same system as -# icinga and only on systems with icinga installed the icingacmd -# group exists. In all other cases the user used for ssh access has -# to be added to the icingacmd group on the remote icinga server. -getent group icingacmd > /dev/null - -if [ $? -eq 0 ]; then -%{_sbindir}/usermod %{usermodparam} icingacmd %{apacheuser} -fi - -%preun - -%post +getent group icingacmd >/dev/null || groupadd -r icingacmd +usermod -a -G icingacmd,%{icingawebgroup} %{wwwuser} +exit 0 %clean -[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot} +rm -rf %{buildroot} %files -# main dirs %defattr(-,root,root) -%doc etc/schema doc packages/RPM.md -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/public -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/modules -# configs +%{basedir}/application/controllers +%{basedir}/application/fonts +%{basedir}/application/forms +%{basedir}/application/layouts +%{basedir}/application/views +%{basedir}/doc +%{basedir}/modules +%{basedir}/public +%{wwwconfigdir}/icingaweb2.conf +%attr(2775,root,%{icingawebgroup}) %dir %{logdir} + + +%pre common +getent group %{icingawebgroup} >/dev/null || groupadd -r %{icingawebgroup} +exit 0 + +%files common %defattr(-,root,root) -%config(noreplace) %attr(-,root,root) %{apacheconfdir}/icingaweb.conf -%config(noreplace) %attr(-,%{apacheuser},%{apachegroup}) %{configdir} -# logs -%attr(2775,%{apacheuser},%{apachegroup}) %dir %{logdir} -# shipped docs -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/doc +%{basedir}/application/locale +%dir %{basedir}/modules +%attr(2770,root,%{icingawebgroup}) %config(noreplace) %{configdir} + %files -n php-Icinga -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/application -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/library +%defattr(-,root,root) +%{phpdir}/Icinga + %files -n icingacli -%attr(0755,root,root) /usr/bin/icingacli -%attr(0755,root,root) %{sharedir}/bin/icingacli -%attr(0755,root,root) %{sharedir}/bin/license_writer.py +%defattr(-,root,root) +%{basedir}/application/clicommands +%attr(0755,root,root) %{bindir}/icingacli -%changelog + +%files vendor-dompdf +%defattr(-,root,root) +%{basedir}/library/vendor/dompdf + + +%files vendor-HTMLPurifier +%defattr(-,root,root) +%{basedir}/library/vendor/HTMLPurifier + + +%files vendor-JShrink +%defattr(-,root,root) +%{basedir}/library/vendor/JShrink + + +%files vendor-lessphp +%defattr(-,root,root) +%{basedir}/library/vendor/lessphp + + +%files vendor-Parsedown +%defattr(-,root,root) +%{basedir}/library/vendor/Parsedown + + +%files vendor-Zend +%defattr(-,root,root) +%{basedir}/library/vendor/Zend From fd044017fb385e93145243fbe6f51bd98d7c0595 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 17:31:00 +0100 Subject: [PATCH 092/106] Revert "Highlight hovered state rows even if there is no href" This reverts commit 73f9328f12a4f3c41c138e77ad2e92a588f1ca59. Highlighting table rows which do not contain a link does not make sense. refs #8024 --- public/css/icinga/monitoring-colors.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less index 86268d2ce..1e657101f 100644 --- a/public/css/icinga/monitoring-colors.less +++ b/public/css/icinga/monitoring-colors.less @@ -195,7 +195,7 @@ tr.state.handled td.state { } /* HOVER colors */ -tr.state:hover, tr[href]:hover { +tr[href]:hover { color: black; background-color: #eee; } From e376bd628578f816644eac5f2ae417f1f4cc76ef Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 17:54:09 +0100 Subject: [PATCH 093/106] monitoring: Fix that exporting a object's history throws an exception fixes #6586 --- modules/monitoring/application/controllers/ShowController.php | 3 +-- .../monitoring/library/Monitoring/Object/MonitoredObject.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php index efec6665a..ba865deaa 100644 --- a/modules/monitoring/application/controllers/ShowController.php +++ b/modules/monitoring/application/controllers/ShowController.php @@ -73,9 +73,8 @@ class Monitoring_ShowController extends Controller public function historyAction() { $this->getTabs()->activate('history'); - //$this->view->object->populate(); $this->view->object->fetchEventHistory(); - $this->view->history = $this->view->object->eventhistory->paginate($this->params->get('limit', 50)); + $this->view->history = $this->view->object->eventhistory->getQuery()->paginate($this->params->get('limit', 50)); $this->handleFormatRequest($this->view->object->eventhistory); $this->fetchHostStats(); } diff --git a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php index 4be004d99..2d9f1f30c 100644 --- a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php +++ b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php @@ -421,7 +421,7 @@ abstract class MonitoredObject if ($this->type === self::TYPE_SERVICE) { $eventHistory->where('service_description', $this->service_description); } - $this->eventhistory = $eventHistory->getQuery(); + $this->eventhistory = $eventHistory; return $this; } From 3bd24c48ff453f2e47b0be154e9f7214b0ccc079 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 17:54:39 +0100 Subject: [PATCH 094/106] monitoring: Do not provide export when viewing a monitored object This is simply not possible at the moment. --- .../Monitoring/Web/Controller/MonitoredObjectController.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php b/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php index 7ee73d575..94dbe3f10 100644 --- a/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php +++ b/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php @@ -223,8 +223,6 @@ abstract class MonitoredObjectController extends Controller ) ); } - $tabs - ->extend(new OutputFormat()) - ->extend(new DashboardAction()); + $tabs->extend(new DashboardAction()); } } From fc05f4d53e50e7f02e0fcfc9ff0c2bd7f650dc74 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 29 Dec 2014 17:55:34 +0100 Subject: [PATCH 095/106] setup: Fix the mode of created directories --- modules/setup/library/Setup/WebWizard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php index e4d61dfd7..102c2c6a0 100644 --- a/modules/setup/library/Setup/WebWizard.php +++ b/modules/setup/library/Setup/WebWizard.php @@ -352,7 +352,7 @@ class WebWizard extends Wizard implements SetupWizard $configDir . '/preferences', $configDir . '/enabledModules' ), - 0775 + 2770 ) ); From 58cfb679830cdbcf32ecda8e7e30df5ff65b5988 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:27:18 +0100 Subject: [PATCH 096/106] Load setup module when necessary when bootstrapping the CLI fixes #8146 --- library/Icinga/Application/Cli.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/Icinga/Application/Cli.php b/library/Icinga/Application/Cli.php index 7d1a98eec..6341d561e 100644 --- a/library/Icinga/Application/Cli.php +++ b/library/Icinga/Application/Cli.php @@ -43,7 +43,8 @@ class Cli extends ApplicationBootstrap ->parseBasicParams() ->setupLogger() ->setupResourceFactory() - ->setupModuleManager(); + ->setupModuleManager() + ->loadSetupModuleIfNecessary(); } protected function setupLogging() From c1aff80f7b31b319e93665fcaf7bf4ba6d0683af Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:39:11 +0100 Subject: [PATCH 097/106] monitoring: Fix "Show resource configuration" link --- .../monitoring/application/forms/Config/BackendConfigForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 4b1aa65b6..c60848858 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -253,7 +253,7 @@ class BackendConfigForm extends ConfigForm array( 'value' => sprintf( '%s', - $this->getView()->href('/icingaweb/config/editresource', array('resource' => $resourceName)), + $this->getView()->url('config/editresource', array('resource' => $resourceName)), mt('monitoring', 'Show resource configuration') ), 'escape' => false From d595541d42425e3f793381fc27998bb05155b907 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:40:09 +0100 Subject: [PATCH 098/106] monitoring: optimize imports in the backend configuration form --- .../monitoring/application/forms/Config/BackendConfigForm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index c60848858..3953830fd 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -5,10 +5,10 @@ namespace Icinga\Module\Monitoring\Forms\Config; use InvalidArgumentException; -use Icinga\Web\Notification; -use Icinga\Forms\ConfigForm; use Icinga\Application\Config; use Icinga\Exception\ConfigurationError; +use Icinga\Forms\ConfigForm; +use Icinga\Web\Notification; /** * Form class for creating/modifying monitoring backends From 2a1f12354e19f723d7b309d7f298679b1bbe52d4 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:41:22 +0100 Subject: [PATCH 099/106] monitoring: Use '@return $this' when documenting fluent interfaces in the backend configuration form --- .../monitoring/application/forms/Config/BackendConfigForm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 3953830fd..c25c73544 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -36,7 +36,7 @@ class BackendConfigForm extends ConfigForm * * @param Config $resources The resource configuration * - * @return self + * @return $this * * @throws ConfigurationError In case there are no valid monitoring backend resources */ @@ -64,7 +64,7 @@ class BackendConfigForm extends ConfigForm * * @param array $values The values to extend the configuration with * - * @return self + * @return $this * * @throws InvalidArgumentException In case the backend does already exist */ From 6a67b7fee39928dc81d87db1ff756b58ba7c2a68 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:43:35 +0100 Subject: [PATCH 100/106] monitoring: add description to @see tags in the backend configuration form --- .../application/forms/Config/BackendConfigForm.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index c25c73544..54bd8371c 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -160,9 +160,7 @@ class BackendConfigForm extends ConfigForm /** * Populate the form in case a monitoring backend is being edited * - * @see Form::onRequest() - * - * @throws ConfigurationError In case the backend name is missing in the request or is invalid + * @throws ConfigurationError In case the backend name is missing in the request or is invalid */ public function onRequest() { @@ -181,7 +179,8 @@ class BackendConfigForm extends ConfigForm } /** - * @see Form::createElements() + * (non-PHPDoc) + * @see Form::createElements() For the method documentation. */ public function createElements(array $formData) { From 27110ce5943e357d11bcdb9de73c8e9e861bdbfb Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:44:33 +0100 Subject: [PATCH 101/106] monitoring: use @type instead of @var in the backend configuration form --- .../monitoring/application/forms/Config/BackendConfigForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 54bd8371c..80afbc653 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -18,7 +18,7 @@ class BackendConfigForm extends ConfigForm /** * The available monitoring backend resources split by type * - * @var array + * @type array */ protected $resources; From 24b2369adba047d49568f15c678946404e878e45 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:45:24 +0100 Subject: [PATCH 102/106] monitoring: Fix PHPDoc of BackendConfigForm::setResourceConfig() --- .../monitoring/application/forms/Config/BackendConfigForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 80afbc653..67672dd20 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -34,7 +34,7 @@ class BackendConfigForm extends ConfigForm /** * Set the resource configuration to use * - * @param Config $resources The resource configuration + * @param Config $resourceConfig The resource configuration * * @return $this * From e72361c2cba622da5f441a04b20528dbbe6c52ca Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:47:19 +0100 Subject: [PATCH 103/106] monitoring: Fix missing return argument in the backend configuration form --- .../monitoring/application/forms/Config/BackendConfigForm.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 67672dd20..51d5b5542 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -147,7 +147,7 @@ class BackendConfigForm extends ConfigForm } } catch (InvalidArgumentException $e) { Notification::error($e->getMessage()); - return; + return null; } if ($this->save()) { From e05e04bb744a803c0f6802bf1e70699920fce564 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 09:47:45 +0100 Subject: [PATCH 104/106] monitoring: Uppercasse the first word of comments in the backend configuration form --- .../monitoring/application/forms/Config/BackendConfigForm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 51d5b5542..3ad18c830 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -138,10 +138,10 @@ class BackendConfigForm extends ConfigForm { $monitoringBackend = $this->request->getQuery('backend'); try { - if ($monitoringBackend === null) { // create new backend + if ($monitoringBackend === null) { // Create new backend $this->add($this->getValues()); $message = mt('monitoring', 'Monitoring backend "%s" has been successfully created'); - } else { // edit existing backend + } else { // Edit existing backend $this->edit($monitoringBackend, $this->getValues()); $message = mt('monitoring', 'Monitoring backend "%s" has been successfully changed'); } From d6e331018bb36e7562b870c4fd27f950dfd53d97 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 10:02:31 +0100 Subject: [PATCH 105/106] monitoring: Use Form::translate() in the backend configuration form refs #7551 --- .../forms/Config/BackendConfigForm.php | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 3ad18c830..ca45c068b 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -28,7 +28,7 @@ class BackendConfigForm extends ConfigForm public function init() { $this->setName('form_config_monitoring_backends'); - $this->setSubmitLabel(mt('monitoring', 'Save Changes')); + $this->setSubmitLabel($this->translate('Save Changes')); } /** @@ -50,7 +50,7 @@ class BackendConfigForm extends ConfigForm } if (empty($resources)) { - throw new ConfigurationError(mt('monitoring', 'Could not find any valid monitoring backend resources')); + throw new ConfigurationError($this->translate('Could not find any valid monitoring backend resources')); } $this->resources = $resources; @@ -72,9 +72,9 @@ class BackendConfigForm extends ConfigForm { $name = isset($values['name']) ? $values['name'] : ''; if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('Monitoring backend name missing')); } elseif ($this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend already exists')); + throw new InvalidArgumentException($this->translate('Monitoring backend already exists')); } unset($values['name']); @@ -95,11 +95,11 @@ class BackendConfigForm extends ConfigForm public function edit($name, array $values) { if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Old monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('Old monitoring backend name missing')); } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) { - throw new InvalidArgumentException(mt('monitoring', 'New monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('New monitoring backend name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Unknown monitoring backend provided')); + throw new InvalidArgumentException($this->translate('Unknown monitoring backend provided')); } unset($values['name']); @@ -119,9 +119,9 @@ class BackendConfigForm extends ConfigForm public function remove($name) { if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('Monitoring backend name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Unknown monitoring backend provided')); + throw new InvalidArgumentException($this->translate('Unknown monitoring backend provided')); } $backendConfig = $this->config->getSection($name); @@ -131,8 +131,6 @@ class BackendConfigForm extends ConfigForm /** * Add or edit a monitoring backend and save the configuration - * - * @see Form::onSuccess() */ public function onSuccess() { @@ -140,10 +138,10 @@ class BackendConfigForm extends ConfigForm try { if ($monitoringBackend === null) { // Create new backend $this->add($this->getValues()); - $message = mt('monitoring', 'Monitoring backend "%s" has been successfully created'); + $message = $this->translate('Monitoring backend "%s" has been successfully created'); } else { // Edit existing backend $this->edit($monitoringBackend, $this->getValues()); - $message = mt('monitoring', 'Monitoring backend "%s" has been successfully changed'); + $message = $this->translate('Monitoring backend "%s" has been successfully changed'); } } catch (InvalidArgumentException $e) { Notification::error($e->getMessage()); @@ -167,9 +165,9 @@ class BackendConfigForm extends ConfigForm $monitoringBackend = $this->request->getQuery('backend'); if ($monitoringBackend !== null) { if ($monitoringBackend === '') { - throw new ConfigurationError(mt('monitoring', 'Monitoring backend name missing')); + throw new ConfigurationError($this->translate('Monitoring backend name missing')); } elseif (! $this->config->hasSection($monitoringBackend)) { - throw new ConfigurationError(mt('monitoring', 'Unknown monitoring backend provided')); + throw new ConfigurationError($this->translate('Unknown monitoring backend provided')); } $backendConfig = $this->config->getSection($monitoringBackend)->toArray(); @@ -199,7 +197,7 @@ class BackendConfigForm extends ConfigForm 'disabled', array( 'required' => true, - 'label' => mt('monitoring', 'Disable This Backend') + 'label' => $this->translate('Disable This Backend') ) ); $this->addElement( @@ -207,8 +205,8 @@ class BackendConfigForm extends ConfigForm 'name', array( 'required' => true, - 'label' => mt('monitoring', 'Backend Name'), - 'description' => mt('monitoring', 'The identifier of this backend') + 'label' => $this->translate('Backend Name'), + 'description' => $this->translate('The identifier of this backend') ) ); $this->addElement( @@ -217,8 +215,8 @@ class BackendConfigForm extends ConfigForm array( 'required' => true, 'autosubmit' => true, - 'label' => mt('monitoring', 'Backend Type'), - 'description' => mt('monitoring', 'The data source used for retrieving monitoring information'), + 'label' => $this->translate('Backend Type'), + 'description' => $this->translate('The data source used for retrieving monitoring information'), 'multiOptions' => $resourceTypes, 'value' => $resourceType ) @@ -229,8 +227,8 @@ class BackendConfigForm extends ConfigForm 'resource', array( 'required' => true, - 'label' => mt('monitoring', 'Resource'), - 'description' => mt('monitoring', 'The resource to use'), + 'label' => $this->translate('Resource'), + 'description' => $this->translate('The resource to use'), 'multiOptions' => $this->resources[$resourceType], 'autosubmit' => true ) @@ -253,7 +251,7 @@ class BackendConfigForm extends ConfigForm 'value' => sprintf( '%s', $this->getView()->url('config/editresource', array('resource' => $resourceName)), - mt('monitoring', 'Show resource configuration') + $this->translate('Show resource configuration') ), 'escape' => false ) From 50bbf77d0c499afa015b4a6317be3ce69bf01400 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 30 Dec 2014 10:08:33 +0100 Subject: [PATCH 106/106] Fix module domain detection in Form::getTranslationDomain() The usage of preg_replace had two errors: 1) The regular expression was wrong 2) $matches[0] always contains the full matched string, not the first parenthesized subpattern The correct version of preg_replace would've been: if (preg_match('/^Icinga\\\\Module\\\\([A-Za-z]+)\\\\/', get_called_class(), $matches) === 1) { return strtolower($matches[1]); } But since there's no benefit of using a regular expression here except less speed, I replaced it with using explode. refs #7551 --- library/Icinga/Web/Form.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 850285baa..64712961f 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -806,19 +806,20 @@ class Form extends Zend_Form } /** - * Return the translation domain for this form + * Get the translation domain for this form * - * The returned translation domain is either determined based on - * this form's class path or it is the default `icinga' domain + * The returned translation domain is either determined based on this form's qualified name or it is the default + * 'icinga' domain * - * @return string + * @return string */ protected function getTranslationDomain() { - if (preg_match('@^Icinga\\\\Module\\\\([A-z]+)\\\\.*$@', get_called_class(), $matches) === 1) { - return strtolower($matches[0]); + $parts = explode('\\', get_called_class()); + if ($parts[1] === 'Module') { + // Assume format Icinga\Module\ModuleName\Forms\... + return strtolower($parts[2]); } - return 'icinga'; }