function ContentEntityCloneTest::testEntityPropertiesModifications

Same name in other branches
  1. 9 core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCloneTest.php \Drupal\KernelTests\Core\Entity\ContentEntityCloneTest::testEntityPropertiesModifications()
  2. 8.9.x core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCloneTest.php \Drupal\KernelTests\Core\Entity\ContentEntityCloneTest::testEntityPropertiesModifications()
  3. 11.x core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCloneTest.php \Drupal\KernelTests\Core\Entity\ContentEntityCloneTest::testEntityPropertiesModifications()

Tests references of entity properties after entity cloning.

File

core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCloneTest.php, line 282

Class

ContentEntityCloneTest
Tests proper cloning of content entities.

Namespace

Drupal\KernelTests\Core\Entity

Code

public function testEntityPropertiesModifications() : void {
    // Create a test entity with a translation, which will internally trigger
    // entity cloning for the new translation and create references for some of
    // the entity properties.
    $entity = EntityTestMulRev::create([
        'name' => 'original',
        'language' => 'en',
    ]);
    $translation = $entity->addTranslation('de');
    $entity->save();
    // Clone the entity.
    $clone = clone $entity;
    // Retrieve the entity properties.
    $reflection = new \ReflectionClass($entity);
    $properties = $reflection->getProperties(~\ReflectionProperty::IS_STATIC);
    $translation_unique_properties = [
        'activeLangcode',
        'translationInitialize',
        'fieldDefinitions',
        'languages',
        'langcodeKey',
        'defaultLangcode',
        'defaultLangcodeKey',
        'revisionTranslationAffectedKey',
        'validated',
        'validationRequired',
        'entityTypeId',
        'typedData',
        'cacheContexts',
        'cacheTags',
        'cacheMaxAge',
        '_serviceIds',
        '_entityStorages',
        'enforceDefaultTranslation',
    ];
    foreach ($properties as $property) {
        $property_name = $property->getName();
        // Only modify properties that will accept strings as default values.
        if ($property->hasType()) {
            if ($property->getType()
                ->getName() !== 'string') {
                continue;
            }
        }
        // Modify each entity property on the clone and assert that the change is
        // not propagated to the original entity.
        $property->setValue($entity, 'default-value');
        $property->setValue($translation, 'default-value');
        $property->setValue($clone, 'test-entity-cloning');
        // Static properties remain the same across all instances of the class.
        if ($property->isStatic()) {
            $this->assertEquals('test-entity-cloning', $property->getValue($entity), "Entity property {$property_name} is not cloned properly.");
            $this->assertEquals('test-entity-cloning', $property->getValue($translation), "Entity property {$property_name} is not cloned properly.");
            $this->assertEquals('test-entity-cloning', $property->getValue($clone), "Entity property {$property_name} is not cloned properly.");
        }
        else {
            $this->assertEquals('default-value', $property->getValue($entity), "Entity property {$property_name} is not cloned properly.");
            $this->assertEquals('default-value', $property->getValue($translation), "Entity property {$property_name} is not cloned properly.");
            $this->assertEquals('test-entity-cloning', $property->getValue($clone), "Entity property {$property_name} is not cloned properly.");
        }
        // Modify each entity property on the translation entity object and assert
        // that the change is propagated to the default translation entity object
        // except for the properties that are unique for each entity translation
        // object.
        $property->setValue($translation, 'test-translation-cloning');
        // Using assertEquals or assertNotEquals here is dangerous as if the
        // assertion fails and the property for some reasons contains the entity
        // object e.g. the "typedData" property then the property will be
        // serialized, but this will cause exceptions because the entity is
        // modified in a non-consistent way and ContentEntityBase::__sleep() will
        // not be able to properly access all properties and this will cause
        // exceptions without a proper backtrace.
        if (in_array($property->getName(), $translation_unique_properties)) {
            $this->assertEquals('default-value', $property->getValue($entity), "Entity property {$property_name} is not cloned properly.");
            $this->assertEquals('test-translation-cloning', $property->getValue($translation), "Entity property {$property_name} is not cloned properly.");
        }
        else {
            $this->assertEquals('test-translation-cloning', $property->getValue($entity), "Entity property {$property_name} is not cloned properly.");
            $this->assertEquals('test-translation-cloning', $property->getValue($translation), "Entity property {$property_name} is not cloned properly.");
        }
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.