1<?php
2/**
3 * Plugin Now: Inserts a timestamp.
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     David Peplow <david@peplow.net>
7 */
8
9// must be run within DokuWiki
10if(!defined('DOKU_INC')) die();
11
12
13class syntax_plugin_simplewikipagetree extends DokuWiki_Syntax_Plugin {
14
15    private $startFile = false;
16
17    public function getType() { return 'substition'; }
18    public function getSort() { return 32; }
19
20    public function connectTo($mode) {
21        $this->Lexer->addSpecialPattern('<simplewiki-pagetree>',$mode,'plugin_simplewikipagetree');
22    }
23
24    public function handle($match, $state, $pos, Doku_Handler $handler) {
25        return array($match, $state, $pos);
26    }
27
28    public function render($mode, Doku_Renderer $renderer, $data) {
29    // $data is what the function handle return'ed.
30        if($mode == 'xhtml'){
31            /** @var Doku_Renderer_xhtml $renderer */
32            $renderer->doc = '';
33            $renderer->doc .= '<style>';
34            $renderer->doc .= '.simplewiki-pagetree .open > .icon { background-image:url('.DOKU_REL.'lib/plugins/simplewikipagetree/img/chevron-down.svg);}';
35            $renderer->doc .= '.simplewiki-pagetree .closed > .icon { background-image:url('.DOKU_REL.'lib/plugins/simplewikipagetree/img/chevron-right.svg);}';
36            $renderer->doc .= '.simplewiki-pagetree .file > .icon { background-image:url('.DOKU_REL.'lib/plugins/simplewikipagetree/img/bullet.svg);}';
37            $renderer->doc .= '</style>';
38
39            $renderer->doc .= $this::renderPageTree('data/pages',true);
40            return true;
41        }
42        return false;
43    }
44
45    private function renderPageTree($path, $root=false){
46        global $INFO;
47        $out .= '<ul';
48        if($root == true){
49            $out .= ' class="simplewiki-pagetree" ';
50        }
51        $out .= '>';
52        $files = scandir($path);
53        foreach($files as $file){
54
55            // only if start page should be displayed
56            if($file == '.' or $file == '..' or ($file == 'start.txt' && $this->startFile == true)  or $file == 'sidebar.txt'){
57                continue;
58            }
59
60
61
62            $filepath = $path.'/'.$file;
63
64            // skip if this is a text-file and a folder with the same name exists
65            if($this->startFile == false){
66                $path_parts = pathinfo($filepath);
67                if(is_dir($path_parts['dirname'].'/'.$path_parts['filename']) && $path_parts['dirname'] && $path_parts['extension'] == 'txt'){
68                    continue;
69                }
70            }
71
72            $id = $this->getID($filepath);
73
74            // skip start-page
75            if($id == 'start'){
76                continue;
77            }
78
79            // skip entry if user has no view permissions
80            //// Todo: Display file instead of folders if there are no files with view persmission inside folder
81            //// Todo: Fix problem with hirarchies
82            $info = basicinfo($id);
83            if($info['perm'] == 0){
84                continue;
85            }
86
87
88            if(is_dir($filepath)){
89                if($id == substr($INFO['id'],0,strlen($id))){
90                    $out .= '<li class="open">';
91                }else{
92                    $out .= '<li class="closed">';
93                }
94
95            }else{
96                $out .= '<li class="file">';
97            }
98            $out .= '<div class="icon"></div>';
99
100            $activeInjection = '';
101            if($this->isActive($filepath)){
102                $activeInjection = ' class="active" ';
103            }
104
105
106            $out .= '<a href="'.$this->getURL($filepath).'"'.$activeInjection.'>';
107            $out .= $this->getTitle($filepath);
108            $out .= '</a>';
109            if(is_dir($filepath)){
110                $out .= $this->renderPageTree($filepath);
111            }
112
113            $out .= '</li>';
114        }
115        $out .= '</ul>';
116        return $out;
117    }
118
119    private function getID($filepath){
120        $id = str_replace('data/pages/','',$filepath);
121        $id = str_replace('/',':',$id);
122        $id = str_replace('.txt','',$id);
123        return $id;
124    }
125
126    private function getTitle($filepath){
127        $id = $this->getID($filepath);
128
129        // only if start page should be displayed
130        if($this->startFile == true){
131            if(is_dir($filepath)){
132                $id .= ':start';
133            }
134        }
135
136        $title = p_get_first_heading($id);
137
138        if($title == ''){
139            $title = end(explode(':',$id));
140
141            // return last part of id without "start" if it is a dir
142            if(is_dir($filepath)){
143                $title = end(explode(':',$this->getID($filepath)));
144            }
145
146        }
147
148        return $title;
149    }
150
151    private function getURL($filepath){
152        global $conf;
153        $url = $this->getID($filepath);
154
155        // only if start page should be displayed
156        if($this->startFile == true){
157            if(is_dir($filepath)){
158                $url .= ':start';
159            }
160        }
161
162        if($conf['useslash'] == 1){
163            $url = str_replace(":","/",$url);
164        }
165        $url = DOKU_REL.$url;
166        return $url;
167    }
168
169    private function isActive($filepath){
170        global $INFO;
171
172        $id = $this->getID($filepath);
173
174        if(is_dir($filepath)){
175            $id .= ':start';
176        }
177
178        if($id == $INFO['id'] ){
179            return true;
180        }
181
182        return false;
183    }
184}