vendor/symfony/event-dispatcher/Debug/WrappedListener.php line 106
- <?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]];
- }
- }