. */ namespace Symfony\Component\EventDispatcher; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * * Listeners are registered on the manager and events are dispatched through the * manager. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * @author Fabien Potencier * @author Jordi Boggiano * * @api */ class EventDispatcher implements EventDispatcherInterface { private $listeners = array(); /** * @see EventDispatcherInterface::dispatch * * @api */ public function dispatch($eventName, Event $event = null) { if (!isset($this->listeners[$eventName])) { return; } if (null === $event) { $event = new Event(); } $this->doDispatch($this->getListeners($eventName), $eventName, $event); } /** * @see EventDispatcherInterface::getListeners * * @api */ public function getListeners($eventName = null) { if (null !== $eventName) { return $this->sortListeners($eventName); } $sorted = array(); foreach (array_keys($this->listeners) as $eventName) { $sorted[$eventName] = $this->sortListeners($eventName); } return $sorted; } /** * @see EventDispatcherInterface::hasListeners * * @api */ public function hasListeners($eventName = null) { return (Boolean) count($this->getListeners($eventName)); } /** * @see EventDispatcherInterface::addListener * * @api */ public function addListener($eventName, $listener, $priority = 0) { if (!isset($this->listeners[$eventName][$priority])) { if (!isset($this->listeners[$eventName])) { $this->listeners[$eventName] = array(); } $this->listeners[$eventName][$priority] = array(); } $this->listeners[$eventName][$priority][] = $listener; } /** * @see EventDispatcherInterface::removeListener */ public function removeListener($eventName, $listener) { if (!isset($this->listeners[$eventName])) { return; } foreach ($this->listeners[$eventName] as $priority => $listeners) { if (false !== ($key = array_search($listener, $listeners))) { unset($this->listeners[$eventName][$priority][$key]); } } } /** * @see EventDispatcherInterface::addSubscriber */ public function addSubscriber(EventSubscriberInterface $subscriber, $priority = 0) { foreach ((array) $subscriber->getSubscribedEvents() as $eventName => $method) { $this->addListener($eventName, array($subscriber, $method), $priority); } } /** * @see EventDispatcherInterface::removeSubscriber */ public function removeSubscriber(EventSubscriberInterface $subscriber) { foreach ((array) $subscriber->getSubscribedEvents() as $eventName => $method) { $this->removeListener($eventName, array($subscriber, $method)); } } /** * Triggers the listeners of an event. * * This method can be overridden to add functionality that is executed * for each listener. * * @param array[callback] $listeners The event listeners. * @param string $eventName The name of the event to dispatch. * @param Event $event The event object to pass to the event handlers/listeners. */ protected function doDispatch($listeners, $eventName, Event $event) { foreach ($listeners as $listener) { call_user_func($listener, $event); if ($event->isPropagationStopped()) { break; } } } /** * Sorts the internal list of listeners for the given event by priority. * * @param string $eventName The name of the event. */ private function sortListeners($eventName) { if (!isset($this->listeners[$eventName])) { return array(); } krsort($this->listeners[$eventName]); return call_user_func_array('array_merge', $this->listeners[$eventName]); } }