class ContainerAwareEventDispatcher

Lazily loads listeners and subscribers from the dependency injection container

@author Fabien Potencier <fabien@symfony.com> @author Bernhard Schussek <bschussek@gmail.com> @author Jordan Alliot <jordan.alliot@gmail.com>

Hierarchy

Expanded class hierarchy of ContainerAwareEventDispatcher

1 file declares its use of ContainerAwareEventDispatcher
ContainerAwareEventDispatcherTest.php in drupal/core/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php
1 string reference to 'ContainerAwareEventDispatcher'
core.services.yml in drupal/core/core.services.yml
drupal/core/core.services.yml

File

drupal/core/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php, line 24

Namespace

Symfony\Component\EventDispatcher
View source
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.
   *
   * @throws \InvalidArgumentException
   */
  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,
    );
  }
  public function removeListener($eventName, $listener) {
    $this
      ->lazyLoad($eventName);
    if (isset($this->listeners[$eventName])) {
      foreach ($this->listeners[$eventName] as $key => $l) {
        foreach ($this->listenerIds[$eventName] as $i => $args) {
          list($serviceId, $method, $priority) = $args;
          if ($key === $serviceId . '.' . $method) {
            if ($listener === array(
              $l,
              $method,
            )) {
              unset($this->listeners[$eventName][$key]);
              if (empty($this->listeners[$eventName])) {
                unset($this->listeners[$eventName]);
              }
              unset($this->listenerIds[$eventName][$i]);
              if (empty($this->listenerIds[$eventName])) {
                unset($this->listenerIds[$eventName]);
              }
            }
          }
        }
      }
    }
    parent::removeListener($eventName, $listener);
  }

  /**
   * @see EventDispatcherInterface::hasListeners
   */
  public function hasListeners($eventName = null) {
    if (null === $eventName) {
      return (bool) count($this->listenerIds) || (bool) count($this->listeners);
    }
    if (isset($this->listenerIds[$eventName])) {
      return true;
    }
    return parent::hasListeners($eventName);
  }

  /**
   * @see EventDispatcherInterface::getListeners
   */
  public function getListeners($eventName = null) {
    if (null === $eventName) {
      foreach (array_keys($this->listenerIds) as $serviceEventName) {
        $this
          ->lazyLoad($serviceEventName);
      }
    }
    else {
      $this
        ->lazyLoad($eventName);
    }
    return parent::getListeners($eventName);
  }

  /**
   * Adds a service as event subscriber
   *
   * @param string $serviceId The service ID of the subscriber service
   * @param string $class     The service's class name (which must implement EventSubscriberInterface)
   */
  public function addSubscriberService($serviceId, $class) {
    foreach ($class::getSubscribedEvents() as $eventName => $params) {
      if (is_string($params)) {
        $this->listenerIds[$eventName][] = array(
          $serviceId,
          $params,
          0,
        );
      }
      elseif (is_string($params[0])) {
        $this->listenerIds[$eventName][] = array(
          $serviceId,
          $params[0],
          isset($params[1]) ? $params[1] : 0,
        );
      }
      else {
        foreach ($params as $listener) {
          $this->listenerIds[$eventName][] = array(
            $serviceId,
            $listener[0],
            isset($listener[1]) ? $listener[1] : 0,
          );
        }
      }
    }
  }

  /**
   * {@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) {
    $this
      ->lazyLoad($eventName);
    return parent::dispatch($eventName, $event);
  }
  public function getContainer() {
    return $this->container;
  }

  /**
   * Lazily loads listeners for this event from the dependency injection
   * container.
   *
   * @param string $eventName The name of the event to dispatch. The name of
   *                          the event is the name of the method that is
   *                          invoked on listeners.
   */
  protected function lazyLoad($eventName) {
    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]) {
          parent::removeListener($eventName, array(
            $this->listeners[$eventName][$key],
            $method,
          ));
          $this
            ->addListener($eventName, array(
            $listener,
            $method,
          ), $priority);
        }
        $this->listeners[$eventName][$key] = $listener;
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ContainerAwareEventDispatcher::$container private property The container from where services are loaded
ContainerAwareEventDispatcher::$listenerIds private property The service IDs of the event listeners and subscribers
ContainerAwareEventDispatcher::$listeners private property The services registered as listeners Overrides EventDispatcher::$listeners
ContainerAwareEventDispatcher::addListenerService public function Adds a service as event listener
ContainerAwareEventDispatcher::addSubscriberService public function Adds a service as event subscriber
ContainerAwareEventDispatcher::dispatch public function Lazily loads listeners for this event from the dependency injection container. Overrides EventDispatcher::dispatch
ContainerAwareEventDispatcher::getContainer public function
ContainerAwareEventDispatcher::getListeners public function Overrides EventDispatcher::getListeners
ContainerAwareEventDispatcher::hasListeners public function Overrides EventDispatcher::hasListeners
ContainerAwareEventDispatcher::lazyLoad protected function Lazily loads listeners for this event from the dependency injection container.
ContainerAwareEventDispatcher::removeListener public function Removes an event listener from the specified events. Overrides EventDispatcher::removeListener
ContainerAwareEventDispatcher::__construct public function Constructor.
EventDispatcher::$sorted private property
EventDispatcher::addListener public function @api Overrides EventDispatcherInterface::addListener
EventDispatcher::addSubscriber public function @api Overrides EventDispatcherInterface::addSubscriber
EventDispatcher::doDispatch protected function Triggers the listeners of an event.
EventDispatcher::removeSubscriber public function Overrides EventDispatcherInterface::removeSubscriber
EventDispatcher::sortListeners private function Sorts the internal list of listeners for the given event by priority.