summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Hojtsy2017-05-25 16:27:59 (GMT)
committerGabor Hojtsy2017-05-25 16:27:59 (GMT)
commit68d8cd2608ce6421f396f4a7081ec60e0c38a803 (patch)
treecea76d4c5e06896b3e6e8e800ea48ca6fa3a79ed
parent8a6aad980d338f9c2d44d5235a95468f3a31b481 (diff)
Issue #2830031 by mikeryan, heddn, phenaproxima: Fix SqlBase fallback priorities and document them
-rw-r--r--core/modules/migrate/src/Plugin/migrate/source/SqlBase.php47
-rw-r--r--core/modules/migrate/tests/src/Kernel/SqlBaseTest.php43
2 files changed, 71 insertions, 19 deletions
diff --git a/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
index 3c6d4c4..0bb72e7 100644
--- a/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
+++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
@@ -15,13 +15,37 @@ use Drupal\migrate\Plugin\RequirementsInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
- * Sources whose data may be fetched via DBTNG.
+ * Sources whose data may be fetched via a database connection.
*
- * By default, an existing database connection with key 'migrate' and target
- * 'default' is used. These may be overridden with explicit 'key' and/or
- * 'target' configuration keys. In addition, if the configuration key 'database'
- * is present, it is used as a database connection information array to define
- * the connection.
+ * Database configuration, which may appear either within the source plugin
+ * configuration or in state, is structured as follows:
+ *
+ * 'key' - The database key name (defaults to 'migrate').
+ * 'target' - The database target name (defaults to 'default').
+ * 'database' - Database connection information as accepted by
+ * Database::addConnectionInfo(). If not present, the key/target is assumed
+ * to already be defined (e.g., in settings.php).
+ *
+ * This configuration info is obtained in the following order:
+ *
+ * 1. If the source plugin configuration contains a key 'database_state_key',
+ * its value is taken as the name of a state key which contains an array
+ * with the above database configuration.
+ * 2. Otherwise, if the source plugin configuration contains 'key', the above
+ * database configuration is obtained directly from the plugin configuration.
+ * 3. Otherwise, if the state 'migrate.fallback_state_key' exists, its value is
+ * taken as the name of a state key which contains an array with the above
+ * database configuration.
+ * 4. Otherwise, if a connection named 'migrate' exists, that is used as the
+ * database connection.
+ * 5. Otherwise, RequirementsException is thrown.
+ *
+ * It is strongly recommended that database connections be explicitly defined
+ * via 'database_state_key' or in the source plugin configuration. Defining
+ * migrate.fallback_state_key or a 'migrate' connection affects not only any
+ * migrations intended to use that particular connection, but all
+ * SqlBase-derived source plugins which do not have explicit database
+ * configuration.
*/
abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPluginInterface, RequirementsInterface {
@@ -101,16 +125,21 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi
*/
public function getDatabase() {
if (!isset($this->database)) {
- // See if the database info is in state - if not, fallback to
- // configuration.
+ // Look first for an explicit state key containing the configuration.
if (isset($this->configuration['database_state_key'])) {
$this->database = $this->setUpDatabase($this->state->get($this->configuration['database_state_key']));
}
+ // Next, use explicit configuration in the source plugin.
+ elseif (isset($this->configuration['key'])) {
+ $this->database = $this->setUpDatabase($this->configuration);
+ }
+ // Next, try falling back to the global state key.
elseif (($fallback_state_key = $this->state->get('migrate.fallback_state_key'))) {
$this->database = $this->setUpDatabase($this->state->get($fallback_state_key));
}
+ // If all else fails, let setUpDatabase() fallback to the 'migrate' key.
else {
- $this->database = $this->setUpDatabase($this->configuration);
+ $this->database = $this->setUpDatabase([]);
}
}
return $this->database;
diff --git a/core/modules/migrate/tests/src/Kernel/SqlBaseTest.php b/core/modules/migrate/tests/src/Kernel/SqlBaseTest.php
index ef15bd5..faf064d 100644
--- a/core/modules/migrate/tests/src/Kernel/SqlBaseTest.php
+++ b/core/modules/migrate/tests/src/Kernel/SqlBaseTest.php
@@ -7,6 +7,7 @@
namespace Drupal\Tests\migrate\Kernel;
+use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\migrate\source\TestSqlBase;
use Drupal\Core\Database\Database;
@@ -23,11 +24,24 @@ class SqlBaseTest extends MigrateTestBase {
public function testConnectionTypes() {
$sql_base = new TestSqlBase();
- // Check the default values.
- $sql_base->setConfiguration([]);
- $this->assertIdentical($sql_base->getDatabase()->getTarget(), 'default');
- $this->assertIdentical($sql_base->getDatabase()->getKey(), 'migrate');
+ // Verify that falling back to the default 'migrate' connection (defined in
+ // the base class) works.
+ $this->assertSame($sql_base->getDatabase()->getTarget(), 'default');
+ $this->assertSame($sql_base->getDatabase()->getKey(), 'migrate');
+
+ // Verify the fallback state key overrides the 'migrate' connection.
+ $target = 'test_fallback_target';
+ $key = 'test_fallback_key';
+ $config = ['target' => $target, 'key' => $key];
+ $database_state_key = 'test_fallback_state';
+ \Drupal::state()->set($database_state_key, $config);
+ \Drupal::state()->set('migrate.fallback_state_key', $database_state_key);
+ // Create a test connection using the default database configuration.
+ Database::addConnectionInfo($key, $target, Database::getConnectionInfo('default')['default']);
+ $this->assertSame($sql_base->getDatabase()->getTarget(), $target);
+ $this->assertSame($sql_base->getDatabase()->getKey(), $key);
+ // Verify that setting explicit connection information overrides fallbacks.
$target = 'test_db_target';
$key = 'test_migrate_connection';
$config = ['target' => $target, 'key' => $key];
@@ -35,8 +49,8 @@ class SqlBaseTest extends MigrateTestBase {
Database::addConnectionInfo($key, $target, Database::getConnectionInfo('default')['default']);
// Validate we have injected our custom key and target.
- $this->assertIdentical($sql_base->getDatabase()->getTarget(), $target);
- $this->assertIdentical($sql_base->getDatabase()->getKey(), $key);
+ $this->assertSame($sql_base->getDatabase()->getTarget(), $target);
+ $this->assertSame($sql_base->getDatabase()->getKey(), $key);
// Now test we can have SqlBase create the connection from an info array.
$sql_base = new TestSqlBase();
@@ -51,7 +65,7 @@ class SqlBaseTest extends MigrateTestBase {
$sql_base->getDatabase();
// Validate the connection has been created with the right values.
- $this->assertIdentical(Database::getConnectionInfo($key)[$target], $database);
+ $this->assertSame(Database::getConnectionInfo($key)[$target], $database);
// Now, test this all works when using state to store db info.
$target = 'test_state_db_target';
@@ -63,8 +77,8 @@ class SqlBaseTest extends MigrateTestBase {
Database::addConnectionInfo($key, $target, Database::getConnectionInfo('default')['default']);
// Validate we have injected our custom key and target.
- $this->assertIdentical($sql_base->getDatabase()->getTarget(), $target);
- $this->assertIdentical($sql_base->getDatabase()->getKey(), $key);
+ $this->assertSame($sql_base->getDatabase()->getTarget(), $target);
+ $this->assertSame($sql_base->getDatabase()->getKey(), $key);
// Now test we can have SqlBase create the connection from an info array.
$sql_base = new TestSqlBase();
@@ -81,7 +95,16 @@ class SqlBaseTest extends MigrateTestBase {
$sql_base->getDatabase();
// Validate the connection has been created with the right values.
- $this->assertIdentical(Database::getConnectionInfo($key)[$target], $database);
+ $this->assertSame(Database::getConnectionInfo($key)[$target], $database);
+
+ // Verify that falling back to 'migrate' when the connection is not defined
+ // throws a RequirementsException.
+ \Drupal::state()->delete('migrate.fallback_state_key');
+ $sql_base->setConfiguration([]);
+ Database::renameConnection('migrate', 'fallback_connection');
+ $this->setExpectedException(RequirementsException::class,
+ 'No database connection configured for source plugin');
+ $sql_base->getDatabase();
}
}