diff --git a/src/Form/Ingest/Review.php b/src/Form/Ingest/Review.php index 345f99a..62ec884 100644 --- a/src/Form/Ingest/Review.php +++ b/src/Form/Ingest/Review.php @@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; +use Drupal\islandora_spreadsheet_ingest\Util\MigrationRollbackBatch; +use Drupal\migrate_tools\MigrateExecutable; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\migrate\Plugin\MigrationInterface; @@ -145,7 +147,7 @@ public function submitActivation(array &$form, FormStateInterface $form_state) { * @param mixed $context * A reference to the batch context. */ - public function runBatchOp(MigrationInterface $migration, MigrateBatchExecutable $e, &$context) { + public function runBatchOp(MigrationInterface $migration, MigrateExecutable $e, &$context) { $sandbox =& $context['sandbox']; if (!isset($sandbox['prepped'])) { @@ -193,6 +195,10 @@ protected function processingMethods() { 'label' => $this->t('Immediate'), 'callable' => [$this, 'submitProcessImmediate'], ], + 'rollback_migration_group' => [ + 'label' => $this->t('Rollback Migration Group'), + 'callable' => [$this, 'submitProcessRollbackMigrationGroup'], + ], ]; } @@ -250,6 +256,38 @@ protected function submitProcessImmediate(array &$form, FormStateInterface $form } } + /** + * Callback for the "rollback_migration_group" method. + */ + protected function submitProcessRollbackMigrationGroup(): void { + try { + $migrations = $this->migrationPluginManager->createInstancesByTag($this->migrationGroupDeriver->deriveTag($this->entity)); + $batch = [ + 'operations' => [], + ]; + + foreach ($migrations as $migration) { + $executable = new MigrationRollbackBatch($migration, $this->messenger, [ + 'limit' => 0, + 'update' => 0, + 'force' => 0, + ]); + $batch['operations'][] = [ + [$this, 'runBatchOp'], + [$migration, $executable], + ]; + } + + batch_set($batch); + } catch (\Exception $e) { + $this->logger('isi.review')->error("Failed to roll back migration: {exc}\n{backtrace}", [ + 'exc' => $e->getMessage(), + 'backtrace' => $e->getTraceAsString(), + ]); + $this->messenger->addError($this->t("Failed to rollback migration.")); + } + } + /** * Submission handler; route to selected processing method. */ diff --git a/src/Util/MigrationRollbackBatch.php b/src/Util/MigrationRollbackBatch.php new file mode 100644 index 0000000..8fac98a --- /dev/null +++ b/src/Util/MigrationRollbackBatch.php @@ -0,0 +1,105 @@ +messenger = $messenger; + } + + /** + * Prepare a batch array for execution for the given migration. + * + * @return array + * A batch array with operations and the like. + * + * @throws \Exception + * If the migration could not be enqueued successfully. + */ + public function prepareBatch(): array { + return [ + 'title' => $this->t('Rolling back migration: @migration', ['@migration' => $this->migration->id()]), + 'operations' => [ + [[$this, 'processBatch'], []], + ], + 'finished' => [$this, 'finishBatch'], + ]; + } + + /** + * Process each batch to roll back all contained rows + * + * @param array $context + * @return void + */ + public function processBatch(array &$context): void { + $context['message'] = $this->t('Processing of "@migration_id"', ['@migration_id' => $this->migration->id()]); + + $status = $this->rollback(); + + if ($status === MigrationInterface::RESULT_COMPLETED) { + $message = $this->t('Rollback completed', ['@id' => $this->migration->id()]); + $this->messenger->addStatus($message); + } + else { + $message = $this->t('Rollback of @name migration failed.', ['@name' => $this->migration->id()]); + $this->messenger->addError($message); + } + + $context['message'] = $this->t('"@migration_id" has been processed', ['@migration_id' => $this->migration->id()]); + } + + + /** + * Display success or error messages following the completion of processing + * + * @param $success + * @param $results + * @param $ops + * @param $interval + * @return void + */ + public function finishBatch($success, $results, $ops, $interval): void { + if (!$success || empty($results['errors'])) { + $this->messenger->addError( + $this->t( + 'Rollback encountered errors.' + ) + ); + + foreach ($results['errors'] as $e) { + $this->messenger->addError( + $this->t('Migration group rollback failed with exception: @e', ['@e' => $e])); + } + } + } +}