diff --git a/core/lib/Drupal/Core/Entity/ContentEntityForm.php b/core/lib/Drupal/Core/Entity/ContentEntityForm.php index 14e910d..aba9adb 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityForm.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityForm.php @@ -3,6 +3,7 @@ namespace Drupal\Core\Entity; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Entity\Display\EntityFormDisplayInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Form\FormStateInterface; @@ -30,6 +31,13 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface protected $entity; /** + * Whether a deep serialization should be performed on the entity object. + * + * @var bool + */ + protected $entityDeepSerializationRequired = FALSE; + + /** * The entity type bundle info service. * * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface @@ -44,6 +52,13 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface protected $time; /** + * The widget plugin manager. + * + * @var \Drupal\Component\Plugin\PluginManagerInterface + */ + protected $widgetPluginManager; + + /** * Constructs a ContentEntityForm object. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager @@ -52,12 +67,15 @@ class ContentEntityForm extends EntityForm implements ContentEntityFormInterface * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Component\Plugin\PluginManagerInterface $widget_plugin_manager + * The widget plugin manager. */ - public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { + public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, PluginManagerInterface $widget_plugin_manager = NULL) { $this->entityManager = $entity_manager; $this->entityTypeBundleInfo = $entity_type_bundle_info ?: \Drupal::service('entity_type.bundle.info'); $this->time = $time ?: \Drupal::service('datetime.time'); + $this->widgetPluginManager = $widget_plugin_manager ?: \Drupal::service('plugin.manager.field.widget'); } /** @@ -67,7 +85,8 @@ public static function create(ContainerInterface $container) { return new static( $container->get('entity.manager'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('plugin.manager.field.widget') ); } @@ -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; } @@ -450,4 +480,19 @@ protected function showRevisionUi() { return $this->entity->getEntityType()->showRevisionUi(); } + /** + * {@inheritdoc} + */ + public function isEntityDeepSerializationRequired() { + return $this->entityDeepSerializationRequired; + } + + /** + * {@inheritdoc} + */ + public function __sleep() { + $this->entity->setDeepSerialization($this->entityDeepSerializationRequired); + return parent::__sleep(); + } + } diff --git a/core/lib/Drupal/Core/Entity/ContentEntityFormInterface.php b/core/lib/Drupal/Core/Entity/ContentEntityFormInterface.php index 9688b1f..9aabfdd 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityFormInterface.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityFormInterface.php @@ -75,4 +75,12 @@ public function isDefaultFormLangcode(FormStateInterface $form_state); */ public function validateForm(array &$form, FormStateInterface $form_state); + /** + * Returns the current estimation if entity deep serialization is required. + * + * @return bool + * TRUE if deep serialization is reqired, FALSE otherwise. + */ + public function isEntityDeepSerializationRequired(); + } diff --git a/core/lib/Drupal/Core/Form/FormCache.php b/core/lib/Drupal/Core/Form/FormCache.php index 13e5430..09e3df3 100644 --- a/core/lib/Drupal/Core/Form/FormCache.php +++ b/core/lib/Drupal/Core/Form/FormCache.php @@ -183,6 +183,22 @@ public function setCache($form_build_id, $form, FormStateInterface $form_state) return; } + // Cache the form state. We have to first cache the form state as + // serializing it will lead to serializing the contained form object, which + // might make changes to the contained entity object such as flagging it + // for deep serialization in the sleep method of the form object, but if we + // first serialize the form array then the entity contained within it will + // be serialized without the logic from the sleep method of the form object + // has been executed and therefore deep serialization of the entity + // contained in the form object will not be possible anymore as the sleep + // method of the entity will have been called already without first + // flagging the entity for deep serialization. + // @see \Drupal\Core\Entity\ContentEntityForm::__sleep(). + // @see \Drupal\Core\Entity\ContentEntityBase::__sleep(). + if ($data = $form_state->getCacheableArray()) { + $this->keyValueExpirableFactory->get('form_state')->setWithExpire($form_build_id, $data, $expire); + } + // Cache form structure. if (isset($form)) { if ($this->currentUser->isAuthenticated()) { @@ -191,10 +207,6 @@ public function setCache($form_build_id, $form, FormStateInterface $form_state) unset($form['#build_id_old']); $this->keyValueExpirableFactory->get('form')->setWithExpire($form_build_id, $form, $expire); } - - if ($data = $form_state->getCacheableArray()) { - $this->keyValueExpirableFactory->get('form_state')->setWithExpire($form_build_id, $data, $expire); - } } /** diff --git a/core/modules/book/src/Form/BookOutlineForm.php b/core/modules/book/src/Form/BookOutlineForm.php index 8b4e364..7b73bf7 100644 --- a/core/modules/book/src/Form/BookOutlineForm.php +++ b/core/modules/book/src/Form/BookOutlineForm.php @@ -4,6 +4,7 @@ use Drupal\book\BookManagerInterface; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; @@ -41,9 +42,11 @@ class BookOutlineForm extends ContentEntityForm { * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Component\Plugin\PluginManagerInterface $widget_plugin_manager + * The widget plugin manager. */ - public function __construct(EntityManagerInterface $entity_manager, BookManagerInterface $book_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { - parent::__construct($entity_manager, $entity_type_bundle_info, $time); + public function __construct(EntityManagerInterface $entity_manager, BookManagerInterface $book_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, PluginManagerInterface $widget_plugin_manager = NULL) { + parent::__construct($entity_manager, $entity_type_bundle_info, $time, $widget_plugin_manager); $this->bookManager = $book_manager; } @@ -55,7 +58,8 @@ public static function create(ContainerInterface $container) { $container->get('entity.manager'), $container->get('book.manager'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('plugin.manager.field.widget') ); } diff --git a/core/modules/comment/src/CommentForm.php b/core/modules/comment/src/CommentForm.php index 3a2e704..f891262 100644 --- a/core/modules/comment/src/CommentForm.php +++ b/core/modules/comment/src/CommentForm.php @@ -4,6 +4,7 @@ use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Unicode; use Drupal\Core\Datetime\DrupalDateTime; @@ -44,7 +45,8 @@ public static function create(ContainerInterface $container) { $container->get('current_user'), $container->get('renderer'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('plugin.manager.field.widget') ); } @@ -61,9 +63,11 @@ public static function create(ContainerInterface $container) { * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Component\Plugin\PluginManagerInterface $widget_plugin_manager + * The widget plugin manager. */ - public function __construct(EntityManagerInterface $entity_manager, AccountInterface $current_user, RendererInterface $renderer, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { - parent::__construct($entity_manager, $entity_type_bundle_info, $time); + public function __construct(EntityManagerInterface $entity_manager, AccountInterface $current_user, RendererInterface $renderer, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, PluginManagerInterface $widget_plugin_manager = NULL) { + parent::__construct($entity_manager, $entity_type_bundle_info, $time, $widget_plugin_manager); $this->currentUser = $current_user; $this->renderer = $renderer; } diff --git a/core/modules/contact/src/MessageForm.php b/core/modules/contact/src/MessageForm.php index da221ff..3372560 100644 --- a/core/modules/contact/src/MessageForm.php +++ b/core/modules/contact/src/MessageForm.php @@ -3,6 +3,7 @@ namespace Drupal\contact; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Datetime\DateFormatterInterface; use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\EntityManagerInterface; @@ -69,9 +70,11 @@ class MessageForm extends ContentEntityForm { * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Component\Plugin\PluginManagerInterface $widget_plugin_manager + * The widget plugin manager. */ - public function __construct(EntityManagerInterface $entity_manager, FloodInterface $flood, LanguageManagerInterface $language_manager, MailHandlerInterface $mail_handler, DateFormatterInterface $date_formatter, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { - parent::__construct($entity_manager, $entity_type_bundle_info, $time); + public function __construct(EntityManagerInterface $entity_manager, FloodInterface $flood, LanguageManagerInterface $language_manager, MailHandlerInterface $mail_handler, DateFormatterInterface $date_formatter, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, PluginManagerInterface $widget_plugin_manager = NULL) { + parent::__construct($entity_manager, $entity_type_bundle_info, $time, $widget_plugin_manager); $this->flood = $flood; $this->languageManager = $language_manager; $this->mailHandler = $mail_handler; @@ -89,7 +92,8 @@ public static function create(ContainerInterface $container) { $container->get('contact.mail_handler'), $container->get('date.formatter'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('plugin.manager.field.widget') ); } diff --git a/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php b/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php index 8a708ce..2b6ee45 100644 --- a/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php +++ b/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php @@ -3,6 +3,7 @@ namespace Drupal\menu_link_content\Form; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; @@ -53,9 +54,11 @@ class MenuLinkContentForm extends ContentEntityForm { * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Component\Plugin\PluginManagerInterface $widget_plugin_manager + * The widget plugin manager. */ - public function __construct(EntityManagerInterface $entity_manager, MenuParentFormSelectorInterface $menu_parent_selector, LanguageManagerInterface $language_manager, PathValidatorInterface $path_validator, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { - parent::__construct($entity_manager, $entity_type_bundle_info, $time); + public function __construct(EntityManagerInterface $entity_manager, MenuParentFormSelectorInterface $menu_parent_selector, LanguageManagerInterface $language_manager, PathValidatorInterface $path_validator, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, PluginManagerInterface $widget_plugin_manager = NULL) { + parent::__construct($entity_manager, $entity_type_bundle_info, $time, $widget_plugin_manager); $this->menuParentSelector = $menu_parent_selector; $this->pathValidator = $path_validator; } @@ -70,7 +73,8 @@ public static function create(ContainerInterface $container) { $container->get('language_manager'), $container->get('path.validator'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('plugin.manager.field.widget') ); } diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/NodeForm.php index bb58377..914bfdd 100644 --- a/core/modules/node/src/NodeForm.php +++ b/core/modules/node/src/NodeForm.php @@ -3,6 +3,7 @@ namespace Drupal\node; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; @@ -33,9 +34,11 @@ class NodeForm extends ContentEntityForm { * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Component\Plugin\PluginManagerInterface $widget_plugin_manager + * The widget plugin manager. */ - public function __construct(EntityManagerInterface $entity_manager, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { - parent::__construct($entity_manager, $entity_type_bundle_info, $time); + public function __construct(EntityManagerInterface $entity_manager, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, PluginManagerInterface $widget_plugin_manager = NULL) { + parent::__construct($entity_manager, $entity_type_bundle_info, $time, $widget_plugin_manager); $this->tempStoreFactory = $temp_store_factory; } @@ -47,7 +50,8 @@ public static function create(ContainerInterface $container) { $container->get('entity.manager'), $container->get('user.private_tempstore'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('plugin.manager.field.widget') ); } diff --git a/core/modules/user/src/AccountForm.php b/core/modules/user/src/AccountForm.php index 5f4d820..a5b6a04 100644 --- a/core/modules/user/src/AccountForm.php +++ b/core/modules/user/src/AccountForm.php @@ -3,6 +3,7 @@ namespace Drupal\user; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Component\Utility\Crypt; use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\EntityConstraintViolationListInterface; @@ -39,9 +40,11 @@ * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Component\Plugin\PluginManagerInterface $widget_plugin_manager + * The widget plugin manager. */ - public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { - parent::__construct($entity_manager, $entity_type_bundle_info, $time); + public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, PluginManagerInterface $widget_plugin_manager = NULL) { + parent::__construct($entity_manager, $entity_type_bundle_info, $time, $widget_plugin_manager); $this->languageManager = $language_manager; } @@ -53,7 +56,8 @@ public static function create(ContainerInterface $container) { $container->get('entity.manager'), $container->get('language_manager'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('plugin.manager.field.widget') ); }