Commit aab51b93 authored by Dries's avatar Dries

- Patch #524728 by David_Rothstein, JoshuaRogers, JacobSingh et al: refactor...

- Patch #524728 by David_Rothstein, JoshuaRogers, JacobSingh et al: refactor install.php to allow Drupal to be installed from the command line.
parent 1115fba0
......@@ -126,6 +126,9 @@ Drupal 7.0, xxxx-xx-xx (development version)
and allow custom data fields to be attached to itself.
* Provides a subset of the features of the Content Construction
Kit (CCK) module.
- Installer:
* Refactored the installer into an API that allows Drupal to be installed
via a command line script.
- Page organization
* Made the help text area a full featured region with blocks.
* Site mission is replaced with the highlighted content block region and
......
......@@ -390,6 +390,66 @@ function conf_path($require_settings = TRUE, $reset = FALSE) {
return $conf;
}
/**
* Set appropriate server variables needed for command line scripts to work.
*
* This function can be called by command line scripts before bootstrapping
* Drupal, to ensure that the page loads with the desired server parameters.
* This is because many parts of Drupal assume that they are running in a web
* browser and therefore use information from the global PHP $_SERVER variable
* that does not get set when Drupal is run from the command line.
*
* In many cases, the default way in which this function populates the $_SERVER
* variable is sufficient, and it can therefore be called without passing in
* any input. However, command line scripts running on a multisite installation
* (or on any installation that has settings.php stored somewhere other than
* the sites/default folder) need to pass in the URL of the site to allow
* Drupal to detect the correct location of the settings.php file. Passing in
* the 'url' parameter is also required for functions like request_uri() to
* return the expected values.
*
* Most other parameters do not need to be passed in, but may be necessary in
* some cases; for example, if Drupal's ip_address() function needs to return
* anything but the standard localhost value ('127.0.0.1'), the command line
* script should pass in the desired value via the 'REMOTE_ADDR' key.
*
* @param $variables
* (optional) An associative array of variables within $_SERVER that should
* be replaced. If the special element 'url' is provided in this array, it
* will be used to populate some of the server defaults; it should be set to
* the URL of the current page request, excluding any $_GET request but
* including the script name (e.g., http://www.example.com/mysite/index.php).
*
* @see conf_path()
* @see request_uri()
* @see ip_address()
*/
function drupal_override_server_variables($variables = array()) {
// Set defaults based on the provided URL.
if (isset($variables['url'])) {
$url = parse_url($variables['url']);
unset($variables['url']);
}
else {
$url = array();
}
$url += array(
'path' => '',
'host' => 'localhost',
);
$defaults = array(
'HTTP_HOST' => $url['host'],
'SCRIPT_NAME' => $url['path'],
'REMOTE_ADDR' => '127.0.0.1',
'REQUEST_METHOD' => 'GET',
'SERVER_NAME' => NULL,
'SERVER_SOFTWARE' => 'PHP CLI',
'HTTP_USER_AGENT' => NULL,
);
// Replace elements of the $_SERVER array, as appropriate.
$_SERVER = $variables + $_SERVER + $defaults;
}
/**
* Initialize PHP environment.
*/
......@@ -1487,6 +1547,13 @@ function drupal_maintenance_theme() {
_drupal_maintenance_theme();
}
/**
* Return TRUE if a Drupal installation is currently being attempted.
*/
function drupal_installation_attempted() {
return defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'install';
}
/**
* Return the name of the localization function. Use in code that needs to
* run both during installation and normal operation.
......@@ -1496,7 +1563,7 @@ function get_t() {
// This is not converted to drupal_static because there is no point in
// resetting this as it can not change in the course of a request.
if (!isset($t)) {
$t = function_exists('install_main') ? 'st' : 't';
$t = drupal_installation_attempted() ? 'st' : 't';
}
return $t;
}
......
......@@ -15,6 +15,10 @@ function cache_get($key, $table = 'cache') {
return FALSE;
}
function cache_get_multiple(array &$cids, $bin = 'cache') {
return array();
}
function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL) {
return;
}
......
......@@ -3607,15 +3607,18 @@ function drupal_cron_cleanup() {
* An array of file objects of the specified type.
*/
function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1) {
global $profile;
global $install_state;
$config = conf_path();
// When this function is called during Drupal's initial installation process,
// the name of the profile that's about to be installed is stored in the global
// $profile variable. At all other times, the standard Drupal systems variable
// installation state. At all other times, the standard Drupal systems variable
// table contains the name of the current profile, and we can call variable_get()
// to determine what one is active.
if (!isset($profile)) {
if (isset($install_state['parameters']['profile'])) {
$profile = $install_state['parameters']['profile'];
}
else {
$profile = variable_get('install_profile', 'default');
}
$searchdir = array($directory);
......
......@@ -2509,7 +2509,7 @@ function db_result(DatabaseStatementInterface $statement) {
*/
function _db_check_install_needed() {
global $databases;
if (empty($databases) && !function_exists('install_main')) {
if (empty($databases) && !drupal_installation_attempted()) {
include_once DRUPAL_ROOT . '/includes/install.inc';
install_goto('install.php');
}
......
......@@ -705,7 +705,11 @@ function drupal_redirect_form($form, $redirect = NULL) {
call_user_func_array('drupal_goto', $goto);
}
else {
drupal_goto($goto);
// This function can be called from the installer, which guarantees
// that $redirect will always be a string, so catch that case here
// and use the appropriate redirect function.
$function = drupal_installation_attempted() ? 'install_goto' : 'drupal_goto';
$function($goto);
}
}
drupal_goto($_GET['q']);
......
......@@ -165,7 +165,8 @@ function drupal_set_installed_schema_version($module, $version) {
* The name defined in the profile's _profile_details() hook.
*/
function drupal_install_profile_name() {
global $profile;
global $install_state;
$profile = $install_state['parameters']['profile'];
static $name = NULL;
if (!isset($name)) {
......@@ -190,7 +191,6 @@ function drupal_install_profile_name() {
* The auto-detected $base_url that should be configured in settings.php
*/
function drupal_detect_baseurl($file = 'install.php') {
global $profile;
$proto = $_SERVER['HTTPS'] ? 'https://' : 'http://';
$host = $_SERVER['SERVER_NAME'];
$port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':' . $_SERVER['SERVER_PORT']);
......@@ -214,7 +214,7 @@ function drupal_detect_database_types() {
// without modifying the installer.
// Because we have no registry yet, we need to also include the install.inc
// file for the driver explicitly.
require_once DRUPAL_ROOT . '/includes/database/database.inc';
foreach (file_scan_directory(DRUPAL_ROOT . '/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) {
include_once "{$file->filepath}/install.inc";
include_once "{$file->filepath}/database.inc";
......@@ -346,7 +346,7 @@ public function runTasks() {
}
}
else {
drupal_set_message(st('Failed to run all tasks against the database server. The task %task wasn\'t found.', array('%task' => $task['function'])), 'error');
throw new DatabaseTaskException(st("Failed to run all tasks against the database server. The task %task wasn\'t found.", array('%task' => $task['function'])));
}
}
}
......@@ -471,11 +471,11 @@ function drupal_rewrite_settings($settings = array(), $prefix = '') {
$fp = fopen(DRUPAL_ROOT . '/' . $settings_file, 'w');
if ($fp && fwrite($fp, $buffer) === FALSE) {
drupal_set_message(st('Failed to modify %settings, please verify the file permissions.', array('%settings' => $settings_file)), 'error');
throw new Exception(st('Failed to modify %settings, please verify the file permissions.', array('%settings' => $settings_file)));
}
}
else {
drupal_set_message(st('Failed to open %settings, please verify the file permissions.', array('%settings' => $default_settings)), 'error');
throw new Exception(st('Failed to open %settings, please verify the file permissions.', array('%settings' => $default_settings)));
}
}
......@@ -497,24 +497,24 @@ function drupal_get_install_files($module_list = array()) {
/**
* Verify an install profile for installation.
*
* @param $profile
* Name of install profile to verify.
* @param $locale
* Name of locale used (if any).
* @param $install_state
* An array of information about the current installation state.
* @return
* The list of modules to install.
*/
function drupal_verify_profile($profile, $locale) {
function drupal_verify_profile($install_state) {
$profile = $install_state['parameters']['profile'];
$locale = $install_state['parameters']['locale'];
include_once DRUPAL_ROOT . '/includes/file.inc';
include_once DRUPAL_ROOT . '/includes/common.inc';
$profile_file = DRUPAL_ROOT . "/profiles/$profile/$profile.profile";
if (!isset($profile) || !file_exists($profile_file)) {
install_no_profile_error();
throw new Exception(install_no_profile_error());
}
$info = install_profile_info($profile);
$info = $install_state['profile_info'];
// Get a list of modules that exist in Drupal's assorted subdirectories.
$present_modules = array();
......@@ -927,17 +927,19 @@ function install_goto($path) {
*/
function st($string, $args = array()) {
static $locale_strings = NULL;
global $profile, $install_locale;
global $install_state;
if (!isset($locale_strings)) {
$locale_strings = array();
$filename = 'profiles/' . $profile . '/translations/' . $install_locale . '.po';
if (isset($install_state['parameters']['profile']) && isset($install_state['parameters']['locale'])) {
$filename = 'profiles/' . $install_state['parameters']['profile'] . '/translations/' . $install_state['parameters']['locale'] . '.po';
if (file_exists(DRUPAL_ROOT . '/' . $filename)) {
require_once DRUPAL_ROOT . '/includes/locale.inc';
$file = (object) array('filepath' => $filename);
_locale_import_read_po('mem-store', $file);
$locale_strings = _locale_import_one_string('mem-report');
}
}
}
require_once DRUPAL_ROOT . '/includes/theme.inc';
......@@ -974,7 +976,7 @@ function drupal_check_profile($profile) {
$profile_file = DRUPAL_ROOT . "/profiles/$profile/$profile.profile";
if (!isset($profile) || !file_exists($profile_file)) {
install_no_profile_error();
throw new Exception(install_no_profile_error());
}
$info = install_profile_info($profile);
......@@ -1053,8 +1055,6 @@ function drupal_check_module($module) {
* - name: The real name of the install profile for display purposes.
* - description: A brief description of the profile.
* - dependencies: An array of shortnames of other modules this install profile requires.
* - tasks: An associative array of tasks and the page title of each task that need to be
* completed for installation.
*
* Example of .info file:
* @verbatim
......@@ -1078,7 +1078,6 @@ function install_profile_info($profile, $locale = 'en') {
// Set defaults for module info.
$defaults = array(
'dependencies' => array(),
'tasks' => array(),
'description' => '',
'version' => NULL,
'php' => DRUPAL_MINIMUM_PHP,
......
This diff is collapsed.
......@@ -1056,8 +1056,8 @@ protected function setUp() {
drupal_get_schema(NULL, TRUE);
// Run default profile tasks.
$task = 'profile';
default_profile_tasks($task, '');
$install_state = array();
default_profile_site_setup($install_state);
// Rebuild caches.
node_types_rebuild();
......@@ -1073,7 +1073,7 @@ protected function setUp() {
// Restore necessary variables.
variable_set('install_profile', 'default');
variable_set('install_task', 'profile-finished');
variable_set('install_task', 'done');
variable_set('clean_url', $clean_url_original);
variable_set('site_mail', 'simpletest@example.com');
// Set up English language.
......
This diff is collapsed.
......@@ -4,7 +4,24 @@
/**
* Implement hook_profile_tasks().
*/
function default_profile_tasks(&$task, $url) {
function default_profile_tasks() {
$tasks = array(
'default_profile_site_setup' => array(),
);
return $tasks;
}
/**
* Installation task; perform actions to set up the site for this profile.
*
* This task does not return any output, meaning that control will be passed
* along to the next task without ending the page request.
*
* @param $install_state
* An array of information about the current installation state.
*/
function default_profile_site_setup(&$install_state) {
// Enable some standard blocks.
$values = array(
array(
......
......@@ -4,7 +4,23 @@
/**
* Implement hook_profile_tasks().
*/
function expert_profile_tasks(&$task, $url) {
function expert_profile_tasks() {
$tasks = array(
'expert_profile_site_setup' => array(),
);
return $tasks;
}
/**
* Installation task; perform actions to set up the site for this profile.
*
* This task does not return any output, meaning that control will be passed
* along to the next task without ending the page request.
*
* @param $install_state
* An array of information about the current installation state.
*/
function expert_profile_site_setup(&$install_state) {
// Enable some standard blocks.
$values = array(
......
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