]>
Commit | Line | Data |
---|---|---|
4f5b44bd NL |
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 | * | |
28 | * @api | |
29 | */ | |
30 | class EventDispatcher implements EventDispatcherInterface | |
31 | { | |
32 | private $listeners = array(); | |
33 | private $sorted = array(); | |
34 | ||
35 | /** | |
36 | * @see EventDispatcherInterface::dispatch | |
37 | * | |
38 | * @api | |
39 | */ | |
40 | public function dispatch($eventName, Event $event = null) | |
41 | { | |
42 | if (null === $event) { | |
43 | $event = new Event(); | |
44 | } | |
45 | ||
46 | $event->setDispatcher($this); | |
47 | $event->setName($eventName); | |
48 | ||
49 | if (!isset($this->listeners[$eventName])) { | |
50 | return $event; | |
51 | } | |
52 | ||
53 | $this->doDispatch($this->getListeners($eventName), $eventName, $event); | |
54 | ||
55 | return $event; | |
56 | } | |
57 | ||
58 | /** | |
59 | * @see EventDispatcherInterface::getListeners | |
60 | */ | |
61 | public function getListeners($eventName = null) | |
62 | { | |
63 | if (null !== $eventName) { | |
64 | if (!isset($this->sorted[$eventName])) { | |
65 | $this->sortListeners($eventName); | |
66 | } | |
67 | ||
68 | return $this->sorted[$eventName]; | |
69 | } | |
70 | ||
71 | foreach (array_keys($this->listeners) as $eventName) { | |
72 | if (!isset($this->sorted[$eventName])) { | |
73 | $this->sortListeners($eventName); | |
74 | } | |
75 | } | |
76 | ||
77 | return $this->sorted; | |
78 | } | |
79 | ||
80 | /** | |
81 | * @see EventDispatcherInterface::hasListeners | |
82 | */ | |
83 | public function hasListeners($eventName = null) | |
84 | { | |
85 | return (Boolean) count($this->getListeners($eventName)); | |
86 | } | |
87 | ||
88 | /** | |
89 | * @see EventDispatcherInterface::addListener | |
90 | * | |
91 | * @api | |
92 | */ | |
93 | public function addListener($eventName, $listener, $priority = 0) | |
94 | { | |
95 | $this->listeners[$eventName][$priority][] = $listener; | |
96 | unset($this->sorted[$eventName]); | |
97 | } | |
98 | ||
99 | /** | |
100 | * @see EventDispatcherInterface::removeListener | |
101 | */ | |
102 | public function removeListener($eventName, $listener) | |
103 | { | |
104 | if (!isset($this->listeners[$eventName])) { | |
105 | return; | |
106 | } | |
107 | ||
108 | foreach ($this->listeners[$eventName] as $priority => $listeners) { | |
109 | if (false !== ($key = array_search($listener, $listeners, true))) { | |
110 | unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]); | |
111 | } | |
112 | } | |
113 | } | |
114 | ||
115 | /** | |
116 | * @see EventDispatcherInterface::addSubscriber | |
117 | * | |
118 | * @api | |
119 | */ | |
120 | public function addSubscriber(EventSubscriberInterface $subscriber) | |
121 | { | |
122 | foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { | |
123 | if (is_string($params)) { | |
124 | $this->addListener($eventName, array($subscriber, $params)); | |
125 | } elseif (is_string($params[0])) { | |
126 | $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); | |
127 | } else { | |
128 | foreach ($params as $listener) { | |
129 | $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); | |
130 | } | |
131 | } | |
132 | } | |
133 | } | |
134 | ||
135 | /** | |
136 | * @see EventDispatcherInterface::removeSubscriber | |
137 | */ | |
138 | public function removeSubscriber(EventSubscriberInterface $subscriber) | |
139 | { | |
140 | foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { | |
141 | if (is_array($params) && is_array($params[0])) { | |
142 | foreach ($params as $listener) { | |
143 | $this->removeListener($eventName, array($subscriber, $listener[0])); | |
144 | } | |
145 | } else { | |
146 | $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0])); | |
147 | } | |
148 | } | |
149 | } | |
150 | ||
151 | /** | |
152 | * Triggers the listeners of an event. | |
153 | * | |
154 | * This method can be overridden to add functionality that is executed | |
155 | * for each listener. | |
156 | * | |
157 | * @param array[callback] $listeners The event listeners. | |
158 | * @param string $eventName The name of the event to dispatch. | |
159 | * @param Event $event The event object to pass to the event handlers/listeners. | |
160 | */ | |
161 | protected function doDispatch($listeners, $eventName, Event $event) | |
162 | { | |
163 | foreach ($listeners as $listener) { | |
164 | call_user_func($listener, $event); | |
165 | if ($event->isPropagationStopped()) { | |
166 | break; | |
167 | } | |
168 | } | |
169 | } | |
170 | ||
171 | /** | |
172 | * Sorts the internal list of listeners for the given event by priority. | |
173 | * | |
174 | * @param string $eventName The name of the event. | |
175 | */ | |
176 | private function sortListeners($eventName) | |
177 | { | |
178 | $this->sorted[$eventName] = array(); | |
179 | ||
180 | if (isset($this->listeners[$eventName])) { | |
181 | krsort($this->listeners[$eventName]); | |
182 | $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); | |
183 | } | |
184 | } | |
185 | } |