1e1d9dcc8SAndreas Gohr<?php 242f12f7dSAndreas Gohr// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps 3e1d9dcc8SAndreas Gohr 4e1d9dcc8SAndreas Gohrnamespace dokuwiki\Extension; 5e1d9dcc8SAndreas Gohr 6e1d9dcc8SAndreas Gohr/** 7e1d9dcc8SAndreas Gohr * Controls the registration and execution of all events, 8e1d9dcc8SAndreas Gohr */ 9e1d9dcc8SAndreas Gohrclass EventHandler 10e1d9dcc8SAndreas Gohr{ 11e1d9dcc8SAndreas Gohr 12e1d9dcc8SAndreas Gohr // public properties: none 13e1d9dcc8SAndreas Gohr 14e1d9dcc8SAndreas Gohr // private properties 15*1490c177SAndreas 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 34*1490c177SAndreas 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]); 54*1490c177SAndreas 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) { 75*1490c177SAndreas 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