You are here

public function EntitySchemaTest::testPrimaryKeyUpdate in Drupal 8

Same name and namespace in other branches
  1. 9 core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php \Drupal\KernelTests\Core\Entity\EntitySchemaTest::testPrimaryKeyUpdate()

Tests deleting and creating a field that is part of a primary key.

@dataProvider providerTestPrimaryKeyUpdate

Parameters

string $entity_type_id: The ID of the entity type whose schema is being tested.

string $field_name: The name of the field that is being re-installed.

File

core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php, line 132

Class

EntitySchemaTest
Tests the default entity storage schema handler.

Namespace

Drupal\KernelTests\Core\Entity

Code

public function testPrimaryKeyUpdate($entity_type_id, $field_name) {

  // EntityKernelTestBase::setUp() already installs the schema for the
  // 'entity_test' entity type.
  if ($entity_type_id !== 'entity_test') {
    $this
      ->installEntitySchema($entity_type_id);
  }

  /* @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $update_manager */
  $update_manager = $this->container
    ->get('entity.definition_update_manager');
  $entity_type = $update_manager
    ->getEntityType($entity_type_id);

  /* @see \Drupal\Core\Entity\ContentEntityBase::baseFieldDefinitions() */
  switch ($field_name) {
    case 'id':
      $field = BaseFieldDefinition::create('integer')
        ->setLabel('ID')
        ->setReadOnly(TRUE)
        ->setSetting('unsigned', TRUE);
      break;
    case 'revision_id':
      $field = BaseFieldDefinition::create('integer')
        ->setLabel('Revision ID')
        ->setReadOnly(TRUE)
        ->setSetting('unsigned', TRUE);
      break;
    case 'langcode':
      $field = BaseFieldDefinition::create('language')
        ->setLabel('Language');
      if ($entity_type
        ->isRevisionable()) {
        $field
          ->setRevisionable(TRUE);
      }
      if ($entity_type
        ->isTranslatable()) {
        $field
          ->setTranslatable(TRUE);
      }
      break;
  }
  $field
    ->setName($field_name)
    ->setTargetEntityTypeId($entity_type_id)
    ->setProvider($entity_type
    ->getProvider());

  // Build up a map of expected primary keys depending on the entity type
  // configuration.
  $id_key = $entity_type
    ->getKey('id');
  $revision_key = $entity_type
    ->getKey('revision');
  $langcode_key = $entity_type
    ->getKey('langcode');
  $expected = [];
  $expected[$entity_type
    ->getBaseTable()] = [
    $id_key,
  ];
  if ($entity_type
    ->isRevisionable()) {
    $expected[$entity_type
      ->getRevisionTable()] = [
      $revision_key,
    ];
  }
  if ($entity_type
    ->isTranslatable()) {
    $expected[$entity_type
      ->getDataTable()] = [
      $id_key,
      $langcode_key,
    ];
  }
  if ($entity_type
    ->isRevisionable() && $entity_type
    ->isTranslatable()) {
    $expected[$entity_type
      ->getRevisionDataTable()] = [
      $revision_key,
      $langcode_key,
    ];
  }

  // First, test explicitly deleting and re-installing a field. Make sure that
  // all primary keys are there to start with.
  $this
    ->assertSame($expected, $this
    ->findPrimaryKeys($entity_type));

  // Then uninstall the field and make sure all primary keys that the field
  // was part of have been updated. Since this is not a valid state of the
  // entity type (for example a revisionable entity type without a revision ID
  // field or a translatable entity type without a language code field) the
  // actual primary keys at this point are irrelevant.
  $update_manager
    ->uninstallFieldStorageDefinition($field);
  $this
    ->assertNotEquals($expected, $this
    ->findPrimaryKeys($entity_type));

  // Finally, reinstall the field and make sure the primary keys have been
  // recreated.
  $update_manager
    ->installFieldStorageDefinition($field
    ->getName(), $entity_type_id, $field
    ->getProvider(), $field);
  $this
    ->assertSame($expected, $this
    ->findPrimaryKeys($entity_type));

  // Now test updating a field without data. This will end up deleting
  // and re-creating the field, similar to the code above.
  $update_manager
    ->updateFieldStorageDefinition($field);
  $this
    ->assertSame($expected, $this
    ->findPrimaryKeys($entity_type));

  // Now test updating a field with data.

  /* @var \Drupal\Core\Entity\FieldableEntityStorageInterface $storage */
  $storage = $this->entityTypeManager
    ->getStorage($entity_type_id);

  // The schema of ID fields is incorrectly recreated as 'int' instead of
  // 'serial', so we manually have to specify an ID.
  // @todo Remove this in https://www.drupal.org/project/drupal/issues/2928906
  $storage
    ->create([
    'id' => 1,
    'revision_id' => 1,
  ])
    ->save();
  $this
    ->assertTrue($storage
    ->countFieldData($field, TRUE));
  $update_manager
    ->updateFieldStorageDefinition($field);
  $this
    ->assertSame($expected, $this
    ->findPrimaryKeys($entity_type));
  $this
    ->assertTrue($storage
    ->countFieldData($field, TRUE));
}