|
6 | 6 |
|
7 | 7 | class EventDispatcher |
8 | 8 | { |
9 | | - /** @var self|null Singleton instance of the EventDispatcher */ |
10 | 9 | private static ?self $instance = null; |
11 | 10 |
|
12 | | - /** @var array<string, array<int, callable>> */ |
| 11 | + /** @var array<string, callable[]> */ |
13 | 12 | protected array $listeners = []; |
14 | 13 |
|
15 | | - /** |
16 | | - * Singleton instance of the EventDispatcher. |
17 | | - * |
18 | | - * @return self |
19 | | - */ |
20 | 14 | public static function getInstance(): self |
21 | 15 | { |
22 | 16 | if (self::$instance === null) { |
23 | 17 | self::$instance = new self(); |
24 | 18 | } |
| 19 | + |
25 | 20 | return self::$instance; |
26 | 21 | } |
27 | 22 |
|
28 | | - /** |
29 | | - * Register a callback for an event. |
30 | | - * |
31 | | - * @param string $event Event name |
32 | | - * @param callable $callback Callback function |
33 | | - */ |
34 | 23 | public function on(string $event, callable $callback): void |
35 | 24 | { |
36 | | - if (isset($this->listeners[$event]) === false) { |
37 | | - $this->listeners[$event] = []; |
38 | | - } |
| 25 | + $this->listeners[$event] ??= []; |
39 | 26 | $this->listeners[$event][] = $callback; |
40 | 27 | } |
41 | 28 |
|
42 | 29 | /** |
43 | | - * Trigger an event with optional arguments. |
44 | | - * |
45 | | - * @param string $event Event name |
46 | | - * @param mixed ...$args Arguments to pass to the callbacks |
47 | | - * |
| 30 | + * @param mixed ...$args Arguments to pass to the listeners. |
48 | 31 | * @return mixed |
49 | 32 | */ |
50 | 33 | public function trigger(string $event, ...$args) |
51 | 34 | { |
52 | | - $result = null; |
53 | | - if (isset($this->listeners[$event]) === true) { |
54 | | - foreach ($this->listeners[$event] as $callback) { |
55 | | - $result = call_user_func_array($callback, $args); |
56 | | - |
57 | | - // If you return false, it will break the loop and stop the other event listeners. |
58 | | - if ($result === false) { |
59 | | - break; // Stop executing further listeners |
60 | | - } |
| 35 | + $listenerReturnValue = null; |
| 36 | + |
| 37 | + foreach ($this->getListeners($event) as $listener) { |
| 38 | + $listenerReturnValue = $listener(...$args); |
| 39 | + |
| 40 | + if ($listenerReturnValue === false) { |
| 41 | + break; |
61 | 42 | } |
62 | 43 | } |
63 | | - return $result; |
| 44 | + |
| 45 | + return $listenerReturnValue; |
64 | 46 | } |
65 | 47 |
|
66 | | - /** |
67 | | - * Check if an event has any registered listeners. |
68 | | - * |
69 | | - * @param string $event Event name |
70 | | - * |
71 | | - * @return bool True if the event has listeners, false otherwise |
72 | | - */ |
73 | 48 | public function hasListeners(string $event): bool |
74 | 49 | { |
75 | | - return isset($this->listeners[$event]) === true && count($this->listeners[$event]) > 0; |
| 50 | + return ( |
| 51 | + isset($this->listeners[$event]) |
| 52 | + && is_array($this->listeners[$event]) |
| 53 | + && count($this->listeners[$event]) |
| 54 | + ); |
76 | 55 | } |
77 | 56 |
|
78 | | - /** |
79 | | - * Get all listeners registered for a specific event. |
80 | | - * |
81 | | - * @param string $event Event name |
82 | | - * |
83 | | - * @return array<int, callable> Array of callbacks registered for the event |
84 | | - */ |
| 57 | + /** @return callable[] */ |
85 | 58 | public function getListeners(string $event): array |
86 | 59 | { |
87 | 60 | return $this->listeners[$event] ?? []; |
88 | 61 | } |
89 | 62 |
|
90 | | - /** |
91 | | - * Get a list of all events that have registered listeners. |
92 | | - * |
93 | | - * @return array<int, string> Array of event names |
94 | | - */ |
| 63 | + /** @return string[] */ |
95 | 64 | public function getAllRegisteredEvents(): array |
96 | 65 | { |
97 | 66 | return array_keys($this->listeners); |
98 | 67 | } |
99 | 68 |
|
100 | | - /** |
101 | | - * Remove a specific listener for an event. |
102 | | - * |
103 | | - * @param string $event the event name |
104 | | - * @param callable $callback the exact callback to remove |
105 | | - * |
106 | | - * @return void |
107 | | - */ |
108 | 69 | public function removeListener(string $event, callable $callback): void |
109 | 70 | { |
110 | | - if (isset($this->listeners[$event]) === true && count($this->listeners[$event]) > 0) { |
111 | | - $this->listeners[$event] = array_filter($this->listeners[$event], function ($listener) use ($callback) { |
112 | | - return $listener !== $callback; |
113 | | - }); |
114 | | - $this->listeners[$event] = array_values($this->listeners[$event]); // Re-index the array |
| 71 | + if (!$this->hasListeners($event)) { |
| 72 | + return; |
115 | 73 | } |
| 74 | + |
| 75 | + $this->listeners[$event] = array_values(array_filter( |
| 76 | + $this->getListeners($event), |
| 77 | + static fn(callable $listener): bool => $listener !== $callback, |
| 78 | + )); |
116 | 79 | } |
117 | 80 |
|
118 | | - /** |
119 | | - * Remove all listeners for a specific event. |
120 | | - * |
121 | | - * @param string $event the event name |
122 | | - * |
123 | | - * @return void |
124 | | - */ |
125 | 81 | public function removeAllListeners(string $event): void |
126 | 82 | { |
127 | | - if (isset($this->listeners[$event]) === true) { |
128 | | - unset($this->listeners[$event]); |
129 | | - } |
| 83 | + unset($this->listeners[$event]); |
130 | 84 | } |
131 | 85 |
|
132 | | - /** |
133 | | - * Remove the current singleton instance of the EventDispatcher. |
134 | | - * |
135 | | - * @return void |
136 | | - */ |
137 | 86 | public static function resetInstance(): void |
138 | 87 | { |
139 | 88 | self::$instance = null; |
|
0 commit comments