1<?php
2/**
3 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
4 * @author     Myron Turner <turnermm02@shaw.ca>
5 *
6 */
7if(!defined('DOKU_INC')) die();
8
9if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
10require_once(DOKU_PLUGIN.'action.php');
11define ("TOC_URL", DOKU_BASE ."doku.php?id=");
12define ("TOCSEL_IMGDIR", DOKU_BASE . 'lib/plugins/tocselect/img/');
13
14class action_plugin_tocselect extends DokuWiki_Action_Plugin {
15 private $retv;
16 private $ul_count;
17 private $ul_open;
18 private $ul_closed;
19 private $up;
20    function register(Doku_Event_Handler $controller){
21       $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this,'_ajax_call');
22       $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this,'handle_started');
23    }
24
25    function handle_started(Doku_Event $event, $param) {
26             global $conf;
27            if($this->getConf('notoc')) {
28                 $conf['tocminheads'] = 0;
29            }
30
31    }
32    function _ajax_call(Doku_Event $event, $param) {
33
34            global $INPUT;
35
36           if ($event->data == 'tocselect') {
37             $event->stopPropagation();
38             $event->preventDefault();
39             $wikifn = rawurldecode($INPUT->str('seltoc_val'));
40             $regex = preg_quote(':*');
41              if(preg_match('/^(.*?)' . $regex . '\s*$/',$wikifn,$matches))
42              {
43                   $wikifn = $matches[1];
44                   $ns = getNS($wikifn . ':file');
45                   $pathinf = pathinfo(wikiFN($wikifn . ':file') );
46                   if($matches[1]) {
47                       $this->up =  $this->get_up_dir($pathinf );  //inserted in get_dir_list()
48                   }
49                   $list =  $this->get_dir_list($pathinf['dirname'], $ns);
50                    echo $list;
51                    return;
52              }
53              else   $file = wikiFN($wikifn) ;
54
55             $exists =  file_exists($file);
56             if($exists &&  auth_quickaclcheck( $wikifn) ) {
57                 setcookie('tocselect',$wikifn,0,DOKU_BASE);
58                $this->ul_count =  $this->ul_open = $this->ul_closed = 0;
59                $this->get_toc($wikifn);
60                 if($this->retv) {
61                   echo $this->retv;
62                }
63                 else {
64                     $up =  $this->get_up_dir(pathinfo("$file/file"));
65                     echo "<ul>$up";
66                     echo "<li><span class='ten__ptb'>" . $this->getLang('notoc') ." $wikifn</span></li></ul>";
67                    }
68            }
69             else {
70                    if($exists && !auth_quickaclcheck( $wikifn) ) {
71                     echo $this->getLang('perm');
72                    }
73             }
74
75           }
76    }
77
78    function get_toc($id) {
79        $this->retv = "";
80        $toc = p_get_metadata($id,'description tableofcontents');
81        if(!$toc) return "";
82        $current=0;
83        $start_level = 0;
84        $this->ulcount('open');
85
86         $up = $this->get_up_dir(pathinfo(wikiFN("$id:file")));
87         $this->retv .=  "<UL class='tocsel_li1'>$up\n";
88
89        foreach ($toc as $head) {
90            $level =  $this->format_item($head, $current,$id);
91            if($start_level==0) $start_level = $level;
92        }
93        if($start_level != $level)  {
94            $this->retv .= "</UL>\n";
95            $this->ulcount('closed');
96        }
97        $this->retv .=  "</UL>\n";
98        $this->ulcount('closed');
99        if($this->ul_open > $this->ul_closed) {
100        $this->retv .=  "</UL>\n";
101    }
102
103    }
104
105    function format_item($h, &$n,$id){
106            if($n==0) $n=$h['level'];
107
108            if($n < $h['level'] ) {
109              $this->ulcount('open');
110              $this->retv .= "<UL>\n";
111
112            }
113            else if ($n != $h['level']) {
114              $this->retv .= "</UL>\n";
115               $this->ulcount('closed');
116            }
117
118            $this->retv .=    '<li>' . $this->format_link($h['title'], $h['hid'],$id) . "</li>\n";
119            $n = $h['level'];
120            return $n;
121        }
122    function format_link($title,$anchor,$id) {
123        $link = "<a href ='". TOC_URL  . $id. '#'. $anchor."'>" . "$title</a>";
124        return $link;
125    }
126
127    function ulcount($which) {
128
129            if ($which == "open") {
130                if($this->ul_open> 0) $this->retv .="\n" .'<li class="ihidden">';
131                $this->ul_count++;
132                $this->ul_open++;
133            }
134            else if ($which == "closed") {
135                $this->ul_count --;
136                 if($this->ul_closed> 0) $this->retv .="</li>\n";
137                $this->ul_closed ++;
138            }
139    }
140
141    private function get_dir_list($dir, $namespace){
142        $retdir = "<UL>";
143        if(!empty($this->up)) $retdir .= $this->up;
144        $retfile = "";
145        $dir_ar = array();
146        $file_ar = array();
147
148         $dh = opendir($dir);
149         if(!$dh) return;
150         while (($file = readdir($dh)) !== false) {
151            if($file == '.' || $file == '..') continue;           # cur and upper dir
152            if(is_dir("$dir/$file")) {
153                $dir_ar[$file] = $this->handle_directory($file, $namespace);
154            }
155            else {
156                if(!preg_match("/\.txt$/",$file)|| preg_match("/^_/",$file) ) continue;  //exclude non .txt files and templates
157                $file_ar[$file] =  $this->handle_file($file, $namespace);
158            }
159        }
160        closedir($dh);
161        ksort($dir_ar);
162        ksort($file_ar);
163        foreach ($dir_ar as $key=>$val) {
164            $retdir .= $val;
165        }
166        foreach ($file_ar as $key=>$val) {
167            $retfile .= $val;
168        }
169        $ret = $retdir . $retfile  . "</UL>";
170        return $ret;
171    }
172
173    private function handle_directory($curdir, $namespace) {
174        return "<li><span  class='clickerdir  tocselb' onclick=\"tocsel_updatetoc('$namespace:$curdir:*');\">$namespace:$curdir:*</span></li>";
175    }
176
177    private function handle_file($file, $namespace) {
178        $file = preg_replace("/\.txt$/","", $file);
179        return "<li><span  class='clickerfile' onclick=\"tocsel_updatetoc('$namespace:$file');\">$namespace:$file</span></li>";
180    }
181
182    private function handle_up($namespace) {
183        if(empty($namespace))
184              $title = 'Root NS';
185         else  $title = $namespace;
186        $png = '<img title = "' . $title. '"src = "' . TOCSEL_IMGDIR.'up.png' . '" />';
187         return "<li class= 'tocsel_up'><span  class='clicker  tocselb' onclick=\"tocsel_updatetoc('$namespace:*');\">$png</span></li>  ";
188    }
189
190    private function get_up_dir($pathinf) {
191         $up = dirname($pathinf['dirname']);
192         $up = preg_replace("#.*?/data/pages#","",$up);
193        $up = str_replace('/', ':',  $up);
194        return $this-> handle_up($up);   // empty $up = root ns
195    }
196 }
197
198
199
200