123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 |
- <?php
- namespace Drupal\KernelTests\Core\Config;
- use Drupal\entity_test\Entity\EntityTest;
- use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
- /**
- * Tests for configuration dependencies.
- *
- * @coversDefaultClass \Drupal\Core\Config\ConfigManager
- *
- * @group config
- */
- class ConfigDependencyTest extends EntityKernelTestBase {
- /**
- * Modules to enable.
- *
- * The entity_test module is enabled to provide content entity types.
- *
- * @var array
- */
- public static $modules = ['config_test', 'entity_test', 'user'];
- /**
- * Tests that calculating dependencies for system module.
- */
- public function testNonEntity() {
- $this->installConfig(['system']);
- $config_manager = \Drupal::service('config.manager');
- $dependents = $config_manager->findConfigEntityDependents('module', ['system']);
- $this->assertTrue(isset($dependents['system.site']), 'Simple configuration system.site has a UUID key even though it is not a configuration entity and therefore is found when looking for dependencies of the System module.');
- // Ensure that calling
- // \Drupal\Core\Config\ConfigManager::findConfigEntityDependentsAsEntities()
- // does not try to load system.site as an entity.
- $config_manager->findConfigEntityDependentsAsEntities('module', ['system']);
- }
- /**
- * Tests creating dependencies on configuration entities.
- */
- public function testDependencyManagement() {
- /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
- $config_manager = \Drupal::service('config.manager');
- $storage = $this->container->get('entity.manager')->getStorage('config_test');
- // Test dependencies between modules.
- $entity1 = $storage->create(
- [
- 'id' => 'entity1',
- 'dependencies' => [
- 'enforced' => [
- 'module' => ['node']
- ]
- ]
- ]
- );
- $entity1->save();
- $dependents = $config_manager->findConfigEntityDependents('module', ['node']);
- $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the Node module.');
- $dependents = $config_manager->findConfigEntityDependents('module', ['config_test']);
- $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the config_test module.');
- $dependents = $config_manager->findConfigEntityDependents('module', ['views']);
- $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the Views module.');
- // Ensure that the provider of the config entity is not actually written to
- // the dependencies array.
- $raw_config = $this->config('config_test.dynamic.entity1');
- $root_module_dependencies = $raw_config->get('dependencies.module');
- $this->assertTrue(empty($root_module_dependencies), 'Node module is not written to the root dependencies array as it is enforced.');
- // Create additional entities to test dependencies on config entities.
- $entity2 = $storage->create(['id' => 'entity2', 'dependencies' => ['enforced' => ['config' => [$entity1->getConfigDependencyName()]]]]);
- $entity2->save();
- $entity3 = $storage->create(['id' => 'entity3', 'dependencies' => ['enforced' => ['config' => [$entity2->getConfigDependencyName()]]]]);
- $entity3->save();
- $entity4 = $storage->create(['id' => 'entity4', 'dependencies' => ['enforced' => ['config' => [$entity3->getConfigDependencyName()]]]]);
- $entity4->save();
- // Test getting $entity1's dependencies as configuration dependency objects.
- $dependents = $config_manager->findConfigEntityDependents('config', [$entity1->getConfigDependencyName()]);
- $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on itself.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity1.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity1.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity1.');
- // Test getting $entity2's dependencies as entities.
- $dependents = $config_manager->findConfigEntityDependentsAsEntities('config', [$entity2->getConfigDependencyName()]);
- $dependent_ids = $this->getDependentIds($dependents);
- $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on config_test.dynamic.entity1.');
- $this->assertFalse(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on itself.');
- $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity2.');
- $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity2.');
- // Test getting node module's dependencies as configuration dependency
- // objects.
- $dependents = $config_manager->findConfigEntityDependents('module', ['node']);
- $this->assertTrue(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 has a dependency on the Node module.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on the Node module.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the Node module.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the Node module.');
- // Test getting node module's dependencies as configuration dependency
- // objects after making $entity3 also dependent on node module but $entity1
- // no longer depend on node module.
- $entity1->setEnforcedDependencies([])->save();
- $entity3->setEnforcedDependencies(['module' => ['node'], 'config' => [$entity2->getConfigDependencyName()]])->save();
- $dependents = $config_manager->findConfigEntityDependents('module', ['node']);
- $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the Node module.');
- $this->assertFalse(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 does not have a dependency on the Node module.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the Node module.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the Node module.');
- // Test dependency on a content entity.
- $entity_test = EntityTest::create([
- 'name' => $this->randomString(),
- 'type' => 'entity_test',
- ]);
- $entity_test->save();
- $entity2->setEnforcedDependencies(['config' => [$entity1->getConfigDependencyName()], 'content' => [$entity_test->getConfigDependencyName()]])->save();;
- $dependents = $config_manager->findConfigEntityDependents('content', [$entity_test->getConfigDependencyName()]);
- $this->assertFalse(isset($dependents['config_test.dynamic.entity1']), 'config_test.dynamic.entity1 does not have a dependency on the content entity.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity2']), 'config_test.dynamic.entity2 has a dependency on the content entity.');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity3']), 'config_test.dynamic.entity3 has a dependency on the content entity (via entity2).');
- $this->assertTrue(isset($dependents['config_test.dynamic.entity4']), 'config_test.dynamic.entity4 has a dependency on the content entity (via entity3).');
- // Create a configuration entity of a different type with the same ID as one
- // of the entities already created.
- $alt_storage = $this->container->get('entity.manager')->getStorage('config_query_test');
- $alt_storage->create(['id' => 'entity1', 'dependencies' => ['enforced' => ['config' => [$entity1->getConfigDependencyName()]]]])->save();
- $alt_storage->create(['id' => 'entity2', 'dependencies' => ['enforced' => ['module' => ['views']]]])->save();
- $dependents = $config_manager->findConfigEntityDependentsAsEntities('config', [$entity1->getConfigDependencyName()]);
- $dependent_ids = $this->getDependentIds($dependents);
- $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on itself.');
- $this->assertTrue(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test.dynamic.entity1.');
- $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test.dynamic.entity1.');
- $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test.dynamic.entity1.');
- $this->assertTrue(in_array('config_query_test:entity1', $dependent_ids), 'config_query_test.dynamic.entity1 has a dependency on config_test.dynamic.entity1.');
- $this->assertFalse(in_array('config_query_test:entity2', $dependent_ids), 'config_query_test.dynamic.entity2 does not have a dependency on config_test.dynamic.entity1.');
- $dependents = $config_manager->findConfigEntityDependentsAsEntities('module', ['node', 'views']);
- $dependent_ids = $this->getDependentIds($dependents);
- $this->assertFalse(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 does not have a dependency on Views or Node.');
- $this->assertFalse(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 does not have a dependency on Views or Node.');
- $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on Views or Node.');
- $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on Views or Node.');
- $this->assertFalse(in_array('config_query_test:entity1', $dependent_ids), 'config_test.query.entity1 does not have a dependency on Views or Node.');
- $this->assertTrue(in_array('config_query_test:entity2', $dependent_ids), 'config_test.query.entity2 has a dependency on Views or Node.');
- $dependents = $config_manager->findConfigEntityDependentsAsEntities('module', ['config_test']);
- $dependent_ids = $this->getDependentIds($dependents);
- $this->assertTrue(in_array('config_test:entity1', $dependent_ids), 'config_test.dynamic.entity1 has a dependency on config_test module.');
- $this->assertTrue(in_array('config_test:entity2', $dependent_ids), 'config_test.dynamic.entity2 has a dependency on config_test module.');
- $this->assertTrue(in_array('config_test:entity3', $dependent_ids), 'config_test.dynamic.entity3 has a dependency on config_test module.');
- $this->assertTrue(in_array('config_test:entity4', $dependent_ids), 'config_test.dynamic.entity4 has a dependency on config_test module.');
- $this->assertTrue(in_array('config_query_test:entity1', $dependent_ids), 'config_test.query.entity1 has a dependency on config_test module.');
- $this->assertTrue(in_array('config_query_test:entity2', $dependent_ids), 'config_test.query.entity2 has a dependency on config_test module.');
- // Test the ability to find missing content dependencies.
- $missing_dependencies = $config_manager->findMissingContentDependencies();
- $this->assertEqual([], $missing_dependencies);
- $expected = [
- $entity_test->uuid() => [
- 'entity_type' => 'entity_test',
- 'bundle' => $entity_test->bundle(),
- 'uuid' => $entity_test->uuid(),
- ],
- ];
- // Delete the content entity so that is it now missing.
- $entity_test->delete();
- $missing_dependencies = $config_manager->findMissingContentDependencies();
- $this->assertEqual($expected, $missing_dependencies);
- // Add a fake missing dependency to ensure multiple missing dependencies
- // work.
- $entity1->setEnforcedDependencies(['content' => [$entity_test->getConfigDependencyName(), 'entity_test:bundle:uuid']])->save();;
- $expected['uuid'] = [
- 'entity_type' => 'entity_test',
- 'bundle' => 'bundle',
- 'uuid' => 'uuid',
- ];
- $missing_dependencies = $config_manager->findMissingContentDependencies();
- $this->assertEqual($expected, $missing_dependencies);
- }
- /**
- * Tests ConfigManager::uninstall() and config entity dependency management.
- */
- public function testConfigEntityUninstall() {
- /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
- $config_manager = \Drupal::service('config.manager');
- /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
- $storage = $this->container->get('entity.manager')
- ->getStorage('config_test');
- // Test dependencies between modules.
- $entity1 = $storage->create(
- [
- 'id' => 'entity1',
- 'dependencies' => [
- 'enforced' => [
- 'module' => ['node', 'config_test']
- ],
- ],
- ]
- );
- $entity1->save();
- $entity2 = $storage->create(
- [
- 'id' => 'entity2',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity1->getConfigDependencyName()],
- ],
- ],
- ]
- );
- $entity2->save();
- // Perform a module rebuild so we can know where the node module is located
- // and uninstall it.
- // @todo Remove as part of https://www.drupal.org/node/2186491
- system_rebuild_module_data();
- // Test that doing a config uninstall of the node module deletes entity2
- // since it is dependent on entity1 which is dependent on the node module.
- $config_manager->uninstall('module', 'node');
- $this->assertFalse($storage->load('entity1'), 'Entity 1 deleted');
- $this->assertFalse($storage->load('entity2'), 'Entity 2 deleted');
- }
- /**
- * Data provider for self::testConfigEntityUninstallComplex().
- */
- public function providerConfigEntityUninstallComplex() {
- // Ensure that alphabetical order has no influence on dependency fixing and
- // removal.
- return [
- [['a', 'b', 'c', 'd']],
- [['d', 'c', 'b', 'a']],
- [['c', 'd', 'a', 'b']],
- ];
- }
- /**
- * Tests complex configuration entity dependency handling during uninstall.
- *
- * Configuration entities can be deleted or updated during module uninstall
- * because they have dependencies on the module.
- *
- * @param array $entity_id_suffixes
- * The suffixes to add to the 4 entities created by the test.
- *
- * @dataProvider providerConfigEntityUninstallComplex
- */
- public function testConfigEntityUninstallComplex(array $entity_id_suffixes) {
- /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
- $config_manager = \Drupal::service('config.manager');
- /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
- $storage = $this->container->get('entity.manager')
- ->getStorage('config_test');
- // Entity 1 will be deleted because it depends on node.
- $entity_1 = $storage->create(
- [
- 'id' => 'entity_' . $entity_id_suffixes[0],
- 'dependencies' => [
- 'enforced' => [
- 'module' => ['node', 'config_test']
- ],
- ],
- ]
- );
- $entity_1->save();
- // Entity 2 has a dependency on entity 1 but it can be fixed because
- // \Drupal\config_test\Entity::onDependencyRemoval() will remove the
- // dependency before config entities are deleted.
- $entity_2 = $storage->create(
- [
- 'id' => 'entity_' . $entity_id_suffixes[1],
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity_1->getConfigDependencyName()],
- ],
- ],
- ]
- );
- $entity_2->save();
- // Entity 3 will be unchanged because it is dependent on entity 2 which can
- // be fixed. The ConfigEntityInterface::onDependencyRemoval() method will
- // not be called for this entity.
- $entity_3 = $storage->create(
- [
- 'id' => 'entity_' . $entity_id_suffixes[2],
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity_2->getConfigDependencyName()],
- ],
- ],
- ]
- );
- $entity_3->save();
- // Entity 4's config dependency will be fixed but it will still be deleted
- // because it also depends on the node module.
- $entity_4 = $storage->create(
- [
- 'id' => 'entity_' . $entity_id_suffixes[3],
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity_1->getConfigDependencyName()],
- 'module' => ['node', 'config_test']
- ],
- ],
- ]
- );
- $entity_4->save();
- // Set a more complicated test where dependencies will be fixed.
- \Drupal::state()->set('config_test.fix_dependencies', [$entity_1->getConfigDependencyName()]);
- \Drupal::state()->set('config_test.on_dependency_removal_called', []);
- // Do a dry run using
- // \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
- $config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('module', ['node']);
- $this->assertEqual($entity_1->uuid(), $config_entities['delete'][1]->uuid(), 'Entity 1 will be deleted.');
- $this->assertEqual($entity_2->uuid(), reset($config_entities['update'])->uuid(), 'Entity 2 will be updated.');
- $this->assertEqual($entity_3->uuid(), reset($config_entities['unchanged'])->uuid(), 'Entity 3 is not changed.');
- $this->assertEqual($entity_4->uuid(), $config_entities['delete'][0]->uuid(), 'Entity 4 will be deleted.');
- $called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
- $this->assertFalse(in_array($entity_3->id(), $called), 'ConfigEntityInterface::onDependencyRemoval() is not called for entity 3.');
- $this->assertSame([$entity_1->id(), $entity_4->id(), $entity_2->id()], $called, 'The most dependent entites have ConfigEntityInterface::onDependencyRemoval() called first.');
- // Perform a module rebuild so we can know where the node module is located
- // and uninstall it.
- // @todo Remove as part of https://www.drupal.org/node/2186491
- system_rebuild_module_data();
- // Perform the uninstall.
- $config_manager->uninstall('module', 'node');
- // Test that expected actions have been performed.
- $this->assertFalse($storage->load($entity_1->id()), 'Entity 1 deleted');
- $entity_2 = $storage->load($entity_2->id());
- $this->assertTrue($entity_2, 'Entity 2 not deleted');
- $this->assertEqual($entity_2->calculateDependencies()->getDependencies()['config'], [], 'Entity 2 dependencies updated to remove dependency on entity 1.');
- $entity_3 = $storage->load($entity_3->id());
- $this->assertTrue($entity_3, 'Entity 3 not deleted');
- $this->assertEqual($entity_3->calculateDependencies()->getDependencies()['config'], [$entity_2->getConfigDependencyName()], 'Entity 3 still depends on entity 2.');
- $this->assertFalse($storage->load($entity_4->id()), 'Entity 4 deleted');
- }
- /**
- * @covers ::uninstall
- * @covers ::getConfigEntitiesToChangeOnDependencyRemoval
- */
- public function testConfigEntityUninstallThirdParty() {
- /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
- $config_manager = \Drupal::service('config.manager');
- /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
- $storage = $this->container->get('entity_type.manager')
- ->getStorage('config_test');
- // Entity 1 will be fixed because it only has a dependency via third-party
- // settings, which are fixable.
- $entity_1 = $storage->create([
- 'id' => 'entity_1',
- 'dependencies' => [
- 'enforced' => [
- 'module' => ['config_test'],
- ],
- ],
- 'third_party_settings' => [
- 'node' => [
- 'foo' => 'bar',
- ],
- ],
- ]);
- $entity_1->save();
- // Entity 2 has a dependency on entity 1.
- $entity_2 = $storage->create([
- 'id' => 'entity_2',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity_1->getConfigDependencyName()],
- ],
- ],
- 'third_party_settings' => [
- 'node' => [
- 'foo' => 'bar',
- ],
- ],
- ]);
- $entity_2->save();
- // Entity 3 will be unchanged because it is dependent on entity 2 which can
- // be fixed. The ConfigEntityInterface::onDependencyRemoval() method will
- // not be called for this entity.
- $entity_3 = $storage->create([
- 'id' => 'entity_3',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity_2->getConfigDependencyName()],
- ],
- ],
- ]);
- $entity_3->save();
- // Entity 4's config dependency will be fixed but it will still be deleted
- // because it also depends on the node module.
- $entity_4 = $storage->create([
- 'id' => 'entity_4',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity_1->getConfigDependencyName()],
- 'module' => ['node', 'config_test'],
- ],
- ],
- ]);
- $entity_4->save();
- \Drupal::state()->set('config_test.fix_dependencies', []);
- \Drupal::state()->set('config_test.on_dependency_removal_called', []);
- // Do a dry run using
- // \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
- $config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('module', ['node']);
- $config_entity_ids = [
- 'update' => [],
- 'delete' => [],
- 'unchanged' => [],
- ];
- foreach ($config_entities as $type => $config_entities_by_type) {
- foreach ($config_entities_by_type as $config_entity) {
- $config_entity_ids[$type][] = $config_entity->id();
- }
- }
- $expected = [
- 'update' => [$entity_1->id(), $entity_2->id()],
- 'delete' => [$entity_4->id()],
- 'unchanged' => [$entity_3->id()],
- ];
- $this->assertSame($expected, $config_entity_ids);
- $called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
- $this->assertFalse(in_array($entity_3->id(), $called), 'ConfigEntityInterface::onDependencyRemoval() is not called for entity 3.');
- $this->assertSame([$entity_1->id(), $entity_4->id(), $entity_2->id()], $called, 'The most dependent entities have ConfigEntityInterface::onDependencyRemoval() called first.');
- // Perform a module rebuild so we can know where the node module is located
- // and uninstall it.
- // @todo Remove as part of https://www.drupal.org/node/2186491
- system_rebuild_module_data();
- // Perform the uninstall.
- $config_manager->uninstall('module', 'node');
- // Test that expected actions have been performed.
- $entity_1 = $storage->load($entity_1->id());
- $this->assertTrue($entity_1, 'Entity 1 not deleted');
- $this->assertSame($entity_1->getThirdPartySettings('node'), [], 'Entity 1 third party settings updated.');
- $entity_2 = $storage->load($entity_2->id());
- $this->assertTrue($entity_2, 'Entity 2 not deleted');
- $this->assertSame($entity_2->getThirdPartySettings('node'), [], 'Entity 2 third party settings updated.');
- $this->assertSame($entity_2->calculateDependencies()->getDependencies()['config'], [$entity_1->getConfigDependencyName()], 'Entity 2 still depends on entity 1.');
- $entity_3 = $storage->load($entity_3->id());
- $this->assertTrue($entity_3, 'Entity 3 not deleted');
- $this->assertSame($entity_3->calculateDependencies()->getDependencies()['config'], [$entity_2->getConfigDependencyName()], 'Entity 3 still depends on entity 2.');
- $this->assertFalse($storage->load($entity_4->id()), 'Entity 4 deleted');
- }
- /**
- * Tests deleting a configuration entity and dependency management.
- */
- public function testConfigEntityDelete() {
- /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
- $config_manager = \Drupal::service('config.manager');
- /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
- $storage = $this->container->get('entity.manager')->getStorage('config_test');
- // Test dependencies between configuration entities.
- $entity1 = $storage->create(
- [
- 'id' => 'entity1'
- ]
- );
- $entity1->save();
- $entity2 = $storage->create(
- [
- 'id' => 'entity2',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity1->getConfigDependencyName()],
- ],
- ],
- ]
- );
- $entity2->save();
- // Do a dry run using
- // \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
- $config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('config', [$entity1->getConfigDependencyName()]);
- $this->assertEqual($entity2->uuid(), reset($config_entities['delete'])->uuid(), 'Entity 2 will be deleted.');
- $this->assertTrue(empty($config_entities['update']), 'No dependent configuration entities will be updated.');
- $this->assertTrue(empty($config_entities['unchanged']), 'No dependent configuration entities will be unchanged.');
- // Test that doing a delete of entity1 deletes entity2 since it is dependent
- // on entity1.
- $entity1->delete();
- $this->assertFalse($storage->load('entity1'), 'Entity 1 deleted');
- $this->assertFalse($storage->load('entity2'), 'Entity 2 deleted');
- // Set a more complicated test where dependencies will be fixed.
- \Drupal::state()->set('config_test.fix_dependencies', [$entity1->getConfigDependencyName()]);
- // Entity1 will be deleted by the test.
- $entity1 = $storage->create(
- [
- 'id' => 'entity1',
- ]
- );
- $entity1->save();
- // Entity2 has a dependency on Entity1 but it can be fixed because
- // \Drupal\config_test\Entity::onDependencyRemoval() will remove the
- // dependency before config entities are deleted.
- $entity2 = $storage->create(
- [
- 'id' => 'entity2',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity1->getConfigDependencyName()],
- ],
- ],
- ]
- );
- $entity2->save();
- // Entity3 will be unchanged because it is dependent on Entity2 which can
- // be fixed.
- $entity3 = $storage->create(
- [
- 'id' => 'entity3',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity2->getConfigDependencyName()],
- ],
- ],
- ]
- );
- $entity3->save();
- // Do a dry run using
- // \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval().
- $config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('config', [$entity1->getConfigDependencyName()]);
- $this->assertTrue(empty($config_entities['delete']), 'No dependent configuration entities will be deleted.');
- $this->assertEqual($entity2->uuid(), reset($config_entities['update'])->uuid(), 'Entity 2 will be updated.');
- $this->assertEqual($entity3->uuid(), reset($config_entities['unchanged'])->uuid(), 'Entity 3 is not changed.');
- // Perform the uninstall.
- $entity1->delete();
- // Test that expected actions have been performed.
- $this->assertFalse($storage->load('entity1'), 'Entity 1 deleted');
- $entity2 = $storage->load('entity2');
- $this->assertTrue($entity2, 'Entity 2 not deleted');
- $this->assertEqual($entity2->calculateDependencies()->getDependencies()['config'], [], 'Entity 2 dependencies updated to remove dependency on Entity1.');
- $entity3 = $storage->load('entity3');
- $this->assertTrue($entity3, 'Entity 3 not deleted');
- $this->assertEqual($entity3->calculateDependencies()->getDependencies()['config'], [$entity2->getConfigDependencyName()], 'Entity 3 still depends on Entity 2.');
- }
- /**
- * Tests getConfigEntitiesToChangeOnDependencyRemoval() with content entities.
- *
- * At the moment there is no runtime code that calculates configuration
- * dependencies on content entity delete because this calculation is expensive
- * and all content dependencies are soft. This test ensures that the code
- * works for content entities.
- *
- * @see \Drupal\Core\Config\ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval()
- */
- public function testContentEntityDelete() {
- $this->installEntitySchema('entity_test');
- /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
- $config_manager = \Drupal::service('config.manager');
- $content_entity = EntityTest::create();
- $content_entity->save();
- /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $storage */
- $storage = $this->container->get('entity.manager')->getStorage('config_test');
- $entity1 = $storage->create(
- [
- 'id' => 'entity1',
- 'dependencies' => [
- 'enforced' => [
- 'content' => [$content_entity->getConfigDependencyName()]
- ],
- ],
- ]
- );
- $entity1->save();
- $entity2 = $storage->create(
- [
- 'id' => 'entity2',
- 'dependencies' => [
- 'enforced' => [
- 'config' => [$entity1->getConfigDependencyName()]
- ],
- ],
- ]
- );
- $entity2->save();
- // Create a configuration entity that is not in the dependency chain.
- $entity3 = $storage->create(['id' => 'entity3']);
- $entity3->save();
- $config_entities = $config_manager->getConfigEntitiesToChangeOnDependencyRemoval('content', [$content_entity->getConfigDependencyName()]);
- $this->assertEqual($entity1->uuid(), $config_entities['delete'][1]->uuid(), 'Entity 1 will be deleted.');
- $this->assertEqual($entity2->uuid(), $config_entities['delete'][0]->uuid(), 'Entity 2 will be deleted.');
- $this->assertTrue(empty($config_entities['update']), 'No dependencies of the content entity will be updated.');
- $this->assertTrue(empty($config_entities['unchanged']), 'No dependencies of the content entity will be unchanged.');
- }
- /**
- * Gets a list of identifiers from an array of configuration entities.
- *
- * @param \Drupal\Core\Config\Entity\ConfigEntityInterface[] $dependents
- * An array of configuration entities.
- *
- * @return array
- * An array with values of entity_type_id:ID
- */
- protected function getDependentIds(array $dependents) {
- $dependent_ids = [];
- foreach ($dependents as $dependent) {
- $dependent_ids[] = $dependent->getEntityTypeId() . ':' . $dependent->id();
- }
- return $dependent_ids;
- }
- }
|