diff --git a/core/modules/migrate_drupal_ui/migrate_drupal_ui.routing.yml b/core/modules/migrate_drupal_ui/migrate_drupal_ui.routing.yml index d02ea98dbd1..9eff2227891 100644 --- a/core/modules/migrate_drupal_ui/migrate_drupal_ui.routing.yml +++ b/core/modules/migrate_drupal_ui/migrate_drupal_ui.routing.yml @@ -1,7 +1,43 @@ migrate_drupal_ui.upgrade: path: '/upgrade' defaults: - _form: '\Drupal\migrate_drupal_ui\Form\MigrateUpgradeForm' + _form: '\Drupal\migrate_drupal_ui\Form\OverviewForm' + _title: 'Upgrade' + requirements: + _custom_access: '\Drupal\migrate_drupal_ui\MigrateAccessCheck::checkAccess' + options: + _admin_route: TRUE +migrate_drupal_ui.upgrade_incremental: + path: '/upgrade/incremental' + defaults: + _form: '\Drupal\migrate_drupal_ui\Form\IncrementalForm' + _title: 'Upgrade' + requirements: + _custom_access: '\Drupal\migrate_drupal_ui\MigrateAccessCheck::checkAccess' + options: + _admin_route: TRUE +migrate_drupal_ui.upgrade_credential: + path: '/upgrade/credentials' + defaults: + _form: '\Drupal\migrate_drupal_ui\Form\CredentialForm' + _title: 'Upgrade' + requirements: + _custom_access: '\Drupal\migrate_drupal_ui\MigrateAccessCheck::checkAccess' + options: + _admin_route: TRUE +migrate_drupal_ui.upgrade_id_conflict: + path: '/upgrade/idconflict' + defaults: + _form: '\Drupal\migrate_drupal_ui\Form\IdConflictForm' + _title: 'Upgrade' + requirements: + _custom_access: '\Drupal\migrate_drupal_ui\MigrateAccessCheck::checkAccess' + options: + _admin_route: TRUE +migrate_drupal_ui.upgrade_review: + path: '/upgrade/review' + defaults: + _form: '\Drupal\migrate_drupal_ui\Form\ReviewForm' _title: 'Upgrade' requirements: _custom_access: '\Drupal\migrate_drupal_ui\MigrateAccessCheck::checkAccess' diff --git a/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php b/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php new file mode 100644 index 00000000000..c3cbbc8b49f --- /dev/null +++ b/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php @@ -0,0 +1,257 @@ +renderer = $renderer; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('renderer'), + $container->get('tempstore.private') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'migrate_drupal_ui_credential_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + if ($this->store->get('step') != 'credential') { + $this->store->set('step', 'overview'); + return $this->redirect('migrate_drupal_ui.upgrade'); + } + + $form = parent::buildForm($form, $form_state); + $form['actions']['submit']['#value'] = $this->t('Review upgrade'); + + $form['#title'] = $this->t('Drupal Upgrade'); + + $drivers = $this->getDatabaseTypes(); + $drivers_keys = array_keys($drivers); + // @todo https://www.drupal.org/node/2678510 Because this is a multi-step + // form, the form is not rebuilt during submission. Ideally we would get + // the chosen driver from form input, if available, in order to use + // #limit_validation_errors in the same way + // \Drupal\Core\Installer\Form\SiteSettingsForm does. + $default_driver = current($drivers_keys); + + $default_options = []; + + $form['version'] = [ + '#type' => 'radios', + '#default_value' => 7, + '#title' => $this->t('Drupal version of the source site'), + '#options' => ['6' => $this->t('Drupal 6'), '7' => $this->t('Drupal 7')], + '#required' => TRUE, + ]; + + $form['database'] = [ + '#type' => 'details', + '#title' => $this->t('Source database'), + '#description' => $this->t('Provide credentials for the database of the Drupal site you want to upgrade.'), + '#open' => TRUE, + ]; + + $form['database']['driver'] = [ + '#type' => 'radios', + '#title' => $this->t('Database type'), + '#required' => TRUE, + '#default_value' => $default_driver, + ]; + if (count($drivers) == 1) { + $form['database']['driver']['#disabled'] = TRUE; + } + + // Add driver-specific configuration options. + foreach ($drivers as $key => $driver) { + $form['database']['driver']['#options'][$key] = $driver->name(); + + $form['database']['settings'][$key] = $driver->getFormOptions($default_options); + // @todo https://www.drupal.org/node/2678510 Using + // #limit_validation_errors in the submit does not work so it is not + // possible to require the database and username for mysql and pgsql. + // This is because this is a multi-step form. + $form['database']['settings'][$key]['database']['#required'] = FALSE; + $form['database']['settings'][$key]['username']['#required'] = FALSE; + $form['database']['settings'][$key]['#prefix'] = '
' . $this->t('It looks like you have content on your new site which may be overwritten if you continue to run this upgrade. The upgrade should be performed on a clean Drupal 8 installation. For more information see the upgrade handbook.', [':id-conflicts-handbook' => 'https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#id_conflicts']) . '
', + ]; + + return $form; + } + + /** + * Formats a set of failing audit results as strings. + * + * Each string is the label of the destination plugin of the migration that + * failed the audit, keyed by the destination plugin ID in order to prevent + * duplication. + * + * @param \Drupal\migrate\Audit\AuditResult[] $conflicts + * The failing audit results. + * + * @return string[] + * The formatted audit results. + */ + protected function formatConflicts(array $conflicts) { + $items = []; + + foreach ($conflicts as $conflict) { + $definition = $conflict->getMigration()->getDestinationPlugin()->getPluginDefinition(); + $id = $definition['id']; + $items[$id] = $definition['label']; + } + sort($items, SORT_STRING); + + return $items; + } + + /** + * Build the markup for i18n warnings. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\migrate\Audit\AuditResult[] $conflicts + * The failing audit results. + * + * @return array + * The form structure. + */ + protected function i18nWarningForm(array &$form, array $conflicts) { + $form['i18n'] = [ + '#title' => $this->t('There is translated content of these types:'), + '#theme' => 'item_list', + '#items' => $this->formatConflicts($conflicts), + ]; + + $form['i18n_warning'] = [ + '#type' => 'markup', + '#markup' => '' . $this->t('It looks like you are migrating translated content from your old site. Possible ID conflicts for translations are not automatically detected in the current version of Drupal. Refer to the upgrade handbook for instructions on how to avoid ID conflicts with translated content.', [':id-conflicts-handbook' => 'https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#id_conflicts']) . '
', + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $this->store->set('step', 'review'); + $form_state->setRedirect('migrate_drupal_ui.upgrade_review'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('I acknowledge I may lose data. Continue anyway.'); + } + +} diff --git a/core/modules/migrate_drupal_ui/src/Form/IncrementalForm.php b/core/modules/migrate_drupal_ui/src/Form/IncrementalForm.php new file mode 100644 index 00000000000..31ca8ab962b --- /dev/null +++ b/core/modules/migrate_drupal_ui/src/Form/IncrementalForm.php @@ -0,0 +1,131 @@ +state = $state; + $this->dateFormatter = $date_formatter; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('state'), + $container->get('date.formatter'), + $container->get('tempstore.private') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'migrate_drupal_ui_incremental_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + if ($this->store->get('step') != 'incremental') { + $this->store->set('step', 'overview'); + return $this->redirect('migrate_drupal_ui.upgrade'); + } + + $form = parent::buildForm($form, $form_state); + $form['#title'] = $this->t('Upgrade'); + + $date_performed = $this->store->get('performed'); + // @todo Add back support for rollbacks. + // https://www.drupal.org/node/2687849 + $form['upgrade_option_item'] = [ + '#type' => 'item', + '#prefix' => $this->t('An upgrade has already been performed on this site. To perform a new migration, create a clean and empty new install of Drupal 8. Rollbacks are not yet supported through the user interface. For more information, see the upgrading handbook.', [':url' => 'https://www.drupal.org/upgrade/migrate']), + '#description' => $this->t('Last upgrade: @date', ['@date' => $this->dateFormatter->format($date_performed)]), + ]; + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + // Retrieve the database driver from state. + $database_state_key = $this->state->get('migrate.fallback_state_key', ''); + if ($database_state_key) { + try { + $database = $this->state->get($database_state_key, [])['database']; + if ($connection = $this->getConnection($database)) { + if ($version = $this->getLegacyDrupalVersion($connection)) { + $this->setupMigrations($database, $form_state); + $valid_legacy_database = TRUE; + } + } + } + catch (DatabaseExceptionWrapper $exception) { + // Hide DB exceptions and forward to the DB credentials form. In that + // form we can more properly display errors and accept new credentials. + } + } + if (empty($valid_legacy_database)) { + $form_state->setValue('step', 'credentials')->setRebuild(); + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $this->store->set('step', 'id_conflict'); + $form_state->setRedirect('migrate_drupal_ui.upgrade_id_conflict'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Import new configuration and content from old site'); + } + +} diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php deleted file mode 100644 index 6ff17f2c555..00000000000 --- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php +++ /dev/null @@ -1,1077 +0,0 @@ - [ - 'blog', - 'blogapi', - 'calendarsignup', - 'color', - 'content_copy', - 'content_multigroup', - 'content_permissions', - 'date_api', - 'date_locale', - 'date_php4', - 'date_popup', - 'date_repeat', - 'date_timezone', - 'date_tools', - 'datepicker', - 'ddblock', - 'event', - 'fieldgroup', - 'filefield_meta', - 'help', - 'i18n', - 'i18nstrings', - 'imageapi', - 'imageapi_gd', - 'imageapi_imagemagick', - 'imagecache_ui', - 'jquery_ui', - 'nodeaccess', - 'number', - 'openid', - 'php', - 'ping', - 'poll', - 'throttle', - 'tracker', - 'translation', - 'trigger', - 'variable', - 'variable_admin', - 'views_export', - 'views_ui', - ], - '7' => [ - 'blog', - 'bulk_export', - 'contextual', - 'ctools', - 'ctools_access_ruleset', - 'ctools_ajax_sample', - 'ctools_custom_content', - 'dashboard', - 'date_all_day', - 'date_api', - 'date_context', - 'date_migrate', - 'date_popup', - 'date_repeat', - 'date_repeat_field', - 'date_tools', - 'date_views', - 'entity', - 'entity_feature', - 'entity_token', - 'entityreference', - 'field_ui', - 'help', - 'openid', - 'overlay', - 'page_manager', - 'php', - 'poll', - 'search_embedded_form', - 'search_extra_type', - 'search_node_tags', - 'simpletest', - 'stylizer', - 'term_depth', - 'toolbar', - 'translation', - 'trigger', - 'views_content', - 'views_ui', - ], - ]; - - /** - * Constructs the MigrateUpgradeForm. - * - * @param \Drupal\Core\State\StateInterface $state - * The state service. - * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter - * The date formatter service. - * @param \Drupal\Core\Render\RendererInterface $renderer - * The renderer service. - * @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $plugin_manager - * The migration plugin manager. - * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager - * The field plugin manager. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. - */ - public function __construct(StateInterface $state, DateFormatterInterface $date_formatter, RendererInterface $renderer, MigrationPluginManagerInterface $plugin_manager, MigrateFieldPluginManagerInterface $field_plugin_manager, ModuleHandlerInterface $module_handler, MessengerInterface $messenger) { - $this->state = $state; - $this->dateFormatter = $date_formatter; - $this->renderer = $renderer; - $this->pluginManager = $plugin_manager; - $this->fieldPluginManager = $field_plugin_manager; - $this->moduleHandler = $module_handler; - $this->messenger = $messenger; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('state'), - $container->get('date.formatter'), - $container->get('renderer'), - $container->get('plugin.manager.migration'), - $container->get('plugin.manager.migrate.field'), - $container->get('module_handler'), - $container->get('messenger') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'migrate_drupal_ui_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state) { - $this->step = $form_state->get('step') ?: 'overview'; - switch ($this->step) { - case 'overview': - return $this->buildOverviewForm($form, $form_state); - - case 'credentials': - return $this->buildCredentialForm($form, $form_state); - - case 'confirm_id_conflicts': - return $this->buildIdConflictForm($form, $form_state); - - case 'confirm': - return $this->buildConfirmForm($form, $form_state); - - default: - $this->messenger->addError($this->t('Unrecognized form step @step', ['@step' => $this->step])); - return []; - } - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - // This method is intentionally empty, see the specific submit methods for - // each form step. - } - - /** - * Builds the form presenting an overview of the migration process. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - * - * @return array - * The form structure. - */ - public function buildOverviewForm(array $form, FormStateInterface $form_state) { - $form['#title'] = $this->t('Upgrade'); - - if ($date_performed = $this->state->get('migrate_drupal_ui.performed')) { - // @todo Add back support for rollbacks. - // https://www.drupal.org/node/2687849 - $form['upgrade_option_item'] = [ - '#type' => 'item', - '#prefix' => $this->t('An upgrade has already been performed on this site. To perform a new migration, create a clean and empty new install of Drupal 8. Rollbacks are not yet supported through the user interface. For more information, see the upgrading handbook.', [':url' => 'https://www.drupal.org/upgrade/migrate']), - '#description' => $this->t('Last upgrade: @date', ['@date' => $this->dateFormatter->format($date_performed)]), - ]; - $form['actions']['incremental'] = [ - '#type' => 'submit', - '#value' => $this->t('Import new configuration and content from old site'), - '#button_type' => 'primary', - '#validate' => ['::validateIncrementalForm'], - '#submit' => ['::submitIncrementalForm'], - ]; - return $form; - } - else { - $form['info_header'] = [ - '#markup' => '' . $this->t('Upgrade a site by importing its files and the data from its database into a clean and empty new install of Drupal 8. See the Drupal site upgrades handbook for more information.', [ - ':url' => 'https://www.drupal.org/upgrade/migrate', - ]), - ]; - - $form['legend']['#markup'] = ''; - $form['legend']['#markup'] .= '
' . $this->t('The upgrade can take a long time. It is better to upgrade from a local copy of your site instead of directly from your live site.'), - ]; - - $validate = []; - } - - $form['actions'] = ['#type' => 'actions']; - $form['actions']['save'] = [ - '#type' => 'submit', - '#value' => $this->t('Continue'), - '#button_type' => 'primary', - '#validate' => $validate, - '#submit' => ['::submitOverviewForm'], - ]; - return $form; - } - - /** - * Form submission handler for the overview form. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - public function submitOverviewForm(array &$form, FormStateInterface $form_state) { - $form_state->set('step', 'credentials')->setRebuild(); - } - - /** - * Validation handler for the incremental overview form. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - public function validateIncrementalForm(array &$form, FormStateInterface $form_state) { - // Retrieve the database driver from state. - $database_state_key = $this->state->get('migrate.fallback_state_key', ''); - if ($database_state_key) { - try { - $database = $this->state->get($database_state_key, [])['database']; - if ($connection = $this->getConnection($database)) { - if ($version = $this->getLegacyDrupalVersion($connection)) { - $this->setupMigrations($database, $form_state); - $valid_legacy_database = TRUE; - } - } - } - catch (DatabaseExceptionWrapper $exception) { - // Hide DB exceptions and forward to the DB credentials form. In that - // form we can more properly display errors and accept new credentials. - } - } - if (empty($valid_legacy_database)) { - $form_state->setValue('step', 'credentials')->setRebuild(); - } - } - - /** - * Form submission handler for the incremental overview form. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - public function submitIncrementalForm(array &$form, FormStateInterface $form_state) { - $form_state->set('step', 'confirm_id_conflicts')->setRebuild(); - } - - /** - * Builds the database credential form and adds file location information. - * - * This is largely borrowed from \Drupal\Core\Installer\Form\SiteSettingsForm. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - * - * @return array - * The form structure. - * - * @todo Private files directory not yet implemented, depends on - * https://www.drupal.org/node/2547125. - */ - public function buildCredentialForm(array $form, FormStateInterface $form_state) { - $form['#title'] = $this->t('Drupal Upgrade'); - - $drivers = $this->getDatabaseTypes(); - $drivers_keys = array_keys($drivers); - // @todo https://www.drupal.org/node/2678510 Because this is a multi-step - // form, the form is not rebuilt during submission. Ideally we would get - // the chosen driver from form input, if available, in order to use - // #limit_validation_errors in the same way - // \Drupal\Core\Installer\Form\SiteSettingsForm does. - $default_driver = current($drivers_keys); - - $default_options = []; - - $form['version'] = [ - '#type' => 'radios', - '#default_value' => 7, - '#title' => $this->t('Drupal version of the source site'), - '#options' => ['6' => $this->t('Drupal 6'), '7' => $this->t('Drupal 7')], - '#required' => TRUE, - ]; - - $form['database'] = [ - '#type' => 'details', - '#title' => $this->t('Source database'), - '#description' => $this->t('Provide credentials for the database of the Drupal site you want to upgrade.'), - '#open' => TRUE, - ]; - - $form['database']['driver'] = [ - '#type' => 'radios', - '#title' => $this->t('Database type'), - '#required' => TRUE, - '#default_value' => $default_driver, - ]; - if (count($drivers) == 1) { - $form['database']['driver']['#disabled'] = TRUE; - } - - // Add driver-specific configuration options. - foreach ($drivers as $key => $driver) { - $form['database']['driver']['#options'][$key] = $driver->name(); - - $form['database']['settings'][$key] = $driver->getFormOptions($default_options); - // @todo https://www.drupal.org/node/2678510 Using - // #limit_validation_errors in the submit does not work so it is not - // possible to require the database and username for mysql and pgsql. - // This is because this is a multi-step form. - $form['database']['settings'][$key]['database']['#required'] = FALSE; - $form['database']['settings'][$key]['username']['#required'] = FALSE; - $form['database']['settings'][$key]['#prefix'] = '
' . $this->t('It looks like you have content on your new site which may be overwritten if you continue to run this upgrade. The upgrade should be performed on a clean Drupal 8 installation. For more information see the upgrade handbook.', [':id-conflicts-handbook' => 'https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#id_conflicts']) . '
', - ]; - - return $form; - } - - /** - * Formats a set of failing audit results as strings. - * - * Each string is the label of the destination plugin of the migration that - * failed the audit, keyed by the destination plugin ID in order to prevent - * duplication. - * - * @param \Drupal\migrate\Audit\AuditResult[] $conflicts - * The failing audit results. - * - * @return string[] - * The formatted audit results. - */ - protected function formatConflicts(array $conflicts) { - $items = []; - - foreach ($conflicts as $conflict) { - $definition = $conflict->getMigration()->getDestinationPlugin()->getPluginDefinition(); - $id = $definition['id']; - $items[$id] = $definition['label']; - } - sort($items, SORT_STRING); - - return $items; - } - - /** - * Build the markup for i18n warnings. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - * @param \Drupal\migrate\Audit\AuditResult[] $conflicts - * The failing audit results. - * - * @return array - * The form structure. - */ - protected function i18nWarningForm(array &$form, FormStateInterface $form_state, array $conflicts) { - $form['i18n'] = [ - '#title' => $this->t('There is translated content of these types:'), - '#theme' => 'item_list', - '#items' => $this->formatConflicts($conflicts), - ]; - - $form['i18n_warning'] = [ - '#type' => 'markup', - '#markup' => '' . $this->t('It looks like you are migrating translated content from your old site. Possible ID conflicts for translations are not automatically detected in the current version of Drupal. Refer to the upgrade handbook for instructions on how to avoid ID conflicts with translated content.', [':id-conflicts-handbook' => 'https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#id_conflicts']) . '
', - ]; - - return $form; - } - - /** - * Submission handler for the confirmation form. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - public function submitConfirmIdConflictForm(array &$form, FormStateInterface $form_state) { - $form_state->set('step', 'confirm'); - $form_state->setRebuild(); - } - - /** - * Confirmation form showing available and missing migration paths. - * - * The confirmation form uses the source_module and destination_module - * properties on the source, destination and field plugins as well as the - * system data from the source to determine if there is a migration path for - * each module in the source. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - * - * @return array - * The form structure. - */ - public function buildConfirmForm(array $form, FormStateInterface $form_state) { - $form = parent::buildForm($form, $form_state); - $form['actions']['submit']['#submit'] = ['::submitConfirmForm']; - - $form['actions']['submit']['#value'] = $this->t('Perform upgrade'); - - $version = $form_state->get('version'); - - // Get the source_module and destination_module for each migration. - $migrations = $this->getMigrations('migrate_drupal_' . $version, $version); - $table_data = []; - foreach ($migrations as $migration) { - $migration_id = $migration->getPluginId(); - $source_module = $migration->getSourcePlugin()->getSourceModule(); - if (!$source_module) { - $this->messenger->addError($this->t('Source module not found for @migration_id.', ['@migration_id' => $migration_id])); - } - $destination_module = $migration->getDestinationPlugin()->getDestinationModule(); - if (!$destination_module) { - $this->messenger->addError($this->t('Destination module not found for @migration_id.', ['@migration_id' => $migration_id])); - } - - if ($source_module && $destination_module) { - $table_data[$source_module][$destination_module][$migration_id] = $migration->label(); - } - } - - // Get the source_module and destination_module from the field plugins. - $definitions = $this->fieldPluginManager->getDefinitions(); - foreach ($definitions as $definition) { - // This is not strict so that we find field plugins with an annotation - // where the Drupal core version is an integer and when it is a string. - if (in_array($version, $definition['core'])) { - $source_module = $definition['source_module']; - $destination_module = $definition['destination_module']; - $table_data[$source_module][$destination_module][$definition['id']] = $definition['id']; - } - } - - // Fetch the system data at the first opportunity. - $system_data = $form_state->get('system_data'); - - // Add source_module and destination_module for modules that do not need an - // upgrade path and are enabled on the source site. - foreach ($this->noUpgradePaths[$version] as $extension) { - if ($system_data['module'][$extension]['status']) { - $table_data[$extension]['core'][$extension] = $extension; - } - } - - // Sort the table by source module names and within that destination - // module names. - ksort($table_data); - foreach ($table_data as $source_module => $destination_module_info) { - ksort($table_data[$source_module]); - } - - // Remove core profiles from the system data. - foreach (['standard', 'minimal'] as $profile) { - unset($system_data['module'][$profile]); - } - - $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data); - - // Missing migrations. - $missing_module_list = [ - '#type' => 'details', - '#open' => TRUE, - '#title' => [ - '#type' => 'html_tag', - '#tag' => 'span', - '#value' => $this->t('Modules that will not be upgraded'), - '#attributes' => ['id' => ['error']], - ], - '#description' => $this->t('There are no modules installed on your new site to replace these modules. If you proceed with the upgrade now, configuration and/or content needed by these modules will not be available on your new site. For more information, see Review the pre-upgrade analysis in the Upgrading to Drupal 8 handbook.', [':review' => 'https://www.drupal.org/docs/8/upgrade/upgrade-using-web-browser#pre-upgrade-analysis', ':migrate' => 'https://www.drupal.org/docs/8/upgrade']), - '#weight' => 2, - ]; - $missing_module_list['module_list'] = [ - '#type' => 'table', - '#header' => [ - $this->t('Drupal @version', ['@version' => $version]), - $this->t('Drupal 8'), - ], - ]; - $missing_count = 0; - ksort($unmigrated_source_modules); - foreach ($unmigrated_source_modules as $source_module => $module_data) { - if ($module_data['status']) { - $missing_count++; - $missing_module_list['module_list'][$source_module] = [ - 'source_module' => [ - '#type' => 'html_tag', - '#tag' => 'span', - '#value' => $source_module, - '#attributes' => [ - 'class' => [ - 'upgrade-analysis-report__status-icon', - 'upgrade-analysis-report__status-icon--error', - ], - ], - ], - 'destination_module' => ['#plain_text' => 'Not upgraded'], - ]; - } - } - - // Available migrations. - $available_module_list = [ - '#type' => 'details', - '#title' => [ - '#type' => 'html_tag', - '#tag' => 'span', - '#value' => $this->t('Modules that will be upgraded'), - '#attributes' => ['id' => ['checked']], - ], - '#weight' => 3, - ]; - - $available_module_list['module_list'] = [ - '#type' => 'table', - '#header' => [ - $this->t('Drupal @version', ['@version' => $version]), - $this->t('Drupal 8'), - ], - ]; - - $available_count = 0; - foreach ($table_data as $source_module => $destination_module_info) { - $available_count++; - $destination_details = []; - foreach ($destination_module_info as $destination_module => $migration_ids) { - $destination_details[$destination_module] = [ - '#type' => 'item', - '#plain_text' => $destination_module, - ]; - } - $available_module_list['module_list'][$source_module] = [ - 'source_module' => [ - '#type' => 'html_tag', - '#tag' => 'span', - '#value' => $source_module, - '#attributes' => [ - 'class' => [ - 'upgrade-analysis-report__status-icon', - 'upgrade-analysis-report__status-icon--checked', - ], - ], - ], - 'destination_module' => $destination_details, - ]; - } - - $counters = []; - $general_info = []; - - if ($missing_count) { - $counters[] = [ - '#theme' => 'status_report_counter', - '#amount' => $missing_count, - '#text' => $this->formatPlural($missing_count, 'Module will not be upgraded', 'Modules will not be upgraded'), - '#severity' => 'error', - '#weight' => 0, - ]; - $general_info[] = $missing_module_list; - } - if ($available_count) { - $counters[] = [ - '#theme' => 'status_report_counter', - '#amount' => $available_count, - '#text' => $this->formatPlural($available_count, 'Module will be upgraded', 'Modules will be upgraded'), - '#severity' => 'checked', - '#weight' => 1, - ]; - $general_info[] = $available_module_list; - } - - $form['status_report_page'] = [ - '#theme' => 'status_report_page', - '#counters' => $counters, - '#general_info' => $general_info, - ]; - - $form['#attached']['library'][] = 'migrate_drupal_ui/base'; - - return $form; - } - - /** - * Submission handler for the confirmation form. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - public function submitConfirmForm(array &$form, FormStateInterface $form_state) { - $storage = $form_state->getStorage(); - - $migrations = $storage['migrations']; - $config['source_base_path'] = $storage['source_base_path']; - $batch = [ - 'title' => $this->t('Running upgrade'), - 'progress_message' => '', - 'operations' => [ - [ - [MigrateUpgradeImportBatch::class, 'run'], - [array_keys($migrations), $config], - ], - ], - 'finished' => [ - MigrateUpgradeImportBatch::class, 'finished', - ], - ]; - batch_set($batch); - $form_state->setRedirect('' . $this->t('Upgrade a site by importing its files and the data from its database into a clean and empty new install of Drupal 8. See the Drupal site upgrades handbook for more information.', [ + ':url' => 'https://www.drupal.org/upgrade/migrate', + ]), + ]; + + $form['legend']['#markup'] = ''; + $form['legend']['#markup'] .= '
' . $this->t('The upgrade can take a long time. It is better to upgrade from a local copy of your site instead of directly from your live site.'),
+ ];
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $this->store->set('step', 'credential');
+ $form_state->setRedirect('migrate_drupal_ui.upgrade_credential');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfirmText() {
+ return $this->t('Continue');
+ }
+
+}
diff --git a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php
new file mode 100644
index 00000000000..d6c82206332
--- /dev/null
+++ b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php
@@ -0,0 +1,380 @@
+ [
+ 'blog',
+ 'blogapi',
+ 'calendarsignup',
+ 'color',
+ 'content_copy',
+ 'content_multigroup',
+ 'content_permissions',
+ 'date_api',
+ 'date_locale',
+ 'date_php4',
+ 'date_popup',
+ 'date_repeat',
+ 'date_timezone',
+ 'date_tools',
+ 'datepicker',
+ 'ddblock',
+ 'event',
+ 'fieldgroup',
+ 'filefield_meta',
+ 'help',
+ 'i18n',
+ 'i18nstrings',
+ 'imageapi',
+ 'imageapi_gd',
+ 'imageapi_imagemagick',
+ 'imagecache_ui',
+ 'jquery_ui',
+ 'nodeaccess',
+ 'number',
+ 'openid',
+ 'php',
+ 'ping',
+ 'poll',
+ 'throttle',
+ 'tracker',
+ 'translation',
+ 'trigger',
+ 'variable',
+ 'variable_admin',
+ 'views_export',
+ 'views_ui',
+ ],
+ '7' => [
+ 'blog',
+ 'bulk_export',
+ 'contextual',
+ 'ctools',
+ 'ctools_access_ruleset',
+ 'ctools_ajax_sample',
+ 'ctools_custom_content',
+ 'dashboard',
+ 'date_all_day',
+ 'date_api',
+ 'date_context',
+ 'date_migrate',
+ 'date_popup',
+ 'date_repeat',
+ 'date_repeat_field',
+ 'date_tools',
+ 'date_views',
+ 'entity',
+ 'entity_feature',
+ 'entity_token',
+ 'entityreference',
+ 'field_ui',
+ 'help',
+ 'openid',
+ 'overlay',
+ 'page_manager',
+ 'php',
+ 'poll',
+ 'search_embedded_form',
+ 'search_extra_type',
+ 'search_node_tags',
+ 'simpletest',
+ 'stylizer',
+ 'term_depth',
+ 'toolbar',
+ 'translation',
+ 'trigger',
+ 'views_content',
+ 'views_ui',
+ ],
+ ];
+
+ /**
+ * ReviewForm constructor.
+ *
+ * @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_plugin_manager
+ * The field plugin manager service.
+ * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempstore_private
+ * The private tempstore factory.
+ */
+ public function __construct(MigrateFieldPluginManagerInterface $field_plugin_manager, PrivateTempStoreFactory $tempstore_private) {
+ parent::__construct($tempstore_private);
+ $this->fieldPluginManager = $field_plugin_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('plugin.manager.migrate.field'),
+ $container->get('tempstore.private')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'migrate_drupal_ui_review_form';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state) {
+ if ($this->store->get('step') != 'review') {
+ $this->store->set('step', 'overview');
+ return $this->redirect('migrate_drupal_ui.upgrade');
+ }
+
+ $form = parent::buildForm($form, $form_state);
+ $form['#title'] = $this->t('What will be upgraded?');
+
+ $version = $this->store->get('version');
+ // Get the source_module and destination_module for each migration.
+ $migrations = $this->getMigrations('migrate_drupal_' . $version, $version);
+ $table_data = [];
+ foreach ($migrations as $migration) {
+ $migration_id = $migration->getPluginId();
+ $source_module = $migration->getSourcePlugin()->getSourceModule();
+ if (!$source_module) {
+ $this->messenger()->addError($this->t('Source module not found for @migration_id.', ['@migration_id' => $migration_id]));
+ }
+ $destination_module = $migration->getDestinationPlugin()->getDestinationModule();
+ if (!$destination_module) {
+ $this->messenger()->addError($this->t('Destination module not found for @migration_id.', ['@migration_id' => $migration_id]));
+ }
+
+ if ($source_module && $destination_module) {
+ $table_data[$source_module][$destination_module][$migration_id] = $migration->label();
+ }
+ }
+
+ // Get the source_module and destination_module from the field plugins.
+ $definitions = $this->fieldPluginManager->getDefinitions();
+ foreach ($definitions as $definition) {
+ // This is not strict so that we find field plugins with an annotation
+ // where the Drupal core version is an integer and when it is a string.
+ if (in_array($version, $definition['core'])) {
+ $source_module = $definition['source_module'];
+ $destination_module = $definition['destination_module'];
+ $table_data[$source_module][$destination_module][$definition['id']] = $definition['id'];
+ }
+ }
+
+ // Fetch the system data at the first opportunity.
+ $system_data = $this->store->get('system_data');
+
+ // Add source_module and destination_module for modules that do not need an
+ // upgrade path and are enabled on the source site.
+ foreach ($this->noUpgradePaths[$version] as $extension) {
+ if ($system_data['module'][$extension]['status']) {
+ $table_data[$extension]['core'][$extension] = $extension;
+ }
+ }
+
+ // Sort the table by source module names and within that destination
+ // module names.
+ ksort($table_data);
+ foreach ($table_data as $source_module => $destination_module_info) {
+ ksort($table_data[$source_module]);
+ }
+
+ // Remove core profiles from the system data.
+ foreach (['standard', 'minimal'] as $profile) {
+ unset($system_data['module'][$profile]);
+ }
+
+ $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data);
+
+ // Missing migrations.
+ $missing_module_list = [
+ '#type' => 'details',
+ '#open' => TRUE,
+ '#title' => [
+ '#type' => 'html_tag',
+ '#tag' => 'span',
+ '#value' => $this->t('Modules that will not be upgraded'),
+ '#attributes' => ['id' => ['error']],
+ ],
+ '#description' => $this->t('There are no modules installed on your new site to replace these modules. If you proceed with the upgrade now, configuration and/or content needed by these modules will not be available on your new site. For more information, see Review the pre-upgrade analysis in the Upgrading to Drupal 8 handbook.', [':review' => 'https://www.drupal.org/docs/8/upgrade/upgrade-using-web-browser#pre-upgrade-analysis', ':migrate' => 'https://www.drupal.org/docs/8/upgrade']),
+ '#weight' => 2,
+ ];
+ $missing_module_list['module_list'] = [
+ '#type' => 'table',
+ '#header' => [
+ $this->t('Drupal @version', ['@version' => $version]),
+ $this->t('Drupal 8'),
+ ],
+ ];
+ $missing_count = 0;
+ ksort($unmigrated_source_modules);
+ foreach ($unmigrated_source_modules as $source_module => $module_data) {
+ if ($module_data['status']) {
+ $missing_count++;
+ $missing_module_list['module_list'][$source_module] = [
+ 'source_module' => [
+ '#type' => 'html_tag',
+ '#tag' => 'span',
+ '#value' => $source_module,
+ '#attributes' => [
+ 'class' => [
+ 'upgrade-analysis-report__status-icon',
+ 'upgrade-analysis-report__status-icon--error',
+ ],
+ ],
+ ],
+ 'destination_module' => ['#plain_text' => 'Not upgraded'],
+ ];
+ }
+ }
+
+ // Available migrations.
+ $available_module_list = [
+ '#type' => 'details',
+ '#title' => [
+ '#type' => 'html_tag',
+ '#tag' => 'span',
+ '#value' => $this->t('Modules that will be upgraded'),
+ '#attributes' => ['id' => ['checked']],
+ ],
+ '#weight' => 3,
+ ];
+
+ $available_module_list['module_list'] = [
+ '#type' => 'table',
+ '#header' => [
+ $this->t('Drupal @version', ['@version' => $version]),
+ $this->t('Drupal 8'),
+ ],
+ ];
+
+ $available_count = 0;
+ foreach ($table_data as $source_module => $destination_module_info) {
+ $available_count++;
+ $destination_details = [];
+ foreach ($destination_module_info as $destination_module => $migration_ids) {
+ $destination_details[$destination_module] = [
+ '#type' => 'item',
+ '#plain_text' => $destination_module,
+ ];
+ }
+ $available_module_list['module_list'][$source_module] = [
+ 'source_module' => [
+ '#type' => 'html_tag',
+ '#tag' => 'span',
+ '#value' => $source_module,
+ '#attributes' => [
+ 'class' => [
+ 'upgrade-analysis-report__status-icon',
+ 'upgrade-analysis-report__status-icon--checked',
+ ],
+ ],
+ ],
+ 'destination_module' => $destination_details,
+ ];
+ }
+
+ $counters = [];
+ $general_info = [];
+
+ if ($missing_count) {
+ $counters[] = [
+ '#theme' => 'status_report_counter',
+ '#amount' => $missing_count,
+ '#text' => $this->formatPlural($missing_count, 'Module will not be upgraded', 'Modules will not be upgraded'),
+ '#severity' => 'error',
+ '#weight' => 0,
+ ];
+ $general_info[] = $missing_module_list;
+ }
+ if ($available_count) {
+ $counters[] = [
+ '#theme' => 'status_report_counter',
+ '#amount' => $available_count,
+ '#text' => $this->formatPlural($available_count, 'Module will be upgraded', 'Modules will be upgraded'),
+ '#severity' => 'checked',
+ '#weight' => 1,
+ ];
+ $general_info[] = $available_module_list;
+ }
+
+ $form['status_report_page'] = [
+ '#theme' => 'status_report_page',
+ '#counters' => $counters,
+ '#general_info' => $general_info,
+ ];
+
+ $form['#attached']['library'][] = 'migrate_drupal_ui/base';
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $migrations = $this->store->get('migrations');
+ $config['source_base_path'] = $this->store->get('source_base_path');
+ $batch = [
+ 'title' => $this->t('Running upgrade'),
+ 'progress_message' => '',
+ 'operations' => [
+ [
+ [MigrateUpgradeImportBatch::class, 'run'],
+ [array_keys($migrations), $config],
+ ],
+ ],
+ 'finished' => [
+ MigrateUpgradeImportBatch::class, 'finished',
+ ],
+ ];
+ batch_set($batch);
+ $form_state->setRedirect('