function EntityDefinitionUpdateTest::testBaseFieldDeleteWithExistingData

Same name in other branches
  1. 9 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 506

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->assertCount(count($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->assertCount(count($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.