diff --git a/core/assets/scaffold/files/default.settings.php b/core/assets/scaffold/files/default.settings.php
index 5784a9c7523..ee3b49c0a8d 100644
--- a/core/assets/scaffold/files/default.settings.php
+++ b/core/assets/scaffold/files/default.settings.php
@@ -765,6 +765,49 @@ $settings['entity_update_backup'] = TRUE;
*/
$settings['migrate_node_migrate_type_classic'] = FALSE;
+/**
+ * The default settings for migration sources.
+ *
+ * These settings are used as the default settings on the Credential form at
+ * /upgrade/credentials.
+ *
+ * - migrate_source_version - The version of the source database. This can be
+ * '6' or '7'. Defaults to '7'.
+ * - migrate_source_connection - The key in the $databases array for the source
+ * site.
+ * - migrate_file_public_path - The location of the source Drupal 6 or Drupal 7
+ * public files. This can be a local file directory containing the source
+ * Drupal 6 or Drupal 7 site (e.g /var/www/docroot), or the site address
+ * (e.g http://example.com).
+ * - migrate_file_private_path - The location of the source Drupal 7 private
+ * files. This can be a local file directory containing the source Drupal 7
+ * site (e.g /var/www/docroot), or empty to use the same value as Public
+ * files directory.
+ *
+ * Sample configuration for a drupal 6 source site with the source files in a
+ * local directory.
+ *
+ * @code
+ * $settings['migrate_source_version'] = '6';
+ * $settings['migrate_source_connection'] = 'migrate';
+ * $settings['migrate_file_public_path'] = '/var/www/drupal6';
+ * @endcode
+ *
+ * Sample configuration for a drupal 7 source site with public source files on
+ * the source site and the private files in a local directory.
+ *
+ * @code
+ * $settings['migrate_source_version'] = '7';
+ * $settings['migrate_source_connection'] = 'migrate';
+ * $settings['migrate_file_public_path'] = 'https://drupal7.com';
+ * $settings['migrate_file_private_path'] = '/var/www/drupal7';
+ * @endcode
+ */
+# $settings['migrate_source_connection'] = '';
+# $settings['migrate_source_version'] = '';
+# $settings['migrate_file_public_path'] = '';
+# $settings['migrate_file_private_path'] = '';
+
/**
* Load local development override configuration, if available.
*
diff --git a/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php b/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php
index 8900a507684..87e57604bb8 100644
--- a/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php
@@ -5,8 +5,10 @@ namespace Drupal\migrate_drupal_ui\Form;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\Database;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\State\StateInterface;
+use Drupal\Core\Site\Settings;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\Exception\BadPluginDefinitionException;
@@ -99,19 +101,42 @@ class CredentialForm extends MigrateUpgradeFormBase {
'#description' => $this->t('Provide the information to access the Drupal site you want to upgrade. Files can be imported into the upgraded site as well. See the Upgrade documentation for more detailed instructions.', [':url' => 'https://www.drupal.org/upgrade/migrate']),
];
+ $migrate_source_version = Settings::get('migrate_source_version') == '6' ? '6' : '7';
$form['version'] = [
'#type' => 'radios',
- '#default_value' => 7,
+ '#default_value' => $migrate_source_version,
'#title' => $this->t('Drupal version of the source site'),
'#options' => ['6' => $this->t('Drupal 6'), '7' => $this->t('Drupal 7')],
'#required' => TRUE,
];
+ $available_connections = array_diff(array_keys(Database::getAllConnectionInfo()), ['default']);
+ $options = array_combine($available_connections, $available_connections);
+ $migrate_source_connection = Settings::get('migrate_source_connection');
+ $preferred_connections = $migrate_source_connection
+ ? ['migrate', $migrate_source_connection]
+ : ['migrate'];
+ $default_options = array_intersect($preferred_connections, $available_connections);
+ $form['source_connection'] = [
+ '#type' => 'select',
+ '#title' => $this->t('Source connection'),
+ '#options' => $options,
+ '#default_value' => array_pop($default_options),
+ '#empty_option' => $this->t('- User defined -'),
+ '#description' => $this->t('Choose one of the keys from the $databases array or else select "User defined" and enter database credentials.'),
+ '#access' => !empty($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,
+ '#states' => [
+ 'visible' => [
+ ':input[name=source_connection]' => ['value' => ''],
+ ],
+ ],
];
$form['database']['driver'] = [
@@ -119,6 +144,11 @@ class CredentialForm extends MigrateUpgradeFormBase {
'#title' => $this->t('Database type'),
'#required' => TRUE,
'#default_value' => $default_driver,
+ '#states' => [
+ 'required' => [
+ ':input[name=source_connection]' => ['value' => ''],
+ ],
+ ],
];
if (count($drivers) == 1) {
$form['database']['driver']['#disabled'] = TRUE;
@@ -136,6 +166,27 @@ class CredentialForm extends MigrateUpgradeFormBase {
// for mysql and pgsql must not be required.
$form['database']['settings'][$key]['database']['#required'] = FALSE;
$form['database']['settings'][$key]['username']['#required'] = FALSE;
+ $form['database']['settings'][$key]['database']['#states'] = [
+ 'required' => [
+ ':input[name=source_connection]' => ['value' => ''],
+ ':input[name=driver]' => ['value' => $key],
+ ],
+ ];
+ if ($key != 'sqlite') {
+ $form['database']['settings'][$key]['username']['#states'] = [
+ 'required' => [
+ ':input[name=source_connection]' => ['value' => ''],
+ ':input[name=driver]' => ['value' => $key],
+ ],
+ ];
+ $form['database']['settings'][$key]['password']['#states'] = [
+ 'required' => [
+ ':input[name=source_connection]' => ['value' => ''],
+ ':input[name=driver]' => ['value' => $key],
+ ],
+ ];
+ }
+
$form['database']['settings'][$key]['#prefix'] = '
' . $this->t('@driver_name settings', ['@driver_name' => $driver->name()]) . '
';
$form['database']['settings'][$key]['#type'] = 'container';
$form['database']['settings'][$key]['#tree'] = TRUE;
@@ -164,6 +215,7 @@ class CredentialForm extends MigrateUpgradeFormBase {
$form['source']['d6_source_base_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Document root for files'),
+ '#default_value' => Settings::get('migrate_file_public_path') ?? '',
'#description' => $this->t('To import files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot), or your site address (for example http://example.com).'),
'#states' => [
'visible' => [
@@ -176,6 +228,7 @@ class CredentialForm extends MigrateUpgradeFormBase {
$form['source']['source_base_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Document root for public files'),
+ '#default_value' => Settings::get('migrate_file_public_path') ?? '',
'#description' => $this->t('To import public files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot), or your site address (for example http://example.com).'),
'#states' => [
'visible' => [
@@ -188,7 +241,7 @@ class CredentialForm extends MigrateUpgradeFormBase {
$form['source']['source_private_file_path'] = [
'#type' => 'textfield',
'#title' => $this->t('Document root for private files'),
- '#default_value' => '',
+ '#default_value' => Settings::get('migrate_file_private_path') ?? '',
'#description' => $this->t('To import private files from your current Drupal site, enter a local file directory containing your site (e.g. /var/www/docroot). Leave blank to use the same value as Public files directory.'),
'#states' => [
'visible' => [
@@ -205,29 +258,36 @@ class CredentialForm extends MigrateUpgradeFormBase {
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
- // Retrieve the database driver from the form, use reflection to get the
- // namespace, and then construct a valid database array the same as in
- // settings.php.
- $driver = $form_state->getValue('driver');
- $drivers = $this->getDatabaseTypes();
- $reflection = new \ReflectionClass($drivers[$driver]);
- $install_namespace = $reflection->getNamespaceName();
+ $source_connection = $form_state->getValue('source_connection');
+ if ($source_connection) {
+ $info = Database::getConnectionInfo($source_connection);
+ $database = reset($info);
+ }
+ else {
+ // Retrieve the database driver from the form, use reflection to get the
+ // namespace, and then construct a valid database array the same as in
+ // settings.php.
+ $driver = $form_state->getValue('driver');
+ $drivers = $this->getDatabaseTypes();
+ $reflection = new \ReflectionClass($drivers[$driver]);
+ $install_namespace = $reflection->getNamespaceName();
- $database = $form_state->getValue($driver);
- // Cut the trailing \Install from namespace.
- $database['namespace'] = substr($install_namespace, 0, strrpos($install_namespace, '\\'));
- $database['driver'] = $driver;
+ $database = $form_state->getValue($driver);
+ // Cut the trailing \Install from namespace.
+ $database['namespace'] = substr($install_namespace, 0, strrpos($install_namespace, '\\'));
+ $database['driver'] = $driver;
- // Validate the driver settings and just end here if we have any issues.
- $connection = NULL;
- $error_key = $database['driver'] . '][database';
- if ($errors = $drivers[$driver]->validateDatabaseSettings($database)) {
- foreach ($errors as $name => $message) {
- $this->errors[$name] = $message;
+ // Validate the driver settings and just end here if we have any issues.
+ $connection = NULL;
+ if ($errors = $drivers[$driver]->validateDatabaseSettings($database)) {
+ foreach ($errors as $name => $message) {
+ $this->errors[$name] = $message;
+ }
}
}
// Get the Drupal version of the source database so it can be validated.
+ $error_key = $database['driver'] . '][database';
if (!$this->errors) {
try {
$connection = $this->getConnection($database);
@@ -283,6 +343,17 @@ class CredentialForm extends MigrateUpgradeFormBase {
* Ensures that entered path can be read.
*/
public function validatePaths($element, FormStateInterface $form_state) {
+ $version = $form_state->getValue('version');
+ // Only validate the paths relevant to the legacy Drupal version.
+ if (($version !== '7')
+ && ($element['#name'] == 'source_base_path' || $element['#name'] == 'source_private_file_path')) {
+ return;
+ }
+
+ if ($version !== '6' && ($element['#name'] == 'd6_source_base_path')) {
+ return;
+ }
+
if ($source = $element['#value']) {
$msg = $this->t('Failed to read from @title.', ['@title' => $element['#title']]);
if (UrlHelper::isExternal($source)) {
diff --git a/core/modules/migrate_drupal_ui/tests/src/FunctionalJavascript/SettingsTest.php b/core/modules/migrate_drupal_ui/tests/src/FunctionalJavascript/SettingsTest.php
new file mode 100644
index 00000000000..776f115f7a6
--- /dev/null
+++ b/core/modules/migrate_drupal_ui/tests/src/FunctionalJavascript/SettingsTest.php
@@ -0,0 +1,274 @@
+drupalLogin($this->rootUser);
+ }
+
+ /**
+ * Test the Credential form with defaults in settings.php.
+ *
+ * @param string|null $source_connection
+ * The value for the source_connection select field.
+ * @param string $version
+ * The legacy Drupal version.
+ * @param string[] $manual
+ * User entered form values.
+ * @param string[] $databases
+ * Databases data or the settings array.
+ * @param string $expected_source_connection
+ * The expected source database connection key.
+ *
+ * @throws \Behat\Mink\Exception\ElementNotFoundException
+ * @throws \Behat\Mink\Exception\ExpectationException
+ *
+ * @dataProvider providerTestCredentialForm
+ */
+ public function testCredentialForm($source_connection, $version, array $manual, array $databases, $expected_source_connection) {
+ // Write settings.
+ $migrate_file_public_path = '/var/www/drupal7/sites/default/files';
+ $migrate_file_private_path = '/var/www/drupal7/sites/default/files/private';
+ $settings['settings']['migrate_source_version'] = (object) [
+ 'value' => $version,
+ 'required' => TRUE,
+ ];
+ $settings['settings']['migrate_source_connection'] = (object) [
+ 'value' => $source_connection,
+ 'required' => TRUE,
+ ];
+ $settings['settings']['migrate_file_public_path'] = (object) [
+ 'value' => $migrate_file_public_path,
+ 'required' => TRUE,
+ ];
+ $settings['settings']['migrate_file_private_path'] = (object) [
+ 'value' => $migrate_file_private_path,
+ 'required' => TRUE,
+ ];
+ foreach ($databases as $key => $value) {
+ $settings['databases'][$key]['default'] = (object) [
+ 'value' => $value['default'],
+ 'required' => TRUE,
+ ];
+ }
+ $this->writeSettings($settings);
+
+ $edits = [];
+ // Enter the values manually if provided.
+ if (!empty($manual)) {
+ $edit = [];
+ $driver = 'mysql';
+ $edit[$driver]['host'] = $manual['host'];
+ $edit[$driver]['database'] = $manual['database'];
+ $edit[$driver]['username'] = $manual['username'];
+ $edit[$driver]['password'] = $manual['password'];
+ $edits = $this->translatePostValues($edit);
+ }
+
+ // Start the upgrade process.
+ $this->drupalGet('/upgrade');
+ $this->submitForm([], 'Continue');
+ $session = $this->assertSession();
+ // The source connection field is only displayed when there are connections
+ // other than default.
+ if (empty($databases)) {
+ $session->fieldNotExists('source_connection');
+ }
+ else {
+ $session->fieldExists('source_connection');
+ }
+
+ // Submit the Credential form.
+ $this->submitForm($edits, 'Review upgrade');
+
+ // Confirm that the form actually submitted. IF it submitted, we should see
+ // error messages about reading files. If there is no error message, that
+ // indicates that the form did not submit.
+ $session->responseContains('Failed to read from Document root');
+
+ // Assert the form values.
+ $session->fieldValueEquals('version', $version);
+
+ // Check the manually entered credentials or simply the database key.
+ if (empty($manual)) {
+ $session->fieldValueEquals('source_connection', $expected_source_connection);
+ }
+ else {
+ $session->fieldValueEquals('mysql[host]', $manual['host']);
+ $session->fieldValueEquals('mysql[database]', $manual['database']);
+ $session->fieldValueEquals('mysql[username]', $manual['username']);
+ }
+
+ // Confirm the file paths are correct.
+ $session->fieldValueEquals('d6_source_base_path', $migrate_file_public_path);
+ $session->fieldValueEquals('source_base_path', $migrate_file_public_path);
+ $session->fieldValueEquals('source_private_file_path', $migrate_file_private_path);
+ }
+
+ /**
+ * Data provider for testCredentialForm.
+ */
+ public function providerTestCredentialForm() {
+ return [
+ 'no values in settings.php' => [
+ 'source_connection' => "",
+ 'version' => '7',
+ 'manual' => [
+ 'host' => '172.18.0.2',
+ 'database' => 'drupal7',
+ 'username' => 'kate',
+ 'password' => 'pwd',
+ ],
+ 'databases' => [],
+ 'expected_source_connection' => '',
+ ],
+ 'single database in settings, migrate' => [
+ 'source_connection' => 'migrate',
+ 'version' => '7',
+ 'manual' => [],
+ 'databases' => [
+ 'migrate' => [
+ 'default' => [
+ 'database' => 'drupal7',
+ 'username' => 'user',
+ 'password' => 'pwd',
+ 'prefix' => 'test',
+ 'host' => '172.18.0.3',
+ 'port' => '3307',
+ 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
+ 'driver' => 'mysql',
+ ],
+ ],
+ ],
+ 'expected_source_connection' => 'migrate',
+ ],
+ 'migrate_source_connection not set' => [
+ 'source_connection' => '',
+ 'version' => '7',
+ 'manual' => [],
+ 'databases' => [
+ 'migrate' => [
+ 'default' => [
+ 'database' => 'drupal7',
+ 'username' => 'user',
+ 'password' => 'pwd',
+ 'prefix' => 'test',
+ 'host' => '172.18.0.3',
+ 'port' => '3307',
+ 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
+ 'driver' => 'mysql',
+ ],
+ ],
+ ],
+ 'expected_source_connection' => 'migrate',
+ ],
+ 'single database in settings, legacy' => [
+ 'source_connection' => 'legacy',
+ 'version' => '6',
+ 'manual' => [],
+ 'databases' => [
+ 'legacy' => [
+ 'default' => [
+ 'database' => 'drupal6',
+ 'username' => 'user',
+ 'password' => 'pwd',
+ 'prefix' => 'test',
+ 'host' => '172.18.0.6',
+ 'port' => '3307',
+ 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
+ 'driver' => 'mysql',
+ ],
+ ],
+ ],
+ 'expected_source_connection' => 'legacy',
+ ],
+ 'two databases in settings' => [
+ 'source_connection' => 'source2',
+ 'version' => '7',
+ 'manual' => [],
+ 'databases' => [
+ 'migrate' => [
+ 'default' => [
+ 'database' => 'drupal7',
+ 'username' => 'user',
+ 'password' => 'pwd',
+ 'prefix' => 'test',
+ 'host' => '172.18.0.3',
+ 'port' => '3307',
+ 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
+ 'driver' => 'mysql',
+ ],
+ ],
+ 'legacy' => [
+ 'default' => [
+ 'database' => 'site',
+ 'username' => 'user',
+ 'password' => 'pwd',
+ 'prefix' => 'test',
+ 'host' => '172.18.0.2',
+ 'port' => '3307',
+ 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
+ 'driver' => 'mysql',
+ ],
+ ],
+ ],
+ 'expected_source_connection' => 'migrate',
+ ],
+ 'database in settings, but use manual' => [
+ 'source_connection' => '',
+ 'version' => '7',
+ 'manual' => [
+ 'host' => '172.18.0.2',
+ 'database' => 'drupal7',
+ 'username' => 'kate',
+ 'password' => 'pwd',
+ ],
+ 'databases' => [
+ 'legacy' => [
+ 'default' => [
+ 'database' => 'site',
+ 'username' => 'user',
+ 'password' => 'pwd',
+ 'prefix' => 'test',
+ 'host' => '172.18.0.2',
+ 'port' => '3307',
+ 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
+ 'driver' => 'mysql',
+ ],
+ ],
+ ],
+ 'expected_source_connection' => '',
+ ],
+ ];
+ }
+
+}
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 5784a9c7523..ee3b49c0a8d 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -765,6 +765,49 @@ $settings['entity_update_backup'] = TRUE;
*/
$settings['migrate_node_migrate_type_classic'] = FALSE;
+/**
+ * The default settings for migration sources.
+ *
+ * These settings are used as the default settings on the Credential form at
+ * /upgrade/credentials.
+ *
+ * - migrate_source_version - The version of the source database. This can be
+ * '6' or '7'. Defaults to '7'.
+ * - migrate_source_connection - The key in the $databases array for the source
+ * site.
+ * - migrate_file_public_path - The location of the source Drupal 6 or Drupal 7
+ * public files. This can be a local file directory containing the source
+ * Drupal 6 or Drupal 7 site (e.g /var/www/docroot), or the site address
+ * (e.g http://example.com).
+ * - migrate_file_private_path - The location of the source Drupal 7 private
+ * files. This can be a local file directory containing the source Drupal 7
+ * site (e.g /var/www/docroot), or empty to use the same value as Public
+ * files directory.
+ *
+ * Sample configuration for a drupal 6 source site with the source files in a
+ * local directory.
+ *
+ * @code
+ * $settings['migrate_source_version'] = '6';
+ * $settings['migrate_source_connection'] = 'migrate';
+ * $settings['migrate_file_public_path'] = '/var/www/drupal6';
+ * @endcode
+ *
+ * Sample configuration for a drupal 7 source site with public source files on
+ * the source site and the private files in a local directory.
+ *
+ * @code
+ * $settings['migrate_source_version'] = '7';
+ * $settings['migrate_source_connection'] = 'migrate';
+ * $settings['migrate_file_public_path'] = 'https://drupal7.com';
+ * $settings['migrate_file_private_path'] = '/var/www/drupal7';
+ * @endcode
+ */
+# $settings['migrate_source_connection'] = '';
+# $settings['migrate_source_version'] = '';
+# $settings['migrate_file_public_path'] = '';
+# $settings['migrate_file_private_path'] = '';
+
/**
* Load local development override configuration, if available.
*