1 | <?php |
||
16 | class Event { |
||
17 | use |
||
18 | Singleton; |
||
19 | const INIT_STATE_METHOD = 'init'; |
||
20 | /** |
||
21 | * @var callable[][] |
||
22 | */ |
||
23 | protected $callbacks = []; |
||
24 | /** |
||
25 | * @var callable[][] |
||
26 | */ |
||
27 | protected $callbacks_cache; |
||
28 | 26 | protected function init () { |
|
29 | /** @noinspection PhpUndefinedFieldInspection */ |
||
30 | 26 | if ($this->__request_id > 1) { |
|
31 | 2 | $this->callbacks = []; |
|
32 | } |
||
33 | 26 | } |
|
34 | /** |
||
35 | * Add event handler |
||
36 | * |
||
37 | * @param string $event For example `admin/System/components/plugins/disable` |
||
38 | * @param callable $callback Callable, that will be called at event dispatching |
||
39 | * |
||
40 | * @return Event |
||
41 | */ |
||
42 | 26 | function on ($event, $callback) { |
|
43 | 26 | if (!$event || !is_callable($callback)) { |
|
44 | 2 | return $this; |
|
45 | } |
||
46 | 26 | $this->callbacks[$event][] = $callback; |
|
47 | 26 | return $this; |
|
48 | } |
||
49 | /** |
||
50 | * Remove event handler |
||
51 | * |
||
52 | * @param string $event |
||
53 | * @param callable|null $callback If not specified - all callbacks for this event will be removed |
||
54 | * |
||
55 | * @return Event |
||
56 | */ |
||
57 | 2 | function off ($event, $callback = null) { |
|
58 | 2 | if (!isset($this->callbacks[$event])) { |
|
59 | 2 | return $this; |
|
60 | } |
||
61 | 2 | if (!$callback) { |
|
62 | 2 | unset($this->callbacks[$event]); |
|
63 | 2 | return $this; |
|
64 | } |
||
65 | 2 | $this->callbacks[$event] = array_filter( |
|
66 | 2 | $this->callbacks[$event], |
|
67 | function ($c) use ($callback) { |
||
68 | 2 | return $c !== $callback; |
|
69 | 2 | } |
|
70 | ); |
||
71 | 2 | return $this; |
|
72 | } |
||
73 | /** |
||
74 | * Similar to `::on()`, but but removes handler after handling of first event |
||
75 | * |
||
76 | * @param string $event |
||
77 | * @param callable $callback |
||
78 | * |
||
79 | * @return Event |
||
80 | */ |
||
81 | 4 | function once ($event, $callback) { |
|
82 | 4 | if (!$event || !is_callable($callback)) { |
|
83 | 2 | return $this; |
|
84 | } |
||
85 | 2 | $wrapped_callback = function (...$arguments) use (&$wrapped_callback, $event, $callback) { |
|
86 | $this->off($event, $wrapped_callback); |
||
87 | $callback(...$arguments); |
||
88 | 2 | }; |
|
89 | 2 | return $this->on($event, $wrapped_callback); |
|
90 | } |
||
91 | /** |
||
92 | * Fire event |
||
93 | * |
||
94 | * After event name it is possible to specify as many arguments as needed |
||
95 | * |
||
96 | * @param string $event For example `admin/System/components/plugins/disable` |
||
97 | * @param mixed[] $arguments |
||
98 | * |
||
99 | * @return bool |
||
100 | */ |
||
101 | 16 | function fire ($event, ...$arguments) { |
|
116 | /** |
||
117 | * Before firing events we need to ensure that events callbacks were registered |
||
118 | */ |
||
119 | 16 | protected function ensure_events_registered () { |
|
120 | 16 | if (!$this->callbacks_cache) { |
|
121 | 16 | $this->register_events(); |
|
122 | 16 | $this->callbacks_cache = $this->callbacks; |
|
123 | 16 | } elseif (!$this->callbacks) { |
|
124 | 2 | $this->callbacks = $this->callbacks_cache; |
|
125 | } |
||
126 | 16 | } |
|
127 | /** |
||
128 | * Initialize all events handlers |
||
129 | */ |
||
130 | 16 | protected function register_events () { |
|
135 | /** |
||
136 | * @return string[] |
||
137 | */ |
||
138 | 16 | protected function events_files_paths () { |
|
139 | 16 | $paths = []; |
|
140 | 16 | foreach (get_files_list(MODULES, false, 'd', true) as $path) { |
|
152 | } |
||
153 |