From 788e3eb6fc09e26b2dd814ad1108da50ec0182ea Mon Sep 17 00:00:00 2001
From: Eric Lippmann <eric.lippmann@netways.de>
Date: Mon, 28 Jul 2014 19:17:03 +0200
Subject: [PATCH] doc: No longer use separate view scripts

refs #4820
---
 .../controllers/IcingawebController.php       | 19 +++--
 .../controllers/IndexController.php           |  4 +-
 .../controllers/ModuleController.php          | 69 +++++++++++++++----
 .../application/views/scripts/chapter.phtml   |  3 +
 .../views/scripts/icingaweb/chapter.phtml     | 40 -----------
 .../views/scripts/icingaweb/toc.phtml         | 23 -------
 .../views/scripts/index/index.phtml           |  5 +-
 .../views/scripts/module/chapter.phtml        | 40 -----------
 .../views/scripts/module/index.phtml          |  2 +-
 .../views/scripts/module/toc.phtml            | 25 -------
 .../doc/application/views/scripts/pdf.phtml   |  7 ++
 .../doc/application/views/scripts/toc.phtml   |  6 ++
 modules/doc/library/Doc/DocController.php     | 58 ++++++++++++----
 13 files changed, 138 insertions(+), 163 deletions(-)
 create mode 100644 modules/doc/application/views/scripts/chapter.phtml
 delete mode 100644 modules/doc/application/views/scripts/icingaweb/chapter.phtml
 delete mode 100644 modules/doc/application/views/scripts/icingaweb/toc.phtml
 delete mode 100644 modules/doc/application/views/scripts/module/chapter.phtml
 delete mode 100644 modules/doc/application/views/scripts/module/toc.phtml
 create mode 100644 modules/doc/application/views/scripts/pdf.phtml
 create mode 100644 modules/doc/application/views/scripts/toc.phtml

diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php
index 092de4025..813439169 100644
--- a/modules/doc/application/controllers/IcingawebController.php
+++ b/modules/doc/application/controllers/IcingawebController.php
@@ -9,11 +9,11 @@ use Icinga\Module\Doc\DocController;
 class Doc_IcingawebController extends DocController
 {
     /**
-     * View toc of Icinga Web 2's documentation
+     * View the toc of Icinga Web 2's documentation
      */
     public function tocAction()
     {
-        $this->populateToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2');
+        $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter');
     }
 
     /**
@@ -25,8 +25,19 @@ class Doc_IcingawebController extends DocController
     {
         $chapterName = $this->getParam('chapterName');
         if ($chapterName === null) {
-            throw new Zend_Controller_Action_Exception('Missing parameter "chapterName"', 404);
+            throw new Zend_Controller_Action_Exception(
+                $this->translate('Missing parameter \'chapterName\''),
+                404
+            );
         }
-        $this->populateChapter($chapterName, Icinga::app()->getApplicationDir('/../doc'));
+        $this->renderChapter(Icinga::app()->getApplicationDir('/../doc'), $chapterName, 'doc/icingaweb/chapter');
+    }
+
+    /**
+     * View Icinga Web 2's documentation as PDF
+     */
+    public function pdfAction()
+    {
+        $this->renderPdf(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter');
     }
 }
diff --git a/modules/doc/application/controllers/IndexController.php b/modules/doc/application/controllers/IndexController.php
index 63b5e8cdf..c83cfabab 100644
--- a/modules/doc/application/controllers/IndexController.php
+++ b/modules/doc/application/controllers/IndexController.php
@@ -6,7 +6,5 @@ use Icinga\Module\Doc\DocController;
 
 class Doc_IndexController extends DocController
 {
-    public function indexAction()
-    {
-    }
+    public function indexAction() {}
 }
diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php
index 2ce1b1e73..b04a56400 100644
--- a/modules/doc/application/controllers/ModuleController.php
+++ b/modules/doc/application/controllers/ModuleController.php
@@ -30,24 +30,36 @@ class Doc_ModuleController extends DocController
      *
      * @param   $moduleName
      *
-     * @throws  Zend_Controller_Action_Exception
+     * @throws  Zend_Controller_Action_Exception    If the required parameter 'moduleName' is empty or either if the
+     *                                              given module is neither installed nor enabled
      */
     protected function assertModuleEnabled($moduleName)
     {
-        if ($moduleName === null) {
-            throw new Zend_Controller_Action_Exception('Missing parameter "moduleName"', 404);
+        if (empty($moduleName)) {
+            throw new Zend_Controller_Action_Exception(
+                $this->translate('Missing parameter \'moduleName\''),
+                404
+            );
         }
         $moduleManager = Icinga::app()->getModuleManager();
         if (! $moduleManager->hasInstalled($moduleName)) {
-            throw new Zend_Controller_Action_Exception('Module ' . $moduleName . ' is not installed', 404);
+            throw new Zend_Controller_Action_Exception(
+                $this->translate('Module') . ' \'' . $moduleName . '\' ' . $this->translate('is not installed'),
+                404
+            );
         }
         if (! $moduleManager->hasEnabled($moduleName)) {
-            throw new Zend_Controller_Action_Exception('Module ' . $moduleName. ' is not enabled', 404);
+            throw new Zend_Controller_Action_Exception(
+                $this->translate('Module') . ' \'' . $moduleName . '\' ' . $this->translate('is not enabled'),
+                404
+            );
         }
     }
 
     /**
-     * View toc of a module's documentation
+     * View the toc of a module's documentation
+     *
+     * @see assertModuleEnabled()
      */
     public function tocAction()
     {
@@ -55,7 +67,12 @@ class Doc_ModuleController extends DocController
         $this->assertModuleEnabled($moduleName);
         $moduleManager = Icinga::app()->getModuleManager();
         try {
-            $this->populateToc($moduleManager->getModuleDir($moduleName, '/doc'), $moduleName);
+            $this->renderToc(
+                $moduleManager->getModuleDir($moduleName, '/doc'),
+                $moduleName,
+                'doc/module/chapter',
+                array('moduleName' => $moduleName)
+            );
         } catch (DocException $e) {
             throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
         }
@@ -65,22 +82,50 @@ class Doc_ModuleController extends DocController
     /**
      * View a chapter of a module's documentation
      *
-     * @throws Zend_Controller_Action_Exception
+     * @throws  Zend_Controller_Action_Exception    If the required parameter 'chapterName' is missing or if an error in
+     *                                              the documentation module's library occurs
+     * @see     assertModuleEnabled()
      */
     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);
+        $chapterTitle = $this->getParam('chapterName');
+        if ($chapterTitle === null) {
+            throw new Zend_Controller_Action_Exception(
+                $this->translate('Missing parameter \'chapterName\''),
+                404
+            );
         }
         $moduleManager = Icinga::app()->getModuleManager();
         try {
-            $this->populateChapter($chapterName, $moduleManager->getModuleDir($moduleName, '/doc'));
+            $this->renderChapter(
+                $moduleManager->getModuleDir($moduleName, '/doc'),
+                $chapterTitle,
+                'doc/module/chapter',
+                array('moduleName' => $moduleName)
+            );
         } catch (DocException $e) {
             throw new Zend_Controller_Action_Exception($e->getMessage(), 404);
         }
         $this->view->moduleName = $moduleName;
     }
+
+    /**
+     * View a module's documentation as PDF
+     *
+     * @see assertModuleEnabled()
+     */
+    public function pdfAction()
+    {
+        $moduleName = $this->getParam('moduleName');
+        $this->assertModuleEnabled($moduleName);
+        $moduleManager = Icinga::app()->getModuleManager();
+        $this->renderPdf(
+            $moduleManager->getModuleDir($moduleName, '/doc'),
+            $moduleName,
+            'doc/module/chapter',
+            array('moduleName' => $moduleName)
+        );
+    }
 }
