3 namespace Drupal\KernelTests\Core\Config;
5 use Drupal\Core\Config\InstallStorage;
6 use Drupal\Core\Config\PreExistingConfigException;
7 use Drupal\Core\Config\UnmetDependenciesException;
8 use Drupal\KernelTests\KernelTestBase;
11 * Tests installation of configuration objects in installation functionality.
14 * @see \Drupal\Core\Config\ConfigInstaller
16 class ConfigInstallTest extends KernelTestBase {
21 public static $modules = ['system'];
26 protected function setUp() {
29 // Ensure the global variable being asserted by this test does not exist;
30 // a previous test executed in this request/process might have set it.
31 unset($GLOBALS['hook_config_test']);
35 * Tests module installation.
37 public function testModuleInstallation() {
38 $default_config = 'config_test.system';
39 $default_configuration_entity = 'config_test.dynamic.dotted.default';
41 // Verify that default module config does not exist before installation yet.
42 $config = $this->config($default_config);
43 $this->assertIdentical($config->isNew(), TRUE);
44 $config = $this->config($default_configuration_entity);
45 $this->assertIdentical($config->isNew(), TRUE);
47 // Ensure that schema provided by modules that are not installed is not
49 $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'), 'Configuration schema for config_schema_test.someschema does not exist.');
51 // Install the test module.
52 $this->installModules(['config_test']);
54 // Verify that default module config exists.
55 \Drupal::configFactory()->reset($default_config);
56 \Drupal::configFactory()->reset($default_configuration_entity);
57 $config = $this->config($default_config);
58 $this->assertIdentical($config->isNew(), FALSE);
59 $config = $this->config($default_configuration_entity);
60 $this->assertIdentical($config->isNew(), FALSE);
62 // Verify that config_test API hooks were invoked for the dynamic default
63 // configuration entity.
64 $this->assertFalse(isset($GLOBALS['hook_config_test']['load']));
65 $this->assertTrue(isset($GLOBALS['hook_config_test']['presave']));
66 $this->assertTrue(isset($GLOBALS['hook_config_test']['insert']));
67 $this->assertFalse(isset($GLOBALS['hook_config_test']['update']));
68 $this->assertFalse(isset($GLOBALS['hook_config_test']['predelete']));
69 $this->assertFalse(isset($GLOBALS['hook_config_test']['delete']));
71 // Install the schema test module.
72 $this->enableModules(['config_schema_test']);
73 $this->installConfig(['config_schema_test']);
75 // After module installation the new schema should exist.
76 $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'), 'Configuration schema for config_schema_test.someschema exists.');
78 // Test that uninstalling configuration removes configuration schema.
79 $this->config('core.extension')->set('module', [])->save();
80 \Drupal::service('config.manager')->uninstall('module', 'config_test');
81 $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'), 'Configuration schema for config_schema_test.someschema does not exist.');
85 * Tests that collections are ignored if the event does not return anything.
87 public function testCollectionInstallationNoCollections() {
88 // Install the test module.
89 $this->enableModules(['config_collection_install_test']);
90 $this->installConfig(['config_collection_install_test']);
91 /** @var \Drupal\Core\Config\StorageInterface $active_storage */
92 $active_storage = \Drupal::service('config.storage');
93 $this->assertEqual([], $active_storage->getAllCollectionNames());
97 * Tests config objects in collections are installed as expected.
99 public function testCollectionInstallationCollections() {
101 'another_collection',
105 // Set the event listener to return three possible collections.
106 // @see \Drupal\config_collection_install_test\EventSubscriber
107 \Drupal::state()->set('config_collection_install_test.collection_names', $collections);
108 // Install the test module.
109 $this->enableModules(['config_collection_install_test']);
110 $this->installConfig(['config_collection_install_test']);
111 /** @var \Drupal\Core\Config\StorageInterface $active_storage */
112 $active_storage = \Drupal::service('config.storage');
113 $this->assertEqual($collections, $active_storage->getAllCollectionNames());
114 foreach ($collections as $collection) {
115 $collection_storage = $active_storage->createCollection($collection);
116 $data = $collection_storage->read('config_collection_install_test.test');
117 $this->assertEqual($collection, $data['collection']);
120 // Tests that clashing configuration in collections is detected.
122 \Drupal::service('module_installer')->install(['config_collection_clash_install_test']);
123 $this->fail('Expected PreExistingConfigException not thrown.');
125 catch (PreExistingConfigException $e) {
126 $this->assertEqual($e->getExtension(), 'config_collection_clash_install_test');
127 $this->assertEqual($e->getConfigObjects(), [
128 'another_collection' => ['config_collection_install_test.test'],
129 'collection.test1' => ['config_collection_install_test.test'],
130 'collection.test2' => ['config_collection_install_test.test'],
132 $this->assertEqual($e->getMessage(), 'Configuration objects (another_collection/config_collection_install_test.test, collection/test1/config_collection_install_test.test, collection/test2/config_collection_install_test.test) provided by config_collection_clash_install_test already exist in active configuration');
135 // Test that the we can use the config installer to install all the
136 // available default configuration in a particular collection for enabled
138 \Drupal::service('config.installer')->installCollectionDefaultConfig('entity');
139 // The 'entity' collection will not exist because the 'config_test' module
141 $this->assertEqual($collections, $active_storage->getAllCollectionNames());
142 // Enable the 'config_test' module and try again.
143 $this->enableModules(['config_test']);
144 \Drupal::service('config.installer')->installCollectionDefaultConfig('entity');
145 $collections[] = 'entity';
146 $this->assertEqual($collections, $active_storage->getAllCollectionNames());
147 $collection_storage = $active_storage->createCollection('entity');
148 $data = $collection_storage->read('config_test.dynamic.dotted.default');
149 $this->assertSame(['label' => 'entity'], $data);
151 // Test that the config manager uninstalls configuration from collections
153 \Drupal::service('config.manager')->uninstall('module', 'config_collection_install_test');
154 $this->assertEqual(['entity'], $active_storage->getAllCollectionNames());
155 \Drupal::service('config.manager')->uninstall('module', 'config_test');
156 $this->assertEqual([], $active_storage->getAllCollectionNames());
160 * Tests collections which do not support config entities install correctly.
162 * Config entity detection during config installation is done by matching
163 * config name prefixes. If a collection provides a configuration with a
164 * matching name but does not support config entities it should be created
165 * using simple configuration.
167 public function testCollectionInstallationCollectionConfigEntity() {
171 \Drupal::state()->set('config_collection_install_test.collection_names', $collections);
172 // Install the test module.
173 $this->installModules(['config_test', 'config_collection_install_test']);
174 /** @var \Drupal\Core\Config\StorageInterface $active_storage */
175 $active_storage = \Drupal::service('config.storage');
176 $this->assertEqual($collections, $active_storage->getAllCollectionNames());
177 $collection_storage = $active_storage->createCollection('entity');
179 // The config_test.dynamic.dotted.default configuration object saved in the
180 // active store should be a configuration entity complete with UUID. Because
181 // the entity collection does not support configuration entities the
182 // configuration object stored there with the same name should only contain
184 $name = 'config_test.dynamic.dotted.default';
185 $data = $active_storage->read($name);
186 $this->assertTrue(isset($data['uuid']));
187 $data = $collection_storage->read($name);
188 $this->assertSame(['label' => 'entity'], $data);
192 * Tests the configuration with unmet dependencies is not installed.
194 public function testDependencyChecking() {
195 $this->installModules(['config_test']);
197 $this->installModules(['config_install_dependency_test']);
198 $this->fail('Expected UnmetDependenciesException not thrown.');
200 catch (UnmetDependenciesException $e) {
201 $this->assertEqual($e->getExtension(), 'config_install_dependency_test');
202 $this->assertEqual($e->getConfigObjects(), ['config_test.dynamic.other_module_test_with_dependency' => ['config_other_module_config_test', 'config_test.dynamic.dotted.english']]);
203 $this->assertEqual($e->getMessage(), 'Configuration objects provided by <em class="placeholder">config_install_dependency_test</em> have unmet dependencies: <em class="placeholder">config_test.dynamic.other_module_test_with_dependency (config_other_module_config_test, config_test.dynamic.dotted.english)</em>');
206 $this->installModules(['config_install_double_dependency_test']);
207 $this->fail('Expected UnmetDependenciesException not thrown.');
209 catch (UnmetDependenciesException $e) {
210 $this->assertEquals('config_install_double_dependency_test', $e->getExtension());
211 $this->assertEquals(['config_test.dynamic.other_module_test_with_dependency' => ['config_other_module_config_test', 'config_test.dynamic.dotted.english']], $e->getConfigObjects());
212 $this->assertEquals('Configuration objects provided by <em class="placeholder">config_install_double_dependency_test</em> have unmet dependencies: <em class="placeholder">config_test.dynamic.other_module_test_with_dependency (config_other_module_config_test, config_test.dynamic.dotted.english)</em>', $e->getMessage());
214 $this->installModules(['config_test_language']);
216 $this->installModules(['config_install_dependency_test']);
217 $this->fail('Expected UnmetDependenciesException not thrown.');
219 catch (UnmetDependenciesException $e) {
220 $this->assertEqual($e->getExtension(), 'config_install_dependency_test');
221 $this->assertEqual($e->getConfigObjects(), ['config_test.dynamic.other_module_test_with_dependency' => ['config_other_module_config_test']]);
222 $this->assertEqual($e->getMessage(), 'Configuration objects provided by <em class="placeholder">config_install_dependency_test</em> have unmet dependencies: <em class="placeholder">config_test.dynamic.other_module_test_with_dependency (config_other_module_config_test)</em>');
224 $this->installModules(['config_other_module_config_test']);
225 $this->installModules(['config_install_dependency_test']);
226 $entity = \Drupal::entityManager()->getStorage('config_test')->load('other_module_test_with_dependency');
227 $this->assertTrue($entity, 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.');
228 // Ensure that dependencies can be added during module installation by
230 $this->assertSame('config_install_dependency_test', $entity->getDependencies()['module'][0]);
234 * Tests imported configuration entities with and without language information.
236 public function testLanguage() {
237 $this->installModules(['config_test_language']);
238 // Test imported configuration with implicit language code.
239 $storage = new InstallStorage();
240 $data = $storage->read('config_test.dynamic.dotted.english');
241 $this->assertTrue(!isset($data['langcode']));
243 $this->config('config_test.dynamic.dotted.english')->get('langcode'),
247 // Test imported configuration with explicit language code.
248 $data = $storage->read('config_test.dynamic.dotted.french');
249 $this->assertEqual($data['langcode'], 'fr');
251 $this->config('config_test.dynamic.dotted.french')->get('langcode'),
259 * @param array $modules
262 protected function installModules(array $modules) {
263 $this->container->get('module_installer')->install($modules);
264 $this->container = \Drupal::getContainer();