vendor/symfony/event-dispatcher/Debug/WrappedListener.php line 116
<?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\Debug;use Psr\EventDispatcher\StoppableEventInterface;use Symfony\Component\EventDispatcher\EventDispatcherInterface;use Symfony\Component\Stopwatch\Stopwatch;use Symfony\Component\VarDumper\Caster\ClassStub;/*** @author Fabien Potencier <fabien@symfony.com>*/final class WrappedListener{private string|array|object $listener;private ?\Closure $optimizedListener;private string $name;private bool $called = false;private bool $stoppedPropagation = false;private Stopwatch $stopwatch;private ?EventDispatcherInterface $dispatcher;private string $pretty;private string $callableRef;private ClassStub|string $stub;private ?int $priority = null;private static bool $hasClassStub;public function __construct(callable|array $listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null, int $priority = null){$this->listener = $listener;$this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? $listener(...) : null);$this->stopwatch = $stopwatch;$this->dispatcher = $dispatcher;$this->priority = $priority;if (\is_array($listener)) {[$this->name, $this->callableRef] = $this->parseListener($listener);$this->pretty = $this->name.'::'.$listener[1];$this->callableRef .= '::'.$listener[1];} elseif ($listener instanceof \Closure) {$r = new \ReflectionFunction($listener);if (str_contains($r->name, '{closure}')) {$this->pretty = $this->name = 'closure';} elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {$this->name = $class->name;$this->pretty = $this->name.'::'.$r->name;} else {$this->pretty = $this->name = $r->name;}} elseif (\is_string($listener)) {$this->pretty = $this->name = $listener;} else {$this->name = get_debug_type($listener);$this->pretty = $this->name.'::__invoke';$this->callableRef = $listener::class.'::__invoke';}if (null !== $name) {$this->name = $name;}self::$hasClassStub ??= class_exists(ClassStub::class);}public function getWrappedListener(): callable|array{return $this->listener;}public function wasCalled(): bool{return $this->called;}public function stoppedPropagation(): bool{return $this->stoppedPropagation;}public function getPretty(): string{return $this->pretty;}public function getInfo(string $eventName): array{$this->stub ??= self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->callableRef ?? $this->listener) : $this->pretty.'()';return ['event' => $eventName,'priority' => $this->priority ??= $this->dispatcher?->getListenerPriority($eventName, $this->listener),'pretty' => $this->pretty,'stub' => $this->stub,];}public function __invoke(object $event, string $eventName, EventDispatcherInterface $dispatcher): void{$dispatcher = $this->dispatcher ?: $dispatcher;$this->called = true;$this->priority ??= $dispatcher->getListenerPriority($eventName, $this->listener);$e = $this->stopwatch->start($this->name, 'event_listener');try {($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher);} finally {if ($e->isStarted()) {$e->stop();}}if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {$this->stoppedPropagation = true;}}private function parseListener(array $listener): array{if ($listener[0] instanceof \Closure) {foreach ((new \ReflectionFunction($listener[0]))->getAttributes(\Closure::class) as $attribute) {if ($name = $attribute->getArguments()['name'] ?? false) {return [$name, $attribute->getArguments()['class'] ?? $name];}}}if (\is_object($listener[0])) {return [get_debug_type($listener[0]), \get_class($listener[0])];}return [$listener[0], $listener[0]];}}