diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index e173a95..8e37141 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -303,6 +303,20 @@ const REGISTRY_WRITE_LOOKUP_CACHE = 2; const DRUPAL_PHP_FUNCTION_PATTERN = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'; /** + * $config_directories key for active directory. + * + * @see config_get_config_directory + */ +const CONFIG_ACTIVE_DIRECTORY = 'active'; + +/** + * $config_directories key for staging directory. + * + * @see config_get_config_directory + */ +const CONFIG_STAGING_DIRECTORY = 'staging'; + +/** * Starts the timer with the specified name. * * If you start and stop the same timer multiple times, the measured intervals @@ -478,18 +492,25 @@ function find_conf_path($http_host, $script_name, $require_settings = TRUE) { /** * Returns the path of the configuration directory. * + * @param string $type + * Type of config directory to return. Drupal core provides 'active' and + * 'staging'. + * * @return string * The configuration directory path. */ -function config_get_config_directory() { - global $config_directory_name; +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'; + $path = conf_path() . '/files/simpletest/' . substr($test_prefix, 10) . '/config/' . $type; + } + elseif (!empty($config_directories[$type])) { + $path = conf_path() . '/files/' . $config_directories[$type]; } else { - $path = conf_path() . '/files/' . $config_directory_name; + throw new Exception(t('The configuration directory type %type does not exist.', array('%type' => $type))); } return $path; } @@ -682,7 +703,7 @@ function drupal_settings_initialize() { global $base_url, $base_path, $base_root, $script_path; // Export these settings.php variables to the global namespace. - global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name; + global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directories; $conf = array(); // Make conf_path() available as local variable in settings.php. diff --git a/core/includes/config.inc b/core/includes/config.inc index 347bf85..ef98160 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -137,7 +137,7 @@ function config_sync_changes(array $config_changes, StorageInterface $source_sto */ function config_import() { // Retrieve a list of differences between FileStorage and the active store. - $source_storage = new FileStorage(); + $source_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); $target_storage = drupal_container()->get('config.storage'); $config_changes = config_sync_get_changes($source_storage, $target_storage); @@ -219,7 +219,7 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou function config_export() { // Retrieve a list of differences between the active store and FileStorage. $source_storage = drupal_container()->get('config.storage'); - $target_storage = new FileStorage(); + $target_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); $config_changes = config_sync_get_changes($source_storage, $target_storage); if (empty($config_changes)) { diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index edaf8ec..454982a 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -313,7 +313,7 @@ function install_begin_request(&$install_state) { // Check existing settings.php. $install_state['database_verified'] = install_verify_database_settings(); - $install_state['config_verified'] = install_ensure_config_directory(); + $install_state['config_verified'] = install_ensure_config_directory(CONFIG_ACTIVE_DIRECTORY) && install_ensure_config_directory(CONFIG_STAGING_DIRECTORY); $install_state['settings_verified'] = $install_state['config_verified'] && $install_state['database_verified']; if ($install_state['database_verified']) { @@ -1046,8 +1046,8 @@ function install_settings_form_submit($form, &$form_state) { drupal_rewrite_settings($settings); - // Add the config directory to settings.php. - drupal_install_config_directory(); + // Add the config directories to settings.php. + drupal_install_config_directories(); // Indicate that the settings file has been verified, and check the database // for the last completed task, now that we have a valid connection. This diff --git a/core/includes/install.inc b/core/includes/install.inc index f1184a7..725c404 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -254,22 +254,26 @@ function drupal_rewrite_settings($settings = array()) { * @see install_settings_form_submit() * @see update_prepare_d8_bootstrap() */ -function drupal_install_config_directory() { - global $config_directory_name; +function drupal_install_config_directories() { + global $config_directories; // Add a randomized config directory name to settings.php, unless it was // manually defined in the existing already. - if (!$config_directory_name) { - $settings['config_directory_name'] = array( - 'value' => 'config_' . drupal_hash_base64(drupal_random_bytes(55)), + if (empty($config_directories)) { + $settings['config_directories'] = array( 'required' => TRUE, + 'value' => array( + CONFIG_ACTIVE_DIRECTORY => 'config/active_' . drupal_hash_base64(drupal_random_bytes(55)), + CONFIG_STAGING_DIRECTORY => 'config/staging_' . drupal_hash_base64(drupal_random_bytes(55)), + ) ); + // Rewrite settings.php, which also sets the value as global variable. drupal_rewrite_settings($settings); } // Ensure that the config directory exists or can be created, and is writable. - if (!install_ensure_config_directory()) { + if (!install_ensure_config_directory(CONFIG_ACTIVE_DIRECTORY)) { // This should never fail, since if the config directory was specified in // settings.php it will have already been created and verified earlier, and // if it wasn't specified in settings.php, it is created here inside the @@ -281,21 +285,37 @@ function drupal_install_config_directory() { '@handbook_url' => 'http://drupal.org/server-permissions', ))); } + // Ensure that the staging config directory exists or can be created, and is + // writable. + if (!install_ensure_config_directory(CONFIG_STAGING_DIRECTORY)) { + throw new Exception(st('The directory %directory could not be created or could not be made writable. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see the online handbook.', array( + '%directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY), + '@handbook_url' => 'http://drupal.org/server-permissions', + ))); + } + } /** * Ensures that the config directory exists and is writable, or can be made so. + * + * @param string $type + * Type of config directory to return. Drupal core provides 'active' and + * 'staging'. + * + * @return bool + * TRUE if the config directory exists and is writable. */ -function install_ensure_config_directory() { +function install_ensure_config_directory($type) { // The config directory must be defined in settings.php. - global $config_directory_name; - if (empty($config_directory_name)) { + global $config_directories; + if (!isset($config_directories[$type])) { return FALSE; } // The logic here is similar to that used by system_requirements() for other // directories that the installer creates. else { - $config_directory = config_get_config_directory(); + $config_directory = config_get_config_directory($type); return file_prepare_directory($config_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); } } diff --git a/core/includes/update.inc b/core/includes/update.inc index 30be3cd..5582bb4 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -89,7 +89,7 @@ function update_prepare_d8_bootstrap() { drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); // Check whether settings.php needs to be rewritten. - $settings_exist = !empty($GLOBALS['config_directory_name']); + $settings_exist = !empty($GLOBALS['config_directories']); // If any of the required settings needs to be written, then settings.php // needs to be writable. @@ -139,11 +139,11 @@ function update_prepare_d8_bootstrap() { // Update the environment for the language bootstrap if needed. update_prepare_d8_language(); - // Ensure the configuration directory exists and is writable or create it. - // If no $config_directory_name has been specified in settings.php and - // created manually already, and the directory cannot be created by the + // Ensure the configuration directories exist and are writable, or create + // them. If the directories have not been specified in settings.php and + // created manually already, and either directory cannot be created by the // web server, an exception will be thrown, halting the update. - drupal_install_config_directory(); + drupal_install_config_directories(); // Change language column to langcode in url_alias. if (db_table_exists('url_alias') && db_field_exists('url_alias', 'language')) { diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php index ec92fdf..5b8453a 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php @@ -47,8 +47,8 @@ class ConfigImportTest extends WebTestBase { // Export. config_export(); - // Delete the configuration objects. - $file_storage = new FileStorage(); + // Delete the configuration objects from the import directory. + $file_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); $file_storage->delete($name); $file_storage->delete($dynamic_name); @@ -73,15 +73,15 @@ class ConfigImportTest extends WebTestBase { $name = 'config_test.new'; $dynamic_name = 'config_test.dynamic.new'; - // Verify the configuration to create does not exist yet. - $file_storage = new FileStorage(); - $this->assertIdentical($file_storage->exists($name), FALSE, $name . ' not found.'); - $this->assertIdentical($file_storage->exists($dynamic_name), FALSE, $dynamic_name . ' not found.'); - // Export. config_export(); - // Create new configuration objects. + // Verify the new configuration does not exist in the import directory. + $file_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); + $this->assertIdentical($file_storage->exists($name), FALSE, $name . ' not found.'); + $this->assertIdentical($file_storage->exists($dynamic_name), FALSE, $dynamic_name . ' not found.'); + + // Create new configuration objects in the import directory. $file_storage->write($name, array( 'add_me' => 'new value', )); @@ -112,8 +112,9 @@ class ConfigImportTest extends WebTestBase { // Export. config_export(); - // Replace the file content of the existing configuration objects. - $file_storage = new FileStorage(); + // Replace the file content of the existing configuration objects in the + // import directory. + $file_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); $this->assertIdentical($file_storage->exists($name), TRUE, $name . ' found.'); $this->assertIdentical($file_storage->exists($dynamic_name), TRUE, $dynamic_name . ' found.'); $file_storage->write($name, array( diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php b/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php index 092687f..accb94b 100644 --- a/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/Storage/FileStorageTest.php @@ -25,7 +25,7 @@ class FileStorageTest extends ConfigStorageTestBase { function setUp() { parent::setUp(); $this->storage = new FileStorage(); - $this->invalidStorage = new FileStorage(array('directory' => $this->configFileDirectory . '/nonexisting')); + $this->invalidStorage = new FileStorage(array('directory' => $this->configActiveDirectory . '/nonexisting')); // FileStorage::listAll() requires other configuration data to exist. $this->storage->write('system.performance', config('system.performance')->get()); diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index f58e1de..2054df3 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -688,7 +688,7 @@ abstract class TestBase { // Backup statics and globals. $this->originalContainer = clone drupal_container(); $this->originalLanguage = $language_interface; - $this->originalConfigDirectory = $GLOBALS['config_directory_name']; + $this->originalConfigDirectories = $GLOBALS['config_directories']; // Save further contextual information. $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files'); @@ -720,9 +720,14 @@ abstract class TestBase { // The child site automatically adjusts the global $config_directory_name to // a test-prefix-specific directory within the public files directory. // @see config_get_config_directory() - $GLOBALS['config_directory_name'] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config'; - $this->configFileDirectory = $this->originalFileDirectory . '/' . $GLOBALS['config_directory_name']; - file_prepare_directory($this->configFileDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); + $GLOBALS['config_directory'] = array( + CONFIG_ACTIVE_DIRECTORY => 'simpletest/' . substr($this->databasePrefix, 10) . '/config/active', + CONFIG_STAGING_DIRECTORY => 'simpletest/' . substr($this->databasePrefix, 10) . '/config/staging', + ); + $this->configActiveDirectory = $this->originalFileDirectory . '/' . $GLOBALS['config_directory'][CONFIG_ACTIVE_DIRECTORY]; + $this->configStagingDirectory = $this->originalFileDirectory . '/' . $GLOBALS['config_directory'][CONFIG_STAGING_DIRECTORY]; + file_prepare_directory($this->configActiveDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); + file_prepare_directory($this->configStagingDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); // Log fatal errors. ini_set('log_errors', 1); @@ -780,7 +785,7 @@ abstract class TestBase { // Restore original statics and globals. drupal_container($this->originalContainer); $language_interface = $this->originalLanguage; - $GLOBALS['config_directory_name'] = $this->originalConfigDirectory; + $GLOBALS['config_directories'] = $this->originalConfigDirectories; // Restore original shutdown callbacks. $callbacks = &drupal_register_shutdown_function(); diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 0e42214..cb03863 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -330,14 +330,15 @@ function system_requirements($phase) { // Check the config directory if it is defined in settings.php. If it isn't // defined, the installer will create a valid config directory later, but // during runtime we must always display an error. - if (!empty($GLOBALS['config_directory_name'])) { - $directories[] = config_get_config_directory(); + if (!empty($GLOBALS['config_directories'])) { + $directories[] = config_get_config_directory(CONFIG_ACTIVE_DIRECTORY); + $directories[] = config_get_config_directory(CONFIG_STAGING_DIRECTORY); } elseif ($phase != 'install') { - $requirements['config directory'] = array( - 'title' => $t('Configuration directory'), + $requirements['config directories'] = array( + 'title' => $t('Configuration directories'), 'value' => $t('Not present'), - 'description' => $t('Your %file file must define the $config_directory_name variable as the name of a directory in which configuration files can be written.', array('%file' => conf_path() . '/settings.php')), + 'description' => $t('Your %file file must define the $config_directories variable as an array containing the name of a directories in which configuration files can be written.', array('%file' => conf_path() . '/settings.php')), 'severity' => REQUIREMENT_ERROR, ); } diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php index 2c12638..0e4626a 100755 --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -257,9 +257,12 @@ $drupal_hash_salt = ''; * @todo Flesh this out, provide more details, etc. * * Example: - * $config_directory_name = '/some/directory/outside/webroot'; + * $config_directories = array( + * CONFIG_ACTIVE_DIRECTORY => '/some/directory/outside/webroot', + * CONFIG_STAGING_DIRECTORY => '/another/directory/outside/webroot', + * ); */ -$config_directory_name = ''; +$config_directories = array(); /** * Base URL (optional).