You are here

protected function SqlContentEntityStorageSchema::postUpdateEntityTypeSchema 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::postUpdateEntityTypeSchema()
  2. 9 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::postUpdateEntityTypeSchema()

Allows subscribers to do any cleanup necessary after data copying.

Parameters

\Drupal\Core\Entity\EntityTypeInterface $entity_type: The updated entity type definition.

\Drupal\Core\Entity\EntityTypeInterface $original: The original entity type definition.

\Drupal\Core\Field\FieldStorageDefinitionInterface[] $field_storage_definitions: The updated field storage definitions, including possibly new ones.

\Drupal\Core\Field\FieldStorageDefinitionInterface[] $original_field_storage_definitions: The original field storage definitions.

array &$sandbox: (optional) A sandbox array provided by a hook_update_N() implementation or a Batch API callback. If the entity schema update requires a data migration, this parameter is mandatory. Defaults to NULL.

Overrides SqlFieldableEntityTypeListenerTrait::postUpdateEntityTypeSchema

File

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

Class

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

Namespace

Drupal\Core\Entity\Sql

Code

protected function postUpdateEntityTypeSchema(EntityTypeInterface $entity_type, EntityTypeInterface $original, array $field_storage_definitions, array $original_field_storage_definitions, array &$sandbox = NULL) {

  /** @var \Drupal\Core\Entity\Sql\TableMappingInterface $original_table_mapping */
  $original_table_mapping = $sandbox['original_table_mapping'];

  /** @var \Drupal\Core\Entity\Sql\TableMappingInterface $new_table_mapping */
  $new_table_mapping = $sandbox['new_table_mapping'];

  /** @var \Drupal\Core\Entity\Sql\TableMappingInterface $backup_table_mapping */
  $backup_table_mapping = $sandbox['backup_table_mapping'];

  // Rename the original tables so we can put them back in place in case
  // anything goes wrong.
  $backup_table_names = array_combine($this
    ->getTableNames($original, $original_field_storage_definitions, $original_table_mapping), $this
    ->getTableNames($original, $original_field_storage_definitions, $backup_table_mapping));
  $renamed_tables = [];
  try {
    foreach ($backup_table_names as $original_table_name => $backup_table_name) {
      $this->database
        ->schema()
        ->renameTable($original_table_name, $backup_table_name);
      $renamed_tables[$original_table_name] = $backup_table_name;
    }
  } catch (\Exception $e) {
    foreach ($renamed_tables as $original_table_name => $backup_table_name) {
      $this->database
        ->schema()
        ->renameTable($backup_table_name, $original_table_name);
    }

    // Re-throw the original exception.
    throw $e;
  }

  // Put the new tables in place and update the entity type and field storage
  // definitions.
  try {
    foreach ($sandbox['temporary_table_names'] as $current_table_name => $temp_table_name) {
      $this->database
        ->schema()
        ->renameTable($temp_table_name, $current_table_name);
    }

    // Store the updated entity schema.
    $new_entity_schema = $sandbox['new_entity_schema'];
    $this->schema[$entity_type
      ->id()] = $new_entity_schema;
    $this->entityType = $entity_type;
    $this->fieldStorageDefinitions = $field_storage_definitions;
    $this
      ->saveEntitySchemaData($entity_type, $new_entity_schema);

    // The storage needs to use the updated definitions and table mapping
    // before generating and saving the final field schema data.
    $this->storage
      ->setEntityType($entity_type);
    $this->storage
      ->setFieldStorageDefinitions($field_storage_definitions);
    $this->storage
      ->setTableMapping($new_table_mapping);

    // Store the updated field schema for each field storage.
    foreach ($field_storage_definitions as $field_storage_definition) {
      if ($new_table_mapping
        ->requiresDedicatedTableStorage($field_storage_definition)) {
        $this
          ->createDedicatedTableSchema($field_storage_definition, TRUE);
      }
      elseif ($new_table_mapping
        ->allowsSharedTableStorage($field_storage_definition)) {

        // The shared tables are already fully created, but we need to save
        // the per-field schema definitions for later use.
        $this
          ->createSharedTableSchema($field_storage_definition, TRUE);
      }
    }
  } catch (\Exception $e) {

    // Something went wrong, bring back the original tables.
    foreach ($backup_table_names as $original_table_name => $backup_table_name) {

      // We are in the 'original data recovery' phase, so we need to be sure
      // that the initial tables can be properly restored.
      if ($this->database
        ->schema()
        ->tableExists($original_table_name)) {
        $this->database
          ->schema()
          ->dropTable($original_table_name);
      }
      $this->database
        ->schema()
        ->renameTable($backup_table_name, $original_table_name);
    }

    // Re-throw the original exception.
    throw $e;
  }

  // At this point the update process either finished successfully or any
  // error has been thrown already. We can either keep the backup tables in
  // place or drop them.
  if (Settings::get('entity_update_backup', TRUE)) {
    $backup_key = $sandbox['backup_prefix_key'];
    $backup = [
      'entity_type' => $original,
      'field_storage_definitions' => $original_field_storage_definitions,
      'table_mapping' => $backup_table_mapping,
      'request_time' => $sandbox['backup_request_time'],
    ];
    $this
      ->updateBackupRepository()
      ->set("{$original->id()}.{$backup_key}", $backup);
  }
  else {
    foreach ($backup_table_names as $original_table_name => $backup_table_name) {
      $this->database
        ->schema()
        ->dropTable($backup_table_name);
    }
  }
}