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