From e573df5fd0835d9d5fd1c9f935d0c8ba5f780982 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Fri, 27 Sep 2024 11:54:03 +0200 Subject: [PATCH] Issue #3302833 by akhil babu, b_sharpe, alexpott, oily, smustgrave: Improve PluginNotFound exception to include possible shorthand action IDs --- .../Config/Action/ConfigActionManager.php | 17 +++++++++++++++-- .../AddModerationConfigActionTest.php | 2 +- .../AddToAllBundlesConfigActionTest.php | 2 +- .../Core/Recipe/PermissionsPerBundleTest.php | 2 +- .../Core/Recipe/RecipeRunnerTest.php | 19 ++++++++++++++++++- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/core/lib/Drupal/Core/Config/Action/ConfigActionManager.php b/core/lib/Drupal/Core/Config/Action/ConfigActionManager.php index 0bd38dd26d5..00952fa3657 100644 --- a/core/lib/Drupal/Core/Config/Action/ConfigActionManager.php +++ b/core/lib/Drupal/Core/Config/Action/ConfigActionManager.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Drupal\Core\Config\Action; +use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Component\Plugin\PluginBase; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\Action\Attribute\ConfigAction; @@ -137,8 +138,20 @@ class ConfigActionManager extends DefaultPluginManager { $action_id = $this->getShorthandActionIdsForEntityType($entity_type)[$action_id] ?? $action_id; } } - /** @var \Drupal\Core\Config\Action\ConfigActionPluginInterface $action */ - $action = $this->createInstance($action_id); + try { + /** @var \Drupal\Core\Config\Action\ConfigActionPluginInterface $action */ + $action = $this->createInstance($action_id); + } + catch (PluginNotFoundException $e) { + $entity_type = $this->configManager->getEntityTypeIdByName($configName); + if ($entity_type) { + $action_ids = $this->getShorthandActionIdsForEntityType($entity_type); + $valid_ids = implode(', ', array_keys($action_ids)); + throw new PluginNotFoundException($action_id, sprintf('The "%s" entity does not support the "%s" config action. Valid config actions for %s are: %s', $entity_type, $action_id, $entity_type, $valid_ids)); + } + throw $e; + } + foreach ($this->getConfigNamesMatchingExpression($configName) as $name) { $action->apply($name, $data); $typed_config = $this->typedConfig->createFromNameAndData($name, $this->configFactory->get($name)->getRawData()); diff --git a/core/modules/content_moderation/tests/src/Kernel/ConfigAction/AddModerationConfigActionTest.php b/core/modules/content_moderation/tests/src/Kernel/ConfigAction/AddModerationConfigActionTest.php index 4d5afd395e2..a48ec826cc7 100644 --- a/core/modules/content_moderation/tests/src/Kernel/ConfigAction/AddModerationConfigActionTest.php +++ b/core/modules/content_moderation/tests/src/Kernel/ConfigAction/AddModerationConfigActionTest.php @@ -76,7 +76,7 @@ class AddModerationConfigActionTest extends KernelTestBase { public function testActionOnlyTargetsWorkflows(): void { $recipe = $this->createRecipe('user.role.anonymous'); $this->expectException(PluginNotFoundException::class); - $this->expectExceptionMessage('The "addNodeTypes" plugin does not exist.'); + $this->expectExceptionMessage('The "user_role" entity does not support the "addNodeTypes" config action.'); RecipeRunner::processRecipe($recipe); } diff --git a/core/modules/field/tests/src/Kernel/AddToAllBundlesConfigActionTest.php b/core/modules/field/tests/src/Kernel/AddToAllBundlesConfigActionTest.php index 4f6ec730877..0c849c246ff 100644 --- a/core/modules/field/tests/src/Kernel/AddToAllBundlesConfigActionTest.php +++ b/core/modules/field/tests/src/Kernel/AddToAllBundlesConfigActionTest.php @@ -74,7 +74,7 @@ class AddToAllBundlesConfigActionTest extends KernelTestBase { // Expect an error when the 'addToAllBundles' action is invoked on anything // other than a field storage config entity. $this->expectException(PluginNotFoundException::class); - $this->expectExceptionMessage('The "addToAllBundles" plugin does not exist.'); + $this->expectExceptionMessage('The "user_role" entity does not support the "addToAllBundles" config action.'); $this->applyAction('user.role.anonymous'); } diff --git a/core/tests/Drupal/KernelTests/Core/Recipe/PermissionsPerBundleTest.php b/core/tests/Drupal/KernelTests/Core/Recipe/PermissionsPerBundleTest.php index c9465a31d49..0a702e0322c 100644 --- a/core/tests/Drupal/KernelTests/Core/Recipe/PermissionsPerBundleTest.php +++ b/core/tests/Drupal/KernelTests/Core/Recipe/PermissionsPerBundleTest.php @@ -124,7 +124,7 @@ config: YAML; $this->expectException(PluginNotFoundException::class); - $this->expectExceptionMessage('The "grantPermissionsForEachNodeType" plugin does not exist.'); + $this->expectExceptionMessage('The "field_storage_config" entity does not support the "grantPermissionsForEachNodeType" config action.'); $this->applyRecipeFromString($recipe_data); } diff --git a/core/tests/Drupal/KernelTests/Core/Recipe/RecipeRunnerTest.php b/core/tests/Drupal/KernelTests/Core/Recipe/RecipeRunnerTest.php index 64d94653c13..871b040527d 100644 --- a/core/tests/Drupal/KernelTests/Core/Recipe/RecipeRunnerTest.php +++ b/core/tests/Drupal/KernelTests/Core/Recipe/RecipeRunnerTest.php @@ -203,6 +203,23 @@ class RecipeRunnerTest extends KernelTestBase { public function testInvalidConfigAction() :void { $recipe_data = <<createRecipe($recipe_data); + $this->expectException(PluginNotFoundException::class); + $this->expectExceptionMessage('The "setFoo" plugin does not exist.'); + RecipeRunner::processRecipe($recipe); + } + + public function testInvalidConfigActionAppliedOnConfigEntity() :void { + $recipe_data = <<createRecipe($recipe_data); $this->expectException(PluginNotFoundException::class); - $this->expectExceptionMessage('The "setBody" plugin does not exist.'); + $this->expectExceptionMessage('The "config_test" entity does not support the "setBody" config action.'); RecipeRunner::processRecipe($recipe); }