diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 86eeaf8..bb6c3c3 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -483,11 +483,11 @@ function find_conf_path($http_host, $script_name, $require_settings = TRUE) { } /** - * 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 +503,7 @@ function config_get_config_directory($type = CONFIG_ACTIVE_DIRECTORY) { $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; } @@ -2421,20 +2421,24 @@ function drupal_get_bootstrap_phase() { * * @see Drupal\Core\DrupalKernel * - * @param $reset - * A new container instance to reset the Drupal container to. + * @param Symfony\Component\DependencyInjection\Container $new_container + * A new container instance to replace the current. + * @param bool $reset + * (optional) Internal use only. Whether to enforce a reset of the statically + * cached container. Pass NULL for $new_container to recreate a new Container + * from scratch in a subsequent call to this function. Used by tests. * * @return Symfony\Component\DependencyInjection\Container * The instance of the Container used to set up and maintain object * instances. */ -function drupal_container(Container $reset = NULL) { +function drupal_container(Container $new_container = NULL, $reset = FALSE) { // We do not use drupal_static() here because we do not have a mechanism by // which to reinitialize the stored objects, so a drupal_static_reset() call // would leave Drupal in a nonfunctional state. static $container = NULL; - if (isset($reset)) { - $container = $reset; + if (isset($new_container) || $reset) { + $container = $new_container; } elseif (!isset($container)) { // Return a ContainerBuilder instance with the bare essentials needed for any @@ -2462,6 +2466,13 @@ function drupal_container(Container $reset = NULL) { $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory') ->addArgument(new Reference('config.storage')) ->addArgument(new Reference('dispatcher')); + + // Register configuration state. + $container->setParameter('config.state.options', array( + 'directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY), + )); + $container->register('config.state', 'Drupal\Core\Config\FileStorage') + ->addArgument('%config.state.options%'); } return $container; } diff --git a/core/includes/config.inc b/core/includes/config.inc index ef98160..0448979 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -129,15 +129,15 @@ function config_sync_changes(array $config_changes, StorageInterface $source_sto } /** - * 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. - $source_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY))); + // Retrieve a list of differences between staging and the active store. + $source_storage = drupal_container()->get('config.state'); $target_storage = drupal_container()->get('config.storage'); $config_changes = config_sync_get_changes($source_storage, $target_storage); @@ -214,12 +214,12 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou } /** - * 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))); + $target_storage = drupal_container()->get('config.state'); $config_changes = config_sync_get_changes($source_storage, $target_storage); if (empty($config_changes)) { diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php index 2161896..8f2523a 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php @@ -7,8 +7,6 @@ namespace Drupal\config\Tests; -use Drupal\Core\Config\DatabaseStorage; -use Drupal\Core\Config\FileStorage; use Drupal\simpletest\WebTestBase; /** @@ -64,6 +62,8 @@ function testNoImport() { function testDeleted() { $name = 'config_test.system'; $dynamic_name = 'config_test.dynamic.default'; + $storage = $this->container->get('config.storage'); + $state = $this->container->get('config.state'); // Verify the default configuration values exist. $config = config($name); @@ -75,17 +75,15 @@ function testDeleted() { 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); + $state->delete($name); + $state->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($storage->read($name), FALSE); + $this->assertIdentical($storage->read($dynamic_name), FALSE); $config = config($name); $this->assertIdentical($config->get('foo'), NULL); @@ -107,34 +105,37 @@ function testDeleted() { function testNew() { $name = 'config_test.new'; $dynamic_name = 'config_test.dynamic.new'; + $storage = $this->container->get('config.storage'); + $state = $this->container->get('config.state'); // 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($state->exists($name), FALSE, $name . ' not found.'); + $this->assertIdentical($state->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( + ); + $state->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.'); + ); + $state->write($dynamic_name, $original_dynamic_data); + $this->assertIdentical($state->exists($name), TRUE, $name . ' found.'); + $this->assertIdentical($state->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 +152,27 @@ function testNew() { function testUpdated() { $name = 'config_test.system'; $dynamic_name = 'config_test.dynamic.default'; + $storage = $this->container->get('config.storage'); + $state = $this->container->get('config.state'); // Export. config_export(); + // Verify that the configuration objects to import exist. + $this->assertIdentical($state->exists($name), TRUE, $name . ' found.'); + $this->assertIdentical($state->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( + ); + $state->write($name, $original_name_data); + $original_dynamic_data = array( 'id' => 'default', 'label' => 'Updated', - )); + ); + $state->write($dynamic_name, $original_dynamic_data); // Verify the active store still returns the default values. $config = config($name); @@ -183,6 +189,10 @@ function testUpdated() { $config = config($dynamic_name); $this->assertIdentical($config->get('label'), 'Updated'); + // Verify that the original file content is still the same. + $this->assertIdentical($state->read($name), $original_name_data); + $this->assertIdentical($state->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 --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php index aa3ebd1..253d4df 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php @@ -721,12 +721,23 @@ protected function prepareEnvironment() { // 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; + } + + // Reset and create a new service container. + drupal_container(NULL, TRUE); + $this->container = drupal_container(); + + $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);