Issue #2909185 by longwave, donquixote, andypost, andregp, pounard, jibran, martin107, kostyashupenko, catch, znerol: Replace ContainerAwareEventDispatcher with Symfony EventDispatcher

merge-requests/7287/head
Alex Pott 2024-03-29 13:18:59 +00:00
parent ed13e94203
commit 6e733866fe
No known key found for this signature in database
GPG Key ID: BDA67E7EE836E5CE
7 changed files with 51 additions and 52 deletions

View File

@ -873,8 +873,7 @@ services:
arguments: ['@request_stack'] arguments: ['@request_stack']
Drupal\Core\Routing\RouteMatchInterface: '@current_route_match' Drupal\Core\Routing\RouteMatchInterface: '@current_route_match'
event_dispatcher: event_dispatcher:
class: Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher class: Symfony\Component\EventDispatcher\EventDispatcher
arguments: ['@service_container']
Psr\EventDispatcher\EventDispatcherInterface: '@event_dispatcher' Psr\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
Symfony\Contracts\EventDispatcher\EventDispatcherInterface: '@event_dispatcher' Symfony\Contracts\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
controller_resolver: controller_resolver:

View File

@ -2,6 +2,8 @@
namespace Drupal\Component\EventDispatcher; namespace Drupal\Component\EventDispatcher;
@trigger_error('The ' . __NAMESPACE__ . '\ContainerAwareEventDispatcher is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use Symfony\Component\EventDispatcher\EventDispatcher instead. See https://www.drupal.org/node/3376090', E_USER_DEPRECATED);
use Psr\EventDispatcher\StoppableEventInterface; use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@ -30,6 +32,11 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
* runtime is not affected by this change though. * runtime is not affected by this change though.
* </dd> * </dd>
* </dl> * </dl>
*
* @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use
* \Symfony\Component\EventDispatcher\EventDispatcher instead.
*
* @see https://www.drupal.org/node/3376090
*/ */
class ContainerAwareEventDispatcher implements EventDispatcherInterface { class ContainerAwareEventDispatcher implements EventDispatcherInterface {

View File

@ -29,6 +29,7 @@ use Drupal\Core\Site\Settings;
use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/** /**
@ -82,7 +83,7 @@ class CoreServiceProvider implements ServiceProviderInterface, ServiceModifierIn
$container->addCompilerPass(new TwigExtensionPass()); $container->addCompilerPass(new TwigExtensionPass());
// Add a compiler pass for registering event subscribers. // Add a compiler pass for registering event subscribers.
$container->addCompilerPass(new RegisterEventSubscribersPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new RegisterEventSubscribersPass(new RegisterListenersPass()), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new LoggerAwarePass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new LoggerAwarePass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new RegisterAccessChecksPass()); $container->addCompilerPass(new RegisterAccessChecksPass());

View File

@ -4,59 +4,50 @@ namespace Drupal\Core\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
/** /**
* Registers all event subscribers to the event dispatcher. * Wraps the Symfony event subscriber pass to use different tag names.
*/ */
class RegisterEventSubscribersPass implements CompilerPassInterface { class RegisterEventSubscribersPass implements CompilerPassInterface {
/**
* Constructs a RegisterEventSubscribersPass object.
*
* @param \Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass $pass
* The Symfony compiler pass that registers event subscribers.
*/
public function __construct(
protected RegisterListenersPass $pass
) {}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function process(ContainerBuilder $container) { public function process(ContainerBuilder $container) {
if (!$container->hasDefinition('event_dispatcher')) { $this->renameTag($container, 'event_subscriber', 'kernel.event_subscriber');
return; $this->pass->process($container);
} $this->renameTag($container, 'kernel.event_subscriber', 'event_subscriber');
}
$definition = $container->getDefinition('event_dispatcher'); /**
* Renames tags in the container.
$event_subscriber_info = []; *
foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) { * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
* The container.
// We must assume that the class value has been correctly filled, even if * @param string $source_tag
// the service is created by a factory. * The tag to be renamed.
$class = $container->getDefinition($id)->getClass(); * @param string $target_tag
* The tag to rename with.
$interface = EventSubscriberInterface::class; */
if (!is_subclass_of($class, $interface)) { protected function renameTag(ContainerBuilder $container, string $source_tag, string $target_tag): void {
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); foreach ($container->getDefinitions() as $definition) {
} if ($definition->hasTag($source_tag)) {
$attributes = $definition->getTag($source_tag)[0];
// Get all subscribed events. $definition->addTag($target_tag, $attributes);
foreach ($class::getSubscribedEvents() as $event_name => $params) { $definition->clearTag($source_tag);
if (is_string($params)) {
$priority = 0;
$event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $params]];
}
elseif (is_string($params[0])) {
$priority = $params[1] ?? 0;
$event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $params[0]]];
}
else {
foreach ($params as $listener) {
$priority = $listener[1] ?? 0;
$event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $listener[0]]];
}
}
} }
} }
foreach (array_keys($event_subscriber_info) as $event_name) {
krsort($event_subscriber_info[$event_name]);
}
$definition->addArgument($event_subscriber_info);
} }
} }

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Drupal\Tests\layout_builder\Unit; namespace Drupal\Tests\layout_builder\Unit;
use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockManagerInterface; use Drupal\Core\Block\BlockManagerInterface;
@ -24,6 +23,7 @@ use Drupal\layout_builder\Section;
use Drupal\layout_builder\SectionComponent; use Drupal\layout_builder\SectionComponent;
use Drupal\Tests\UnitTestCase; use Drupal\Tests\UnitTestCase;
use Prophecy\Argument; use Prophecy\Argument;
use Symfony\Component\EventDispatcher\EventDispatcher;
/** /**
* @coversDefaultClass \Drupal\layout_builder\Section * @coversDefaultClass \Drupal\layout_builder\Section
@ -62,7 +62,7 @@ class SectionRenderTest extends UnitTestCase {
/** /**
* The event dispatcher. * The event dispatcher.
* *
* @var \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher * @var \Symfony\Component\EventDispatcher\EventDispatcher
*/ */
protected $eventDispatcher; protected $eventDispatcher;
@ -77,7 +77,7 @@ class SectionRenderTest extends UnitTestCase {
$this->contextHandler = $this->prophesize(ContextHandlerInterface::class); $this->contextHandler = $this->prophesize(ContextHandlerInterface::class);
$this->contextRepository = $this->prophesize(ContextRepositoryInterface::class); $this->contextRepository = $this->prophesize(ContextRepositoryInterface::class);
// @todo Refactor this into some better tests in https://www.drupal.org/node/2942605. // @todo Refactor this into some better tests in https://www.drupal.org/node/2942605.
$this->eventDispatcher = (new \ReflectionClass(ContainerAwareEventDispatcher::class))->newInstanceWithoutConstructor(); $this->eventDispatcher = (new \ReflectionClass(EventDispatcher::class))->newInstanceWithoutConstructor();
$this->account = $this->prophesize(AccountInterface::class); $this->account = $this->prophesize(AccountInterface::class);
$subscriber = new BlockComponentRenderArray($this->account->reveal()); $subscriber = new BlockComponentRenderArray($this->account->reveal());

View File

@ -25,6 +25,7 @@ use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
* synchronizations. * synchronizations.
* *
* @group EventDispatcher * @group EventDispatcher
* @group legacy
*/ */
class ContainerAwareEventDispatcherTest extends TestCase { class ContainerAwareEventDispatcherTest extends TestCase {

View File

@ -4,13 +4,13 @@ declare(strict_types=1);
namespace Drupal\Tests\Core\EventSubscriber; namespace Drupal\Tests\Core\EventSubscriber;
use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher as EventDispatcher;
use Drupal\Core\EventSubscriber\RedirectResponseSubscriber; use Drupal\Core\EventSubscriber\RedirectResponseSubscriber;
use Drupal\Core\Routing\TrustedRedirectResponse; use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Utility\UnroutedUrlAssemblerInterface; use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
use Drupal\Tests\UnitTestCase; use Drupal\Tests\UnitTestCase;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent;
@ -87,7 +87,7 @@ class RedirectResponseSubscriberTest extends UnitTestCase {
* @dataProvider providerTestDestinationRedirect * @dataProvider providerTestDestinationRedirect
*/ */
public function testDestinationRedirect(Request $request, $expected) { public function testDestinationRedirect(Request $request, $expected) {
$dispatcher = new EventDispatcher(\Drupal::getContainer()); $dispatcher = new EventDispatcher();
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://example.com/drupal'); $response = new RedirectResponse('http://example.com/drupal');
$request->headers->set('HOST', 'example.com'); $request->headers->set('HOST', 'example.com');
@ -128,7 +128,7 @@ class RedirectResponseSubscriberTest extends UnitTestCase {
* @dataProvider providerTestDestinationRedirectToExternalUrl * @dataProvider providerTestDestinationRedirectToExternalUrl
*/ */
public function testDestinationRedirectToExternalUrl($request, $expected) { public function testDestinationRedirectToExternalUrl($request, $expected) {
$dispatcher = new EventDispatcher(\Drupal::getContainer()); $dispatcher = new EventDispatcher();
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://other-example.com'); $response = new RedirectResponse('http://other-example.com');
@ -143,7 +143,7 @@ class RedirectResponseSubscriberTest extends UnitTestCase {
* @covers ::checkRedirectUrl * @covers ::checkRedirectUrl
*/ */
public function testRedirectWithOptInExternalUrl() { public function testRedirectWithOptInExternalUrl() {
$dispatcher = new EventDispatcher(\Drupal::getContainer()); $dispatcher = new EventDispatcher();
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new TrustedRedirectResponse('http://external-url.com'); $response = new TrustedRedirectResponse('http://external-url.com');
$request = Request::create(''); $request = Request::create('');
@ -176,7 +176,7 @@ class RedirectResponseSubscriberTest extends UnitTestCase {
* @dataProvider providerTestDestinationRedirectWithInvalidUrl * @dataProvider providerTestDestinationRedirectWithInvalidUrl
*/ */
public function testDestinationRedirectWithInvalidUrl(Request $request) { public function testDestinationRedirectWithInvalidUrl(Request $request) {
$dispatcher = new EventDispatcher(\Drupal::getContainer()); $dispatcher = new EventDispatcher();
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://example.com/drupal'); $response = new RedirectResponse('http://example.com/drupal');