1<?php
2
3use dokuwiki\Extension\SyntaxPlugin;
4use dokuwiki\plugin\filelist\Crawler;
5use dokuwiki\plugin\filelist\Output;
6use dokuwiki\plugin\filelist\Path;
7
8/**
9 * Filelist Plugin: Lists files matching a given glob pattern.
10 *
11 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
12 * @author     Gina Haeussge <osd@foosel.net>
13 */
14class syntax_plugin_filelist extends SyntaxPlugin
15{
16    /** @inheritdoc */
17    public function getType()
18    {
19        return 'substition';
20    }
21
22    /** @inheritdoc */
23    public function getPType()
24    {
25        return 'block';
26    }
27
28    /** @inheritdoc */
29    public function getSort()
30    {
31        return 222;
32    }
33
34    /** @inheritdoc */
35    public function connectTo($mode)
36    {
37        $this->Lexer->addSpecialPattern('\{\{filelist>.+?\}\}', $mode, 'plugin_filelist');
38    }
39
40    /** @inheritdoc */
41    public function handle($match, $state, $pos, Doku_Handler $handler)
42    {
43        global $INPUT;
44
45        // do not allow the syntax in discussion plugin comments
46        if (!$this->getConf('allow_in_comments') && $INPUT->has('comment')) {
47            return false;
48        }
49
50        $match = substr($match, strlen('{{filelist>'), -2);
51        [$path, $flags] = explode('&', $match, 2);
52
53        // load default config options
54        $flags = $this->getConf('defaults') . '&' . $flags;
55        $flags = explode('&', $flags);
56
57        $params = [
58            'sort' => 'name',
59            'order' => 'asc',
60            'style' => 'list',
61            'tableheader' => 0,
62            'recursive' => 0,
63            'titlefile' => '_title.txt',
64            'cache' => 0,
65            'randlinks' => 0,
66            'showsize' => 0,
67            'showdate' => 0,
68            'listsep' => ', ',
69        ];
70        foreach ($flags as $flag) {
71            [$name, $value] = sexplode('=', $flag, 2, '');
72            $params[trim($name)] = trim(trim($value), '"'); // quotes can be use to keep whitespace
73        }
74
75        // separate path and pattern
76        $path = Path::cleanPath($path, false);
77        $parts = explode('/', $path);
78        $pattern = array_pop($parts);
79        $base = implode('/', $parts) . '/';
80
81        return [$base, $pattern, $params];
82    }
83
84    /**
85     * Create output
86     */
87    public function render($format, Doku_Renderer $renderer, $data)
88    {
89        [$base, $pattern, $params] = $data;
90
91        if ($format != 'xhtml' && $format != 'odt') {
92            return false;
93        }
94
95        // disable caching
96        if ($params['cache'] === 0) {
97            $renderer->nocache();
98        }
99
100
101        try {
102            $pathHelper = new Path($this->getConf('paths'));
103            $pathInfo = $pathHelper->getPathInfo($base);
104        } catch (Exception $e) {
105            $renderer->cdata('[n/a: ' . $this->getLang('error_outsidejail') . ']');
106            return true;
107        }
108
109        $crawler = new Crawler($this->getConf('extensions'));
110        $crawler->setSortBy($params['sort']);
111        $crawler->setSortReverse($params['order'] === 'desc');
112
113        $result = $crawler->crawl(
114            $pathInfo['root'],
115            $pathInfo['local'],
116            $pattern,
117            $params['recursive'],
118            $params['titlefile']
119        );
120
121        // if we got nothing back, display a message
122        if ($result == []) {
123            $renderer->cdata('[n/a: ' . $this->getLang('error_nomatch') . ']');
124            return true;
125        }
126
127        $output = new Output($renderer, $pathInfo['root'], $pathInfo['web'], $result);
128
129        switch ($params['style']) {
130            case 'list':
131            case 'olist':
132                $output->renderAsList($params);
133                break;
134            case 'table':
135                $output->renderAsTable($params);
136                break;
137        }
138        return true;
139    }
140}
141