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