Commit de33f74b authored by Dries's avatar Dries
Browse files

- Patch #688704 by Crell, boombatower, noahb: give DB its own autoload function.

parent b647348f
...@@ -1947,6 +1947,10 @@ function _drupal_bootstrap_database() { ...@@ -1947,6 +1947,10 @@ function _drupal_bootstrap_database() {
Database::setLoggingCallback('watchdog', WATCHDOG_NOTICE, WATCHDOG_ERROR); Database::setLoggingCallback('watchdog', WATCHDOG_NOTICE, WATCHDOG_ERROR);
// Register autoload functions so that we can access classes and interfaces. // Register autoload functions so that we can access classes and interfaces.
// The database autoload routine comes first so that we can load the database
// system without hitting the database. That is especially important during
// the install or upgrade process.
spl_autoload_register('db_autoload');
spl_autoload_register('drupal_autoload_class'); spl_autoload_register('drupal_autoload_class');
spl_autoload_register('drupal_autoload_interface'); spl_autoload_register('drupal_autoload_interface');
} }
...@@ -2381,7 +2385,6 @@ function drupal_autoload_class($class) { ...@@ -2381,7 +2385,6 @@ function drupal_autoload_class($class) {
*/ */
function _registry_check_code($type, $name = NULL) { function _registry_check_code($type, $name = NULL) {
static $lookup_cache, $cache_update_needed; static $lookup_cache, $cache_update_needed;
if ($type == 'class' && class_exists($name) || $type == 'interface' && interface_exists($name)) { if ($type == 'class' && class_exists($name) || $type == 'interface' && interface_exists($name)) {
return TRUE; return TRUE;
} }
......
...@@ -41,8 +41,7 @@ function clear($cid = NULL, $wildcard = FALSE) { ...@@ -41,8 +41,7 @@ function clear($cid = NULL, $wildcard = FALSE) {
// subtle bugs, some of which would not be fixed unless the site // subtle bugs, some of which would not be fixed unless the site
// administrator cleared the cache manually. // administrator cleared the cache manually.
try { try {
if (function_exists('drupal_install_initialize_database')) { if (class_exists('Database')) {
drupal_install_initialize_database();
parent::clear($cid, $wildcard); parent::clear($cid, $wildcard);
} }
} }
......
...@@ -761,7 +761,9 @@ public function truncate($table, array $options = array()) { ...@@ -761,7 +761,9 @@ public function truncate($table, array $options = array()) {
public function schema() { public function schema() {
if (empty($this->schema)) { if (empty($this->schema)) {
$class = $this->getDriverClass('DatabaseSchema'); $class = $this->getDriverClass('DatabaseSchema');
$this->schema = new $class($this); if (class_exists($class)) {
$this->schema = new $class($this);
}
} }
return $this->schema; return $this->schema;
} }
...@@ -2109,6 +2111,73 @@ public function valid() { ...@@ -2109,6 +2111,73 @@ public function valid() {
} }
} }
/**
* Autoload callback for the database system.
*/
function db_autoload($class) {
static $base_path = '';
static $checked = array();
static $files = array(
'query.inc' => array(
'QueryPlaceholderInterface',
'QueryConditionInterface', 'DatabaseCondition',
'Query', 'DeleteQuery', 'InsertQuery', 'UpdateQuery', 'MergeQuery', 'TruncateQuery',
'QueryAlterableInterface',
),
'select.inc' => array('QueryAlterableInterface', 'SelectQueryInterface', 'SelectQuery', 'SelectQueryExtender'),
'database.inc' => array('DatabaseConnection'),
'log.inc' => array('DatabaseLog'),
'prefetch.inc' => array('DatabaseStatementPrefetch'),
'schema.inc' => array('DatabaseSchema'),
);
// If a class doesn't exist, it may get checked a second time
// by class_exists(). If so, just bail out now.
if (isset($checked[$class])) {
return;
}
$checked[$class] = TRUE;
if (empty($base_path)) {
$base_path = dirname(realpath(__FILE__));
}
// If there is an underscore in the class name, we know it's a
// driver-specific file so check for those. If not, it's a generic.
// Note that we use require_once here instead of require because of a
// quirk in class_exists(). By default, class_exists() will try to
// autoload a class if it's not found. However, we cannot tell
// at this point whether or not the class is going to exist, only
// the file that it would be in if it does exist. That means we may
// try to include a file that was already included by another
// autoload call, which would break. Using require_once() neatly
// avoids that issue.
if (strpos($class, '_') !== FALSE) {
list($base, $driver) = explode('_', $class);
// Drivers have an extra file, and may put their SelectQuery implementation
// in the main query file since it's so small.
$driver_files = $files;
$driver_files['query.inc'][] = 'SelectQuery';
$driver_files['install.inc'] = array('DatabaseTasks');
foreach ($driver_files as $file => $classes) {
if (in_array($base, $classes)) {
require_once "{$base_path}/{$driver}/{$file}";
return;
}
}
}
else {
foreach ($files as $file => $classes) {
if (in_array($class, $classes)) {
require_once $base_path . '/' . $file;
return;
}
}
}
}
/** /**
* The following utility functions are simply convenience wrappers. * The following utility functions are simply convenience wrappers.
......
...@@ -278,6 +278,7 @@ function install_begin_request(&$install_state) { ...@@ -278,6 +278,7 @@ function install_begin_request(&$install_state) {
// Initialize the database system. Note that the connection // Initialize the database system. Note that the connection
// won't be initialized until it is actually requested. // won't be initialized until it is actually requested.
require_once DRUPAL_ROOT . '/includes/database/database.inc'; require_once DRUPAL_ROOT . '/includes/database/database.inc';
spl_autoload_register('db_autoload');
// Verify the last completed task in the database, if there is one. // Verify the last completed task in the database, if there is one.
$task = install_verify_completed_task(); $task = install_verify_completed_task();
...@@ -350,7 +351,6 @@ function install_run_tasks(&$install_state) { ...@@ -350,7 +351,6 @@ function install_run_tasks(&$install_state) {
$install_state['tasks_performed'][] = $task_name; $install_state['tasks_performed'][] = $task_name;
$install_state['installation_finished'] = empty($tasks_to_perform); $install_state['installation_finished'] = empty($tasks_to_perform);
if ($install_state['database_tables_exist'] && ($task['run'] == INSTALL_TASK_RUN_IF_NOT_COMPLETED || $install_state['installation_finished'])) { if ($install_state['database_tables_exist'] && ($task['run'] == INSTALL_TASK_RUN_IF_NOT_COMPLETED || $install_state['installation_finished'])) {
drupal_install_initialize_database();
variable_set('install_task', $install_state['installation_finished'] ? 'done' : $task_name); variable_set('install_task', $install_state['installation_finished'] ? 'done' : $task_name);
} }
} }
...@@ -1325,7 +1325,6 @@ function install_load_profile(&$install_state) { ...@@ -1325,7 +1325,6 @@ function install_load_profile(&$install_state) {
function install_bootstrap_full(&$install_state) { function install_bootstrap_full(&$install_state) {
// Bootstrap newly installed Drupal, while preserving existing messages. // Bootstrap newly installed Drupal, while preserving existing messages.
$messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : ''; $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : '';
drupal_install_initialize_database();
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$_SESSION['messages'] = $messages; $_SESSION['messages'] = $messages;
......
...@@ -219,20 +219,14 @@ function drupal_detect_baseurl($file = 'install.php') { ...@@ -219,20 +219,14 @@ function drupal_detect_baseurl($file = 'install.php') {
function drupal_detect_database_types() { function drupal_detect_database_types() {
$databases = array(); $databases = array();
// Initialize the database system if it has not been
// initialized yet. We do not initialize it earlier to make
// requirements check during the installation.
require_once DRUPAL_ROOT . '/includes/database/database.inc';
// We define a driver as a directory in /includes/database that in turn // We define a driver as a directory in /includes/database that in turn
// contains a database.inc file. That allows us to drop in additional drivers // contains a database.inc file. That allows us to drop in additional drivers
// without modifying the installer. // without modifying the installer.
// Because we have no registry yet, we need to also include the install.inc // Because we have no registry yet, we need to also include the install.inc
// file for the driver explicitly. // file for the driver explicitly.
require_once DRUPAL_ROOT . '/includes/database/database.inc'; require_once DRUPAL_ROOT . '/includes/database/database.inc';
spl_autoload_register('db_autoload');
foreach (file_scan_directory(DRUPAL_ROOT . '/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) { foreach (file_scan_directory(DRUPAL_ROOT . '/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) {
include_once "{$file->uri}/install.inc";
include_once "{$file->uri}/database.inc";
$drivers[$file->filename] = $file->uri; $drivers[$file->filename] = $file->uri;
} }
...@@ -546,28 +540,6 @@ function drupal_verify_profile($install_state) { ...@@ -546,28 +540,6 @@ function drupal_verify_profile($install_state) {
return $requirements; return $requirements;
} }
/**
* Manually include all files for the active database.
*
* Because we have no registry yet, we need to manually include the
* necessary database include files.
*/
function drupal_install_initialize_database() {
static $included = FALSE;
if (!$included) {
$connection_info = Database::getConnectionInfo();
$driver = $connection_info['default']['driver'];
require_once DRUPAL_ROOT . '/includes/database/query.inc';
require_once DRUPAL_ROOT . '/includes/database/select.inc';
require_once DRUPAL_ROOT . '/includes/database/schema.inc';
foreach (glob(DRUPAL_ROOT . '/includes/database/' . $driver . '/*.inc') as $include_file) {
require_once $include_file;
}
$included = TRUE;
}
}
/** /**
* Callback to install the system module. * Callback to install the system module.
* *
...@@ -577,7 +549,6 @@ function drupal_install_initialize_database() { ...@@ -577,7 +549,6 @@ function drupal_install_initialize_database() {
function drupal_install_system() { function drupal_install_system() {
$system_path = dirname(drupal_get_filename('module', 'system', NULL)); $system_path = dirname(drupal_get_filename('module', 'system', NULL));
require_once DRUPAL_ROOT . '/' . $system_path . '/system.install'; require_once DRUPAL_ROOT . '/' . $system_path . '/system.install';
drupal_install_initialize_database();
module_invoke('system', 'install'); module_invoke('system', 'install');
$system_versions = drupal_get_schema_versions('system'); $system_versions = drupal_get_schema_versions('system');
......
...@@ -39,6 +39,7 @@ function _drupal_maintenance_theme() { ...@@ -39,6 +39,7 @@ function _drupal_maintenance_theme() {
// Because we are operating in a crippled environment, we need to // Because we are operating in a crippled environment, we need to
// bootstrap just enough to allow hook invocations to work. // bootstrap just enough to allow hook invocations to work.
require_once DRUPAL_ROOT . '/includes/database/database.inc'; require_once DRUPAL_ROOT . '/includes/database/database.inc';
spl_autoload_register('db_autoload');
$module_list['system']['filename'] = 'modules/system/system.module'; $module_list['system']['filename'] = 'modules/system/system.module';
module_list(TRUE, FALSE, FALSE, $module_list); module_list(TRUE, FALSE, FALSE, $module_list);
drupal_load('module', 'system'); drupal_load('module', 'system');
......
...@@ -102,9 +102,6 @@ function update_prepare_d7_bootstrap() { ...@@ -102,9 +102,6 @@ function update_prepare_d7_bootstrap() {
// Allow the database system to work even if the registry has not been // Allow the database system to work even if the registry has not been
// created yet. // created yet.
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
drupal_install_initialize_database();
spl_autoload_unregister('drupal_autoload_class');
spl_autoload_unregister('drupal_autoload_interface');
// The new cache_bootstrap bin is required to bootstrap to // The new cache_bootstrap bin is required to bootstrap to
// DRUPAL_BOOTSTRAP_SESSION, so create it here rather than in // DRUPAL_BOOTSTRAP_SESSION, so create it here rather than in
......
...@@ -566,6 +566,8 @@ protected function setUp() { ...@@ -566,6 +566,8 @@ protected function setUp() {
$this->originalPrefix = $db_prefix; $this->originalPrefix = $db_prefix;
$this->originalFileDirectory = file_directory_path(); $this->originalFileDirectory = file_directory_path();
spl_autoload_register('db_autoload');
// Reset all statics so that test is performed with a clean environment. // Reset all statics so that test is performed with a clean environment.
drupal_static_reset(); drupal_static_reset();
......
...@@ -185,7 +185,9 @@ function simpletest_test_form_submit($form, &$form_state) { ...@@ -185,7 +185,9 @@ function simpletest_test_form_submit($form, &$form_state) {
// Get list of tests. // Get list of tests.
$tests_list = array(); $tests_list = array();
foreach ($form_state['values'] as $class_name => $value) { foreach ($form_state['values'] as $class_name => $value) {
if (class_exists($class_name) && $value === 1) { // Since class_exists() will likely trigger an autoload lookup,
// we do the fast check first.
if ($value === 1 && class_exists($class_name)) {
$tests_list[] = $class_name; $tests_list[] = $class_name;
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment