=== modified file 'includes/bootstrap.inc' --- includes/bootstrap.inc 2008-11-11 22:39:58 +0000 +++ includes/bootstrap.inc 2008-11-15 16:56:17 +0000 @@ -413,8 +413,7 @@ function conf_init() { global $base_url, $base_path, $base_root; // Export the following settings.php variables to the global namespace - global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access; - $conf = array(); + global $db_prefix, $cookie_domain, $installed_profile, $update_free_access; if (!drupal_valid_http_host()) { // HTTP_HOST is invalid, e.g. if containing slashes it may be an attack. @@ -566,21 +565,8 @@ function drupal_get_filename($type, $nam * with variable_set() as well as those explicitly specified in the configuration * file. */ -function variable_init($conf = array()) { - // NOTE: caching the variables improves performance by 20% when serving cached pages. - if ($cached = cache_get('variables', 'cache')) { - $variables = $cached->data; - } - else { - $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed()); - cache_set('variables', $variables); - } - - foreach ($conf as $name => $value) { - $variables[$name] = $value; - } - - return $variables; +function variable_init() { + return array_map('unserialize', Database::getConnection('_bootstrap')->query('SELECT name, value FROM {variable}')->fetchAllKeyed()); } /** @@ -1053,7 +1039,7 @@ function drupal_anonymous_user($session * DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input data. */ function drupal_bootstrap($phase = NULL) { - static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; + static $phases = array(DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; if (isset($phase)) { while ($phases && $phase > $completed_phase) { @@ -1077,16 +1063,32 @@ function drupal_get_bootstrap_phase() { } function _drupal_bootstrap($phase) { - global $conf; + global $conf, $databases; switch ($phase) { - case DRUPAL_BOOTSTRAP_CONFIGURATION: + case DRUPAL_BOOTSTRAP_DATABASE: + // Initialize the database system. Note that the connection + // won't be initialized until it is actually requested. + require_once DRUPAL_ROOT . '/includes/database/database.inc'; + // Register autoload functions so that we can access classes and interfaces. + spl_autoload_register('drupal_autoload_class'); + spl_autoload_register('drupal_autoload_interface'); + // Initialize configuration variables. + $conf = variable_init(); drupal_initialize_variables(); - // Start a page timer: - timer_start('page'); // Initialize the configuration conf_init(); + $databases = variable_get('databases', NULL); + // If there are no databases then we need to install, but first we + // rebuild the registry and then the next page will build the menu. + if (!$databases && !(isset($_GET['q']) && $_GET['q'] == 'install')) { + registry_rebuild(); + require_once DRUPAL_ROOT . '/includes/install.inc'; + install_goto('index.php?q=install'); + } + // Start a page timer: + timer_start('page'); break; case DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE: @@ -1102,15 +1104,6 @@ function _drupal_bootstrap($phase) { } break; - case DRUPAL_BOOTSTRAP_DATABASE: - // Initialize the database system. Note that the connection - // won't be initialized until it is actually requested. - require_once DRUPAL_ROOT . '/includes/database/database.inc'; - // Register autoload functions so that we can access classes and interfaces. - spl_autoload_register('drupal_autoload_class'); - spl_autoload_register('drupal_autoload_interface'); - break; - case DRUPAL_BOOTSTRAP_ACCESS: // Deny access to blocked IP addresses - t() is not yet available. if (drupal_is_denied(ip_address())) { @@ -1126,11 +1119,6 @@ function _drupal_bootstrap($phase) { session_start(); break; - case DRUPAL_BOOTSTRAP_VARIABLES: - // Initialize configuration variables, using values from settings.php if available. - $conf = variable_init(isset($conf) ? $conf : array()); - break; - case DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE: // Load module handling. require_once DRUPAL_ROOT . '/includes/module.inc'; @@ -1514,7 +1502,7 @@ function _registry_check_code($type, $na // This function may get called when the default database is not active, but // there is no reason we'd ever want to not use the default database for // this query. - $file = Database::getConnection('default')->query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array( + $file = Database::getConnection('_bootstrap')->query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array( ':name' => $name, ':type' => $type, )) === modified file 'includes/database/database.inc' --- includes/database/database.inc 2008-11-15 08:23:06 +0000 +++ includes/database/database.inc 2008-11-15 16:59:56 +0000 @@ -916,9 +916,7 @@ abstract class Database { } if (!isset(self::$connections[$key][$target])) { - // If we're trying to open a target that doesn't exist, we need to know - // what the actual target we got was. - $target = self::openConnection(self::$activeKey, $target); + $target = self::openConnection($key, $target); } return isset(self::$connections[$key][$target]) ? self::$connections[$key][$target] : NULL; @@ -961,9 +959,7 @@ abstract class Database { final protected static function parseConnectionInfo() { global $databases; - _db_check_install_needed(); - - $databaseInfo = $databases; + $databaseInfo = $databases ? $databases : array(); foreach ($databaseInfo as $index => $info) { foreach ($databaseInfo[$index] as $target => $value) { // If there is no "driver" property, then we assume it's an array of @@ -974,6 +970,11 @@ abstract class Database { } } } + $databaseInfo['_bootstrap']['default'] = array( + 'driver' => 'sqlite', + 'database' => 'sites/default/files/.ht.boot.sqlite', + ); + $databaseInfo['default'] = $databaseInfo['_bootstrap']; self::$databaseInfo = $databaseInfo; } @@ -1036,7 +1037,7 @@ abstract class Database { final protected static function openConnection($key, $target) { global $db_prefix; - if (empty(self::$databaseInfo)) { + if (empty(self::$databaseInfo[$key])) { self::parseConnectionInfo(); } try { === modified file 'includes/form.inc' --- includes/form.inc 2008-11-15 15:32:36 +0000 +++ includes/form.inc 2008-11-15 23:57:23 +0000 @@ -1,5 +1,5 @@ $block) { // $key == module_delta $output .= theme('block', $block); @@ -1782,7 +1782,7 @@ function template_preprocess(&$variables $variables['logged_in'] = FALSE; if ($variables['db_is_active'] = db_is_active() && !defined('MAINTENANCE_MODE')) { // Check for administrators. - if (user_access('access administration pages')) { + if (module_invoke('user', 'access', 'access administration pages')) { $variables['is_admin'] = TRUE; } // Flag front page status. === modified file 'install.php' --- install.php 2008-11-10 05:22:56 +0000 +++ install.php 2008-11-16 00:16:28 +0000 @@ -271,7 +271,6 @@ function install_settings_form(&$form_st '#default_value' => empty($database['username']) ? '' : $database['username'], '#size' => 45, '#maxlength' => 45, - '#required' => TRUE, ); // Database username === modified file 'modules/system/system.info' --- modules/system/system.info 2008-10-12 01:23:01 +0000 +++ modules/system/system.info 2008-11-16 01:18:12 +0000 @@ -6,6 +6,7 @@ version = VERSION core = 7.x files[] = system.module files[] = system.admin.inc +files[] = system.install.inc files[] = image.gd.inc files[] = system.install required = TRUE === added file 'modules/system/system.install.inc' --- modules/system/system.install.inc 1970-01-01 00:00:00 +0000 +++ modules/system/system.install.inc 2008-11-16 02:07:05 +0000 @@ -0,0 +1,245 @@ +filename; + // Load profile details and store them for later retrieval. + $function = $profile->name . '_profile_details'; + if (function_exists($function)) { + $details = $function(); + } + $profiles[$profile->name] = $details; + + // Determine the name of the profile; default to file name if defined name + // is unspecified. + $name = isset($details['name']) ? $details['name'] : $profile->name; + $names[$profile->name] = $name; + } + + // Display radio buttons alphabetically by human-readable name. + natcasesort($names); + + foreach ($names as $profile => $name) { + $form['profile'][$name] = array( + '#type' => 'radio', + '#value' => 'default', + '#return_value' => $profile, + '#title' => $name, + '#description' => isset($profiles[$profile]['description']) ? $profiles[$profile]['description'] : '', + '#parents' => array('profile'), + ); + } + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save and continue'), + ); + break; + case 'database': + $drivers = drupal_detect_database_types(); + if (!$drivers) { + $form['no_drivers'] = array( + '#markup' => t('Your web server does not appear to support any common database types. Check with your hosting provider to see if they offer any databases that Drupal supports.', array('@drupal-databases' => 'http://drupal.org/node/270#database')), + ); + } + else { + $form['basic_options'] = array( + '#type' => 'fieldset', + '#title' => t('Basic options'), + '#description' => '

' . t('To set up your @drupal database, enter the following information.', array('@drupal' => $profile_name)) . '

', + '#tree' => TRUE, + ); + + if (count($drivers) == 1) { + $form['basic_options']['driver'] = array( + '#type' => 'hidden', + '#value' => current(array_keys($drivers)), + ); + $database_description = t('The name of the %driver database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('%driver' => current($drivers), '@drupal' => drupal_install_profile_name())); + } + else { + $form['basic_options']['driver'] = array( + '#type' => 'radios', + '#title' => t('Database type'), + '#required' => TRUE, + '#options' => $drivers, + '#default_value' => !empty($database['driver']) ? $database['driver'] : current(array_keys($drivers)), + '#description' => t('The type of database your @drupal data will be stored in.', array('@drupal' => $profile_name)), + ); + $database_description = t('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => $profile_name)); + } + + // Database name + $form['basic_options']['database'] = array( + '#type' => 'textfield', + '#title' => t('Database name'), + '#default_value' => '', + '#size' => 45, + '#maxlength' => 45, + '#required' => TRUE, + '#description' => $database_description, + ); + + // Database username + $form['basic_options']['username'] = array( + '#type' => 'textfield', + '#title' => t('Database username'), + '#default_value' => '', + '#size' => 45, + '#maxlength' => 45, + ); + + // Database username + $form['basic_options']['password'] = array( + '#type' => 'password', + '#title' => t('Database password'), + '#default_value' => '', + '#size' => 45, + '#maxlength' => 45, + ); + + $form['advanced_options'] = array( + '#type' => 'fieldset', + '#title' => t('Advanced options'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#description' => t("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider."), + '#tree' => TRUE, + ); + + // Database host + $form['advanced_options']['host'] = array( + '#type' => 'textfield', + '#title' => t('Database host'), + '#default_value' => empty($database['host']) ? 'localhost' : $database['host'], + '#size' => 45, + '#maxlength' => 45, + '#required' => TRUE, + '#description' => t('If your database is located on a different server, change this.'), + ); + + // Database port + $form['advanced_options']['port'] = array( + '#type' => 'textfield', + '#title' => t('Database port'), + '#default_value' => '', + '#size' => 45, + '#maxlength' => 45, + '#description' => t('If your database server is listening to a non-standard port, enter its number.'), + ); + // Table prefix + $db_prefix = ($profile == 'default') ? 'drupal_' : $profile . '_'; + $form['advanced_options']['db_prefix'] = array( + '#type' => 'textfield', + '#title' => t('Table prefix'), + '#default_value' => '', + '#size' => 45, + '#maxlength' => 45, + '#description' => t('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => $profile_name, '%prefix' => $db_prefix)), + '#parents' => array('db_prefix'), + ); + + $form['save'] = array( + '#type' => 'submit', + '#value' => t('Save and continue'), + ); + } + break; + } + return $form; +} + +function system_install_form_submit($form, &$form_state) { + $current_step = $form_state['install']['step']; + switch ($current_step) { + case 'profile-select': + variable_set('install_profile', $form_state['values']['profile']); + break; + case 'database': + variable_set('databases', array('default' => array('default' => $form_state['values']['basic_options'] + $form_state['values']['advanced_options']))); + break; + } + $break = FALSE; + foreach ($form['#install_tasks'] as $step => $label) { + if ($break) { + break; + } + if ($step == $current_step) { + $break = TRUE; + } + } + $form_state['install']['step'] = $step; + $form_state['rebuild'] = TRUE; +} + +function _system_install_all_tasks($profile_files, $profile) { + // Default list of tasks. + $tasks = array( + 'profile-select' => t('Choose profile'), + #'locale-select' => t('Choose language'), + #'requirements' => t('Verify requirements'), + 'database' => t('Set up database'), + 'profile-install-batch' => t('Install profile'), + 'configure' => t('Configure site'), + ); + // If we have only one profile, remove 'Choose profile' + // and rename 'Install profile'. + if (count($profile_files) == 1) { + unset($tasks['profile-select']); + $tasks['profile-install-batch'] = t('Install site'); + } + + // Add tasks defined by the profile. + if ($profile) { + $function = $profile . '_profile_task_list'; + if (function_exists($function)) { + $result = $function(); + if (is_array($result)) { + $tasks += $result; + } + } + } + + // Add finished step as the last task. + $tasks['finished'] = t('Finished'); + return $tasks; +} + +/** + * Find all .profile files. + */ +function _system_install_find_profiles() { + return file_scan_directory('./profiles', '/\.profile$/', array('.', '..', 'CVS'), 0, TRUE, 'name', 0); +} + +function _system_install_task_list() { + static $storage; + if (func_num_args()) { + $storage = func_get_args(); + } + return $storage; +} === modified file 'modules/system/system.module' --- modules/system/system.module 2008-11-15 08:23:06 +0000 +++ modules/system/system.module 2008-11-16 01:37:39 +0000 @@ -350,6 +350,12 @@ function system_elements() { * Implementation of hook_menu(). */ function system_menu() { + $items['install'] = array( + 'title' => 'Install system', + 'page callback' => 'system_install_page', + 'access callback' => '_system_install_access', + 'type' => MENU_CALLBACK, + ); $items['system/files'] = array( 'title' => 'File download', 'page callback' => 'file_download', @@ -698,6 +704,13 @@ function _system_themes_access($theme) { } /** + * Menu item access callback - check that there are no databases. + */ +function _system_install_access() { + return !variable_get('databases', NULL); +} + +/** * Implementation of hook_init(). */ function system_init() {