From 20d8630910242b920ae196fadc54182f3fcf2057 Mon Sep 17 00:00:00 2001
From: Tim Rohaly <tr@202830.no-reply.drupal.org>
Date: Fri, 14 Feb 2025 01:06:36 -0800
Subject: [PATCH 1/5] Issue #3502021 by tr: Support for object oriented hook
 implementations using autowired services

---
 src/Hook/VotingApiWidgetsEntityHooks.php | 63 ++++++++++++++++++++++++
 src/Hook/VotingApiWidgetsFormHooks.php   | 43 ++++++++++++++++
 src/Hook/VotingApiWidgetsHelpHooks.php   | 47 ++++++++++++++++++
 votingapi_widgets.module                 | 52 +++++++------------
 votingapi_widgets.services.yml           | 18 ++++++-
 5 files changed, 186 insertions(+), 37 deletions(-)
 create mode 100644 src/Hook/VotingApiWidgetsEntityHooks.php
 create mode 100644 src/Hook/VotingApiWidgetsFormHooks.php
 create mode 100644 src/Hook/VotingApiWidgetsHelpHooks.php

diff --git a/src/Hook/VotingApiWidgetsEntityHooks.php b/src/Hook/VotingApiWidgetsEntityHooks.php
new file mode 100644
index 0000000..54b5d0f
--- /dev/null
+++ b/src/Hook/VotingApiWidgetsEntityHooks.php
@@ -0,0 +1,63 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\votingapi_widgets\Hook;
+
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\votingapi_widgets\Plugin\VotingApiWidgetManager;
+
+/**
+ * Hook implementations used to create and dispatch Entity Events.
+ */
+final class VotingApiWidgetsEntityHooks {
+
+  /**
+   * Constructs a new VotingApiWidgetsEntityHooks service.
+   *
+   * @param \Drupal\votingapi_widgets\Plugin\VotingApiWidgetManager $widgetManager
+   *   The entity_type.manager service.
+   */
+  public function __construct(
+    protected VotingApiWidgetManager $widgetManager,
+  ) {}
+
+  /**
+   * Implements hook_entity_base_field_info().
+   */
+  #[Hook('entity_base_field_info')]
+  public function entityBaseFieldInfo(EntityTypeInterface $entity_type): array {
+    $fields = [];
+
+    // Add the field_name as a base field.
+    if ($entity_type->id() != 'vote') {
+      return $fields;
+    }
+
+    $fields['field_name'] = BaseFieldDefinition::create('string')
+      ->setLabel(new TranslatableMarkup('Field name'))
+      ->setName('field_name')
+      ->setRevisionable(FALSE)
+      ->setRequired(FALSE)
+      ->setDescription(new TranslatableMarkup('Holds the field name.'))
+      ->setPropertyConstraints('value', ['Length' => ['max' => FieldStorageConfig::NAME_MAX_LENGTH]]);
+
+    return $fields;
+  }
+
+  /**
+   * Implements hook_entity_type_build().
+   */
+  #[Hook('entity_type_build')]
+  public function entityTypeBuild(array &$entity_types): void {
+    $plugins = $this->widgetManager->getDefinitions();
+    foreach ($plugins as $plugin_id => $definition) {
+      $entity_types['vote']->setFormClass('votingapi_' . $plugin_id, 'Drupal\votingapi_widgets\Form\BaseRatingForm');
+    }
+  }
+
+}
diff --git a/src/Hook/VotingApiWidgetsFormHooks.php b/src/Hook/VotingApiWidgetsFormHooks.php
new file mode 100644
index 0000000..4fb7ebe
--- /dev/null
+++ b/src/Hook/VotingApiWidgetsFormHooks.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\votingapi_widgets\Hook;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslationInterface;
+
+/**
+ * Hook implementations used to alter and enhance forms.
+ */
+final class VotingApiWidgetsFormHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Constructs a new VotingApiWidgetsFormHooks service.
+   *
+   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
+   *   The string translation service.
+   */
+  public function __construct(
+    TranslationInterface $string_translation,
+  ) {
+    $this->stringTranslation = $string_translation;
+  }
+
+  /**
+   * Implements hook_form_FORM_ID_alter() for field_config_edit_form.
+   */
+  #[Hook('form_field_config_edit_form_alter')]
+  public function fieldConfigEditFormAlter(array &$form, FormStateInterface $form_state): void {
+    if ($form_state->getFormObject()->getEntity()->bundle() == 'voting_api_field') {
+      // We only support posting one comment at the time so it doesn't make sense
+      // to let the site builder choose anything else.
+      $form['field_storage']['subform']['cardinality_container']['cardinality']['#default_value'] = 1;
+      $form['field_storage']['subform']['cardinality_container']['#access'] = FALSE;
+    }
+  }
+
+}
diff --git a/src/Hook/VotingApiWidgetsHelpHooks.php b/src/Hook/VotingApiWidgetsHelpHooks.php
new file mode 100644
index 0000000..7c32f45
--- /dev/null
+++ b/src/Hook/VotingApiWidgetsHelpHooks.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\votingapi_widgets\Hook;
+
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\StringTranslation\TranslationInterface;
+
+/**
+ * Hook implementations used to provide help.
+ */
+final class VotingApiWidgetsHelpHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Constructs a new VotingApiWidgetsHelpHooks service.
+   *
+   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
+   *   The string translation service.
+   */
+  public function __construct(
+    TranslationInterface $string_translation,
+  ) {
+    $this->stringTranslation = $string_translation;
+  }
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help(string $route_name, RouteMatchInterface $route_match): ?string {
+    switch ($route_name) {
+      // Main module help for the votingapi_widgets module.
+      case 'help.page.votingapi_widgets':
+        $output = '<h3>' . $this->t('About') . '</h3>';
+        $output .= '<p>' . $this->t('Voting API Widgets') . '</p>';
+        return $output;
+
+      default:
+    }
+    return NULL;
+  }
+
+}
diff --git a/votingapi_widgets.module b/votingapi_widgets.module
index 55e2efc..f88aa97 100644
--- a/votingapi_widgets.module
+++ b/votingapi_widgets.module
@@ -2,56 +2,48 @@
 
 /**
  * @file
- * Contains votingapi_widgets.module..
+ * Contains votingapi_widgets.module.
  */
 
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Hook\Attribute\LegacyHook;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\votingapi_widgets\Hook\VotingApiWidgetsEntityHooks;
+use Drupal\votingapi_widgets\Hook\VotingApiWidgetsFormHooks;
+use Drupal\votingapi_widgets\Hook\VotingApiWidgetsHelpHooks;
 
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function votingapi_widgets_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    // Main module help for the votingapi_widgets module.
-    case 'help.page.votingapi_widgets':
-      $output = '';
-      $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('Voting API Widgets') . '</p>';
-      return $output;
-
-    default:
-  }
+  return \Drupal::service(VotingApiWidgetsHelpHooks::class)->help($route_name, $route_match);
 }
 
 /**
  * Implements hook_entity_base_field_info().
  */
