vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php line 63

  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Bridge\Doctrine;
  11. use Doctrine\Common\EventArgs;
  12. use Doctrine\Common\EventManager;
  13. use Doctrine\Common\EventSubscriber;
  14. use Psr\Container\ContainerInterface;
  15. /**
  16.  * Allows lazy loading of listener and subscriber services.
  17.  *
  18.  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  19.  */
  20. class ContainerAwareEventManager extends EventManager
  21. {
  22.     /**
  23.      * Map of registered listeners.
  24.      *
  25.      * <event> => <listeners>
  26.      */
  27.     private array $listeners = [];
  28.     private array $subscribers;
  29.     private array $initialized = [];
  30.     private bool $initializedSubscribers false;
  31.     private array $methods = [];
  32.     private ContainerInterface $container;
  33.     /**
  34.      * @param list<string|EventSubscriber|array{string[], string|object}> $subscriberIds List of subscribers, subscriber ids, or [events, listener] tuples
  35.      */
  36.     public function __construct(ContainerInterface $container, array $subscriberIds = [])
  37.     {
  38.         $this->container $container;
  39.         $this->subscribers $subscriberIds;
  40.     }
  41.     public function dispatchEvent($eventNameEventArgs $eventArgs null): void
  42.     {
  43.         if (!$this->initializedSubscribers) {
  44.             $this->initializeSubscribers();
  45.         }
  46.         if (!isset($this->listeners[$eventName])) {
  47.             return;
  48.         }
  49.         $eventArgs ??= EventArgs::getEmptyInstance();
  50.         if (!isset($this->initialized[$eventName])) {
  51.             $this->initializeListeners($eventName);
  52.         }
  53.         foreach ($this->listeners[$eventName] as $hash => $listener) {
  54.             $listener->{$this->methods[$eventName][$hash]}($eventArgs);
  55.         }
  56.     }
  57.     /**
  58.      * @return object[][]
  59.      */
  60.     public function getListeners($event null): array
  61.     {
  62.         if (null === $event) {
  63.             trigger_deprecation('symfony/doctrine-bridge''6.2''Calling "%s()" without an event name is deprecated. Call "getAllListeners()" instead.'__METHOD__);
  64.             return $this->getAllListeners();
  65.         }
  66.         if (!$this->initializedSubscribers) {
  67.             $this->initializeSubscribers();
  68.         }
  69.         if (!isset($this->initialized[$event])) {
  70.             $this->initializeListeners($event);
  71.         }
  72.         return $this->listeners[$event];
  73.     }
  74.     public function getAllListeners(): array
  75.     {
  76.         if (!$this->initializedSubscribers) {
  77.             $this->initializeSubscribers();
  78.         }
  79.         foreach ($this->listeners as $event => $listeners) {
  80.             if (!isset($this->initialized[$event])) {
  81.                 $this->initializeListeners($event);
  82.             }
  83.         }
  84.         return $this->listeners;
  85.     }
  86.     public function hasListeners($event): bool
  87.     {
  88.         if (!$this->initializedSubscribers) {
  89.             $this->initializeSubscribers();
  90.         }
  91.         return isset($this->listeners[$event]) && $this->listeners[$event];
  92.     }
  93.     public function addEventListener($events$listener): void
  94.     {
  95.         if (!$this->initializedSubscribers) {
  96.             $this->initializeSubscribers();
  97.         }
  98.         $hash $this->getHash($listener);
  99.         foreach ((array) $events as $event) {
  100.             // Overrides listener if a previous one was associated already
  101.             // Prevents duplicate listeners on same event (same instance only)
  102.             $this->listeners[$event][$hash] = $listener;
  103.             if (\is_string($listener)) {
  104.                 unset($this->initialized[$event]);
  105.             } else {
  106.                 $this->methods[$event][$hash] = $this->getMethod($listener$event);
  107.             }
  108.         }
  109.     }
  110.     public function removeEventListener($events$listener): void
  111.     {
  112.         if (!$this->initializedSubscribers) {
  113.             $this->initializeSubscribers();
  114.         }
  115.         $hash $this->getHash($listener);
  116.         foreach ((array) $events as $event) {
  117.             // Check if we actually have this listener associated
  118.             if (isset($this->listeners[$event][$hash])) {
  119.                 unset($this->listeners[$event][$hash]);
  120.             }
  121.             if (isset($this->methods[$event][$hash])) {
  122.                 unset($this->methods[$event][$hash]);
  123.             }
  124.         }
  125.     }
  126.     public function addEventSubscriber(EventSubscriber $subscriber): void
  127.     {
  128.         if (!$this->initializedSubscribers) {
  129.             $this->initializeSubscribers();
  130.         }
  131.         parent::addEventSubscriber($subscriber);
  132.     }
  133.     public function removeEventSubscriber(EventSubscriber $subscriber): void
  134.     {
  135.         if (!$this->initializedSubscribers) {
  136.             $this->initializeSubscribers();
  137.         }
  138.         parent::removeEventSubscriber($subscriber);
  139.     }
  140.     private function initializeListeners(string $eventName)
  141.     {
  142.         $this->initialized[$eventName] = true;
  143.         foreach ($this->listeners[$eventName] as $hash => $listener) {
  144.             if (\is_string($listener)) {
  145.                 $this->listeners[$eventName][$hash] = $listener $this->container->get($listener);
  146.                 $this->methods[$eventName][$hash] = $this->getMethod($listener$eventName);
  147.             }
  148.         }
  149.     }
  150.     private function initializeSubscribers()
  151.     {
  152.         $this->initializedSubscribers true;
  153.         foreach ($this->subscribers as $subscriber) {
  154.             if (\is_array($subscriber)) {
  155.                 $this->addEventListener(...$subscriber);
  156.                 continue;
  157.             }
  158.             if (\is_string($subscriber)) {
  159.                 $subscriber $this->container->get($subscriber);
  160.             }
  161.             parent::addEventSubscriber($subscriber);
  162.         }
  163.         $this->subscribers = [];
  164.     }
  165.     private function getHash(string|object $listener): string
  166.     {
  167.         if (\is_string($listener)) {
  168.             return '_service_'.$listener;
  169.         }
  170.         return spl_object_hash($listener);
  171.     }
  172.     private function getMethod(object $listenerstring $event): string
  173.     {
  174.         if (!method_exists($listener$event) && method_exists($listener'__invoke')) {
  175.             return '__invoke';
  176.         }
  177.         return $event;
  178.     }
  179. }