diff --git a/core/tests/Drupal/KernelTests/Core/Entity/ContentEntitySerializationTest.php b/core/tests/Drupal/KernelTests/Core/Entity/ContentEntitySerializationTest.php index f40d4ed..07dad80 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/ContentEntitySerializationTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/ContentEntitySerializationTest.php @@ -141,4 +141,67 @@ protected function doTestSerialization($deep_serialization) { $this->assertEquals($deep_serialization ? 'test deep serialization on language property' : $original_language_name, $language->getName()); } + /** + * Tests deep serialization with circular entity references. + */ + public function testDeepSerializationWithCircularEntityReferences() { + $field_name = $this->entityReferenceFieldName; + $user = $this->createUser(); + + // Case 1: new_entity->existing_entity->parent_new_entity + /** @var \Drupal\entity_test\Entity\EntityTestMul $entity_level_zero */ + $entity_level_zero = $this->entityStorage->create([ + 'name' => 'entity zero', + 'user_id' => $user->id(), + 'language' => 'en', + ]); + $entity_level_zero->save(); + $entity_level_one = $entity_level_zero->createDuplicate(); + $entity_level_one->setName('entity one'); + $entity_level_one->save(); + + // Case 1: + // Create a circular reference, where the parent entity is referenced at the + // end of the chain back again with a different object reference than the + // one at the beginning of the chain. + $entity_level_zero->$field_name->appendItem($entity_level_one); + // Ensure that the main entity has different object references by cloning + // it, otherwise PHP will not serialize the same object twice. + $entity_level_zero_clone = clone $entity_level_zero; + $this->assertNotSame($entity_level_zero, $entity_level_zero_clone); + $entity_level_one->$field_name->appendItem($entity_level_zero_clone); + + // Make sure all the entities are initialized in the structure, otherwise + // they will not be contained in the serialization. + $entity_level_zero->$field_name->entity->$field_name->entity; + + // Now serialize the entity structure through deep serialization. + $entity_level_zero->setDeepSerialization(TRUE); + $serialized_main_entity = serialize($entity_level_zero); + $this->assertEquals(2, substr_count($serialized_main_entity, 'entity zero')); + $this->assertEquals(1, substr_count($serialized_main_entity, 'entity one')); + + + // Case 2: + // Reset the entities for the next test. + $entity_level_zero = $this->entityStorage->loadUnchanged($entity_level_zero->id()); + $entity_level_one = $this->entityStorage->loadUnchanged($entity_level_one->id()); + + // Create a circular reference, where the parent entity is referenced at the + // end of the chain back again with the same object reference as at the + // beginning of the chain. + $entity_level_zero->$field_name->appendItem($entity_level_one); + $entity_level_one->$field_name->appendItem($entity_level_zero); + + // Make sure all the entities are initialized in the structure, otherwise + // they will not be contained in the serialization. + $entity_level_zero->$field_name->entity->$field_name->entity; + + // Now serialize the entity structure through deep serialization. + $entity_level_zero->setDeepSerialization(TRUE); + $serialized_main_entity = serialize($entity_level_zero); + $this->assertEquals(2, substr_count($serialized_main_entity, 'entity zero')); + $this->assertEquals(2, substr_count($serialized_main_entity, 'entity one')); + } + }