diff --git a/modules/doc/application/views/scripts/chapter.phtml b/modules/doc/application/views/scripts/chapter.phtml
new file mode 100644
index 000000000..7657d69fb
--- /dev/null
+++ b/modules/doc/application/views/scripts/chapter.phtml
@@ -0,0 +1,3 @@
+<div class="chapter">
+    <?= $sectionRenderer->render($this, $this->getHelper('Url')); ?>
+</div>
diff --git a/modules/doc/application/views/scripts/icingaweb/chapter.phtml b/modules/doc/application/views/scripts/icingaweb/chapter.phtml
deleted file mode 100644
index 2ab744ebd..000000000
--- a/modules/doc/application/views/scripts/icingaweb/chapter.phtml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-$urlHelper = $this->getHelper('Url');
-$view = $this;
-?>
-<div class="chapter">
-<?= preg_replace_callback(
-    '/<a\s+(?P<attribs>[^>]*?\s+)?href="#(?P<fragment>[^"]+)"/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(
-                '<a %s%shref="%s"',
-                strlen($match['attribs']) ? trim($match['attribs']) . ' ' : '',
-                $section->nofollow ? 'rel="nofollow" ' : '',
-                $url->getAbsoluteUrl()
-            );
-        }
-        return $match[0];
-    },
-    $chapterHtml
-); ?>
-</div>
diff --git a/modules/doc/application/views/scripts/icingaweb/toc.phtml b/modules/doc/application/views/scripts/icingaweb/toc.phtml
deleted file mode 100644
index bf91ffc77..000000000
--- a/modules/doc/application/views/scripts/icingaweb/toc.phtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<div class="controls">
-    <h1><?= $docName ?> documentation</h1>
-</div>
-<div class="content" data-base-target="_next">
-    <?php
-    $urlHelper = $this->getHelper('Url');
-    $view = $this;
-    ?>
-    <?= $tocRenderer->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(
-            '<li><a %shref="%s">%s</a></li>',
-            $section->nofollow ? 'rel="nofollow" ' : '',
-            $url->getAbsoluteUrl(),
-            $section->title
-        );
-    }); ?>
-</div>
diff --git a/modules/doc/application/views/scripts/index/index.phtml b/modules/doc/application/views/scripts/index/index.phtml
index 3cebdca69..e4218bee2 100644
--- a/modules/doc/application/views/scripts/index/index.phtml
+++ b/modules/doc/application/views/scripts/index/index.phtml
@@ -1,5 +1,6 @@
-<h1>Available documentations</h1>
+<div class="controls"></div>
+<h1><?= $this->translate('Available documentations'); ?></h1>
 <ul>
     <li><a href="<?= $this->href('doc/icingaweb/toc'); ?>">Icinga Web 2</a></li>
-    <li><a href="<?= $this->href('doc/module/'); ?>">Module documentations</a></li>
+    <li><a href="<?= $this->href('doc/module/'); ?>"><?= $this->translate('Module documentations'); ?></a></li>
 </ul>
diff --git a/modules/doc/application/views/scripts/module/chapter.phtml b/modules/doc/application/views/scripts/module/chapter.phtml
deleted file mode 100644
index 3a809209f..000000000
--- a/modules/doc/application/views/scripts/module/chapter.phtml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-$urlHelper = $this->getHelper('Url');
-$view = $this;
-?>
-<div class="chapter">
-<?= preg_replace_callback(
-    '/<a\s+(?P<attribs>[^>]*?\s+)?href="#(?P<fragment>[^"]+)"/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(
-                '<a %s%shref="%s"',
-                strlen($match['attribs']) ? trim($match['attribs']) . ' ' : '',
-                $section->nofollow ? 'rel="nofollow" ' : '',
-                $url->getAbsoluteUrl()
-            );
-        }
-        return $match[0];
-    },
-    $chapterHtml
-); ?>
-</div>
diff --git a/modules/doc/application/views/scripts/module/index.phtml b/modules/doc/application/views/scripts/module/index.phtml
index 0755748c7..cc184016f 100644
--- a/modules/doc/application/views/scripts/module/index.phtml
+++ b/modules/doc/application/views/scripts/module/index.phtml
@@ -1,4 +1,4 @@
-<h1>Module documentations</h1>
+<h1><?= $this->translate('Module documentations'); ?></h1>
 <ul>
     <?php foreach ($modules as $module): ?>
         <li>
