1<?php
2/**
3 * Backlinks: Show a list of backlinks for the given pagename
4 * Usage:
5 * {{backlinks>page}} to display the backlinks page in the current namespace
6 * {{backlinks>:page}} for "page" in top namespace
7 * {{backlinks>namespace:page}} for "page" in namespace "namespace"
8 * {{backlinks>.namespace:page}} for "page" in subnamespace "namespace"
9 *
10 */
11
12if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
14require_once(DOKU_PLUGIN.'syntax.php');
15require_once(DOKU_INC.'inc/fulltext.php');
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     * return some info
24     */
25    function getInfo(){
26        return array(
27            'author' => 'Jonathan Arkell',
28            'email'  => 'jonnay@jonnay.net',
29            'date'   => '2005-10-24',
30            'name'   => 'Backlink Plugin',
31            'desc'   => 'Displays the backlinks for the given wikipage',
32            'url'    => 'https://www.dokuwiki.org/plugin:backlinks',
33        );
34    }
35
36    /**
37     * What kind of syntax are we?
38     */
39    function getType(){
40        return 'substition';
41    }
42
43    /**
44     * Where to sort in?
45     */
46    function getSort(){
47        return 30;
48    }
49
50    /**
51     * Paragraph Type
52     */
53    function getPType(){
54        return 'block';
55    }
56
57    /**
58     * Connect pattern to lexer
59     */
60    function connectTo($mode) {
61      $this->Lexer->addSpecialPattern("{{backlinks}}",$mode,'plugin_backlinks');
62    }
63
64    /**
65     * Handle the match
66     */
67    function handle($match, $state, $pos, &$handler){
68        global $ID;
69
70        $syntax = substr($match,12,-2);             // strip markup
71        $page = $ID;
72
73        resolve_pageid(getNS($ID),$page,$exists);   // resolve shortcuts
74
75        // check for permission
76        if (auth_quickaclcheck($page) < 1) return false;
77
78        $links = ft_backlinks($page);
79        foreach ($links as $link)
80        {
81            $backlinks[substr($link, strrpos($link, ':')+1)] = $link;
82        }
83        ksort($backlinks);
84
85        return array($page,$backlinks);
86    }
87
88    /**
89     * Create output
90     */
91    function render($mode, &$renderer, $data) {
92        if($mode == 'xhtml'){
93            $file = wikiFN($data[0]);
94
95            $renderer->doc .= '<div class="backlinks">';
96
97            if (!empty($data[1]))
98            {
99                $lastLetter = '';
100                $pageList = array();
101                array_push($data[1]," Dummy Entry"); // ugh.  Hacky Kludge.
102                foreach($data[1] as $name => $page) {
103                    if ($name{0} != $lastLetter) {
104                        if (!empty($pageList)) {
105                            $renderer->doc .= '<h3>'.strtoupper($lastLetter).'</h3>';
106                            $this->renderPageList($renderer, $pageList);
107                            $pageList = array();
108                        }
109                    }
110                    $pageList[] = $page;
111                    $lastLetter = $name{0};
112                }
113            } else {
114            	$renderer->doc .= "{$data[0]} has no backlinks";
115            }
116
117            $renderer->doc .= '</div>';
118            return true;
119        }
120        return false;
121    }
122
123    function renderpageList(&$renderer, $pageList)
124    {
125        if (empty ($pageList)) {
126            return;
127        }
128
129        $renderer->doc .= '<ul>';
130        foreach($pageList as $page) {
131          $renderer->doc .= '<li>';
132          $renderer->internalLink($page, $page);
133          $renderer->doc .= '</li>';
134        }
135        $renderer->doc .= '</ul>';
136    }
137
138    /**
139     * Corrects relative internal links and media
140     */
141    function _correctRelNS($instr,$incl){
142        global $ID;
143
144        // check if included page is in same namespace
145        $iNS = getNS($incl);
146        if (getNS($ID) == $iNS) return $instr;
147
148        // convert internal links and media from relative to absolute
149        $n = count($instr);
150        for($i = 0; $i < $n; $i++){
151            if (substr($instr[$i][0], 0, 8) == 'internal'){
152
153                // relative subnamespace
154                if ($instr[$i][1][0]{0} == '.'){
155                    $instr[$i][1][0] = $iNS.':'.substr($instr[$i][1][0], 1);
156
157                // relative link
158                } elseif (strpos($instr[$i][1][0],':') === false) {
159                    $instr[$i][1][0] = $iNS.':'.$instr[$i][1][0];
160                }
161            }
162        }
163        return $instr;
164    }
165}
166
167//Setup VIM: ex: et ts=4 enc=utf-8 :