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