From b9dfd470e35da9efbfc885c60483f49a92089350 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Sat, 2 Mar 2024 11:27:41 +0000
Subject: [PATCH] Issue #3420993 by Amber Himes Matz, andypost, sakthi_dev,
 smustgrave, larowlan, catch, quietone: Convert HelpSection plugin discovery
 to attributes

---
 .../help/src/Attribute/HelpSection.php        | 57 +++++++++++++++++++
 core/modules/help/src/HelpSectionManager.php  |  3 +-
 .../Plugin/HelpSection/HelpTopicSection.php   | 16 +++---
 .../Plugin/HelpSection/HookHelpSection.php    | 13 +++--
 .../Plugin/HelpSection/EmptyHelpSection.php   | 13 +++--
 .../Plugin/HelpSection/TestHelpSection.php    | 17 +++---
 6 files changed, 90 insertions(+), 29 deletions(-)
 create mode 100644 core/modules/help/src/Attribute/HelpSection.php

diff --git a/core/modules/help/src/Attribute/HelpSection.php b/core/modules/help/src/Attribute/HelpSection.php
new file mode 100644
index 000000000000..17564b7df0e1
--- /dev/null
+++ b/core/modules/help/src/Attribute/HelpSection.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\help\Attribute;
+
+use Drupal\Component\Plugin\Attribute\Plugin;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Defines a HelpSection attribute object for plugin discovery.
+ *
+ * Plugin Namespace: Plugin\HelpSection
+ *
+ * For a working example, see \Drupal\help\Plugin\HelpSection\HookHelpSection.
+ *
+ * @see \Drupal\help\HelpSectionPluginInterface
+ * @see \Drupal\help\Plugin\HelpSection\HelpSectionPluginBase
+ * @see \Drupal\help\HelpSectionManager
+ * @see hook_help_section_info_alter()
+ * @see plugin_api
+ */
+#[\Attribute(\Attribute::TARGET_CLASS)]
+class HelpSection extends Plugin {
+
+  /**
+   * Constructs a HelpSection attribute.
+   *
+   * @param string $id
+   *   The plugin ID.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup $title
+   *   The text to use as the title of the help page section.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description
+   *   (optional) The description of the help page section.
+   * @param string|null $permission
+   *   (optional) The permission required to access the help page section.
+   *
+   *   Only set if this section needs its own permission, beyond the generic
+   *   'access help pages' permission needed to see the /admin/help
+   *   page itself.
+   * @param int|null $weight
+   *   (optional) The weight of the help page section.
+   * @param string|null $deriver
+   *   (optional) The deriver class.
+   *
+   *   The sections will be ordered by this weight on the help page.
+   */
+  public function __construct(
+    public readonly string $id,
+    public readonly TranslatableMarkup $title,
+    public readonly ?TranslatableMarkup $description = NULL,
+    public readonly ?string $permission = NULL,
+    public readonly ?int $weight = NULL,
+    public readonly ?string $deriver = NULL,
+  ) {}
+
+}
diff --git a/core/modules/help/src/HelpSectionManager.php b/core/modules/help/src/HelpSectionManager.php
index 1943ee056d48..656ab14dc199 100644
--- a/core/modules/help/src/HelpSectionManager.php
+++ b/core/modules/help/src/HelpSectionManager.php
@@ -3,6 +3,7 @@
 namespace Drupal\help;
 
 use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\help\Attribute\HelpSection;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
