1e1d9dcc8SAndreas Gohr<?php 2091ad7bdSAndreas Gohr// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps 3e1d9dcc8SAndreas Gohr 4e1d9dcc8SAndreas Gohrnamespace dokuwiki\Extension; 5e1d9dcc8SAndreas Gohr 60ecde6ceSAndreas Gohruse dokuwiki\Logger; 70ecde6ceSAndreas Gohr 8e1d9dcc8SAndreas Gohr/** 9e1d9dcc8SAndreas Gohr * The Action plugin event 10e1d9dcc8SAndreas Gohr */ 11e1d9dcc8SAndreas Gohrclass Event 12e1d9dcc8SAndreas Gohr{ 13091ad7bdSAndreas Gohr /** @var string READONLY event name, objects must register against this name to see the event */ 14091ad7bdSAndreas Gohr public $name = ''; 15091ad7bdSAndreas Gohr /** @var mixed|null READWRITE data relevant to the event, no standardised format, refer to event docs */ 161490c177SAndreas Gohr public $data; 17091ad7bdSAndreas Gohr /** 18091ad7bdSAndreas Gohr * @var mixed|null READWRITE the results of the event action, only relevant in "_AFTER" advise 19091ad7bdSAndreas Gohr * event handlers may modify this if they are preventing the default action 20091ad7bdSAndreas Gohr * to provide the after event handlers with event results 21091ad7bdSAndreas Gohr */ 221490c177SAndreas Gohr public $result; 23091ad7bdSAndreas Gohr /** @var bool READONLY if true, event handlers can prevent the events default action */ 24091ad7bdSAndreas Gohr public $canPreventDefault = true; 25e1d9dcc8SAndreas Gohr 26091ad7bdSAndreas Gohr /** @var bool whether or not to carry out the default action associated with the event */ 27091ad7bdSAndreas Gohr protected $runDefault = true; 28091ad7bdSAndreas Gohr /** @var bool whether or not to continue propagating the event to other handlers */ 29091ad7bdSAndreas Gohr protected $mayContinue = true; 30e1d9dcc8SAndreas Gohr 31e1d9dcc8SAndreas Gohr /** 32e1d9dcc8SAndreas Gohr * event constructor 33e1d9dcc8SAndreas Gohr * 34e1d9dcc8SAndreas Gohr * @param string $name 35e1d9dcc8SAndreas Gohr * @param mixed $data 36e1d9dcc8SAndreas Gohr */ 37e1d9dcc8SAndreas Gohr public function __construct($name, &$data) 38e1d9dcc8SAndreas Gohr { 39e1d9dcc8SAndreas Gohr 40e1d9dcc8SAndreas Gohr $this->name = $name; 41e1d9dcc8SAndreas Gohr $this->data =& $data; 42e1d9dcc8SAndreas Gohr } 43e1d9dcc8SAndreas Gohr 44e1d9dcc8SAndreas Gohr /** 45e1d9dcc8SAndreas Gohr * @return string 46e1d9dcc8SAndreas Gohr */ 47e1d9dcc8SAndreas Gohr public function __toString() 48e1d9dcc8SAndreas Gohr { 49e1d9dcc8SAndreas Gohr return $this->name; 50e1d9dcc8SAndreas Gohr } 51e1d9dcc8SAndreas Gohr 52e1d9dcc8SAndreas Gohr /** 53091ad7bdSAndreas Gohr * advise all registered BEFORE handlers of this event 54e1d9dcc8SAndreas Gohr * 55e1d9dcc8SAndreas Gohr * if these methods are used by functions outside of this object, they must 56e1d9dcc8SAndreas Gohr * properly handle correct processing of any default action and issue an 57e1d9dcc8SAndreas Gohr * advise_after() signal. e.g. 58e1d9dcc8SAndreas Gohr * $evt = new dokuwiki\Plugin\Doku_Event(name, data); 59e1d9dcc8SAndreas Gohr * if ($evt->advise_before(canPreventDefault) { 60e1d9dcc8SAndreas Gohr * // default action code block 61e1d9dcc8SAndreas Gohr * } 62e1d9dcc8SAndreas Gohr * $evt->advise_after(); 63e1d9dcc8SAndreas Gohr * unset($evt); 64e1d9dcc8SAndreas Gohr * 65e1d9dcc8SAndreas Gohr * @param bool $enablePreventDefault 66091ad7bdSAndreas Gohr * @return bool results of processing the event, usually $this->runDefault 67e1d9dcc8SAndreas Gohr */ 68e1d9dcc8SAndreas Gohr public function advise_before($enablePreventDefault = true) 69e1d9dcc8SAndreas Gohr { 70e1d9dcc8SAndreas Gohr global $EVENT_HANDLER; 71e1d9dcc8SAndreas Gohr 72e1d9dcc8SAndreas Gohr $this->canPreventDefault = $enablePreventDefault; 7389614c82SAndreas Gohr if ($EVENT_HANDLER !== null) { 74e1d9dcc8SAndreas Gohr $EVENT_HANDLER->process_event($this, 'BEFORE'); 7589614c82SAndreas Gohr } else { 760ecde6ceSAndreas Gohr Logger::getInstance(Logger::LOG_DEBUG) 770ecde6ceSAndreas Gohr ->log($this->name . ':BEFORE event triggered before event system was initialized'); 7889614c82SAndreas Gohr } 79e1d9dcc8SAndreas Gohr 80091ad7bdSAndreas Gohr return (!$enablePreventDefault || $this->runDefault); 81e1d9dcc8SAndreas Gohr } 82e1d9dcc8SAndreas Gohr 83091ad7bdSAndreas Gohr /** 84091ad7bdSAndreas Gohr * advise all registered AFTER handlers of this event 85091ad7bdSAndreas Gohr * 86091ad7bdSAndreas Gohr * @param bool $enablePreventDefault 87091ad7bdSAndreas Gohr * @see advise_before() for details 88091ad7bdSAndreas Gohr */ 89e1d9dcc8SAndreas Gohr public function advise_after() 90e1d9dcc8SAndreas Gohr { 91e1d9dcc8SAndreas Gohr global $EVENT_HANDLER; 92e1d9dcc8SAndreas Gohr 93091ad7bdSAndreas Gohr $this->mayContinue = true; 9489614c82SAndreas Gohr 9589614c82SAndreas Gohr if ($EVENT_HANDLER !== null) { 96e1d9dcc8SAndreas Gohr $EVENT_HANDLER->process_event($this, 'AFTER'); 9789614c82SAndreas Gohr } else { 980ecde6ceSAndreas Gohr Logger::getInstance(Logger::LOG_DEBUG)-> 990ecde6ceSAndreas Gohr log($this->name . ':AFTER event triggered before event system was initialized'); 10089614c82SAndreas Gohr } 101e1d9dcc8SAndreas Gohr } 102e1d9dcc8SAndreas Gohr 103e1d9dcc8SAndreas Gohr /** 104e1d9dcc8SAndreas Gohr * trigger 105e1d9dcc8SAndreas Gohr * 106e1d9dcc8SAndreas Gohr * - advise all registered (<event>_BEFORE) handlers that this event is about to take place 107e1d9dcc8SAndreas Gohr * - carry out the default action using $this->data based on $enablePrevent and 108e1d9dcc8SAndreas Gohr * $this->_default, all of which may have been modified by the event handlers. 109e1d9dcc8SAndreas Gohr * - advise all registered (<event>_AFTER) handlers that the event has taken place 110e1d9dcc8SAndreas Gohr * 111e1d9dcc8SAndreas Gohr * @param null|callable $action 112e1d9dcc8SAndreas Gohr * @param bool $enablePrevent 113e1d9dcc8SAndreas Gohr * @return mixed $event->results 114e1d9dcc8SAndreas Gohr * the value set by any <event>_before or <event> handlers if the default action is prevented 115e1d9dcc8SAndreas Gohr * or the results of the default action (as modified by <event>_after handlers) 116e1d9dcc8SAndreas Gohr * or NULL no action took place and no handler modified the value 117e1d9dcc8SAndreas Gohr */ 118e1d9dcc8SAndreas Gohr public function trigger($action = null, $enablePrevent = true) 119e1d9dcc8SAndreas Gohr { 120e1d9dcc8SAndreas Gohr 121e1d9dcc8SAndreas Gohr if (!is_callable($action)) { 122e1d9dcc8SAndreas Gohr $enablePrevent = false; 123091ad7bdSAndreas Gohr if ($action !== null) { 124e1d9dcc8SAndreas Gohr trigger_error( 125e1d9dcc8SAndreas Gohr 'The default action of ' . $this . 126e1d9dcc8SAndreas Gohr ' is not null but also not callable. Maybe the method is not public?', 127e1d9dcc8SAndreas Gohr E_USER_WARNING 128e1d9dcc8SAndreas Gohr ); 129e1d9dcc8SAndreas Gohr } 130e1d9dcc8SAndreas Gohr } 131e1d9dcc8SAndreas Gohr 132e1d9dcc8SAndreas Gohr if ($this->advise_before($enablePrevent) && is_callable($action)) { 1334352f974SAndreas Gohr $this->result = call_user_func_array($action, [&$this->data]); 134e1d9dcc8SAndreas Gohr } 135e1d9dcc8SAndreas Gohr 136e1d9dcc8SAndreas Gohr $this->advise_after(); 137e1d9dcc8SAndreas Gohr 138e1d9dcc8SAndreas Gohr return $this->result; 139e1d9dcc8SAndreas Gohr } 140e1d9dcc8SAndreas Gohr 141e1d9dcc8SAndreas Gohr /** 142e1d9dcc8SAndreas Gohr * stopPropagation 143e1d9dcc8SAndreas Gohr * 144e1d9dcc8SAndreas Gohr * stop any further processing of the event by event handlers 145e1d9dcc8SAndreas Gohr * this function does not prevent the default action taking place 146e1d9dcc8SAndreas Gohr */ 147e1d9dcc8SAndreas Gohr public function stopPropagation() 148e1d9dcc8SAndreas Gohr { 149091ad7bdSAndreas Gohr $this->mayContinue = false; 150e1d9dcc8SAndreas Gohr } 151e1d9dcc8SAndreas Gohr 152e1d9dcc8SAndreas Gohr /** 153e1d9dcc8SAndreas Gohr * may the event propagate to the next handler? 154e1d9dcc8SAndreas Gohr * 155e1d9dcc8SAndreas Gohr * @return bool 156e1d9dcc8SAndreas Gohr */ 157e1d9dcc8SAndreas Gohr public function mayPropagate() 158e1d9dcc8SAndreas Gohr { 159091ad7bdSAndreas Gohr return $this->mayContinue; 160e1d9dcc8SAndreas Gohr } 161e1d9dcc8SAndreas Gohr 162e1d9dcc8SAndreas Gohr /** 163e1d9dcc8SAndreas Gohr * preventDefault 164e1d9dcc8SAndreas Gohr * 165e1d9dcc8SAndreas Gohr * prevent the default action taking place 166e1d9dcc8SAndreas Gohr */ 167e1d9dcc8SAndreas Gohr public function preventDefault() 168e1d9dcc8SAndreas Gohr { 169091ad7bdSAndreas Gohr $this->runDefault = false; 170e1d9dcc8SAndreas Gohr } 171e1d9dcc8SAndreas Gohr 172e1d9dcc8SAndreas Gohr /** 173e1d9dcc8SAndreas Gohr * should the default action be executed? 174e1d9dcc8SAndreas Gohr * 175e1d9dcc8SAndreas Gohr * @return bool 176e1d9dcc8SAndreas Gohr */ 177e1d9dcc8SAndreas Gohr public function mayRunDefault() 178e1d9dcc8SAndreas Gohr { 179091ad7bdSAndreas Gohr return $this->runDefault; 180e1d9dcc8SAndreas Gohr } 181cbb44eabSAndreas Gohr 182cbb44eabSAndreas Gohr /** 183cbb44eabSAndreas Gohr * Convenience method to trigger an event 184cbb44eabSAndreas Gohr * 185cbb44eabSAndreas Gohr * Creates, triggers and destroys an event in one go 186cbb44eabSAndreas Gohr * 187cbb44eabSAndreas Gohr * @param string $name name for the event 188cbb44eabSAndreas Gohr * @param mixed $data event data 189cbb44eabSAndreas Gohr * @param callable $action (optional, default=NULL) default action, a php callback function 190cbb44eabSAndreas Gohr * @param bool $canPreventDefault (optional, default=true) can hooks prevent the default action 191cbb44eabSAndreas Gohr * 192cbb44eabSAndreas Gohr * @return mixed the event results value after all event processing is complete 193cbb44eabSAndreas Gohr * by default this is the return value of the default action however 194cbb44eabSAndreas Gohr * it can be set or modified by event handler hooks 195cbb44eabSAndreas Gohr */ 196*fe15e2c0SAndreas Gohr public static function createAndTrigger($name, &$data, $action = null, $canPreventDefault = true) 197091ad7bdSAndreas Gohr { 198cbb44eabSAndreas Gohr $evt = new Event($name, $data); 199cbb44eabSAndreas Gohr return $evt->trigger($action, $canPreventDefault); 200cbb44eabSAndreas Gohr } 201e1d9dcc8SAndreas Gohr} 202