1e1d9dcc8SAndreas Gohr<?php 2*091ad7bdSAndreas Gohr// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps 3e1d9dcc8SAndreas Gohr 4e1d9dcc8SAndreas Gohrnamespace dokuwiki\Extension; 5e1d9dcc8SAndreas Gohr 6e1d9dcc8SAndreas Gohr/** 7e1d9dcc8SAndreas Gohr * The Action plugin event 8e1d9dcc8SAndreas Gohr */ 9e1d9dcc8SAndreas Gohrclass Event 10e1d9dcc8SAndreas Gohr{ 11*091ad7bdSAndreas Gohr /** @var string READONLY event name, objects must register against this name to see the event */ 12*091ad7bdSAndreas Gohr public $name = ''; 13*091ad7bdSAndreas Gohr /** @var mixed|null READWRITE data relevant to the event, no standardised format, refer to event docs */ 14*091ad7bdSAndreas Gohr public $data = null; 15*091ad7bdSAndreas Gohr /** 16*091ad7bdSAndreas Gohr * @var mixed|null READWRITE the results of the event action, only relevant in "_AFTER" advise 17*091ad7bdSAndreas Gohr * event handlers may modify this if they are preventing the default action 18*091ad7bdSAndreas Gohr * to provide the after event handlers with event results 19*091ad7bdSAndreas Gohr */ 20*091ad7bdSAndreas Gohr public $result = null; 21*091ad7bdSAndreas Gohr /** @var bool READONLY if true, event handlers can prevent the events default action */ 22*091ad7bdSAndreas Gohr public $canPreventDefault = true; 23e1d9dcc8SAndreas Gohr 24*091ad7bdSAndreas Gohr /** @var bool whether or not to carry out the default action associated with the event */ 25*091ad7bdSAndreas Gohr protected $runDefault = true; 26*091ad7bdSAndreas Gohr /** @var bool whether or not to continue propagating the event to other handlers */ 27*091ad7bdSAndreas Gohr protected $mayContinue = true; 28e1d9dcc8SAndreas Gohr 29e1d9dcc8SAndreas Gohr /** 30e1d9dcc8SAndreas Gohr * event constructor 31e1d9dcc8SAndreas Gohr * 32e1d9dcc8SAndreas Gohr * @param string $name 33e1d9dcc8SAndreas Gohr * @param mixed $data 34e1d9dcc8SAndreas Gohr */ 35e1d9dcc8SAndreas Gohr public function __construct($name, &$data) 36e1d9dcc8SAndreas Gohr { 37e1d9dcc8SAndreas Gohr 38e1d9dcc8SAndreas Gohr $this->name = $name; 39e1d9dcc8SAndreas Gohr $this->data =& $data; 40e1d9dcc8SAndreas Gohr } 41e1d9dcc8SAndreas Gohr 42e1d9dcc8SAndreas Gohr /** 43e1d9dcc8SAndreas Gohr * @return string 44e1d9dcc8SAndreas Gohr */ 45e1d9dcc8SAndreas Gohr public function __toString() 46e1d9dcc8SAndreas Gohr { 47e1d9dcc8SAndreas Gohr return $this->name; 48e1d9dcc8SAndreas Gohr } 49e1d9dcc8SAndreas Gohr 50e1d9dcc8SAndreas Gohr /** 51*091ad7bdSAndreas Gohr * advise all registered BEFORE handlers of this event 52e1d9dcc8SAndreas Gohr * 53e1d9dcc8SAndreas Gohr * if these methods are used by functions outside of this object, they must 54e1d9dcc8SAndreas Gohr * properly handle correct processing of any default action and issue an 55e1d9dcc8SAndreas Gohr * advise_after() signal. e.g. 56e1d9dcc8SAndreas Gohr * $evt = new dokuwiki\Plugin\Doku_Event(name, data); 57e1d9dcc8SAndreas Gohr * if ($evt->advise_before(canPreventDefault) { 58e1d9dcc8SAndreas Gohr * // default action code block 59e1d9dcc8SAndreas Gohr * } 60e1d9dcc8SAndreas Gohr * $evt->advise_after(); 61e1d9dcc8SAndreas Gohr * unset($evt); 62e1d9dcc8SAndreas Gohr * 63e1d9dcc8SAndreas Gohr * @param bool $enablePreventDefault 64*091ad7bdSAndreas Gohr * @return bool results of processing the event, usually $this->runDefault 65e1d9dcc8SAndreas Gohr */ 66e1d9dcc8SAndreas Gohr public function advise_before($enablePreventDefault = true) 67e1d9dcc8SAndreas Gohr { 68e1d9dcc8SAndreas Gohr global $EVENT_HANDLER; 69e1d9dcc8SAndreas Gohr 70e1d9dcc8SAndreas Gohr $this->canPreventDefault = $enablePreventDefault; 7189614c82SAndreas Gohr if ($EVENT_HANDLER !== null) { 72e1d9dcc8SAndreas Gohr $EVENT_HANDLER->process_event($this, 'BEFORE'); 7389614c82SAndreas Gohr } else { 7489614c82SAndreas Gohr dbglog($this->name . ':BEFORE event triggered before event system was initialized'); 7589614c82SAndreas Gohr } 76e1d9dcc8SAndreas Gohr 77*091ad7bdSAndreas Gohr return (!$enablePreventDefault || $this->runDefault); 78e1d9dcc8SAndreas Gohr } 79e1d9dcc8SAndreas Gohr 80*091ad7bdSAndreas Gohr /** 81*091ad7bdSAndreas Gohr * advise all registered AFTER handlers of this event 82*091ad7bdSAndreas Gohr * 83*091ad7bdSAndreas Gohr * @param bool $enablePreventDefault 84*091ad7bdSAndreas Gohr * @see advise_before() for details 85*091ad7bdSAndreas Gohr */ 86e1d9dcc8SAndreas Gohr public function advise_after() 87e1d9dcc8SAndreas Gohr { 88e1d9dcc8SAndreas Gohr global $EVENT_HANDLER; 89e1d9dcc8SAndreas Gohr 90*091ad7bdSAndreas Gohr $this->mayContinue = true; 9189614c82SAndreas Gohr 9289614c82SAndreas Gohr if ($EVENT_HANDLER !== null) { 93e1d9dcc8SAndreas Gohr $EVENT_HANDLER->process_event($this, 'AFTER'); 9489614c82SAndreas Gohr } else { 9589614c82SAndreas Gohr dbglog($this->name . ':AFTER event triggered before event system was initialized'); 9689614c82SAndreas Gohr } 97e1d9dcc8SAndreas Gohr } 98e1d9dcc8SAndreas Gohr 99e1d9dcc8SAndreas Gohr /** 100e1d9dcc8SAndreas Gohr * trigger 101e1d9dcc8SAndreas Gohr * 102e1d9dcc8SAndreas Gohr * - advise all registered (<event>_BEFORE) handlers that this event is about to take place 103e1d9dcc8SAndreas Gohr * - carry out the default action using $this->data based on $enablePrevent and 104e1d9dcc8SAndreas Gohr * $this->_default, all of which may have been modified by the event handlers. 105e1d9dcc8SAndreas Gohr * - advise all registered (<event>_AFTER) handlers that the event has taken place 106e1d9dcc8SAndreas Gohr * 107e1d9dcc8SAndreas Gohr * @param null|callable $action 108e1d9dcc8SAndreas Gohr * @param bool $enablePrevent 109e1d9dcc8SAndreas Gohr * @return mixed $event->results 110e1d9dcc8SAndreas Gohr * the value set by any <event>_before or <event> handlers if the default action is prevented 111e1d9dcc8SAndreas Gohr * or the results of the default action (as modified by <event>_after handlers) 112e1d9dcc8SAndreas Gohr * or NULL no action took place and no handler modified the value 113e1d9dcc8SAndreas Gohr */ 114e1d9dcc8SAndreas Gohr public function trigger($action = null, $enablePrevent = true) 115e1d9dcc8SAndreas Gohr { 116e1d9dcc8SAndreas Gohr 117e1d9dcc8SAndreas Gohr if (!is_callable($action)) { 118e1d9dcc8SAndreas Gohr $enablePrevent = false; 119*091ad7bdSAndreas Gohr if ($action !== null) { 120e1d9dcc8SAndreas Gohr trigger_error( 121e1d9dcc8SAndreas Gohr 'The default action of ' . $this . 122e1d9dcc8SAndreas Gohr ' is not null but also not callable. Maybe the method is not public?', 123e1d9dcc8SAndreas Gohr E_USER_WARNING 124e1d9dcc8SAndreas Gohr ); 125e1d9dcc8SAndreas Gohr } 126e1d9dcc8SAndreas Gohr } 127e1d9dcc8SAndreas Gohr 128e1d9dcc8SAndreas Gohr if ($this->advise_before($enablePrevent) && is_callable($action)) { 129e1d9dcc8SAndreas Gohr if (is_array($action)) { 130e1d9dcc8SAndreas Gohr list($obj, $method) = $action; 131e1d9dcc8SAndreas Gohr $this->result = $obj->$method($this->data); 132e1d9dcc8SAndreas Gohr } else { 133e1d9dcc8SAndreas Gohr $this->result = $action($this->data); 134e1d9dcc8SAndreas Gohr } 135e1d9dcc8SAndreas Gohr } 136e1d9dcc8SAndreas Gohr 137e1d9dcc8SAndreas Gohr $this->advise_after(); 138e1d9dcc8SAndreas Gohr 139e1d9dcc8SAndreas Gohr return $this->result; 140e1d9dcc8SAndreas Gohr } 141e1d9dcc8SAndreas Gohr 142e1d9dcc8SAndreas Gohr /** 143e1d9dcc8SAndreas Gohr * stopPropagation 144e1d9dcc8SAndreas Gohr * 145e1d9dcc8SAndreas Gohr * stop any further processing of the event by event handlers 146e1d9dcc8SAndreas Gohr * this function does not prevent the default action taking place 147e1d9dcc8SAndreas Gohr */ 148e1d9dcc8SAndreas Gohr public function stopPropagation() 149e1d9dcc8SAndreas Gohr { 150*091ad7bdSAndreas Gohr $this->mayContinue = false; 151e1d9dcc8SAndreas Gohr } 152e1d9dcc8SAndreas Gohr 153e1d9dcc8SAndreas Gohr /** 154e1d9dcc8SAndreas Gohr * may the event propagate to the next handler? 155e1d9dcc8SAndreas Gohr * 156e1d9dcc8SAndreas Gohr * @return bool 157e1d9dcc8SAndreas Gohr */ 158e1d9dcc8SAndreas Gohr public function mayPropagate() 159e1d9dcc8SAndreas Gohr { 160*091ad7bdSAndreas Gohr return $this->mayContinue; 161e1d9dcc8SAndreas Gohr } 162e1d9dcc8SAndreas Gohr 163e1d9dcc8SAndreas Gohr /** 164e1d9dcc8SAndreas Gohr * preventDefault 165e1d9dcc8SAndreas Gohr * 166e1d9dcc8SAndreas Gohr * prevent the default action taking place 167e1d9dcc8SAndreas Gohr */ 168e1d9dcc8SAndreas Gohr public function preventDefault() 169e1d9dcc8SAndreas Gohr { 170*091ad7bdSAndreas Gohr $this->runDefault = false; 171e1d9dcc8SAndreas Gohr } 172e1d9dcc8SAndreas Gohr 173e1d9dcc8SAndreas Gohr /** 174e1d9dcc8SAndreas Gohr * should the default action be executed? 175e1d9dcc8SAndreas Gohr * 176e1d9dcc8SAndreas Gohr * @return bool 177e1d9dcc8SAndreas Gohr */ 178e1d9dcc8SAndreas Gohr public function mayRunDefault() 179e1d9dcc8SAndreas Gohr { 180*091ad7bdSAndreas Gohr return $this->runDefault; 181e1d9dcc8SAndreas Gohr } 182cbb44eabSAndreas Gohr 183cbb44eabSAndreas Gohr /** 184cbb44eabSAndreas Gohr * Convenience method to trigger an event 185cbb44eabSAndreas Gohr * 186cbb44eabSAndreas Gohr * Creates, triggers and destroys an event in one go 187cbb44eabSAndreas Gohr * 188cbb44eabSAndreas Gohr * @param string $name name for the event 189cbb44eabSAndreas Gohr * @param mixed $data event data 190cbb44eabSAndreas Gohr * @param callable $action (optional, default=NULL) default action, a php callback function 191cbb44eabSAndreas Gohr * @param bool $canPreventDefault (optional, default=true) can hooks prevent the default action 192cbb44eabSAndreas Gohr * 193cbb44eabSAndreas Gohr * @return mixed the event results value after all event processing is complete 194cbb44eabSAndreas Gohr * by default this is the return value of the default action however 195cbb44eabSAndreas Gohr * it can be set or modified by event handler hooks 196cbb44eabSAndreas Gohr */ 197*091ad7bdSAndreas Gohr static public function createAndTrigger($name, &$data, $action = null, $canPreventDefault = true) 198*091ad7bdSAndreas Gohr { 199cbb44eabSAndreas Gohr $evt = new Event($name, $data); 200cbb44eabSAndreas Gohr return $evt->trigger($action, $canPreventDefault); 201cbb44eabSAndreas Gohr } 202e1d9dcc8SAndreas Gohr} 203