diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index 7209030..7f7cc11 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -113,12 +113,12 @@ public function installDefaultConfig($type, $name) { } // Gets a profile storage to search for overrides if necessary. - $profile_storage = $this->getProfileStorage($name); + $profile_storages = $this->getProfileStorages($name); // Gather information about all the supported collections. $collection_info = $this->configManager->getConfigCollectionInfo(); foreach ($collection_info->getCollectionNames() as $collection) { - $config_to_create = $this->getConfigToCreate($storage, $collection, $prefix, $profile_storage); + $config_to_create = $this->getConfigToCreate($storage, $collection, $prefix, $profile_storages); // If we're installing a profile ensure configuration that is overriding // is excluded. if ($name == $this->drupalGetProfile()) { @@ -223,19 +223,22 @@ public function installOptionalConfig(StorageInterface $storage = NULL, $depende * The configuration collection to use. * @param string $prefix * (optional) Limit to configuration starting with the provided string. + * @param \Drupal\Core\Config\StorageInterface[] $profile_storages + * An array of storage interfaces containing profile configuration to check + * for overrides. * * @return array * An array of configuration data read from the source storage keyed by the * configuration object name. */ - protected function getConfigToCreate(StorageInterface $storage, $collection, $prefix = '', StorageInterface $profile_storage = NULL) { + protected function getConfigToCreate(StorageInterface $storage, $collection, $prefix = '', array $profile_storages = []) { if ($storage->getCollectionName() != $collection) { $storage = $storage->createCollection($collection); } $data = $storage->readMultiple($storage->listAll($prefix)); // Check to see if the corresponding override storage has any overrides. - if ($profile_storage) { + foreach ($profile_storages as $profile_storage) { if ($profile_storage->getCollectionName() != $collection) { $profile_storage = $profile_storage->createCollection($collection); } @@ -436,10 +439,10 @@ public function checkConfigurationToInstall($type, $name) { // Add the extension that will be enabled to the list of enabled extensions. $enabled_extensions[] = $name; // Gets a profile storage to search for overrides if necessary. - $profile_storage = $this->getProfileStorage($name); + $profile_storages = $this->getProfileStorages($name); // Check the dependencies of configuration provided by the module. - $invalid_default_config = $this->findDefaultConfigWithUnmetDependencies($storage, $enabled_extensions, $profile_storage); + $invalid_default_config = $this->findDefaultConfigWithUnmetDependencies($storage, $enabled_extensions, $profile_storages); if (!empty($invalid_default_config)) { throw UnmetDependenciesException::create($name, $invalid_default_config); } @@ -460,14 +463,19 @@ public function checkConfigurationToInstall($type, $name) { /** * Finds default configuration with unmet dependencies. * + * @param \Drupal\Core\Config\StorageInterface $storage + * The storage containing the default configuration. * @param array $enabled_extensions * A list of all the currently enabled modules and themes. + * @param \Drupal\Core\Config\StorageInterface[] $profile_storages + * An array of storage interfaces containing profile configuration to check + * for overrides. * * @return array * List of configuration that has unmet dependencies */ - protected function findDefaultConfigWithUnmetDependencies(StorageInterface $storage, array $enabled_extensions, StorageInterface $profile_storage = NULL) { - $config_to_create = $this->getConfigToCreate($storage, StorageInterface::DEFAULT_COLLECTION, '', $profile_storage); + protected function findDefaultConfigWithUnmetDependencies(StorageInterface $storage, array $enabled_extensions, array $profile_storages = []) { + $config_to_create = $this->getConfigToCreate($storage, StorageInterface::DEFAULT_COLLECTION, '', $profile_storages); $all_config = array_merge($this->configFactory->listAll(), array_keys($config_to_create)); return array_filter(array_keys($config_to_create), function($config_name) use ($enabled_extensions, $all_config, $config_to_create) { return !$this->validateDependencies($config_name, $config_to_create[$config_name], $enabled_extensions, $all_config); @@ -550,27 +558,30 @@ protected function getEnabledExtensions() { /** * Gets the profile storage to use to check for profile overrides. * + * The install profile can override module configuration during a module + * install. Both the install and optional directories are checking for + * matching configuration. This allows profiles to override default + * configuration for modules they do not depend on. + * * @param string $installing_name * (optional) The name of the extension currently being installed. * - * @return \Drupal\Core\Config\StorageInterface|null - * A storage to access configuration from the installation profile. If a - * Drupal installation is not in progress or we're installing the profile - * itself, then it will return NULL as the profile storage should not be - * used. + * @return \Drupal\Core\Config\StorageInterface[]|null + * Storages to access configuration from the installation profile. If we're + * installing the profile itself, then it will return an empty array as the + * profile storage should not be used. */ - protected function getProfileStorage($installing_name = '') { + protected function getProfileStorages($installing_name = '') { $profile = $this->drupalGetProfile(); - if ($this->drupalInstallationAttempted() && $profile != $installing_name) { + $profile_storages = []; + if ($profile && $profile != $installing_name) { // Profiles should not contain optional configuration so always use the // install directory. - $profile_install_path = $this->getDefaultConfigDirectory('module', $profile); - $profile_storage = new FileStorage($profile_install_path, StorageInterface::DEFAULT_COLLECTION); - } - else { - $profile_storage = NULL; + $profile_path = $this->drupalGetPath('module', $profile); + $profile_storages[] = new FileStorage($profile_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION); + $profile_storages[] = new FileStorage($profile_path . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION); } - return $profile_storage; + return $profile_storages; } /** diff --git a/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php b/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php index b5409be..e10dfe0 100644 --- a/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php +++ b/core/modules/config/src/Tests/ConfigInstallProfileOverrideTest.php @@ -92,12 +92,12 @@ function testInstallProfileConfigOverwrite() { } // Install the config_test module and ensure that the override from the - // install profile is not used. Optional configuration can not override + // install profile is used. Optional configuration can override // configuration in a modules config/install directory. $this->container->get('module_installer')->install(['config_test']); $this->rebuildContainer(); $config_test_storage = \Drupal::entityManager()->getStorage('config_test'); - $this->assertEqual($config_test_storage->load('dotted.default')->label(), 'Default', 'The config_test entity is not overridden by the profile optional configuration.'); + $this->assertEqual($config_test_storage->load('dotted.default')->label(), 'Default install profile override', 'The config_test entity is overridden by the profile optional configuration.'); // Test that override of optional configuration does work. $this->assertEqual($config_test_storage->load('override')->label(), 'Override', 'The optional config_test entity is overridden by the profile optional configuration.'); // Test that override of optional configuration which introduces an unmet diff --git a/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php b/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php index b0450e5..dbe8310 100644 --- a/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php +++ b/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php @@ -78,6 +78,10 @@ public function testConfigTranslationModuleInstall() { $this->container->get('module_installer')->install(['block', 'config_translation']); $this->resetAll(); + // The testing profile overrides locale.settings to disable translation + // import. Test that this override is in place. + $this->assertFalse($this->config('locale.settings')->get('translation.import_enabled'), 'Translations imports are disabled by default in the Testing profile.'); + $admin_user = $this->drupalCreateUser(array('administer modules', 'administer site configuration', 'administer languages', 'access administration pages', 'administer permissions', 'translate configuration')); $this->drupalLogin($admin_user);