<?php namespace Symfony\Component\EventDispatcher; class EventDispatcher implements EventDispatcherInterface { private $listeners = array(); private $sorted = array(); public function dispatch($eventName, Event $event = null) { if (null === $event) { $event = new Event(); } $event->setDispatcher($this); $event->setName($eventName); if (!isset($this->listeners[$eventName])) { return $event; } $this->doDispatch($this->getListeners($eventName), $eventName, $event); return $event; } public function getListeners($eventName = null) { if (null !== $eventName) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } return $this->sorted[$eventName]; } foreach (array_keys($this->listeners) as $eventName) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } } return $this->sorted; } public function hasListeners($eventName = null) { return (Boolean) count($this->getListeners($eventName)); } public function addListener($eventName, $listener, $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; unset($this->sorted[$eventName]); } 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], $this->sorted[$eventName]); } } } public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->addListener($eventName, array($subscriber, $params)); } elseif (is_string($params[0])) { $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); } } } } public function removeSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_array($params) && is_array($params[0])) { foreach ($params as $listener) { $this->removeListener($eventName, array($subscriber, $listener[0])); } } else { $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0])); } } } protected function doDispatch($listeners, $eventName, Event $event) { foreach ($listeners as $listener) { call_user_func($listener, $event); if ($event->isPropagationStopped()) { break; } } } private function sortListeners($eventName) { $this->sorted[$eventName] = array(); if (isset($this->listeners[$eventName])) { krsort($this->listeners[$eventName]); $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } } }