You are here

public function MigrateExecutable::rollback in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/migrate/src/MigrateExecutable.php \Drupal\migrate\MigrateExecutable::rollback()
  2. 10 core/modules/migrate/src/MigrateExecutable.php \Drupal\migrate\MigrateExecutable::rollback()

Performs a rollback operation - remove previously-imported items.

Overrides MigrateExecutableInterface::rollback

File

core/modules/migrate/src/MigrateExecutable.php, line 292

Class

MigrateExecutable
Defines a migrate executable class.

Namespace

Drupal\migrate

Code

public function rollback() {

  // Only begin the rollback operation if the migration is currently idle.
  if ($this->migration
    ->getStatus() !== MigrationInterface::STATUS_IDLE) {
    $this->message
      ->display($this
      ->t('Migration @id is busy with another operation: @status', [
      '@id' => $this->migration
        ->id(),
      '@status' => $this
        ->t($this->migration
        ->getStatusLabel()),
    ]), 'error');
    return MigrationInterface::RESULT_FAILED;
  }

  // Announce that rollback is about to happen.
  $this
    ->getEventDispatcher()
    ->dispatch(new MigrateRollbackEvent($this->migration), MigrateEvents::PRE_ROLLBACK);

  // Optimistically assume things are going to work out; if not, $return will be
  // updated to some other status.
  $return = MigrationInterface::RESULT_COMPLETED;
  $this->migration
    ->setStatus(MigrationInterface::STATUS_ROLLING_BACK);
  $id_map = $this
    ->getIdMap();
  $destination = $this->migration
    ->getDestinationPlugin();

  // Loop through each row in the map, and try to roll it back.
  $id_map
    ->rewind();
  while ($id_map
    ->valid()) {
    $destination_key = $id_map
      ->currentDestination();
    if ($destination_key) {
      $map_row = $id_map
        ->getRowByDestination($destination_key);
      if ($map_row['rollback_action'] == MigrateIdMapInterface::ROLLBACK_DELETE) {
        $this
          ->getEventDispatcher()
          ->dispatch(new MigrateRowDeleteEvent($this->migration, $destination_key), MigrateEvents::PRE_ROW_DELETE);
        $destination
          ->rollback($destination_key);
        $this
          ->getEventDispatcher()
          ->dispatch(new MigrateRowDeleteEvent($this->migration, $destination_key), MigrateEvents::POST_ROW_DELETE);
      }

      // We're now done with this row, so remove it from the map.
      $id_map
        ->deleteDestination($destination_key);
    }
    else {

      // If there is no destination key the import probably failed and we can
      // remove the row without further action.
      $source_key = $id_map
        ->currentSource();
      $id_map
        ->delete($source_key);
    }
    $id_map
      ->next();

    // Check for memory exhaustion.
    if (($return = $this
      ->checkStatus()) != MigrationInterface::RESULT_COMPLETED) {
      break;
    }

    // If anyone has requested we stop, return the requested result.
    if ($this->migration
      ->getStatus() == MigrationInterface::STATUS_STOPPING) {
      $return = $this->migration
        ->getInterruptionResult();
      $this->migration
        ->clearInterruptionResult();
      break;
    }
  }

  // Notify modules that rollback attempt was complete.
  $this
    ->getEventDispatcher()
    ->dispatch(new MigrateRollbackEvent($this->migration), MigrateEvents::POST_ROLLBACK);
  $this->migration
    ->setStatus(MigrationInterface::STATUS_IDLE);
  return $return;
}