You are here

public function SqlContentEntityStorageSchema::onFieldStorageDefinitionDelete in Drupal 10

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onFieldStorageDefinitionDelete()
  2. 9 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onFieldStorageDefinitionDelete()

Reacts to the deletion of a field storage definition.

Parameters

\Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition: The field being deleted.

Overrides FieldStorageDefinitionListenerInterface::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.');
      }
    }
    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();
    }
    try {

      // 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 (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()]);
}