From 6ff5a986dd9818b6ecb81786abe01d29beb28ef3 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 26 May 2014 13:08:47 +0200 Subject: [PATCH 01/96] Modules: Don't call `FrontController::getRoute()' twice refs #6303 --- library/Icinga/Application/Modules/Module.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/Icinga/Application/Modules/Module.php b/library/Icinga/Application/Modules/Module.php index c765ca380..e9a8ab583 100644 --- a/library/Icinga/Application/Modules/Module.php +++ b/library/Icinga/Application/Modules/Module.php @@ -600,18 +600,19 @@ class Module */ protected function registerRoutes() { - $this->app->getFrontController()->getRouter()->addRoute( + $router = $this->app->getFrontController()->getRouter(); + $router->addRoute( $this->name . '_jsprovider', new Route( 'js/' . $this->name . '/:file', array( 'controller' => 'static', 'action' =>'javascript', - 'module_name' => $this->name + 'module_name' => $this->name ) ) ); - $this->app->getFrontController()->getRouter()->addRoute( + $router->addRoute( $this->name . '_img', new Route( 'img/' . $this->name . '/:file', From a91961284dd580e283cd1dc7bfa4b0b7e17228fc Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 09:26:53 +0200 Subject: [PATCH 02/96] modules/doc: Show nothing on index yet Before, doc's IndexController::indexAction() showed the documentation of Icinga Web 2 but index should rather show an overview of available docs. refs #4820 --- .../controllers/IndexController.php | 26 +------------------ .../views/scripts/index/index.phtml | 5 ---- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/modules/doc/application/controllers/IndexController.php b/modules/doc/application/controllers/IndexController.php index 299ae5c65..1911f0534 100644 --- a/modules/doc/application/controllers/IndexController.php +++ b/modules/doc/application/controllers/IndexController.php @@ -1,37 +1,13 @@ parser = new DocParser($module); - } - - - public function tocAction() - { - // Temporary workaround - list($html, $toc) = $this->parser->getDocumentation(); - $this->view->toc = $toc; - } - - /** - * Display the application's documentation - */ public function indexAction() { - $this->populateView(); + } } -// @codingStandardsIgnoreEnd diff --git a/modules/doc/application/views/scripts/index/index.phtml b/modules/doc/application/views/scripts/index/index.phtml index a178cc155..e69de29bb 100644 --- a/modules/doc/application/views/scripts/index/index.phtml +++ b/modules/doc/application/views/scripts/index/index.phtml @@ -1,5 +0,0 @@ -

Icinga 2 Documentation

-partial('module/view.phtml', 'doc', array( - 'toc' => $toc, - 'html' => $html -)); ?> \ No newline at end of file From 83c12cfb2ef5c29158c885d5f493dddb0394b2a8 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 09:35:02 +0200 Subject: [PATCH 03/96] modules/doc: Add partial for displaying doc and toc refs #4820 --- .../views/scripts/partials/docandtoc.phtml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 modules/doc/application/views/scripts/partials/docandtoc.phtml diff --git a/modules/doc/application/views/scripts/partials/docandtoc.phtml b/modules/doc/application/views/scripts/partials/docandtoc.phtml new file mode 100644 index 000000000..704e5ef88 --- /dev/null +++ b/modules/doc/application/views/scripts/partials/docandtoc.phtml @@ -0,0 +1,19 @@ + +

No documentation available.

+ +
+ partial( + 'layout/menu.phtml', + 'default', + array( + 'items' => $docToc->getChildren(), + 'sub' => false, + 'url' => '' + ) + ); + ?> +
+
+ +
+ From e6abe21fb8bb2ec444e9432a012abfbf3a9af457 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 09:36:14 +0200 Subject: [PATCH 04/96] modules/doc: Rename DocParser::getDocumentation() to getDocAndToc() refs #4820 --- modules/doc/library/Doc/Controller.php | 14 +++++++------- modules/doc/library/Doc/DocParser.php | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/doc/library/Doc/Controller.php b/modules/doc/library/Doc/Controller.php index 3f7b1da4e..840011150 100644 --- a/modules/doc/library/Doc/Controller.php +++ b/modules/doc/library/Doc/Controller.php @@ -9,15 +9,15 @@ use Icinga\Web\Controller\ActionController; class Controller extends ActionController { /** - * Set HTML and toc + * Publish doc HTML and toc to the view * - * @param string $module + * @param string $module Name of the module for which to populate doc and toc. `null` for Icinga Web 2's doc */ protected function populateView($module = null) { - $parser = new DocParser($module); - list($html, $toc) = $parser->getDocumentation(); - $this->view->html = $html; - $this->view->toc = $toc; + $parser = new DocParser($module); + list($docHtml, $docToc) = $parser->getDocAndToc(); + $this->view->docHtml = $docHtml; + $this->view->docToc = $docToc; } -} \ No newline at end of file +} diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 945a96eea..ac3c58ea6 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -4,6 +4,8 @@ namespace Icinga\Module\Doc; +require_once 'vendor/Parsedown/Parsedown.php'; + use RecursiveIteratorIterator; use RecursiveDirectoryIterator; use Parsedown; @@ -11,8 +13,6 @@ use Icinga\Application\Icinga; use Icinga\Web\Menu; use Icinga\Web\Url; -require_once 'vendor/Parsedown/Parsedown.php'; - /** * Parser for documentation written in Markdown */ @@ -51,12 +51,12 @@ class DocParser } /** - * Retrieve table of contents and HTML converted from markdown files sorted by filename + * Retrieve doc as HTML converted from markdown files sorted by filename and the table of contents * * @return array * @throws DocException */ - public function getDocumentation() + public function getDocAndToc() { $iter = new RecursiveIteratorIterator( new MarkdownFileIterator( From ce37c20736b10309353a284d62c5bfc09206213b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 09:40:00 +0200 Subject: [PATCH 05/96] modules/doc: Add route 'modules/doc/icingaweb' to display Icinga Web 2's documentation refs #4820 --- .../application/controllers/IcingawebController.php | 13 +++++++++++++ .../application/views/scripts/icingaweb/index.phtml | 9 +++++++++ 2 files changed, 22 insertions(+) create mode 100644 modules/doc/application/controllers/IcingawebController.php create mode 100644 modules/doc/application/views/scripts/icingaweb/index.phtml diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php new file mode 100644 index 000000000..209e751f4 --- /dev/null +++ b/modules/doc/application/controllers/IcingawebController.php @@ -0,0 +1,13 @@ +populateView(); + } +} diff --git a/modules/doc/application/views/scripts/icingaweb/index.phtml b/modules/doc/application/views/scripts/icingaweb/index.phtml new file mode 100644 index 000000000..ae6573b2b --- /dev/null +++ b/modules/doc/application/views/scripts/icingaweb/index.phtml @@ -0,0 +1,9 @@ +

Icinga Web 2 Documentation

+partial( + 'partials/docandtoc.phtml', + 'doc', + array( + 'docToc' => $docToc, + 'docHtml' => $docHtml + ) +); ?> From 99971e241c22f5a6c5d3a9665c5f310a2ad65422 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:03:18 +0200 Subject: [PATCH 06/96] modules/doc: Replace Parsedown's decprecated method parse() with text() refs #4820 --- 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 ac3c58ea6..f098d6907 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -125,7 +125,7 @@ class DocParser } $fileObject->flock(LOCK_UN); } - $html = Parsedown::instance()->parse(implode('', $cat)); + $html = Parsedown::instance()->text(implode('', $cat)); $html = preg_replace_callback( '#
(.*?)\
#s', array($this, 'highlight'), From 74ea4d19b829738f66f6778536532257b44069c8 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:04:36 +0200 Subject: [PATCH 07/96] modules/doc: Rename populateView() to renderDocAndToc() Rename populateView() to renderDocAndToc() since the method now sets the viewHelper to docandtoc.phtml refs #4820 --- .../views/scripts/partials/docandtoc.phtml | 33 ++++++++++--------- modules/doc/library/Doc/Controller.php | 4 ++- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/modules/doc/application/views/scripts/partials/docandtoc.phtml b/modules/doc/application/views/scripts/partials/docandtoc.phtml index 704e5ef88..46f7b0bfe 100644 --- a/modules/doc/application/views/scripts/partials/docandtoc.phtml +++ b/modules/doc/application/views/scripts/partials/docandtoc.phtml @@ -1,19 +1,20 @@ +

documentation

-

No documentation available.

+

Documentation not available.

-
- partial( - 'layout/menu.phtml', - 'default', - array( - 'items' => $docToc->getChildren(), - 'sub' => false, - 'url' => '' - ) - ); - ?> -
-
- -
+
+partial( + 'layout/menu.phtml', + 'default', + array( + 'items' => $docToc->getChildren(), + 'sub' => false, + 'url' => '' + ) + ); +?> +
+
+ +
diff --git a/modules/doc/library/Doc/Controller.php b/modules/doc/library/Doc/Controller.php index 840011150..ae5bc177f 100644 --- a/modules/doc/library/Doc/Controller.php +++ b/modules/doc/library/Doc/Controller.php @@ -13,11 +13,13 @@ class Controller extends ActionController * * @param string $module Name of the module for which to populate doc and toc. `null` for Icinga Web 2's doc */ - protected function populateView($module = null) + protected function renderDocAndToc($module = null) { $parser = new DocParser($module); list($docHtml, $docToc) = $parser->getDocAndToc(); $this->view->docHtml = $docHtml; $this->view->docToc = $docToc; + $this->view->docName = $module === null ? 'Icinga Web 2' : ucfirst($module); + $this->_helper->viewRenderer('partials/docandtoc', null, true); } } From 40c2c64985be040976c27ca169ec0ca9174db63d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:06:28 +0200 Subject: [PATCH 08/96] modules/doc: Implement doc/module/$moduleName URLs refs #4820 --- .../controllers/ModuleController.php | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index 5e3636f92..5c7851542 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -1,5 +1,4 @@ view->enabledModules = Icinga::app()->getModuleManager()->listEnabledModules(); } - /** - * Display a module's documentation - */ - public function viewAction() - { - $this->populateView($this->getParam('name')); - } - /** * Provide run-time dispatching of module documentation * - * @param string $methodName - * @param array $args + * @param string $methodName + * @param array $args * * @return mixed */ public function __call($methodName, $args) { - // TODO(el): Setup routing to retrieve module name as param and point route to moduleAction - $moduleManager = Icinga::app()->getModuleManager(); - $moduleName = substr($methodName, 0, -6); // Strip 'Action' suffix - if (!$moduleManager->hasEnabled($moduleName)) { - // TODO(el): Throw a not found exception once the code has been moved to the moduleAction (see TODO above) + $moduleManager = Icinga::app()->getModuleManager(); + $moduleName = substr($methodName, 0, -6); // Strip 'Action' suffix + if (! $moduleManager->hasEnabled($moduleName)) { + // TODO(el): Distinguish between not enabled and not installed return parent::__call($methodName, $args); } - $this->_helper->redirector->gotoSimpleAndExit('view', null, null, array('name' => $moduleName)); + $this->renderDocAndToc($moduleName); } } -// @codingStandardsIgnoreEnd From ba860edb75f76b42bb16e5975783b20d17d8e86c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:07:09 +0200 Subject: [PATCH 09/96] modules/doc: Remove icingaweb/index.phtml since it's replaced by renderDocAndToc() refs #4820 --- .../doc/application/controllers/IcingawebController.php | 2 +- .../doc/application/views/scripts/icingaweb/index.phtml | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 modules/doc/application/views/scripts/icingaweb/index.phtml diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index 209e751f4..90b1e23f4 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -8,6 +8,6 @@ class Doc_IcingawebController extends DocController { public function indexAction() { - $this->populateView(); + $this->renderDocAndToc(); } } diff --git a/modules/doc/application/views/scripts/icingaweb/index.phtml b/modules/doc/application/views/scripts/icingaweb/index.phtml deleted file mode 100644 index ae6573b2b..000000000 --- a/modules/doc/application/views/scripts/icingaweb/index.phtml +++ /dev/null @@ -1,9 +0,0 @@ -

Icinga Web 2 Documentation

-partial( - 'partials/docandtoc.phtml', - 'doc', - array( - 'docToc' => $docToc, - 'docHtml' => $docHtml - ) -); ?> From 4001f1de62fb6bf0dc8d1e5df03c83ea350dedac Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:09:50 +0200 Subject: [PATCH 10/96] modules/doc: Remove module/view.phtml as it has been replaced by renderDocAndToc() refs #4820 --- modules/doc/application/views/scripts/module/view.phtml | 7 ------- modules/doc/library/Doc/DocException.php | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 modules/doc/application/views/scripts/module/view.phtml diff --git a/modules/doc/application/views/scripts/module/view.phtml b/modules/doc/application/views/scripts/module/view.phtml deleted file mode 100644 index 291947ad7..000000000 --- a/modules/doc/application/views/scripts/module/view.phtml +++ /dev/null @@ -1,7 +0,0 @@ - -

No documentation available.

- -
- -
- diff --git a/modules/doc/library/Doc/DocException.php b/modules/doc/library/Doc/DocException.php index cb7134045..795c9a5f9 100644 --- a/modules/doc/library/Doc/DocException.php +++ b/modules/doc/library/Doc/DocException.php @@ -4,7 +4,7 @@ namespace Icinga\Module\Doc; -use \Exception; +use Exception; class DocException extends Exception { From a40f34394b7e17914937640f43653cf467633f5b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:11:03 +0200 Subject: [PATCH 11/96] modules/doc: List available documentations on index refs #4820 --- modules/doc/application/views/scripts/index/index.phtml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/doc/application/views/scripts/index/index.phtml b/modules/doc/application/views/scripts/index/index.phtml index e69de29bb..9edb5910d 100644 --- a/modules/doc/application/views/scripts/index/index.phtml +++ b/modules/doc/application/views/scripts/index/index.phtml @@ -0,0 +1,5 @@ +

Available documentations

+ From 5627c09b3771857bb3fe97cf4a8e07fec58de79b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:11:28 +0200 Subject: [PATCH 12/96] modules/doc: Reduce tab size to two spaces in module/index.phtml refs #4820 --- modules/doc/application/views/scripts/module/index.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/application/views/scripts/module/index.phtml b/modules/doc/application/views/scripts/module/index.phtml index 36f11e15e..5e9eaae9d 100644 --- a/modules/doc/application/views/scripts/module/index.phtml +++ b/modules/doc/application/views/scripts/module/index.phtml @@ -1,6 +1,6 @@

Module documentations

    -
  • +
From 89bddb10e7cfe90fed4426228e9837d058cf8d16 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:16:58 +0200 Subject: [PATCH 13/96] modules/doc: Tell which doc directory does not exist, in case it does not exist :) Thanks Michael refs #4820 --- modules/doc/library/Doc/DocParser.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index f098d6907..39f8c8718 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -35,16 +35,16 @@ class DocParser $dir = Icinga::app()->getApplicationDir('/../doc'); } else { $mm = Icinga::app()->getModuleManager(); - if (!$mm->hasInstalled($module)) { + if (! $mm->hasInstalled($module)) { throw new DocException('Module is not installed'); } - if (!$mm->hasEnabled($module)) { + if (! $mm->hasEnabled($module)) { throw new DocException('Module is not enabled'); } $dir = $mm->getModuleDir($module, '/doc'); } - if (!is_dir($dir)) { - throw new DocException('Doc directory does not exist'); + if (! is_dir($dir)) { + throw new DocException('Doc directory `' . $dir .'\' does not exist'); } $this->dir = $dir; $this->module = $module; @@ -81,7 +81,7 @@ class DocParser throw new DocException('Couldn\'t get the lock'); } $line = null; - while (!$fileObject->eof()) { + while (! $fileObject->eof()) { // Save last line for setext-style headers $lastLine = $line; $line = $fileObject->fgets(); @@ -156,7 +156,7 @@ class DocParser */ protected function extractHeader($line, $lastLine) { - if (!$line) { + if (! $line) { return null; } $header = null; @@ -167,7 +167,7 @@ class DocParser // Atx-style $level = strlen($match[0]); $header = trim(substr($line, $level)); - if (!$header) { + if (! $header) { return null; } } elseif ( @@ -177,7 +177,7 @@ class DocParser ) { // Setext $header = trim($lastLine); - if (!$header) { + if (! $header) { return null; } if ($match[0][0] === '=') { From 1d5c4c50554f24ac81ada45c20d1e61de6089730 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:17:37 +0200 Subject: [PATCH 14/96] modules/doc: Add styles refs #4820 --- modules/doc/public/css/module.less | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 modules/doc/public/css/module.less diff --git a/modules/doc/public/css/module.less b/modules/doc/public/css/module.less new file mode 100644 index 000000000..45d97e5c6 --- /dev/null +++ b/modules/doc/public/css/module.less @@ -0,0 +1,9 @@ +.toc { + float: left; + width: 33.333% +} + +.doc { + float: left; + width: 66.667% +} From 5923622fb8b80089fbc00189da4be84ebf8b4db4 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 23 May 2014 14:22:35 +0200 Subject: [PATCH 15/96] modules/doc: Fix toc links The DocParser generates toc links with a hard-coded URL. This should be changed to be generated from a route. But we did not decide how to handle route overrides yet. refs #4820 --- modules/doc/library/Doc/DocParser.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 39f8c8718..04086469b 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -104,14 +104,13 @@ class DocParser $item = end($toc)->item->addChild( $id, array( + // TODO(el): URL should be generated from a route else we always have to adapt the + // URL here when we change URLs 'url' => Url::fromPath( - 'doc/module/view', - array( - 'name' => $this->module - ) + $this->module === null ? 'doc/icingaweb' : 'doc/module/' . $this->module )->setAnchor($id)->getRelativeUrl(), 'title' => htmlspecialchars($header), - 'priority' => $itemPriority++, + 'priority' => $itemPriority++, // Post-increment is on purpose 'attribs' => $attribs ) ); From b58ec5f445afd020c57a90c07634eb18bf9a2ec2 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 26 May 2014 13:33:32 +0200 Subject: [PATCH 16/96] Add Module::addRoute() to add a route to the route chain refs #6303 --- library/Icinga/Application/Modules/Module.php | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Application/Modules/Module.php b/library/Icinga/Application/Modules/Module.php index e9a8ab583..9d3fb3dee 100644 --- a/library/Icinga/Application/Modules/Module.php +++ b/library/Icinga/Application/Modules/Module.php @@ -30,6 +30,7 @@ namespace Icinga\Application\Modules; use Exception; +use Zend_Controller_Router_Route_Abstract; use Zend_Controller_Router_Route as Route; use Icinga\Application\ApplicationBootstrap; use Icinga\Application\Config; @@ -150,6 +151,16 @@ class Module */ private $app; + + /** + * Routes to add to the route chain + * + * @var array Array of name-route pairs + * + * @see addRoute() + */ + protected $routes = array(); + /** * Create a new module object * @@ -594,13 +605,17 @@ class Module } /** - * Register routes for web access + * Add routes for static content and any route added via addRoute() to the route chain * - * @return self + * @return self + * @see addRoute() */ protected function registerRoutes() { $router = $this->app->getFrontController()->getRouter(); + foreach ($this->routes as $name => $route) { + $router->addRoute($name, $route); + } $router->addRoute( $this->name . '_jsprovider', new Route( @@ -687,4 +702,19 @@ class Module return $this; } + + /** + * Add a route which will be added to the route chain + * + * @param string $name Name of the route + * @param Zend_Controller_Router_Route_Abstract $route Instance of the route + * + * @return self + * @see registerRoutes() + */ + protected function addRoute($name, Zend_Controller_Router_Route_Abstract $route) + { + $this->routes[$name] = $route; + return $this; + } } From 6ce739e23d4e1c01249e803cf80357bf44cfc037 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 14:31:17 +0200 Subject: [PATCH 17/96] Doc: Construct parser with the path to the documentation Before, the parser decided which path to used based on a given module name. Now, the parser requires the path to the documentation. Further the toc items no longer include a URL. The must URL must be generated from a render function or view script. refs #4820 --- modules/doc/library/Doc/DocParser.php | 54 +++++++++++---------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 04086469b..fc87faf27 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -9,7 +9,7 @@ require_once 'vendor/Parsedown/Parsedown.php'; use RecursiveIteratorIterator; use RecursiveDirectoryIterator; use Parsedown; -use Icinga\Application\Icinga; +use Icinga\Exception\NotReadableError; use Icinga\Web\Menu; use Icinga\Web\Url; @@ -18,36 +18,30 @@ use Icinga\Web\Url; */ class DocParser { - protected $dir; - - protected $module; + /** + * Path to the documentation + * + * @var string + */ + protected $path; /** - * Create a new documentation parser for the given module or the application + * Create a new documentation parser for the given path * - * @param string $module + * @param string $path Path to the documentation * * @throws DocException + * @throws NotReadableError */ - public function __construct($module = null) + public function __construct($path) { - if ($module === null) { - $dir = Icinga::app()->getApplicationDir('/../doc'); - } else { - $mm = Icinga::app()->getModuleManager(); - if (! $mm->hasInstalled($module)) { - throw new DocException('Module is not installed'); - } - if (! $mm->hasEnabled($module)) { - throw new DocException('Module is not enabled'); - } - $dir = $mm->getModuleDir($module, '/doc'); + if (! is_dir($path)) { + throw new DocException('Doc directory `' . $path .'\' does not exist'); } - if (! is_dir($dir)) { - throw new DocException('Doc directory `' . $dir .'\' does not exist'); + if (! is_readable($path)) { + throw new NotReadableError('Doc directory `' . $path .'\' is not readable'); } - $this->dir = $dir; - $this->module = $module; + $this->path = $path; } /** @@ -60,7 +54,7 @@ class DocParser { $iter = new RecursiveIteratorIterator( new MarkdownFileIterator( - new RecursiveDirectoryIterator($this->dir) + new RecursiveDirectoryIterator($this->path) ) ); $fileInfos = iterator_to_array($iter); @@ -89,7 +83,7 @@ class DocParser if ($header !== null) { list($header, $level) = $header; $id = $this->extractHeaderId($header); - $attribs = array(); + $nofollow = false; $this->reduceToc($toc, $level); if ($id === null) { $path = array(); @@ -98,20 +92,16 @@ class DocParser } $path[] = $header; $id = implode('-', $path); - $attribs['rel'] = 'nofollow'; + $nofollow = true; } $id = urlencode(str_replace('.', '.', strip_tags($id))); $item = end($toc)->item->addChild( $id, array( - // TODO(el): URL should be generated from a route else we always have to adapt the - // URL here when we change URLs - 'url' => Url::fromPath( - $this->module === null ? 'doc/icingaweb' : 'doc/module/' . $this->module - )->setAnchor($id)->getRelativeUrl(), - 'title' => htmlspecialchars($header), + 'id' => $id, + 'title' => $header, 'priority' => $itemPriority++, // Post-increment is on purpose - 'attribs' => $attribs + 'nofollow' => $nofollow ) ); $toc[] = ((object) array( From 71615151a4a20ba8098d857fe3ed5ebaf9fcd112 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 14:48:35 +0200 Subject: [PATCH 18/96] Doc: Rename `Controller' to `DocController' refs #4820 --- modules/doc/library/Doc/{Controller.php => DocController.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename modules/doc/library/Doc/{Controller.php => DocController.php} (94%) diff --git a/modules/doc/library/Doc/Controller.php b/modules/doc/library/Doc/DocController.php similarity index 94% rename from modules/doc/library/Doc/Controller.php rename to modules/doc/library/Doc/DocController.php index ae5bc177f..7a6b4f854 100644 --- a/modules/doc/library/Doc/Controller.php +++ b/modules/doc/library/Doc/DocController.php @@ -6,7 +6,7 @@ namespace Icinga\Module\Doc; use Icinga\Web\Controller\ActionController; -class Controller extends ActionController +class DocController extends ActionController { /** * Publish doc HTML and toc to the view From 884e4c8e946c40c5a3b0570ad64ab85e8101b790 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 14:49:32 +0200 Subject: [PATCH 19/96] Doc: Add `DocController::renderToc()' method refs #4820 --- modules/doc/library/Doc/DocController.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php index 7a6b4f854..967f7f070 100644 --- a/modules/doc/library/Doc/DocController.php +++ b/modules/doc/library/Doc/DocController.php @@ -22,4 +22,19 @@ class DocController extends ActionController $this->view->docName = $module === null ? 'Icinga Web 2' : ucfirst($module); $this->_helper->viewRenderer('partials/docandtoc', null, true); } + + /** + * Render a toc + * + * @param string $path Path to the documentation + * @param string + */ + protected function renderToc($path, $name) + { + $parser = new DocParser($path); + list($docHtml, $docToc) = $parser->getDocAndToc(); + $this->view->docToc = $docToc; + $this->view->docName = $name; + $this->_helper->viewRenderer('partials/toc', null, true); + } } From dd6427019a637f45cffc3dcf8e568e0c447d61e9 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 14:50:48 +0200 Subject: [PATCH 20/96] Doc: Add action to render the toc of Icinga Web 2's documentation refs #4820 --- .../application/controllers/IcingawebController.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index 90b1e23f4..f9e05cefd 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -2,12 +2,16 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -use Icinga\Module\Doc\Controller as DocController; +use Icinga\Application\Icinga; +use Icinga\Module\Doc\DocController; class Doc_IcingawebController extends DocController { - public function indexAction() + /** + * View toc of Icinga Web 2's documentation + */ + public function tocAction() { - $this->renderDocAndToc(); + $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2'); } } From 0f5e0767713f2c9db96d2ad1e13d34c625bcad54 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 14:53:25 +0200 Subject: [PATCH 21/96] Doc: Add action to view the toc of a module's documentation refs #4820 --- .../controllers/ModuleController.php | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index 5c7851542..cdeca3e50 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -2,8 +2,9 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} +use \Zend_Controller_Action_Exception; use Icinga\Application\Icinga; -use Icinga\Module\Doc\Controller as DocController; +use Icinga\Module\Doc\DocController; class Doc_ModuleController extends DocController { @@ -16,21 +17,34 @@ class Doc_ModuleController extends DocController } /** - * Provide run-time dispatching of module documentation + * Assert that the given module is enabled * - * @param string $methodName - * @param array $args + * @param $moduleName * - * @return mixed + * @throws Zend_Controller_Action_Exception */ - public function __call($methodName, $args) + protected function assertModuleEnabled($moduleName) { - $moduleManager = Icinga::app()->getModuleManager(); - $moduleName = substr($methodName, 0, -6); // Strip 'Action' suffix - if (! $moduleManager->hasEnabled($moduleName)) { - // TODO(el): Distinguish between not enabled and not installed - return parent::__call($methodName, $args); + if ($moduleName === null) { + throw new Zend_Controller_Action_Exception('Missing parameter "moduleName"', 404); } - $this->renderDocAndToc($moduleName); + $moduleManager = Icinga::app()->getModuleManager(); + if (! $moduleManager->hasInstalled($moduleName)) { + throw new Zend_Controller_Action_Exception('Module ' . $moduleName . ' is not installed', 404); + } + if (! $moduleManager->hasEnabled($moduleName)) { + throw new Zend_Controller_Action_Exception('Module ' . $moduleName. ' is not enabled', 404); + } + } + + /** + * View toc of a module's documentation + */ + public function tocAction() + { + $moduleName = $this->getParam('moduleName'); + $this->assertModuleEnabled($moduleName); + $moduleManager = Icinga::app()->getModuleManager(); + $this->renderToc($moduleManager->getModuleDir($moduleName, '/doc'), $moduleName); } } From e320d8613c87e41617c4b7e183550f4ad16f5239 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 15:02:09 +0200 Subject: [PATCH 22/96] Doc: Rename `docandtoc' view script to `chapter' Prepare that every chapter is displayed on a new page. refs #4820 --- .../views/scripts/partials/chapter.phtml | 1 + .../views/scripts/partials/docandtoc.phtml | 20 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) create mode 100644 modules/doc/application/views/scripts/partials/chapter.phtml delete mode 100644 modules/doc/application/views/scripts/partials/docandtoc.phtml diff --git a/modules/doc/application/views/scripts/partials/chapter.phtml b/modules/doc/application/views/scripts/partials/chapter.phtml new file mode 100644 index 000000000..b0e1fe0cb --- /dev/null +++ b/modules/doc/application/views/scripts/partials/chapter.phtml @@ -0,0 +1 @@ + diff --git a/modules/doc/application/views/scripts/partials/docandtoc.phtml b/modules/doc/application/views/scripts/partials/docandtoc.phtml deleted file mode 100644 index 46f7b0bfe..000000000 --- a/modules/doc/application/views/scripts/partials/docandtoc.phtml +++ /dev/null @@ -1,20 +0,0 @@ -

documentation

- -

Documentation not available.

- -
-partial( - 'layout/menu.phtml', - 'default', - array( - 'items' => $docToc->getChildren(), - 'sub' => false, - 'url' => '' - ) - ); -?> -
-
- -
- From 282af5a79467ea4cc49b9c6da0424877ccc0b304 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 15:03:02 +0200 Subject: [PATCH 23/96] Doc: Add `toc' view script refs #4820 --- .../application/views/scripts/partials/toc.phtml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 modules/doc/application/views/scripts/partials/toc.phtml diff --git a/modules/doc/application/views/scripts/partials/toc.phtml b/modules/doc/application/views/scripts/partials/toc.phtml new file mode 100644 index 000000000..c32285516 --- /dev/null +++ b/modules/doc/application/views/scripts/partials/toc.phtml @@ -0,0 +1,14 @@ +
+

documentation

+
+
+partial( + 'layout/menu.phtml', + 'default', + array( + 'items' => $docToc->getChildren(), + 'sub' => false, + 'url' => '' + ) +) ?> +
From dad7dc9e6ca0c9d2028a8b9d799a8ff8cf5fa0e4 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 15:06:48 +0200 Subject: [PATCH 24/96] Doc: Rename `DocController::renderDocAndToc()' to `renderChapter()' Prepare that every chapter is displayed on a new page. refs #4820 --- modules/doc/library/Doc/DocController.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php index 967f7f070..0929eac4e 100644 --- a/modules/doc/library/Doc/DocController.php +++ b/modules/doc/library/Doc/DocController.php @@ -9,25 +9,24 @@ use Icinga\Web\Controller\ActionController; class DocController extends ActionController { /** - * Publish doc HTML and toc to the view + * Render a chapter * - * @param string $module Name of the module for which to populate doc and toc. `null` for Icinga Web 2's doc + * @param string $chapterName Name of the chapter + * @param string $path Path to the documentation */ - protected function renderDocAndToc($module = null) + protected function renderChapter($chapterName, $path) { - $parser = new DocParser($module); + $parser = new DocParser($path); list($docHtml, $docToc) = $parser->getDocAndToc(); - $this->view->docHtml = $docHtml; - $this->view->docToc = $docToc; - $this->view->docName = $module === null ? 'Icinga Web 2' : ucfirst($module); - $this->_helper->viewRenderer('partials/docandtoc', null, true); + $this->view->chapterHtml = $docHtml; + $this->_helper->viewRenderer('partials/chapter', null, true); } /** * Render a toc * * @param string $path Path to the documentation - * @param string + * @param string $name Name of the documentation */ protected function renderToc($path, $name) { From e78d98a60786b14e2cb7fbb498587013f1046704 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 15:07:49 +0200 Subject: [PATCH 25/96] Doc: Add action to display a chapter of Icinga Web 2's documentation Note that the FULL documentation is displayed yet. refs #4820 --- .../controllers/IcingawebController.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index f9e05cefd..5ddc4d323 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -2,6 +2,7 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} +use \Zend_Controller_Action_Exception; use Icinga\Application\Icinga; use Icinga\Module\Doc\DocController; @@ -14,4 +15,18 @@ class Doc_IcingawebController extends DocController { $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2'); } + + /** + * View a chapter of Icinga Web 2's documentation + * + * @throws Zend_Controller_Action_Exception + */ + public function chapterAction() + { + $chapterName = $this->getParam('chapterName'); + if ($chapterName === null) { + throw new Zend_Controller_Action_Exception('Missing parameter "chapterName"', 404); + } + $this->renderChapter($chapterName, Icinga::app()->getApplicationDir('/../doc')); + } } From 178402b65c80e5029be43ddad74636d83c1f698f Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 15:09:01 +0200 Subject: [PATCH 26/96] Doc: Add action to view a chapter of a module's documentation Note that the FULL documentation is displayed yet. refs #4820 --- .../controllers/ModuleController.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index cdeca3e50..fd74050ec 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -47,4 +47,21 @@ class Doc_ModuleController extends DocController $moduleManager = Icinga::app()->getModuleManager(); $this->renderToc($moduleManager->getModuleDir($moduleName, '/doc'), $moduleName); } + + /** + * View a chapter of a module's documentation + * + * @throws Zend_Controller_Action_Exception + */ + public function chapterAction() + { + $moduleName = $this->getParam('moduleName'); + $this->assertModuleEnabled($moduleName); + $chapterName = $this->getParam('chapterName'); + if ($chapterName === null) { + throw new Zend_Controller_Action_Exception('Missing parameter "chapterName"', 404); + } + $moduleManager = Icinga::app()->getModuleManager(); + $this->renderChapter($chapterName, $moduleManager->getModuleDir($moduleName, '/doc')); + } } From 6159c0545794b39d503ca2dfa8fda78b81189c81 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 27 May 2014 15:09:43 +0200 Subject: [PATCH 27/96] Doc: Fix IndexController not using `DocController' refs #4820 --- modules/doc/application/controllers/IndexController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/application/controllers/IndexController.php b/modules/doc/application/controllers/IndexController.php index 1911f0534..aa44c9c5d 100644 --- a/modules/doc/application/controllers/IndexController.php +++ b/modules/doc/application/controllers/IndexController.php @@ -2,7 +2,7 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -use Icinga\Module\Doc\Controller as DocController; +use Icinga\Module\Doc\DocController; class Doc_IndexController extends DocController { From 93ee8e0a3d6bfb4b6e98e58f1d5eec14898d5cf6 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 13:28:06 +0200 Subject: [PATCH 28/96] Doc: Remove index/toc view script I see no reference to this file. refs #4820 --- .../doc/application/views/scripts/index/toc.phtml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 modules/doc/application/views/scripts/index/toc.phtml diff --git a/modules/doc/application/views/scripts/index/toc.phtml b/modules/doc/application/views/scripts/index/toc.phtml deleted file mode 100644 index 9188e21ff..000000000 --- a/modules/doc/application/views/scripts/index/toc.phtml +++ /dev/null @@ -1,14 +0,0 @@ -
-

Module documentations

-
-
-partial( - 'layout/menu.phtml', - 'default', - array( - 'items' => $toc->getChildren(), - 'sub' => false, - 'url' => '' - ) -) ?> -
From c12c4a9e4ca64543d981b3aa1486c12fd3ffedcf Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 13:29:02 +0200 Subject: [PATCH 29/96] Modules: Call `Module::registerWebIntegration()' after including the run script Routes added via a module's run script were not respected since `Module::registerRoutes()' is called from `Module::registerWebIntegration()'. refs #6303 --- library/Icinga/Application/Modules/Module.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Application/Modules/Module.php b/library/Icinga/Application/Modules/Module.php index 9d3fb3dee..6959c6903 100644 --- a/library/Icinga/Application/Modules/Module.php +++ b/library/Icinga/Application/Modules/Module.php @@ -192,8 +192,7 @@ class Module */ public function register() { - $this->registerAutoloader() - ->registerWebIntegration(); + $this->registerAutoloader(); try { $this->launchRunScript(); } catch (Exception $e) { @@ -205,6 +204,7 @@ class Module ); return false; } + $this->registerWebIntegration(); return true; } From 0f4d2ad80c6a3b89f06232837a11bae6324b63f0 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 13:33:07 +0200 Subject: [PATCH 30/96] Doc: Support `doc/module/:moduleName/chapter/:chapterName' URLs refs #4820 --- modules/doc/run.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 modules/doc/run.php diff --git a/modules/doc/run.php b/modules/doc/run.php new file mode 100644 index 000000000..4db96cbc3 --- /dev/null +++ b/modules/doc/run.php @@ -0,0 +1,19 @@ +isCli()) { + return; +} + +$docModuleChapter = new Zend_Controller_Router_Route( + 'doc/module/:moduleName/chapter/:chapterName', + array( + 'controller' => 'module', + 'action' => 'chapter', + 'module' => 'doc' + ) +); + +$this->addRoute('doc/module/chapter', $docModuleChapter); From b11c0c36f9c82bb7967ab896eb4eb68624d8ce22 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 13:34:39 +0200 Subject: [PATCH 31/96] Doc: Support `doc/icingaweb/chapter/:chapterName' URLs refs #4820 --- modules/doc/run.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/doc/run.php b/modules/doc/run.php index 4db96cbc3..9d93ee865 100644 --- a/modules/doc/run.php +++ b/modules/doc/run.php @@ -16,4 +16,15 @@ $docModuleChapter = new Zend_Controller_Router_Route( ) ); +$docIcingaWebChapter = new Zend_Controller_Router_Route( + 'doc/icingaweb/chapter/:chapterName', + array( + 'controller' => 'icingaweb', + 'action' => 'chapter', + 'module' => 'doc' + ) +); + $this->addRoute('doc/module/chapter', $docModuleChapter); +$this->addRoute('doc/icingaweb/chapter', $docIcingaWebChapter); + From 040473f9860065b30a120f417662af9e8a2fdd1d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:13:42 +0200 Subject: [PATCH 32/96] lib: Add NodeInterface --- library/Icinga/Data/Tree/NodeInterface.php | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 library/Icinga/Data/Tree/NodeInterface.php diff --git a/library/Icinga/Data/Tree/NodeInterface.php b/library/Icinga/Data/Tree/NodeInterface.php new file mode 100644 index 000000000..8ecca86c6 --- /dev/null +++ b/library/Icinga/Data/Tree/NodeInterface.php @@ -0,0 +1,38 @@ + Date: Wed, 28 May 2014 17:14:33 +0200 Subject: [PATCH 33/96] lib: Add TreeIterator --- library/Icinga/Data/Tree/TreeIterator.php | 90 +++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 library/Icinga/Data/Tree/TreeIterator.php diff --git a/library/Icinga/Data/Tree/TreeIterator.php b/library/Icinga/Data/Tree/TreeIterator.php new file mode 100644 index 000000000..6722f3b35 --- /dev/null +++ b/library/Icinga/Data/Tree/TreeIterator.php @@ -0,0 +1,90 @@ +nodes = $node->getChildren(); +// } +// +// public function hasChildren() +// { +// return $this->current()->hasChildren(); +// } +// +// public function getChildren() +// { +// return new self($this->current()); +// } +// +// public function current() +// { +// return $this->nodes[$this->position]; +// } +// +// public function next() +// { +// ++$this->position; +// } +// +// public function valid() +// { +// return isset($this->nodes[$this->position]); +// } +// +// public function rewind() +// { +// $this->position = 0; +// } +// +// public function key() +// { +// return $this->position; +// } +//} + +use ArrayIterator; +use RecursiveIterator; + +class TreeIterator extends ArrayIterator implements RecursiveIterator +{ + /** + * Create a new TreeIterator + * + * @param NodeInterface $node + */ + public function __construct(NodeInterface $node) + { + parent::__construct($node->getChildren()); + } + + /** + * Whether an iterator can be created for the current node + * + * @return bool + */ + public function hasChildren() + { + return $this->current()->hasChildren(); + } + + /** + * Return an iterator for the current node + * + * @return self + */ + public function getChildren() + { + return new self($this->current()); + } +} From d2936d033808aaaf90dab0a8fe7456604e50ebb4 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:15:08 +0200 Subject: [PATCH 34/96] doc/lib: Add DocToc class representing a toc refs #4820 --- modules/doc/library/Doc/DocToc.php | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 modules/doc/library/Doc/DocToc.php diff --git a/modules/doc/library/Doc/DocToc.php b/modules/doc/library/Doc/DocToc.php new file mode 100644 index 000000000..db7d9cb03 --- /dev/null +++ b/modules/doc/library/Doc/DocToc.php @@ -0,0 +1,48 @@ +value = $value; + } + + public function getValue() + { + return $this->value; + } + + public function appendChild($value) + { + $child = new self($value); + $this->children[] = $child; + return $child; + } + + public function hasChildren() + { + return ! empty($this->children); + } + + public function getChildren() + { + return $this->children; + } + + public function getIterator() + { + return new TreeIterator($this); + } +} From f0b6a3557e2fe622bd83c4e53fe6fd109028171e Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:15:43 +0200 Subject: [PATCH 35/96] doc/lib: Add DocTocHtmlRenderer class to render a toc to HTML refs #4820 --- .../doc/library/Doc/DocTocHtmlRenderer.php | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 modules/doc/library/Doc/DocTocHtmlRenderer.php diff --git a/modules/doc/library/Doc/DocTocHtmlRenderer.php b/modules/doc/library/Doc/DocTocHtmlRenderer.php new file mode 100644 index 000000000..e402f3eb4 --- /dev/null +++ b/modules/doc/library/Doc/DocTocHtmlRenderer.php @@ -0,0 +1,45 @@ +html[] = '
    '; + } + + public function endIteration() + { + $this->html[] = '
'; + } + + public function beginChildren() + { + $this->html[] = '
    '; + } + + public function endChildren() + { + $this->html[] = '
'; + } + + public function render($callback) + { + foreach ($this as $node) { + $this->html[] = $callback($node->getValue()); + } + return implode("\n", $this->html); + } +} From 2f1303a13b7471100958982c07d56b55b6d4f361 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:16:37 +0200 Subject: [PATCH 36/96] doc: No longer use a partial for viewing a toc refs #4820 --- .../application/views/scripts/partials/toc.phtml | 14 -------------- modules/doc/library/Doc/DocController.php | 9 ++++----- 2 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 modules/doc/application/views/scripts/partials/toc.phtml diff --git a/modules/doc/application/views/scripts/partials/toc.phtml b/modules/doc/application/views/scripts/partials/toc.phtml deleted file mode 100644 index c32285516..000000000 --- a/modules/doc/application/views/scripts/partials/toc.phtml +++ /dev/null @@ -1,14 +0,0 @@ -
-

documentation

-
-
-partial( - 'layout/menu.phtml', - 'default', - array( - 'items' => $docToc->getChildren(), - 'sub' => false, - 'url' => '' - ) -) ?> -
diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php index 0929eac4e..ef44de478 100644 --- a/modules/doc/library/Doc/DocController.php +++ b/modules/doc/library/Doc/DocController.php @@ -23,17 +23,16 @@ class DocController extends ActionController } /** - * Render a toc + * Populate toc * * @param string $path Path to the documentation * @param string $name Name of the documentation */ - protected function renderToc($path, $name) + protected function populateToc($path, $name) { $parser = new DocParser($path); - list($docHtml, $docToc) = $parser->getDocAndToc(); - $this->view->docToc = $docToc; + list($docHtml, $tocRenderer) = $parser->getDocAndToc(); + $this->view->tocRenderer = $tocRenderer; $this->view->docName = $name; - $this->_helper->viewRenderer('partials/toc', null, true); } } From d3a9f17fc2f8d0bcbacc4cc7bbbec3b7e21b773a Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:18:07 +0200 Subject: [PATCH 37/96] doc/parser: Return the DocTocHtmlRenderer instead of an array refs #4820 --- modules/doc/library/Doc/DocParser.php | 37 ++++++++++++--------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index fc87faf27..3bd6b3a1e 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -10,8 +10,6 @@ use RecursiveIteratorIterator; use RecursiveDirectoryIterator; use Parsedown; use Icinga\Exception\NotReadableError; -use Icinga\Web\Menu; -use Icinga\Web\Url; /** * Parser for documentation written in Markdown @@ -59,10 +57,10 @@ class DocParser ); $fileInfos = iterator_to_array($iter); natcasesort($fileInfos); - $cat = array(); - $toc = array((object) array( + $cat = array(); + $tocStack = array((object) array( 'level' => 0, - 'item' => new Menu('doc') + 'node' => new DocToc() )); $itemPriority = 1; foreach ($fileInfos as $fileInfo) { @@ -84,30 +82,29 @@ class DocParser list($header, $level) = $header; $id = $this->extractHeaderId($header); $nofollow = false; - $this->reduceToc($toc, $level); + $this->reduceToc($tocStack, $level); if ($id === null) { $path = array(); - foreach (array_slice($toc, 1) as $entry) { - $path[] = $entry->item->getTitle(); + foreach (array_slice($tocStack, 1) as $entity) { + $path[] = $entity->node->getValue()->title; } $path[] = $header; $id = implode('-', $path); $nofollow = true; } $id = urlencode(str_replace('.', '.', strip_tags($id))); - $item = end($toc)->item->addChild( - $id, - array( + $node = end($tocStack)->node->appendChild( + (object) array( 'id' => $id, 'title' => $header, 'priority' => $itemPriority++, // Post-increment is on purpose 'nofollow' => $nofollow ) ); - $toc[] = ((object) array( + $tocStack[] = (object) array( 'level' => $level, - 'item' => $item - )); + 'node' => $node + ); $line = '' . PHP_EOL . $line; } $cat[] = $line; @@ -120,7 +117,7 @@ class DocParser array($this, 'highlight'), $html ); - return array($html, $toc[0]->item); + return array($html, new DocTocHtmlRenderer($tocStack[0]->node)); } /** @@ -200,14 +197,14 @@ class DocParser } /** - * Reduce the toc to the given level + * Reduce the toc stack to the given level * - * @param array &$toc + * @param array &$tocStack * @param int $level */ - protected function reduceToc(array &$toc, $level) { - while (end($toc)->level >= $level) { - array_pop($toc); + protected function reduceToc(array &$tocStack, $level) { + while (end($tocStack)->level >= $level) { + array_pop($tocStack); } } } From 72ab5027b5afc998b9aea89fdbcbed69a56cdfe8 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:18:57 +0200 Subject: [PATCH 38/96] doc: Add view script for the toc of Icinga Web 2's doc refs #4820 --- .../controllers/IcingawebController.php | 2 +- .../application/views/scripts/icingaweb/toc.phtml | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 modules/doc/application/views/scripts/icingaweb/toc.phtml diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index 5ddc4d323..0820a82ca 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -13,7 +13,7 @@ class Doc_IcingawebController extends DocController */ public function tocAction() { - $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2'); + $this->populateToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2'); } /** diff --git a/modules/doc/application/views/scripts/icingaweb/toc.phtml b/modules/doc/application/views/scripts/icingaweb/toc.phtml new file mode 100644 index 000000000..065071f01 --- /dev/null +++ b/modules/doc/application/views/scripts/icingaweb/toc.phtml @@ -0,0 +1,15 @@ +
+

