Problem/Motivation

The method \Drupal\eca\EventSubscriber\EcaBase::onEvent currently handles only the event object, that's being passed on by \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch. That dispatcher also passes on the event name and the context.

We should also handle the event name as the second argument, pass that on to the processor and from there to \Drupal\eca\Entity\EcaStorage::loadByEvent to only load those event, that really are used in models.

Ran into that issue while implementing eca_state_machine where they have one event class WorkflowTransitionEvent which is used with a huge variety of event names. But those event names are not included anywhere other than that second argument described above.

I'll post a fix, shouldn't be that difficult.

Issue fork eca-3271039

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

jurgenhaas created an issue. See original summary.

jurgenhaas’s picture

Issue tags: +release1.0
Parent issue: » #3238206: ECA 1.0.0 stable release plan

jurgenhaas’s picture

Status: Active » Needs review

This is working as expected and all tests are still passing.

mxh’s picture

Status: Needs review » Needs work

\Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher::dispatch states regarding the $eventName parameter:

@param string|null $eventName
The name of the event to dispatch. If not supplied, the class of $event should be used instead.

That means NULL or nothing is allowed to be set, meaning it's not guaranteed to have an event name defined. That needs to be taken care of accordingly. This is relevant when using Symfony-based packages within Drupal that are not aware of Drupal.

When having an event name, it could be considered using the event name instead of the event class in general. I currently don't see that it makes sense to use both within EcaStorage::loadByEvent and thus looks like unnecessary overhead.

jurgenhaas’s picture

That means NULL or nothing is allowed to be set, meaning it's not guaranteed to have an event name defined. That needs to be taken care of accordingly. This is relevant when using Symfony-based packages within Drupal that are not aware of Drupal.

That's correct, calling dispatch can omit the event name, but the dispatch method itself already makes sure that the event name is being set with a string value before triggering the callable from the subscriber. So, there we can rely on the event name being present. Unless I'm missing something?

When having an event name, it could be considered using the event name instead of the event class in general. I currently don't see that it makes sense to use both within EcaStorage::loadByEvent and thus looks like unnecessary overhead.

That's a good point, the event name should be unique where the class isn't. I'll give that a try.

jurgenhaas’s picture

Status: Needs work » Needs review

Yes, that works as well and the modified code is contained in the MR for another review.

mxh’s picture

Status: Needs review » Reviewed & tested by the community

So, there we can rely on the event name being present. Unless I'm missing something?

The problem is, that this is not a guarantee from that method, because it's neither documented nor contracted in any way. The only thing where this is "defined" is by its current inner implementation. But it may be very unlikely that Drupal is changing that behavior in the future, thus I don't see this as a blocker. We should generally rely on officially API contracts though and only fall back to "trusting" inner implementation logic.

  • jurgenhaas committed 3942840 on 1.0.x
    Issue #3271039: Check events against the triggered event name
    
jurgenhaas’s picture

Status: Reviewed & tested by the community » Fixed

Thanks for the clarification, you're absolutely right. In this case, at least we know for sure that all model tests would be failing right away, if that inner implementation in core would have changed.

mxh’s picture

Now that we take that event name into account, it might also make sense to drop "drupal_event_class" in favor of "drupal_id" everywhere it is currently used (especially on appliance checks). At least we should consider passing it along the ::applies methods as it is now part of the pre-emptive loading of configurations. We should also consider renaming "drupal_id" to "drupal_event_name" for sake of consistency. We could address this as a separate issue if you agree.

jurgenhaas’s picture

Great idea, I'm all up for this. Removing the drupal_event_class completely should be the goal. I've just scanned the code and it's almost possible:

  • All instances of $this->drupalEventClass() in plugins can be replaced with drupal_id
  • The usage of $this->plugin->drupalEventClass() in \Drupal\eca\Entity\Objects\EcaEvent::applies can be replaced with the event name as you suggested.
  • The only one that needs some thought is \Drupal\eca\Event\TriggerEvent::dispatchFromPlugin where we determine the event class from the ECA event plugin.

Let's address this in a new issue though.

mxh’s picture

Status: Fixed » Closed (fixed)

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