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