Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
46 / 46 |
|
100.00% |
18 / 18 |
CRAP | |
100.00% |
1 / 1 |
Manager | |
100.00% |
46 / 46 |
|
100.00% |
18 / 18 |
32 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
3 | |||
on | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
off | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
4 | |||
get | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
has | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getResults | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
alive | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
trigger | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
6 | |||
__set | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__get | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__isset | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__unset | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
offsetSet | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
offsetGet | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
offsetExists | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
offsetUnset | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
count | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getIterator | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (https://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@noladev.com> |
7 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
8 | * @license https://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Event; |
15 | |
16 | use Pop\Utils\CallableObject; |
17 | use ArrayAccess; |
18 | use ArrayIterator; |
19 | use Countable; |
20 | use IteratorAggregate; |
21 | |
22 | /** |
23 | * Event manager class |
24 | * |
25 | * @category Pop |
26 | * @package Pop\Event |
27 | * @author Nick Sagona, III <dev@noladev.com> |
28 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
29 | * @license https://www.popphp.org/license New BSD License |
30 | * @version 4.3.7 |
31 | */ |
32 | class Manager implements ArrayAccess, Countable, IteratorAggregate |
33 | { |
34 | |
35 | /** |
36 | * Constant to stop the event manager |
37 | * @var string |
38 | */ |
39 | const STOP = 'Pop\Event\Manager::STOP'; |
40 | |
41 | /** |
42 | * Constant to send a kill signal to the application |
43 | * @var string |
44 | */ |
45 | const KILL = 'Pop\Event\Manager::KILL'; |
46 | |
47 | /** |
48 | * Event listeners |
49 | * @var array |
50 | */ |
51 | protected array $listeners = []; |
52 | |
53 | /** |
54 | * Event results |
55 | * @var array |
56 | */ |
57 | protected array $results = []; |
58 | |
59 | /** |
60 | * Event 'alive' tracking flag |
61 | * @var bool |
62 | */ |
63 | protected bool $alive = true; |
64 | |
65 | /** |
66 | * Constructor |
67 | * |
68 | * Instantiate the event manager object. |
69 | * |
70 | * @param ?string $name |
71 | * @param mixed $action |
72 | * @param int $priority |
73 | */ |
74 | public function __construct(?string $name = null, mixed $action = null, int $priority = 0) |
75 | { |
76 | if (($name !== null) && ($action !== null)) { |
77 | $this->on($name, $action, $priority); |
78 | } |
79 | } |
80 | |
81 | /** |
82 | * Attach an event listener |
83 | * |
84 | * $event->on('event.name', 'someFunction'); |
85 | * $event->on('event.name', function() { ... }); |
86 | * $event->on('event.name', new SomeClass()); |
87 | * $event->on('event.name', [new SomeClass, 'foo']); |
88 | * $event->on('event.name', 'SomeClass'); |
89 | * $event->on('event.name', 'SomeClass->foo'); |
90 | * $event->on('event.name', 'SomeClass::bar'); |
91 | * |
92 | * @param string $name |
93 | * @param mixed $action |
94 | * @param int $priority |
95 | * @return Manager |
96 | */ |
97 | public function on(string $name, mixed $action, int $priority = 0): static |
98 | { |
99 | if (!isset($this->listeners[$name])) { |
100 | $this->listeners[$name] = new \SplPriorityQueue(); |
101 | } |
102 | $this->listeners[$name]->insert(new CallableObject($action), (int)$priority); |
103 | |
104 | return $this; |
105 | } |
106 | |
107 | /** |
108 | * Detach an event listener |
109 | * |
110 | * @param string $name |
111 | * @param mixed $action |
112 | * @return Manager |
113 | */ |
114 | public function off(string $name, mixed $action): static |
115 | { |
116 | // If the event exists, loop through and remove the action if found. |
117 | if (isset($this->listeners[$name])) { |
118 | $newListeners = new \SplPriorityQueue(); |
119 | |
120 | $listeners = clone $this->listeners[$name]; |
121 | $listeners->setExtractFlags(\SplPriorityQueue::EXTR_BOTH); |
122 | |
123 | foreach ($listeners as $value) { |
124 | $item = $listeners->current(); |
125 | if ($action !== $item['data']) { |
126 | $newListeners->insert($item['data'], $item['priority']); |
127 | } |
128 | } |
129 | |
130 | $this->listeners[$name] = $newListeners; |
131 | } |
132 | |
133 | return $this; |
134 | } |
135 | |
136 | /** |
137 | * Return an event |
138 | * |
139 | * @param string $name |
140 | * @return mixed |
141 | */ |
142 | public function get(string $name): mixed |
143 | { |
144 | $listener = null; |
145 | if (isset($this->listeners[$name])) { |
146 | $listener = $this->listeners[$name]; |
147 | } |
148 | |
149 | return $listener; |
150 | } |
151 | |
152 | /** |
153 | * Determine whether the event manage has an event registered with it |
154 | * |
155 | * @param string $name |
156 | * @return bool |
157 | */ |
158 | public function has(string $name): bool |
159 | { |
160 | return (isset($this->listeners[$name])); |
161 | } |
162 | |
163 | /** |
164 | * Return the event results |
165 | * |
166 | * @param string $name |
167 | * @return mixed |
168 | */ |
169 | public function getResults(string $name): mixed |
170 | { |
171 | return $this->results[$name] ?? null; |
172 | } |
173 | |
174 | /** |
175 | * Determine if the project application is still alive or has been killed |
176 | * |
177 | * @return bool |
178 | */ |
179 | public function alive(): bool |
180 | { |
181 | return $this->alive; |
182 | } |
183 | |
184 | /** |
185 | * Trigger an event listener priority |
186 | * |
187 | * @param string $name |
188 | * @param array $params |
189 | * @return void |
190 | */ |
191 | public function trigger(string $name, array $params = []): void |
192 | { |
193 | if (isset($this->listeners[$name])) { |
194 | if (!isset($this->results[$name])) { |
195 | $this->results[$name] = []; |
196 | } |
197 | |
198 | foreach ($this->listeners[$name] as $action) { |
199 | if (end($this->results[$name]) == self::STOP) { |
200 | return; |
201 | } |
202 | |
203 | $params['result'] = end($this->results[$name]); |
204 | $result = $action->call($params); |
205 | $this->results[$name][] = $result; |
206 | |
207 | if ($result == self::KILL) { |
208 | $this->alive = false; |
209 | } |
210 | } |
211 | } |
212 | } |
213 | |
214 | /** |
215 | * Set an event |
216 | * |
217 | * @param string $name |
218 | * @param mixed $value |
219 | * @return void |
220 | */ |
221 | public function __set(string $name, mixed $value): void |
222 | { |
223 | $this->on($name, $value); |
224 | } |
225 | |
226 | /** |
227 | * Get an event |
228 | * |
229 | * @param string $name |
230 | * @return mixed |
231 | */ |
232 | public function __get(string $name): mixed |
233 | { |
234 | return $this->get($name); |
235 | } |
236 | |
237 | /** |
238 | * Determine if an event exists |
239 | * |
240 | * @param string $name |
241 | * @return bool |
242 | */ |
243 | public function __isset(string $name): bool |
244 | { |
245 | return $this->has($name); |
246 | } |
247 | |
248 | /** |
249 | * Unset an event |
250 | * |
251 | * @param string $name |
252 | * @return void |
253 | */ |
254 | public function __unset(string $name): void |
255 | { |
256 | if (isset($this->listeners[$name])) { |
257 | unset($this->listeners[$name]); |
258 | } |
259 | } |
260 | |
261 | /** |
262 | * Set an event |
263 | * |
264 | * @param mixed $offset |
265 | * @param mixed $value |
266 | * @return void |
267 | */ |
268 | public function offsetSet(mixed $offset, mixed $value): void |
269 | { |
270 | $this->on($offset, $value); |
271 | } |
272 | |
273 | /** |
274 | * Get an event |
275 | * |
276 | * @param mixed $offset |
277 | * @return mixed |
278 | */ |
279 | public function offsetGet(mixed $offset): mixed |
280 | { |
281 | return $this->get($offset); |
282 | } |
283 | |
284 | /** |
285 | * Determine if an event exists |
286 | * |
287 | * @param string $offset |
288 | * @return bool |
289 | */ |
290 | public function offsetExists($offset): bool |
291 | { |
292 | return $this->has($offset); |
293 | } |
294 | |
295 | /** |
296 | * Unset an event |
297 | * |
298 | * @param mixed $offset |
299 | * @return void |
300 | */ |
301 | public function offsetUnset(mixed $offset): void |
302 | { |
303 | if (isset($this->listeners[$offset])) { |
304 | unset($this->listeners[$offset]); |
305 | } |
306 | } |
307 | |
308 | /** |
309 | * Return count |
310 | * |
311 | * @return int |
312 | */ |
313 | public function count(): int |
314 | { |
315 | return count($this->listeners); |
316 | } |
317 | |
318 | /** |
319 | * Get iterator |
320 | * |
321 | * @return ArrayIterator |
322 | */ |
323 | public function getIterator(): ArrayIterator |
324 | { |
325 | return new ArrayIterator($this->listeners); |
326 | } |
327 | |
328 | } |