This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php namespace nyx\events\traits; |
||
2 | |||
3 | // Internal dependencies |
||
4 | use nyx\events\interfaces; |
||
5 | |||
6 | /** |
||
7 | * Event Emitter |
||
8 | * |
||
9 | * Important note: When using this trait, make sure the class you are using it in also implements the Emitter |
||
10 | * interface. |
||
11 | * |
||
12 | * @version 0.1.0 |
||
13 | * @author Michal Chojnacki <[email protected]> |
||
14 | * @copyright 2012-2017 Nyx Dev Team |
||
15 | * @link https://github.com/unyx/nyx |
||
16 | */ |
||
17 | trait Emitter |
||
18 | { |
||
19 | /** |
||
20 | * @var array The registered listeners. |
||
21 | */ |
||
22 | private $listeners = []; |
||
23 | |||
24 | /** |
||
25 | * @var array The priority-sorted chain of listeners. |
||
26 | */ |
||
27 | private $chain = []; |
||
28 | |||
29 | /** |
||
30 | * @see \nyx\events\interfaces\Emitter::emit() |
||
31 | */ |
||
32 | public function emit($event, ...$payload) |
||
33 | { |
||
34 | // If an object implementing the Event interface gets passed in as the first argument, |
||
35 | // we are going to use its name as the trigger and prepend the object itself to the payload. |
||
36 | if ($event instanceof interfaces\Event) { |
||
37 | array_unshift($payload, $event); |
||
38 | $event = $event->getType(); |
||
39 | } |
||
40 | |||
41 | // If there are no listeners for this event, stop further processing. |
||
42 | if (!isset($this->listeners[$event])) { |
||
43 | return; |
||
44 | } |
||
45 | |||
46 | // Loop through all listeners and invoke the respective callbacks. |
||
47 | foreach ($this->getListeners($event) as $listener) { |
||
48 | $listener(...$payload); |
||
49 | } |
||
50 | } |
||
51 | |||
52 | /** |
||
53 | * @see \nyx\events\interfaces\Emitter::on() |
||
54 | */ |
||
55 | public function on(string $event, callable $listener, int $priority = 0) : interfaces\Emitter |
||
56 | { |
||
57 | // Register the listener for the given event. |
||
58 | $this->listeners[$event][$priority][] = $listener; |
||
59 | |||
60 | // Make sure we reset the priority chain as this listener might have been added after it |
||
61 | // had already been sorted. |
||
62 | unset($this->chain[$event]); |
||
63 | |||
64 | return $this; |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * @see \nyx\events\interfaces\Emitter::once() |
||
69 | */ |
||
70 | public function once(string $event, callable $listener, int $priority = 0) : interfaces\Emitter |
||
71 | { |
||
72 | // We'll create a wrapper closure which will remove the listener once it receives the first event |
||
73 | // and forward the arguments from the wrapper to the actual listener. |
||
74 | $wrapper = function (...$payload) use (&$wrapper, $event, $listener) { |
||
75 | $this->off($event, $wrapper); |
||
76 | |||
77 | $listener(...$payload); |
||
78 | }; |
||
79 | |||
80 | // Register the wrapper. |
||
81 | return $this->on($event, $wrapper, $priority); |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * @see \nyx\events\interfaces\Emitter::off() |
||
86 | */ |
||
87 | public function off(string $event = null, callable $listener = null) : interfaces\Emitter |
||
88 | { |
||
89 | // When no listener is specified, we will be removing either all listeners altogether |
||
90 | // or the listeners for the specified event name. |
||
91 | if (!isset($listener)) { |
||
92 | if (isset($event)) { |
||
93 | unset($this->listeners[$event], $this->chain[$event]); |
||
94 | } else { |
||
95 | $this->listeners = []; |
||
96 | $this->chain = []; |
||
97 | } |
||
98 | |||
99 | return $this; |
||
100 | } |
||
101 | |||
102 | // Without a name but with a listener callable we are going to remove the specified listener from |
||
103 | // all events it's listening to. Note that this is a costly operation and should be avoided if you can. |
||
104 | if (!isset($event)) { |
||
105 | return $this->removeListener($listener); |
||
106 | } |
||
107 | |||
108 | // If we get to this point it means we were given both a name and a listener. |
||
109 | return $this->removeListenerFromEvent($listener, $event); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * @see \nyx\events\interfaces\Emitter::register() |
||
114 | */ |
||
115 | public function register(interfaces\Subscriber $subscriber) : interfaces\Emitter |
||
116 | { |
||
117 | foreach ($subscriber->getSubscribedEvents() as $event => $params) { |
||
118 | // If just a callable was given. |
||
119 | if (is_string($params)) { |
||
120 | $this->on($event, [$subscriber, $params]); |
||
121 | } |
||
122 | // A callable and a priority. |
||
123 | elseif (isset($params[0]) && is_string($params[0])) { |
||
124 | $this->on($event, [$subscriber, $params[0]], isset($params[1]) ? $params[1] : 0); |
||
125 | } |
||
126 | // An array of callables (and their optional priorities) |
||
127 | else { |
||
128 | foreach ($params as $listener) { |
||
129 | $this->on($event, [$subscriber, $listener[0]], isset($listener[1]) ? $listener[1] : 0); |
||
130 | } |
||
131 | } |
||
132 | } |
||
133 | |||
134 | return $this; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * @see \nyx\events\interfaces\Emitter::deregister() |
||
139 | */ |
||
140 | public function deregister(interfaces\Subscriber $subscriber) : interfaces\Emitter |
||
141 | { |
||
142 | foreach ($subscriber->getSubscribedEvents() as $event => $params) { |
||
143 | if (is_array($params) && is_array($params[0])) { |
||
144 | foreach ($params as $listener) { |
||
145 | $this->off($event, [$subscriber, $listener[0]]); |
||
146 | } |
||
147 | } else { |
||
148 | $this->off($event, [$subscriber, is_string($params) ? $params : $params[0]]); |
||
149 | } |
||
150 | } |
||
151 | |||
152 | return $this; |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * @see \nyx\events\interfaces\Emitter::getListeners() |
||
157 | */ |
||
158 | public function getListeners(string $event = null) : array |
||
159 | { |
||
160 | // Sort the listeners for a given trigger name and return that subset. |
||
161 | if (isset($event)) { |
||
162 | if (!isset($this->chain[$event])) { |
||
163 | $this->sortListeners($event); |
||
164 | } |
||
165 | |||
166 | return $this->chain[$event]; |
||
167 | } |
||
168 | |||
169 | // If no trigger name was given, sort all listeners and return them. |
||
170 | foreach (array_keys($this->listeners) as $event) { |
||
171 | if (!isset($this->chain[$event])) { |
||
172 | $this->sortListeners($event); |
||
173 | } |
||
174 | } |
||
175 | |||
176 | return $this->chain; |
||
177 | } |
||
178 | |||
179 | /** |
||
180 | * @see \nyx\events\interfaces\Emitter::hasListeners() |
||
181 | */ |
||
182 | public function hasListeners(string $event = null) : bool |
||
183 | { |
||
184 | return count($this->getListeners($event)) > 0; |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * @see \nyx\events\interfaces\Emitter::countListeners() |
||
189 | */ |
||
190 | public function countListeners(string $event = null) : int |
||
191 | { |
||
192 | return count($this->getListeners($event)); |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Removes the given listener from all events it is listening to. |
||
197 | * |
||
198 | * @param callable $listener The listener to remove. |
||
199 | * @return $this |
||
200 | */ |
||
201 | View Code Duplication | protected function removeListener(callable $listener) : interfaces\Emitter |
|
0 ignored issues
–
show
|
|||
202 | { |
||
203 | foreach ($this->listeners as $event => $priorityMap) { |
||
204 | foreach ($priorityMap as $priority => $listeners) { |
||
205 | if (false !== $key = array_search($listener, $listeners, true)) { |
||
206 | unset($this->listeners[$event][$priority][$key], $this->chain[$event]); |
||
207 | } |
||
208 | } |
||
209 | } |
||
210 | |||
211 | return $this; |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * Removes the given listener from the given event. |
||
216 | * |
||
217 | * @param callable $listener The listener to remove. |
||
218 | * @param string $event The event to remove the listener from. |
||
219 | * @return $this |
||
220 | */ |
||
221 | View Code Duplication | protected function removeListenerFromEvent(callable $listener, string $event) : interfaces\Emitter |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
222 | { |
||
223 | foreach ($this->listeners[$event] as $priority => $listeners) { |
||
224 | if (false !== $key = array_search($listener, $listeners, true)) { |
||
225 | unset($this->listeners[$event][$priority][$key], $this->chain[$event]); |
||
226 | } |
||
227 | } |
||
228 | |||
229 | return $this; |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * Sorts the listeners for the given event name descending by priority, so the higher priority listeners |
||
234 | * can get called first in the chain. |
||
235 | * |
||
236 | * @param string $event The name of the event. |
||
237 | * @return $this |
||
238 | */ |
||
239 | protected function sortListeners(string $event) : interfaces\Emitter |
||
240 | { |
||
241 | if (!isset($this->listeners[$event])) { |
||
242 | return $this; |
||
243 | } |
||
244 | |||
245 | // Sort the listeners by priority in a descending order. |
||
246 | krsort($this->listeners[$event]); |
||
247 | |||
248 | $this->chain[$event] = array_merge(...$this->listeners[$event]); |
||
249 | |||
250 | return $this; |
||
251 | } |
||
252 | } |
||
253 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.