diff --git a/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeRollbackBatch.php b/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeRollbackBatch.php
new file mode 100644
index 0000000..2ca582b
--- /dev/null
+++ b/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeRollbackBatch.php
@@ -0,0 +1,211 @@
+getDefinition($migration_id);
+ $configuration = [];
+
+ // @todo Find a way to avoid this in https://www.drupal.org/node/2804611.
+ if ($definition['destination']['plugin'] === 'entity:file') {
+ // Make sure we have a single trailing slash.
+ if ($definition['source']['plugin'] === 'd7_file_private') {
+ $configuration['source']['constants']['source_base_path'] = rtrim($config['source_private_file_path'], '/') . '/';
+ }
+ $configuration['source']['constants']['source_base_path'] = rtrim($config['source_base_path'], '/') . '/';
+ }
+
+ /** @var \Drupal\migrate\Plugin\Migration $migration */
+ $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id, $configuration);
+
+ if ($migration) {
+ static::$messages = new MigrateMessageCapture();
+ $executable = new MigrateExecutable($migration, static::$messages);
+
+ $migration_name = $migration->label() ? $migration->label() : $migration_id;
+
+ try {
+ $migration_status = $executable->rollback();
+ }
+ catch (\Exception $e) {
+ \Drupal::logger('migrate_drupal_ui')->error($e->getMessage());
+ $migration_status = MigrationInterface::RESULT_FAILED;
+ }
+
+ switch ($migration_status) {
+ case MigrationInterface::RESULT_COMPLETED:
+ // Store the number processed in the sandbox.
+ $context['sandbox']['num_processed'] += static::$numProcessed;
+ $message = new PluralTranslatableMarkup(
+ $context['sandbox']['num_processed'], 'Rolled back @migration (processed 1 item total)', 'Rolled back @migration (processed @count items total)',
+ ['@migration' => $migration_name]);
+ $context['sandbox']['messages'][] = $message;
+ \Drupal::logger('migrate_drupal_ui')->notice($message);
+ $context['sandbox']['num_processed'] = 0;
+ $context['results']['successes']++;
+ break;
+
+ case MigrationInterface::RESULT_INCOMPLETE:
+ $context['sandbox']['messages'][] = (string) new PluralTranslatableMarkup(
+ static::$numProcessed, 'Continuing with @migration (processed 1 item)', 'Continuing with @migration (processed @count items)',
+ ['@migration' => $migration_name]);
+ $context['sandbox']['num_processed'] += static::$numProcessed;
+ break;
+
+ case MigrationInterface::RESULT_STOPPED:
+ $context['sandbox']['messages'][] = t('Operation stopped by request');
+ break;
+
+ case MigrationInterface::RESULT_FAILED:
+ $context['sandbox']['messages'][] = t('Operation on @migration failed', ['@migration' => $migration_name]);
+ $context['results']['failures']++;
+ static::logger()->error('Operation on @migration failed', ['@migration' => $migration_name]);
+ break;
+
+ case MigrationInterface::RESULT_SKIPPED:
+ $context['sandbox']['messages'][] = (string) new TranslatableMarkup('Operation on @migration skipped due to unfulfilled dependencies', ['@migration' => $migration_name]);
+ \Drupal::logger('migrate_drupal_ui')->error('Operation on @migration skipped due to unfulfilled dependencies', ['@migration' => $migration_name]);
+ break;
+
+ case MigrationInterface::RESULT_DISABLED:
+ // Skip silently if disabled.
+ break;
+ }
+
+ // Unless we're continuing on with this migration, take it off the list.
+ if ($migration_status != MigrationInterface::RESULT_INCOMPLETE) {
+ array_shift($context['sandbox']['migration_ids']);
+ $context['sandbox']['current']++;
+ }
+
+ // Add and log any captured messages.
+ foreach (static::$messages->getMessages() as $message) {
+ $context['sandbox']['messages'][] = $message;
+ \Drupal::logger('migrate_drupal_ui')->error($message);
+ }
+
+ // Only display the last MESSAGE_LENGTH messages, in reverse order.
+ $message_count = count($context['sandbox']['messages']);
+ $context['message'] = '';
+ for ($index = max(0, $message_count - self::MESSAGE_LENGTH); $index < $message_count; $index++) {
+ $context['message'] = $context['sandbox']['messages'][$index] . "
\n" . $context['message'];
+ }
+ if ($message_count > self::MESSAGE_LENGTH) {
+ // Indicate there are earlier messages not displayed.
+ $context['message'] .= '…';
+ }
+ // At the top of the list, display the next one (which will be the one
+ // that is running while this message is visible).
+ if (!empty($context['sandbox']['migration_ids'])) {
+ $migration_id = reset($context['sandbox']['migration_ids']);
+ $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);
+ $migration_name = $migration->label() ? $migration->label() : $migration_id;
+ $context['message'] = (string) new TranslatableMarkup('Currently rolling back @migration (@current of @max total tasks)', [
+ '@migration' => $migration_name,
+ '@current' => $context['sandbox']['current'],
+ '@max' => $context['sandbox']['max'],
+ ]) . "
\n" . $context['message'];
+ }
+ }
+ else {
+ array_shift($context['sandbox']['migration_ids']);
+ $context['sandbox']['current']++;
+ }
+
+ $context['finished'] = 1 - count($context['sandbox']['migration_ids']) / $context['sandbox']['max'];
+ }
+
+ /**
+ * Callback executed when Migrate Upgrade Rollback batch process completes.
+ *
+ * @param bool $success
+ * TRUE if batch successfully completed.
+ * @param array $results
+ * Batch results.
+ * @param array $operations
+ * An array of methods run in the batch.
+ * @param string $elapsed
+ * The time to run the batch.
+ */
+ public static function finished($success, array $results, array $operations, $elapsed) {
+ $successes = $results['successes'];
+ $failures = $results['failures'];
+
+ // If we had any successes log that for the user.
+ if ($successes > 0) {
+ drupal_set_message(\Drupal::translation()->formatPlural($successes, 'Completed 1 rollback task successfully', 'Completed @count rollback tasks successfully'));
+ }
+
+ // If we had failures, log them and show the migration failed.
+ if ($failures > 0) {
+ drupal_set_message(\Drupal::translation()->formatPlural($failures, '1 rollback failed', '@count rollbacks failed'));
+ drupal_set_message(t('Rollback process not completed'), 'error');
+ }
+ else {
+ drupal_set_message(t('Rollback of the upgrade is complete - you may now start the upgrade process from scratch.'));
+ }
+
+ if (\Drupal::moduleHandler()->moduleExists('dblog')) {
+ $url = Url::fromRoute('migrate_drupal_ui.log');
+ drupal_set_message(Link::fromTextAndUrl(new TranslatableMarkup('Review the detailed upgrade log'), $url), $failures ? 'error' : 'status');
+ }
+ }
+
+}
diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
index 66e7b04..2ece404 100644
--- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
@@ -14,6 +14,7 @@
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeImportBatch;
+use Drupal\migrate_drupal_ui\Batch\MigrateUpgradeRollbackBatch;
use Drupal\migrate_drupal\MigrationConfigurationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -350,6 +351,7 @@ public function submitOverviewForm(array &$form, FormStateInterface $form_state)
case static::MIGRATE_UPGRADE_ROLLBACK:
$form_state->setValue('step', 'confirm');
break;
+
default:
$form_state->setValue('step', 'credentials');
break;
@@ -763,10 +765,10 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) {
$form['actions']['submit']['#value'] = $this->t('Perform upgrade');
- if ($rollback = $form_state->getValue('upgrade_option') == static::MIGRATE_UPGRADE_ROLLBACK) {
+ if ($form_state->getValue('upgrade_option') == static::MIGRATE_UPGRADE_ROLLBACK) {
$form_state->setStorage(['upgrade_option' => static::MIGRATE_UPGRADE_ROLLBACK]);
$form['rollback'] = [
- '#markup' => $this->t('All previously-imported content, as well as configuration such as field definitions, will be removed.')
+ '#markup' => $this->t('All previously-imported content, as well as configuration such as field definitions, will be removed.'),
];
$form['actions']['submit']['#value'] = $this->t('Perform rollback');
}
@@ -964,6 +966,7 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) {
*/
public function submitConfirmForm(array &$form, FormStateInterface $form_state) {
$storage = $form_state->getStorage();
+ $config['source_base_path'] = $storage['source_base_path'];
if (isset($storage['upgrade_option']) && $storage['upgrade_option'] == static::MIGRATE_UPGRADE_ROLLBACK) {
$migrations = $this->pluginManager->createInstances([]);
@@ -988,14 +991,13 @@ public function submitConfirmForm(array &$form, FormStateInterface $form_state)
'progress_message' => '',
'operations' => [
[
- [MigrateUpgradeRunBatch::class, 'run'],
- [array_keys($migrations), 'rollback', []],
+ [MigrateUpgradeRollbackBatch::class, 'run'],
+ [array_keys($migrations), $config],
],
],
'finished' => [
- MigrateUpgradeRunBatch::class,
- 'finished',
- ],
+ MigrateUpgradeRollbackBatch::class, 'finished',
+ ],
];
batch_set($batch);
$form_state->setRedirect('migrate_drupal_ui.upgrade');
@@ -1003,19 +1005,17 @@ public function submitConfirmForm(array &$form, FormStateInterface $form_state)
}
else {
$migrations = $storage['migrations'];
- $config['source_base_path'] = $storage['source_base_path'];
$batch = [
'title' => $this->t('Running upgrade'),
'progress_message' => '',
'operations' => [
[
- [MigrateUpgradeRunBatch::class, 'run'],
- [array_keys($migrations), 'import', $config],
+ [MigrateUpgradeImportBatch::class, 'run'],
+ [array_keys($migrations), $config],
],
],
'finished' => [
- MigrateUpgradeRunBatch::class,
- 'finished',
+ MigrateUpgradeImportBatch::class, 'finished',
],
];
batch_set($batch);
@@ -1061,12 +1061,6 @@ public function getCancelUrl() {
public function getDescription() {
// The description is added by the buildConfirmForm() method.
// @see \Drupal\migrate_drupal_ui\Form\MigrateUpgradeForm::buildConfirmForm()
- if ($this->state->get('migrate_drupal_ui.performed')) {
- return;
- }
- else {
- return $this->t('
Upgrade analysis report
'); - } } /**