Problem/Motivation
This is a follow-up for #2824097: Deep serialization for content entities to make an exact snapshot of an entity object's structure based on its current state to make the form cache store the deeply serialized entity in case a widget for nested/inline entity forms is being used by the form display.
We need this in order not to loose changes made on inline referenced entities. Currently core has the behavior that when a new field item is appended because of WidgetBase::addMoreSubmit the form object will be cached and as part of it the entity having the values from the new field item. However if you are dealing with inline references, then the changes will be lost and in some cases there is even no workaround possible.
This is not only a task / feature request, but also a bug report. There is a similar issue - #2824293: Inconsistent form build between initial form generation and the first ajax request which should use deep serialization to ensure the referenced entities are the same on the first ajax call as during the initial form build and this issue here should ensure that the entities are the same between subsequent ajax calls.
Proposed resolution
In ContentEntityForm::setFormDisplay()
check if the provided form display uses a widget that is flagged to require entity deep serialization and if so in ContentEntityForm::__sleep()
flag the entity for deep serialization.
Remaining tasks
Write Patch, Review & Commit.
User interface changes
None.
API changes
ContentEntityFormInterface:: isEntityDeepSerializationRequired() to check if the entity from the form object has to be serialized deeply. This might be used by custom/contrib modules and will be used by the autosave_form module to check if the entity has to be deeply serialized instead of implementing the whole check over again.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#26 | interdiff-25-26.txt | 1.9 KB | gease |
#26 | 2844229-26-combined.patch | 43.66 KB | gease |
#25 | 2844229-25-combined.patch | 43.66 KB | gease |
#25 | 2844229-25.patch | 22.18 KB | gease |
#22 | 2844229-22-combined.patch | 43.58 KB | tstoeckler |
Comments
Comment #3
hchonovThis patch is a PoC and is built on top of #2824097-86: Deep serialization for content entities to make an exact snapshot of an entity object's structure based on its current state. It should be tested when the patch from the other issue is committed.
The relevant part of the patch is contained only in ContentEntityForm, the other parts are just adjustments to the constructors of classes extending from ContentEntityForm.
Comment #4
hchonovI've just realised that I will be needing a getter for the property "entityDeepSerializationRequired" in order to not duplicate the logic for estimating it in the autosave_form module.
Comment #5
hchonovRe-roll.
Comment #6
hchonovComment #7
hchonovComment #8
hchonovComment #9
hchonovComment #10
hchonovI've just found out that if we first cache the form array in the FormCache then the logic for flagging the entity for deep serialization in ContentEntityForm::sleep will not be called and the entity contained the form array having the same reference in the form object as well will be serialized just as normal without being flagged for deep serialization and serializing later the form object will be too late as all the entity references will be already thrown away.
To solve this we have two options:
1. Add additional deep serialization logic in the form cache
or
2. Just adjust the form cache to first serialize the form object and then the form array.
I think 2. is much better solution without any additional code to the form cache, only rearranging what is being first cached. This is also the solution I've implemented in the current patch.
Comment #11
hchonovI am not sure if it is better that we introduce a new widget setting "entity_deep_serialization" and check if it is set or it is better that we introduce a new abstract class/interface EntityReferenceInlineWidgetBase/EntityReferenceInlineWidgetInterface and check
"is_subclass_of(widget_definion['class'], $inline_wdiget_class/$inline_widget_interface)".
Comment #12
hchonovActually this is a bug report as it is the same as #2824293: Inconsistent form build between initial form generation and the first ajax request, but the other issue has to take care between the initial form build and the first ajax call and this one between subsequent ajax calls.
Comment #13
hchonovThere might be components that don't have a type property, therefore we have to check that the component has a type. This could occur by adding components e.g. through hook_entity_extra_field_info().
Comment #15
kfritscheRe-roll #13
Comment #18
DamienMcKennaIf it helps confirm this works as intended, I've been writing tests in #2830829: Entities are not updated during buildEntity() phase to cover some common scenarios on Inline Entity Form.
Comment #19
tstoecklerRebased with the help of PhpStorm's magic wand.
Comment #20
tstoecklerLet's make it clear that this is postponed for now.
Comment #21
tstoecklerTo at least make sure this doesn't break anything, here's a combined patch with #147 over in #2824097: Deep serialization for content entities to make an exact snapshot of an entity object's structure based on its current state.
Comment #22
tstoecklerOK, that was easy enough.
Comment #25
geaseRe-roll against 8.9.x of both from #22.
Comment #26
geaseRemoved deprecation and code style issues from combined patch. Testing bare patch doesn't make sense, cause it relies on change record which is to be introduced with #2824097: Deep serialization for content entities to make an exact snapshot of an entity object's structure based on its current state.
Deprecation notices touch only combined patch, bare patch didn't need to be updated.