diff --git a/core/modules/drupal_upgrade/drupal_upgrade.info.yml b/core/modules/drupal_upgrade/drupal_upgrade.info.yml new file mode 100644 index 0000000..0615e41 --- /dev/null +++ b/core/modules/drupal_upgrade/drupal_upgrade.info.yml @@ -0,0 +1,11 @@ +name: Drupal Upgrade +type: module +description: 'UI for direct upgrades from older Drupal versions.' +package: Core (Experimental) +version: VERSION +core: 8.x +configure: drupal_upgrade.upgrade +dependencies: + - migrate + - migrate_drupal + - dblog diff --git a/core/modules/drupal_upgrade/drupal_upgrade.install b/core/modules/drupal_upgrade/drupal_upgrade.install new file mode 100644 index 0000000..94ac744 --- /dev/null +++ b/core/modules/drupal_upgrade/drupal_upgrade.install @@ -0,0 +1,16 @@ +toString(); + drupal_set_message(t("The Drupal Upgrade module has been enabled. Proceed to the upgrade form.", ['@url' => $url])); +} diff --git a/core/modules/drupal_upgrade/drupal_upgrade.module b/core/modules/drupal_upgrade/drupal_upgrade.module new file mode 100644 index 0000000..2366914 --- /dev/null +++ b/core/modules/drupal_upgrade/drupal_upgrade.module @@ -0,0 +1,19 @@ +' . t('The Drupal Upgrade module provides a one-click upgrade from an earlier version of Drupal. For details, see the online documentation for the Drupal Upgrade module in the handbook on upgrading from previous versions.', [':migrate' => 'https://www.drupal.org/upgrade/migrate']) . '
'; + return $output; + } +} diff --git a/core/modules/drupal_upgrade/drupal_upgrade.routing.yml b/core/modules/drupal_upgrade/drupal_upgrade.routing.yml new file mode 100644 index 0000000..4842376 --- /dev/null +++ b/core/modules/drupal_upgrade/drupal_upgrade.routing.yml @@ -0,0 +1,18 @@ +drupal_upgrade.upgrade: + path: '/upgrade' + defaults: + _form: '\Drupal\drupal_upgrade\Form\MigrateUpgradeForm' + _title: 'Upgrade' + requirements: + _permission: 'administer software updates' + options: + _admin_route: TRUE + +drupal_upgrade.log: + path: '/upgrade/log' + defaults: + _controller: '\Drupal\drupal_upgrade\Controller\MigrateController::showLog' + requirements: + _permission: 'administer software updates' + options: + _admin_route: TRUE diff --git a/core/modules/drupal_upgrade/src/Controller/MigrateController.php b/core/modules/drupal_upgrade/src/Controller/MigrateController.php new file mode 100644 index 0000000..b46fc77 --- /dev/null +++ b/core/modules/drupal_upgrade/src/Controller/MigrateController.php @@ -0,0 +1,24 @@ + 'drupal_upgrade']; + return $this->redirect('dblog.overview'); + } +} diff --git a/core/modules/drupal_upgrade/src/DrushLogMigrateMessage.php b/core/modules/drupal_upgrade/src/DrushLogMigrateMessage.php new file mode 100644 index 0000000..7f075cb --- /dev/null +++ b/core/modules/drupal_upgrade/src/DrushLogMigrateMessage.php @@ -0,0 +1,28 @@ + [ + 'source_module' => 'system', + 'destination_module' => 'action' + ], + 'd6_aggregator_feed' => [ + 'source_module' => 'aggregator', + 'destination_module' => 'aggregator', + ], + 'd6_aggregator_item' => [ + 'source_module' => 'aggregator', + 'destination_module' => 'aggregator', + ], + 'd6_aggregator_settings' => [ + 'source_module' => 'aggregator', + 'destination_module' => 'aggregator', + ], + 'd7_aggregator_feed' => [ + 'source_module' => 'aggregator', + 'destination_module' => 'aggregator', + ], + 'd7_aggregator_item' => [ + 'source_module' => 'aggregator', + 'destination_module' => 'aggregator', + ], + 'd7_aggregator_settings' => [ + 'source_module' => 'aggregator', + 'destination_module' => 'aggregator', + ], + 'd7_blocked_ips' => [ + 'source_module' => 'system', + 'destination_module' => 'ban', + ], + 'd6_block' => [ + 'source_module' => 'block', + 'destination_module' => 'block', + ], + 'd7_block' => [ + 'source_module' => 'block', + 'destination_module' => 'block', + ], + 'block_content_body_field' => [ + 'source_module' => 'block', + 'destination_module' => 'block_content', + ], + 'block_content_type' => [ + 'source_module' => 'block', + 'destination_module' => 'block_content', + ], + 'd6_custom_block' => [ + 'source_module' => 'block', + 'destination_module' => 'block_content', + ], + 'd7_custom_block' => [ + 'source_module' => 'block', + 'destination_module' => 'block_content', + ], + 'd6_book' => [ + 'source_module' => 'book', + 'destination_module' => 'book', + ], + 'd6_book_settings' => [ + 'source_module' => 'book', + 'destination_module' => 'book', + ], + 'd6_comment' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd6_comment_entity_display' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd6_comment_entity_form_display' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd6_comment_entity_form_display_subject' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd6_comment_field' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd6_comment_field_instance' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd6_comment_type' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd7_comment' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd7_comment_entity_display' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd7_comment_entity_form_display' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd7_comment_entity_form_display_subject' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd7_comment_field' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd7_comment_field_instance' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'd7_comment_type' => [ + 'source_module' => 'comment', + 'destination_module' => 'comment', + ], + 'contact_category' => [ + 'source_module' => 'contact', + 'destination_module' => 'contact', + ], + 'd6_contact_settings' => [ + 'source_module' => 'contact', + 'destination_module' => 'contact', + ], + 'd7_contact_settings' => [ + 'source_module' => 'contact', + 'destination_module' => 'contact', + ], + 'd6_dblog_settings' => [ + 'source_module' => 'dblog', + 'destination_module' => 'dblog', + ], + 'd7_dblog_settings' => [ + 'source_module' => 'dblog', + 'destination_module' => 'dblog', + ], + 'd6_field' => [ + 'source_module' => 'content', + 'destination_module' => 'field', + ], + 'd6_field_formatter_settings' => [ + 'source_module' => 'content', + 'destination_module' => 'field', + ], + 'd6_field_instance' => [ + 'source_module' => 'content', + 'destination_module' => 'field', + ], + 'd6_field_instance_widget_settings' => [ + 'source_module' => 'content', + 'destination_module' => 'field', + ], + 'd7_field' => [ + 'source_module' => 'field', + 'destination_module' => 'field', + ], + 'd7_field_formatter_settings' => [ + 'source_module' => 'field', + 'destination_module' => 'field', + ], + 'd7_field_instance' => [ + 'source_module' => 'field', + 'destination_module' => 'field', + ], + 'd7_field_instance_widget_settings' => [ + 'source_module' => 'field', + 'destination_module' => 'field', + ], + 'd7_view_modes' => [ + 'source_module' => 'field', + 'destination_module' => 'field', + ], + 'd6_file' => [ + 'source_module' => 'system', + 'destination_module' => 'file', + ], + 'd6_file_settings' => [ + 'source_module' => 'system', + 'destination_module' => 'file', + ], + 'd6_upload' => [ + 'source_module' => 'upload', + 'destination_module' => 'file', + ], + 'd6_upload_entity_display' => [ + 'source_module' => 'upload', + 'destination_module' => 'file', + ], + 'd6_upload_entity_form_display' => [ + 'source_module' => 'upload', + 'destination_module' => 'file', + ], + 'd6_upload_field' => [ + 'source_module' => 'upload', + 'destination_module' => 'file', + ], + 'd6_upload_field_instance' => [ + 'source_module' => 'upload', + 'destination_module' => 'file', + ], + 'd7_file' => [ + 'source_module' => 'file', + 'destination_module' => 'file', + ], + 'd6_filter_format' => [ + 'source_module' => 'filter', + 'destination_module' => 'filter', + ], + 'd7_filter_format' => [ + 'source_module' => 'filter', + 'destination_module' => 'filter', + ], + 'd6_forum_settings' => [ + 'source_module' => 'forum', + 'destination_module' => 'forum', + ], + 'd7_forum_settings' => [ + 'source_module' => 'forum', + 'destination_module' => 'forum', + ], + 'd6_imagecache_presets' => [ + 'source_module' => 'imagecache', + 'destination_module' => 'image', + ], + 'd7_image_settings' => [ + 'source_module' => 'image', + 'destination_module' => 'image', + ], + 'd7_image_styles' => [ + 'source_module' => 'image', + 'destination_module' => 'image', + ], + 'd7_language_negotiation_settings' => [ + 'source_module' => 'locale', + 'destination_module' => 'language', + ], + 'language' => [ + 'source_module' => 'locale', + 'destination_module' => 'language', + ], + 'locale_settings' => [ + 'source_module' => 'locale', + 'destination_module' => 'locale', + ], + 'd6_menu_links' => [ + 'source_module' => 'menu', + 'destination_module' => 'menu_link_content', + ], + 'd7_menu_links' => [ + 'source_module' => 'menu', + 'destination_module' => 'menu_link_content', + ], + 'menu_settings' => [ + 'source_module' => 'menu', + 'destination_module' => 'menu_ui', + ], + 'd6_node' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_node_revision' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_node_setting_promote' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_node_setting_status' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_node_setting_sticky' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_node_settings' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_node_type' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_view_modes' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd7_node' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd7_node_revision' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd7_node_settings' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd7_node_title_label' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd7_node_type' => [ + 'source_module' => 'node', + 'destination_module' => 'node', + ], + 'd6_url_alias' => [ + 'source_module' => 'path', + 'destination_module' => 'path', + ], + 'd7_url_alias' => [ + 'source_module' => 'path', + 'destination_module' => 'path', + ], + 'search_page' => [ + 'source_module' => 'search', + 'destination_module' => 'search', + ], + 'd6_search_settings' => [ + 'source_module' => 'search', + 'destination_module' => 'search', + ], + 'd7_search_settings' => [ + 'source_module' => 'search', + 'destination_module' => 'search', + ], + 'd7_shortcut' => [ + 'source_module' => 'shortcut', + 'destination_module' => 'shortcut', + ], + 'd7_shortcut_set' => [ + 'source_module' => 'shortcut', + 'destination_module' => 'shortcut', + ], + 'd7_shortcut_set_users' => [ + 'source_module' => 'shortcut', + 'destination_module' => 'shortcut', + ], + 'd6_simpletest_settings' => [ + 'source_module' => 'simpletest', + 'destination_module' => 'simpletest', + ], + 'd7_simpletest_settings' => [ + 'source_module' => 'simpletest', + 'destination_module' => 'simpletest', + ], + 'd6_statistics_settings' => [ + 'source_module' => 'statistics', + 'destination_module' => 'statistics', + ], + 'd6_syslog_settings' => [ + 'source_module' => 'syslog', + 'destination_module' => 'syslog', + ], + 'd7_syslog_settings' => [ + 'source_module' => 'syslog', + 'destination_module' => 'syslog', + ], + 'd6_date_formats' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_cron' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_date' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_file' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_image' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_image_gd' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_logging' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_maintenance' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_performance' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_rss' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'd6_system_site' => [ + 'source_module' => 'system', + 'destination_module' => 'system', + ], + 'menu' => [ + 'source_module' => 'menu', + 'destination_module' => 'system', + ], + 'taxonomy_settings' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_taxonomy_term' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_taxonomy_vocabulary' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_term_node' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_term_node_revision' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_vocabulary_entity_display' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_vocabulary_entity_form_display' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_vocabulary_field' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd6_vocabulary_field_instance' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd7_taxonomy_term' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'd7_taxonomy_vocabulary' => [ + 'source_module' => 'taxonomy', + 'destination_module' => 'taxonomy', + ], + 'text_settings' => [ + 'source_module' => 'text', + 'destination_module' => 'text', + ], + 'd7_tracker_node' => [ + 'source_module' => 'tracker', + 'destination_module' => 'tracker', + ], + 'd7_tracker_settings' => [ + 'source_module' => 'tracker', + 'destination_module' => 'tracker', + ], + 'd7_tracker_user' => [ + 'source_module' => 'tracker', + 'destination_module' => 'tracker', + ], + 'update_settings' => [ + 'source_module' => 'update', + 'destination_module' => 'update', + ], + 'd6_profile_values' => [ + 'source_module' => 'profile', + 'destination_module' => 'user', + ], + 'd6_user' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd6_user_contact_settings' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd6_user_mail' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd6_user_picture_file' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd6_user_role' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd6_user_settings' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd7_user' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd7_user_flood' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd7_user_mail' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'd7_user_role' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'user_picture_entity_display' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'user_picture_entity_form_display' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'user_picture_field' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'user_picture_field_instance' => [ + 'source_module' => 'user', + 'destination_module' => 'user', + ], + 'user_profile_entity_display' => [ + 'source_module' => 'profile', + 'destination_module' => 'user', + ], + 'user_profile_entity_form_display' => [ + 'source_module' => 'profile', + 'destination_module' => 'user', + ], + 'user_profile_field' => [ + 'source_module' => 'profile', + 'destination_module' => 'user', + ], + 'user_profile_field_instance' => [ + 'source_module' => 'profile', + 'destination_module' => 'user', + ], + ]; + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'drupal_upgrade_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $step = $form_state->getValue('step', 'overview'); + switch ($step) { + case 'overview': + return $this->buildOverviewForm($form, $form_state); + case 'credentials': + return $this->buildCredentialForm($form, $form_state); + case 'confirm': + return $this->buildConfirmForm($form, $form_state); + default: + drupal_set_message($this->t('Unrecognized form step @step', + ['@step' => $step]), 'error'); + return []; + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) {} + + /** + * Build 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('Drupal Upgrade'); + + if ($date_performed = \Drupal::state()->get('drupal_upgrade.performed')) { + $form['upgrade_option_item'] = [ + '#type' => 'item', + '#prefix' => t('An upgrade has already been performed on this site.
'), + '#description' => t('Last upgrade: @date
', + ['@date' => \Drupal::service('date.formatter')->format($date_performed)]), + ]; + $form['upgrade_option'] = array( + '#type' => 'radios', + '#title' => $this->t('You have two options:'), + '#default_value' => static::MIGRATE_UPGRADE_INCREMENTAL, + '#options' => [ + static::MIGRATE_UPGRADE_INCREMENTAL => $this->t('Rerun: Import additional configuration and content that was not available when running the upgrade previously.'), + static::MIGRATE_UPGRADE_ROLLBACK => $this->t('Rollback: Remove content and configuration entities (such as fields and node types). Default values of other configuration will not be reverted (such as site name).'), + ], + ); + $validate = ['::validateCredentialForm']; + } + else { + $form['info_header'] = [ + '#markup' => '' . $this->t('Upgrade a Drupal site by importing it into a clean and empty new install of Drupal 8. You will lose any existing configuration once you import your site into it. See the upgrading handbook for more detailed information.', [ + ':url' => 'https://www.drupal.org/upgrade/migrate' + ]), + ]; + + $info[] = $this->t('Back up the database for this site. Upgrade will change the database for this site.'); + $info[] = $this->t('Make sure that the host this site is on has access to the database for your previous site.'); + $info[] = $this->t('If your previous site has private files to be migrated, a copy of your files directory must be accessible on the host this site is on.'); + $info[] = $this->t('In general, enable all modules on this site that are enabled on the previous site. For example, if you have used the book module on the previous site then you must enable the book module on this site for that data to be available on this site.'); + $info[] = $this->t('Put this site into maintenance mode.', [ + ':url' => Url::fromRoute('system.site_maintenance_mode') + ->toString(TRUE) + ->getGeneratedUrl(), + ]); + + $form['info'] = [ + '#theme' => 'item_list', + '#list_type' => 'ol', + '#items' => $info, + ]; + + $form['info_footer'] = [ + '#markup' => '
' . $this->t('This upgrade can take a long time. It is better to import a local copy of your site instead of directly importing 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; + } + + /** + * Overview form submission handler. + * + * @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) { + switch ($form_state->getValue('upgrade_option')) { + case static::MIGRATE_UPGRADE_INCREMENTAL: + $form_state->setValue('step', 'confirm'); + break; + case static::MIGRATE_UPGRADE_ROLLBACK: + $form_state->setValue('step', 'confirm'); + break; + default: + $form_state->setValue('step', 'credentials'); + break; + } + $form_state->setRebuild(); + } + + /** + * Build the form gathering database credential and file location information. + * This is largely borrowed from 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. + */ + public function buildCredentialForm(array $form, FormStateInterface $form_state) { + // Make sure the install API is available. + include_once DRUPAL_ROOT . '/core/includes/install.inc'; + + $form['#title'] = $this->t('Drupal Upgrade'); + + $drivers = drupal_get_database_types(); + $drivers_keys = array_keys($drivers); + $default_driver = current($drivers_keys); + $default_options = []; + + $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); + $form['database']['settings'][$key]['#prefix'] = '
Upgrade analysis report
'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Perform upgrade'); + } + + /** + * {@inheritdoc} + */ + public function getCancelText() { + return $this->t('Cancel'); + } + + /** + * {@inheritdoc} + */ + public function getFormName() { + return 'confirm'; + } + +} diff --git a/core/modules/drupal_upgrade/src/MigrateMessageCapture.php b/core/modules/drupal_upgrade/src/MigrateMessageCapture.php new file mode 100644 index 0000000..11df8b4 --- /dev/null +++ b/core/modules/drupal_upgrade/src/MigrateMessageCapture.php @@ -0,0 +1,48 @@ +messages[] = $message; + } + + /** + * Clear out any captured messages. + */ + public function clear() { + $this->messages = []; + } + + /** + * Return any captured messages. + * + * @return array + */ + public function getMessages() { + return $this->messages; + } + +} diff --git a/core/modules/drupal_upgrade/src/MigrateUpgradeRunBatch.php b/core/modules/drupal_upgrade/src/MigrateUpgradeRunBatch.php new file mode 100644 index 0000000..6894afc --- /dev/null +++ b/core/modules/drupal_upgrade/src/MigrateUpgradeRunBatch.php @@ -0,0 +1,360 @@ +addListener(MigrateEvents::POST_ROW_SAVE, + [get_class(), 'onPostRowSave']); + \Drupal::service('event_dispatcher')->addListener(MigrateEvents::MAP_SAVE, + [get_class(), 'onMapSave']); + \Drupal::service('event_dispatcher')->addListener(MigrateEvents::IDMAP_MESSAGE, + [get_class(), 'onIdMapMessage']); + } + else { + \Drupal::service('event_dispatcher')->addListener(MigrateEvents::POST_ROW_DELETE, + [get_class(), 'onPostRowDelete']); + \Drupal::service('event_dispatcher')->addListener(MigrateEvents::MAP_DELETE, + [get_class(), 'onMapDelete']); + } + static::$maxExecTime = ini_get('max_execution_time'); + if (static::$maxExecTime <= 0) { + static::$maxExecTime = 60; + } + // Set an arbitrary threshold of 3 seconds (e.g., if max_execution_time is + // 45 seconds, we will quit at 42 seconds so a slow item or cleanup + // overhead don't put us over 45). + static::$maxExecTime -= 3; + static::$listenersAdded = TRUE; + } + if (!isset($context['sandbox']['migration_ids'])) { + $context['sandbox']['max'] = count($initial_ids); + $context['sandbox']['current'] = 1; + // Total number processed for this migration. + $context['sandbox']['num_processed'] = 0; + // migration_ids will be the list of IDs remaining to run. + $context['sandbox']['migration_ids'] = $initial_ids; + $context['sandbox']['messages'] = []; + $context['results']['failures'] = 0; + $context['results']['successes'] = 0; + $context['results']['operation'] = $operation; + } + + // Number processed in this batch. + static::$numProcessed = 0; + + $migration_id = reset($context['sandbox']['migration_ids']); + /** @var \Drupal\migrate\Entity\Migration $migration */ + $migration = Migration::load($migration_id); + if ($migration) { + static::$messages = new MigrateMessageCapture(); + $executable = new MigrateExecutable($migration, static::$messages); + + $migration_name = $migration->label() ? $migration->label() : $migration_id; + + try { + if ($operation == 'import') { + $migration_status = $executable->import(); + } + else { + $migration_status = $executable->rollback(); + } + } + catch (\Exception $e) { + static::logger()->error($e->getMessage()); + $migration_status = MigrationInterface::RESULT_FAILED; + } + + switch ($migration_status) { + case MigrationInterface::RESULT_COMPLETED: + if ($operation == 'import') { + $singular_message = 'Upgraded @migration (processed 1 item total)'; + $plural_message = 'Upgraded @migration (processed @num_processed items total)'; + } + else { + $singular_message = 'Rolled back @migration (processed 1 item total)'; + $plural_message = 'Rolled back @migration (processed @num_processed items total)'; + $migration->delete(); + } + // Store the number processed in the sandbox. + $context['sandbox']['num_processed'] += static::$numProcessed; + $message = \Drupal::translation()->formatPlural( + $context['sandbox']['num_processed'], $singular_message, $plural_message, + ['@migration' => $migration_name, '@num_processed' => $context['sandbox']['num_processed']]); + $context['sandbox']['messages'][] = $message; + static::logger()->notice($message); + $context['sandbox']['num_processed'] = 0; + $context['results']['successes']++; + break; + + case MigrationInterface::RESULT_INCOMPLETE: + $singular_message = 'Continuing with @migration (processed 1 item)'; + $plural_message = 'Continuing with @migration (processed @num_processed items)'; + $context['sandbox']['messages'][] = \Drupal::translation()->formatPlural( + static::$numProcessed, $singular_message, $plural_message, + ['@migration' => $migration_name, '@num_processed' => static::$numProcessed]); + $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'][] = t('Operation on @migration skipped due to unfulfilled dependencies', ['@migration' => $migration_name]); + static::logger()->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; + static::logger()->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]. "