function ContentEntityCloneTest::testEntityPropertiesModifications

Same name and namespace 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. 10 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) {
    // The original property is typed and can not be set to a string.
    if ($property->getName() === 'originalEntity') {
      continue;
    }
    $property_name = $property->getName();
    // 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.