You are here

public function EntityDefinitionUpdateTest::testBaseFieldDeleteWithExistingData in Drupal 9

Same name and namespace in other branches
  1. 8 core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php \Drupal\KernelTests\Core\Entity\EntityDefinitionUpdateTest::testBaseFieldDeleteWithExistingData()
  2. 10 core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php \Drupal\KernelTests\Core\Entity\EntityDefinitionUpdateTest::testBaseFieldDeleteWithExistingData()

Tests deleting a base field when it has existing data.

@dataProvider baseFieldDeleteWithExistingDataTestCases

File

core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php, line 499

Class

EntityDefinitionUpdateTest
Tests EntityDefinitionUpdateManager functionality.

Namespace

Drupal\KernelTests\Core\Entity

Code

public function testBaseFieldDeleteWithExistingData($entity_type_id, $create_entity_revision, $base_field_revisionable, $create_entity_translation) {

  // Enable an additional language.
  ConfigurableLanguage::createFromLangcode('ro')
    ->save();

  /** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */
  $storage = $this->entityTypeManager
    ->getStorage($entity_type_id);
  $schema_handler = $this->database
    ->schema();

  // Create an entity without the base field, to ensure NULL values are not
  // added to the dedicated table storage to be purged.

  /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
  $entity = $storage
    ->create();
  $entity
    ->save();

  // Add the base field and run the update.
  $this
    ->addBaseField('string', $entity_type_id, $base_field_revisionable, TRUE, $create_entity_translation);
  $this
    ->applyEntityUpdates();

  /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
  $table_mapping = $storage
    ->getTableMapping();
  $storage_definition = \Drupal::service('entity.last_installed_schema.repository')
    ->getLastInstalledFieldStorageDefinitions($entity_type_id)['new_base_field'];

  // Save an entity with the base field populated.
  $entity = $storage
    ->create([
    'new_base_field' => 'foo',
  ]);
  $entity
    ->save();
  if ($create_entity_translation) {
    $translation = $entity
      ->addTranslation('ro', [
      'new_base_field' => 'foo-ro',
    ]);
    $translation
      ->save();
  }
  if ($create_entity_revision) {
    $entity
      ->setNewRevision(TRUE);
    $entity
      ->isDefaultRevision(FALSE);
    $entity->new_base_field = 'bar';
    $entity
      ->save();
    if ($create_entity_translation) {
      $translation = $entity
        ->getTranslation('ro');
      $translation->new_base_field = 'bar-ro';
      $translation
        ->save();
    }
  }

  // Remove the base field and apply updates.
  $this
    ->removeBaseField($entity_type_id);
  $this
    ->applyEntityUpdates();

  // Check that the base field's column is deleted.
  $this
    ->assertFalse($schema_handler
    ->fieldExists($entity_type_id, 'new_base_field'), 'Column deleted from shared table for new_base_field.');

  // Check that a dedicated 'deleted' table was created for the deleted base
  // field.
  $dedicated_deleted_table_name = $table_mapping
    ->getDedicatedDataTableName($storage_definition, TRUE);
  $this
    ->assertTrue($schema_handler
    ->tableExists($dedicated_deleted_table_name), 'A dedicated table was created for the deleted new_base_field.');
  $expected[] = [
    'bundle' => $entity
      ->bundle(),
    'deleted' => '1',
    'entity_id' => '2',
    'revision_id' => '2',
    'langcode' => 'en',
    'delta' => '0',
    'new_base_field_value' => 'foo',
  ];
  if ($create_entity_translation) {
    $expected[] = [
      'bundle' => $entity
        ->bundle(),
      'deleted' => '1',
      'entity_id' => '2',
      'revision_id' => '2',
      'langcode' => 'ro',
      'delta' => '0',
      'new_base_field_value' => 'foo-ro',
    ];
  }

  // Check that the deleted field's data is preserved in the dedicated
  // 'deleted' table.
  $result = $this->database
    ->select($dedicated_deleted_table_name, 't')
    ->fields('t')
    ->orderBy('revision_id', 'ASC')
    ->orderBy('langcode', 'ASC')
    ->execute()
    ->fetchAll(\PDO::FETCH_ASSOC);
  $this
    ->assertSameSize($expected, $result);

  // Use assertEquals and not assertSame here to prevent that a different
  // sequence of the columns in the table will affect the check.
  $this
    ->assertEquals($expected, $result);
  if ($create_entity_revision) {
    $dedicated_deleted_revision_table_name = $table_mapping
      ->getDedicatedRevisionTableName($storage_definition, TRUE);
    $this
      ->assertTrue($schema_handler
      ->tableExists($dedicated_deleted_revision_table_name), 'A dedicated revision table was created for the deleted new_base_field.');
    if ($base_field_revisionable) {
      $expected[] = [
        'bundle' => $entity
          ->bundle(),
        'deleted' => '1',
        'entity_id' => '2',
        'revision_id' => '3',
        'langcode' => 'en',
        'delta' => '0',
        'new_base_field_value' => 'bar',
      ];
      if ($create_entity_translation) {
        $expected[] = [
          'bundle' => $entity
            ->bundle(),
          'deleted' => '1',
          'entity_id' => '2',
          'revision_id' => '3',
          'langcode' => 'ro',
          'delta' => '0',
          'new_base_field_value' => 'bar-ro',
        ];
      }
    }
    $result = $this->database
      ->select($dedicated_deleted_revision_table_name, 't')
      ->fields('t')
      ->orderBy('revision_id', 'ASC')
      ->orderBy('langcode', 'ASC')
      ->execute()
      ->fetchAll(\PDO::FETCH_ASSOC);
    $this
      ->assertSameSize($expected, $result);

    // Use assertEquals and not assertSame here to prevent that a different
    // sequence of the columns in the table will affect the check.
    $this
      ->assertEquals($expected, $result);
  }

  // Check that the field storage definition is marked for purging.
  $deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')
    ->getFieldStorageDefinitions();
  $this
    ->assertArrayHasKey($storage_definition
    ->getUniqueStorageIdentifier(), $deleted_storage_definitions, 'The base field is marked for purging.');

  // Purge field data, and check that the storage definition has been
  // completely removed once the data is purged.
  field_purge_batch(10);
  $deleted_storage_definitions = \Drupal::service('entity_field.deleted_fields_repository')
    ->getFieldStorageDefinitions();
  $this
    ->assertEmpty($deleted_storage_definitions, 'The base field has been deleted.');
  $this
    ->assertFalse($schema_handler
    ->tableExists($dedicated_deleted_table_name), 'A dedicated field table was deleted after new_base_field was purged.');
  if (isset($dedicated_deleted_revision_table_name)) {
    $this
      ->assertFalse($schema_handler
      ->tableExists($dedicated_deleted_revision_table_name), 'A dedicated field revision table was deleted after new_base_field was purged.');
  }
}