diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalUpgradeForm.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalUpgradeForm.php
new file mode 100644
index 0000000..e7570fb
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalUpgradeForm.php
@@ -0,0 +1,218 @@
+ $this->t('Enter the database credentials for the legacy Drupal ' .
+ 'site you are upgrading into this Drupal 8 instance.'),
+ );
+ // The following is stolen from install.core.inc. If the install process
+ // would use form classes (https://drupal.org/node/2112569), we could inherit.
+ global $databases;
+
+ $database = isset($databases['default']['default']) ? $databases['default']['default'] : array();
+
+ drupal_set_title(t('Database configuration'));
+
+ require_once DRUPAL_ROOT . '/core/includes/install.inc';
+ $drivers = drupal_get_database_types();
+ $drivers_keys = array_keys($drivers);
+
+ $form['driver'] = array(
+ '#type' => 'radios',
+ '#title' => t('Database type'),
+ '#required' => TRUE,
+ '#default_value' => !empty($database['driver']) ? $database['driver'] : current($drivers_keys),
+ );
+ if (count($drivers) == 1) {
+ $form['driver']['#disabled'] = TRUE;
+ }
+
+ // Add driver specific configuration options.
+ foreach ($drivers as $key => $driver) {
+ $form['driver']['#options'][$key] = $driver->name();
+
+ $form['settings'][$key] = $driver->getFormOptions($database);
+ $form['settings'][$key]['#prefix'] = '
' .
+ $this->t('@driver_name settings', array('@driver_name' => $driver->name())) . '
';
+ $form['settings'][$key]['#type'] = 'container';
+ $form['settings'][$key]['#tree'] = TRUE;
+ $form['settings'][$key]['advanced_options']['#parents'] = array($key);
+ $form['settings'][$key]['#states'] = array(
+ 'visible' => array(
+ ':input[name=driver]' => array('value' => $key),
+ )
+ );
+ }
+
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['save'] = array(
+ '#type' => 'submit',
+ '#value' => t('Next'),
+ '#button_type' => 'primary',
+ '#limit_validation_errors' => array(
+ array('driver'),
+ array(isset($form_state['input']['driver']) ? $form_state['input']['driver'] : current($drivers_keys)),
+ ),
+ );
+ }
+ elseif (isset($form_state['step']) && $form_state['step'] == 'confirmation') {
+ Database::addConnectionInfo('migrate', 'default', $form_state['database']);
+ $version = $form_state['drupal_version'];
+ $form['description'] = array(
+ '#markup' => $this->t('We are importing from a site running Drupal version @version.',
+ array('@version' => $version)),
+ );
+ $migrations = $this->storageController()->loadMultiple();
+ // For now, identify the relevant migrations based on prefix.
+ $prefix = 'd' . $version . '_';
+ $options = array();
+ foreach (array_keys($migrations) as $machine_name) {
+ if (!strncmp($prefix, $machine_name, strlen($prefix))) {
+ $options[$machine_name] = $machine_name;
+ }
+ }
+ $form['migrations'] = array(
+ '#type' => 'checkboxes',
+ '#options' => $options,
+ );
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => $this->t('Submit'),
+ );
+ }
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, array &$form_state) {
+ if (isset($form_state['values']['driver'])) {
+ // Verify we have a valid connection to a Drupal database supported for
+ // upgrade.
+ $driver = $form_state['values']['driver'];
+ $form_state['database'] = $form_state['values'][$driver];
+ $form_state['database']['driver'] = $driver;
+ // @todo: There should be a DrupalSqlBase class to use to determine the
+ // version.
+ try {
+ Database::addConnectionInfo('migrate', 'default', $form_state['database']);
+ $connection = Database::getConnection('default', 'migrate');
+ }
+ catch (\Exception $e) {
+ $message = t('Unable to connect to the source database. %message',
+ array('%message' => $e->getMessage()));
+ $this->setFormError(NULL, $form_state, $message);
+ return;
+ }
+ if (!$connection->schema()->tableExists('node')) {
+ $this->setFormError(NULL, $form_state, t('Source database does not ' .
+ 'contain a Drupal installation.'));
+ }
+ // Note we check D8 first, because it's reintroduced the menu_router
+ // table we have used as the signature of D6.
+ elseif ($connection->schema()->tableExists('key_value')) {
+ $this->setFormError(NULL, $form_state, t('Upgrade from this version ' .
+ 'of Drupal is not supported.'));
+ }
+ elseif ($connection->schema()->tableExists('filter_format')) {
+ $form_state['drupal_version'] = 7;
+ }
+ elseif ($connection->schema()->tableExists('menu_router')) {
+ $form_state['drupal_version'] = 6;
+ }
+ else {
+ $this->setFormError(NULL, $form_state, t('Upgrade from this version ' .
+ 'of Drupal is not supported.'));
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, array &$form_state) {
+ if (isset($form_state['values']['driver'])) {
+ $form_state['rebuild'] = TRUE;
+ $form_state['step'] = 'confirmation';
+ }
+ elseif ($form_state['step'] == 'confirmation') {
+ $migration_ids = array_keys(array_filter($form_state['values']['migrations']));
+ $batch = array(
+ 'title' => t('Running migrations'),
+ 'operations' => array(
+ array(array('Drupal\migrate_drupal\MigrateDrupalRunBatch', 'run'), array($migration_ids, $form_state['database'])),
+ ),
+ 'finished' => array('Drupal\migrate_drupal\MigrateDrupalRunBatch', 'finished'),
+ 'progress_message' => '',
+ 'init_message' => t('Processing migration @num of @max.', array('@num' => '1', '@max' => count($migration_ids))),
+ );
+ $this->batchSet($batch);
+ }
+ }
+
+ /**
+ * Set a batch.
+ *
+ * @param $batch
+ */
+ protected function batchSet($batch) {
+ batch_set($batch);
+ }
+
+ /**
+ * @return EntityStorageControllerInterface
+ */
+ protected function storageController() {
+ if (!isset($this->storageController)) {
+ $this->storageController = \Drupal::entityManager()->getStorageController('migration');
+ }
+ return $this->storageController;
+ }
+
+ /**
+ * Returns the properties to be serialized
+ *
+ * @return array
+ */
+ public function __sleep() {
+ // This apparently contains a PDOStatement somewhere.
+ unset($this->storageController);
+ return parent::__sleep();
+ }
+}
diff --git a/core/modules/migrate_drupal/migrate_drupal.routing.yml b/core/modules/migrate_drupal/migrate_drupal.routing.yml
index a7e8fef..73f5b20 100644
--- a/core/modules/migrate_drupal/migrate_drupal.routing.yml
+++ b/core/modules/migrate_drupal/migrate_drupal.routing.yml
@@ -5,3 +5,10 @@ migrate_drupal.run:
_title: 'Run'
requirements:
_permission: 'administer site configuration'
+migrate_drupal.upgrade:
+ path: '/upgrade'
+ defaults:
+ _form: '\Drupal\migrate_drupal\Form\MigrateDrupalUpgradeForm'
+ _title: 'Upgrade Drupal'
+ requirements:
+ _permission: 'administer site configuration'