vendor/jms/serializer/src/EventDispatcher/EventDispatcher.php line 112

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace JMS\Serializer\EventDispatcher;
  4. use JMS\Serializer\Exception\InvalidArgumentException;
  5. /**
  6.  * Light-weight event dispatcher.
  7.  *
  8.  * This implementation focuses primarily on performance, and dispatching
  9.  * events for certain classes. It is not a general purpose event dispatcher.
  10.  *
  11.  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  12.  */
  13. class EventDispatcher implements EventDispatcherInterface
  14. {
  15.     /**
  16.      * @var array
  17.      */
  18.     private $listeners = [];
  19.     /**
  20.      * ClassListeners cache
  21.      *
  22.      * @var array
  23.      */
  24.     private $classListeners = [];
  25.     public static function getDefaultMethodName(string $eventName): string
  26.     {
  27.         return 'on' str_replace(['_''.'], ''$eventName);
  28.     }
  29.     /**
  30.      * Sets the listeners.
  31.      *
  32.      * @param array $listeners
  33.      */
  34.     public function setListeners(array $listeners): void
  35.     {
  36.         $this->listeners $listeners;
  37.         $this->classListeners = [];
  38.     }
  39.     /**
  40.      * @internal Used for profiling
  41.      */
  42.     public function getListeners(): array
  43.     {
  44.         return $this->listeners;
  45.     }
  46.     /**
  47.      * {@inheritdoc}
  48.      */
  49.     public function addListener(string $eventName$callable, ?string $class null, ?string $format null, ?string $interface null): void
  50.     {
  51.         $this->listeners[$eventName][] = [$callable$class$format$interface];
  52.         unset($this->classListeners[$eventName]);
  53.     }
  54.     public function addSubscriber(EventSubscriberInterface $subscriber): void
  55.     {
  56.         foreach ($subscriber->getSubscribedEvents() as $eventData) {
  57.             if (!isset($eventData['event'])) {
  58.                 throw new InvalidArgumentException(sprintf('Each event must have a "event" key.'));
  59.             }
  60.             $method $eventData['method'] ?? self::getDefaultMethodName($eventData['event']);
  61.             $class $eventData['class'] ?? null;
  62.             $format $eventData['format'] ?? null;
  63.             $interface $eventData['interface'] ?? null;
  64.             $this->listeners[$eventData['event']][] = [[$subscriber$method], $class$format$interface];
  65.             unset($this->classListeners[$eventData['event']]);
  66.         }
  67.     }
  68.     public function hasListeners(string $eventNamestring $classstring $format): bool
  69.     {
  70.         if (!isset($this->listeners[$eventName])) {
  71.             return false;
  72.         }
  73.         if (!isset($this->classListeners[$eventName][$class][$format])) {
  74.             $this->classListeners[$eventName][$class][$format] = $this->initializeListeners($eventName$class$format);
  75.         }
  76.         return !!$this->classListeners[$eventName][$class][$format];
  77.     }
  78.     public function dispatch(string $eventNamestring $classstring $formatEvent $event): void
  79.     {
  80.         if (!isset($this->listeners[$eventName])) {
  81.             return;
  82.         }
  83.         $object $event instanceof ObjectEvent $event->getObject() : null;
  84.         $realClass is_object($object) ? get_class($object) : '';
  85.         $objectClass $realClass !== $class $realClass $class $class;
  86.         if (!isset($this->classListeners[$eventName][$objectClass][$format])) {
  87.             $this->classListeners[$eventName][$objectClass][$format] = $this->initializeListeners($eventName$class$format);
  88.         }
  89.         foreach ($this->classListeners[$eventName][$objectClass][$format] as $listener) {
  90.             if (!empty($listener[3]) && !($object instanceof $listener[3])) {
  91.                 continue;
  92.             }
  93.             \call_user_func($listener[0], $event$eventName$class$format$this);
  94.             if ($event->isPropagationStopped()) {
  95.                 break;
  96.             }
  97.         }
  98.     }
  99.     /**
  100.      * @return array An array of listeners
  101.      */
  102.     protected function initializeListeners(string $eventNamestring $loweredClassstring $format): array
  103.     {
  104.         $listeners = [];
  105.         foreach ($this->listeners[$eventName] as $listener) {
  106.             if (null !== $listener[1] && $loweredClass !== $listener[1]) {
  107.                 continue;
  108.             }
  109.             if (null !== $listener[2] && $format !== $listener[2]) {
  110.                 continue;
  111.             }
  112.             $listeners[] = $listener;
  113.         }
  114.         return $listeners;
  115.     }
  116. }