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
66                    }
67            }
68             else {
69                    if($exists && !auth_quickaclcheck( $wikifn) ) {
70                     echo $this->getLang('perm');
71                    }
72             }
73
74           }
75    }
76
77    function get_toc($id) {
78        $this->retv = "";
79        $toc = p_get_metadata($id,'description tableofcontents');
80        if(!$toc) return "";
81        $current=0;
82        $start_level = 0;
83        $this->ulcount('open');
84
85         $up = $this->get_up_dir(pathinfo(wikiFN("$id:file")));
86         $this->retv .=  "<UL class='tocsel_li1'>$up\n";
87
88        foreach ($toc as $head) {
89            $level =  $this->format_item($head, $current,$id);
90            if($start_level==0) $start_level = $level;
91        }
92        if($start_level != $level)  {
93            $this->retv .= "</UL>\n";
94            $this->ulcount('closed');
95        }
96        $this->retv .=  "</UL>\n";
97        $this->ulcount('closed');
98        if($this->ul_open > $this->ul_closed) {
99        $this->retv .=  "</UL>\n";
100    }
101
102    }
103
104    function format_item($h, &$n,$id){
105            if($n==0) $n=$h['level'];
106
107            if($n < $h['level'] ) {
108              $this->ulcount('open');
109              $this->retv .= "<UL>\n";
110
111            }
112            else if ($n != $h['level']) {
113              $this->retv .= "</UL>\n";
114               $this->ulcount('closed');
115            }
116
117            $this->retv .=    '<li>' . $this->format_link($h['title'], $h['hid'],$id) . "</li>\n";
118            $n = $h['level'];
119            return $n;
120        }
121    function format_link($title,$anchor,$id) {
122        $link = "<a href ='". TOC_URL  . $id. '#'. $anchor."'>" . "$title</a>";
123        return $link;
124    }
125
126    function ulcount($which) {
127
128            if ($which == "open") {
129                if($this->ul_open> 0) $this->retv .="\n" .'<li class="ihidden">';
130                $this->ul_count++;
131                $this->ul_open++;
132            }
133            else if ($which == "closed") {
134                $this->ul_count --;
135                 if($this->ul_closed> 0) $this->retv .="</li>\n";
136                $this->ul_closed ++;
137            }
138    }
139
140    private function get_dir_list($dir, $namespace){
141        $retdir = "<UL>";
142        if(!empty($this->up)) $retdir .= $this->up;
143        $retfile = "";
144        $dir_ar = array();
145        $file_ar = array();
146
147         $dh = opendir($dir);
148         if(!$dh) return;
149         while (($file = readdir($dh)) !== false) {
150            if($file == '.' || $file == '..') continue;           # cur and upper dir
151            if(is_dir("$dir/$file")) {
152                $dir_ar[$file] = $this->handle_directory($file, $namespace);
153            }
154            else {
155                if(!preg_match("/\.txt$/",$file)|| preg_match("/^_/",$file) ) continue;  //exclude non .txt files and templates
156                $file_ar[$file] =  $this->handle_file($file, $namespace);
157            }
158        }
159        closedir($dh);
160        ksort($dir_ar);
161        ksort($file_ar);
162        foreach ($dir_ar as $key=>$val) {
163            $retdir .= $val;
164        }
165        foreach ($file_ar as $key=>$val) {
166            $retfile .= $val;
167        }
168        $ret = $retdir . $retfile  . "</UL>";
169        return $ret;
170    }
171
172    private function handle_directory($curdir, $namespace) {
173        return "<li><span  class='clickerdir  tocselb' onclick=\"tocsel_updatetoc('$namespace:$curdir:*');\">$namespace:$curdir:*</span></li>";
174    }
175
176    private function handle_file($file, $namespace) {
177        $file = preg_replace("/\.txt$/","", $file);
178        return "<li><span  class='clickerfile' onclick=\"tocsel_updatetoc('$namespace:$file');\">$namespace:$file</span></li>";
179    }
180
181    private function handle_up($namespace) {
182        if(empty($namespace))
183              $title = 'Root NS';
184         else  $title = $namespace;
185        $png = '<img title = "' . $title. '"src = "' . TOCSEL_IMGDIR.'up.png' . '" />';
186         return "<li class= 'tocsel_up'><span  class='clicker  tocselb' onclick=\"tocsel_updatetoc('$namespace:*');\">$png</span></li>  ";
187    }
188
189    private function get_up_dir($pathinf) {
190         $up = dirname($pathinf['dirname']);
191         $up = preg_replace("#.*?/data/pages#","",$up);
192        $up = str_replace('/', ':',  $up);
193        return $this-> handle_up($up);   // empty $up = root ns
194    }
195 }
196
197
198
199