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 if (is_array($action)) { 130 list($obj, $method) = $action; 131 $this->result = $obj->$method($this->data); 132 } else { 133 $this->result = $action($this->data); 134 } 135 } 136 137 $this->advise_after(); 138 139 return $this->result; 140 } 141 142 /** 143 * stopPropagation 144 * 145 * stop any further processing of the event by event handlers 146 * this function does not prevent the default action taking place 147 */ 148 public function stopPropagation() 149 { 150 $this->mayContinue = false; 151 } 152 153 /** 154 * may the event propagate to the next handler? 155 * 156 * @return bool 157 */ 158 public function mayPropagate() 159 { 160 return $this->mayContinue; 161 } 162 163 /** 164 * preventDefault 165 * 166 * prevent the default action taking place 167 */ 168 public function preventDefault() 169 { 170 $this->runDefault = false; 171 } 172 173 /** 174 * should the default action be executed? 175 * 176 * @return bool 177 */ 178 public function mayRunDefault() 179 { 180 return $this->runDefault; 181 } 182 183 /** 184 * Convenience method to trigger an event 185 * 186 * Creates, triggers and destroys an event in one go 187 * 188 * @param string $name name for the event 189 * @param mixed $data event data 190 * @param callable $action (optional, default=NULL) default action, a php callback function 191 * @param bool $canPreventDefault (optional, default=true) can hooks prevent the default action 192 * 193 * @return mixed the event results value after all event processing is complete 194 * by default this is the return value of the default action however 195 * it can be set or modified by event handler hooks 196 */ 197 static public function createAndTrigger($name, &$data, $action = null, $canPreventDefault = true) 198 { 199 $evt = new Event($name, $data); 200 return $evt->trigger($action, $canPreventDefault); 201 } 202} 203