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