Problem/Motivation

The signature of the "Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.

Calling the "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as first argument is deprecated since Symfony 4.3, pass it second and provide the event object first instead.

Related https://symfony.com/blog/new-in-symfony-4-3-simpler-event-dispatching

Proposed resolution

Copy the logic from Symfony's on EventDispatcher::dispatch() to allow calling the method with both order of arguments, and also to allow the new Symfony Contracts Event class to be passed in.

Update all core usages of EventDispatcher::dispatch()

Add deprecation notices for when ::dispatch() is called with the old argument order.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Drupal has been updated for upstream changes in the Symfony 5 Events system. See https://www.drupal.org/node/3159012 for more information.

CommentFileSizeAuthor
#51 3055194--8.9-v5--core-only.patch41.6 KBtstoeckler
#51 3055194--8.8--core-only.patch41.6 KBtstoeckler
#50 3055194--9.0-v1.patch44.46 KBtstoeckler
#50 3055194--8.9-v5.patch47.98 KBtstoeckler
#50 3055194--8.8-v2.patch48.51 KBtstoeckler
#41 3055194-41.patch45.11 KBcatch
#41 interdiff-40-41.txt2.3 KBcatch
#40 3055194-41.patch43.94 KBcatch
#39 3055194-40.patch43.94 KBcatch
#38 3055194-38.patch43.94 KBcatch
#38 interdiff-3055194-35-38.txt4.52 KBcatch
#35 3055194-34.patch42.06 KBcatch
#34 3055194-33.patch59.88 KBcatch
#33 3055194-32.patch59.88 KBcatch
#33 interdiff-30-32.txt39.58 KBcatch
#30 3055194-30.patch4.27 KBcatch
#24 interdiff.3055194.18-24.txt1.02 KBlongwave
#24 3055194-24.patch4.56 KBlongwave
#18 interdiff.3055194.17-18.txt2.25 KBmikelutz
#18 3055194-18.drupal.patch4.17 KBmikelutz
#17 3055194-17.drupal.patch1.91 KBmikelutz
#8 3055194_update_event_dispatcher.patch6.86 KBmkalkbrenner
#2 3055194-2.drupal.TEST_ONLY.patch197.67 KBmikelutz
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mikelutz created an issue. See original summary.

mikelutz’s picture

Status: Active » Needs review
FileSize
197.67 KB

Test patch

Status: Needs review » Needs work

The last submitted patch, 2: 3055194-2.drupal.TEST_ONLY.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

mikelutz’s picture

So, this one will be a little tricky. They've swapped the order of the event object and event name, and made the event name optional and the event object mandatory. This aligns with PSR-14. The idea is to use the FQCN of the event object as the event name, and eventually removing the need for event names. Our dispatcher cannot expand it's argument list to accomodate this while implementing Symfony/Component/EventDispatcher/EventDispatcherInterface becuase it throws a fatal error in php 7.0 and 7.1. We can't not implement Symfony/Component/EventDispatcher/EventDispatcherInterface because we typehint it all over the place.

I think we will have to fork and replace the symfony interface with one where we can expand the argument list and do our deprecations now, so that for Drupal 9 we are compliant with the SF5 and PSR-14 interfaces.

andypost’s picture

Issue summary: View changes

Probably the best choice is get consensus on #2825358: Event class constants for event names can cause fatal errors when a module is installed first and then start implement BC shim

mkalkbrenner’s picture

I think we will have to fork and replace the symfony interface with one where we can expand the argument list and do our deprecations now, so that for Drupal 9 we are compliant with the SF5 and PSR-14 interfaces.

Why not just using the LegacyEventDispatcherProxy as described at https://symfony.com/blog/new-in-symfony-4-3-simpler-event-dispatching ?

mikelutz’s picture

Because that is not available in Symfony 3.

mkalkbrenner’s picture

Because that is not available in Symfony 3.

That's true but not relevant. The event dispatcher is "independent" from the symfony version. You can install the symfony event dispatcher in version 4.3 which is compatible to "symfony" 3.4.

mikelutz’s picture

Symfony/event-dispatcher 4.3 isn't compatible with php 7.0. we can't use it in Drupal 8.
When we fix it in Drupal 9, that is the route will take, but this is postponed until the branch opens.

mikelutz’s picture

Status: Needs review » Postponed
hchonov’s picture

Symfony/event-dispatcher 4.3 isn't compatible with php 7.0. we can't use it in Drupal 8.
When we fix it in Drupal 9, that is the route will take, but this is postponed until the branch opens.

