Problem/Motivation

Prior to #2932462: Add EntityContextDefinition for the 80% use case, it was possible to create a ContextDefinition for an arbitrary entity data type, e.g. ContextDefinition::create('entity:user') or ContextDefinition::create('string'). This is significantly harder in D9, because ContextDefinition's constructor requires any entity:-prefixed data type to be using an instance of EntityContextDefinition. (Note that entity -- no colon -- is still a valid data type for ContextDefinition.)

So, if the data type is variable, there's no easy way to create a context definition for it. You have to know in advance that context definitions for a specific entity type need to use EntityContextDefinition::create(). That's both poor DX, and a problem for modules like Rules that rely extensively on variable data types. (See https://drupal.slack.com/archives/CDDD98AMN/p1586802654384900 for some more discussion about the problems this causes for Rules.)

Proposed resolution

ContextDefinition::create() should helpfully call EntityContextDefinition::create() if the data type begins with entity:. That way it can continue to be a useful factory method when the data type is not known in advance.

Remaining tasks

Review the merge request and commit it.

API changes

None.

UI changes

None.

Data model changes

None.

Release note

Not sure if we need one...?

Issue fork drupal-3126747

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

TR created an issue. See original summary.

TR’s picture

Title: EntityContextDefinition breaks the context system » EntityContextDefinition breaks the plugin context system
Issue summary: View changes
Issue tags: +Contributed project blocker
tim.plunkett’s picture

You can use ContextDefinition::create('entity') or ContextDefinition::create() for generic conditions.
EntityContextDefinition is only to replace usages when the entity type is already known.

tim.plunkett’s picture

Status: Active » Needs review
Issue tags: +Needs tests
FileSize
646 bytes

Here is a proposal that I think captures what you described in Slack.

TR’s picture

Issue summary: View changes
tim.plunkett’s picture

Title: EntityContextDefinition breaks the plugin context system » ContextDefinition::create() can no longer be used with an entitytype-specific datatype (like entity:user)

EntityContextDefinition isn't what's broken per se. It's the regression to being able to pass "entity:WHATEVER" as a data type.

But, the patch above points to a larger issue (that should be opened as a follow-up):
If supporting other ContextDefinition subclasses requires changing ContextDefinition itself, contrib/custom code cannot participate.
This is already partially true in \Drupal\Core\Annotation\ContextDefinition::getDefinitionClass(), but has an affordance for custom classes.

TR’s picture

The patch is enough to allow me to make Rules work in D9. I think it should also be backported to D8 so that the deprecation error isn't triggered by ContextDefinition::create('entity:' . $datatype) and so the API remains the same in D8 and D9.

Looking at the way the BC layer in ContextDefinition was written in D8.6+, I don't understand why delegation was used rather than the simple fix in the the above patch. If the simple fix is good enough for D9 then I think it should be fine for D8.

EntityContextDefinition isn't what's broken per se. It's the regression to being able to pass "entity:WHATEVER" as a data type.

Yes. Although EntityContextDefintion::__construct() should still be fixed to accept "any" and "entity" as datatypes. "any" because that is the documented default value so it should work if I use "any" or leave off the datatype. And "entity" because it wasn't clear to me that ContextDefintion::create('entity') was still valid - the documentation says "Constructing a ContextDefinition object for an entity type is deprecated" so I assumed that applied to the generic 'entity' as well. Regardless, my expectation is that EntityContextDefintion::create('entity') and EntityContextDefintion::create() should work.

But, the patch above points to a larger issue (that should be opened as a follow-up):
If supporting other ContextDefinition subclasses requires changing ContextDefinition itself, contrib/custom code cannot participate.

Yes. Even with this change, Rules still has to do some work because we rely on extending Context, which means we will have to replicate and override all the subclasses of Context. But that's at least do-able with this patch. For the follow up, perhaps we can consider a context manager service. Or better yet see if we can move any entity-specific stuff "up" a level so we can treat all typed data the same way and eliminate the need for EntityContextDefinition.

tim.plunkett’s picture

I don't understand why delegation was used rather than the simple fix in the the above patch

Because the above patch just occurred to me when I wrote it on Monday, and it hadn't occurred to me almost 2 years ago when we worked on the original implementation.

Although EntityContextDefintion::__construct() should still be fixed to accept "any" and "entity" as datatypes.

EntityContextDefintion cannot accept any or entity. It must know the entity type.

it wasn't clear to me that ContextDefintion::create('entity') was still valid

I think we can all agree that the docs need improving.

TR’s picture

Because the above patch just occurred to me when I wrote it on Monday, and it hadn't occurred to me almost 2 years ago when we worked on the original implementation.

OK, I was worried that I was missing something fundamental. The patch in #4 is a good and simple solution without the drawbacks and the regression of the BC layer added in D8.

EntityContextDefintion cannot accept any or entity. It must know the entity type.

It must know it as it is currently written, but if 'any' or 'entity' were passed into the constructor it could just delegate the construction to its parent class ContextDefinition, right? The problem is that since EntityContextDefinition is a subclass of ContextDefinition, it inherits the signature of the __contruct() method, so it is really obligated to properly handle any arguments that are valid according to the method signature, especially arguments that are default values. PHP does not allow us to modify the method signature on a subclass, and even if it did it would be bad OO practice to do so.

I will work on adding a test for #4 over the weekend.

jonathan1055’s picture

Thank you @tim.plunkett and @TR for working on this. As a contributor to Rules D8, working on many of the deprecation issues, I support your effort to get this in, then we can make proper progress on Rules.

Yuri’s picture

Just wondering if anyone is successfully using Rules for D9?
I'm using D9.0.5 and installed Rules dev, installed manually the patch #4 (since composer complained the patch could not be installed), cleared caches, but entity relationships don't appear in Actions.

When I create a new component, add a new condition 'Entity is of bundle', I see a data sector where i can select @node.node_route_context:node
And I see two other required fields 'Bundle' and 'Type' which give no supportive text how to input data, apparently direct input fields. If I enter in those node and article (also tested with [node] and [article], it does not result in the custom fields in the article content type to show up in the action:

'Add list item' or 'Set a data value' allows to set a context variable Data @node.node_route_context:node with all its standard fields, but the custom fields added are not visible.

TR’s picture

@Yuri: Your post has nothing to do with this issue.

tim.plunkett’s picture

Status: Needs review » Needs work

NW for tests

Version: 9.0.x-dev » 9.1.x-dev

Drupal 9.0.10 was released on December 3, 2020 and is the final full bugfix release for the Drupal 9.0.x series. Drupal 9.0.x will not receive any further development aside from security fixes. Sites should update to Drupal 9.1.0 to continue receiving regular bugfixes.

Drupal-9-only bug reports should be targeted for the 9.1.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.2.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

phenaproxima made their first commit to this issue’s fork.

phenaproxima’s picture

Version: 9.1.x-dev » 9.2.x-dev
Status: Needs work » Needs review
Issue tags: -Needs tests

OK, I wrote a simple test of this, based on @tim.plunkett's patch in #4. Probably could use more robust coverage, but I imagine this is technically enough to remove the "Needs tests" tag. :)

phenaproxima’s picture

Issue summary: View changes

I decided to rewrite the IS to more concisely communicate the nature of the problem, as best I can tell, and the fix that @tim.plunkett's patch implements.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue tags: +Bug Smash Initiative

This is definitely a bug so I'm adding it to the Bug Smash Initiative.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Spokje’s picture

Status: Needs review » Reviewed & tested by the community

- Patch is now against 9.3.x.
- Looked at the changes and they make sense to me (minimalistic testing is going to be big in 2021...)

Marking as RTBC if TestBot agrees. (Me thinks TestBot will kick it back to NW if something fails.

  • catch committed 1c94be4 on 9.3.x
    Issue #3126747 by phenaproxima, tim.plunkett, TR, Spokje:...

  • catch committed be844d5 on 9.2.x
    Issue #3126747 by phenaproxima, tim.plunkett, TR, Spokje:...

  • catch committed 25e88fd on 9.1.x
    Issue #3126747 by phenaproxima, tim.plunkett, TR, Spokje:...
catch’s picture

Version: 9.3.x-dev » 9.1.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 9.3.x and cherry-picked to 9.2.x and 9.1.x, thanks!

Status: Fixed » Closed (fixed)

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