diff --git a/core/core.services.yml b/core/core.services.yml index 73c7873..2596c25 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -139,7 +139,7 @@ services: arguments: ['@config.storage', '@event_dispatcher', '@config.typed'] config.installer: class: Drupal\Core\Config\ConfigInstaller - arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher'] + arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher', '@logger.channel.default'] config.storage: class: Drupal\Core\Config\CachedStorage arguments: ['@config.storage.active', '@cache.config'] diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index 205c539..6900071 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\Unicode; use Drupal\Core\Config\Entity\ConfigDependencyManager; use Drupal\Core\Site\Settings; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; class ConfigInstaller implements ConfigInstallerInterface { @@ -57,6 +58,13 @@ class ConfigInstaller implements ConfigInstallerInterface { protected $sourceStorage; /** + * The logger. + * + * @var \Psr\Log\LoggerInterface + */ + protected $logger; + + /** * Is configuration being created as part of a configuration sync. * * @var bool @@ -76,13 +84,16 @@ class ConfigInstaller implements ConfigInstallerInterface { * The configuration manager. * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher * The event dispatcher. + * @param \Psr\Log\LoggerInterface $logger + * The logger. */ - public function __construct(ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, ConfigManagerInterface $config_manager, EventDispatcherInterface $event_dispatcher) { + public function __construct(ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, ConfigManagerInterface $config_manager, EventDispatcherInterface $event_dispatcher, LoggerInterface $logger) { $this->configFactory = $config_factory; $this->activeStorages[$active_storage->getCollectionName()] = $active_storage; $this->typedConfig = $typed_config; $this->configManager = $config_manager; $this->eventDispatcher = $event_dispatcher; + $this->logger = $logger; } /** @@ -131,16 +142,6 @@ public function installDefaultConfig($type, $name) { * The list of configuration objects to create. */ protected function listDefaultConfigToInstall($type, $name, $collection, array $enabled_extensions) { - // Unless we are installing the profile, remove it from the list. - if ($install_profile = Settings::get('install_profile')) { - if ($name !== $install_profile) { - $key = array_search($install_profile, $enabled_extensions); - if ($key !== FALSE) { - unset($enabled_extensions[$key]); - } - } - } - // Get all default configuration owned by this extension that is provided // by other enabled modules and merge it with all the default configuration // that is provided by the extension that is installable. @@ -240,6 +241,7 @@ protected function createConfiguration($collection, array $config_to_install, ar // extensions won't have. If this fails just ignore the configuration // and continue. if (!$this->validateDependencies($name, $data[$name], $enabled_extensions, $all_config)) { + $this->logger->info('Unable to create %config_name configuration because it has unmet dependencies.', array('%config_name' => $name)); continue; } $entity_storage = $this->configManager @@ -409,7 +411,7 @@ public function checkConfigurationToInstall($type, $name) { // Install profiles can not have config clashes. Configuration that // has the same name as a module's configuration will be used instead. - if ($name != drupal_get_profile()) { + if ($name != Settings::get('install_profile')) { // Validate default configuration of this module. Bail if unable to // install. Should not continue installing more modules because those // may depend on this one. diff --git a/core/modules/config/src/Tests/ConfigInstallWebTest.php b/core/modules/config/src/Tests/ConfigInstallWebTest.php index b04ce39..5748d51 100644 --- a/core/modules/config/src/Tests/ConfigInstallWebTest.php +++ b/core/modules/config/src/Tests/ConfigInstallWebTest.php @@ -214,4 +214,21 @@ public function testPreExistingConfigInstall() { $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default) provided by config_clash_test_theme already exist in active configuration'); } } + + /** + * Tests unmet dependencies detection. + */ + public function testUnmetDependenciesInstall() { + $this->drupalLogin($this->adminUser); + // We need to install separately since config_install_dependency_test does + // not depend on config_test and order is important. + $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE), t('Save configuration')); + $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration')); + $this->assertRaw('Unable to install Config install dependency test, config_test.dynamic.other_module_test_with_dependency has unmet dependencies.'); + + $this->drupalPostForm('admin/modules', array('modules[Testing][config_other_module_config_test][enable]' => TRUE), t('Save configuration')); + $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration')); + $this->rebuildContainer(); + $this->assertTrue(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.'); + } } diff --git a/core/modules/config/src/Tests/ConfigOtherModuleTest.php b/core/modules/config/src/Tests/ConfigOtherModuleTest.php index 082e485..886f59e 100644 --- a/core/modules/config/src/Tests/ConfigOtherModuleTest.php +++ b/core/modules/config/src/Tests/ConfigOtherModuleTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Config\PreExistingConfigException; use Drupal\Core\Config\StorageInterface; +use Drupal\Core\Config\UnmetDependenciesException; use Drupal\simpletest\WebTestBase; /** @@ -97,6 +98,29 @@ public function testUninstall() { } /** + * Tests the configuration with unmet dependencies is not installed. + */ + public function testDependencyChecking() { + $this->installModule('config_install_dependency_test'); + $this->installModule('config_test'); + $this->assertFalse(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration is ignored during install.'); + $this->uninstallModule('config_install_dependency_test'); + + try { + $this->installModule('config_install_dependency_test'); + $this->fail('Expected UnmetDependenciesException not thrown.'); + } + catch (UnmetDependenciesException $e) { + $this->assertEqual($e->getExtension(), 'config_install_dependency_test'); + $this->assertEqual($e->getConfigObjects(), ['config_test.dynamic.other_module_test_with_dependency']); + $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.other_module_test_with_dependency) provided by config_install_dependency_test have unmet dependencies'); + } + $this->installModule('config_other_module_config_test'); + $this->installModule('config_install_dependency_test'); + $this->assertTrue(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.'); + } + + /** * Installs a module. * * @param string $module diff --git a/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml b/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml new file mode 100644 index 0000000..69470f8 --- /dev/null +++ b/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml @@ -0,0 +1,11 @@ +id: other_module_test_with_dependency +label: 'Other module test with dependency' +weight: 0 +style: '' +status: true +langcode: en +protected_property: Default +dependencies: + enforced: + module: + - config_other_module_config_test diff --git a/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml b/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml new file mode 100644 index 0000000..e9b3c72 --- /dev/null +++ b/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml @@ -0,0 +1,5 @@ +name: 'Config install dependency test' +type: module +package: Testing +version: VERSION +core: 8.x