According to https://www.drupal.org/docs/8/system-requirements/php-requirements

Support for PHP 7.0 will continue until at least March 6, 2019. We will post an announcement as soon as the end of PHP 7.0 support has been scheduled.

So why don't we say that from Drupal 8.8.0 we are not going to support PHP 7.0 anymore? That would be exactly 8 months between our promise to support it at least until March 6, 2019 and the release date of Drupal 8.8.0 scheduled for December 4, 2019.

Also PHP 7.0 is EOL since January 10, 2019. I think that 11 months supporting an EOL version is pretty enough, especially given the fact there is an incompatibility that we could fix by doing so.

mikelutz’s picture

So why don't we say that from Drupal 8.8.0 we are not going to support PHP 7.0 anymore?

I've discussed this with the Release Managers in the recent past and I have just reached out for reconfirmation, although I have absolutely no reason to believe the answer has changed. I am under the impression that the decision has been made that it is too late to consider changing the minimum php version requirement for the 8.8.0 release. I'll edit this comment with either confirmation or additional information when I hear back, but I am quite confident that it is safe to assume that updating the minimum php version is not going to happen.

Even if we did, changing a major version on the dispatcher would introduce a number of hard BC breaks that likely wouldn't be acceptable in a Drupal minor release.

It looks like Drupal 9 will be releasing on Symfony 4.4, and this deprecation is in Symfony 4, scheduled for removal in Symfony 5, so we will be able to make our adjustments in Drupal 9.

hchonov’s picture

Even if we did, changing a major version on the dispatcher would introduce a number of hard BC breaks that likely wouldn't be acceptable in a Drupal minor release.

Not if we use the BC layer as suggested in #6 or provide our own based on that one.

hchonov’s picture

I've discussed this with the Release Managers in the recent past and I have just reached out for reconfirmation

Tagging accordingly.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

mikelutz’s picture

Version: 8.9.x-dev » 9.0.x-dev
Status: Postponed » Needs work
Issue tags: -Needs release manager review

Re-opening this, as the Drupal 9.0 branch is well open.

mikelutz’s picture

Here is just a fresh baseline patch with the skipped deprecation removed, for no particular reason. Looking at the code, I think that the LegacyEventDispatcherProxy class is going to override too much of our custom code in ::dispatch, so I suspect we will have to implement its BC logic ourselved in the dispatcher.

mikelutz’s picture

Status: Needs work » Needs review
FileSize
4.17 KB
2.25 KB

Alright, So as I suspected, using LegacyEventDispatcherProxy completely replaces the dispatcher, and we have custom code there. This patch instead takes the bridge logic from that class and uses it to detect and swap the arguments in a BC way.

So with this patch, you can call the dispatcher with the new argument order, but it's not forced yet. We should then switch the order of all the dispatch calls in core, and start triggering errors if they are called in the old order. There are other skipped deprecations around the even system that should be removed at that time, this is just step one.

longwave’s picture

We are trying not to add new deprecations in 9.0.x so should we add a @todo and a followup issue here to deprecate this in 9.1.x? Or, as the existing BC layer is enough for now, just bump this to 9.1.x anyway?

mikelutz’s picture

At the end of this whole process of becoming compatible with the Symfony 4/5 dispatcher we will probably want to trigger some deprecation errors, but I don't think we need todos right now. Symfony itself is triggering plenty of errors around the event system that we are currently suppressing. Once we fix core for those and remove the suppressions, a lot of the error triggering will already be done for us. I'd like to get further in the process before I worry too much about post 9.1.x @todos and such.

I would love to get through this process in 9.0 if possible, as this is a step towards Symfony 5 compatibility in Drupal 9, and after the process of trying to get Drupal 8 compatible with Symfony 4 at the last minute, I would love to be compataible with 5 from the get go, and just fix new things as they come up, rather than trying to sort through everything in crunch time like we did last year.

longwave’s picture

My point was that in this specific case we are replacing a Symfony deprecation with a silent BC layer, but in Drupal 10 I assume we want to remove that BC layer entirely? If so we should create at least a followup to do that now - and to achieve that, we also need to deprecate some time in the Drupal 9 cycle. If we don't do this now, we will likely just forget that this silent BC layer even exists.

xjm’s picture

Issue tags: +beta target

Maybe.

mikelutz’s picture

Version: 9.0.x-dev » 9.1.x-dev
Status: Needs review » Needs work

