1<?php
2/**
3 *  Add smart navigation capability to dokuwiki
4 *
5 *  Roland Hellebart's tree plugin ( his http://wiki.splitbrain.org/plugin:tree )
6 *  was used as a base for this.
7 *
8 *  Documentation is located at http://wiki.splitbrain.org/plugin:navilevel
9 *
10 *  @license    GNU_GPL_v2
11 *  @author     Thanos Massias
12 */
13
14if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
15if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
16require_once(DOKU_PLUGIN.'syntax.php');
17
18/**
19 *  All DokuWiki plugins to extend the parser/rendering mechanism
20 *  need to inherit from this class
21 */
22 class syntax_plugin_navilevel extends DokuWiki_Syntax_Plugin {
23
24
25    function getInfo(){
26        return array(
27            'author' => 'Thanos Massias',
28            'email'  => 'thanos.massias@gmail.com',
29            'date'   => '2007-06-14',
30            'name'   => 'navilevel Plugin',
31            'desc'   => 'Add smart Navigation Capability',
32            'url'    => 'http://www.acsys.gr/plugins/navilevel/',
33        );
34    }
35
36    /**
37     *  What kind of syntax are we?
38     */
39    function getType(){
40        return 'protected';
41    }
42
43    /**
44     *  What kind of syntax do we allow (optional)
45     */
46    function getAllowedTypes() {
47        return array('protected');
48    }
49
50    /**
51     *  What about paragraphs? (optional)
52     */
53    function getPType(){
54        return 'block';
55    }
56
57    /**
58     *  Where to sort in?
59     */
60    function getSort(){
61        return 203;
62    }
63
64    /**
65     *  Connect pattern to lexer
66     */
67    function connectTo($mode) {
68        $this->Lexer->addEntryPattern('<navilevel.*?>(?=.*?</navilevel>)',$mode,'plugin_navilevel');
69    }
70
71    function postConnect() {
72        $this->Lexer->addExitPattern('</navilevel>','plugin_navilevel');
73    }
74
75    /**
76     *  Handle the match
77     */
78    function handle($match, $state, $pos, &$handler){
79        switch ($state) {
80          case DOKU_LEXER_ENTER :
81            break;
82          case DOKU_LEXER_MATCHED :
83            break;
84          case DOKU_LEXER_UNMATCHED :
85            break;
86          case DOKU_LEXER_EXIT :
87            break;
88          case DOKU_LEXER_SPECIAL :
89            break;
90        }
91        return array($match, $state);
92    }
93
94    /**
95     *  Create output
96     */
97    function render($mode, &$renderer, $data) {
98        // You may have to configure $rellevel to suite your site
99        //
100        // $lowlevel = 1;  --> sites not based on per-namespace start pages (default)
101        // $lowlevel = 2;  --> sites     based on per-namespace start pages
102        //
103        $lowlevel = 1;
104
105        global $ID;
106        global $ullevellast;
107        $linklineID = ':'.$ID;
108        //  In case you want the plugin to work correctly within a sidebar add the
109        //  following two lines in '/dokuwiki_home/lib/tpl/template_name/main.php':
110        //  ---------------------
111        //  global $PPID;
112        //  $PPID = $ID;
113        //  ---------------------
114        global $PPID;
115        if ('X'.$PPID != 'X'){
116            if ($ID != $PPID){
117                $linklineID = ':'.$PPID;
118            }
119        }
120        $partsID = explode(':', $linklineID);
121        $countpartsID = count($partsID);
122
123        $showall = 0;
124        if (($countpartsID == 2) && ($partsID[1] == 'sitemap')){
125          $showall = 1;
126        }
127
128        if($mode == 'xhtml'){
129            switch ($data[1]) {
130                case DOKU_LEXER_ENTER :
131                  $renderer->doc .= "\n";
132                  break;
133
134                case DOKU_LEXER_MATCHED :
135                  break;
136
137                case DOKU_LEXER_UNMATCHED :
138                    $content = $data[0];
139
140                    //  clean up the input data
141                    //  clear any trailing or leading empty lines from the data set
142                    $content = preg_replace("/[\r\n]*$/","",$content);
143                    $content = preg_replace("/^\s*[\r\n]*/","",$content);
144
145                    //  Not sure if PHP handles the DOS \r\n or Mac \r, so being paranoid
146                    //  and converting them if they exist to \n
147                    $content = preg_replace("/\r\n/","\n",$content);
148                    $content = preg_replace("/\r/","\n",$content);
149                    $result = $this->tree_explode_node($content);
150
151                    $ullevellast = 0;
152
153                    foreach ($result as $input){
154                        $arrinput = explode('|', $input);
155                        $linkline = $arrinput[0];
156                        $linkline = trim($linkline);
157                        $linktext_before = $arrinput[1];
158                        $linktext_before = trim($linktext_before);
159                        $linkname = $arrinput[2];
160                        $linkname = trim($linkname);
161                        $linktext_after = $arrinput[3];
162                        $linktext_after = trim($linktext_after);
163                        if (strlen($linkline) > 0) {
164                            $linkline = cleanID($linkline);
165                            if (substr($linkline,0,1) != ':'){
166                                $linkline = ':'.$linkline;
167                            }
168
169                            $parts = explode(':', $linkline);
170                            $countparts = count($parts);
171
172                            $listlink = 0;
173                            //  low level links
174                            if ($countparts < (2 + $lowlevel)){
175                                $listlink = 1;
176                            }else{
177                                //  children, yes - grandchildren and beyond, no
178                                if ($countparts <= $countpartsID + 1){
179                                    $listlink = 1;
180                                    $tmppathID = '';
181                                    $tmppath   = '';
182                                    $i = 0;
183                                    foreach ($parts as $part){
184                                        if (($i > 0) && ($i < $countparts - 2)){
185                                            if ('X'.$partsID[$i] != 'X') {
186                                                $tmppathID .= ':'.$partsID[$i];
187                                                $tmppath   .= ':'.$parts[$i];
188                                                if ($tmppathID !== $tmppath){
189                                                    $listlink = 0;
190                                                }
191                                            }
192                                        }
193                                        $i++;
194                                    }
195                                }
196                            }
197
198                            if ($listlink || $showall){
199                                $ullevel = $countparts - 1;
200                                if ($ullevel == $ullevellast){
201                                    $renderer->doc .= "\n</li>";
202                                }
203                                if ($ullevel > $ullevellast){
204                                    $renderer->doc .= "\n<ul>";
205                                }
206                                if ($ullevel < $ullevellast){
207                                    for ($j = 0; $j < ($ullevellast - $ullevel); $j++){
208                                        $renderer->doc .= "\n</li>\n</ul>";
209                                    }
210                                    $renderer->doc .= "\n</li>";
211                                }
212                                $ullevellast = $ullevel;
213                                $renderer->doc .= "\n".'<li class="level'.$ullevel.'"><div class="li"> ';
214                                if (strlen($linktext_before) > 0) {
215                                    $renderer->doc .= $linktext_before.' ';
216                                }
217                                if (strlen($linkname) > 0) {
218                                    $renderer->doc .= $renderer->internallink($linkline,$linkname);
219                                }else{
220                                    $renderer->doc .= $renderer->internallink($linkline);
221                                }
222                                if (strlen($linktext_after) > 0) {
223                                    $renderer->doc .= ' '.$linktext_after;
224                                }
225                                $renderer->doc .= "</div>";
226                            }else{
227                                $renderer->doc .= "";
228                            }
229                        }
230                    }
231                    break;
232
233                case DOKU_LEXER_EXIT :
234                    $ullevel = 1;
235                    if ($ullevel == $ullevellast){
236                        $renderer->doc .= "\n</li>";
237                    }
238                    if ($ullevel > $ullevellast){
239                        $renderer->doc .= "\n<ul>";
240                    }
241                    if ($ullevel < $ullevellast){
242                        for ($j = 0; $j < ($ullevellast - $ullevel); $j++) {
243                            $renderer->doc .= "\n</li>\n</ul>";
244                        }
245                        $renderer->doc .= "\n</li>";
246                    }
247                    $renderer->doc .= "\n</ul>";
248                    break;
249
250                case DOKU_LEXER_SPECIAL :
251                    break;
252            }
253            return false;
254        }
255
256        // unsupported $mode
257        return false;
258    }
259
260    function tree_explode_node(&$str) {
261        $len = strlen($str) + 1;
262        $inside = false;
263        $word = '';
264        for ($i = 0; $i < $len; ++$i) {
265            $next = $i+1;
266            if ($str[$i] == "\n") {
267                $out[] = $word;
268                $word = '';
269            } elseif ($next == $len) {
270                $out[] = $word;
271                $word = '';
272            } else {
273                $word .= $str[$i];
274            }
275        }
276        $str = substr($str, $next);
277        $out[] = $word;
278        return $out;
279    }
280}
281
282//Setup VIM: ex: et ts=4 enc=utf-8 :
283?>
284