From eb61f11b363485994541485f88f3a4fa64a30b0b Mon Sep 17 00:00:00 2001 From: catch <catch@35733.no-reply.drupal.org> Date: Fri, 1 Mar 2024 14:41:47 +0000 Subject: [PATCH] Issue #3420986 by kim.pepper, sorlov, larowlan, mstrelan: Convert Condition plugin discovery to attributes --- .../Core/Condition/Attribute/Condition.php | 57 +++++++++++++++++++ .../Core/Condition/ConditionInterface.php | 1 + .../Core/Condition/ConditionManager.php | 14 ++++- .../Core/Condition/ConditionPluginBase.php | 1 + .../Entity/Plugin/Condition/EntityBundle.php | 11 ++-- .../src/Plugin/Condition/BaloneySpam.php | 11 ++-- .../src/Plugin/Condition/MissingSchema.php | 11 ++-- .../src/Plugin/Condition/Language.php | 21 ++++--- .../Condition/CurrentThemeCondition.php | 11 ++-- .../src/Plugin/Condition/RequestPath.php | 11 ++-- .../src/Plugin/Condition/ResponseStatus.php | 11 ++-- .../Condition/ConditionTestDualUser.php | 26 ++++++--- .../Condition/ConditionTestNoExistingType.php | 21 ++++--- .../Condition/OptionalContextCondition.php | 22 ++++--- .../user/src/Plugin/Condition/UserRole.php | 21 ++++--- 15 files changed, 176 insertions(+), 74 deletions(-) create mode 100644 core/lib/Drupal/Core/Condition/Attribute/Condition.php diff --git a/core/lib/Drupal/Core/Condition/Attribute/Condition.php b/core/lib/Drupal/Core/Condition/Attribute/Condition.php new file mode 100644 index 000000000000..da1db7c21202 --- /dev/null +++ b/core/lib/Drupal/Core/Condition/Attribute/Condition.php @@ -0,0 +1,57 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Core\Condition\Attribute; + +use Drupal\Component\Plugin\Attribute\Plugin; +use Drupal\Core\StringTranslation\TranslatableMarkup; + +/** + * Defines a condition plugin attribute. + * + * Condition plugins provide generalized conditions for use in other + * operations, such as conditional block placement. + * + * Plugin Namespace: Plugin\Condition + * + * For a working example, see \Drupal\user\Plugin\Condition\UserRole. + * + * @see \Drupal\Core\Condition\ConditionManager + * @see \Drupal\Core\Condition\ConditionInterface + * @see \Drupal\Core\Condition\ConditionPluginBase + * @see block_api + * + * @ingroup plugin_api + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +class Condition extends Plugin { + + /** + * Constructs a Condition attribute. + * + * @param string $id + * The plugin ID. + * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $label + * (optional) The human-readable name of the condition. + * @param string|null $module + * (optional) The name of the module providing the type. + * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $category + * (optional) The category under which the condition should be listed in the + * UI. + * @param array $context_definitions + * (optional) An array of context definitions describing the context used by + * the plugin. + * @param class-string|null $deriver + * (optional) The deriver class. + */ + public function __construct( + public readonly string $id, + public readonly ?TranslatableMarkup $label = NULL, + public readonly ?string $module = NULL, + public readonly ?TranslatableMarkup $category = NULL, + public readonly array $context_definitions = [], + public readonly ?string $deriver = NULL, + ) {} + +} diff --git a/core/lib/Drupal/Core/Condition/ConditionInterface.php b/core/lib/Drupal/Core/Condition/ConditionInterface.php index 4ebd1ce2ebf9..9ad23df0fba7 100644 --- a/core/lib/Drupal/Core/Condition/ConditionInterface.php +++ b/core/lib/Drupal/Core/Condition/ConditionInterface.php @@ -39,6 +39,7 @@ * @see \Drupal\Core\Executable\ExecutableInterface * @see \Drupal\Core\Condition\ConditionManager * @see \Drupal\Core\Condition\Annotation\Condition + * @see \Drupal\Core\Condition\Attribute\Condition * @see \Drupal\Core\Condition\ConditionPluginBase * * @ingroup plugin_api diff --git a/core/lib/Drupal/Core/Condition/ConditionManager.php b/core/lib/Drupal/Core/Condition/ConditionManager.php index cb8782daa989..5f989fc529aa 100644 --- a/core/lib/Drupal/Core/Condition/ConditionManager.php +++ b/core/lib/Drupal/Core/Condition/ConditionManager.php @@ -4,9 +4,10 @@ use Drupal\Component\Plugin\CategorizingPluginManagerInterface; use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Executable\ExecutableException; -use Drupal\Core\Executable\ExecutableManagerInterface; use Drupal\Core\Executable\ExecutableInterface; +use Drupal\Core\Executable\ExecutableManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\CategorizingPluginManagerTrait; use Drupal\Core\Plugin\DefaultPluginManager; @@ -16,7 +17,7 @@ /** * A plugin manager for condition plugins. * - * @see \Drupal\Core\Condition\Annotation\Condition + * @see \Drupal\Core\Condition\Attribute\Condition * @see \Drupal\Core\Condition\ConditionInterface * @see \Drupal\Core\Condition\ConditionPluginBase * @@ -42,7 +43,14 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac $this->alterInfo('condition_info'); $this->setCacheBackend($cache_backend, 'condition_plugins'); - parent::__construct('Plugin/Condition', $namespaces, $module_handler, 'Drupal\Core\Condition\ConditionInterface', 'Drupal\Core\Condition\Annotation\Condition'); + parent::__construct( + 'Plugin/Condition', + $namespaces, + $module_handler, + ConditionInterface::class, + Condition::class, + 'Drupal\Core\Condition\Annotation\Condition' + ); } /** diff --git a/core/lib/Drupal/Core/Condition/ConditionPluginBase.php b/core/lib/Drupal/Core/Condition/ConditionPluginBase.php index 48d6cc64faed..bb310787dcfa 100644 --- a/core/lib/Drupal/Core/Condition/ConditionPluginBase.php +++ b/core/lib/Drupal/Core/Condition/ConditionPluginBase.php @@ -12,6 +12,7 @@ * Provides a basis for fulfilling contexts for condition plugins. * * @see \Drupal\Core\Condition\Annotation\Condition + * @see \Drupal\Core\Condition\Attribute\Condition * @see \Drupal\Core\Condition\ConditionInterface * @see \Drupal\Core\Condition\ConditionManager * diff --git a/core/lib/Drupal/Core/Entity/Plugin/Condition/EntityBundle.php b/core/lib/Drupal/Core/Entity/Plugin/Condition/EntityBundle.php index f073fdbcc12e..d9f19258361c 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/Condition/EntityBundle.php +++ b/core/lib/Drupal/Core/Entity/Plugin/Condition/EntityBundle.php @@ -2,20 +2,21 @@ namespace Drupal\Core\Entity\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\Core\Entity\Plugin\Condition\Deriver\EntityBundle as EntityBundleDeriver; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides the 'Entity Bundle' condition. - * - * @Condition( - * id = "entity_bundle", - * deriver = "\Drupal\Core\Entity\Plugin\Condition\Deriver\EntityBundle", - * ) */ +#[Condition( + id: "entity_bundle", + deriver: EntityBundleDeriver::class, +)] class EntityBundle extends ConditionPluginBase implements ContainerFactoryPluginInterface { /** diff --git a/core/modules/block/tests/modules/block_test/src/Plugin/Condition/BaloneySpam.php b/core/modules/block/tests/modules/block_test/src/Plugin/Condition/BaloneySpam.php index a977c166e214..050e93ca2758 100644 --- a/core/modules/block/tests/modules/block_test/src/Plugin/Condition/BaloneySpam.php +++ b/core/modules/block/tests/modules/block_test/src/Plugin/Condition/BaloneySpam.php @@ -2,16 +2,17 @@ namespace Drupal\block_test\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; +use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Provides a 'baloney_spam' condition. - * - * @Condition( - * id = "baloney_spam", - * label = @Translation("Baloney spam"), - * ) */ +#[Condition( + id: "baloney_spam", + label: new TranslatableMarkup("Baloney spam"), +)] class BaloneySpam extends ConditionPluginBase { /** diff --git a/core/modules/block/tests/modules/block_test/src/Plugin/Condition/MissingSchema.php b/core/modules/block/tests/modules/block_test/src/Plugin/Condition/MissingSchema.php index 977374c51323..e856ffdaed5d 100644 --- a/core/modules/block/tests/modules/block_test/src/Plugin/Condition/MissingSchema.php +++ b/core/modules/block/tests/modules/block_test/src/Plugin/Condition/MissingSchema.php @@ -2,16 +2,17 @@ namespace Drupal\block_test\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; +use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Provides a 'missing_schema' condition. - * - * @Condition( - * id = "missing_schema", - * label = @Translation("Missing schema"), - * ) */ +#[Condition( + id: "missing_schema", + label: new TranslatableMarkup("Missing schema"), +)] class MissingSchema extends ConditionPluginBase { /** diff --git a/core/modules/language/src/Plugin/Condition/Language.php b/core/modules/language/src/Plugin/Condition/Language.php index 62008496ecfe..9fea9d010376 100644 --- a/core/modules/language/src/Plugin/Condition/Language.php +++ b/core/modules/language/src/Plugin/Condition/Language.php @@ -2,24 +2,29 @@ namespace Drupal\language\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Plugin\Context\ContextDefinition; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a 'Language' condition. - * - * @Condition( - * id = "language", - * label = @Translation("Language"), - * context_definitions = { - * "language" = @ContextDefinition("language", label = @Translation("Language")) - * } - * ) */ +#[Condition( + id: "language", + label: new TranslatableMarkup("Language"), + context_definitions: [ + "language" => new ContextDefinition( + data_type: "language", + label: new TranslatableMarkup("Language"), + ), + ] +)] class Language extends ConditionPluginBase implements ContainerFactoryPluginInterface { /** diff --git a/core/modules/system/src/Plugin/Condition/CurrentThemeCondition.php b/core/modules/system/src/Plugin/Condition/CurrentThemeCondition.php index d282963aa6ff..5c0f4ad48f6c 100644 --- a/core/modules/system/src/Plugin/Condition/CurrentThemeCondition.php +++ b/core/modules/system/src/Plugin/Condition/CurrentThemeCondition.php @@ -2,21 +2,22 @@ namespace Drupal\system\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\Theme\ThemeManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a 'Current Theme' condition. - * - * @Condition( - * id = "current_theme", - * label = @Translation("Current Theme"), - * ) */ +#[Condition( + id: "current_theme", + label: new TranslatableMarkup("Current Theme"), +)] class CurrentThemeCondition extends ConditionPluginBase implements ContainerFactoryPluginInterface { /** diff --git a/core/modules/system/src/Plugin/Condition/RequestPath.php b/core/modules/system/src/Plugin/Condition/RequestPath.php index 9b4bd474d1a7..7e6aa074d7f8 100644 --- a/core/modules/system/src/Plugin/Condition/RequestPath.php +++ b/core/modules/system/src/Plugin/Condition/RequestPath.php @@ -2,23 +2,24 @@ namespace Drupal\system\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Path\CurrentPathStack; use Drupal\Core\Path\PathMatcherInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\path_alias\AliasManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RequestStack; /** * Provides a 'Request Path' condition. - * - * @Condition( - * id = "request_path", - * label = @Translation("Request Path"), - * ) */ +#[Condition( + id: "request_path", + label: new TranslatableMarkup("Request Path"), +)] class RequestPath extends ConditionPluginBase implements ContainerFactoryPluginInterface { /** diff --git a/core/modules/system/src/Plugin/Condition/ResponseStatus.php b/core/modules/system/src/Plugin/Condition/ResponseStatus.php index aa82db66b99e..9dcf47db301f 100644 --- a/core/modules/system/src/Plugin/Condition/ResponseStatus.php +++ b/core/modules/system/src/Plugin/Condition/ResponseStatus.php @@ -4,10 +4,12 @@ namespace Drupal\system\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\StringTranslation\PluralTranslatableMarkup; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; @@ -15,12 +17,11 @@ /** * Provides a 'Response status' condition. - * - * @Condition( - * id = "response_status", - * label = @Translation("Response status"), - * ) */ +#[Condition( + id: "response_status", + label: new TranslatableMarkup("Response status"), +)] class ResponseStatus extends ConditionPluginBase implements ContainerFactoryPluginInterface { /** diff --git a/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestDualUser.php b/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestDualUser.php index 81d3e7cea27b..7463a5a04e90 100644 --- a/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestDualUser.php +++ b/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestDualUser.php @@ -2,20 +2,28 @@ namespace Drupal\condition_test\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; +use Drupal\Core\Plugin\Context\EntityContextDefinition; +use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Provides a condition that requires two users. - * - * @Condition( - * id = "condition_test_dual_user", - * label = @Translation("Dual user"), - * context_definitions = { - * "user1" = @ContextDefinition("entity:user", label = @Translation("User 1")), - * "user2" = @ContextDefinition("entity:user", label = @Translation("User 2")) - * } - * ) */ +#[Condition( + id: "condition_test_dual_user", + label: new TranslatableMarkup("Dual user"), + context_definitions: [ + "user1" => new EntityContextDefinition( + data_type: "entity:user", + label: new TranslatableMarkup("User 1"), + ), + "user2" => new EntityContextDefinition( + data_type: "entity:user", + label: new TranslatableMarkup("User 2"), + ), + ] +)] class ConditionTestDualUser extends ConditionPluginBase { /** diff --git a/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestNoExistingType.php b/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestNoExistingType.php index f465916e84dd..717dc39dfd5d 100644 --- a/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestNoExistingType.php +++ b/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/ConditionTestNoExistingType.php @@ -2,19 +2,24 @@ namespace Drupal\condition_test\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; +use Drupal\Core\Plugin\Context\ContextDefinition; +use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Provides a condition that has a no existing context. - * - * @Condition( - * id = "condition_test_no_existing_type", - * label = @Translation("No existing type"), - * context_definitions = { - * "no_existing_type" = @ContextDefinition("no_existing_type", label = @Translation("No existing type")), - * } - * ) */ +#[Condition( + id: "condition_test_no_existing_type", + label: new TranslatableMarkup("No existing type"), + context_definitions: [ + "no_existing_type" => new ContextDefinition( + data_type: "no_existing_type", + label: new TranslatableMarkup("No existing type"), + ), + ] +)] class ConditionTestNoExistingType extends ConditionPluginBase { /** diff --git a/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/OptionalContextCondition.php b/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/OptionalContextCondition.php index 46f48d24a123..031c96129249 100644 --- a/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/OptionalContextCondition.php +++ b/core/modules/system/tests/modules/condition_test/src/Plugin/Condition/OptionalContextCondition.php @@ -2,22 +2,28 @@ namespace Drupal\condition_test\Plugin\Condition; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; +use Drupal\Core\Plugin\Context\EntityContextDefinition; +use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Provides a condition with an optional node context. * * The context type entity:node is used since that would allow to also use this * for web tests with the node route context. - * - * @Condition( - * id = "condition_test_optional_context", - * label = @Translation("Optional context"), - * context_definitions = { - * "node" = @ContextDefinition("entity:node", label = @Translation("Node"), required = FALSE), - * } - * ) */ +#[Condition( + id: "condition_test_optional_context", + label: new TranslatableMarkup("Optional context"), + context_definitions: [ + "node" => new EntityContextDefinition( + data_type: "entity:node", + label: new TranslatableMarkup("Node"), + required: FALSE, + ), + ] +)] class OptionalContextCondition extends ConditionPluginBase { /** diff --git a/core/modules/user/src/Plugin/Condition/UserRole.php b/core/modules/user/src/Plugin/Condition/UserRole.php index abd08467e1cb..b046adf86900 100644 --- a/core/modules/user/src/Plugin/Condition/UserRole.php +++ b/core/modules/user/src/Plugin/Condition/UserRole.php @@ -3,22 +3,27 @@ namespace Drupal\user\Plugin\Condition; use Drupal\Component\Utility\Html; +use Drupal\Core\Condition\Attribute\Condition; use Drupal\Core\Condition\ConditionPluginBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Plugin\Context\EntityContextDefinition; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; /** * Provides a 'User Role' condition. - * - * @Condition( - * id = "user_role", - * label = @Translation("User Role"), - * context_definitions = { - * "user" = @ContextDefinition("entity:user", label = @Translation("User")) - * } - * ) */ +#[Condition( + id: "user_role", + label: new TranslatableMarkup("User Role"), + context_definitions: [ + "user" => new EntityContextDefinition( + data_type: "entity:user", + label: new TranslatableMarkup("User"), + ), + ], +)] class UserRole extends ConditionPluginBase { /** -- GitLab