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