diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php index 3d2e9b4..ef49b65 100644 --- a/core/lib/Drupal/Core/Config/ConfigManager.php +++ b/core/lib/Drupal/Core/Config/ConfigManager.php @@ -305,7 +305,7 @@ public function getConfigEntitiesToChangeOnDependencyRemoval($type, array $names * {@inheritdoc} */ public function getConfigEntitiesToChange($operation, $type, array $names, $dry_run = TRUE) { - $this->normalizeNames($type, $names); + $names = $this->getNormalizedNames($type, $names); // Determine the current list of dependent configuration entities and set up // initial values. $dependency_manager = $this->getConfigDependencyManager(); @@ -349,7 +349,7 @@ public function getConfigEntitiesToChange($operation, $type, array $names, $dry_ } // Now that we've fixed all the possible dependencies, for the remaining we - // need to apply the default action depending on the operation. + // apply the default action, depending on the operation. if ($operation == ConfigManagerInterface::REMOVE) { // On remove the default action of unresolved dependencies is deletion. // Reverse the deletes so that entities are removed in the correct order @@ -393,11 +393,10 @@ public function getConfigCollectionInfo() { /** * Calls an entity's dependency resolver method. * - * A helper method to call the entity's dependency resolver method, such as: - * onDependencyRemoval() or onDependencyUpdate(). The methods are called with - * the correct list of affected entities. This list should only contain - * dependencies on the entity. Configuration and content entity dependencies - * will be converted into entity objects. + * A helper method to call the entity's dependency resolver method, such as + * onDependencyRemoval() or onDependencyUpdating(). The methods are called + * with the correct list of affected entities. This list should only contain + * dependencies on the entity. * * @param string $operation * Can be one of the ConfigManagerInterface constants: REMOVE, UPDATE. @@ -409,11 +408,10 @@ public function getConfigCollectionInfo() { * The type of dependency being checked. Either 'module', 'theme', 'config' * or 'content'. * @param array $names - * The specific names to check. If $type equals 'module' or 'theme' then it - * should be a list of module names or theme names. In the case of 'config' - * or 'content' it should be a list of configuration dependency names. When - * type equals 'config' or 'content', the caller can choose to pass the - * names as array keys and the entire entities as values. + * A list of specific items, keyed by the configuration dependency names. If + * $type equals 'module' or 'theme' then the value is the same as the key. + * In the case of 'config' or 'content' the values are the full dependency + * entities. * * @return bool * TRUE if the entity has changed as a result of calling the @@ -496,12 +494,17 @@ public function findMissingContentDependencies() { * case of 'config' or 'content' it should be a list of configuration * dependency names. For entity dependencies, the caller can, alternatively, * pass the full entity object instead of its dependency name. + * + * @return array + * The normalized list of dependencies, keyed by dependency name. If $type + * equals 'module' or 'theme', the value is the same as the key. In the case + * of 'config' or 'content' it should be the full dependency entity. */ - protected function normalizeNames($type, array &$names) { + protected function getNormalizedNames($type, array $names) { $normalized = []; foreach ($names as $key => $value) { - // The name has been pass as string, in the value. if (is_string($value)) { + // The name has been passed as a string, in the value. if ($type == 'config') { $normalized[$value] = $this->loadConfigEntityByName($value); } @@ -511,16 +514,17 @@ protected function normalizeNames($type, array &$names) { $normalized[$value] = $this->entityManager->loadEntityByConfigTarget($entity_type_id, $uuid); } else { + // Module or theme. The value is the same as the key. $normalized[$value] = $value; } } - // The name has been passed as a full config or content entity. elseif ($value instanceof EntityInterface) { + // The name has been passed as a full config or content entity. /** @var \Drupal\Core\Entity\EntityInterface $value */ $normalized[$value->getConfigDependencyName()] = $value; } } - $names = $normalized; + return $normalized; } } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index bbd0d1d..5424dda 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -358,7 +358,7 @@ public function preSave(EntityStorageInterface $storage) { } // Fix any dependencies. - $config_entities = $this->getConfigManager() ->getConfigEntitiesToChange(ConfigManagerInterface::UPDATE, 'config', [$this], FALSE); + $config_entities = $this->getConfigManager()->getConfigEntitiesToChange(ConfigManagerInterface::UPDATE, 'config', [$this], FALSE); /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $dependent_entity */ foreach ($config_entities['update'] as $dependent_entity) { $dependent_entity->save(); diff --git a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml index 6cad91b..9af8c7b 100644 --- a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml +++ b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml @@ -152,3 +152,16 @@ config_test.foo: config_test.bar: type: config_test.foo + +config_test.dependent_config_test.*: + type: config_entity + mapping: + id: + type: string + label: 'ID' + label: + type: label + label: 'Label' + targetConfigId: + type: string + label: 'Target configuration ID' diff --git a/core/modules/config/tests/config_test/src/Entity/DependentConfigTest.php b/core/modules/config/tests/config_test/src/Entity/DependentConfigTest.php new file mode 100644 index 0000000..c5ba944 --- /dev/null +++ b/core/modules/config/tests/config_test/src/Entity/DependentConfigTest.php @@ -0,0 +1,84 @@ +targetConfigId)) { + $storage = $this->entityTypeManager()->getStorage('config_test'); + if ($target = $storage->load($this->targetConfigId)) { + $this->addDependency($target->getConfigDependencyKey(), $target->getConfigDependencyName()); + } + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function onDependencyUpdating(array $dependencies) { + $changed = parent::onDependencyUpdating($dependencies); + + if (!empty($this->targetConfigId)) { + $storage = $this->entityTypeManager()->getStorage('config_test'); + if ($target = $storage->load($this->targetConfigId)) { + if (!empty($dependency = $dependencies[$target->getConfigDependencyKey()][$target->getConfigDependencyName()])) { + $this->set('label', "Config of '{$dependency->label()}'"); + $changed = TRUE; + } + } + } + + return $changed; + } + +} diff --git a/core/modules/config/tests/src/Kernel/ConfigDependencyTest.php b/core/modules/config/tests/src/Kernel/ConfigDependencyTest.php new file mode 100644 index 0000000..b9ebf9a --- /dev/null +++ b/core/modules/config/tests/src/Kernel/ConfigDependencyTest.php @@ -0,0 +1,60 @@ +container->get('entity_type.manager')->getStorage('config_test'); + + /** @var \Drupal\config_test\Entity\DependentConfigTest $dependency */ + $dependency = $storage->create(['id' => 'dependency', 'label' => 'Dependency']); + $dependency->save(); + + // Create a new 'dependent_config_test' config entity that has $dependency + // entity as dependency. + $config = DependentConfigTest::create([ + 'id' => 'config', + // The $config entity label reflects the dependency entity label. + 'label' => "Config of '{$dependency->label()}'", + 'targetConfigId' => 'dependency', + ]); + $config->save(); + + // Modify the dependency by setting a new label. + $dependency->set('label', 'Overridden')->save(); + + // Check that $config has automatically changed its label. + $this->assertSame("Config of 'Overridden'", DependentConfigTest::load('config')->label()); + + // Delete the dependency. + $dependency->delete(); + + // Check that $config has been deleted too. + $this->assertNull(DependentConfigTest::load('config')); + } + +}