function EntityDefinitionUpdateProviderTest::testBaseFieldDeleteWithExistingData

Same name and namespace in other branches
  1. 11.x core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateProviderTest.php \Drupal\KernelTests\Core\Entity\EntityDefinitionUpdateProviderTest::testBaseFieldDeleteWithExistingData()

Tests deleting a base field when it has existing data.

@dataProvider baseFieldDeleteWithExistingDataTestCases

File

core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateProviderTest.php, line 70

Class

EntityDefinitionUpdateProviderTest
Tests EntityDefinitionUpdateManager functionality.

Namespace

Drupal\KernelTests\Core\Entity

Code

public function testBaseFieldDeleteWithExistingData($entity_type_id, $create_entity_revision, $base_field_revisionable, $create_entity_translation) : void {
  // 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.');
  }
}

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