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