diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index c14ab53215995a4bbc13ca2e03044cb1d5bd24db..1109452a69619de630826c738812ffd34185caa4 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -387,6 +387,13 @@ function conf_path($require_settings = TRUE, $reset = FALSE) { return $conf; } + // Check for a simpletest override. + if ($simpletest_conf_path = _drupal_simpletest_conf_path()) { + $conf = $simpletest_conf_path; + return $conf; + } + + // Otherwise, use the normal $conf_path. $script_name = $_SERVER['SCRIPT_NAME']; if (!$script_name) { $script_name = $_SERVER['SCRIPT_FILENAME']; @@ -396,6 +403,50 @@ function conf_path($require_settings = TRUE, $reset = FALSE) { return $conf; } +/** + * Determines whether to use an overridden value for conf_path(). + * + * Simpletest may provide a secondary, test-specific settings.php file to load + * after the primary one used by the parent site and override its variables. + * - If the child settings.php does not override $conf_path, then this function + * returns FALSE and conf_path() returns the directory of the primary + * settings.php. + * - If the child settings.php does override $conf_path, then + * _drupal_load_test_overrides() sets the 'simpletest_conf_path' setting, and + * this function returns that to conf_path(), causing installations and + * upgrades to act on that one. + * + * @return string|false + * The overridden $conf_path, or FALSE if the $conf_path should not currently + * be overridden. + * + * @see conf_path() + * @see _drupal_load_test_overrides() + */ +function _drupal_simpletest_conf_path() { + // Ensure that the settings object is available. conf_path() is called once + // before the Settings class is included, and at that point it should still + // load the primary $conf_path. See drupal_settings_initialize(). + if (!class_exists('Drupal\Component\Utility\Settings', FALSE)) { + return FALSE; + } + + // If no $simpletest_conf_path is set, use the normal $conf_path. + if (!($simpletest_conf_path = settings()->get('simpletest_conf_path'))) { + return FALSE; + } + + // Ensure that this is actually a simpletest request. We can't check this + // before settings.php is loaded. + if (!drupal_valid_test_ua()) { + return FALSE; + } + + // When the $simpletest_conf_path is set in a valid test request, + // return that path. + return $simpletest_conf_path; +} + /** * Finds the appropriate configuration directory for a given host and path. * @@ -474,11 +525,7 @@ function find_conf_path($http_host, $script_name, $require_settings = TRUE) { function config_get_config_directory($type = CONFIG_ACTIVE_DIRECTORY) { global $config_directories; - if ($test_prefix = drupal_valid_test_ua()) { - // @see Drupal\simpletest\WebTestBase::setUp() - $path = conf_path() . '/files/simpletest/' . substr($test_prefix, 10) . '/config_' . $type; - } - elseif (!empty($config_directories[$type])) { + if (!empty($config_directories[$type])) { // Allow a configuration directory path to be outside of webroot. if (empty($config_directories[$type]['absolute'])) { $path = conf_path() . '/files/' . $config_directories[$type]['path']; @@ -2566,6 +2613,7 @@ function drupal_valid_test_ua($new_prefix = NULL) { // and the HMAC must match. if ($time_diff >= 0 && $time_diff <= 5 && $hmac == drupal_hmac_base64($check_string, $key)) { $test_prefix = $prefix; + _drupal_load_test_overrides($test_prefix); return $test_prefix; } } @@ -2574,6 +2622,43 @@ function drupal_valid_test_ua($new_prefix = NULL) { return $test_prefix; } +/** + * Overrides low-level and environment-specific configuration. + * + * Very strictly for internal use only. + * + * Loads settings.php from the simpletest public files directory. These files + * can change the global $conf, the global $config_directories, the return + * value of conf_path(), and settings(). + * + * @param string $test_prefix + * The simpletest prefix. + */ +function _drupal_load_test_overrides($test_prefix) { + global $conf, $config_directories; + + // Do not use the parent site's config directories. Use only the child site's. + // @see Drupal\simpletest\TestBase::prepareConfigDirectories() + $path_prefix = 'simpletest/' . substr($test_prefix, 10); + $config_directories = array(); + foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $type) { + $config_directories[$type] = array('path' => $path_prefix . '/config_' . $type); + } + + // Check for and load a settings.php file in the simpletest files directory. + $filename = conf_path() . '/files/' . $path_prefix . '/settings.php'; + if (file_exists($filename)) { + $settings = settings()->getAll(); + $conf_path = &drupal_static('conf_path'); + // This can override $conf, $conf_path, $settings, and $config_directories. + include $filename; + // Keep the overriden $conf_path alive across drupal_static_reset() calls. + // @see conf_path() + $settings['simpletest_conf_path'] = $conf_path; + new Settings($settings); + } +} + /** * Generates a user agent string with a HMAC and timestamp for simpletest. */ diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 5cca38afd1d58186653c1218126f0626159eede1..4e7b6b1d4893d0bd1453d869c071fcc2e05bbf8a 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -858,6 +858,36 @@ protected function setUp() { $this->setup = TRUE; } + /** + * Writes a test-specific settings.php file for the child site. + * + * The child site loads this after the parent site's settings.php, so settings + * here override those. + * + * @param $settings An array of settings to write out, in the format expected + * by drupal_rewrite_settings(). + * + * @see _drupal_load_test_overrides() + * @see drupal_rewrite_settings() + */ + protected function writeSettings($settings) { + // drupal_rewrite_settings() sets the in-memory global variables in addition + // to writing the file. We'll want to restore the original globals. + foreach (array_keys($settings) as $variable_name) { + $original_globals[$variable_name] = isset($GLOBALS[$variable_name]) ? $GLOBALS[$variable_name] : NULL; + } + + include_once DRUPAL_ROOT . '/core/includes/install.inc'; + $filename = $this->public_files_directory . '/settings.php'; + file_put_contents($filename, "<?php\n"); + drupal_rewrite_settings($settings, $filename); + + // Restore the original globals. + foreach ($original_globals as $variable_name => $value) { + $GLOBALS[$variable_name] = $value; + } + } + /** * Reset all data structures after having enabled new modules. * diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalAnonymousUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalAnonymousUpgradePathTest.php new file mode 100644 index 0000000000000000000000000000000000000000..01ce148d5d57fd1eabe9c8521cda7b4bdda2ce5b --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalAnonymousUpgradePathTest.php @@ -0,0 +1,52 @@ +<?php + +/** + * @file + * Contains \Drupal\system\Tests\Upgrade\BareMinimalAnonymousUpgradePathTest. + */ + +namespace Drupal\system\Tests\Upgrade; + +/** + * Tests the upgrade path without prior creation of config directions. + */ +class BareMinimalAnonymousUpgradePathTest extends BareMinimalUpgradePathTest { + + public static function getInfo() { + return array( + 'name' => 'Basic minimal profile upgrade, free access', + 'description' => 'Basic upgrade path tests for a minimal profile install with a bare database and update_free_access set to TRUE.', + 'group' => 'Upgrade path', + ); + } + + /** + * Overrides \Drupal\system\Tests\Upgrade\UpgradePathTestBase::setUp(). + */ + public function setUp() { + parent::setUp(); + + // Override $update_free_access in settings.php to allow the anonymous user + // to run updates. + $settings['settings']['update_free_access'] = (object) array( + 'value' => TRUE, + 'required' => TRUE, + ); + $this->writeSettings($settings); + } + + /** + * Overrides \Drupal\system\Tests\Upgrade\UpgradePathTestBase::prepareD8Session(). + */ + protected function prepareD8Session() { + // There is no active session, so nothing needs to be done here. + } + + /** + * Overrides \Drupal\system\Tests\Upgrade\UpgradePathTestBase::assertSessionKept(). + */ + protected function finishUpgradeSession() { + // There is no active session, so nothing needs to be done here. + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalNoConfigUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalNoConfigUpgradePathTest.php new file mode 100644 index 0000000000000000000000000000000000000000..00feb8906ee1d942c5726cbe5197e885cbb36c31 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalNoConfigUpgradePathTest.php @@ -0,0 +1,68 @@ +<?php + +/** + * @file + * Contains \Drupal\system\Tests\Upgrade\BareMinimalNoConfigUpgradePathTest. + */ + +namespace Drupal\system\Tests\Upgrade; + +/** + * Tests the database upgrade path without creating config directories. + */ +class BareMinimalNoConfigUpgradePathTest extends BareMinimalUpgradePathTest { + + public static function getInfo() { + return array( + 'name' => 'Basic minimal profile upgrade, no config', + 'description' => 'Basic upgrade path tests for a minimal profile install with a bare database and config directory not pre-created.', + 'group' => 'Upgrade path', + ); + } + + /** + * Overrides \Drupal\system\Tests\Upgrade\UpgradePathTestBase::setUp(). + */ + public function setUp() { + parent::setUp(); + + // Override $conf_path and $config_directories in settings.php. + $settings['conf_path'] = (object) array( + 'value' => $this->public_files_directory, + 'required' => TRUE, + ); + $settings['config_directories'] = (object) array( + 'value' => array(), + 'required' => TRUE, + ); + $this->writeSettings($settings); + } + + /** + * Overrides \Drupal\system\Tests\Upgrade\UpgradePathTestBase::refreshVariables(). + */ + protected function refreshVariables() { + // Refresh the variables only if the site was already upgraded. + if ($this->upgradedSite) { + // update.php puts the new, randomized config directries in this file. + include $this->public_files_directory . '/settings.php'; + $GLOBALS['config_directories'] = array(); + foreach ($config_directories as $type => $data) { + // update.php runs as the child site, so writes the paths relative to + // that "$conf_path/files", but here, we're running as the parent site, + // so need to make the paths relative to our "conf_path()/files". + // + // Example: + // - Parent site conf_path(): 'sites/default' + // - Child site $conf_path: 'sites/default/files/simpletest/123456' + // - Child site $data['path']: 'config_xyz' + // - Desired result: 'simpletest/123456/files/config_xyz' + // + // @see config_get_config_directory() + $GLOBALS['config_directories'][$type]['path'] = substr($conf_path, strlen(conf_path() . '/files/')) . '/files/' . $data['path']; + } + parent::refreshVariables(); + } + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php index 9c51bee19953a000bab4ef3d7e819d7a38ff068d..b6feee4f1f0836034c907661c65647e7357aecdc 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\system\Tests\Upgrade\BareMinimalUpgradePathTest. + * Contains \Drupal\system\Tests\Upgrade\BareMinimalUpgradePathTest. */ namespace Drupal\system\Tests\Upgrade; @@ -16,6 +16,7 @@ * content) so that an upgrade from of a site under this profile may be tested. */ class BareMinimalUpgradePathTest extends UpgradePathTestBase { + public static function getInfo() { return array( 'name' => 'Basic minimal profile upgrade path, bare database', @@ -43,12 +44,7 @@ public function testBasicMinimalUpgrade() { $this->assertResponse(200); // Verify that we are still logged in. - $this->drupalGet('user'); - $this->clickLink(t('Edit')); - $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.'); - - // Logout and verify that we can login back in with our initial password. - $this->drupalLogout(); + $this->finishUpgradeSession(); $this->drupalLogin((object) array( 'uid' => 1, 'name' => 'admin', @@ -95,4 +91,14 @@ public function testBasicMinimalUpgrade() { $this->assertEqual(array('default' => 'Drupal\Core\Mail\PhpMail'), config('system.mail')->get('interface'), 'Default mail configuration set.'); } + /** + * Asserts that the session was kept during update. Also, log out. + */ + protected function finishUpgradeSession() { + $this->drupalGet('user'); + $this->clickLink(t('Edit')); + $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.'); + $this->drupalLogout(); + } + }