Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Steps to reproduce
- Allow custom layout overrides on articles
- Create an article with body value "original"
- Save article
- Open article /layout page
- update article at /edit page. set body to "updated"
- Open article /layout page
- Save layout
- Article body is again "original"
I discovered this in #2946333: Allow synced Layout override Translations: translating labels and inline blocks because save a translated layout would revert a non translated layout
Proposed resolution
At least get all other field from active entity before saving.
Also could get all other fields from active entity before rendering layout builder to see update field values.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
Comment | File | Size | Author |
---|---|---|---|
#27 | 3033686-revert-25-interdiff.txt | 2.02 KB | tim.plunkett |
#27 | 3033686-revert-25-PASS.patch | 3.16 KB | tim.plunkett |
#27 | 3033686-revert-25-FAIL.patch | 2.23 KB | tim.plunkett |
#27 | 3033686-revert-25-FAIL-no-access.patch | 3.64 KB | tim.plunkett |
#21 | 3033686-override-21-FAIL.patch | 2.17 KB | tim.plunkett |
Comments
Comment #2
tedbowComment #3
tedbowComment #5
tim.plunkettWhat happens if we replace this with the
else
code? Doesn't look good that every other field works except ours, do we need a change in LayoutSectionItem/LayoutSectionItemList instead?This change looks off to me. We should either not be calling
parent::buildEntity()
at all or should be using that result here. And returning a different entity than the one we use as a context value seems wrong for the same reasons.Nit, here we click to get to the page and there we go to it directly. I'm not picky about which way we do it but let's be consistent within a test method.
Nit, extra blank line
Comment #6
tedbow@tim.plunkett thanks for the review!
$this->getEditedFieldNames($form_state)
just returns our field in this case.Changed to
$active_entity->{$edited_field_name} = $previous_context_entity->{$edited_field_name};
Also change the test not do the
drupalGet()
before the last assertion because that could mask an error. We should ready be there after the layout is saved.Looking at the parent
\Drupal\Core\Entity\ContentEntityForm::buildEntity()
I think we still need to call this. We just need to callsetEntity()
before we callbuildEntity()
Changed to set all the fields on
$previous_context_entity
from$active_entity
except thegetEditedFieldNames()
fields plus certain keys we should never be updating.removed this @todo and assertions. this would fail but I think that is separate issue. Should the user doing the layout see new changes to the entity layout builder.
This issue is about making sure these new values are not overwritten.
Comment #7
tim.plunkettI think these variable names are more confusing after the last interdiff
This makes me even more nervous. Are we sure those are the only 4 that matter?
Could this instead add
$entity_type->getKeys();
?Comment #8
tedbow$entity_type->getKeys()
because some key values could have actually been updated and we should carry over their values so we don't revert their values.$langcode
is example of this. Before you make a translation you are free to change the language of entity.Comment #9
tim.plunkettThanks, the explanation about getKeys makes sense.
I think this comment should go with this code
This comment should go with this code
Leaving this comment to go with this code
Move the blank line from below this code to above this code
Nit: put this on one line
Just to avoid accidental changes later, this deserves an explicit comment explaining that it is purposefully visiting the layout page so that there will be a tempstore entry _before_ editing the node values.
Also we should be super careful to fix tests if we ever make it so that visiting the layout page without changing anything does not make a tempstore entry... Maybe better to explicitly add a block here?
Comment #10
tedbowAddressed all in #9 including adding a block to the override in the test.
Comment #11
tim.plunkettNit, might as well put this below the comment too
Didn't get an answer on this part
Not this part, that clears the tempstore! Also, blank line
Comment #12
tedbow$section_storage_entity->getFields()
at all because$section_storage_entity->getFieldDefinitions()
gives us everything we need.also uploading a test only patch that only runs this test class. Because 3) #10 test would have also passed in HEAD. So making sure we have the correct test.
Comment #14
tedbowfor the test only I update drupalci.yml incorrectly
Comment #15
tim.plunkettThanks! RTBC assuming the FAIL fails and the other passes.
Comment #17
tedbow#14 was intended to fail
Comment #18
xjmWhoopsie-daisy, data loss.
Comment #20
xjmCommitted to 8.7.x.
I am assuming this also affects 8.6.x unless it's a recent regression. Should we backport it?
Comment #21
tim.plunkettThe fix in 8.7 relies on the existence of an entity form, which wasn't backported to 8.6
In the meantime, here's the test backport
Comment #24
xjmReverted at @tim.plunkett's request. Thanks!
Comment #25
tim.plunkettComment #27
tim.plunkettThe override of
buildEntity()
turns out to be completely unnecessary (at least in its current implementation). I added that in #3004536: Move the Layout Builder UI into an entity form for better integration with other content authoring modules and core features #49 and #53, and it turns out that it wasn't really needed, only the addition in #68 of that issue.Comment #28
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThanks, Tim! The new "pass" patch looks great to me and fixes the problem I encountered in #2950869-41: Entity queries querying the latest revision very slow with lots of revisions.
Comment #29
tim.plunkettHighlighting from the "FAIL-no-access" patch:
I added the buildEntity because our layout field wasn't being synced correctly.
Later, that issue added the #access = TRUE line. It turns out, that's all that was needed. It was preventing it from being synced over.
Thanks for the review!
Comment #32
xjmSo the why-this-works is a bit mind-bending, especially for how simple the final patch actually is. @tim.plunkett, @tedbow, and I walked through it.
One thing that's out of scope that we want a followup for is for:
NIH, but that's kinda scary. The followup wouldn't be #2942975: [PP-1] Expose Layout Builder data to REST and JSON:API, but rather a separate issue to discuss hardening this so that it's a bit less sweeping than
TRUE
.I manually tested the new patch and confirmed that it's working. However, there is one thing that's still weird. When I reloaded the layout tab in step 6 of the STR in the IS, I expected to see the updated field content on the page. However, it still shows the original field content, which only appears to "change" after save. So from the perspective of the user editing the layout, there's a weird mismatch between what's on their screen and the actual state of the data.
It's still way better than data loss (actually, this should be critical), but it'd be good to at least discuss the "stale content from the tempstore" behavior and whether we should fix it or open a followup or whatnot.
Comment #33
xjmComment #34
tim.plunkett#3035955: Ensure that setting #access => TRUE for the Layout Builder field is acceptable is for the bit mentioned in #32.
#3035992: Stale values can be displayed by the Layout Builder UI but are saved correctly is the follow-up for this issue (which I linked from that side of things)
I think we need to fix the data loss NOW, which is what the patch does.
This issue also blocks multiple other issues.
Comment #35
tedbowThis looks good. Talked to @xjm and @tim.plunkett about the follow up and I think we can handle that there.
Comment #37
xjmOK, I'mm comfortable with committing this as-is to stop the data loss, so long as we have #3035992: Stale values can be displayed by the Layout Builder UI but are saved correctly.
Committed to 8.7.x. Thanks!
It seems increasingly unlikely that there will be a straightforward backport for this, so leaving it as an 8.7.x-only major bugfix for now.
Comment #39
Ryanm81 CreditAttribution: Ryanm81 commentedThis same issue now seems to be happening with Drupal 10.1.
Upon reverting the layout back to default for a node, it strips all the fields of that node.
This seems dependent on if there were new sections added/removed to the default layout after node creation.