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