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 switch ($data[0]) { 76 case 'syntaxmodes': 77 $renderer->doc .= $this->renderSyntaxModes(); 78 break; 79 case 'syntaxtypes': 80 $renderer->doc .= $this->renderSyntaxTypes(); 81 break; 82 case 'syntaxplugins': 83 $this->renderPlugins('syntax', $renderer); 84 break; 85 case 'adminplugins': 86 $this->renderPlugins('admin', $renderer); 87 break; 88 case 'actionplugins': 89 $this->renderPlugins('action', $renderer); 90 break; 91 case 'rendererplugins': 92 $this->renderPlugins('renderer', $renderer); 93 break; 94 case 'helperplugins': 95 $this->renderPlugins('helper', $renderer); 96 break; 97 case 'authplugins': 98 $this->renderPlugins('auth', $renderer); 99 break; 100 case 'remoteplugins': 101 $this->renderPlugins('remote', $renderer); 102 break; 103 case 'helpermethods': 104 $this->renderHelperMethods($renderer); 105 break; 106 case 'hooks': 107 $this->renderHooks($renderer); 108 break; 109 case 'datetime': 110 $renderer->doc .= date('r'); 111 break; 112 default: 113 $renderer->doc .= "no info about " . htmlspecialchars($data[0]); 114 } 115 return true; 116 } 117 return false; 118 } 119 120 /** 121 * list all installed plugins 122 * 123 * uses some of the original renderer methods 124 * 125 * @param string $type 126 * @param Doku_Renderer $renderer 127 */ 128 protected function renderPlugins($type, Doku_Renderer $renderer) 129 { 130 global $lang; 131 $plugins = plugin_list($type); 132 $plginfo = []; 133 134 // remove subparts 135 foreach ($plugins as $p) { 136 $po = plugin_load($type, $p); 137 if (! $po instanceof PluginInterface) continue; 138 [$name, /* part */] = explode('_', $p, 2); 139 $plginfo[$name] = $po->getInfo(); 140 } 141 142 // list them 143 $renderer->listu_open(); 144 foreach ($plginfo as $info) { 145 $renderer->listitem_open(1); 146 $renderer->listcontent_open(); 147 $renderer->externallink($info['url'], $info['name']); 148 $renderer->cdata(' '); 149 $renderer->emphasis_open(); 150 $renderer->cdata($info['date']); 151 $renderer->emphasis_close(); 152 $renderer->cdata(' ' . $lang['by'] . ' '); 153 $renderer->emaillink($info['email'], $info['author']); 154 $renderer->linebreak(); 155 $renderer->cdata($info['desc']); 156 $renderer->listcontent_close(); 157 $renderer->listitem_close(); 158 } 159 $renderer->listu_close(); 160 } 161 162 /** 163 * list all installed plugins 164 * 165 * uses some of the original renderer methods 166 * 167 * @param Doku_Renderer_xhtml $renderer 168 */ 169 protected function renderHelperMethods(Doku_Renderer_xhtml $renderer) 170 { 171 $plugins = plugin_list('helper'); 172 foreach ($plugins as $p) { 173 $po = plugin_load('helper', $p); 174 if (!$po instanceof PluginInterface) continue; 175 176 if (!method_exists($po, 'getMethods')) continue; 177 $methods = $po->getMethods(); 178 $info = $po->getInfo(); 179 180 $hid = $this->addToToc($info['name'], 2, $renderer); 181 $doc = '<h2><a name="' . $hid . '" id="' . $hid . '">' . hsc($info['name']) . '</a></h2>'; 182 $doc .= '<div class="level2">'; 183 $doc .= '<p>' . strtr(hsc($info['desc']), ["\n" => "<br />"]) . '</p>'; 184 $doc .= '<pre class="code">$' . $p . " = plugin_load('helper', '" . $p . "');</pre>"; 185 $doc .= '</div>'; 186 foreach ($methods as $method) { 187 $title = '$' . $p . '->' . $method['name'] . '()'; 188 $hid = $this->addToToc($title, 3, $renderer); 189 $doc .= '<h3><a name="' . $hid . '" id="' . $hid . '">' . hsc($title) . '</a></h3>'; 190 $doc .= '<div class="level3">'; 191 $doc .= '<div class="table"><table class="inline"><tbody>'; 192 $doc .= '<tr><th>Description</th><td colspan="2">' . $method['desc'] . 193 '</td></tr>'; 194 if ($method['params']) { 195 $c = count($method['params']); 196 $doc .= '<tr><th rowspan="' . $c . '">Parameters</th><td>'; 197 $params = []; 198 foreach ($method['params'] as $desc => $type) { 199 $params[] = hsc($desc) . '</td><td>' . hsc($type); 200 } 201 $doc .= implode('</td></tr><tr><td>', $params) . '</td></tr>'; 202 } 203 if ($method['return']) { 204 $doc .= '<tr><th>Return value</th><td>' . hsc(key($method['return'])) . 205 '</td><td>' . hsc(current($method['return'])) . '</td></tr>'; 206 } 207 $doc .= '</tbody></table></div>'; 208 $doc .= '</div>'; 209 } 210 unset($po); 211 212 $renderer->doc .= $doc; 213 } 214 } 215 216 /** 217 * lists all known syntax types and their registered modes 218 * 219 * @return string 220 */ 221 protected function renderSyntaxTypes() 222 { 223 global $PARSER_MODES; 224 $doc = ''; 225 226 $doc .= '<div class="table"><table class="inline"><tbody>'; 227 foreach ($PARSER_MODES as $mode => $modes) { 228 $doc .= '<tr>'; 229 $doc .= '<td class="leftalign">'; 230 $doc .= $mode; 231 $doc .= '</td>'; 232 $doc .= '<td class="leftalign">'; 233 $doc .= implode(', ', $modes); 234 $doc .= '</td>'; 235 $doc .= '</tr>'; 236 } 237 $doc .= '</tbody></table></div>'; 238 return $doc; 239 } 240 241 /** 242 * lists all known syntax modes and their sorting value 243 * 244 * @return string 245 */ 246 protected function renderSyntaxModes() 247 { 248 $modes = p_get_parsermodes(); 249 250 $compactmodes = []; 251 foreach ($modes as $mode) { 252 $compactmodes[$mode['sort']][] = $mode['mode']; 253 } 254 $doc = ''; 255 $doc .= '<div class="table"><table class="inline"><tbody>'; 256 257 foreach ($compactmodes as $sort => $modes) { 258 $rowspan = ''; 259 if (count($modes) > 1) { 260 $rowspan = ' rowspan="' . count($modes) . '"'; 261 } 262 263 foreach ($modes as $index => $mode) { 264 $doc .= '<tr>'; 265 $doc .= '<td class="leftalign">'; 266 $doc .= $mode; 267 $doc .= '</td>'; 268 269 if ($index === 0) { 270 $doc .= '<td class="rightalign" ' . $rowspan . '>'; 271 $doc .= $sort; 272 $doc .= '</td>'; 273 } 274 $doc .= '</tr>'; 275 } 276 } 277 278 $doc .= '</tbody></table></div>'; 279 return $doc; 280 } 281 282 /** 283 * Render all currently registered event handlers 284 * 285 * @param Doku_Renderer $renderer 286 */ 287 protected function renderHooks(Doku_Renderer $renderer) 288 { 289 global $EVENT_HANDLER; 290 291 $list = $EVENT_HANDLER->getEventHandlers(); 292 ksort($list); 293 294 $renderer->listu_open(); 295 foreach ($list as $event => $handlers) { 296 $renderer->listitem_open(1); 297 $renderer->listcontent_open(); 298 $renderer->cdata($event); 299 $renderer->listcontent_close(); 300 301 $renderer->listo_open(); 302 foreach ($handlers as $sequence) { 303 foreach ($sequence as $handler) { 304 $renderer->listitem_open(2); 305 $renderer->listcontent_open(); 306 $renderer->cdata(get_class($handler[0]) . '::' . $handler[1] . '()'); 307 $renderer->listcontent_close(); 308 $renderer->listitem_close(); 309 } 310 } 311 $renderer->listo_close(); 312 $renderer->listitem_close(); 313 } 314 $renderer->listu_close(); 315 } 316 317 /** 318 * Adds a TOC item 319 * 320 * @param string $text 321 * @param int $level 322 * @param Doku_Renderer_xhtml $renderer 323 * @return string 324 */ 325 protected function addToToc($text, $level, Doku_Renderer_xhtml $renderer) 326 { 327 global $conf; 328 329 $hid = ''; 330 if (($level >= $conf['toptoclevel']) && ($level <= $conf['maxtoclevel'])) { 331 $hid = $renderer->_headerToLink($text, true); 332 $renderer->toc[] = [ 333 'hid' => $hid, 334 'title' => $text, 335 'type' => 'ul', 336 'level' => $level - $conf['toptoclevel'] + 1 337 ]; 338 } 339 return $hid; 340 } 341} 342