Chris@0: migration = $this->getMock(MigrationInterface::class); Chris@0: $this->migration->method('id')->willReturn('fubar'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests different connection types. Chris@0: */ Chris@0: public function testConnectionTypes() { Chris@0: $sql_base = new TestSqlBase([], $this->migration); Chris@0: Chris@0: // Verify that falling back to the default 'migrate' connection (defined in Chris@0: // the base class) works. Chris@14: $this->assertSame('default', $sql_base->getDatabase()->getTarget()); Chris@14: $this->assertSame('migrate', $sql_base->getDatabase()->getKey()); Chris@0: Chris@0: // Verify the fallback state key overrides the 'migrate' connection. Chris@0: $target = 'test_fallback_target'; Chris@0: $key = 'test_fallback_key'; Chris@0: $config = ['target' => $target, 'key' => $key]; Chris@0: $database_state_key = 'test_fallback_state'; Chris@0: \Drupal::state()->set($database_state_key, $config); Chris@0: \Drupal::state()->set('migrate.fallback_state_key', $database_state_key); Chris@0: // Create a test connection using the default database configuration. Chris@0: Database::addConnectionInfo($key, $target, Database::getConnectionInfo('default')['default']); Chris@0: $this->assertSame($sql_base->getDatabase()->getTarget(), $target); Chris@0: $this->assertSame($sql_base->getDatabase()->getKey(), $key); Chris@0: Chris@0: // Verify that setting explicit connection information overrides fallbacks. Chris@0: $target = 'test_db_target'; Chris@0: $key = 'test_migrate_connection'; Chris@0: $config = ['target' => $target, 'key' => $key]; Chris@0: $sql_base->setConfiguration($config); Chris@0: Database::addConnectionInfo($key, $target, Database::getConnectionInfo('default')['default']); Chris@0: Chris@0: // Validate we have injected our custom key and target. Chris@0: $this->assertSame($sql_base->getDatabase()->getTarget(), $target); Chris@0: $this->assertSame($sql_base->getDatabase()->getKey(), $key); Chris@0: Chris@0: // Now test we can have SqlBase create the connection from an info array. Chris@0: $sql_base = new TestSqlBase([], $this->migration); Chris@0: Chris@0: $target = 'test_db_target2'; Chris@0: $key = 'test_migrate_connection2'; Chris@0: $database = Database::getConnectionInfo('default')['default']; Chris@0: $config = ['target' => $target, 'key' => $key, 'database' => $database]; Chris@0: $sql_base->setConfiguration($config); Chris@0: Chris@0: // Call getDatabase() to get the connection defined. Chris@0: $sql_base->getDatabase(); Chris@0: Chris@0: // Validate the connection has been created with the right values. Chris@0: $this->assertSame(Database::getConnectionInfo($key)[$target], $database); Chris@0: Chris@0: // Now, test this all works when using state to store db info. Chris@0: $target = 'test_state_db_target'; Chris@0: $key = 'test_state_migrate_connection'; Chris@0: $config = ['target' => $target, 'key' => $key]; Chris@0: $database_state_key = 'migrate_sql_base_test'; Chris@0: \Drupal::state()->set($database_state_key, $config); Chris@0: $sql_base->setConfiguration(['database_state_key' => $database_state_key]); Chris@0: Database::addConnectionInfo($key, $target, Database::getConnectionInfo('default')['default']); Chris@0: Chris@0: // Validate we have injected our custom key and target. Chris@0: $this->assertSame($sql_base->getDatabase()->getTarget(), $target); Chris@0: $this->assertSame($sql_base->getDatabase()->getKey(), $key); Chris@0: Chris@0: // Now test we can have SqlBase create the connection from an info array. Chris@0: $sql_base = new TestSqlBase([], $this->migration); Chris@0: Chris@0: $target = 'test_state_db_target2'; Chris@0: $key = 'test_state_migrate_connection2'; Chris@0: $database = Database::getConnectionInfo('default')['default']; Chris@0: $config = ['target' => $target, 'key' => $key, 'database' => $database]; Chris@0: $database_state_key = 'migrate_sql_base_test2'; Chris@0: \Drupal::state()->set($database_state_key, $config); Chris@0: $sql_base->setConfiguration(['database_state_key' => $database_state_key]); Chris@0: Chris@0: // Call getDatabase() to get the connection defined. Chris@0: $sql_base->getDatabase(); Chris@0: Chris@0: // Validate the connection has been created with the right values. Chris@0: $this->assertSame(Database::getConnectionInfo($key)[$target], $database); Chris@0: Chris@0: // Verify that falling back to 'migrate' when the connection is not defined Chris@0: // throws a RequirementsException. Chris@0: \Drupal::state()->delete('migrate.fallback_state_key'); Chris@0: $sql_base->setConfiguration([]); Chris@0: Database::renameConnection('migrate', 'fallback_connection'); Chris@0: $this->setExpectedException(RequirementsException::class, Chris@0: 'No database connection configured for source plugin'); Chris@0: $sql_base->getDatabase(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that SqlBase respects high-water values. Chris@0: * Chris@0: * @param mixed $high_water Chris@0: * (optional) The high-water value to set. Chris@0: * @param array $query_result Chris@0: * (optional) The expected query results. Chris@0: * Chris@0: * @dataProvider highWaterDataProvider Chris@0: */ Chris@0: public function testHighWater($high_water = NULL, array $query_result = []) { Chris@0: $configuration = [ Chris@0: 'high_water_property' => [ Chris@0: 'name' => 'order', Chris@0: ], Chris@0: ]; Chris@0: $source = new TestSqlBase($configuration, $this->migration); Chris@0: Chris@0: if ($high_water) { Chris@0: $source->getHighWaterStorage()->set($this->migration->id(), $high_water); Chris@0: } Chris@0: Chris@14: $statement = $this->createMock(StatementInterface::class); Chris@14: $statement->expects($this->atLeastOnce())->method('setFetchMode')->with(\PDO::FETCH_ASSOC); Chris@14: $query = $this->createMock(SelectInterface::class); Chris@14: $query->method('execute')->willReturn($statement); Chris@0: $query->expects($this->atLeastOnce())->method('orderBy')->with('order', 'ASC'); Chris@0: Chris@0: $condition_group = $this->getMock(ConditionInterface::class); Chris@0: $query->method('orConditionGroup')->willReturn($condition_group); Chris@0: Chris@0: $source->setQuery($query); Chris@0: $source->rewind(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Data provider for ::testHighWater(). Chris@0: * Chris@0: * @return array Chris@0: * The scenarios to test. Chris@0: */ Chris@0: public function highWaterDataProvider() { Chris@0: return [ Chris@0: 'no high-water value set' => [], Chris@0: 'high-water value set' => [33], Chris@0: ]; Chris@0: } Chris@0: Chris@0: } Chris@0: Chris@0: /** Chris@0: * A dummy source to help with testing SqlBase. Chris@0: * Chris@0: * @package Drupal\migrate\Plugin\migrate\source Chris@0: */ Chris@0: class TestSqlBase extends SqlBase { Chris@0: Chris@0: /** Chris@0: * The query to execute. Chris@0: * Chris@0: * @var \Drupal\Core\Database\Query\SelectInterface Chris@0: */ Chris@0: protected $query; Chris@0: Chris@0: /** Chris@0: * Overrides the constructor so we can create one easily. Chris@0: * Chris@0: * @param array $configuration Chris@0: * The plugin instance configuration. Chris@0: * @param \Drupal\migrate\Plugin\MigrationInterface $migration Chris@0: * (optional) The migration being run. Chris@0: */ Chris@0: public function __construct(array $configuration = [], MigrationInterface $migration = NULL) { Chris@0: parent::__construct($configuration, 'sql_base', [], $migration, \Drupal::state()); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the database without caching it. Chris@0: */ Chris@0: public function getDatabase() { Chris@0: $this->database = NULL; Chris@0: return parent::getDatabase(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Allows us to set the configuration from a test. Chris@0: * Chris@0: * @param array $config Chris@0: * The config array. Chris@0: */ Chris@0: public function setConfiguration($config) { Chris@0: $this->configuration = $config; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getIds() {} Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function fields() {} Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function query() { Chris@0: return $this->query; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Sets the query to execute. Chris@0: * Chris@0: * @param \Drupal\Core\Database\Query\SelectInterface $query Chris@0: * The query to execute. Chris@0: */ Chris@0: public function setQuery(SelectInterface $query) { Chris@0: $this->query = $query; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getHighWaterStorage() { Chris@0: return parent::getHighWaterStorage(); Chris@0: } Chris@0: Chris@0: }