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.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

hchonov created an issue. See original summary.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

hchonov’s picture

Status: Needs review » Needs work
FileSize
15.65 KB

This 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.

hchonov’s picture

FileSize
16.49 KB
1.12 KB

I'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.

hchonov’s picture

FileSize
16.4 KB

Re-roll.

hchonov’s picture

Title: Serializing content entity form objects should deeply serialize the entity » Serializing content entity form objects should deeply serialize the entity in case of nested/inline entity forms
Issue summary: View changes
hchonov’s picture

Issue summary: View changes
hchonov’s picture

FileSize
16.35 KB
846 bytes
hchonov’s picture

Issue summary: View changes
hchonov’s picture

FileSize
18.23 KB
1.78 KB

I'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.

hchonov’s picture

+++ b/core/lib/Drupal/Core/Entity/ContentEntityForm.php
@@ -328,6 +347,17 @@ public function getFormDisplay(FormStateInterface $form_state) {
   public function setFormDisplay(EntityFormDisplayInterface $form_display, FormStateInterface $form_state) {
     $form_state->set('form_display', $form_display);
+
+    // If one of the widgets requires a deep entity serialization then the
+    // entity should be deeply serialized as part of the form object
+    // serialization.
+    foreach ($form_display->getComponents() as $component) {
+      if (($widget_definition = $this->widgetPluginManager->getDefinition($component['type'])) && !empty($widget_definition['entity_deep_serialization'])) {
+        $this->entityDeepSerializationRequired = TRUE;
+        break;
+      }
+    }
+
     return $this;
   }

I 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)".

hchonov’s picture

Actually 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.

hchonov’s picture

FileSize
18.48 KB
1.03 KB

There 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().

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kfritsche’s picture

FileSize
18.62 KB

Re-roll #13

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

DamienMcKenna’s picture

If 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.

tstoeckler’s picture

FileSize
19.35 KB

Rebased with the help of PhpStorm's magic wand.

tstoeckler’s picture

Title: Serializing content entity form objects should deeply serialize the entity in case of nested/inline entity forms » [PP-1] Serializing content entity form objects should deeply serialize the entity in case of nested/inline entity forms
Status: Needs work » Postponed

Let's make it clear that this is postponed for now.

tstoeckler’s picture

tstoeckler’s picture

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

gease’s picture

gease’s picture

Removed 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.

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

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

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

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

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.

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

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.