splitbrain /
dokuwiki
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * DokuWiki Events |
||
| 4 | * |
||
| 5 | * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) |
||
| 6 | * @author Christopher Smith <[email protected]> |
||
| 7 | */ |
||
| 8 | |||
| 9 | if(!defined('DOKU_INC')) die('meh.'); |
||
| 10 | |||
| 11 | /** |
||
| 12 | * The event |
||
| 13 | */ |
||
| 14 | class Doku_Event { |
||
| 15 | |||
| 16 | // public properties |
||
| 17 | public $name = ''; // READONLY event name, objects must register against this name to see the event |
||
| 18 | public $data = null; // READWRITE data relevant to the event, no standardised format (YET!) |
||
| 19 | public $result = null; // READWRITE the results of the event action, only relevant in "_AFTER" advise |
||
| 20 | // event handlers may modify this if they are preventing the default action |
||
| 21 | // to provide the after event handlers with event results |
||
| 22 | public $canPreventDefault = true; // READONLY if true, event handlers can prevent the events default action |
||
| 23 | |||
| 24 | // private properties, event handlers can effect these through the provided methods |
||
| 25 | var $_default = true; // whether or not to carry out the default action associated with the event |
||
| 26 | var $_continue = true; // whether or not to continue propagating the event to other handlers |
||
| 27 | |||
| 28 | /** |
||
| 29 | * event constructor |
||
| 30 | * |
||
| 31 | * @param string $name |
||
| 32 | * @param mixed $data |
||
| 33 | */ |
||
| 34 | function __construct($name, &$data) { |
||
| 35 | |||
| 36 | $this->name = $name; |
||
| 37 | $this->data =& $data; |
||
| 38 | |||
| 39 | } |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @return string |
||
| 43 | */ |
||
| 44 | function __toString() { |
||
| 45 | return $this->name; |
||
| 46 | } |
||
| 47 | |||
| 48 | /** |
||
| 49 | * advise functions |
||
| 50 | * |
||
| 51 | * advise all registered 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 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->_default |
||
| 65 | */ |
||
| 66 | function advise_before($enablePreventDefault=true) { |
||
| 67 | global $EVENT_HANDLER; |
||
| 68 | |||
| 69 | $this->canPreventDefault = $enablePreventDefault; |
||
| 70 | $EVENT_HANDLER->process_event($this,'BEFORE'); |
||
| 71 | |||
| 72 | return (!$enablePreventDefault || $this->_default); |
||
| 73 | } |
||
| 74 | |||
| 75 | function advise_after() { |
||
| 76 | global $EVENT_HANDLER; |
||
| 77 | |||
| 78 | $this->_continue = true; |
||
| 79 | $EVENT_HANDLER->process_event($this,'AFTER'); |
||
| 80 | } |
||
| 81 | |||
| 82 | /** |
||
| 83 | * trigger |
||
| 84 | * |
||
| 85 | * - advise all registered (<event>_BEFORE) handlers that this event is about to take place |
||
| 86 | * - carry out the default action using $this->data based on $enablePrevent and |
||
| 87 | * $this->_default, all of which may have been modified by the event handlers. |
||
| 88 | * - advise all registered (<event>_AFTER) handlers that the event has taken place |
||
| 89 | * |
||
| 90 | * @param null|callable $action |
||
| 91 | * @param bool $enablePrevent |
||
| 92 | * @return mixed $event->results |
||
| 93 | * the value set by any <event>_before or <event> handlers if the default action is prevented |
||
| 94 | * or the results of the default action (as modified by <event>_after handlers) |
||
| 95 | * or NULL no action took place and no handler modified the value |
||
| 96 | */ |
||
| 97 | function trigger($action=null, $enablePrevent=true) { |
||
| 98 | |||
| 99 | if (!is_callable($action)) { |
||
| 100 | $enablePrevent = false; |
||
| 101 | if (!is_null($action)) { |
||
| 102 | trigger_error('The default action of '.$this.' is not null but also not callable. Maybe the method is not public?', E_USER_WARNING); |
||
| 103 | } |
||
| 104 | } |
||
| 105 | |||
| 106 | if ($this->advise_before($enablePrevent) && is_callable($action)) { |
||
| 107 | if (is_array($action)) { |
||
| 108 | list($obj,$method) = $action; |
||
| 109 | $this->result = $obj->$method($this->data); |
||
| 110 | } else { |
||
| 111 | $this->result = $action($this->data); |
||
| 112 | } |
||
| 113 | } |
||
| 114 | |||
| 115 | $this->advise_after(); |
||
| 116 | |||
| 117 | return $this->result; |
||
| 118 | } |
||
| 119 | |||
| 120 | /** |
||
| 121 | * stopPropagation |
||
| 122 | * |
||
| 123 | * stop any further processing of the event by event handlers |
||
| 124 | * this function does not prevent the default action taking place |
||
| 125 | */ |
||
| 126 | function stopPropagation() { |
||
| 127 | $this->_continue = false; |
||
| 128 | } |
||
| 129 | |||
| 130 | /** |
||
| 131 | * preventDefault |
||
| 132 | * |
||
| 133 | * prevent the default action taking place |
||
| 134 | */ |
||
| 135 | function preventDefault() { |
||
| 136 | $this->_default = false; |
||
| 137 | } |
||
| 138 | } |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Controls the registration and execution of all events, |
||
| 142 | */ |
||
| 143 | class Doku_Event_Handler { |
||
| 144 | |||
| 145 | // public properties: none |
||
| 146 | |||
| 147 | // private properties |
||
| 148 | protected $_hooks = array(); // array of events and their registered handlers |
||
| 149 | |||
| 150 | /** |
||
| 151 | * event_handler |
||
| 152 | * |
||
| 153 | * constructor, loads all action plugins and calls their register() method giving them |
||
| 154 | * an opportunity to register any hooks they require |
||
| 155 | */ |
||
| 156 | function __construct() { |
||
| 157 | |||
| 158 | // load action plugins |
||
| 159 | /** @var DokuWiki_Action_Plugin $plugin */ |
||
| 160 | $plugin = null; |
||
| 161 | $pluginlist = plugin_list('action'); |
||
| 162 | |||
| 163 | foreach ($pluginlist as $plugin_name) { |
||
| 164 | $plugin = plugin_load('action',$plugin_name); |
||
| 165 | |||
| 166 | if ($plugin !== null) $plugin->register($this); |
||
| 167 | } |
||
| 168 | } |
||
| 169 | |||
| 170 | /** |
||
| 171 | * register_hook |
||
| 172 | * |
||
| 173 | * register a hook for an event |
||
| 174 | * |
||
| 175 | * @param string $event string name used by the event, (incl '_before' or '_after' for triggers) |
||
| 176 | * @param string $advise |
||
| 177 | * @param object $obj object in whose scope method is to be executed, |
||
| 178 | * if NULL, method is assumed to be a globally available function |
||
| 179 | * @param string $method event handler function |
||
| 180 | * @param mixed $param data passed to the event handler |
||
| 181 | * @param int $seq sequence number for ordering hook execution (ascending) |
||
| 182 | */ |
||
| 183 | function register_hook($event, $advise, $obj, $method, $param=null, $seq=0) { |
||
| 184 | $seq = (int)$seq; |
||
| 185 | $doSort = !isset($this->_hooks[$event.'_'.$advise][$seq]); |
||
| 186 | $this->_hooks[$event.'_'.$advise][$seq][] = array($obj, $method, $param); |
||
| 187 | |||
| 188 | if ($doSort) { |
||
| 189 | ksort($this->_hooks[$event.'_'.$advise]); |
||
| 190 | } |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * process the before/after event |
||
| 195 | * |
||
| 196 | * @param Doku_Event $event |
||
| 197 | * @param string $advise BEFORE or AFTER |
||
| 198 | */ |
||
| 199 | function process_event($event,$advise='') { |
||
| 200 | |||
| 201 | $evt_name = $event->name . ($advise ? '_'.$advise : '_BEFORE'); |
||
| 202 | |||
| 203 | if (!empty($this->_hooks[$evt_name])) { |
||
| 204 | foreach ($this->_hooks[$evt_name] as $sequenced_hooks) { |
||
| 205 | foreach ($sequenced_hooks as $hook) { |
||
| 206 | list($obj, $method, $param) = $hook; |
||
| 207 | |||
| 208 | if (is_null($obj)) { |
||
| 209 | $method($event, $param); |
||
| 210 | } else { |
||
| 211 | $obj->$method($event, $param); |
||
| 212 | } |
||
| 213 | |||
| 214 | if (!$event->_continue) return; |
||
|
0 ignored issues
–
show
|
|||
| 215 | } |
||
| 216 | } |
||
| 217 | } |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | /** |
||
| 222 | * trigger_event |
||
| 223 | * |
||
| 224 | * function wrapper to process (create, trigger and destroy) an event |
||
| 225 | * |
||
| 226 | * @param string $name name for the event |
||
| 227 | * @param mixed $data event data |
||
| 228 | * @param callback $action (optional, default=NULL) default action, a php callback function |
||
| 229 | * @param bool $canPreventDefault (optional, default=true) can hooks prevent the default action |
||
| 230 | * |
||
| 231 | * @return mixed the event results value after all event processing is complete |
||
| 232 | * by default this is the return value of the default action however |
||
| 233 | * it can be set or modified by event handler hooks |
||
| 234 | */ |
||
| 235 | function trigger_event($name, &$data, $action=null, $canPreventDefault=true) { |
||
| 236 | |||
| 237 | $evt = new Doku_Event($name, $data); |
||
| 238 | return $evt->trigger($action, $canPreventDefault); |
||
| 239 | } |
||
| 240 |
This check looks for access to properties that are not accessible from the current context.
If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.