diff options
author | catch <6915-catch@users.noreply.drupalcode.org> | 2025-04-25 08:27:24 +0100 |
---|---|---|
committer | catch <6915-catch@users.noreply.drupalcode.org> | 2025-04-25 08:27:24 +0100 |
commit | 0fac8cc763e0b2e79b365ad211ab4567019c710b (patch) | |
tree | 62f55bd4aafd8a9ef4ab75ba768816fadf671c4b /core | |
parent | 23301df602cf737ba8bf31e34909c36b3f98f22d (diff) | |
download | drupal-0fac8cc763e0b2e79b365ad211ab4567019c710b.tar.gz drupal-0fac8cc763e0b2e79b365ad211ab4567019c710b.zip |
Issue #3504368 by godotislate, dpagini, smustgrave: Removing field from LB content type edits associated roles
Diffstat (limited to 'core')
4 files changed, 116 insertions, 6 deletions
diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php index 21b40363398..8f7ff854006 100644 --- a/core/lib/Drupal/Core/Config/ConfigManager.php +++ b/core/lib/Drupal/Core/Config/ConfigManager.php @@ -295,17 +295,21 @@ class ConfigManager implements ConfigManagerInterface { // a UUID key. if ($entity_type_id) { $id = substr($config_name, strlen($definitions[$entity_type_id]->getConfigPrefix()) + 1); - $entities[$entity_type_id][] = $id; + $entities[$entity_type_id][$config_name] = $id; } } - $entities_to_return = []; + // Align the order of entities returned to the dependency order by first + // populating the keys in the same order. + $entities_to_return = array_fill_keys(array_keys($dependencies), NULL); foreach ($entities as $entity_type_id => $entities_to_load) { $storage = $this->entityTypeManager->getStorage($entity_type_id); - // Remove the keys since there are potential ID clashes from different - // configuration entity types. - $entities_to_return[] = array_values($storage->loadMultiple($entities_to_load)); + $loaded_entities = $storage->loadMultiple($entities_to_load); + foreach ($loaded_entities as $loaded_entity) { + $entities_to_return[$loaded_entity->getConfigDependencyName()] = $loaded_entity; + } } - return array_merge(...$entities_to_return); + // Return entities list with NULL entries removed. + return array_filter($entities_to_return); } /** diff --git a/core/modules/config/tests/config_test/config_test.permissions.yml b/core/modules/config/tests/config_test/config_test.permissions.yml new file mode 100644 index 00000000000..e838e8f927e --- /dev/null +++ b/core/modules/config/tests/config_test/config_test.permissions.yml @@ -0,0 +1,2 @@ +permission_callbacks: + - \Drupal\config_test\ConfigTestPermissions::configTestPermissions diff --git a/core/modules/config/tests/config_test/src/ConfigTestPermissions.php b/core/modules/config/tests/config_test/src/ConfigTestPermissions.php new file mode 100644 index 00000000000..e562cd940bc --- /dev/null +++ b/core/modules/config/tests/config_test/src/ConfigTestPermissions.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\config_test; + +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Provide dynamic permissions for testing permission dependencies on config. + */ +class ConfigTestPermissions implements ContainerInjectionInterface { + + use StringTranslationTrait; + + public function __construct(protected EntityTypeManagerInterface $entityTypeManager) {} + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container): static { + return new static( + $container->get('entity_type.manager'), + ); + } + + /** + * Permissions callback. + * + * @return array + * The list of permissions. + */ + public function configTestPermissions(): array { + /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface[] $entities */ + $entities = $this->entityTypeManager->getStorage('config_test')->loadMultiple(); + $permissions = []; + foreach ($entities as $entity) { + $config_name = $entity->getConfigDependencyName(); + $permissions["permission with $config_name dependency"] = [ + 'title' => $this->t('Permission with a dependency on config test entity %id', [ + '%id' => $entity->id(), + ]), + 'dependencies' => [$entity->getConfigDependencyKey() => [$config_name]], + ]; + } + return $permissions; + } + +} diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php index b0ac992f084..38449b22255 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigDependencyTest.php @@ -6,6 +6,7 @@ namespace Drupal\KernelTests\Core\Config; use Drupal\entity_test\Entity\EntityTest; use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; +use Drupal\user\Entity\Role; /** * Tests for configuration dependencies. @@ -641,6 +642,57 @@ class ConfigDependencyTest extends EntityKernelTestBase { } /** + * Tests that config dependency ordering. + */ + public function testDependencyOrder(): void { + $storage = $this->container->get('entity_type.manager')->getStorage('config_test'); + // Test dependencies between modules. + $entity1 = $storage->create(['id' => 'entity1']); + $entity1->save(); + // 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' => [$entity1->getConfigDependencyName()]]]]); + $entity3->save(); + // Include a role entity to test ordering when dependencies have multiple + // entity types. + $role = Role::create([ + 'id' => 'test_role', + 'label' => 'Test role', + // This adds an implicit dependency on $entity 2, and hence also $entity1, + // to the role. + 'permissions' => ["permission with {$entity2->getConfigDependencyName()} dependency"], + ]); + $role->save(); + $entity4 = $storage->create([ + 'id' => 'entity4', + 'dependencies' => [ + 'enforced' => [ + 'config' => [ + // Add dependencies to $entity3 and the role so that the $entity4 + // should be last to be processed when handling dependency removal. + // The role should be processed after $entity1 and $entity2, but + // before $entity4. + $entity3->getConfigDependencyName(), + $role->getConfigDependencyName(), + ], + ], + ], + ]); + $entity4->save(); + + // Create scenario where entity1 is deleted, but all the config_test + // entities depending on entity1 are fixed instead of being deleted. This + // means that entity2 is not deleted, so the role should not lose the + // permission depending on entity2. + \Drupal::state()->set('config_test.fix_dependencies', ['config_test.dynamic.entity1']); + $entity1->delete(); + $role = Role::load('test_role'); + $this->assertNotNull($role); + $this->assertTrue($role->hasPermission("permission with {$entity2->getConfigDependencyName()} dependency")); + } + + /** * Gets a list of identifiers from an array of configuration entities. * * @param \Drupal\Core\Config\Entity\ConfigEntityInterface[] $dependents |