1<?php
2
3/**
4 * Info Plugin: Displays information about various DokuWiki internals
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Andreas Gohr <andi@splitbrain.org>
8 * @author     Esther Brunner <wikidesign@gmail.com>
9 */
10class syntax_plugin_info extends DokuWiki_Syntax_Plugin
11{
12
13    /**
14     * What kind of syntax are we?
15     */
16    public function getType()
17    {
18        return 'substition';
19    }
20
21    /**
22     * What about paragraphs?
23     */
24    public function getPType()
25    {
26        return 'block';
27    }
28
29    /**
30     * Where to sort in?
31     */
32    public function getSort()
33    {
34        return 155;
35    }
36
37    /**
38     * Connect pattern to lexer
39     */
40    public function connectTo($mode)
41    {
42        $this->Lexer->addSpecialPattern('~~INFO:\w+~~', $mode, 'plugin_info');
43    }
44
45    /**
46     * Handle the match
47     *
48     * @param string $match The text matched by the patterns
49     * @param int $state The lexer state for the match
50     * @param int $pos The character position of the matched text
51     * @param Doku_Handler $handler The Doku_Handler object
52     * @return  array Return an array with all data you want to use in render
53     */
54    public function handle($match, $state, $pos, Doku_Handler $handler)
55    {
56        $match = substr($match, 7, -2); //strip ~~INFO: from start and ~~ from end
57        return array(strtolower($match));
58    }
59
60    /**
61     * Create output
62     *
63     * @param string $format string     output format being rendered
64     * @param Doku_Renderer $renderer the current renderer object
65     * @param array $data data created by handler()
66     * @return  boolean                 rendered correctly?
67     */
68    public function render($format, Doku_Renderer $renderer, $data)
69    {
70        if ($format == 'xhtml') {
71            /** @var Doku_Renderer_xhtml $renderer */
72            //handle various info stuff
73            switch ($data[0]) {
74                case 'syntaxmodes':
75                    $renderer->doc .= $this->renderSyntaxModes();
76                    break;
77                case 'syntaxtypes':
78                    $renderer->doc .= $this->renderSyntaxTypes();
79                    break;
80                case 'syntaxplugins':
81                    $this->renderPlugins('syntax', $renderer);
82                    break;
83                case 'adminplugins':
84                    $this->renderPlugins('admin', $renderer);
85                    break;
86                case 'actionplugins':
87                    $this->renderPlugins('action', $renderer);
88                    break;
89                case 'rendererplugins':
90                    $this->renderPlugins('renderer', $renderer);
91                    break;
92                case 'helperplugins':
93                    $this->renderPlugins('helper', $renderer);
94                    break;
95                case 'authplugins':
96                    $this->renderPlugins('auth', $renderer);
97                    break;
98                case 'remoteplugins':
99                    $this->renderPlugins('remote', $renderer);
100                    break;
101                case 'helpermethods':
102                    $this->renderHelperMethods($renderer);
103                    break;
104                case 'hooks':
105                    $this->renderHooks($renderer);
106                    break;
107                case 'datetime':
108                    $renderer->doc .= date('r');
109                    break;
110                default:
111                    $renderer->doc .= "no info about " . htmlspecialchars($data[0]);
112            }
113            return true;
114        }
115        return false;
116    }
117
118    /**
119     * list all installed plugins
120     *
121     * uses some of the original renderer methods
122     *
123     * @param string $type
124     * @param Doku_Renderer $renderer
125     */
126    protected function renderPlugins($type, Doku_Renderer $renderer)
127    {
128        global $lang;
129        $plugins = plugin_list($type);
130        $plginfo = array();
131
132        // remove subparts
133        foreach ($plugins as $p) {
134            if (!$po = plugin_load($type, $p)) continue;
135            list($name,/* $part */) = explode('_', $p, 2);
136            $plginfo[$name] = $po->getInfo();
137        }
138
139        // list them
140        $renderer->listu_open();
141        foreach ($plginfo as $info) {
142            $renderer->listitem_open(1);
143            $renderer->listcontent_open();
144            $renderer->externallink($info['url'], $info['name']);
145            $renderer->cdata(' ');
146            $renderer->emphasis_open();
147            $renderer->cdata($info['date']);
148            $renderer->emphasis_close();
149            $renderer->cdata(' ' . $lang['by'] . ' ');
150            $renderer->emaillink($info['email'], $info['author']);
151            $renderer->linebreak();
152            $renderer->cdata($info['desc']);
153            $renderer->listcontent_close();
154            $renderer->listitem_close();
155        }
156        $renderer->listu_close();
157    }
158
159    /**
160     * list all installed plugins
161     *
162     * uses some of the original renderer methods
163     *
164     * @param Doku_Renderer_xhtml $renderer
165     */
166    protected function renderHelperMethods(Doku_Renderer_xhtml $renderer)
167    {
168        $plugins = plugin_list('helper');
169        foreach ($plugins as $p) {
170            if (!$po = plugin_load('helper', $p)) continue;
171
172            if (!method_exists($po, 'getMethods')) continue;
173            $methods = $po->getMethods();
174            $info = $po->getInfo();
175
176            $hid = $this->addToToc($info['name'], 2, $renderer);
177            $doc = '<h2><a name="' . $hid . '" id="' . $hid . '">' . hsc($info['name']) . '</a></h2>';
178            $doc .= '<div class="level2">';
179            $doc .= '<p>' . strtr(hsc($info['desc']), array("\n" => "<br />")) . '</p>';
180            $doc .= '<pre class="code">$' . $p . " = plugin_load('helper', '" . $p . "');</pre>";
181            $doc .= '</div>';
182            foreach ($methods as $method) {
183                $title = '$' . $p . '->' . $method['name'] . '()';
184                $hid = $this->addToToc($title, 3, $renderer);
185                $doc .= '<h3><a name="' . $hid . '" id="' . $hid . '">' . hsc($title) . '</a></h3>';
186                $doc .= '<div class="level3">';
187                $doc .= '<div class="table"><table class="inline"><tbody>';
188                $doc .= '<tr><th>Description</th><td colspan="2">' . $method['desc'] .
189                    '</td></tr>';
190                if ($method['params']) {
191                    $c = count($method['params']);
192                    $doc .= '<tr><th rowspan="' . $c . '">Parameters</th><td>';
193                    $params = array();
194                    foreach ($method['params'] as $desc => $type) {
195                        $params[] = hsc($desc) . '</td><td>' . hsc($type);
196                    }
197                    $doc .= join('</td></tr><tr><td>', $params) . '</td></tr>';
198                }
199                if ($method['return']) {
200                    $doc .= '<tr><th>Return value</th><td>' . hsc(key($method['return'])) .
201                        '</td><td>' . hsc(current($method['return'])) . '</td></tr>';
202                }
203                $doc .= '</tbody></table></div>';
204                $doc .= '</div>';
205            }
206            unset($po);
207
208            $renderer->doc .= $doc;
209        }
210    }
211
212    /**
213     * lists all known syntax types and their registered modes
214     *
215     * @return string
216     */
217    protected function renderSyntaxTypes()
218    {
219        global $PARSER_MODES;
220        $doc = '';
221
222        $doc .= '<div class="table"><table class="inline"><tbody>';
223        foreach ($PARSER_MODES as $mode => $modes) {
224            $doc .= '<tr>';
225            $doc .= '<td class="leftalign">';
226            $doc .= $mode;
227            $doc .= '</td>';
228            $doc .= '<td class="leftalign">';
229            $doc .= join(', ', $modes);
230            $doc .= '</td>';
231            $doc .= '</tr>';
232        }
233        $doc .= '</tbody></table></div>';
234        return $doc;
235    }
236
237    /**
238     * lists all known syntax modes and their sorting value
239     *
240     * @return string
241     */
242    protected function renderSyntaxModes()
243    {
244        $modes = p_get_parsermodes();
245
246        $compactmodes = array();
247        foreach ($modes as $mode) {
248            $compactmodes[$mode['sort']][] = $mode['mode'];
249        }
250        $doc = '';
251        $doc .= '<div class="table"><table class="inline"><tbody>';
252
253        foreach ($compactmodes as $sort => $modes) {
254            $rowspan = '';
255            if (count($modes) > 1) {
256                $rowspan = ' rowspan="' . count($modes) . '"';
257            }
258
259            foreach ($modes as $index => $mode) {
260                $doc .= '<tr>';
261                $doc .= '<td class="leftalign">';
262                $doc .= $mode;
263                $doc .= '</td>';
264
265                if ($index === 0) {
266                    $doc .= '<td class="rightalign" ' . $rowspan . '>';
267                    $doc .= $sort;
268                    $doc .= '</td>';
269                }
270                $doc .= '</tr>';
271            }
272        }
273
274        $doc .= '</tbody></table></div>';
275        return $doc;
276    }
277
278    /**
279     * Render all currently registered event handlers
280     *
281     * @param Doku_Renderer $renderer
282     */
283    protected function renderHooks(Doku_Renderer $renderer)
284    {
285        global $EVENT_HANDLER;
286
287        $list = $EVENT_HANDLER->getEventHandlers();
288        ksort($list);
289
290        $renderer->listu_open();
291        foreach ($list as $event => $handlers) {
292            $renderer->listitem_open(1);
293            $renderer->listcontent_open();
294            $renderer->cdata($event);
295            $renderer->listcontent_close();
296
297            $renderer->listo_open();
298            foreach ($handlers as $sequence) {
299                foreach ($sequence as $handler) {
300                    $renderer->listitem_open(2);
301                    $renderer->listcontent_open();
302                    $renderer->cdata(get_class($handler[0]) . '::' . $handler[1] . '()');
303                    $renderer->listcontent_close();
304                    $renderer->listitem_close();
305                }
306            }
307            $renderer->listo_close();
308            $renderer->listitem_close();
309        }
310        $renderer->listu_close();
311    }
312
313    /**
314     * Adds a TOC item
315     *
316     * @param string $text
317     * @param int $level
318     * @param Doku_Renderer_xhtml $renderer
319     * @return string
320     */
321    protected function addToToc($text, $level, Doku_Renderer_xhtml $renderer)
322    {
323        global $conf;
324
325        $hid = '';
326        if (($level >= $conf['toptoclevel']) && ($level <= $conf['maxtoclevel'])) {
327            $hid = $renderer->_headerToLink($text, true);
328            $renderer->toc[] = array(
329                'hid' => $hid,
330                'title' => $text,
331                'type' => 'ul',
332                'level' => $level - $conf['toptoclevel'] + 1,
333            );
334        }
335        return $hid;
336    }
337}
338