ContainerAwareEventDispatcher.php

Namespace

Symfony\Component\EventDispatcher

File

drupal/core/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php
View source
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Component\EventDispatcher;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * 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>
 */
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,
    );
  }
  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;
      }
    }
  }

}

Classes

Namesort descending Description
ContainerAwareEventDispatcher Lazily loads listeners and subscribers from the dependency injection container