bc79a958da127ba019cc3a7f7defb0f887fbde5c
[yaffs-website] / vendor / symfony / event-dispatcher / EventDispatcher.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\EventDispatcher;
13
14 /**
15  * The EventDispatcherInterface is the central point of Symfony's event listener system.
16  *
17  * Listeners are registered on the manager and events are dispatched through the
18  * manager.
19  *
20  * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
21  * @author Jonathan Wage <jonwage@gmail.com>
22  * @author Roman Borschel <roman@code-factory.org>
23  * @author Bernhard Schussek <bschussek@gmail.com>
24  * @author Fabien Potencier <fabien@symfony.com>
25  * @author Jordi Boggiano <j.boggiano@seld.be>
26  * @author Jordan Alliot <jordan.alliot@gmail.com>
27  * @author Nicolas Grekas <p@tchwork.com>
28  */
29 class EventDispatcher implements EventDispatcherInterface
30 {
31     private $listeners = array();
32     private $sorted = array();
33
34     /**
35      * {@inheritdoc}
36      */
37     public function dispatch($eventName, Event $event = null)
38     {
39         if (null === $event) {
40             $event = new Event();
41         }
42
43         if ($listeners = $this->getListeners($eventName)) {
44             $this->doDispatch($listeners, $eventName, $event);
45         }
46
47         return $event;
48     }
49
50     /**
51      * {@inheritdoc}
52      */
53     public function getListeners($eventName = null)
54     {
55         if (null !== $eventName) {
56             if (empty($this->listeners[$eventName])) {
57                 return array();
58             }
59
60             if (!isset($this->sorted[$eventName])) {
61                 $this->sortListeners($eventName);
62             }
63
64             return $this->sorted[$eventName];
65         }
66
67         foreach ($this->listeners as $eventName => $eventListeners) {
68             if (!isset($this->sorted[$eventName])) {
69                 $this->sortListeners($eventName);
70             }
71         }
72
73         return array_filter($this->sorted);
74     }
75
76     /**
77      * {@inheritdoc}
78      */
79     public function getListenerPriority($eventName, $listener)
80     {
81         if (empty($this->listeners[$eventName])) {
82             return;
83         }
84
85         if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
86             $listener[0] = $listener[0]();
87         }
88
89         foreach ($this->listeners[$eventName] as $priority => $listeners) {
90             foreach ($listeners as $k => $v) {
91                 if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
92                     $v[0] = $v[0]();
93                     $this->listeners[$eventName][$priority][$k] = $v;
94                 }
95                 if ($v === $listener) {
96                     return $priority;
97                 }
98             }
99         }
100     }
101
102     /**
103      * {@inheritdoc}
104      */
105     public function hasListeners($eventName = null)
106     {
107         if (null !== $eventName) {
108             return !empty($this->listeners[$eventName]);
109         }
110
111         foreach ($this->listeners as $eventListeners) {
112             if ($eventListeners) {
113                 return true;
114             }
115         }
116
117         return false;
118     }
119
120     /**
121      * {@inheritdoc}
122      */
123     public function addListener($eventName, $listener, $priority = 0)
124     {
125         $this->listeners[$eventName][$priority][] = $listener;
126         unset($this->sorted[$eventName]);
127     }
128
129     /**
130      * {@inheritdoc}
131      */
132     public function removeListener($eventName, $listener)
133     {
134         if (empty($this->listeners[$eventName])) {
135             return;
136         }
137
138         if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
139             $listener[0] = $listener[0]();
140         }
141
142         foreach ($this->listeners[$eventName] as $priority => $listeners) {
143             foreach ($listeners as $k => $v) {
144                 if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
145                     $v[0] = $v[0]();
146                 }
147                 if ($v === $listener) {
148                     unset($listeners[$k], $this->sorted[$eventName]);
149                 } else {
150                     $listeners[$k] = $v;
151                 }
152             }
153
154             if ($listeners) {
155                 $this->listeners[$eventName][$priority] = $listeners;
156             } else {
157                 unset($this->listeners[$eventName][$priority]);
158             }
159         }
160     }
161
162     /**
163      * {@inheritdoc}
164      */
165     public function addSubscriber(EventSubscriberInterface $subscriber)
166     {
167         foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
168             if (is_string($params)) {
169                 $this->addListener($eventName, array($subscriber, $params));
170             } elseif (is_string($params[0])) {
171                 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
172             } else {
173                 foreach ($params as $listener) {
174                     $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
175                 }
176             }
177         }
178     }
179
180     /**
181      * {@inheritdoc}
182      */
183     public function removeSubscriber(EventSubscriberInterface $subscriber)
184     {
185         foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
186             if (is_array($params) && is_array($params[0])) {
187                 foreach ($params as $listener) {
188                     $this->removeListener($eventName, array($subscriber, $listener[0]));
189                 }
190             } else {
191                 $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0]));
192             }
193         }
194     }
195
196     /**
197      * Triggers the listeners of an event.
198      *
199      * This method can be overridden to add functionality that is executed
200      * for each listener.
201      *
202      * @param callable[] $listeners The event listeners
203      * @param string     $eventName The name of the event to dispatch
204      * @param Event      $event     The event object to pass to the event handlers/listeners
205      */
206     protected function doDispatch($listeners, $eventName, Event $event)
207     {
208         foreach ($listeners as $listener) {
209             if ($event->isPropagationStopped()) {
210                 break;
211             }
212             \call_user_func($listener, $event, $eventName, $this);
213         }
214     }
215
216     /**
217      * Sorts the internal list of listeners for the given event by priority.
218      *
219      * @param string $eventName The name of the event
220      */
221     private function sortListeners($eventName)
222     {
223         krsort($this->listeners[$eventName]);
224         $this->sorted[$eventName] = array();
225
226         foreach ($this->listeners[$eventName] as $priority => $listeners) {
227             foreach ($listeners as $k => $listener) {
228                 if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
229                     $listener[0] = $listener[0]();
230                     $this->listeners[$eventName][$priority][$k] = $listener;
231                 }
232                 $this->sorted[$eventName][] = $listener;
233             }
234         }
235     }
236 }