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']
Drupal\Core\Routing\RouteMatchInterface: '@current_route_match'
event_dispatcher:
class: Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
arguments: ['@service_container']
class: Symfony\Component\EventDispatcher\EventDispatcher
Psr\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
Symfony\Contracts\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
controller_resolver:

View File

@ -2,6 +2,8 @@
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 Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@ -30,6 +32,11 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
* runtime is not affected by this change though.
* </dd>
* </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 {

View File

@ -29,6 +29,7 @@ use Drupal\Core\Site\Settings;
use Psr\Log\LoggerAwareInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
@ -82,7 +83,7 @@ class CoreServiceProvider implements ServiceProviderInterface, ServiceModifierIn
$container->addCompilerPass(new TwigExtensionPass());
// 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 RegisterAccessChecksPass());

View File

@ -4,59 +4,50 @@ namespace Drupal\Core\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
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 {
/**
* 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}
*/
public function process(ContainerBuilder $container) {
if (!$container->hasDefinition('event_dispatcher')) {
return;
}
$this->renameTag($container, 'event_subscriber', 'kernel.event_subscriber');
$this->pass->process($container);
$this->renameTag($container, 'kernel.event_subscriber', 'event_subscriber');
}
$definition = $container->getDefinition('event_dispatcher');
$event_subscriber_info = [];
foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) {
// We must assume that the class value has been correctly filled, even if
// the service is created by a factory.
$class = $container->getDefinition($id)->getClass();
$interface = EventSubscriberInterface::class;
if (!is_subclass_of($class, $interface)) {
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
}
// Get all subscribed events.
foreach ($class::getSubscribedEvents() as $event_name => $params) {
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]]];
}
}
/**
* Renames tags in the container.
*
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
* The container.
* @param string $source_tag
* The tag to be renamed.
* @param string $target_tag
* The tag to rename with.
*/
protected function renameTag(ContainerBuilder $container, string $source_tag, string $target_tag): void {
foreach ($container->getDefinitions() as $definition) {
if ($definition->hasTag($source_tag)) {
$attributes = $definition->getTag($source_tag)[0];
$definition->addTag($target_tag, $attributes);
$definition->clearTag($source_tag);
}
}
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;
use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockManagerInterface;
@ -24,6 +23,7 @@ use Drupal\layout_builder\Section;
use Drupal\layout_builder\SectionComponent;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
use Symfony\Component\EventDispatcher\EventDispatcher;
/**
* @coversDefaultClass \Drupal\layout_builder\Section
@ -62,7 +62,7 @@ class SectionRenderTest extends UnitTestCase {
/**
* The event dispatcher.
*
* @var \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
* @var \Symfony\Component\EventDispatcher\EventDispatcher
*/
protected $eventDispatcher;
@ -77,7 +77,7 @@ class SectionRenderTest extends UnitTestCase {
$this->contextHandler = $this->prophesize(ContextHandlerInterface::class);
$this->contextRepository = $this->prophesize(ContextRepositoryInterface::class);
// @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);
$subscriber = new BlockComponentRenderArray($this->account->reveal());

View File

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

View File

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