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 | 50 | protected function init () { |
|
29 | /** @noinspection PhpUndefinedFieldInspection */ |
||
30 | 50 | if ($this->__request_id > 1) { |
|
31 | 2 | $this->callbacks = []; |
|
32 | } |
||
33 | 50 | } |
|
34 | /** |
||
35 | * Add event handler |
||
36 | * |
||
37 | * @param string $event For example `admin/System/components/modules/disable` |
||
38 | * @param callable $callback Callable, that will be called at event dispatching |
||
39 | * |
||
40 | * @return Event |
||
41 | */ |
||
42 | 50 | function on ($event, $callback) { |
|
43 | 50 | if (!$event || !is_callable($callback)) { |
|
44 | 2 | return $this; |
|
45 | } |
||
46 | 50 | $this->callbacks[$event][] = $callback; |
|
47 | 50 | 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 | 6 | function off ($event, $callback = null) { |
|
58 | 6 | if (!isset($this->callbacks[$event])) { |
|
59 | 2 | return $this; |
|
60 | } |
||
61 | 6 | if (!$callback) { |
|
62 | 2 | unset($this->callbacks[$event]); |
|
63 | 2 | return $this; |
|
64 | } |
||
65 | 6 | $this->callbacks[$event] = array_filter( |
|
66 | 6 | $this->callbacks[$event], |
|
67 | function ($c) use ($callback) { |
||
68 | 6 | return $c !== $callback; |
|
69 | 6 | } |
|
70 | ); |
||
71 | 6 | 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 | 8 | function once ($event, $callback) { |
|
82 | 8 | if (!$event || !is_callable($callback)) { |
|
83 | 2 | return $this; |
|
84 | } |
||
85 | 8 | $wrapped_callback = function (...$arguments) use (&$wrapped_callback, $event, $callback) { |
|
86 | 6 | $this->off($event, $wrapped_callback); |
|
87 | 6 | return $callback(...$arguments); |
|
88 | 8 | }; |
|
89 | 8 | 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/modules/disable` |
||
97 | * @param mixed[] $arguments |
||
98 | * |
||
99 | * @return bool |
||
100 | */ |
||
101 | 40 | function fire ($event, ...$arguments) { |
|
102 | 40 | $this->ensure_events_registered(); |
|
103 | if ( |
||
104 | 40 | !$event || |
|
105 | 40 | !isset($this->callbacks[$event]) |
|
106 | ) { |
||
107 | 40 | return true; |
|
108 | } |
||
109 | 30 | foreach ($this->callbacks[$event] as $callback) { |
|
110 | 30 | if ($callback(...$arguments) === false) { |
|
111 | 30 | return false; |
|
112 | } |
||
113 | } |
||
114 | 30 | return true; |
|
115 | } |
||
116 | /** |
||
117 | * Before firing events we need to ensure that events callbacks were registered |
||
118 | */ |
||
119 | 40 | protected function ensure_events_registered () { |
|
120 | 40 | if (!$this->callbacks_cache) { |
|
121 | 40 | $this->register_events(); |
|
122 | 40 | $this->callbacks_cache = $this->callbacks; |
|
123 | 40 | } elseif (!$this->callbacks) { |
|
124 | 2 | $this->callbacks = $this->callbacks_cache; |
|
125 | } |
||
126 | 40 | } |
|
127 | /** |
||
128 | * Initialize all events handlers |
||
129 | */ |
||
130 | 40 | protected function register_events () { |
|
135 | /** |
||
136 | * @return string[] |
||
137 | */ |
||
138 | 40 | protected function events_files_paths () { |
|
139 | 40 | $paths = []; |
|
140 | 40 | foreach (get_files_list(MODULES, false, 'd', true) as $path) { |
|
141 | 40 | if (file_exists("$path/events.php")) { |
|
147 | } |
||
148 |