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