diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index 1d69be2..4770eae 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -149,6 +149,13 @@ protected $validationRequired = FALSE; /** + * Whether to serialize the initialized fields when serializing the entity. + * + * @var bool + */ + public $serializeFields = FALSE; + + /** * {@inheritdoc} */ public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = array()) { @@ -416,7 +423,8 @@ public function __sleep() { $this->values[$name][$langcode] = $field->getValue(); } } - $this->fields = array(); + // Serialize initialized fields only if requested so. + $this->fields = $this->serializeFields ? $this->fields : []; $this->fieldDefinitions = NULL; $this->languages = NULL; $this->clearTranslationCache(); @@ -427,6 +435,14 @@ public function __sleep() { /** * {@inheritdoc} */ + public function __wakeup() { + $this->serializeFields = FALSE; + parent::__wakeup(); + } + + /** + * {@inheritdoc} + */ public function id() { return $this->getEntityKey('id'); } diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php index 63bd90d..d31f79a 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php @@ -664,4 +664,16 @@ public static function getPreconfiguredOptions() { return $options; } + /** + * {@inheritdoc} + */ + public function __sleep() { + // If the parent entity is serializing the initialized fields so have to do + // the referenced entity as well. + if ($this->getEntity()->serializeFields && isset($this->entity)) { + $this->entity->serializeFields = TRUE; + } + return parent::__sleep(); + } + } diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntitySerializationTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntitySerializationTest.php new file mode 100644 index 0000000..7711b57 --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntitySerializationTest.php @@ -0,0 +1,185 @@ +installEntitySchema('entity_test_rev'); + + // Create the entity reference fields. + $this->createEntityReferenceField( + $this->entityType, + $this->bundle, + $this->fieldName, + 'Field test', + $this->referencedEntityType, + 'default', + array('target_bundles' => array($this->bundle)), + FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED + ); + + $this->createEntityReferenceField( + $this->referencedEntityType, + $this->bundle, + $this->fieldName, + 'Field test', + $this->referencedEntityType, + 'default', + array('target_bundles' => array($this->bundle)), + FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED + ); + + } + + /** + * Tests the regular entity serialization. + */ + public function testEntitySerialization() { + $entity = $this->container->get('entity_type.manager') + ->getStorage($this->entityType) + ->create(['type' => $this->bundle, 'name' => 'test entity']); + + $serialized_entity = serialize($entity); + $entity = unserialize($serialized_entity); + + $this->assertEquals('test entity', $entity->label()); + } + + /** + * Tests the regular entity serialization with references. + */ + public function testRegularEntitySerializationWithEntityReferences() { + $entity = $this->createEntity(); + + // Assert that the regular serialization will not serialize references. + $original_label = $entity->{$this->fieldName}->entity->label(); + $entity->{$this->fieldName}->entity->name = 'test referenced entity changed'; + $serialized_entity = serialize($entity); + $entity = unserialize($serialized_entity); + $this->assertEquals($original_label, $entity->{$this->fieldName}->entity->label()); + } + + /** + * Tests entity serialization with flag for serializing references. + */ + public function testEntitySerializationWithSerializingEntityReferences() { + $entity = $this->createEntity(); + + // Assert that using the "serializeFields" flag the serialization will + // serialize references. + $original_label = $entity->{$this->fieldName}->entity->label(); + $new_label = 'test referenced entity changed'; + $this->assertNotEquals($original_label, $new_label); + + $entity->{$this->fieldName}->entity->name = $new_label; + $entity->serializeFields = TRUE; + $serialized_entity = serialize($entity); + $entity = unserialize($serialized_entity); + $this->assertEquals($new_label, $entity->{$this->fieldName}->entity->label()); + // Assert that after unserializing the entity the "serializeFields" flag is + // reset. + $this->assertTrue(empty($entity->serializeFields)); + $this->assertTrue(empty($entity->{$this->fieldName}->entity->serializeFields)); + } + + /** + * Tests entity serialization with flag for serializing references - complex. + */ + public function testEntitySerializationWithSerializingEntityReferencesDeeperStructure() { + $entity = $this->createEntity(); + + // Assert that using the "serializeFields" flag the serialization will + // serialize references on a deeper level as well. + $original_label_first_reference = $entity->{$this->fieldName}->entity->label(); + $new_label_first_reference = 'test referenced entity changed'; + $this->assertNotEquals($original_label_first_reference, $new_label_first_reference); + $original_label_second_reference = $entity->{$this->fieldName}->entity->{$this->fieldName}->entity->label(); + $new_label_second_reference = 'test referenced entity 2 changed'; + $this->assertNotEquals($original_label_second_reference, $new_label_second_reference); + + $entity->{$this->fieldName}->entity->name = $new_label_first_reference; + $entity->{$this->fieldName}->entity->{$this->fieldName}->entity->name = $new_label_second_reference; + $entity->serializeFields = TRUE; + $serialized_entity = serialize($entity); + $entity = unserialize($serialized_entity); + $this->assertEquals($new_label_first_reference, $entity->{$this->fieldName}->entity->label()); + $this->assertEquals($new_label_second_reference, $entity->{$this->fieldName}->entity->{$this->fieldName}->entity->label()); + // Assert that after unserializing the entity the "serializeFields" flag is + // reset. + $this->assertTrue(empty($entity->serializeFields)); + $this->assertTrue(empty($entity->{$this->fieldName}->entity->serializeFields)); + $this->assertTrue(empty($entity->{$this->fieldName}->entity->{$this->fieldName}->entity->serializeFields)); + } + + /** + * Creates and returns an entity with references. + * + * @return \Drupal\Core\Entity\EntityTypeInterface + * The entity object. + */ + protected function createEntity() { + $referenced_entity = $this->container->get('entity_type.manager') + ->getStorage($this->referencedEntityType) + ->create(['type' => $this->bundle, 'name' => 'test referenced entity']); + $referenced_entity->save(); + + $referenced_entity_2 = $this->container->get('entity_type.manager') + ->getStorage($this->referencedEntityType) + ->create(['type' => $this->bundle, 'name' => 'test referenced entity 2']); + $referenced_entity_2->save(); + + $entity = $this->container->get('entity_type.manager') + ->getStorage($this->entityType) + ->create(['type' => $this->bundle, 'name' => 'test entity']); + + $entity->{$this->fieldName}->entity = $referenced_entity; + $referenced_entity->{$this->fieldName}->entity = $referenced_entity_2; + + return $entity; + } + +}