diff --git a/modules/doc/application/views/scripts/module/toc.phtml b/modules/doc/application/views/scripts/module/toc.phtml
deleted file mode 100644
index ec33c507c..000000000
--- a/modules/doc/application/views/scripts/module/toc.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<div class="controls">
-    <h1><?= $docName ?> documentation</h1>
-</div>
-<div class="content" data-base-target="_next">
-    <?php
-    $urlHelper = $this->getHelper('Url');
-    $view = $this;
-    ?>
-    <?= $tocRenderer->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(
-            '<li><a %shref="%s">%s</a></li>',
-            $section->nofollow ? 'rel="nofollow" ' : '',
-            $url->getAbsoluteUrl(),
-            $section->title
-        );
-    }); ?>
-</div>
diff --git a/modules/doc/application/views/scripts/pdf.phtml b/modules/doc/application/views/scripts/pdf.phtml
new file mode 100644
index 000000000..72d77f3c0
--- /dev/null
+++ b/modules/doc/application/views/scripts/pdf.phtml
@@ -0,0 +1,7 @@
+<h1><?= $docName ?> <?= $this->translate('Documentation'); ?></h1>
+<div class="toc">
+    <?= $tocRenderer->render($this, $this->getHelper('Url')); ?>
+</div>
+<div class="chapter">
+    <?= $sectionRenderer->render($this, $this->getHelper('Url')); ?>
+</div>
diff --git a/modules/doc/application/views/scripts/toc.phtml b/modules/doc/application/views/scripts/toc.phtml
new file mode 100644
index 000000000..8ffe2820d
--- /dev/null
+++ b/modules/doc/application/views/scripts/toc.phtml
@@ -0,0 +1,6 @@
+<div class="controls">
+    <h1><?= $docName ?> <?= $this->translate('Documentation'); ?></h1>
+</div>
+<div class="content toc" data-base-target="_next">
+    <?= $tocRenderer->render($this, $this->getHelper('Url')); ?>
+</div>
diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php
index 88fd7476e..de2a7bac9 100644
--- a/modules/doc/library/Doc/DocController.php
+++ b/modules/doc/library/Doc/DocController.php
@@ -4,35 +4,67 @@
 
 namespace Icinga\Module\Doc;
 
-use Icinga\Data\Tree\NodeRenderer;
 use Icinga\Web\Controller\ModuleActionController;
 
 class DocController extends ModuleActionController
 {
     /**
-     * Populate a chapter
+     * Render a chapter
      *
-     * @param string $chapterName   Name of the chapter
-     * @param string $path          Path to the documentation
+     * @param string    $path           Path to the documentation
+     * @param string    $chapterTitle   Title of the chapter
+     * @param string    $url
+     * @param array     $urlParams
      */
-    protected function populateChapter($chapterName, $path)
+    protected function renderChapter($path, $chapterTitle, $url, array $urlParams = array())
     {
         $parser = new DocParser($path);
-        $this->view->chapterHtml = $parser->getChapter($chapterName);
-        $this->view->toc = $parser->getToc();
+        $this->view->sectionRenderer = new SectionRenderer(
+            $parser->getDocTree(),
+            SectionRenderer::decodeUrlParam($chapterTitle),
+            $url,
+            $urlParams
+        );
+        $this->_helper->viewRenderer('chapter', null, true);
     }
 
     /**
-     * Populate toc
+     * Render a toc
      *
-     * @param string $path Path to the documentation
-     * @param string $name Name of the documentation
+     * @param string    $path           Path to the documentation
+     * @param string    $name           Name of the documentation
+     * @param string    $url
+     * @param array     $urlParams
      */
-    protected function populateToc($path, $name)
+    protected function renderToc($path, $name, $url, array $urlParams = array())
     {
         $parser = new DocParser($path);
-        $toc = $parser->getToc();
-        $this->view->tocRenderer = new NodeRenderer($toc);
+        $this->view->tocRenderer = new TocRenderer($parser->getDocTree(), $url, $urlParams);
         $this->view->docName = $name;
+        $this->_helper->viewRenderer('toc', null, true);
+    }
+
+    /**
+     * Render a pdf
+     *
+     * @param string    $path           Path to the documentation
+     * @param string    $name           Name of the documentation
+     * @param string    $url
+     * @param array     $urlParams
+     */
+    protected function renderPdf($path, $name, $url, array $urlParams = array())
+    {
+        $parser = new DocParser($path);
+        $docTree = $parser->getDocTree();
+        $this->view->tocRenderer = new TocRenderer($docTree, $url, $urlParams);
+        $this->view->sectionRenderer = new SectionRenderer(
+            $docTree,
+            null,
+            $url,
+            $urlParams
+        );
+        $this->view->docName = $name;
+        $this->_helper->viewRenderer('pdf', null, true);
+        $this->_request->setParam('format', 'pdf');
     }
 }