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