+#[LegacyHook]
 function votingapi_widgets_entity_base_field_info(EntityTypeInterface $entity_type) {
-  // Add the field_name as a base field.
-  if ($entity_type->id() != 'vote') {
-    return;
-  }
-  $fields = [];
-
-  $fields['field_name'] = BaseFieldDefinition::create('string')
-    ->setLabel(t('Field name'))
-    ->setName('field_name')
-    ->setRevisionable(FALSE)
-    ->setRequired(FALSE)
-    ->setDescription(t('Holds the field name.'))
-    ->setPropertyConstraints('value', ['Length' => ['max' => FieldStorageConfig::NAME_MAX_LENGTH]]);
+  return \Drupal::service(VotingApiWidgetsEntityHooks::class)->entityBaseFieldInfo($entity_type);
+}
 
-  return $fields;
+/**
+ * Implements hook_entity_type_build().
+ */
+#[LegacyHook]
+function votingapi_widgets_entity_type_build(array &$entity_types) {
+  \Drupal::service(VotingApiWidgetsEntityHooks::class)->entityTypeBuild($entity_types);
 }
 
 /**
  * Implements hook_form_FORM_ID_alter() for field_config_edit_form.
  */
+#[LegacyHook]
 function votingapi_widgets_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state) {
   if ($form_state->getFormObject()->getEntity()->bundle() == 'voting_api_field') {
     // We only support posting one comment at the time so it doesn't make sense
@@ -61,16 +53,6 @@ function votingapi_widgets_form_field_config_edit_form_alter(&$form, FormStateIn
   }
 }
 
-/**
- * Implements hook_entity_type_build().
- */
-function votingapi_widgets_entity_type_build(array &$entity_types) {
-  $plugins = \Drupal::service('plugin.manager.voting_api_widget.processor')->getDefinitions();
-  foreach ($plugins as $plugin_id => $definition) {
-    $entity_types['vote']->setFormClass('votingapi_' . $plugin_id, 'Drupal\votingapi_widgets\Form\BaseRatingForm');
-  }
-}
-
 /**
  * Implements hook_theme_suggestions_alter().
  */
diff --git a/votingapi_widgets.services.yml b/votingapi_widgets.services.yml
index 5741534..d38a498 100644
--- a/votingapi_widgets.services.yml
+++ b/votingapi_widgets.services.yml
@@ -1,7 +1,21 @@
 services:
   plugin.manager.voting_api_widget.processor:
-    class: Drupal\votingapi_widgets\Plugin\VotingApiWidgetManager
+    class: \Drupal\votingapi_widgets\Plugin\VotingApiWidgetManager
     parent: default_plugin_manager
+  Drupal\votingapi_widgets\Plugin\VotingApiWidgetManager: '@plugin.manager.voting_api_widget.processor'
+
   voting_api.lazy_loader:
-    class: Drupal\votingapi_widgets\VotingApiLoader
+    class: \Drupal\votingapi_widgets\VotingApiLoader
+    autowire: true
     arguments: ['@plugin.manager.voting_api_widget.processor', '@entity_type.manager']
+  Drupal\votingapi_widgets\VotingApiLoader: '@voting_api.lazy_loader'
+
+  Drupal\votingapi_widgets\Hook\VotingApiWidgetsEntityHooks:
+    class: \Drupal\votingapi_widgets\Hook\VotingApiWidgetsEntityHooks
+    autowire: true
+  Drupal\votingapi_widgets\Hook\VotingApiWidgetsFormHooks:
+    class: \Drupal\votingapi_widgets\Hook\VotingApiWidgetsFormHooks
+    autowire: true
+  Drupal\votingapi_widgets\Hook\VotingApiWidgetsHelpHooks:
+    class: \Drupal\votingapi_widgets\Hook\VotingApiWidgetsHelpHooks
+    autowire: true
-- 
GitLab


From d06cb4a624a0937c1a16ddfec6b9d3e845523885 Mon Sep 17 00:00:00 2001
From: Tim Rohaly <tr@202830.no-reply.drupal.org>
Date: Fri, 14 Feb 2025 01:11:05 -0800
Subject: [PATCH 2/5] missed one

---
 votingapi_widgets.module | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/votingapi_widgets.module b/votingapi_widgets.module
index f88aa97..66cb247 100644
--- a/votingapi_widgets.module
+++ b/votingapi_widgets.module
@@ -45,12 +45,7 @@ function votingapi_widgets_entity_type_build(array &$entity_types) {
  */
 #[LegacyHook]
 function votingapi_widgets_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state) {
-  if ($form_state->getFormObject()->getEntity()->bundle() == 'voting_api_field') {
-    // We only support posting one comment at the time so it doesn't make sense
-    // to let the site builder choose anything else.
-    $form['field_storage']['subform']['cardinality_container']['cardinality']['#default_value'] = 1;
-    $form['field_storage']['subform']['cardinality_container']['#access'] = FALSE;
-  }
+  \Drupal::service(VotingApiWidgetsFormHooks::class)->fieldConfigEditFormAlter($form, $form_state, $form_id);
 }
 
 /**
-- 
GitLab


From b1724721ebcc7794c940246becb5b8fcfdb80d28 Mon Sep 17 00:00:00 2001
From: Tim Rohaly <tr@202830.no-reply.drupal.org>
Date: Fri, 14 Feb 2025 10:36:52 -0800
Subject: [PATCH 3/5] unused use

---
 votingapi_widgets.module | 2 --
 1 file changed, 2 deletions(-)

diff --git a/votingapi_widgets.module b/votingapi_widgets.module
index 66cb247..5c39408 100644
--- a/votingapi_widgets.module
+++ b/votingapi_widgets.module
@@ -6,12 +6,10 @@
  */
 
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Hook\Attribute\LegacyHook;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\field\Entity\FieldConfig;
-use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\votingapi_widgets\Hook\VotingApiWidgetsEntityHooks;
 use Drupal\votingapi_widgets\Hook\VotingApiWidgetsFormHooks;
 use Drupal\votingapi_widgets\Hook\VotingApiWidgetsHelpHooks;
-- 
GitLab


From 2a66859068565238da8de3ea4276744dbf01de30 Mon Sep 17 00:00:00 2001
From: Tim Rohaly <tr@202830.no-reply.drupal.org>
Date: Fri, 14 Feb 2025 14:45:30 -0800
Subject: [PATCH 4/5] remove extra parameter

---
 votingapi_widgets.module | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/votingapi_widgets.module b/votingapi_widgets.module
index 5c39408..83be818 100644
--- a/votingapi_widgets.module
+++ b/votingapi_widgets.module
@@ -43,7 +43,7 @@ function votingapi_widgets_entity_type_build(array &$entity_types) {
  */
 #[LegacyHook]
 function votingapi_widgets_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state) {
-  \Drupal::service(VotingApiWidgetsFormHooks::class)->fieldConfigEditFormAlter($form, $form_state, $form_id);
+  \Drupal::service(VotingApiWidgetsFormHooks::class)->fieldConfigEditFormAlter($form, $form_state);
 }
 
 /**
-- 
GitLab


From f7f3ec8a44a1bb167fa7a86faded8f3b561bbabb Mon Sep 17 00:00:00 2001
From: Tim Rohaly <tr@202830.no-reply.drupal.org>
Date: Sat, 15 Feb 2025 00:36:35 -0800
Subject: [PATCH 5/5] phpcs - comment line length.

---
 src/Hook/VotingApiWidgetsFormHooks.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Hook/VotingApiWidgetsFormHooks.php b/src/Hook/VotingApiWidgetsFormHooks.php
index 4fb7ebe..6d23e8b 100644
--- a/src/Hook/VotingApiWidgetsFormHooks.php
+++ b/src/Hook/VotingApiWidgetsFormHooks.php
@@ -33,8 +33,8 @@ final class VotingApiWidgetsFormHooks {
   #[Hook('form_field_config_edit_form_alter')]
   public function fieldConfigEditFormAlter(array &$form, FormStateInterface $form_state): void {
     if ($form_state->getFormObject()->getEntity()->bundle() == 'voting_api_field') {
-      // We only support posting one comment at the time so it doesn't make sense
-      // to let the site builder choose anything else.
+      // We only support posting one comment at the time so it doesn't make
+      // sense to let the site builder choose anything else.
       $form['field_storage']['subform']['cardinality_container']['cardinality']['#default_value'] = 1;
       $form['field_storage']['subform']['cardinality_container']['#access'] = FALSE;
     }
-- 
GitLab