function SqlContentEntityStorageSchema::onFieldStorageDefinitionDelete

Same name in other branches
  1. 9 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onFieldStorageDefinitionDelete()
  2. 8.9.x core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onFieldStorageDefinitionDelete()
  3. 11.x core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onFieldStorageDefinitionDelete()

File

core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php, line 709

Class

SqlContentEntityStorageSchema
Defines a schema handler that supports revisionable, translatable entities.

Namespace

Drupal\Core\Entity\Sql

Code

public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $storage_definition) {
    // If the field storage does not have any data, we can safely delete its
    // schema.
    if (!$this->storage
        ->countFieldData($storage_definition, TRUE)) {
        $this->performFieldSchemaOperation('delete', $storage_definition);
        return;
    }
    // There's nothing else we can do if the field storage has a custom storage.
    if ($storage_definition->hasCustomStorage()) {
        return;
    }
    $table_mapping = $this->getTableMapping($this->entityType, [
        $storage_definition,
    ]);
    $field_table_name = $table_mapping->getFieldTableName($storage_definition->getName());
    if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) {
        // Move the table to a unique name while the table contents are being
        // deleted.
        $table = $table_mapping->getDedicatedDataTableName($storage_definition);
        $new_table = $table_mapping->getDedicatedDataTableName($storage_definition, TRUE);
        $this->database
            ->schema()
            ->renameTable($table, $new_table);
        if ($this->entityType
            ->isRevisionable()) {
            $revision_table = $table_mapping->getDedicatedRevisionTableName($storage_definition);
            $revision_new_table = $table_mapping->getDedicatedRevisionTableName($storage_definition, TRUE);
            $this->database
                ->schema()
                ->renameTable($revision_table, $revision_new_table);
        }
    }
    else {
        // Move the field data from the shared table to a dedicated one in order
        // to allow it to be purged like any other field.
        $shared_table_field_columns = $table_mapping->getColumnNames($storage_definition->getName());
        // Refresh the table mapping to use the deleted storage definition.
        $deleted_storage_definition = $this->deletedFieldsRepository()
            ->getFieldStorageDefinitions()[$storage_definition->getUniqueStorageIdentifier()];
        $table_mapping = $this->getTableMapping($this->entityType, [
            $deleted_storage_definition,
        ]);
        $dedicated_table_field_schema = $this->getDedicatedTableSchema($deleted_storage_definition);
        $dedicated_table_field_columns = $table_mapping->getColumnNames($deleted_storage_definition->getName());
        $dedicated_table_name = $table_mapping->getDedicatedDataTableName($deleted_storage_definition, TRUE);
        $dedicated_table_name_mapping[$table_mapping->getDedicatedDataTableName($deleted_storage_definition)] = $dedicated_table_name;
        if ($this->entityType
            ->isRevisionable()) {
            $dedicated_revision_table_name = $table_mapping->getDedicatedRevisionTableName($deleted_storage_definition, TRUE);
            $dedicated_table_name_mapping[$table_mapping->getDedicatedRevisionTableName($deleted_storage_definition)] = $dedicated_revision_table_name;
        }
        // Create the dedicated field tables using "deleted" table names.
        foreach ($dedicated_table_field_schema as $name => $table) {
            if (!$this->database
                ->schema()
                ->tableExists($dedicated_table_name_mapping[$name])) {
                $this->database
                    ->schema()
                    ->createTable($dedicated_table_name_mapping[$name], $table);
            }
            else {
                throw new EntityStorageException('The field ' . $storage_definition->getName() . ' has already been deleted and it is in the process of being purged.');
            }
        }
        try {
            if ($this->database
                ->supportsTransactionalDDL()) {
                // If the database supports transactional DDL, we can go ahead and rely
                // on it. If not, we will have to rollback manually if something fails.
                $transaction = $this->database
                    ->startTransaction();
            }
            // Copy the data from the base table.
            $this->database
                ->insert($dedicated_table_name)
                ->from($this->getSelectQueryForFieldStorageDeletion($field_table_name, $shared_table_field_columns, $dedicated_table_field_columns))
                ->execute();
            // Copy the data from the revision table.
            if (isset($dedicated_revision_table_name)) {
                if ($this->entityType
                    ->isTranslatable()) {
                    $revision_table = $storage_definition->isRevisionable() ? $this->storage
                        ->getRevisionDataTable() : $this->storage
                        ->getDataTable();
                }
                else {
                    $revision_table = $storage_definition->isRevisionable() ? $this->storage
                        ->getRevisionTable() : $this->storage
                        ->getBaseTable();
                }
                $this->database
                    ->insert($dedicated_revision_table_name)
                    ->from($this->getSelectQueryForFieldStorageDeletion($revision_table, $shared_table_field_columns, $dedicated_table_field_columns, $field_table_name))
                    ->execute();
            }
        } catch (\Exception $e) {
            if ($this->database
                ->supportsTransactionalDDL()) {
                if (isset($transaction)) {
                    $transaction->rollBack();
                }
            }
            else {
                // Delete the dedicated tables.
                foreach ($dedicated_table_field_schema as $name => $table) {
                    $this->database
                        ->schema()
                        ->dropTable($dedicated_table_name_mapping[$name]);
                }
            }
            throw $e;
        }
        // Delete the field from the shared tables.
        $this->deleteSharedTableSchema($storage_definition);
    }
    unset($this->fieldStorageDefinitions[$storage_definition->getName()]);
}

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