Problem/Motivation

At core 9.1 we get the following deprecation message:

Calling the Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch() method with a string event name as the first argument is deprecated in drupal:9.1.0, an Event object will be required instead in drupal:10.0.0. See https://www.drupal.org/node/3154407

Change Records
https://www.drupal.org/node/3154407 - Signature of EventDispatcherInterface::dispatch() has changed
https://www.drupal.org/node/3159012 - Symfony Event class deprecated, EventDispatcher::dispatch() argument order changed

Issue fork rules-3172039

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jonathan1055 created an issue. See original summary.

jonathan1055’s picture

There are currently 516 warnings at core 9.1. I have fixed this in Scheduler module see #19 in #3166688-19: Deprecated: Calling EventDispatcherInterface::dispatch() with a string event name
Scheduler uses Rules in its tests as we provide Rules actions and conditions.

Just creating this issue to record the current state - I'm OK with having the allowed deprecation count for now, as we have other things to do in Rules which are more urgent.

tr’s picture

Status: Active » Postponed

Core isn't going to backport this change to D8 so fixing this deprecation will have to wait until we branch Rules and have a separate D9 branch. We still have a few years until D10, which is when this change will be required ...

jonathan1055’s picture

StatusFileSize
new9.39 KB

Actually, we can fix this right now and its not too compex to do. This patch resolves all 516 of the warnings, and in essence all it does is intercept the places that dispatch an event, instead of dispatching directly, to use a function which swaps the parameter order when running on Core 9.1 and above before calling the real dispatch function. In summary, and numbering for ease of reference:

  1. I have piggy-backed on the RulesLog class in /src/Logger/RulesLog.php to re-use existing code, as this already has the \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher property, but I understand that this might not be the proper place for our dispatcher function. However, this was done for expediency and to demonstrate the point with minimal code change.
  2. The majority of the actual changes are simply
    -  $event_dispatcher = \Drupal::service('event_dispatcher');
    +  $event_dispatcher = \Drupal::service('logger.ruleslog');
    

    or in test files the equivalent

    -    $event_dispatcher = $this->container->get('event_dispatcher');
    +    $event_dispatcher = $this->container->get('logger.ruleslog');
    
  3. All Rules events (apart from one) extended Symfony\Component\EventDispatcher\GenericEvent which is good. The odd one out is UserLoginEvent which extends just Symfony\Component\EventDispatcher\Event. This had to be changed to use GenericEvent instead, which only involved one extra line $this->arguments = ['account' => $account]; in the __construct() function
  4. src/Logger/RulesLog.php has the new dispatch() function and also uses it in its own call for SystemLoggerEvent
  5. In tests/src/Kernel/EventIntegrationTest.php, the tests testInitEvent() and testTerminateEvent needed to have an $event object to pass to the new dispatch() function, so this was simply added by $event = new GenericEvent()

I am not saying we have to commit this, or even that this is the best solution, but wanted to demonstrate how it can be done, and to test it with druapalci.yml to show that the depecations can be fixed.

jonathan1055’s picture

As expected the patch failed due to the other deprecations, but there are none for the dispatch() parameter order.
See Travis test for 9.1 deprecation info https://travis-ci.org/github/jonathan1055/rules/builds/730185319
Only 347 deprecations in total (297 void hint and 50 placeholder prefix)

Compare with 9.1 test without this patch https://www.drupal.org/pift-ci-job/1832280

tr’s picture

-  $event_dispatcher = \Drupal::service('event_dispatcher');
+  $event_dispatcher = \Drupal::service('logger.ruleslog');

No, I don't want to do this. Rules needs to be able to react to any Symfony event, not just events generated through a Rules-specific mechanism. Plus this adds a mandatory Rules dependency to every contributed module that wants to provide Rules integration - right now those modules can just dispatch events whether or not Rules is enabled, and provide Rules plugins for conditions and actions which are just ignored if Rules is not installed. That wouldn't be true any more, and all those contributed modules would need to be changed.

This deprecation can be handled with a bunch of version_compare() calls, but we're going to have more and more of these non-BC changes in D9.1 as time goes on and each will require its own version_compare() - it's not going to be just this one. I really think this needs to be addressed in a separate minor branch after we switch to semantic versioning.- $event_dispatcher = \Drupal::service('event_dispatcher');
+ $event_dispatcher = \Drupal::service('logger.ruleslog');

tr’s picture

Status: Postponed » Active

Re-opening now that D8 is no longer supported.

We should be able to do this by following the instructions in the change record.

beatrizrodrigues’s picture

Assigned: Unassigned » beatrizrodrigues

I'll work on that.

beatrizrodrigues’s picture

Assigned: beatrizrodrigues » Unassigned
Status: Active » Needs review

So, I changed almost every EventDispatcherInterface::dispatch() calls, but there is this one that I was not able to solve. There was this test called testTerminateEvent() and the call was like this:

// Manually trigger the initialization event.
    $dispatcher->dispatch(KernelEvents::TERMINATE);

A $event was missing, I was able to solve this problem at the testInitEvent() but I couldn't be able to do it in that testTerminateEvent(). I tried to create an event just like I did in the testInitEvent():

    $kernel = $this->container->get('kernel');
    $event = new RequestEvent($kernel, \Drupal::requestStack()->getCurrentRequest(), HttpKernelInterface::MASTER_REQUEST);
    $dispatcher->dispatch($event, KernelEvents::REQUEST);

creating an event, but when I try to create an TerminateEvent, it requests me a response parameter, and I was not able to get it.
So, I would like some suggestions if it is possible. Thank you!!

beatrizrodrigues’s picture

Status: Needs review » Needs work
tr’s picture

Your MR looks very good. I don't have an answer to your question right now, but I will look into it to see if I can find out what to do there.

tr’s picture

I think in the case of EventIntegrationTest, for both testInitEvent() and testTerminateEvent(), you can just create a new Drupal\Component\EventDispatcher\Event and dispatch it as ->dispatch($event, KernelEvents::REQUEST) or ->dispatch($event, KernelEvents::TERMINATE). There is no context declared for these events in rules.rules.events.yml, so the only thing that really matters to Rules for these is the event name, since that's what we listen for and trigger on.

This is a Kernel test, and the test removes all other listeners for these events because we are only trying to verify that Rules responds to them correctly. So for test purposes this should work just fine.

beatrizrodrigues’s picture

Status: Needs work » Needs review

thank you @TR I followed your suggestion. And also did a rebase. Thanks again

tr’s picture

StatusFileSize
new5.6 KB

The MR needs to be rebased again - I'm not sure why, and I'm not sure why the auto rebase couldn't handle it. But also there are two unused use statements now, so I decided to just post a patch to update the MR.

@jonathan1055, do you want to add on the needed changes to .travis.yml for this fix? Drupal 9.1 is no longer supported, so we can fix D9.2 deprecations now, and it's nice to be aware of the new deprecations in D9.3 and D9.4.

  • TR committed bb7a095 on 8.x-3.x authored by beatrizrodrigues
    Issue #3172039 by beatrizrodrigues, TR, jonathan1055: [9.1]...
tr’s picture

Status: Needs review » Fixed

Committed #16.

jonathan1055’s picture

I did not get chance to check the deprecations on Travis before now. The commit has introduced a new one

94x: Symfony\Component\EventDispatcher\Event is deprecated in drupal:9.1.0 and will be replaced by Symfony\Contracts\EventDispatcher\Event in drupal:10.0.0. A new Drupal\Component\EventDispatcher\Event class is available to bridge the two versions of the class. See https://www.drupal.org/node/3159012

We can leave this issue as fixed. I have raised a new issue
#3259445: Symfony\Component\EventDispatcher\Event is deprecated in drupal:9.1.0 to deal with this.

tr’s picture

Yes, I'm aware of that, and have been running a fix for that locally for the past month or so. I have been doing some work with the event system and this is a little tricky to do in a BC way. I will post a patch in your new issue.

tr’s picture

Component: Rules Core » Events

Status: Fixed » Closed (fixed)

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