/** * Parse input options decide on a database. * * @param \Symfony\Component\Console\Input\InputInterface $input * Input object. * @return \Drupal\Core\Database\Connection */ protected function getDatabaseConnection(InputInterface $input) { // Load connection from a url. if ($input->getOption('database-url')) { // @todo this could probably be refactored to not use a global connection. // Ensure database connection isn't set. if (Database::getConnectionInfo('db-tools')) { throw new \RuntimeException('Database "db-tools" is already defined. Cannot define database provided.'); } $info = Database::convertDbUrlToConnectionInfo($input->getOption('database-url'), \Drupal::root()); Database::addConnectionInfo('db-tools', 'default', $info); $key = 'db-tools'; } else { $key = $input->getOption('database'); } // If they supplied a prefix, replace it in the connection information. $prefix = $input->getOption('prefix'); if ($prefix) { $info = Database::getConnectionInfo($key)['default']; $info['prefix']['default'] = $prefix; Database::removeConnection($key); Database::addConnectionInfo($key, 'default', $info); } return Database::getConnection('default', $key); }
/** * @covers ::convertDbUrlToConnectionInfo * * @dataProvider providerGetConnectionInfoAsUrl */ public function testGetConnectionInfoAsUrl(array $info, $expected_url) { Database::addConnectionInfo('default', 'default', $info); $url = Database::getConnectionInfoAsUrl(); // Remove the connection to not pollute subsequent datasets being tested. Database::removeConnection('default'); $this->assertEquals($expected_url, $url); }
/** * {@inheritdoc} */ protected function tearDown() { Database::removeConnection('migrate'); parent::tearDown(); $this->databaseDumpFiles = []; $this->collectMessages = FALSE; unset($this->migration, $this->migrateMessages); }
/** * Test supplying database connection as a url. */ public function testSpecifyDbUrl() { $connection_info = Database::getConnectionInfo('default')['default']; $command = new DbCommandBaseTester(); $command_tester = new CommandTester($command); $command_tester->execute(['-db-url' => $connection_info['driver'] . '://' . $connection_info['username'] . ':' . $connection_info['password'] . '@' . $connection_info['host'] . '/' . $connection_info['database']]); $this->assertEquals('db-tools', $command->getDatabaseConnection($command_tester->getInput())->getKey()); Database::removeConnection('db-tools'); $command_tester->execute(['--database-url' => $connection_info['driver'] . '://' . $connection_info['username'] . ':' . $connection_info['password'] . '@' . $connection_info['host'] . '/' . $connection_info['database']]); $this->assertEquals('db-tools', $command->getDatabaseConnection($command_tester->getInput())->getKey()); }
/** * {@inheritdoc} */ protected function connect() { try { // This doesn't actually test the connection. db_set_active(); // Now actually do a check. Database::getConnection(); $this->pass('Drupal can CONNECT to the database ok.'); } catch (\Exception $e) { // Attempt to create the database if it is not found. if ($e->getCode() == Connection::DATABASE_NOT_FOUND) { // Remove the database string from connection info. $connection_info = Database::getConnectionInfo(); $database = $connection_info['default']['database']; // We cannot use file_directory_temp() here because we haven't yet // successfully connected to the database. $connection_info['default']['database'] = drupal_tempnam(sys_get_temp_dir(), 'sqlite'); // In order to change the Database::$databaseInfo array, need to remove // the active connection, then re-add it with the new info. Database::removeConnection('default'); Database::addConnectionInfo('default', 'default', $connection_info['default']); try { Database::getConnection()->createDatabase($database); Database::closeConnection(); // Now, restore the database config. Database::removeConnection('default'); $connection_info['default']['database'] = $database; Database::addConnectionInfo('default', 'default', $connection_info['default']); // Check the database connection. Database::getConnection(); $this->pass('Drupal can CONNECT to the database ok.'); } catch (DatabaseNotFoundException $e) { // Still no dice; probably a permission issue. Raise the error to the // installer. $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage()))); } } else { // Database connection failed for some other reason than the database // not existing. $this->fail(t('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist, and have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', array('%error' => $e->getMessage()))); return FALSE; } } return TRUE; }
/** * Tests that DatabaseSchema::getPrefixInfo() returns the right database. * * We are testing if the return array of the method * \Drupal\Core\Database\Driver\mysql\Schema::getPrefixInfo(). This return * array is a keyed array with info about amongst other things the database. * The other two by Drupal core supported databases do not have this variable * set in the return array. */ function testGetPrefixInfo() { $connection_info = Database::getConnectionInfo('default'); if ($connection_info['default']['driver'] == 'mysql') { // Copy the default connection info to the 'extra' key. Database::addConnectionInfo('extra', 'default', $connection_info['default']); $db1_connection = Database::getConnection('default', 'default'); $db1_schema = $db1_connection->schema(); $db2_connection = Database::getConnection('default', 'extra'); // Get the prefix info for the first databse. $method = new \ReflectionMethod($db1_schema, 'getPrefixInfo'); $method->setAccessible(TRUE); $db1_info = $method->invoke($db1_schema); // We change the database after opening the connection, so as to prevent // connecting to a non-existent database. $reflection = new \ReflectionObject($db2_connection); $property = $reflection->getProperty('connectionOptions'); $property->setAccessible(TRUE); $connection_info['default']['database'] = 'foobar'; $property->setValue($db2_connection, $connection_info['default']); // For testing purposes, we also change the database info. $reflection_class = new \ReflectionClass('Drupal\\Core\\Database\\Database'); $property = $reflection_class->getProperty('databaseInfo'); $property->setAccessible(TRUE); $info = $property->getValue(); $info['extra']['default']['database'] = 'foobar'; $property->setValue(NULL, $info); $extra_info = Database::getConnectionInfo('extra'); $this->assertSame($extra_info['default']['database'], 'foobar'); $db2_schema = $db2_connection->schema(); $db2_info = $method->invoke($db2_schema); $this->assertNotSame($db2_info['database'], $db1_info['database'], 'Each target connection has a different database.'); $this->assertSame($db2_info['database'], 'foobar', 'The new profile has a different database.'); Database::removeConnection('extra'); } }
/** * Tests pdo options override. */ public function testConnectionOpen() { $connection = Database::getConnection('default'); $reflection = new \ReflectionObject($connection); $connection_property = $reflection->getProperty('connection'); $connection_property->setAccessible(TRUE); $error_mode = $connection_property->getValue($connection)->getAttribute(\PDO::ATTR_ERRMODE); $this->assertEqual($error_mode, \PDO::ERRMODE_EXCEPTION, 'Ensure the default error mode is set to exception.'); $connection = Database::getConnectionInfo('default'); $connection['default']['pdo'][\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT; Database::addConnectionInfo('test', 'default', $connection['default']); $connection = Database::getConnection('default', 'test'); $reflection = new \ReflectionObject($connection); $connection_property = $reflection->getProperty('connection'); $connection_property->setAccessible(TRUE); $error_mode = $connection_property->getValue($connection)->getAttribute(\PDO::ATTR_ERRMODE); $this->assertEqual($error_mode, \PDO::ERRMODE_SILENT, 'Ensure PDO connection options can be overridden.'); Database::removeConnection('test'); }
/** * Cleans up the test environment and restores the original environment. * * Deletes created files, database tables, and reverts environment changes. * * This method needs to be invoked for both unit and integration tests. * * @see TestBase::prepareDatabasePrefix() * @see TestBase::changeDatabasePrefix() * @see TestBase::prepareEnvironment() */ private function restoreEnvironment() { // Destroy the session if one was started during the test-run. $_SESSION = array(); if (PHP_SAPI !== 'cli' && session_status() === PHP_SESSION_ACTIVE) { session_destroy(); $params = session_get_cookie_params(); setcookie(session_name(), '', REQUEST_TIME - 3600, $params['path'], $params['domain'], $params['secure'], $params['httponly']); } session_name($this->originalSessionName); // Reset all static variables. // Unsetting static variables will potentially invoke destruct methods, // which might call into functions that prime statics and caches again. // In that case, all functions are still operating on the test environment, // which means they may need to access its filesystem and database. drupal_static_reset(); if ($this->container && $this->container->has('state') && ($state = $this->container->get('state'))) { $captured_emails = $state->get('system.test_mail_collector') ?: array(); $emailCount = count($captured_emails); if ($emailCount) { $message = $emailCount == 1 ? '1 email was sent during this test.' : $emailCount . ' emails were sent during this test.'; $this->pass($message, 'Email'); } } // Sleep for 50ms to allow shutdown functions and terminate events to // complete. Further information: https://www.drupal.org/node/2194357. usleep(50000); // Remove all prefixed tables. $original_connection_info = Database::getConnectionInfo('simpletest_original_default'); $original_prefix = $original_connection_info['default']['prefix']['default']; $test_connection_info = Database::getConnectionInfo('default'); $test_prefix = $test_connection_info['default']['prefix']['default']; if ($original_prefix != $test_prefix) { $tables = Database::getConnection()->schema()->findTables('%'); foreach ($tables as $table) { if (Database::getConnection()->schema()->dropTable($table)) { unset($tables[$table]); } } } // In case a fatal error occurred that was not in the test process read the // log to pick up any fatal errors. simpletest_log_read($this->testId, $this->databasePrefix, get_class($this)); // Restore original dependency injection container. $this->container = $this->originalContainer; \Drupal::setContainer($this->originalContainer); // Delete test site directory. file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback')); // Restore original database connection. Database::removeConnection('default'); Database::renameConnection('simpletest_original_default', 'default'); // Reset all static variables. // All destructors of statically cached objects have been invoked above; // this second reset is guaranteed to reset everything to nothing. drupal_static_reset(); // Restore original in-memory configuration. $GLOBALS['config'] = $this->originalConfig; $GLOBALS['conf'] = $this->originalConf; new Settings($this->originalSettings); // Restore original statics and globals. $GLOBALS['config_directories'] = $this->originalConfigDirectories; // Re-initialize original stream wrappers of the parent site. // This must happen after static variables have been reset and the original // container and $config_directories are restored, as simpletest_log_read() // uses the public stream wrapper to locate the error.log. $this->originalContainer->get('stream_wrapper_manager')->register(); if (isset($this->originalPrefix)) { drupal_valid_test_ua($this->originalPrefix); } else { drupal_valid_test_ua(FALSE); } // Restore original shutdown callbacks. $callbacks =& drupal_register_shutdown_function(); $callbacks = $this->originalShutdownCallbacks; }
/** * @after * * Additional tear down method to close the connection at the end. */ public function tearDownCloseDatabaseConnection() { // Destroy the database connection, which for example removes the memory // from sqlite in memory. foreach (Database::getAllConnectionInfo() as $key => $targets) { Database::removeConnection($key); } }
/** * Cleans up the test migrate connection. * * @todo Remove when we don't use global. https://www.drupal.org/node/2552791 */ private function cleanupMigrateConnection() { Database::removeConnection('migrate'); $original_connection_info = Database::getConnectionInfo('simpletest_original_migrate'); if ($original_connection_info) { Database::renameConnection('simpletest_original_migrate', 'migrate'); } }
/** * {@inheritdoc} */ protected function tearDown() { Database::removeConnection('migrate'); parent::tearDown(); }
/** * {@inheritdoc} */ protected function connect() { try { // This doesn't actually test the connection. db_set_active(); // Now actually do a check. try { Database::getConnection(); } catch (\Exception $e) { // Detect utf8mb4 incompability. if ($e->getCode() == Connection::UNSUPPORTED_CHARSET || $e->getCode() == Connection::SQLSTATE_SYNTAX_ERROR && $e->errorInfo[1] == Connection::UNKNOWN_CHARSET) { $this->fail(t('Your MySQL server and PHP MySQL driver must support utf8mb4 character encoding. Make sure to use a database system that supports this (such as MySQL/MariaDB/Percona 5.5.3 and up), and that the utf8mb4 character set is compiled in. See the <a href=":documentation" target="_blank">MySQL documentation</a> for more information.', array(':documentation' => 'https://dev.mysql.com/doc/refman/5.0/en/cannot-initialize-character-set.html'))); $info = Database::getConnectionInfo(); $info_copy = $info; // Set a flag to fall back to utf8. Note: this flag should only be // used here and is for internal use only. $info_copy['default']['_dsn_utf8_fallback'] = TRUE; // In order to change the Database::$databaseInfo array, we need to // remove the active connection, then re-add it with the new info. Database::removeConnection('default'); Database::addConnectionInfo('default', 'default', $info_copy['default']); // Connect with the new database info, using the utf8 character set so // that we can run the checkEngineVersion test. Database::getConnection(); // Revert to the old settings. Database::removeConnection('default'); Database::addConnectionInfo('default', 'default', $info['default']); } else { // Rethrow the exception. throw $e; } } $this->pass('Drupal can CONNECT to the database ok.'); } catch (\Exception $e) { // Attempt to create the database if it is not found. if ($e->getCode() == Connection::DATABASE_NOT_FOUND) { // Remove the database string from connection info. $connection_info = Database::getConnectionInfo(); $database = $connection_info['default']['database']; unset($connection_info['default']['database']); // In order to change the Database::$databaseInfo array, need to remove // the active connection, then re-add it with the new info. Database::removeConnection('default'); Database::addConnectionInfo('default', 'default', $connection_info['default']); try { // Now, attempt the connection again; if it's successful, attempt to // create the database. Database::getConnection()->createDatabase($database); } catch (DatabaseNotFoundException $e) { // Still no dice; probably a permission issue. Raise the error to the // installer. $this->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array('%database' => $database, '%error' => $e->getMessage()))); } } else { // Database connection failed for some other reason than the database // not existing. $this->fail(t('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist or does the database user have sufficient privileges to create the database?</li><li>Have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', array('%error' => $e->getMessage()))); return FALSE; } } return TRUE; }
public static final function removeConnection($key) { return BaseDatabase::removeConnection($key); }
/** * {@inheritdoc} */ protected function tearDown() { // Destroy the testing kernel. if (isset($this->kernel)) { $this->kernel->shutdown(); } // Free up memory: Own properties. $this->classLoader = NULL; $this->vfsRoot = NULL; $this->configImporter = NULL; // Free up memory: Custom test class properties. // Note: Private properties cannot be cleaned up. $rc = new \ReflectionClass(__CLASS__); $blacklist = array(); foreach ($rc->getProperties() as $property) { $blacklist[$property->name] = $property->getDeclaringClass()->name; } $rc = new \ReflectionClass($this); foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $property) { if (!$property->isStatic() && !isset($blacklist[$property->name])) { $this->{$property->name} = NULL; } } // Clean up statics, container, and settings. if (function_exists('drupal_static_reset')) { drupal_static_reset(); } \Drupal::unsetContainer(); $this->container = NULL; new Settings(array()); // Destroy the database connection, which for example removes the memory // from sqlite in memory. foreach (Database::getAllConnectionInfo() as $key => $targets) { Database::removeConnection($key); } parent::tearDown(); }
/** * Setup the legacy database connection to migrate from. */ protected function setupLegacyDb() { $db_url = drush_get_option('legacy-db-url'); $db_spec = drush_convert_db_from_db_url($db_url); $db_spec['db_prefix'] = drush_get_option('legacy-db-prefix'); Database::removeConnection('migrate'); Database::addConnectionInfo('migrate', 'default', $db_spec); }