1<?php
2/**
3 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
4 * @author     Andreas Gohr <gohr@cosmocode.de>
5 */
6
7class syntax_plugin_pagenav extends DokuWiki_Syntax_Plugin
8{
9
10    /** @inheritDoc */
11    public function getType()
12    {
13        return 'substition';
14    }
15
16    /** @inheritDoc */
17    public function getPType()
18    {
19        return 'block';
20    }
21
22    /** @inheritDoc */
23    public function getSort()
24    {
25        return 155;
26    }
27
28
29    /** @inheritDoc */
30    public function connectTo($mode)
31    {
32        $this->Lexer->addSpecialPattern('\[<\d*>(?: [^\]]+)?\]', $mode, 'plugin_pagenav');
33    }
34
35
36    /** @inheritDoc */
37    public function handle($match, $state, $pos, Doku_Handler $handler)
38    {
39        //split the match in it's parts
40        $match = substr($match, 1, -1);
41        list($mode, $glob) = explode(' ', $match, 2);
42        $mode = (int)substr($mode, 1, -1);
43        if (!$mode) $mode = 2 + 4 + 8;
44
45        return array(strtolower(trim($glob)), $mode);
46    }
47
48    /** @inheritDoc */
49    public function render($format, Doku_Renderer $renderer, $data)
50    {
51        global $INFO;
52        global $conf;
53        if ($format != 'xhtml') return false;
54
55        list($glob, $mode) = $data;
56        $glob = preg_quote($glob, '/');
57
58        // get all files in current namespace
59        static $list = null; // static to reuse the array for multiple calls.
60        if (is_null($list)) {
61            $list = array();
62            $ns = str_replace(':', '/', getNS($INFO['id']));
63            search($list, $conf['datadir'], 'search_list', array(), utf8_encodeFN($ns));
64        }
65        $id = $INFO['id'];
66
67        // find the start page
68        $exist = false;
69        $start = getNS($INFO['id']) . ':';
70        resolve_pageid('', $start, $exist);
71
72        $cnt = count($list);
73        if ($cnt < 2) return true; // there are no other doc in this namespace
74
75        $first = '';
76        $prev = '';
77        $last = '';
78        $next = '';
79        $self = false;
80
81        // we go through the list only once, handling all options and globs
82        // only for the 'last' command the whole list is iterated
83        for ($i = 0; $i < $cnt; $i++) {
84            if ($list[$i]['id'] == $id) {
85                $self = true;
86            } else {
87                if ($glob && !preg_match('/' . $glob . '/', noNS($list[$i]['id']))) continue;
88                if ($list[$i]['id'] == $start) continue;
89                if (isHiddenPage($list[$i]['id'])) continue;
90
91                if ($self) {
92                    // we're after the current id
93                    if (!$next) {
94                        $next = $list[$i]['id'];
95                    }
96                    $last = $list[$i]['id'];
97                } else {
98                    // we're before the current id
99                    if (!$first) {
100                        $first = $list[$i]['id'];
101                    }
102                    $prev = $list[$i]['id'];
103                }
104            }
105        }
106
107        $renderer->doc .= '<p class="plugin__pagenav">';
108        if ($mode & 4) $renderer->doc .= $this->buildImgLink($first, 'first');
109        if ($mode & 2) $renderer->doc .= $this->buildImgLink($prev, 'prev');
110        if ($mode & 8) $renderer->doc .= $this->buildImgLink($start, 'up');
111        if ($mode & 2) $renderer->doc .= $this->buildImgLink($next, 'next');
112        if ($mode & 4) $renderer->doc .= $this->buildImgLink($last, 'last');
113        $renderer->doc .= '</p>';
114
115        return true;
116    }
117
118    /**
119     * Builds the link using an SVG image
120     *
121     * @param string $page page to link to
122     * @param string $cmd
123     * @return string
124     */
125    protected function buildImgLink($page, $cmd)
126    {
127        $img = inlineSVG(__DIR__ . '/img/' . $cmd . '.svg');
128
129        // no page, gray out item
130        if (blank($page)) {
131            return '<span class="' . $cmd . '">' . $img . '</span>';
132        }
133
134
135        $title = p_get_first_heading($page);
136        $attr = [
137            'href' => wl($page),
138            'title' => $this->getLang($cmd) . ': ' . hsc($title),
139            'class' => 'wikilink1 ' . $cmd,
140        ];
141        return '<a ' . buildAttributes($attr) . '>' . $img . '</a>';
142    }
143}
144