documentation

+
+
+ getHelper('Url'); + $view = $this; + ?> + render(function ($section) use ($urlHelper, $view) { + // Chapter name is not yet defined + $path = $urlHelper->url(array('chapterName' => 'tbd'), 'doc/icingaweb/chapter', false, false); + $url = $view->url($path)->setAnchor($section->id); + return sprintf('
  • %s
  • ', $url->getAbsoluteUrl(), $section->title); + }); ?> +
    From dc1bada56f98abe33def0bb002c10b8bb04e7ce0 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:19:24 +0200 Subject: [PATCH 39/96] doc: Add a view script for module's doc toc refs #4820 --- .../controllers/ModuleController.php | 3 ++- .../application/views/scripts/module/toc.phtml | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 modules/doc/application/views/scripts/module/toc.phtml diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index fd74050ec..b864ff324 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -45,7 +45,8 @@ class Doc_ModuleController extends DocController $moduleName = $this->getParam('moduleName'); $this->assertModuleEnabled($moduleName); $moduleManager = Icinga::app()->getModuleManager(); - $this->renderToc($moduleManager->getModuleDir($moduleName, '/doc'), $moduleName); + $this->populateToc($moduleManager->getModuleDir($moduleName, '/doc'), $moduleName); + $this->view->moduleName = $moduleName; } /** diff --git a/modules/doc/application/views/scripts/module/toc.phtml b/modules/doc/application/views/scripts/module/toc.phtml new file mode 100644 index 000000000..b3be77d79 --- /dev/null +++ b/modules/doc/application/views/scripts/module/toc.phtml @@ -0,0 +1,17 @@ +
    +

    documentation

    +
    +
    + getHelper('Url'); + $view = $this; + ?> + render(function ($section) use ($urlHelper, $view, $moduleName) { + // Chapter name is not yet defined + $path = $urlHelper->url( + array('moduleName' => $moduleName, 'chapterName' => 'tbd'), 'doc/module/chapter', false, false + ); + $url = $view->url($path)->setAnchor($section->id); + return sprintf('
  • %s
  • ', $url->getAbsoluteUrl(), $section->title); + }); ?> +
    From 49e927c4bf3d72e8575889ada522d57cf929600a Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:19:48 +0200 Subject: [PATCH 40/96] doc: Support `doc/module/:moduleName/toc' URLs refs #4820 --- modules/doc/run.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/doc/run.php b/modules/doc/run.php index 9d93ee865..592d85ede 100644 --- a/modules/doc/run.php +++ b/modules/doc/run.php @@ -25,6 +25,16 @@ $docIcingaWebChapter = new Zend_Controller_Router_Route( ) ); +$docModuleToc = new Zend_Controller_Router_Route( + 'doc/module/:moduleName/toc', + array( + 'controller' => 'module', + 'action' => 'toc', + 'module' => 'doc' + ) +); + $this->addRoute('doc/module/chapter', $docModuleChapter); $this->addRoute('doc/icingaweb/chapter', $docIcingaWebChapter); +$this->addRoute('doc/module/toc', $docModuleToc); From 0f1983fb25146e8b39bbfce3d5bf8300d5ba0571 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Wed, 28 May 2014 17:24:28 +0200 Subject: [PATCH 41/96] doc: Fix links in index view scripts refs #4820 --- modules/doc/application/views/scripts/index/index.phtml | 2 +- modules/doc/application/views/scripts/module/index.phtml | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/doc/application/views/scripts/index/index.phtml b/modules/doc/application/views/scripts/index/index.phtml index 9edb5910d..4381bc2a0 100644 --- a/modules/doc/application/views/scripts/index/index.phtml +++ b/modules/doc/application/views/scripts/index/index.phtml @@ -1,5 +1,5 @@

    Available documentations

    diff --git a/modules/doc/application/views/scripts/module/index.phtml b/modules/doc/application/views/scripts/module/index.phtml index 5e9eaae9d..bbd74345a 100644 --- a/modules/doc/application/views/scripts/module/index.phtml +++ b/modules/doc/application/views/scripts/module/index.phtml @@ -1,6 +1,10 @@

    Module documentations

    From 370bfca6e6e1f0897aa74b3b755711bb3a9ec501 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 3 Jun 2014 14:53:28 +0200 Subject: [PATCH 42/96] DocParser: Remove itemPriority since it's nowhere used refs #4820 --- modules/doc/library/Doc/DocParser.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 3bd6b3a1e..299295a03 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -62,7 +62,6 @@ class DocParser 'level' => 0, 'node' => new DocToc() )); - $itemPriority = 1; foreach ($fileInfos as $fileInfo) { try { $fileObject = $fileInfo->openFile(); @@ -97,7 +96,6 @@ class DocParser (object) array( 'id' => $id, 'title' => $header, - 'priority' => $itemPriority++, // Post-increment is on purpose 'nofollow' => $nofollow ) ); From ed8de18ad5cfd3fa2d14c0ce740e1755e113de28 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 3 Jun 2014 14:56:44 +0200 Subject: [PATCH 43/96] DocParser: Use first header in a file as section title refs #4820 --- modules/doc/library/Doc/DocParser.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 299295a03..0957b2dd0 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -72,15 +72,20 @@ class DocParser throw new DocException('Couldn\'t get the lock'); } $line = null; + $sectionTitle = null; while (! $fileObject->eof()) { // Save last line for setext-style headers $lastLine = $line; $line = $fileObject->fgets(); $header = $this->extractHeader($line, $lastLine); if ($header !== null) { - list($header, $level) = $header; - $id = $this->extractHeaderId($header); - $nofollow = false; + list($header, $level) = $header; + if ($sectionTitle === null) { + // The first header is the section's title + $sectionTitle = $header; + } + $id = $this->extractHeaderId($header); + $nofollow = false; $this->reduceToc($tocStack, $level); if ($id === null) { $path = array(); From d5cf2f24726d68880f6fcc3e319317c862040563 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Tue, 3 Jun 2014 15:23:59 +0200 Subject: [PATCH 44/96] doc: Implement `DocParser::getToc()' refs #4820 --- modules/doc/library/Doc/DocParser.php | 122 ++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 17 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 0957b2dd0..3eb97794d 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -6,8 +6,62 @@ namespace Icinga\Module\Doc; require_once 'vendor/Parsedown/Parsedown.php'; +use ArrayIterator; +use RunetimeException; + +class FileLockingIterator extends ArrayIterator +{ + public function next() + { + $this->current()->flock(LOCK_UN); + parent::next(); + } + + public function valid() + { + if (!parent::valid()) { + return false; + } + $fileInfo = $this->current(); + try { + $fileObject = $fileInfo->openFile(); + } catch (RuntimeException $e) { + throw new DocException($e->getMessage()); + } + if ($fileObject->flock(LOCK_SH) === false) { + throw new DocException('Couldn\'t get the lock'); + } + $this[$this->key()] = $fileObject; + return true; + } +} + +use IteratorAggregate; use RecursiveIteratorIterator; use RecursiveDirectoryIterator; + +class DocIterator implements IteratorAggregate +{ + protected $fileInfos; + + public function __construct($path) + { + $iter = new RecursiveIteratorIterator( + new MarkdownFileIterator( + new RecursiveDirectoryIterator($path) + ) + ); + $fileInfos = iterator_to_array($iter); + natcasesort($fileInfos); + $this->fileInfos = $fileInfos; + } + + public function getIterator() + { + return new FileLockingIterator($this->fileInfos); + } +} + use Parsedown; use Icinga\Exception\NotReadableError; @@ -42,6 +96,56 @@ class DocParser $this->path = $path; } + /** + * Retrieve the table of contents + * + * @return DocTocHtmlRenderer + */ + public function getToc() + { + $tocStack = array((object) array( + 'level' => 0, + 'node' => new DocToc() + )); + foreach (new DocIterator($this->path) as $fileObject) { + $line = null; + while (! $fileObject->eof()) { + // Save last line for setext-style headers + $lastLine = $line; + $line = $fileObject->fgets(); + $header = $this->extractHeader($line, $lastLine); + if ($header !== null) { + list($header, $level) = $header; + $id = $this->extractHeaderId($header); + $nofollow = false; + $this->reduceToc($tocStack, $level); + if ($id === null) { + $path = array(); + foreach (array_slice($tocStack, 1) as $entity) { + $path[] = $entity->node->getValue()->title; + } + $path[] = $header; + $id = implode('-', $path); + $nofollow = true; + } + $id = urlencode(str_replace('.', '.', strip_tags($id))); + $node = end($tocStack)->node->appendChild( + (object) array( + 'id' => $id, + 'title' => $header, + 'nofollow' => $nofollow + ) + ); + $tocStack[] = (object) array( + 'level' => $level, + 'node' => $node + ); + } + } + } + return new DocTocHtmlRenderer($tocStack[0]->node); + } + /** * Retrieve doc as HTML converted from markdown files sorted by filename and the table of contents * @@ -50,27 +154,12 @@ class DocParser */ public function getDocAndToc() { - $iter = new RecursiveIteratorIterator( - new MarkdownFileIterator( - new RecursiveDirectoryIterator($this->path) - ) - ); - $fileInfos = iterator_to_array($iter); - natcasesort($fileInfos); $cat = array(); $tocStack = array((object) array( 'level' => 0, 'node' => new DocToc() )); - foreach ($fileInfos as $fileInfo) { - try { - $fileObject = $fileInfo->openFile(); - } catch (RuntimeException $e) { - throw new DocException($e->getMessage()); - } - if ($fileObject->flock(LOCK_SH) === false) { - throw new DocException('Couldn\'t get the lock'); - } + foreach (new DocIterator($this->path) as $fileObject) { $line = null; $sectionTitle = null; while (! $fileObject->eof()) { @@ -112,7 +201,6 @@ class DocParser } $cat[] = $line; } - $fileObject->flock(LOCK_UN); } $html = Parsedown::instance()->text(implode('', $cat)); $html = preg_replace_callback( From 794ae141fae89371dfe5bd0e1fbc63d104776c38 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 13:55:58 +0200 Subject: [PATCH 45/96] lib: Let NodeInterface extend RecursiveIterator Since a node may have children and they should be iterable, the Nodefinterface now extends RecursiveIterator. --- library/Icinga/Data/Tree/NodeInterface.php | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/library/Icinga/Data/Tree/NodeInterface.php b/library/Icinga/Data/Tree/NodeInterface.php index 8ecca86c6..1d96973e0 100644 --- a/library/Icinga/Data/Tree/NodeInterface.php +++ b/library/Icinga/Data/Tree/NodeInterface.php @@ -4,7 +4,9 @@ namespace Icinga\Data\Tree; -interface NodeInterface +use RecursiveIterator; + +interface NodeInterface extends RecursiveIterator { /** * Append a child to the node @@ -21,18 +23,4 @@ interface NodeInterface * @return mixed */ public function getValue(); - - /** - * Whether the node has children - * - * @return bool - */ - public function hasChildren(); - - /** - * Get the node's children - * - * @return array - */ - public function getChildren(); } From d84532d593e71a0024194cab8f05906431b2e044 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 13:57:18 +0200 Subject: [PATCH 46/96] lib: Remove TreeIterator Nodes implementing the NodeInterface (which extends the RecursiveIterator interface) are already iterable. --- library/Icinga/Data/Tree/TreeIterator.php | 90 ----------------------- 1 file changed, 90 deletions(-) delete mode 100644 library/Icinga/Data/Tree/TreeIterator.php diff --git a/library/Icinga/Data/Tree/TreeIterator.php b/library/Icinga/Data/Tree/TreeIterator.php deleted file mode 100644 index 6722f3b35..000000000 --- a/library/Icinga/Data/Tree/TreeIterator.php +++ /dev/null @@ -1,90 +0,0 @@ -nodes = $node->getChildren(); -// } -// -// public function hasChildren() -// { -// return $this->current()->hasChildren(); -// } -// -// public function getChildren() -// { -// return new self($this->current()); -// } -// -// public function current() -// { -// return $this->nodes[$this->position]; -// } -// -// public function next() -// { -// ++$this->position; -// } -// -// public function valid() -// { -// return isset($this->nodes[$this->position]); -// } -// -// public function rewind() -// { -// $this->position = 0; -// } -// -// public function key() -// { -// return $this->position; -// } -//} - -use ArrayIterator; -use RecursiveIterator; - -class TreeIterator extends ArrayIterator implements RecursiveIterator -{ - /** - * Create a new TreeIterator - * - * @param NodeInterface $node - */ - public function __construct(NodeInterface $node) - { - parent::__construct($node->getChildren()); - } - - /** - * Whether an iterator can be created for the current node - * - * @return bool - */ - public function hasChildren() - { - return $this->current()->hasChildren(); - } - - /** - * Return an iterator for the current node - * - * @return self - */ - public function getChildren() - { - return new self($this->current()); - } -} From ce0aee5e4129dbd5d74e6476c5899dba4c5068ec Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 13:58:14 +0200 Subject: [PATCH 47/96] lib: Add Data/Tree/Node.php --- library/Icinga/Data/Tree/Node.php | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 library/Icinga/Data/Tree/Node.php diff --git a/library/Icinga/Data/Tree/Node.php b/library/Icinga/Data/Tree/Node.php new file mode 100644 index 000000000..db3a49749 --- /dev/null +++ b/library/Icinga/Data/Tree/Node.php @@ -0,0 +1,62 @@ +value = $value; + } + + public function getValue() + { + return $this->value; + } + + public function appendChild($value) + { + $child = new static($value); + $this->push($child); + return $child; + } + + public function hasChildren() + { + $current = $this->current(); + if ($current === null) {; + $current = $this; + } + return ! $current->isEmpty(); + } + + public function getChildren() + { + $current = $this->current(); + if ($current === null) {; + $current = $this; + } + return $current; + } + + public function findNodeBy($callback) + { + if (! is_callable($callback)) { + throw new RuntimeException(); + } + foreach (new RecursiveIteratorIterator($this, RecursiveIteratorIterator::SELF_FIRST) as $node) { + if (call_user_func($callback, $node)) { + return $node; + } + } + return null; + } +} From 6c8d35c6671f5e5ea9217b9a5a77f4c5f9ff1097 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 13:58:40 +0200 Subject: [PATCH 48/96] lib: Add a not yet customizable node renderer --- library/Icinga/Data/Tree/NodeRenderer.php | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 library/Icinga/Data/Tree/NodeRenderer.php diff --git a/library/Icinga/Data/Tree/NodeRenderer.php b/library/Icinga/Data/Tree/NodeRenderer.php new file mode 100644 index 000000000..4cebb7e01 --- /dev/null +++ b/library/Icinga/Data/Tree/NodeRenderer.php @@ -0,0 +1,58 @@ +content[] = '
      '; + } + + public function endIteration() + { + $this->content[] = '
    '; + } + + public function beginChildren() + { + $this->content[] = '
      '; + } + + public function endChildren() + { + $this->content[] = '
    '; + } + + public function render($callback) + { + if (! is_callable($callback)) { + throw new RuntimeException('Callable expected'); + } + foreach ($this as $node) { + try { + $content = call_user_func($callback, $node); + } catch (Exception $e) { + throw new RuntimeException($e); + } + $this->content[] = $content; + } + return implode("\n", $this->content); + } +} From cf987544c5c5499abbbbad0fb13b4b6dc63a6b87 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 13:59:11 +0200 Subject: [PATCH 49/96] doc: Remove class DocToc as it's superseded by Data/Tree/Node refs #4820 --- modules/doc/library/Doc/DocToc.php | 48 ------------------------------ 1 file changed, 48 deletions(-) delete mode 100644 modules/doc/library/Doc/DocToc.php diff --git a/modules/doc/library/Doc/DocToc.php b/modules/doc/library/Doc/DocToc.php deleted file mode 100644 index db7d9cb03..000000000 --- a/modules/doc/library/Doc/DocToc.php +++ /dev/null @@ -1,48 +0,0 @@ -value = $value; - } - - public function getValue() - { - return $this->value; - } - - public function appendChild($value) - { - $child = new self($value); - $this->children[] = $child; - return $child; - } - - public function hasChildren() - { - return ! empty($this->children); - } - - public function getChildren() - { - return $this->children; - } - - public function getIterator() - { - return new TreeIterator($this); - } -} From 625a6dae404420998163416ca7240c4c1ba1f0d9 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 13:59:59 +0200 Subject: [PATCH 50/96] doc: Remove DocTocHtmlRenderer as it's superseded by Data/Tree/NodeRenderer refs #4820 --- .../doc/library/Doc/DocTocHtmlRenderer.php | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 modules/doc/library/Doc/DocTocHtmlRenderer.php diff --git a/modules/doc/library/Doc/DocTocHtmlRenderer.php b/modules/doc/library/Doc/DocTocHtmlRenderer.php deleted file mode 100644 index e402f3eb4..000000000 --- a/modules/doc/library/Doc/DocTocHtmlRenderer.php +++ /dev/null @@ -1,45 +0,0 @@ -html[] = '
      '; - } - - public function endIteration() - { - $this->html[] = '
    '; - } - - public function beginChildren() - { - $this->html[] = '
      '; - } - - public function endChildren() - { - $this->html[] = '
    '; - } - - public function render($callback) - { - foreach ($this as $node) { - $this->html[] = $callback($node->getValue()); - } - return implode("\n", $this->html); - } -} From 07330c1ca90b7f0e380927c3866c5aff7443f0b2 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 14:09:12 +0200 Subject: [PATCH 51/96] doc: Don't use absolute 'use' in MarkdownFileIterator refs #4820 --- modules/doc/library/Doc/MarkdownFileIterator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/doc/library/Doc/MarkdownFileIterator.php b/modules/doc/library/Doc/MarkdownFileIterator.php index e8d982ba6..b68195a3e 100644 --- a/modules/doc/library/Doc/MarkdownFileIterator.php +++ b/modules/doc/library/Doc/MarkdownFileIterator.php @@ -4,7 +4,7 @@ namespace Icinga\Module\Doc; -use \RecursiveFilterIterator; +use RecursiveFilterIterator; /** * Iterator over Markdown files recursively From d446e0db2e860b5e9002164b3fad6ee4e1c5ab2b Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 14:10:13 +0200 Subject: [PATCH 52/96] doc: Implement DocParser::getChapter() refs #4820 --- modules/doc/library/Doc/DocIterator.php | 61 ++++++++++ modules/doc/library/Doc/DocParser.php | 143 +++++++++--------------- 2 files changed, 111 insertions(+), 93 deletions(-) create mode 100644 modules/doc/library/Doc/DocIterator.php diff --git a/modules/doc/library/Doc/DocIterator.php b/modules/doc/library/Doc/DocIterator.php new file mode 100644 index 000000000..07a49732f --- /dev/null +++ b/modules/doc/library/Doc/DocIterator.php @@ -0,0 +1,61 @@ +current()->flock(LOCK_UN); + parent::next(); + } + + public function valid() + { + if (!parent::valid()) { + return false; + } + $fileInfo = $this->current(); + try { + $fileObject = $fileInfo->openFile(); + } catch (RuntimeException $e) { + throw new DocException($e->getMessage()); + } + if ($fileObject->flock(LOCK_SH) === false) { + throw new DocException('Couldn\'t get the lock'); + } + $this[$this->key()] = $fileObject; + return true; + } +} + +use IteratorAggregate; +use RecursiveIteratorIterator; +use RecursiveDirectoryIterator; + +class DocIterator implements IteratorAggregate +{ + protected $fileInfos; + + public function __construct($path) + { + $iter = new RecursiveIteratorIterator( + new MarkdownFileIterator( + new RecursiveDirectoryIterator($path) + ) + ); + $fileInfos = iterator_to_array($iter); + natcasesort($fileInfos); + $this->fileInfos = $fileInfos; + } + + public function getIterator() + { + return new FileLockingIterator($this->fileInfos); + } +} diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 3eb97794d..1d77f47b1 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -1,68 +1,13 @@ current()->flock(LOCK_UN); - parent::next(); - } - - public function valid() - { - if (!parent::valid()) { - return false; - } - $fileInfo = $this->current(); - try { - $fileObject = $fileInfo->openFile(); - } catch (RuntimeException $e) { - throw new DocException($e->getMessage()); - } - if ($fileObject->flock(LOCK_SH) === false) { - throw new DocException('Couldn\'t get the lock'); - } - $this[$this->key()] = $fileObject; - return true; - } -} - -use IteratorAggregate; -use RecursiveIteratorIterator; -use RecursiveDirectoryIterator; - -class DocIterator implements IteratorAggregate -{ - protected $fileInfos; - - public function __construct($path) - { - $iter = new RecursiveIteratorIterator( - new MarkdownFileIterator( - new RecursiveDirectoryIterator($path) - ) - ); - $fileInfos = iterator_to_array($iter); - natcasesort($fileInfos); - $this->fileInfos = $fileInfos; - } - - public function getIterator() - { - return new FileLockingIterator($this->fileInfos); - } -} - use Parsedown; +use Icinga\Data\Tree\Node; use Icinga\Exception\NotReadableError; /** @@ -88,10 +33,10 @@ class DocParser public function __construct($path) { if (! is_dir($path)) { - throw new DocException('Doc directory `' . $path .'\' does not exist'); + throw new DocException('Doc directory `' . $path . '\' does not exist'); } if (! is_readable($path)) { - throw new NotReadableError('Doc directory `' . $path .'\' is not readable'); + throw new NotReadableError('Doc directory `' . $path . '\' is not readable'); } $this->path = $path; } @@ -99,16 +44,17 @@ class DocParser /** * Retrieve the table of contents * - * @return DocTocHtmlRenderer + * @return Node */ public function getToc() { $tocStack = array((object) array( 'level' => 0, - 'node' => new DocToc() + 'node' => new Node() )); foreach (new DocIterator($this->path) as $fileObject) { $line = null; + $currentChapterName = null; while (! $fileObject->eof()) { // Save last line for setext-style headers $lastLine = $line; @@ -129,11 +75,17 @@ class DocParser $nofollow = true; } $id = urlencode(str_replace('.', '.', strip_tags($id))); + if ($currentChapterName === null) { + // The first header is the chapter's name + $currentChapterName = $id; + $id = null; + } $node = end($tocStack)->node->appendChild( (object) array( - 'id' => $id, - 'title' => $header, - 'nofollow' => $nofollow + 'id' => $id, + 'title' => $header, + 'nofollow' => $nofollow, + 'chapterName' => $currentChapterName ) ); $tocStack[] = (object) array( @@ -143,72 +95,77 @@ class DocParser } } } - return new DocTocHtmlRenderer($tocStack[0]->node); + return $tocStack[0]->node; } /** - * Retrieve doc as HTML converted from markdown files sorted by filename and the table of contents + * Retrieve a chapter * - * @return array - * @throws DocException + * @param string $chapterName + * + * @return string */ - public function getDocAndToc() + public function getChapter($chapterName) { $cat = array(); $tocStack = array((object) array( 'level' => 0, - 'node' => new DocToc() + 'node' => new Node() )); + $chapterFound = false; foreach (new DocIterator($this->path) as $fileObject) { $line = null; - $sectionTitle = null; + $currentChapterName = null; + $chapter = array(); while (! $fileObject->eof()) { // Save last line for setext-style headers - $lastLine = $line; - $line = $fileObject->fgets(); - $header = $this->extractHeader($line, $lastLine); + $lastLine = $line; + $line = $fileObject->fgets(); + $header = $this->extractHeader($line, $lastLine); if ($header !== null) { list($header, $level) = $header; - if ($sectionTitle === null) { - // The first header is the section's title - $sectionTitle = $header; - } - $id = $this->extractHeaderId($header); - $nofollow = false; + $id = $this->extractHeaderId($header); $this->reduceToc($tocStack, $level); if ($id === null) { $path = array(); foreach (array_slice($tocStack, 1) as $entity) { $path[] = $entity->node->getValue()->title; } - $path[] = $header; - $id = implode('-', $path); - $nofollow = true; + $path[] = $header; + $id = implode('-', $path); } - $id = urlencode(str_replace('.', '.', strip_tags($id))); - $node = end($tocStack)->node->appendChild( + $id = urlencode(str_replace('.', '.', strip_tags($id))); + if ($currentChapterName === null) { + $currentChapterName = $id; + $id = null; + } + $node = end($tocStack)->node->appendChild( (object) array( - 'id' => $id, - 'title' => $header, - 'nofollow' => $nofollow + 'title' => $header ) ); - $tocStack[] = (object) array( + $tocStack[] = (object) array( 'level' => $level, 'node' => $node ); $line = '' . PHP_EOL . $line; } - $cat[] = $line; + $chapter[] = $line; + } + if ($currentChapterName === $chapterName) { + $chapterFound = true; + $cat = $chapter; + } + if (! $chapterFound) { + $cat = array_merge($cat, $chapter); } } - $html = Parsedown::instance()->text(implode('', $cat)); $html = preg_replace_callback( '#
    (.*?)\
    #s', array($this, 'highlight'), - $html + Parsedown::instance()->text(implode('', $cat)) ); - return array($html, new DocTocHtmlRenderer($tocStack[0]->node)); + return $html; } /** From 16d5d65a05591e18ba721f67abe0a039bf0d7fcb Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 14:10:35 +0200 Subject: [PATCH 53/96] doc: Fix actions and view scripts DocParser usage refs #4820 --- .../controllers/IcingawebController.php | 2 +- .../controllers/IndexController.php | 1 - .../controllers/ModuleController.php | 3 +- .../views/scripts/icingaweb/chapter.phtml | 38 +++++++++++++++++++ .../views/scripts/icingaweb/toc.phtml | 26 ++++++++----- .../views/scripts/index/index.phtml | 4 +- .../views/scripts/module/chapter.phtml | 38 +++++++++++++++++++ .../views/scripts/module/index.phtml | 14 +++---- .../views/scripts/module/toc.phtml | 30 +++++++++------ .../views/scripts/partials/chapter.phtml | 1 - modules/doc/library/Doc/DocController.php | 14 +++---- 11 files changed, 131 insertions(+), 40 deletions(-) create mode 100644 modules/doc/application/views/scripts/icingaweb/chapter.phtml create mode 100644 modules/doc/application/views/scripts/module/chapter.phtml delete mode 100644 modules/doc/application/views/scripts/partials/chapter.phtml diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index 0820a82ca..092de4025 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -27,6 +27,6 @@ class Doc_IcingawebController extends DocController if ($chapterName === null) { throw new Zend_Controller_Action_Exception('Missing parameter "chapterName"', 404); } - $this->renderChapter($chapterName, Icinga::app()->getApplicationDir('/../doc')); + $this->populateChapter($chapterName, Icinga::app()->getApplicationDir('/../doc')); } } diff --git a/modules/doc/application/controllers/IndexController.php b/modules/doc/application/controllers/IndexController.php index aa44c9c5d..63b5e8cdf 100644 --- a/modules/doc/application/controllers/IndexController.php +++ b/modules/doc/application/controllers/IndexController.php @@ -8,6 +8,5 @@ class Doc_IndexController extends DocController { public function indexAction() { - } } diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index b864ff324..07092c4ed 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -63,6 +63,7 @@ class Doc_ModuleController extends DocController throw new Zend_Controller_Action_Exception('Missing parameter "chapterName"', 404); } $moduleManager = Icinga::app()->getModuleManager(); - $this->renderChapter($chapterName, $moduleManager->getModuleDir($moduleName, '/doc')); + $this->populateChapter($chapterName, $moduleManager->getModuleDir($moduleName, '/doc')); + $this->view->moduleName = $moduleName; } } diff --git a/modules/doc/application/views/scripts/icingaweb/chapter.phtml b/modules/doc/application/views/scripts/icingaweb/chapter.phtml new file mode 100644 index 000000000..328d0bebe --- /dev/null +++ b/modules/doc/application/views/scripts/icingaweb/chapter.phtml @@ -0,0 +1,38 @@ +getHelper('Url'); +$view = $this; +?> +[^>]*?\s+)?href="#(?P[^"]+)"/im', + function($match) use ($toc, $urlHelper, $view) { + if (($node = $toc->findNodeBy(function ($node) use ($match) { + $section = $node->getValue(); + if (($section->id === null && $section->chapterName === $match['fragment']) + || $section->id === $match['fragment'] + ) { + return true; + } + return false; + }))) { + $section = $node->getValue(); + $path = $urlHelper->url( + array('chapterName' => $section->chapterName), + 'doc/icingaweb/chapter', + false, + false + ); + $url = $view->url($path); + if ($section->id) { + $url->setAnchor($section->id); + } + return sprintf( + 'nofollow ? 'rel="nofollow" ' : '', + $url->getAbsoluteUrl() + ); + } + return $match[0]; + }, + $chapterHtml +); ?> diff --git a/modules/doc/application/views/scripts/icingaweb/toc.phtml b/modules/doc/application/views/scripts/icingaweb/toc.phtml index 065071f01..bf91ffc77 100644 --- a/modules/doc/application/views/scripts/icingaweb/toc.phtml +++ b/modules/doc/application/views/scripts/icingaweb/toc.phtml @@ -1,15 +1,23 @@
    -

    documentation

    +

    documentation

    - getHelper('Url'); $view = $this; - ?> - render(function ($section) use ($urlHelper, $view) { - // Chapter name is not yet defined - $path = $urlHelper->url(array('chapterName' => 'tbd'), 'doc/icingaweb/chapter', false, false); - $url = $view->url($path)->setAnchor($section->id); - return sprintf('
  • %s
  • ', $url->getAbsoluteUrl(), $section->title); - }); ?> + ?> + render(function ($node) use ($urlHelper, $view) { + $section = $node->getValue(); + $path = $urlHelper->url(array('chapterName' => $section->chapterName), 'doc/icingaweb/chapter', false, false); + $url = $view->url($path); + if ($section->id) { + $url->setAnchor($section->id); + } + return sprintf( + '
  • %s
  • ', + $section->nofollow ? 'rel="nofollow" ' : '', + $url->getAbsoluteUrl(), + $section->title + ); + }); ?>
    diff --git a/modules/doc/application/views/scripts/index/index.phtml b/modules/doc/application/views/scripts/index/index.phtml index 4381bc2a0..3cebdca69 100644 --- a/modules/doc/application/views/scripts/index/index.phtml +++ b/modules/doc/application/views/scripts/index/index.phtml @@ -1,5 +1,5 @@

    Available documentations

    diff --git a/modules/doc/application/views/scripts/module/chapter.phtml b/modules/doc/application/views/scripts/module/chapter.phtml new file mode 100644 index 000000000..59a6ecb33 --- /dev/null +++ b/modules/doc/application/views/scripts/module/chapter.phtml @@ -0,0 +1,38 @@ +getHelper('Url'); +$view = $this; +?> +[^>]*?\s+)?href="#(?P[^"]+)"/im', + function($match) use ($toc, $moduleName, $urlHelper, $view) { + if (($node = $toc->findNodeBy(function ($node) use ($match) { + $section = $node->getValue(); + if (($section->id === null && $section->chapterName === $match['fragment']) + || $section->id === $match['fragment'] + ) { + return true; + } + return false; + }))) { + $section = $node->getValue(); + $path = $urlHelper->url( + array('moduleName' => $moduleName, 'chapterName' => $section->chapterName), + 'doc/module/chapter', + false, + false + ); + $url = $view->url($path); + if ($section->id) { + $url->setAnchor($section->id); + } + return sprintf( + 'nofollow ? 'rel="nofollow" ' : '', + $url->getAbsoluteUrl() + ); + } + return $match[0]; + }, + $chapterHtml +); ?> diff --git a/modules/doc/application/views/scripts/module/index.phtml b/modules/doc/application/views/scripts/module/index.phtml index bbd74345a..c3522c4c2 100644 --- a/modules/doc/application/views/scripts/module/index.phtml +++ b/modules/doc/application/views/scripts/module/index.phtml @@ -1,10 +1,10 @@

    Module documentations

    diff --git a/modules/doc/application/views/scripts/module/toc.phtml b/modules/doc/application/views/scripts/module/toc.phtml index b3be77d79..ec33c507c 100644 --- a/modules/doc/application/views/scripts/module/toc.phtml +++ b/modules/doc/application/views/scripts/module/toc.phtml @@ -1,17 +1,25 @@
    -

    documentation

    +

    documentation

    - getHelper('Url'); $view = $this; - ?> - render(function ($section) use ($urlHelper, $view, $moduleName) { - // Chapter name is not yet defined - $path = $urlHelper->url( - array('moduleName' => $moduleName, 'chapterName' => 'tbd'), 'doc/module/chapter', false, false - ); - $url = $view->url($path)->setAnchor($section->id); - return sprintf('
  • %s
  • ', $url->getAbsoluteUrl(), $section->title); - }); ?> + ?> + render(function ($node) use ($urlHelper, $view, $moduleName) { + $section = $node->getValue(); + $path = $urlHelper->url( + array('moduleName' => $moduleName, 'chapterName' => $section->chapterName), 'doc/module/chapter', false, false + ); + $url = $view->url($path); + if ($section->id) { + $url->setAnchor($section->id); + } + return sprintf( + '
  • %s
  • ', + $section->nofollow ? 'rel="nofollow" ' : '', + $url->getAbsoluteUrl(), + $section->title + ); + }); ?>
    diff --git a/modules/doc/application/views/scripts/partials/chapter.phtml b/modules/doc/application/views/scripts/partials/chapter.phtml deleted file mode 100644 index b0e1fe0cb..000000000 --- a/modules/doc/application/views/scripts/partials/chapter.phtml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php index ef44de478..bc335f381 100644 --- a/modules/doc/library/Doc/DocController.php +++ b/modules/doc/library/Doc/DocController.php @@ -4,22 +4,22 @@ namespace Icinga\Module\Doc; +use Icinga\Data\Tree\NodeRenderer; use Icinga\Web\Controller\ActionController; class DocController extends ActionController { /** - * Render a chapter + * Populate a chapter * * @param string $chapterName Name of the chapter * @param string $path Path to the documentation */ - protected function renderChapter($chapterName, $path) + protected function populateChapter($chapterName, $path) { $parser = new DocParser($path); - list($docHtml, $docToc) = $parser->getDocAndToc(); - $this->view->chapterHtml = $docHtml; - $this->_helper->viewRenderer('partials/chapter', null, true); + $this->view->chapterHtml = $parser->getChapter($chapterName); + $this->view->toc = $parser->getToc(); } /** @@ -31,8 +31,8 @@ class DocController extends ActionController protected function populateToc($path, $name) { $parser = new DocParser($path); - list($docHtml, $tocRenderer) = $parser->getDocAndToc(); - $this->view->tocRenderer = $tocRenderer; + $toc = $parser->getToc(); + $this->view->tocRenderer = new NodeRenderer($toc); $this->view->docName = $name; } } From 61ac3b0168cd2979bd20012f35de9c95ee6637b7 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 6 Jun 2014 14:45:13 +0200 Subject: [PATCH 54/96] doc: Fix translation exceptions refs #6432 refs #4820 --- modules/doc/application/locale/.gitkeep | 1 + 1 file changed, 1 insertion(+) create mode 100644 modules/doc/application/locale/.gitkeep diff --git a/modules/doc/application/locale/.gitkeep b/modules/doc/application/locale/.gitkeep new file mode 100644 index 000000000..9fc47527c --- /dev/null +++ b/modules/doc/application/locale/.gitkeep @@ -0,0 +1 @@ +Remove this file and the locale directory once #6432 has been fixed. From 7f6010e1f8b1cca800627088428c581b36f9ea38 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 13 Jun 2014 17:22:43 +0200 Subject: [PATCH 55/96] lib/tree: Add PHPDoc to Node's methods --- library/Icinga/Data/Tree/Node.php | 55 ++++++++++++++++++++-- library/Icinga/Data/Tree/NodeInterface.php | 6 +-- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/library/Icinga/Data/Tree/Node.php b/library/Icinga/Data/Tree/Node.php index db3a49749..b8f9e8dad 100644 --- a/library/Icinga/Data/Tree/Node.php +++ b/library/Icinga/Data/Tree/Node.php @@ -4,24 +4,47 @@ namespace Icinga\Data\Tree; +use Exception; use RecursiveIteratorIterator; use RuntimeException; use SplDoublyLinkedList; class Node extends SplDoublyLinkedList implements NodeInterface { + /** + * The node's value + * + * @var mixed + */ protected $value; + /** + * Create a new node + * + * @param mixed $value The node's value + */ public function __construct($value = null) { $this->value = $value; } + /** + * Get the node's value + * + * @return mixed + */ public function getValue() { return $this->value; } + /** + * Create a new node from the given value and insert the node as the last child of this node + * + * @param mixed $value The node's value + * + * @return NodeInterface The appended node + */ public function appendChild($value) { $child = new static($value); @@ -29,31 +52,55 @@ class Node extends SplDoublyLinkedList implements NodeInterface return $child; } + /** + * Whether this node has child nodes + * + * @return bool + */ public function hasChildren() { $current = $this->current(); - if ($current === null) {; + if ($current === null) { $current = $this; } return ! $current->isEmpty(); } + /** + * Get the node's child nodes + * + * @return NodeInterface + */ public function getChildren() { $current = $this->current(); - if ($current === null) {; + if ($current === null) { $current = $this; } return $current; } + /** + * Find the first child node by searching through nodes deeper than the immediate children using a custom function + * + * @param $callback + * + * @return NodeInterface|null + * @throws Exception + */ public function findNodeBy($callback) { if (! is_callable($callback)) { - throw new RuntimeException(); + throw new RuntimeException('Callable expected'); } foreach (new RecursiveIteratorIterator($this, RecursiveIteratorIterator::SELF_FIRST) as $node) { - if (call_user_func($callback, $node)) { + try { + $found = call_user_func($callback, $node); + } catch (Exception $e) { + // TODO(el): Log exception and return false instead? + throw $e; + } + if ($found) { return $node; } } diff --git a/library/Icinga/Data/Tree/NodeInterface.php b/library/Icinga/Data/Tree/NodeInterface.php index 1d96973e0..6953214dc 100644 --- a/library/Icinga/Data/Tree/NodeInterface.php +++ b/library/Icinga/Data/Tree/NodeInterface.php @@ -9,11 +9,11 @@ use RecursiveIterator; interface NodeInterface extends RecursiveIterator { /** - * Append a child to the node + * Create a new node from the given value and insert the node as the last child of this node * - * @param mixed $value + * @param mixed $value The node's value * - * @return self + * @return NodeInterface The appended node */ public function appendChild($value); From 8fe1d49ce94161d37ce643a05b4ddaff6dd2dc2c Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Fri, 13 Jun 2014 17:23:20 +0200 Subject: [PATCH 56/96] doc/cs: Begin additional if conditions on a new line --- modules/doc/library/Doc/DocParser.php | 19 +++++++++---------- .../doc/library/Doc/MarkdownFileIterator.php | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index 40a6c298e..728dd1c08 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -160,12 +160,11 @@ class DocParser $cat = array_merge($cat, $chapter); } } - $html = preg_replace_callback( + return preg_replace_callback( '#
    (.*?)\
    #s', array($this, 'highlight'), Parsedown::instance()->text(implode('', $cat)) ); - return $html; } /** @@ -194,9 +193,9 @@ class DocParser return null; } $header = null; - if ($line && - $line[0] === '#' && - preg_match('/^#+/', $line, $match) === 1 + if ($line + && $line[0] === '#' + && preg_match('/^#+/', $line, $match) === 1 ) { // Atx-style $level = strlen($match[0]); @@ -205,9 +204,9 @@ class DocParser return null; } } elseif ( - $line && - ($line[0] === '=' || $line[0] === '-') && - preg_match('/^[=-]+\s*$/', $line, $match) === 1 + $line + && ($line[0] === '=' || $line[0] === '-') + && preg_match('/^[=-]+\s*$/', $line, $match) === 1 ) { // Setext $header = trim($lastLine); @@ -235,8 +234,8 @@ class DocParser */ protected function extractHeaderId(&$header) { - if ($header[0] === '<' && - preg_match('#(?:<(?Pa|span) id="(?P.+)">)#u', $header, $match) + if ($header[0] === '<' + && preg_match('#(?:<(?Pa|span) id="(?P.+)">)#u', $header, $match) ) { $header = str_replace($match[0], '', $header); return $match['id']; diff --git a/modules/doc/library/Doc/MarkdownFileIterator.php b/modules/doc/library/Doc/MarkdownFileIterator.php index b68195a3e..2fc8cef1b 100644 --- a/modules/doc/library/Doc/MarkdownFileIterator.php +++ b/modules/doc/library/Doc/MarkdownFileIterator.php @@ -20,7 +20,7 @@ class MarkdownFileIterator extends RecursiveFilterIterator public function accept() { $current = $this->getInnerIterator()->current(); - if (!$current->isFile()) { + if (! $current->isFile()) { return false; } $filename = $current->getFilename(); From e73471030c946229f62eb5bbc4fef3ec7de72b0d Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Mon, 30 Jun 2014 11:43:25 +0200 Subject: [PATCH 57/96] doc/modules/index: Only list modules which have the 'doc' directory refs #4820 --- .../application/controllers/ModuleController.php | 14 +++++++++++--- .../application/views/scripts/module/index.phtml | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index 07092c4ed..e8b7c2fdd 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -2,18 +2,26 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -use \Zend_Controller_Action_Exception; +use Zend_Controller_Action_Exception; use Icinga\Application\Icinga; use Icinga\Module\Doc\DocController; class Doc_ModuleController extends DocController { /** - * List available modules + * List modules which are enabled and having the 'doc' directory */ public function indexAction() { - $this->view->enabledModules = Icinga::app()->getModuleManager()->listEnabledModules(); + $moduleManager = Icinga::app()->getModuleManager(); + $modules = array(); + foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $enabledModule) { + $docDir = $moduleManager->getModuleDir($enabledModule, '/doc'); + if (is_dir($docDir)) { + $modules[] = $enabledModule; + } + } + $this->view->modules = $modules; } /** diff --git a/modules/doc/application/views/scripts/module/index.phtml b/modules/doc/application/views/scripts/module/index.phtml index c3522c4c2..0755748c7 100644 --- a/modules/doc/application/views/scripts/module/index.phtml +++ b/modules/doc/application/views/scripts/module/index.phtml @@ -1,6 +1,6 @@

    Module documentations