Given than 9.1 is open now, I've reconsidered and we should add some deprecation errors in now, and target this for 9.1

longwave’s picture

Status: Needs work » Needs review
FileSize
4.56 KB
1.02 KB

Let's see what we need to fix.

Status: Needs review » Needs work

The last submitted patch, 24: 3055194-24.patch, failed testing. View results

catch’s picture

Priority: Normal » Critical
Issue tags: -beta target +Drupal 10

Bumping to critical since it blocks Drupal 10.

mkalkbrenner’s picture

mkalkbrenner’s picture

Maybe #2833771: PSR-14 (Events) development and support should be marked as duplicate, too.

Since it seems that this issue here is the one that will be continued, I repeat my comment from https://www.drupal.org/project/ideas/issues/2833771#comment-13668083

I just want to mention that we removed the hard dependency to symfony's event-dispatcher in the solarium library, the PHP client for Apache Solr.
In solarium we now do pure PSR-14 compliant event dispatching.

symfony itself became PSR-14 compliant with 4.3. Unfortunately drupal core didn't adopt to it.

In order to get the latest solarium version 6 to work with the search_api_solr module for Drupal 8 and 9 I included a light wight PSR-14-Bridge in search_api_solr 4.1.0:
https://git.drupalcode.org/project/search_api_solr/-/tree/4.x/src/Solari...

like already mentioned in #2876675: Allow symfony/event-dispatcher 4+ to be installed in Drupal 8 I hope that drupal becomes more inclusive for third party libraries in the future.

As I proposed in the past, it is not too late to do something similar to symfony's LegacyEventDispatcherProxy in drupal Core to ease the life for contrib developers and to meet your requirements:

From the release management perspective, we would not block the release of Drupal 9 or any major on adopting this PSR. It would have to be adopted in a way that met our BC requirements and ideally followed the continuous upgrade path policy.

catch’s picture

@mkalkbrenner thanks I marked that issue duplicate of this one too.

#3020303: Consider using Symfony flex to allow switching between major Symfony versions would have made it a lot easier to run Symfony 4 on Drupal 8, (or Symfony 5/6 on Drupal 9), but unfortunately has been stalled for some time (mostly on min/max dependency testing).

catch’s picture

Issue summary: View changes
FileSize
4.27 KB

The patch from #18 no-longer applied to 9.1.x, so here's a re-roll.

Also updated the issue summary.

I think we should go ahead and convert calls to EventDispatcher::dispatch() in this issue.

Then we should try another patch with the deprecation un-suppressed/adding our own, and see if it's possible to trigger a deprecation - whether we can or not may depend on dependencies that are also dispatching events. If we're not able to remove the deprecation suppression due to dependencies, we should add a follow-up for that - so that contrib/custom code can start to take advantage of the forward-compatibility layer.

catch’s picture

Started looking at converting the calls, but while there's not a hard dependency, it will be less overall work if we do #3055198: [Symfony 5] Symfony/Component/EventDispatcher/Event is deprecated in Symfony 4.3 use Symfony/Contracts/EventDispatcher/Event instead first - since the conversions here with otherwise have to use the deprecated Event class.

catch’s picture

Title: [Symfony 5] The signature of the "Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3. » [Symfony 5][PP-1] The signature of the "Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.

Making it clear from the title that this is soft-blocked on the other issue.

catch’s picture

Title: [Symfony 5][PP-1] The signature of the "Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3. » [Symfony 5] [PP-1] The signature of the "Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.
Status: Needs work » Needs review
FileSize
39.58 KB
59.88 KB
catch’s picture

Fixing the syntax error..

catch’s picture

Title: [Symfony 5] [PP-1] The signature of the "Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3. » [Symfony 5] The signature of the "Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.
FileSize
42.06 KB

OK after actually doing the patch, there is only one use statement that actually conflicts with #3055198: [Symfony 5] Symfony/Component/EventDispatcher/Event is deprecated in Symfony 4.3 use Symfony/Contracts/EventDispatcher/Event instead, it just happened that was the first class I looked at before, so here's a standalone one with just the changes required for this issue. Since there's no real conflict at all, removing PP-1 as well, either could go in first and it'll be a small re-roll for the other.

What's still missing, as discussed in #18 and #21, is triggering our own deprecation message. This is the Symfony one:

 @trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.', EventDispatcherInterface::class), E_USER_DEPRECATED);

