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