diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index 29a76bbc74b09..a870b7e3562a4 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -27,6 +27,7 @@ class RegisterListenersPass implements CompilerPassInterface { private array $hotPathEvents = []; private array $noPreloadEvents = []; + private array $deprecatedEvents = []; /** * @return $this @@ -48,6 +49,13 @@ public function setNoPreloadEvents(array $noPreloadEvents): static return $this; } + public function addDeprecatedEvent(string $event, string $package, string $version, string $message, mixed ...$args): static + { + $this->deprecatedEvents[$event] = ['package' => $package, 'version' => $version, 'message' => $message, 'args' => $args]; + + return $this; + } + public function process(ContainerBuilder $container): void { if (!$container->hasDefinition('event_dispatcher') && !$container->hasAlias('event_dispatcher')) { @@ -107,6 +115,10 @@ public function process(ContainerBuilder $container): void } elseif (isset($this->noPreloadEvents[$event['event']])) { ++$noPreload; } + + if (isset($this->deprecatedEvents[$event['event']])) { + trigger_deprecation(...array_values($this->deprecatedEvents[$event['event']])); + } } if ($noPreload && \count($events) === $noPreload) { @@ -158,6 +170,10 @@ public function process(ContainerBuilder $container): void } elseif (isset($this->noPreloadEvents[$args[0]])) { ++$noPreload; } + + if (isset($this->deprecatedEvents[$args[0]])) { + trigger_deprecation(...array_values($this->deprecatedEvents[$args[0]])); + } } if ($noPreload && \count($extractingDispatcher->listeners) === $noPreload) { $container->getDefinition($id)->addTag('container.no_preload'); diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index 65d862637423c..d5255c8aea0b7 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -34,12 +34,14 @@ class EventDispatcher implements EventDispatcherInterface private array $listeners = []; private array $sorted = []; private array $optimized; + private array $deprecated; - public function __construct() + public function __construct(array $deprecated = []) { if (__CLASS__ === static::class) { $this->optimized = []; } + $this->deprecated = $deprecated; } public function dispatch(object $event, string $eventName = null): object @@ -125,6 +127,10 @@ public function hasListeners(string $eventName = null): bool public function addListener(string $eventName, callable|array $listener, int $priority = 0): void { + if (isset($this->deprecated[$eventName])) { + trigger_deprecation(...array_values($this->deprecated[$eventName])); + } + $this->listeners[$eventName][$priority][] = $listener; unset($this->sorted[$eventName], $this->optimized[$eventName]); } diff --git a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php index c18d863a98c12..ec7113a164693 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\AttributeAutoconfigurationPass; @@ -22,6 +23,7 @@ use Symfony\Component\EventDispatcher\Attribute\AsEventListener; use Symfony\Component\EventDispatcher\DependencyInjection\AddEventAliasesPass; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\Tests\Fixtures\CustomEvent; use Symfony\Component\EventDispatcher\Tests\Fixtures\TaggedInvokableListener; @@ -29,6 +31,8 @@ class RegisterListenersPassTest extends TestCase { + use ExpectDeprecationTrait; + /** * Tests that event subscribers not implementing EventSubscriberInterface * trigger an exception. @@ -503,6 +507,26 @@ public function testOmitEventNameOnSubscriber() ]; $this->assertEquals($expectedCalls, $definition->getMethodCalls()); } + + /** + * @group legacy + */ + public function testEventDeprecations() + { + $container = new ContainerBuilder(); + $pass = new RegisterListenersPass(); + $pass->addDeprecatedEvent('event', 'symfony/event-dispatcher', '7.1', 'Event is deprecated'); + + $container->addCompilerPass($pass); + $container->register('event_dispatcher', EventDispatcher::class); + $container->register('listener', Event::class) + ->setPublic(true) + ->addTag('kernel.event_listener', ['event' => 'event']) + ; + + $this->expectDeprecation('Since symfony/event-dispatcher 7.1: Event is deprecated'); + $container->compile(); + } } class SubscriberService implements EventSubscriberInterface