1<?php 2 3/** 4 * DokuWiki Plugin autonumbering (Action Component) 5 * 6 * Adds autonumbering support for DokuWiki headings. 7 * 8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 9 */ 10 11// phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols 12use dokuwiki\Extension\ActionPlugin; 13use dokuwiki\Extension\Event; 14use dokuwiki\Extension\EventHandler; 15 16// must be run within DokuWiki 17if (!defined('DOKU_INC')) { 18 die(); 19} 20// phpcs:enable 21 22class action_plugin_autonumbering extends ActionPlugin 23{ 24 /** 25 * @inheritDoc 26 */ 27 public function register(EventHandler $controller) 28 { 29 $controller->register_hook('PARSER_HANDLER_DONE', 'AFTER', $this, 'numberHeaders'); 30 } 31 32 /** 33 * Rebuild autonumbering calls in document order and replace heading markers. 34 * 35 * DokuWiki headings are parsed as plain header calls, so syntax plugins are 36 * not evaluated inside them. Walking the final instruction list keeps heading 37 * and body counters in the same order. 38 * 39 * @param Event $event Event object 40 * @param mixed $param optional parameter passed when the event was registered 41 * @return void 42 */ 43 public function numberHeaders(Event $event, $param) 44 { 45 if (!$event->data instanceof Doku_Handler) { 46 return; 47 } 48 49 global $COUNTER; 50 $COUNTER = []; 51 52 foreach ($event->data->calls as &$call) { 53 if ($call[0] === 'header') { 54 $call[1][0] = $this->replaceHeaderMarkers($call[1][0], $event->data); 55 continue; 56 } 57 58 if ($call[0] !== 'plugin' || $call[1][0] !== 'autonumbering') { 59 continue; 60 } 61 62 $syntax = plugin_load('syntax', 'autonumbering'); 63 if (!$syntax instanceof syntax_plugin_autonumbering) { 64 continue; 65 } 66 67 $call[1][1] = $syntax->handle($call[1][3], $call[1][2], $call[2], $event->data); 68 } 69 unset($call); 70 } 71 72 /** 73 * Replace autonumbering markers in a heading title with plain heading text. 74 * 75 * @param string $title heading title 76 * @param Doku_Handler $handler parser handler 77 * @return string 78 */ 79 protected function replaceHeaderMarkers($title, Doku_Handler $handler) 80 { 81 $syntax = plugin_load('syntax', 'autonumbering'); 82 if (!$syntax instanceof syntax_plugin_autonumbering) { 83 return $title; 84 } 85 86 return preg_replace_callback( 87 '/~~[a-zA-Z0-9_\.#@]*#[a-zA-Z0-9_\.#@]*~~/', 88 function ($matches) use ($syntax, $handler) { 89 $data = $syntax->handle($matches[0], DOKU_LEXER_SPECIAL, null, $handler); 90 if (empty($data)) { 91 return $matches[0]; 92 } 93 94 return strip_tags($data[0]); 95 }, 96 $title 97 ); 98 } 99} 100