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