Skip to content
Snippets Groups Projects
Verified Commit 3cad0ee9 authored by Dave Long's avatar Dave Long
Browse files

Issue #3312733 by benjifisher, quietone, mikelutz, smustgrave: SQL migrations...

Issue #3312733 by benjifisher, quietone, mikelutz, smustgrave: SQL migrations cannot be instantiated if database is not available and Node, Migrate Drupal modules are enabled
parent de09fc95
No related branches found
No related tags found
26 merge requests!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!4100Issue #3249600: Add support for PHP 8.1 Enums as allowed values for list_* data types,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2334Issue #3228209: Add hasRole() method to AccountInterface,!2062Issue #3246454: Add weekly granularity to views date sort,!1591Issue #3199697: Add JSON:API Translation experimental module,!1484Exposed filters get values from URL when Ajax is on,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1162Issue #3100350: Unable to save '/' root path alias,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!925Issue #2339235: Remove taxonomy hard dependency on node module,!877Issue #2708101: Default value for link text is not saved,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links,!844Resolve #3036010 "Updaters",!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
......@@ -182,20 +182,10 @@ public function getDatabase() {
* Thrown if no source database connection is configured.
*/
protected function setUpDatabase(array $database_info) {
if (isset($database_info['key'])) {
$key = $database_info['key'];
}
else {
// If there is no explicit database configuration at all, fall back to a
// connection named 'migrate'.
$key = 'migrate';
}
if (isset($database_info['target'])) {
$target = $database_info['target'];
}
else {
$target = 'default';
}
// If there is no explicit database configuration at all, fall back to a
// connection named 'migrate'.
$key = $database_info['key'] ?? 'migrate';
$target = $database_info['target'] ?? 'default';
if (isset($database_info['database'])) {
Database::addConnectionInfo($key, $target, $database_info['database']);
}
......@@ -220,7 +210,12 @@ protected function setUpDatabase(array $database_info) {
*/
public function checkRequirements() {
if ($this->pluginDefinition['requirements_met'] === TRUE) {
$this->getDatabase();
try {
$this->getDatabase();
}
catch (\PDOException $e) {
throw new RequirementsException("No database connection available for source plugin " . $this->pluginId, [], 0, $e);
}
}
}
......
name: 'Migration missing database test'
type: module
package: Testing
version: VERSION
dependencies:
- drupal:migrate
id: missing_database
label: Migration using a SQL source
source:
plugin: migrate_missing_database_test
process: {}
destination:
plugin: 'null'
migration_dependencies: {}
<?php
namespace Drupal\migrate_missing_database_test\Plugin\migrate\source;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\migrate\Plugin\migrate\source\SqlBase;
/**
* A simple migrate source for the missing database tests.
*
* @MigrateSource(
* id = "migrate_missing_database_test",
* source_module = "migrate_missing_database_test",
* requirements_met = true
* )
*/
class MigrateMissingDatabaseSource extends SqlBase {
/**
* {@inheritdoc}
*/
public function query(): SelectInterface {
$field_names = ['id'];
$query = $this
->select('missing_database', 'm')
->fields('m', $field_names);
return $query;
}
/**
* {@inheritdoc}
*/
public function fields(): array {
$fields = [
'id' => $this->t('ID'),
];
return $fields;
}
/**
* {@inheritdoc}
*/
public function getIds(): array {
return [
'id' => [
'type' => 'integer',
],
];
}
}
<?php
namespace Drupal\Tests\migrate\Kernel;
use Drupal\Core\Database\Database;
use Drupal\KernelTests\KernelTestBase;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
use Drupal\migrate\Plugin\MigrationInterface;
/**
* Tests that a SQL migration can be instantiated without a database connection.
*
* @group migrate
*/
class MigrateMissingDatabaseTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['migrate', 'migrate_missing_database_test'];
/**
* The migration plugin manager.
*
* @var \Drupal\migrate\Plugin\MigrationPluginManager
*/
protected $migrationPluginManager;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->migrationPluginManager = \Drupal::service('plugin.manager.migration');
// Set the 'migrate' database connection to use a missing host.
$info = Database::getConnectionInfo('default')['default'];
$info['host'] = 'does_not_exist';
Database::addConnectionInfo('migrate', 'default', $info);
}
/**
* Tests a SQL migration without the database connection.
*
* - The migration can be instantiated.
* - The checkRequirements() method throws a RequirementsException.
*/
public function testMissingDatabase(): void {
$migration = $this->migrationPluginManager->createInstance('missing_database');
$this->assertInstanceOf(MigrationInterface::class, $migration);
$this->assertInstanceOf(MigrateIdMapInterface::class, $migration->getIdMap());
$this->expectException(RequirementsException::class);
$this->expectExceptionMessage('No database connection available for source plugin migrate_missing_database_test');
$migration->checkRequirements();
}
}
......@@ -128,6 +128,27 @@ public function testConnectionTypes() {
$sql_base->getDatabase();
}
/**
* Tests the exception when a connection is defined but not available.
*/
public function testBrokenConnection(): void {
$sql_base = new TestSqlBase([], $this->migration);
$target = 'test_state_db_target2';
$key = 'test_state_migrate_connection2';
$database = Database::getConnectionInfo('default')['default'];
$database['host'] = 'no_such_host';
$config = ['target' => $target, 'key' => $key, 'database' => $database];
$database_state_key = 'migrate_sql_base_test2';
\Drupal::state()->set($database_state_key, $config);
$sql_base->setConfiguration(['database_state_key' => $database_state_key]);
// Call checkRequirements(): it will call getDatabase() and convert the
// exception to a RequirementsException.
$this->expectException(RequirementsException::class);
$this->expectExceptionMessage('No database connection available for source plugin sql_base');
$sql_base->checkRequirements();
}
/**
* Tests that SqlBase respects high-water values.
*
......@@ -201,7 +222,7 @@ class TestSqlBase extends SqlBase {
* (optional) The migration being run.
*/
public function __construct(array $configuration = [], MigrationInterface $migration = NULL) {
parent::__construct($configuration, 'sql_base', [], $migration, \Drupal::state());
parent::__construct($configuration, 'sql_base', ['requirements_met' => TRUE], $migration, \Drupal::state());
}
/**
......
<?php
namespace Drupal\Tests\migrate_drupal\Kernel;
use Drupal\Core\Database\Database;
use Drupal\KernelTests\KernelTestBase;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
use Drupal\migrate\Plugin\MigrationInterface;
/**
* Tests that a migration can be instantiated without a database connection.
*
* @group migrate_drupal
*/
class MigrateMissingDatabaseTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['migrate', 'migrate_drupal', 'node'];
/**
* The migration plugin manager.
*
* @var \Drupal\migrate\Plugin\MigrationPluginManager
*/
protected $migrationPluginManager;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->migrationPluginManager = \Drupal::service('plugin.manager.migration');
// Set the 'migrate' database connection to use a missing host.
$info = Database::getConnectionInfo('default')['default'];
$info['host'] = 'does_not_exist';
Database::addConnectionInfo('migrate', 'default', $info);
}
/**
* Tests that a migration can be instantiated with the node module enabled.
*
* When the migrate_drupal and node modules are enabled, the migration
* derivers call checkRequirements() whenever createInstance() is used. If the
* database connection is not available, then Migration::setUpDatabase()
* throws an exception. Check that the exception is caught and the migration
* can still be used to access its IdMap.
*/
public function testMissingDatabase(): void {
$migration = $this->migrationPluginManager->createInstance('d7_node_type');
$this->assertInstanceOf(MigrationInterface::class, $migration);
$this->assertInstanceOf(MigrateIdMapInterface::class, $migration->getIdMap());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment