1<?php
2/**
3 * DokuWiki Syntax Plugin Backlinks.
4 *
5 * Shows a list of pages that link back to a given page.
6 *
7 * Syntax:  {{backlinks>[pagename][#filterNS|!#filterNS]}}
8 *
9 *   [pagename] - a valid wiki pagename or a . for the current page
10 *   [filterNS] - a valid,absolute namespace name, optionally prepended with ! to exclude
11 *
12 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
13 * @author  Michael Klier <chi@chimeric.de>
14 * @author  Mark C. Prins <mprins@users.sf.net>
15 */
16
17/**
18 * All DokuWiki plugins to extend the parser/rendering mechanism
19 * need to inherit from this class.
20 */
21class syntax_plugin_backlinks extends DokuWiki_Syntax_Plugin {
22    /**
23     * Syntax Type.
24     *
25     * Needs to return one of the mode types defined in $PARSER_MODES in parser.php.
26     *
27     * @see DokuWiki_Syntax_Plugin::getType()
28     */
29    public function getType() {
30        return 'substition';
31    }
32
33    /**
34     * @see DokuWiki_Syntax_Plugin::getPType()
35     */
36    public function getPType() {
37        return 'block';
38    }
39
40    /**
41     * @see Doku_Parser_Mode::getSort()
42     */
43    public function getSort() {
44        return 304;
45    }
46
47    /**
48     * Connect pattern to lexer.
49     *
50     * @see Doku_Parser_Mode::connectTo()
51     */
52    public function connectTo($mode) {
53        $this->Lexer->addSpecialPattern('\{\{backlinks>.+?\}\}', $mode, 'plugin_backlinks');
54    }
55
56    /**
57     * Handler to prepare matched data for the rendering process.
58     *
59     * @see DokuWiki_Syntax_Plugin::handle()
60     */
61    public function handle($match, $state, $pos, Doku_Handler $handler) {
62        // strip {{backlinks> from start and }} from end
63        $match = substr($match, 12, -2);
64
65        $includeNS = '';
66        if(strstr($match, "#")) {
67            $includeNS = substr(strstr($match, "#", false), 1);
68            $match     = strstr($match, "#", true);
69        }
70
71        return (array($match, $includeNS));
72    }
73
74    /**
75     * Handles the actual output creation.
76     *
77     * @see DokuWiki_Syntax_Plugin::render()
78     */
79    public function render($mode, Doku_Renderer $renderer, $data) {
80        global $lang;
81        global $INFO;
82        global $ID;
83
84        $id = $ID;
85        // If it's a sidebar, get the original id.
86        if($INFO != null) {
87            $id = $INFO['id'];
88        }
89        $match = $data[0];
90        $match = ($match == '.') ? $id : $match;
91        if(strstr($match, ".:")) {
92            resolve_pageid(getNS($id), $match, $exists);
93        }
94
95        if($mode == 'xhtml') {
96            $renderer->info['cache'] = false;
97
98            $backlinks = ft_backlinks($match);
99
100            dbglog($backlinks, "backlinks: all backlinks to: $match");
101
102            $renderer->doc .= '<div id="plugin__backlinks">' . "\n";
103
104            $filterNS = $data[1];
105            if(!empty($backlinks) && !empty($filterNS)) {
106                if(stripos($filterNS, "!", 0) === 0) {
107                    $filterNS = substr($filterNS, 1);
108                    dbglog($filterNS, "backlinks: exluding all of namespace: $filterNS");
109                    $backlinks = array_filter(
110                        $backlinks, function ($ns) use ($filterNS) {
111                        return stripos($ns, $filterNS, 0) !== 0;
112                    }
113                    );
114                } else {
115                    dbglog($filterNS, "backlinks: including namespace: $filterNS only");
116                    $backlinks = array_filter(
117                        $backlinks, function ($ns) use ($filterNS) {
118                        return stripos($ns, $filterNS, 0) === 0;
119                    }
120                    );
121                }
122            }
123
124            dbglog($backlinks, "backlinks: all backlinks to be rendered");
125
126            if(!empty($backlinks)) {
127
128                $renderer->doc .= '<ul class="idx">';
129
130                foreach($backlinks as $backlink) {
131                    $name = p_get_metadata($backlink, 'title');
132                    if(empty($name)) {
133                        $name = $backlink;
134                    }
135                    $renderer->doc .= '<li><div class="li">';
136                    $renderer->doc .= html_wikilink(':' . $backlink, $name);
137                    $renderer->doc .= '</div></li>' . "\n";
138                }
139
140                $renderer->doc .= '</ul>' . "\n";
141            } else {
142                $renderer->doc .= "<strong>Plugin Backlinks: " . $lang['nothingfound'] . "</strong>" . "\n";
143            }
144
145            $renderer->doc .= '</div>' . "\n";
146
147            return true;
148        }
149        return false;
150    }
151}
152