diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 95adc95..f1bb22e 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -2575,6 +2575,8 @@ function drupal_fast_404() { * Returns TRUE if a Drupal installation is currently being attempted. */ function drupal_installation_attempted() { + return isset($GLOBALS['install_state']); + // @todo Entirely incompatible with non-interactive installer invoked from SimpleTest. return defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'install'; } diff --git a/core/includes/form.inc b/core/includes/form.inc index 395cca7..dfc1cb5 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -3178,6 +3178,10 @@ function form_process_checkbox($element, $form_state) { * Processes a checkboxes form element. */ function form_process_checkboxes($element) { + // The #type checkboxes element itself does not need validation. + // @todo Fix handling of values for checkboxes in programmed form submissions. + unset($element['#needs_validation']); + $value = is_array($element['#value']) ? $element['#value'] : array(); $element['#tree'] = TRUE; if (count($element['#options']) > 0) { diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 32ce838..adb810f 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -240,11 +240,10 @@ function install_begin_request(&$install_state) { if (!$install_state['interactive']) { drupal_override_server_variables($install_state['server']); } - // The user agent header is used to pass a database prefix in the request when // running tests. However, for security reasons, it is imperative that no // installation be permitted using such a prefix. - if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], "simpletest") !== FALSE) { + elseif (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], "simpletest") !== FALSE) { header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); exit; } @@ -1331,7 +1330,7 @@ function install_select_language(&$install_state) { } // One language, but not an interactive installation. Assume the user // knows what he is doing. - $langcode = current($files); + $file = current($files); $install_state['parameters']['langcode'] = $file->langcode; return; } @@ -1887,10 +1886,10 @@ function _install_configure_form($form, &$form_state, &$install_state) { $form['update_notifications']['update_status_module'] = array( '#type' => 'checkboxes', '#options' => array( - 1 => st('Check for updates automatically'), - 2 => st('Receive e-mail notifications'), + 'enable' => st('Check for updates automatically'), + 'notify' => st('Receive e-mail notifications'), ), - '#default_value' => array(1, 2), + '#default_value' => array('enable', 'notify'), '#description' => st('The system will notify you when updates and important security releases are available for installed components. Anonymous information about your site is sent to Drupal.org.', array('@drupal' => 'http://drupal.org')), '#weight' => 15, ); @@ -1929,12 +1928,12 @@ function install_configure_form_submit($form, &$form_state) { variable_set('site_default_country', $form_state['values']['site_default_country']); // Enable update.module if this option was selected. - if ($form_state['values']['update_status_module'][1]) { + if ($form_state['values']['update_status_module']['enable']) { module_enable(array('update'), FALSE); // Add the site maintenance account's email address to the list of // addresses to be notified when updates are available, if selected. - if ($form_state['values']['update_status_module'][2]) { + if ($form_state['values']['update_status_module']['notify']) { variable_set('update_notify_emails', array($form_state['values']['account']['mail'])); } } diff --git a/core/includes/install.inc b/core/includes/install.inc index d203db4..71e5f45 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -94,10 +94,10 @@ function drupal_load_updates() { * @see install_profile_info() */ function drupal_install_profile_distribution_name() { + global $install_state; // During installation, the profile information is stored in the global // installation state (it might not be saved anywhere yet). - if (drupal_installation_attempted()) { - global $install_state; + if (isset($install_state['profile_info']['distribution_name'])) { return $install_state['profile_info']['distribution_name']; } // At all other times, we load the profile via standard methods. diff --git a/core/modules/node/node.module b/core/modules/node/node.module index b0c7126..202dc76 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -3978,6 +3978,9 @@ function node_unpublish_by_keyword_action(Node $node, $context) { */ function node_requirements($phase) { $requirements = array(); + if ($phase !== 'runtime') { + return $requirements; + } // Ensure translations don't break at install time $t = get_t(); // Only show rebuild button if there are either 0, or 2 or more, rows diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index 5725ed8..e54c116 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -593,6 +593,14 @@ abstract class TestBase { ); } Database::addConnectionInfo('default', 'default', $connection_info['default']); + + // Additionally override global $databases, since the installer does not use + // the Database connection info. + // @see install_verify_database_settings() + // @see install_database_errors() + // @todo Fix installer to use Database connection info. + global $databases; + $databases['default']['default'] = $connection_info['default']; } /** @@ -623,6 +631,7 @@ abstract class TestBase { $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files'); $this->originalProfile = drupal_get_profile(); $this->originalUser = $user; + $this->originalSession = isset($_SESSION) ? $_SESSION : NULL; // Save and clean the shutdown callbacks array because it is static cached // and will be changed by the test run. Otherwise it will contain callbacks @@ -714,6 +723,7 @@ abstract class TestBase { // Restore original user session. $user = $this->originalUser; + $_SESSION = $this->originalSession; drupal_save_session(TRUE); } diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 0856611..b18fb07 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -602,13 +602,58 @@ abstract class WebTestBase extends TestBase { // the test's profile as a module. Without this, the installation profile of // the parent site (executing the test) is registered, and the test // profile's hook_install() and other hook implementations are never invoked. - $conf['install_profile'] = $this->profile; + // @todo Double-check this. +// $conf['install_profile'] = $this->profile; - // Perform the actual Drupal installation. - include_once DRUPAL_ROOT . '/core/includes/install.inc'; - drupal_install_system(); + // Set the 'simpletest_parent_profile' variable to add the parent profile's + // search path to the child site's search paths. + // @see drupal_system_listing() + $conf['simpletest_parent_profile'] = $this->originalProfile; - $this->preloadRegistry(); + // Run the Drupal installer non-interactively. + // @see install.php, install.core.inc + require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; + $connection_info = Database::getConnectionInfo('default'); + $this->root_user = (object) array( + 'name' => 'admin', + 'mail' => 'admin@example.com', + 'pass_raw' => $this->randomName(), + ); + $settings = array( + 'interactive' => FALSE, + 'parameters' => array( + 'profile' => $this->profile, + 'langcode' => 'en', + ), + 'forms' => array( + 'install_settings_form' => array( + 'driver' => $connection_info['default']['driver'], + 'username' => $connection_info['default']['username'], + 'host' => $connection_info['default']['host'], + 'port' => $connection_info['default']['port'], + 'password' => $connection_info['default']['password'], + 'database' => $connection_info['default']['database'], + 'prefix' => $connection_info['default']['prefix'], + ), + 'install_configure_form' => array( + 'site_name' => 'Drupal', + 'site_mail' => 'simpletest@example.com', + 'account' => array( + 'name' => $this->root_user->name, + 'mail' => $this->root_user->mail, + 'pass' => array( + 'pass1' => $this->root_user->pass_raw, + 'pass2' => $this->root_user->pass_raw, + ), + ), + 'update_status_module' => array( + 'enable' => FALSE, + 'notify' => FALSE, + ), + ), + ), + ); + install_drupal($settings); // Set path variables. variable_set('file_public_path', $this->public_files_directory); @@ -618,16 +663,8 @@ abstract class WebTestBase extends TestBase { // Set the 'simpletest_parent_profile' variable to add the parent profile's // search path to the child site's search paths. // @see drupal_system_listing() - // @todo This may need to be primed like 'install_profile' above. variable_set('simpletest_parent_profile', $this->originalProfile); - // Include the testing profile. - variable_set('install_profile', $this->profile); - $profile_details = install_profile_info($this->profile, 'en'); - - // Install the modules specified by the testing profile. - module_enable($profile_details['dependencies'], FALSE); - // Install modules needed for this test. This could have been passed in as // either a single array argument or a variable number of string arguments. // @todo Remove this compatibility layer in Drupal 8, and only accept @@ -641,32 +678,15 @@ abstract class WebTestBase extends TestBase { $this->assertTrue($success, t('Enabled modules: %modules', array('%modules' => implode(', ', $modules)))); } - // Run the profile tasks. - $install_profile_module_exists = db_query("SELECT 1 FROM {system} WHERE type = 'module' AND name = :name", array( - ':name' => $this->profile, - ))->fetchField(); - if ($install_profile_module_exists) { - module_enable(array($this->profile), FALSE); - } - // Reset/rebuild all data structures after enabling the modules. $this->resetAll(); - // Run cron once in that environment, as install.php does at the end of - // the installation process. - drupal_cron_run(); - // Ensure that the session is not written to the new environment and replace // the global $user session with uid 1 from the new test site. drupal_save_session(FALSE); // Login as uid 1. $user = user_load(1); - // Restore necessary variables. - variable_set('install_task', 'done'); - config('system.site')->set('mail', 'simpletest@example.com')->save(); - variable_set('date_default_timezone', date_default_timezone_get()); - // Set up English language. unset($conf['language_default']); $language_interface = language_default();