Commit 2b9cec6d authored by Dries's avatar Dries
Browse files

Issue #2176621 by sun, alexpott: Remove global .

parent 6de66844
...@@ -405,7 +405,8 @@ function drupal_valid_http_host($host) { ...@@ -405,7 +405,8 @@ function drupal_valid_http_host($host) {
*/ */
function drupal_settings_initialize() { function drupal_settings_initialize() {
// Export these settings.php variables to the global namespace. // Export these settings.php variables to the global namespace.
global $base_url, $databases, $cookie_domain, $config_directories, $config; global $base_url, $cookie_domain, $config_directories, $config;
$databases = array();
$settings = array(); $settings = array();
$config = array(); $config = array();
...@@ -414,6 +415,8 @@ function drupal_settings_initialize() { ...@@ -414,6 +415,8 @@ function drupal_settings_initialize() {
if (is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) { if (is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) {
require DRUPAL_ROOT . '/' . $conf_path . '/settings.php'; require DRUPAL_ROOT . '/' . $conf_path . '/settings.php';
} }
// Initialize Database.
Database::setMultipleConnectionInfo($databases);
// Initialize Settings. // Initialize Settings.
new Settings($settings); new Settings($settings);
} }
...@@ -1598,7 +1601,7 @@ function _drupal_bootstrap_configuration() { ...@@ -1598,7 +1601,7 @@ function _drupal_bootstrap_configuration() {
// Redirect the user to the installation script if Drupal has not been // Redirect the user to the installation script if Drupal has not been
// installed yet (i.e., if no $databases array has been defined in the // installed yet (i.e., if no $databases array has been defined in the
// settings.php file) and we are not already installing. // settings.php file) and we are not already installing.
if (empty($GLOBALS['databases']) && !drupal_installation_attempted() && !drupal_is_cli()) { if (!Database::getConnectionInfo() && !drupal_installation_attempted() && !drupal_is_cli()) {
include_once __DIR__ . '/install.inc'; include_once __DIR__ . '/install.inc';
install_goto('core/install.php'); install_goto('core/install.php');
} }
......
...@@ -431,7 +431,7 @@ function install_begin_request(&$install_state) { ...@@ -431,7 +431,7 @@ function install_begin_request(&$install_state) {
$task = NULL; $task = NULL;
// Do not install over a configured settings.php. // Do not install over a configured settings.php.
if (!empty($GLOBALS['databases'])) { if (Database::getConnectionInfo()) {
throw new AlreadyInstalledException($container->get('string_translation')); throw new AlreadyInstalledException($container->get('string_translation'));
} }
} }
...@@ -1006,9 +1006,8 @@ function install_verify_completed_task() { ...@@ -1006,9 +1006,8 @@ function install_verify_completed_task() {
* Verifies that settings.php specifies a valid database connection. * Verifies that settings.php specifies a valid database connection.
*/ */
function install_verify_database_settings() { function install_verify_database_settings() {
global $databases; if ($database = Database::getConnectionInfo()) {
if (!empty($databases)) { $database = $database['default'];
$database = $databases['default']['default'];
$settings_file = './' . conf_path(FALSE) . '/settings.php'; $settings_file = './' . conf_path(FALSE) . '/settings.php';
$errors = install_database_errors($database, $settings_file); $errors = install_database_errors($database, $settings_file);
if (empty($errors)) { if (empty($errors)) {
...@@ -1022,7 +1021,6 @@ function install_verify_database_settings() { ...@@ -1022,7 +1021,6 @@ function install_verify_database_settings() {
* Checks a database connection and returns any errors. * Checks a database connection and returns any errors.
*/ */
function install_database_errors($database, $settings_file) { function install_database_errors($database, $settings_file) {
global $databases;
$errors = array(); $errors = array();
// Check database type. // Check database type.
...@@ -1034,18 +1032,13 @@ function install_database_errors($database, $settings_file) { ...@@ -1034,18 +1032,13 @@ function install_database_errors($database, $settings_file) {
else { else {
// Run driver specific validation // Run driver specific validation
$errors += $database_types[$driver]->validateDatabaseSettings($database); $errors += $database_types[$driver]->validateDatabaseSettings($database);
if (!empty($errors)) {
// No point to try further.
return $errors;
}
// Run tasks associated with the database type. Any errors are caught in the // Run tasks associated with the database type. Any errors are caught in the
// calling function. // calling function.
$databases['default']['default'] = $database; Database::addConnectionInfo('default', 'default', $database);
// Just changing the global doesn't get the new information processed.
// We need to close any active connections and tell the Database class to
// re-parse $databases.
if (Database::isActiveConnection()) {
Database::closeConnection();
}
Database::parseConnectionInfo();
try { try {
db_run_tasks($driver); db_run_tasks($driver);
} }
......
...@@ -52,7 +52,7 @@ abstract class Database { ...@@ -52,7 +52,7 @@ abstract class Database {
* *
* @var array * @var array
*/ */
static protected $databaseInfo = NULL; static protected $databaseInfo = array();
/** /**
* A list of key/target credentials to simply ignore. * A list of key/target credentials to simply ignore.
...@@ -85,9 +85,9 @@ abstract class Database { ...@@ -85,9 +85,9 @@ abstract class Database {
/** /**
* Starts logging a given logging key on the specified connection. * Starts logging a given logging key on the specified connection.
* *
* @param $logging_key * @param string $logging_key
* The logging key to log. * The logging key to log.
* @param $key * @param string $key
* The database connection key for which we want to log. * The database connection key for which we want to log.
* *
* @return \Drupal\Core\Database\Log * @return \Drupal\Core\Database\Log
...@@ -122,9 +122,9 @@ final public static function startLog($logging_key, $key = 'default') { ...@@ -122,9 +122,9 @@ final public static function startLog($logging_key, $key = 'default') {
* it again (which does nothing to an open log key) and call methods on it as * it again (which does nothing to an open log key) and call methods on it as
* desired. * desired.
* *
* @param $logging_key * @param string $logging_key
* The logging key to log. * The logging key to log.
* @param $key * @param string $key
* The database connection key for which we want to log. * The database connection key for which we want to log.
* *
* @return array * @return array
...@@ -144,9 +144,9 @@ final public static function getLog($logging_key, $key = 'default') { ...@@ -144,9 +144,9 @@ final public static function getLog($logging_key, $key = 'default') {
/** /**
* Gets the connection object for the specified database key and target. * Gets the connection object for the specified database key and target.
* *
* @param $target * @param string $target
* The database target name. * The database target name.
* @param $key * @param string $key
* The database connection key. Defaults to NULL which means the active key. * The database connection key. Defaults to NULL which means the active key.
* *
* @return \Drupal\Core\Database\Connection * @return \Drupal\Core\Database\Connection
...@@ -179,7 +179,7 @@ final public static function getConnection($target = 'default', $key = NULL) { ...@@ -179,7 +179,7 @@ final public static function getConnection($target = 'default', $key = NULL) {
* Note that this method will return FALSE if no connection has been * Note that this method will return FALSE if no connection has been
* established yet, even if one could be. * established yet, even if one could be.
* *
* @return * @return bool
* TRUE if there is at least one database connection established, FALSE * TRUE if there is at least one database connection established, FALSE
* otherwise. * otherwise.
*/ */
...@@ -190,14 +190,10 @@ final public static function isActiveConnection() { ...@@ -190,14 +190,10 @@ final public static function isActiveConnection() {
/** /**
* Sets the active connection to the specified key. * Sets the active connection to the specified key.
* *
* @return * @return string|null
* The previous database connection key. * The previous database connection key.
*/ */
final public static function setActiveConnection($key = 'default') { final public static function setActiveConnection($key = 'default') {
if (empty(self::$databaseInfo)) {
self::parseConnectionInfo();
}
if (!empty(self::$databaseInfo[$key])) { if (!empty(self::$databaseInfo[$key])) {
$old_key = self::$activeKey; $old_key = self::$activeKey;
self::$activeKey = $key; self::$activeKey = $key;
...@@ -207,56 +203,40 @@ final public static function setActiveConnection($key = 'default') { ...@@ -207,56 +203,40 @@ final public static function setActiveConnection($key = 'default') {
/** /**
* Process the configuration file for database information. * Process the configuration file for database information.
*
* @param array $info
* The database connection information, as defined in settings.php. The
* structure of this array depends on the database driver it is connecting
* to.
*/ */
final public static function parseConnectionInfo() { final public static function parseConnectionInfo(array $info) {
global $databases;
$database_info = is_array($databases) ? $databases : array();
foreach ($database_info as $index => $info) {
foreach ($database_info[$index] as $target => $value) {
// If there is no "driver" property, then we assume it's an array of // If there is no "driver" property, then we assume it's an array of
// possible connections for this target. Pick one at random. That allows // possible connections for this target. Pick one at random. That allows
// us to have, for example, multiple slave servers. // us to have, for example, multiple slave servers.
if (empty($value['driver'])) { if (empty($info['driver'])) {
$database_info[$index][$target] = $database_info[$index][$target][mt_rand(0, count($database_info[$index][$target]) - 1)]; $info = $info[mt_rand(0, count($info) - 1)];
} }
// Parse the prefix information. // Parse the prefix information.
if (!isset($database_info[$index][$target]['prefix'])) { if (!isset($info['prefix'])) {
// Default to an empty prefix. // Default to an empty prefix.
$database_info[$index][$target]['prefix'] = array( $info['prefix'] = array(
'default' => '', 'default' => '',
); );
} }
elseif (!is_array($database_info[$index][$target]['prefix'])) { elseif (!is_array($info['prefix'])) {
// Transform the flat form into an array form. // Transform the flat form into an array form.
$database_info[$index][$target]['prefix'] = array( $info['prefix'] = array(
'default' => $database_info[$index][$target]['prefix'], 'default' => $info['prefix'],
); );
} }
} return $info;
}
if (!is_array(self::$databaseInfo)) {
self::$databaseInfo = $database_info;
}
// Merge the new $database_info into the existing.
// array_merge_recursive() cannot be used, as it would make multiple
// database, user, and password keys in the same database array.
else {
foreach ($database_info as $database_key => $database_values) {
foreach ($database_values as $target => $target_values) {
self::$databaseInfo[$database_key][$target] = $target_values;
}
}
}
} }
/** /**
* Adds database connection information for a given key/target. * Adds database connection information for a given key/target.
* *
* This method allows the addition of new connection credentials at runtime. * This method allows to add new connections at runtime.
*
* Under normal circumstances the preferred way to specify database * Under normal circumstances the preferred way to specify database
* credentials is via settings.php. However, this method allows them to be * credentials is via settings.php. However, this method allows them to be
* added at arbitrary times, such as during unit tests, when connecting to * added at arbitrary times, such as during unit tests, when connecting to
...@@ -264,52 +244,71 @@ final public static function parseConnectionInfo() { ...@@ -264,52 +244,71 @@ final public static function parseConnectionInfo() {
* *
* If the given key/target pair already exists, this method will be ignored. * If the given key/target pair already exists, this method will be ignored.
* *
* @param $key * @param string $key
* The database key. * The database key.
* @param $target * @param string $target
* The database target name. * The database target name.
* @param $info * @param array $info
* The database connection information, as it would be defined in * The database connection information, as defined in settings.php. The
* settings.php. Note that the structure of this array will depend on the * structure of this array depends on the database driver it is connecting
* database driver it is connecting to. * to.
*/ */
public static function addConnectionInfo($key, $target, $info) { final public static function addConnectionInfo($key, $target, array $info) {
if (empty(self::$databaseInfo[$key][$target])) { if (empty(self::$databaseInfo[$key][$target])) {
self::$databaseInfo[$key][$target] = $info; self::$databaseInfo[$key][$target] = self::parseConnectionInfo($info);
} }
} }
/** /**
* Gets information on the specified database connection. * Gets information on the specified database connection.
* *
* @param $connection * @param string $key
* The connection key for which we want information. * (optional) The connection key for which to return information.
*
* @return array|null
*/ */
final public static function getConnectionInfo($key = 'default') { final public static function getConnectionInfo($key = 'default') {
if (empty(self::$databaseInfo)) {
self::parseConnectionInfo();
}
if (!empty(self::$databaseInfo[$key])) { if (!empty(self::$databaseInfo[$key])) {
return self::$databaseInfo[$key]; return self::$databaseInfo[$key];
} }
} }
/**
* Gets connection information for all available databases.
*
* @return array
*/
final public static function getAllConnectionInfo() {
return self::$databaseInfo;
}
/**
* Sets connection information for multiple databases.
*
* @param array $databases
* A multi-dimensional array specifying database connection parameters, as
* defined in settings.php.
*/
final public static function setMultipleConnectionInfo(array $databases) {
foreach ($databases as $key => $targets) {
foreach ($targets as $target => $info) {
self::addConnectionInfo($key, $target, $info);
}
}
}
/** /**
* Rename a connection and its corresponding connection information. * Rename a connection and its corresponding connection information.
* *
* @param $old_key * @param string $old_key
* The old connection key. * The old connection key.
* @param $new_key * @param string $new_key
* The new connection key. * The new connection key.
* @return *
* @return bool
* TRUE in case of success, FALSE otherwise. * TRUE in case of success, FALSE otherwise.
*/ */
final public static function renameConnection($old_key, $new_key) { final public static function renameConnection($old_key, $new_key) {
if (empty(self::$databaseInfo)) {
self::parseConnectionInfo();
}
if (!empty(self::$databaseInfo[$old_key]) && empty(self::$databaseInfo[$new_key])) { if (!empty(self::$databaseInfo[$old_key]) && empty(self::$databaseInfo[$new_key])) {
// Migrate the database connection information. // Migrate the database connection information.
self::$databaseInfo[$new_key] = self::$databaseInfo[$old_key]; self::$databaseInfo[$new_key] = self::$databaseInfo[$old_key];
...@@ -331,9 +330,10 @@ final public static function renameConnection($old_key, $new_key) { ...@@ -331,9 +330,10 @@ final public static function renameConnection($old_key, $new_key) {
/** /**
* Remove a connection and its corresponding connection information. * Remove a connection and its corresponding connection information.
* *
* @param $key * @param string $key
* The connection key. * The connection key.
* @return *
* @return bool
* TRUE in case of success, FALSE otherwise. * TRUE in case of success, FALSE otherwise.
*/ */
final public static function removeConnection($key) { final public static function removeConnection($key) {
...@@ -350,20 +350,16 @@ final public static function removeConnection($key) { ...@@ -350,20 +350,16 @@ final public static function removeConnection($key) {
/** /**
* Opens a connection to the server specified by the given key and target. * Opens a connection to the server specified by the given key and target.
* *
* @param $key * @param string $key
* The database connection key, as specified in settings.php. The default is * The database connection key, as specified in settings.php. The default is
* "default". * "default".
* @param $target * @param string $target
* The database target to open. * The database target to open.
* *
* @throws \Drupal\Core\Database\ConnectionNotDefinedException * @throws \Drupal\Core\Database\ConnectionNotDefinedException
* @throws \Drupal\Core\Database\DriverNotSpecifiedException * @throws \Drupal\Core\Database\DriverNotSpecifiedException
*/ */
final protected static function openConnection($key, $target) { final protected static function openConnection($key, $target) {
if (empty(self::$databaseInfo)) {
self::parseConnectionInfo();
}
// If the requested database does not exist then it is an unrecoverable // If the requested database does not exist then it is an unrecoverable
// error. // error.
if (!isset(self::$databaseInfo[$key])) { if (!isset(self::$databaseInfo[$key])) {
...@@ -399,10 +395,10 @@ final protected static function openConnection($key, $target) { ...@@ -399,10 +395,10 @@ final protected static function openConnection($key, $target) {
/** /**
* Closes a connection to the server specified by the given key and target. * Closes a connection to the server specified by the given key and target.
* *
* @param $target * @param string $target
* The database target name. Defaults to NULL meaning that all target * The database target name. Defaults to NULL meaning that all target
* connections will be closed. * connections will be closed.
* @param $key * @param string $key
* The database connection key. Defaults to NULL which means the active key. * The database connection key. Defaults to NULL which means the active key.
*/ */
public static function closeConnection($target = NULL, $key = NULL) { public static function closeConnection($target = NULL, $key = NULL) {
...@@ -439,9 +435,9 @@ public static function closeConnection($target = NULL, $key = NULL) { ...@@ -439,9 +435,9 @@ public static function closeConnection($target = NULL, $key = NULL) {
* method with the database key and the target to disable. That database key * method with the database key and the target to disable. That database key
* will then always fall back to 'default' for that key, even if it's defined. * will then always fall back to 'default' for that key, even if it's defined.
* *
* @param $key * @param string $key
* The database connection key. * The database connection key.
* @param $target * @param string $target
* The target of the specified key to ignore. * The target of the specified key to ignore.
*/ */
public static function ignoreTarget($key, $target) { public static function ignoreTarget($key, $target) {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\Core\Installer\Form; namespace Drupal\Core\Installer\Form;
use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Crypt;
use Drupal\Core\Database\Database;
use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormBase;
/** /**
...@@ -26,8 +27,6 @@ public function getFormId() { ...@@ -26,8 +27,6 @@ public function getFormId() {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function buildForm(array $form, array &$form_state) { public function buildForm(array $form, array &$form_state) {
global $databases;
$conf_path = './' . conf_path(FALSE); $conf_path = './' . conf_path(FALSE);
$settings_file = $conf_path . '/settings.php'; $settings_file = $conf_path . '/settings.php';
...@@ -36,25 +35,33 @@ public function buildForm(array $form, array &$form_state) { ...@@ -36,25 +35,33 @@ public function buildForm(array $form, array &$form_state) {
$drivers = drupal_get_database_types(); $drivers = drupal_get_database_types();
$drivers_keys = array_keys($drivers); $drivers_keys = array_keys($drivers);
// If database connection settings have been prepared in settings.php already, // Unless there is input for this form (for a non-interactive installation,
// then the existing values need to be taken over. // input originates from the $settings array passed into install_drupal()),
// check whether database connection settings have been prepared in
// settings.php already.
// Note: The installer even executes this form if there is a valid database // Note: The installer even executes this form if there is a valid database
// connection already, since the submit handler of this form is responsible // connection already, since the submit handler of this form is responsible
// for writing all $settings to settings.php (not limited to $databases). // for writing all $settings to settings.php (not limited to $databases).
if (isset($databases['default']['default'])) { if (!isset($form_state['input']['driver']) && $database = Database::getConnectionInfo()) {
$default_driver = $databases['default']['default']['driver']; $form_state['input']['driver'] = $database['default']['driver'];
$default_options = $databases['default']['default']; $form_state['input'][$database['default']['driver']] = $database['default'];
} }
// Otherwise, use the database connection settings from the form input.
// For a non-interactive installation, this is derived from the original if (isset($form_state['input']['driver'])) {
// $settings array passed into install_drupal().
elseif (isset($form_state['input']['driver'])) {
$default_driver = $form_state['input']['driver']; $default_driver = $form_state['input']['driver'];
// In case of database connection info from settings.php, as well as for a
// programmed form submission (non-interactive installer), the table prefix
// information is usually normalized into an array already, but the form
// element only allows to configure one default prefix for all tables.
$prefix = &$form_state['input'][$default_driver]['prefix'];
if (isset($prefix) && is_array($prefix)) {
$prefix = $prefix['default'];
}
$default_options = $form_state['input'][$default_driver]; $default_options = $form_state['input'][$default_driver];
} }
// If there is no database information at all yet, just suggest the first // If there is no database information yet, suggest the first available driver
// available driver as default value, so that its settings form is made // as default value, so that its settings form is made visible via #states
// visible via #states when JavaScript is enabled (see below). // when JavaScript is enabled (see below).
else { else {
$default_driver = current($drivers_keys); $default_driver = current($drivers_keys);
$default_options = array(); $default_options = array();
......
...@@ -958,7 +958,11 @@ private function changeDatabasePrefix() { ...@@ -958,7 +958,11 @@ private function changeDatabasePrefix() {
$connection_info = Database::getConnectionInfo('default'); $connection_info = Database::getConnectionInfo('default');
Database::renameConnection('default', 'simpletest_original_default'); Database::renameConnection('default', 'simpletest_original_default');
foreach ($connection_info as $target => $value) { foreach ($connection_info as $target => $value) {
$connection_info[$target]['prefix'] = $value['prefix']['default'] . $this->databasePrefix; // Replace the full table prefix definition to ensure that no table
// prefixes of the test runner leak into the test.
$connection_info[$target]['prefix'] = array(
'default' => $value['prefix']['default'] . $this->databasePrefix,
);
} }
Database::addConnectionInfo('default', 'default', $connection_info['default']); Database::addConnectionInfo('default', 'default', $connection_info['default']);
} }
...@@ -1162,11 +1166,10 @@ private function restoreEnvironment() { ...@@ -1162,11 +1166,10 @@ private function restoreEnvironment() {
usleep(50000); usleep(50000);
// Remove all prefixed tables. // Remove all prefixed tables.