Problem/Motivation
As a follow up for the issue #3481695: Entity displays cloning requires special config action and inspired by #3482783: Consider making the cloneAs config action optionally fail if the clone already exists, I think it makes sense to ignore the existing entity display if someone tries to copy another entity display into it. This is needed to allow to run recipe multiple time if it has createCopy config action. This will ensure the idempotence of the recipe.
createCopy(), though, doesn't really need to be an action of its own. EntityDisplayBase's createDuplicate() will do the correct thing, and that would work with the cloneAs action. The problem is that cloneAs needs to support wildcards, which it currently does not.
Proposed resolution
Make cloneAs support positional tokens that map to the corresponding parts of the original entity's ID:
config:
actions:
core.entity_view_display.node.*.default:
# The original's ID has three parts: the entity type, the bundle, and the view mode. These are all mapped to the '%' token in the same position. So, if the bundle is `foo`, this will be `node.foo.search_result`.
cloneAs: node.%.search_result
Since this will make cloneAs work properly with wildcards, we should also remove createCopy() as an action.
| Comment | File | Size | Author |
|---|---|---|---|
| #29 | recipe_config_action.mp4 | 12.7 MB | atul_ghate |
| #27 | create_recipe.mp4 | 12.07 MB | atul_ghate |
| #15 | 3483353-create-copy-entity-display-optional.patch | 2.03 KB | a.dmitriiev |
| #12 | 3483353-create-copy-entity-display-optional.patch | 2.75 KB | a.dmitriiev |
Issue fork drupal-3483353
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
Comment #3
a.dmitriiev commentedUploading patch for composer
Comment #4
a.dmitriiev commentedI have checked the change with Drupal CMS search track recipes and it works as expected.
Comment #5
a.dmitriiev commentedComment #6
thejimbirch commentedComment #7
phenaproximaThis is a flaw(?) in the actual method itself, not the recipe system, so a little housekeeping here...
Comment #8
phenaproximaOne possible fix here is to add an optional boolean flag to createCopy() that loads an existing one if possible:
Not sure what the default behavior should be, though. Probably to keep the current behavior but allow it to be overridden.
Comment #9
a.dmitriiev commentedI think optional parameter
bool $use_existing = FALSEwould be a nice solution here, so that the method doesn't try to load the copy always, but only when use_existing is TRUE. Nice approach.Comment #10
a.dmitriiev commentedUpdated patch
Comment #11
a.dmitriiev commentedComment #12
a.dmitriiev commentedForgot about the interface
core/lib/Drupal/Core/Entity/Display/EntityDisplayInterface.phpComment #13
phenaproximaTwo things:
Comment #14
a.dmitriiev commentedThe change is in MR https://git.drupalcode.org/project/drupal/-/merge_requests/9944/diffs . I posted a patch just to use it in composer. Ok, I will remove the change from the interface, but the LayoutBuilder complains that its declaration is different, so this has to stay.
Comment #15
a.dmitriiev commentedUploading the new patch for using in composer. The change was pushed to MR.
Comment #16
a.dmitriiev commentedComment #17
phenaproximaLooks sensible to me, but needs test coverage :) Once that's done I'd be fine RTBCing this.
Also, we need to target 11.x here - this changes public API to an extent and therefore I don't know if committers will be comfortable backporting it to 10.4.x. That will be a decision for them to make.
Comment #20
a.dmitriiev commentedComment #21
phenaproximaJust a couple of suggested clarifications that might benefit the test, but overall I don't have anything to complain about here.
Comment #22
phenaproximaJust a couple of suggested clarifications that might benefit the test, but overall I don't have anything to complain about here.
Comment #23
roderikI did a hit-and-run review comment because I was curious after seeing the review request in Drupal Slack.
I don't know the full issue history, but could you have a look? (Not changing status myself.)
Comment #24
atul_ghate commentedComment #25
smustgrave commentedAppears to have test failures.
Comment #26
a.dmitriiev commentedThe tests were fixed.
Comment #27
atul_ghate commentedI followed the steps to reproduce the issue as outlined below:
1Installed Drupal with the standard profile.
2.Switched to the 3483353-entity-copy-use-existing branch from 11.x.
3.Created a recipe with the createCopy configuration action.
4.Ran the recipe twice and verified the result on the site.
Test result: After running the recipe twice, I am still encountering the same error as mentioned (please refer to the attached video for reference).
Please let me know if there are any steps I might be missing in order to properly reproduce this issue? Thank you.
Comment #28
a.dmitriiev commentedFor action method `createCopy` the new optional parameter was added `use_existing`, that allows avoiding the error. The recipe should have this config action:
Comment #29
atul_ghate commentedHi @a.dmitriiev, thank you for correcting me during the testing.
I went through the verification process again, following the steps outlined in comment #28. (You can check the attached video for reference.)
Test Results:
1.No errors occurred when I ran the same recipe twice.
2.Everything is functioning correctly, and all tests have passed.
Since everything is working as expected, I'm changing the issue status to RTBC.
Comment #30
phenaproximaDrupal CMS's search functionality depends on this patch, and it is therefore a Drupal CMS stable release blocker.
Comment #31
thejimbirch commentedComment #32
alexpottI'm not sure about this. I think with the clone and createCopy config actions we've kind of built new create and createIfNotExists actions and this specific issue has made me ponder if we should have extend those actions to support getting default values from existing entities. That way we'd get both functionalities in a consistent way and we would have the problem we have here where every recipe is going to want to have $use_existing set to TRUE… but obvs we don’t want to change the behaviour of the existing method
Comment #34
phenaproximaThat's a good point.
I have opened a new merge request that implements two new config actions:
The cloneAs and createCopy actions have not yet made it into a stable release, so let's just remove them now and replace them with these more generalized and versatile actions. It turns out this is quite a bit simpler to implement, and the existing test coverage pretty much handles it (you just gotta switch the order of the "arguments", as it were).
There is only one major flaw here that I can see, which is that this gets very awkward when we think about wildcards. If you're trying to create entity displays for every content type and they don't already exist, the action gets bypassed entirely since the config that is being "targeted" for creation doesn't even exist yet. So that might not work for the search recipe. This is tricky.
Comment #35
phenaproximaAs I play with this more, I kind of wonder...do we even need to expose
createCopy()as an action?We already changed EntityDisplayBase::set() so that, if you update the ID, the associated properties are updated as well.
And we already have a fail_if_exists flag in cloneAs -- it's a wrapper around both
createandcreateIfNotExists.So maybe there is actually no bug here at all, and we just should rip out
createCopy, because it's not necessary. You could clone entity displays politely like this:The problem here, again, is wildcards. It's hard to do cloning with wildcards. I think that is why we exposed
createCopy()as an action in the first place. But that obviously has its own problems. So I am now +1 on removingcreateCopy().But we still need to figure out how to support wildcards. One possibility is to change
cloneAsso that it supports positional wildcard arguments, something like this:In this example, the
${1}is replaced by the second period-separated component of the original entity's ID. This would be givingcloneAsa superpower, but it would be similar in syntax to inputs and would handle the problem of cloning when wildcards are there.Comment #36
a.dmitriiev commentedI can confirm that new approach works for Search recipe from Drupal CMS
Comment #37
a.dmitriiev commentedChecked the changes, they are working properly in the recipe for entities with complex ids.
Comment #38
phenaproximaComment #40
phenaproximaComment #41
phenaproximaAdjusting credit.
Comment #42
phenaproximaComment #43
phenaproximaTagging for change record update on commit.
Comment #44
alexpottCommitted and pushed 3de28c0f679 to 11.x and fef85c9a8d8 to 11.1.x and d7ddf065f91 to 10.5.x and 21d16eedcce to 10.4.x. Thanks!
Which CRs need updating?
Comment #49
phenaproximaUpdated https://www.drupal.org/node/3481718.
Comment #50
thejimbirch commented