* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bundle\FrameworkBundle; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\Event; /** * Lazily loads listeners and subscribers from the dependency injection * container * * @author Fabien Potencier * @author Bernhard Schussek */ class ContainerAwareEventDispatcher extends EventDispatcher { /** * The container from where services are loaded * @var ContainerInterface */ private $container; /** * The service IDs of the event listeners and subscribers * @var array */ private $listenerIds = array(); /** * The services registered as listeners * @var array */ private $listeners = array(); /** * Constructor. * * @param ContainerInterface $container A ContainerInterface instance */ public function __construct(ContainerInterface $container) { $this->container = $container; } /** * Adds a service as event listener * * @param string $eventName Event for which the listener is added * @param array $callback The service ID of the listener service & the method * name that has to be called * @param integer $priority The higher this value, the earlier an event listener * will be triggered in the chain. * Defaults to 0. */ public function addListenerService($eventName, $callback, $priority = 0) { if (!is_array($callback) || 2 !== count($callback)) { throw new \InvalidArgumentException('Expected an array("service", "method") argument'); } $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); } /** * {@inheritDoc} * * Lazily loads listeners for this event from the dependency injection * container. * * @throws \InvalidArgumentException if the service is not defined */ public function dispatch($eventName, Event $event = null) { if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $args) { list($serviceId, $method, $priority) = $args; $listener = $this->container->get($serviceId); $key = $serviceId.'.'.$method; if (!isset($this->listeners[$eventName][$key])) { $this->addListener($eventName, array($listener, $method), $priority); } elseif ($listener !== $this->listeners[$eventName][$key]) { $this->removeListener($eventName, array($this->listeners[$eventName][$key], $method)); $this->addListener($eventName, array($listener, $method), $priority); } $this->listeners[$eventName][$key] = $listener; } } parent::dispatch($eventName, $event); } }