diff -u b/core/includes/bootstrap.inc b/core/includes/bootstrap.inc --- b/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -10,6 +10,7 @@ use Symfony\Component\DependencyInjection\Exception\RuntimeException as DependencyInjectionRuntimeException; use Symfony\Component\HttpFoundation\Request; use Drupal\Core\Language\Language; +use Exception; /** * @file @@ -483,11 +484,11 @@ } /** - * Returns the path of the configuration directory. + * Returns the path of a configuration directory. * * @param string $type - * Type of config directory to return. Drupal core provides 'active' and - * 'staging'. + * (optional) The type of config directory to return. Drupal core provides + * 'active' and 'staging'. Defaults to CONFIG_ACTIVE_DIRECTORY. * * @return string * The configuration directory path. @@ -503,7 +504,7 @@ $path = conf_path() . '/files/' . $config_directories[$type]; } else { - throw new Exception(t('The configuration directory type %type does not exist.', array('%type' => $type))); + throw new Exception(format_string('The configuration directory type %type does not exist.', array('%type' => $type))); } return $path; } diff -u b/core/includes/config.inc b/core/includes/config.inc --- b/core/includes/config.inc +++ b/core/includes/config.inc @@ -129,14 +129,14 @@ } /** - * Imports configuration from FileStorage to the active store. + * Imports configuration into the active store. * * @return bool|null * TRUE if configuration was imported successfully, FALSE in case of a * synchronization error, or NULL if there are no changes to synchronize. */ function config_import() { - // Retrieve a list of differences between FileStorage and the active store. + // Retrieve a list of differences between staging and the active store. $source_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); $target_storage = drupal_container()->get('config.storage'); @@ -214,10 +214,10 @@ } /** - * Exports configuration from the active store to FileStorage. + * Exports configuration from the active store to staging. */ function config_export() { - // Retrieve a list of differences between the active store and FileStorage. + // Retrieve a list of differences between the active store and staging. $source_storage = drupal_container()->get('config.storage'); $target_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); diff -u b/core/includes/install.core.inc b/core/includes/install.core.inc --- b/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -320,7 +320,7 @@ // Check existing settings.php. $install_state['database_verified'] = install_verify_database_settings(); - $install_state['config_verified'] = install_ensure_config_directory(CONFIG_ACTIVE_DIRECTORY) && install_ensure_config_directory(CONFIG_STAGING_DIRECTORY); + $install_state['config_verified'] = install_verify_config_directory(CONFIG_ACTIVE_DIRECTORY) && install_verify_config_directory(CONFIG_STAGING_DIRECTORY); $install_state['settings_verified'] = $install_state['config_verified'] && $install_state['database_verified']; if ($install_state['database_verified']) { diff -u b/core/includes/install.inc b/core/includes/install.inc --- b/core/includes/install.inc +++ b/core/includes/install.inc @@ -261,13 +261,12 @@ // manually defined in the existing already. 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)), - ) + ), + 'required' => TRUE, ); - // Rewrite settings.php, which also sets the value as global variable. drupal_rewrite_settings($settings); } @@ -290,6 +289,34 @@ } /** + * Checks whether a config directory name is defined, and if so, whether it + * exists and is writable. + * + * This partically duplicates install_ensure_config_directory(), but is required + * since the installer would create the config directory too early in the + * installation process otherwise (e.g., when only visiting install.php when + * there is a settings.php already, but not actually executing the installation). + * + * @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_verify_config_directory($type) { + global $config_directories; + if (!isset($config_directories[$type])) { + return FALSE; + } + $config_directory = config_get_config_directory($type); + if (is_dir($config_directory) && is_writable($config_directory)) { + return TRUE; + } + return FALSE; +} + +/** * Ensures that the config directory exists and is writable, or can be made so. * * @param string $type diff -u b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php --- b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php @@ -64,6 +64,8 @@ function testDeleted() { $name = 'config_test.system'; $dynamic_name = 'config_test.dynamic.default'; + $active_storage = new DatabaseStorage(); + $staging_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); // Verify the default configuration values exist. $config = config($name); @@ -75,17 +77,15 @@ config_export(); // Delete the configuration objects from the staging directory. - $file_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); - $file_storage->delete($name); - $file_storage->delete($dynamic_name); + $staging_storage->delete($name); + $staging_storage->delete($dynamic_name); // Import. config_import(); // Verify the values have disappeared. - $database_storage = new DatabaseStorage(); - $this->assertIdentical($database_storage->read($name), FALSE); - $this->assertIdentical($database_storage->read($dynamic_name), FALSE); + $this->assertIdentical($active_storage->read($name), FALSE); + $this->assertIdentical($active_storage->read($dynamic_name), FALSE); $config = config($name); $this->assertIdentical($config->get('foo'), NULL); @@ -107,34 +107,36 @@ function testNew() { $name = 'config_test.new'; $dynamic_name = 'config_test.dynamic.new'; + $staging_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); // Export. config_export(); - // Verify the new configuration does not exist in the staging 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.'); + // Verify the configuration to create does not exist yet. + $this->assertIdentical($staging_storage->exists($name), FALSE, $name . ' not found.'); + $this->assertIdentical($staging_storage->exists($dynamic_name), FALSE, $dynamic_name . ' not found.'); // Create new configuration objects in the staging directory. - $file_storage->write($name, array( + $original_name_data = array( 'add_me' => 'new value', - )); - $file_storage->write($dynamic_name, array( + ); + $staging_storage->write($name, $original_name_data); + $original_dynamic_data = array( 'id' => 'new', 'label' => 'New', - )); - $this->assertIdentical($file_storage->exists($name), TRUE, $name . ' found.'); - $this->assertIdentical($file_storage->exists($dynamic_name), TRUE, $dynamic_name . ' found.'); + ); + $staging_storage->write($dynamic_name, $original_dynamic_data); + $this->assertIdentical($staging_storage->exists($name), TRUE, $name . ' found.'); + $this->assertIdentical($staging_storage->exists($dynamic_name), TRUE, $dynamic_name . ' found.'); // Import. config_import(); // Verify the values appeared. $config = config($name); - $this->assertIdentical($config->get('add_me'), 'new value'); + $this->assertIdentical($config->get('add_me'), $original_name_data['add_me']); $config = config($dynamic_name); - $this->assertIdentical($config->get('label'), 'New'); + $this->assertIdentical($config->get('label'), $original_dynamic_data['label']); // Verify that appropriate module API hooks have been invoked. $this->assertFalse(isset($GLOBALS['hook_config_test']['load'])); @@ -151,22 +153,26 @@ function testUpdated() { $name = 'config_test.system'; $dynamic_name = 'config_test.dynamic.default'; + $staging_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); // Export. config_export(); + // Verify that the configuration objects to import exist. + $this->assertIdentical($staging_storage->exists($name), TRUE, $name . ' found.'); + $this->assertIdentical($staging_storage->exists($dynamic_name), TRUE, $dynamic_name . ' found.'); + // Replace the file content of the existing configuration objects in the // staging 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( + $original_name_data = array( 'foo' => 'beer', - )); - $file_storage->write($dynamic_name, array( + ); + $staging_storage->write($name, $original_name_data); + $original_dynamic_data = array( 'id' => 'default', 'label' => 'Updated', - )); + ); + $staging_storage->write($dynamic_name, $original_dynamic_data); // Verify the active store still returns the default values. $config = config($name); @@ -183,6 +189,10 @@ $config = config($dynamic_name); $this->assertIdentical($config->get('label'), 'Updated'); + // Verify that the original file content is still the same. + $this->assertIdentical($staging_storage->read($name), $original_name_data); + $this->assertIdentical($staging_storage->read($dynamic_name), $original_dynamic_data); + // Verify that appropriate module API hooks have been invoked. $this->assertTrue(isset($GLOBALS['hook_config_test']['load'])); $this->assertTrue(isset($GLOBALS['hook_config_test']['presave'])); diff -u b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php --- b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -721,12 +721,19 @@ // uses drupal_valid_test_ua() to adjust the config directory paths to // a test-prefix-specific directory within the public files directory. // @see config_get_config_directory() - require_once DRUPAL_ROOT . '/core/includes/install.inc'; - foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $config_env) { - $GLOBALS['config_directories'][$config_env] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $config_env; - install_ensure_config_directory($config_env); + $GLOBALS['config_directories'] = array(); + foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $type) { + $GLOBALS['config_directories'][$type] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type; + } + + $this->configDirectories = array(); + include_once DRUPAL_ROOT . '/core/includes/install.inc'; + foreach ($GLOBALS['config_directories'] as $type => $path) { + if (!install_ensure_config_directory($type)) { + return FALSE; + } + $this->configDirectories[$type] = $this->originalFileDirectory . '/' . $path; } - $this->configDirectories = $GLOBALS['config_directories']; // Log fatal errors. ini_set('log_errors', 1); diff -u b/sites/default/default.settings.php b/sites/default/default.settings.php --- b/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -257,10 +257,12 @@ * @todo Flesh this out, provide more details, etc. * * Example: + * @code * $config_directories = array( * CONFIG_ACTIVE_DIRECTORY => '/some/directory/outside/webroot', * CONFIG_STAGING_DIRECTORY => '/another/directory/outside/webroot', * ); + * @endcode */ $config_directories = array();