I was originally thinking we should copy the Symfony one exactly, but I think it would be easier to Drupal-ify it instead and use our standard format. Once we've done that we should also add test coverage for the deprecation message.

The last submitted patch, 34: 3055194-33.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 35: 3055194-34.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

catch’s picture

Status: Needs work » Needs review
FileSize
4.52 KB
43.94 KB

Overzealous removing the skipped deprecations, we can't do anything about the parent class/interface so those need to be removed in Drupal 10 as part of the Symfony 5 update process, which is OK.

Also some dispatch invocations in unit tests that my grepping didn't find.

catch’s picture

Think I messed up the patch creation somehow, tests are passing locally. Trying again.

catch’s picture

catch’s picture

Added the deprecation message and a test for it.

catch’s picture

Issue summary: View changes
mkalkbrenner’s picture

+++ b/core/lib/Drupal/Component/EventDispatcher/composer.json
@@ -7,7 +7,8 @@
+    "symfony/event-dispatcher": "^4.4",

Is the event-dispatcher still needed as dependency?

catch’s picture

Yes we still use various classes from there like GenericEvent. It might be worth auditing exactly how much we actually use though.

longwave’s picture

Status: Needs review » Reviewed & tested by the community
+++ b/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php
@@ -86,9 +88,19 @@ public function __construct(ContainerInterface $container, array $listeners = []
+      $event = $event_name ?? new Event();

This is probably quite minor but following #3055198: [Symfony 5] Symfony/Component/EventDispatcher/Event is deprecated in Symfony 4.3 use Symfony/Contracts/EventDispatcher/Event instead we have three events classes to choose from and I wondered exactly which one we should be instantiating here. I suppose this is only the BC layer so instantiating the old Symfony class seems correct.

Everything else looks great so this is good to go, I think.

catch’s picture

So I actually changed that in #3153803: [Symfony 5] Update EventDispatcher::dispatch() to make it forward-compatible with Symfony 5 to use ContractsEvent, but I think that was actually wrong - if existing event listeners are type hinting on the legacy Symfony Event class, we don't want to break those typehints - so the default either needs to be the deprecated class or the Drupal subclass. Either way, I think that issue is the place to finalise that decision since it's where we actually trying to enforce things.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed bd4c5f0 and pushed to 9.1.x. Thanks!

diff --git a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
index be3a950afc..facac8776a 100644
--- a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
+++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
@@ -489,7 +489,7 @@ public function testDispatchLazyListener() {
     };
     $this->dispatcher->addListener('foo', [$factory, 'foo']);
     $this->assertSame(0, $called);
-    $this->dispatcher->dispatch( new Event(), 'foo');
+    $this->dispatcher->dispatch(new Event(), 'foo');
     $this->dispatcher->dispatch(new Event(), 'foo');
     $this->assertSame(1, $called);
   }

Fixed coding standard on commit.

  • alexpott committed bd4c5f0 on 9.1.x
    Issue #3055194 by catch, mikelutz, longwave, mkalkbrenner, hchonov: [...
Ghost of Drupal Past’s picture

tstoeckler’s picture

Here are backports for 8.8, 8.9 and 9.0 in case anyone needs this. Due to the Composer change that is needed for 8.x be warned that this hass more far-reaching consequences there. Because 8.x still has a 3.x symfony/http-kernel, I removed the actual deprecation from those patches.

All patches pass tests on their respective branches at time of writing, which can be seen on #408, #410 and #411 of #2274167: [ignore] Patch testing issue.

(For the record, the version numbers in the patches don't have any meaning other than that it took me a couple tries, respectively, to get them right.)

tstoeckler’s picture

Sorry for the noise. For this to work with Composer setups the patch may not include anything outside of /core, so here's those patches for 8.8 and 8.9.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

alexpott’s picture

Issue tags: +9.1.0 release notes

This is going to affect contrib - see http://grep.xnddx.ru/search?text=-%3Edispatch%28&filename= - we need to mention this in the release notes.

alexpott’s picture

Issue summary: View changes
heddn’s picture

This starting to trouble contrib already: https://www.drupal.org/project/scheduler/issues/3166688, https://gitlab.com/drupalspoons/devel/-/issues/344.

Is/was there no way to introduce this with any BC layer or warning to developers?

moshe weitzman’s picture

Isn't this a compat break between 9.0 and 9.1. Those are not allowed unless I'm missing something. I'm coming from https://gitlab.com/drupalspoons/devel/-/issues/344