xref: /dokuwiki/inc/Extension/EventHandler.php (revision d4f83172d9533c4d84f450fe22ef630816b21d75)
1e1d9dcc8SAndreas Gohr<?php
2*d4f83172SAndreas Gohr
342f12f7dSAndreas Gohr// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
4e1d9dcc8SAndreas Gohr
5e1d9dcc8SAndreas Gohrnamespace dokuwiki\Extension;
6e1d9dcc8SAndreas Gohr
7e1d9dcc8SAndreas Gohr/**
8e1d9dcc8SAndreas Gohr * Controls the registration and execution of all events,
9e1d9dcc8SAndreas Gohr */
10e1d9dcc8SAndreas Gohrclass EventHandler
11e1d9dcc8SAndreas Gohr{
12e1d9dcc8SAndreas Gohr    // public properties:  none
13e1d9dcc8SAndreas Gohr
14e1d9dcc8SAndreas Gohr    // private properties
151490c177SAndreas Gohr    protected $hooks = [];          // array of events and their registered handlers
16e1d9dcc8SAndreas Gohr
17e1d9dcc8SAndreas Gohr    /**
18e1d9dcc8SAndreas Gohr     * event_handler
19e1d9dcc8SAndreas Gohr     *
20e1d9dcc8SAndreas Gohr     * constructor, loads all action plugins and calls their register() method giving them
21e1d9dcc8SAndreas Gohr     * an opportunity to register any hooks they require
22e1d9dcc8SAndreas Gohr     */
23e1d9dcc8SAndreas Gohr    public function __construct()
24e1d9dcc8SAndreas Gohr    {
25e1d9dcc8SAndreas Gohr
26e1d9dcc8SAndreas Gohr        // load action plugins
27e1d9dcc8SAndreas Gohr        /** @var ActionPlugin $plugin */
28e1d9dcc8SAndreas Gohr        $plugin = null;
29e1d9dcc8SAndreas Gohr        $pluginlist = plugin_list('action');
30e1d9dcc8SAndreas Gohr
31e1d9dcc8SAndreas Gohr        foreach ($pluginlist as $plugin_name) {
32e1d9dcc8SAndreas Gohr            $plugin = plugin_load('action', $plugin_name);
33e1d9dcc8SAndreas Gohr
341490c177SAndreas Gohr            if ($plugin instanceof PluginInterface) $plugin->register($this);
35e1d9dcc8SAndreas Gohr        }
36e1d9dcc8SAndreas Gohr    }
37e1d9dcc8SAndreas Gohr
38e1d9dcc8SAndreas Gohr    /**
39e1d9dcc8SAndreas Gohr     * register_hook
40e1d9dcc8SAndreas Gohr     *
41e1d9dcc8SAndreas Gohr     * register a hook for an event
42e1d9dcc8SAndreas Gohr     *
43b646f783SAndreas Gohr     * @param string $event name used by the event
44b646f783SAndreas Gohr     * @param string $advise BEFORE|AFTER
45b646f783SAndreas Gohr     * @param object $obj scope for the method be executed on, NULL for global function or callable
46b646f783SAndreas Gohr     * @param string|callable $method event handler function
47e1d9dcc8SAndreas Gohr     * @param mixed $param data passed to the event handler
48e1d9dcc8SAndreas Gohr     * @param int $seq sequence number for ordering hook execution (ascending)
49e1d9dcc8SAndreas Gohr     */
50e1d9dcc8SAndreas Gohr    public function register_hook($event, $advise, $obj, $method, $param = null, $seq = 0)
51e1d9dcc8SAndreas Gohr    {
52e1d9dcc8SAndreas Gohr        $seq = (int)$seq;
5342f12f7dSAndreas Gohr        $doSort = !isset($this->hooks[$event . '_' . $advise][$seq]);
541490c177SAndreas Gohr        $this->hooks[$event . '_' . $advise][$seq][] = [$obj, $method, $param];
55e1d9dcc8SAndreas Gohr
56e1d9dcc8SAndreas Gohr        if ($doSort) {
5742f12f7dSAndreas Gohr            ksort($this->hooks[$event . '_' . $advise]);
58e1d9dcc8SAndreas Gohr        }
59e1d9dcc8SAndreas Gohr    }
60e1d9dcc8SAndreas Gohr
61e1d9dcc8SAndreas Gohr    /**
62e1d9dcc8SAndreas Gohr     * process the before/after event
63e1d9dcc8SAndreas Gohr     *
64e1d9dcc8SAndreas Gohr     * @param Event $event
65e1d9dcc8SAndreas Gohr     * @param string $advise BEFORE or AFTER
66e1d9dcc8SAndreas Gohr     */
67e1d9dcc8SAndreas Gohr    public function process_event($event, $advise = '')
68e1d9dcc8SAndreas Gohr    {
69e1d9dcc8SAndreas Gohr
70e1d9dcc8SAndreas Gohr        $evt_name = $event->name . ($advise ? '_' . $advise : '_BEFORE');
71e1d9dcc8SAndreas Gohr
7242f12f7dSAndreas Gohr        if (!empty($this->hooks[$evt_name])) {
7342f12f7dSAndreas Gohr            foreach ($this->hooks[$evt_name] as $sequenced_hooks) {
74e1d9dcc8SAndreas Gohr                foreach ($sequenced_hooks as $hook) {
751490c177SAndreas Gohr                    [$obj, $method, $param] = $hook;
76e1d9dcc8SAndreas Gohr
777c9b63b7SAndreas Gohr                    if ($obj === null) {
78e1d9dcc8SAndreas Gohr                        $method($event, $param);
79e1d9dcc8SAndreas Gohr                    } else {
80e1d9dcc8SAndreas Gohr                        $obj->$method($event, $param);
81e1d9dcc8SAndreas Gohr                    }
82e1d9dcc8SAndreas Gohr
83e1d9dcc8SAndreas Gohr                    if (!$event->mayPropagate()) return;
84e1d9dcc8SAndreas Gohr                }
85e1d9dcc8SAndreas Gohr            }
86e1d9dcc8SAndreas Gohr        }
87e1d9dcc8SAndreas Gohr    }
88e1d9dcc8SAndreas Gohr
89e1d9dcc8SAndreas Gohr    /**
90e1d9dcc8SAndreas Gohr     * Check if an event has any registered handlers
91e1d9dcc8SAndreas Gohr     *
92e1d9dcc8SAndreas Gohr     * When $advise is empty, both BEFORE and AFTER events will be considered,
93e1d9dcc8SAndreas Gohr     * otherwise only the given advisory is checked
94e1d9dcc8SAndreas Gohr     *
95e1d9dcc8SAndreas Gohr     * @param string $name Name of the event
96e1d9dcc8SAndreas Gohr     * @param string $advise BEFORE, AFTER or empty
97e1d9dcc8SAndreas Gohr     * @return bool
98e1d9dcc8SAndreas Gohr     */
99e1d9dcc8SAndreas Gohr    public function hasHandlerForEvent($name, $advise = '')
100e1d9dcc8SAndreas Gohr    {
101e1d9dcc8SAndreas Gohr        if ($advise) {
10242f12f7dSAndreas Gohr            return isset($this->hooks[$name . '_' . $advise]);
103e1d9dcc8SAndreas Gohr        }
1047c9b63b7SAndreas Gohr
1057c9b63b7SAndreas Gohr        return isset($this->hooks[$name . '_BEFORE']) || isset($this->hooks[$name . '_AFTER']);
106e1d9dcc8SAndreas Gohr    }
107b646f783SAndreas Gohr
108b646f783SAndreas Gohr    /**
109b646f783SAndreas Gohr     * Get all hooks and their currently registered handlers
110b646f783SAndreas Gohr     *
111b646f783SAndreas Gohr     * The handlers are sorted by sequence, then by register time
112b646f783SAndreas Gohr     *
113b646f783SAndreas Gohr     * @return array
114b646f783SAndreas Gohr     */
115b646f783SAndreas Gohr    public function getEventHandlers()
116b646f783SAndreas Gohr    {
117b646f783SAndreas Gohr        return $this->hooks;
118b646f783SAndreas Gohr    }
119e1d9dcc8SAndreas Gohr}
120