@@ -36,7 +37,7 @@ class HelpSectionManager extends DefaultPluginManager {
    *   The module handler for the alter hook.
    */
   public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    parent::__construct('Plugin/HelpSection', $namespaces, $module_handler, 'Drupal\help\HelpSectionPluginInterface', 'Drupal\help\Annotation\HelpSection');
+    parent::__construct('Plugin/HelpSection', $namespaces, $module_handler, 'Drupal\help\HelpSectionPluginInterface', HelpSection::class, 'Drupal\help\Annotation\HelpSection');
 
     $this->alterInfo('help_section_info');
     $this->setCacheBackend($cache_backend, 'help_section_plugins');
diff --git a/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php b/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php
index 6314ee535c43..e2395f56fb67 100644
--- a/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php
+++ b/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php
@@ -3,6 +3,8 @@
 namespace Drupal\help\Plugin\HelpSection;
 
 use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\help\Attribute\HelpSection;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\help\SearchableHelpInterface;
 use Drupal\help\HelpTopicPluginInterface;
 use Drupal\help\HelpTopicPluginManagerInterface;
@@ -18,17 +20,15 @@
 /**
  * Provides the help topics list section for the help page.
  *
- * @HelpSection(
- *   id = "help_topics",
- *   title = @Translation("Topics"),
- *   weight = -10,
- *   description = @Translation("Topics can be provided by modules or themes. Top-level help topics on your site:"),
- *   permission = "access help pages"
- * )
- *
  * @internal
  *   Plugin classes are internal.
  */
+#[HelpSection(
+  id: 'help_topics',
+  title: new TranslatableMarkup('Topics'),
+  description: new TranslatableMarkup('Topics can be provided by modules or themes. Top-level help topics on your site:'),
+  weight: -10
+)]
 class HelpTopicSection extends HelpSectionPluginBase implements ContainerFactoryPluginInterface, SearchableHelpInterface {
 
   /**
diff --git a/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php b/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php
index 1625c90463f8..9336d7fde403 100644
--- a/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php
+++ b/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php
@@ -3,19 +3,20 @@
 namespace Drupal\help\Plugin\HelpSection;
 
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Link;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\help\Attribute\HelpSection;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides the module topics list section for the help page.
- *
- * @HelpSection(
- *   id = "hook_help",
- *   title = @Translation("Module overviews"),
- *   description = @Translation("Module overviews are provided by modules. Overviews available for your installed modules:"),
- * )
  */
+#[HelpSection(
+  id: 'hook_help',
+  title: new TranslatableMarkup('Module overviews'),
+  description: new TranslatableMarkup('Module overviews are provided by modules. Overviews available for your installed modules:')
+)]
 class HookHelpSection extends HelpSectionPluginBase implements ContainerFactoryPluginInterface {
 
   /**
diff --git a/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php b/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php
index db390285bbfd..45480795756a 100644
--- a/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php
+++ b/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php
@@ -2,17 +2,18 @@
 
 namespace Drupal\help_page_test\Plugin\HelpSection;
 
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\help\Plugin\HelpSection\HelpSectionPluginBase;
+use Drupal\help\Attribute\HelpSection;
 
 /**
  * Provides an empty section for the help page, for testing.
- *
- * @HelpSection(
- *   id = "empty_section",
- *   title = @Translation("Empty section"),
- *   description = @Translation("This description should appear."),
- * )
  */
+#[HelpSection(
+  id: 'empty_section',
+  title: new TranslatableMarkup('Empty section'),
+  description: new TranslatableMarkup('This description should appear.')
+)]
 class EmptyHelpSection extends HelpSectionPluginBase {
 
   /**
diff --git a/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php b/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php
index 9860221800cd..731886e4fda4 100644
--- a/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php
+++ b/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php
@@ -7,20 +7,21 @@
 use Drupal\Core\Url;
 use Drupal\Core\Link;
 use Drupal\help\Plugin\HelpSection\HelpSectionPluginBase;
+use Drupal\help\Attribute\HelpSection;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 
 // cspell:ignore asdrsad barmm foomm sqruct wcsrefsdf sdeeeee
 
 /**
  * Provides a searchable help section for testing.
- *
- * @HelpSection(
- *   id = "help_topics_test",
- *   title = @Translation("Test section"),
- *   weight = 100,
- *   description = @Translation("For testing search"),
- *   permission = "access test help"
- * )
  */
+#[HelpSection(
+  id: 'help_topics_test',
+  title: new TranslatableMarkup('Test section'),
+  description: new TranslatableMarkup('For testing search'),
+  permission: 'access test help',
+  weight: 100
+)]
 class TestHelpSection extends HelpSectionPluginBase implements SearchableHelpInterface {
 
   /**
-- 
GitLab