1<?php
2/**
3 * DokuWiki Plugin DocNavigation (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Gerrit Uitslag <klapinklapin@gmail.com>
7 */
8
9use dokuwiki\Extension\ActionPlugin;
10use dokuwiki\Extension\Event;
11use dokuwiki\Extension\EventHandler;
12
13/**
14 * Add documentation navigation elements around page
15 */
16class action_plugin_docnavigation extends ActionPlugin
17{
18
19    /**
20     * Register the events
21     *
22     * @param EventHandler $controller
23     */
24    public function register(EventHandler $controller)
25    {
26        $controller->register_hook('RENDERER_CONTENT_POSTPROCESS', 'AFTER', $this, 'addtopnavigation');
27    }
28
29    /**
30     * Add navigation bar to top of content
31     *
32     * @param Event $event
33     */
34    public function addtopnavigation(Event $event)
35    {
36        global $ACT;
37
38        if ($event->data[0] != 'xhtml' || !in_array($ACT, ['show', 'preview'])) return;
39
40        $event->data[1] = $this->htmlNavigationbar(false)
41            . $event->data[1]
42            . $this->htmlNavigationbar(true);
43    }
44
45    /**
46     * Return html of navigation elements
47     *
48     * @param bool $linktoToC if true, add referer to ToC
49     * @return string
50     */
51    private function htmlNavigationbar($linktoToC)
52    {
53        global $ID;
54        global $ACT;
55        $data = null;
56        if ($ACT == 'preview') {
57            // the RENDERER_CONTENT_POSTPROCESS event is triggered just after rendering the instruction,
58            // so syntax instance will exists
59            /** @var syntax_plugin_docnavigation_pagenav $pagenav */
60            $pagenav = plugin_load('syntax', 'docnavigation_pagenav');
61            if ($pagenav instanceof syntax_plugin_docnavigation_pagenav) {
62                $data = $pagenav->getPageData($ID);
63            }
64        } else {
65            $data = p_get_metadata($ID, 'docnavigation');
66        }
67
68        $out = '';
69        if (!empty($data)) {
70            if ($linktoToC) {
71                $out .= '<div class="clearer"></div>';
72            }
73
74            $out .= '<div class="docnavbar' . ($linktoToC ? ' showtoc' : '') . '"><div class="leftnav">';
75            if ($data['previous']['link']) {
76                $out .= '← ' . $this->htmlLink($data['previous']);
77            }
78            $out .= '&nbsp;</div>';
79
80            if ($linktoToC) {
81                $out .= '<div class="centernav">';
82                if ($data['toc']['link']) {
83                    $out .= $this->htmlLink($data['toc']);
84                }
85                $out .= '&nbsp;</div>';
86            }
87
88            $out .= '<div class="rightnav">&nbsp;';
89            if ($data['next']['link']) {
90                $out .= $this->htmlLink($data['next']) . ' →';
91            }
92            $out .= '</div></div>';
93        }
94        return $out;
95    }
96
97    /**
98     * Build nice url title, if no title given use original link with original not cleaned id
99     *
100     * @param array $link with: 'link' => string full page id, 'title' => null|string, 'rawlink' => string original not cleaned id, 'hash' => string
101     * @return string
102     */
103    protected function htmlLink($link) {
104        /** @var Doku_Renderer_xhtml $Renderer */
105        static $Renderer = null;
106        if (is_null($Renderer)) {
107            $Renderer = p_get_renderer('xhtml');
108        }
109
110        $title = $this->getTitle($link, $Renderer);
111        $id = ':' . $link['link'] . '#' . $link['hash'];
112        return $Renderer->internallink($id, $title, null, true);
113    }
114
115    /**
116     * Build nice url title, if no title given use original link with original not cleaned id
117     *
118     * @param array $link with: 'link' => string full page id, 'title' => null|string, 'rawlink' => string original not cleaned id, 'hash' => string
119     * @param Doku_Renderer_xhtml $Renderer
120     * @return string
121     */
122    protected function getTitle($link, $Renderer)
123    {
124        if ($link['title'] === null) {
125            $defaulttitle = $Renderer->_simpleTitle($link['rawlink']);
126            return $Renderer->_getLinkTitle(null, $defaulttitle, $isImage, $link['link']);
127        }
128        return $link['title'];
129    }
130}
131