From 5188d5feb076406d976209bace0d8e1ef1065f01 Mon Sep 17 00:00:00 2001
From: James Wilson <jrwilson3@gmail.com>
Date: Mon, 23 Dec 2024 08:14:47 -0500
Subject: [PATCH 1/3] Issue #3495516 by jwilson3: Add Label Help support for
 Title field

---
 README.md                                     | 28 +++-----
 label_help.module                             | 34 ++++++++--
 .../label_help_test/label_help_test.module    | 64 +++++++++++++++++++
 3 files changed, 101 insertions(+), 25 deletions(-)

diff --git a/README.md b/README.md
index e3a8e35..c6449a9 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,7 @@ This module requires no modules outside of Drupal core.
     this dump runs inside the form_alter, it can result in incomplete page
     load. This is expected.
 
+
 ## Using Label Help to create form fields programmatically
 
 The Label Help field defines a theme option named 'description at top' which
@@ -63,9 +64,7 @@ function my_module_form($form, &$form_state) {
   $form['example'] = [
     '#type' => 'textfield',
     '#title' => t('Example'),
-    '#theme_options' => [
-      'description at top' => t('Label help text for the example field.'),
-    ],
+    '#label_help' => t('Label help text for the example field.'),
   ];
   return $form;
 }
@@ -73,28 +72,17 @@ function my_module_form($form, &$form_state) {
 
 ## Modifying form fields using hook_form_alter()
 
-Drupal's hook_form_alter() functions may be used in a custom module or theme
-to add Label Help text to existing form fields. For example, the following
-function uses hook_form_user_login_alter() to change Drupal's user login form
-so that it displays label text top of field 'example':
+Drupal's hook_form_alter() and hook_FORM_ID_alter() functions may be used
+in a custom module or theme to add Label Help text to existing form fields.
+The following example adds help text to the Article content type's Title field.
 
 ```php
-function my_module_form_user_login_alter(&$form, &$form_state, $form_id) {
-  $form['name']['#theme_options'] = [
-    'description at top' => t('Enter your @s username.', [
-      '@s' => variable_get('site_name', 'Drupal')
-    ]),
-  ];
-  unset($form['name']['#description']);
-  $form['pass']['#theme_options'] = [
-    'description at top' => t(
-      'Enter the password that accompanies your username.'
-    ),
-  ];
-  unset($form['pass']['#description']);
+function my_module_form_node_article_alter(&$form, &$form_state, $form_id) {
+  $form['title']['#label_help'] = t('Label help message for the Title field.');
 }
 ```
 
+
 ## Contributing
 
 Local development is done via DDEV and the `ddev-drupal-contrib` add-on.
diff --git a/label_help.module b/label_help.module
index 1ec1bb6..87514f2 100644
--- a/label_help.module
+++ b/label_help.module
@@ -47,23 +47,30 @@ function label_help_theme() {
  * Implements hook_form_alter().
  */
 function label_help_form_alter(&$form, &$form_state, $form_id) {
+  $form['#process'][] = 'label_help_process_form';
+}
+
+/**
+ * Custom process callback for modifying form elements with Label Help.
+ */
+function label_help_process_form($element, FormStateInterface $form_state, &$form) {
   $children = array_intersect_key($form, array_flip(Element::children($form)));
   $form_object = $form_state->getFormObject();
   if (!method_exists($form_object, 'getEntity')) {
-    return;
+    return $element;
   }
   $method = new ReflectionMethod($form_object, 'getEntity');
   if (!$method->isPublic()) {
-    return;
+    return $element;
   }
 
   $form_entity = $form_object->getEntity();
   if (!method_exists($form_entity, 'getFieldDefinition')) {
-    return;
+    return $element;
   }
   $method = new ReflectionMethod($form_entity, 'getFieldDefinition');
   if (!$method->isPublic()) {
-    return;
+    return $element;
   }
 
   $debug = Settings::get('label_help_debug', FALSE);
@@ -75,9 +82,16 @@ function label_help_form_alter(&$form, &$form_state, $form_id) {
 
     $content = NULL;
     $fallback_use_case = FALSE;
+
+    // There are two possible ways to add text content for Label Help:
+    // Option 1) via the Field UI module in the Drupal web interface.
     if ($field && method_exists($field, 'getThirdPartySetting')) {
       $content = $field->getThirdPartySetting('label_help', 'label_help_description');
     }
+    // Option 2) via code, using a custom #label_help Form API property.
+    if (!empty($item['#label_help'])) {
+      $content = $item['#label_help'];
+    }
     if (is_null($content) || strlen($content) === 0) {
       continue;
     }
@@ -260,8 +274,16 @@ function label_help_form_alter(&$form, &$form_state, $form_id) {
         $fallback_use_case = TRUE;
       }
     }
-    else {
+
+    // Custom fields may not be defined with a container or a widget wrapper.
+    // To keep things simple, place the label in the field prefix.
+    elseif (isset($item['#type']) && empty($item['widget'])) {
       $use_case = 16;
+      $element = &$form[$key];
+      _label_help_append_label_suffix($element, $content, $use_case);
+    }
+    else {
+      $use_case = 17;
       $fallback_use_case = TRUE;
     }
 
@@ -291,6 +313,8 @@ function label_help_form_alter(&$form, &$form_state, $form_id) {
       dump($item);
     }
   }
+
+  return $form;
 }
 
 /**
diff --git a/modules/label_help_test/label_help_test.module b/modules/label_help_test/label_help_test.module
index b1a11f5..274dfa9 100644
--- a/modules/label_help_test/label_help_test.module
+++ b/modules/label_help_test/label_help_test.module
@@ -4,3 +4,67 @@
  * @file
  * Primary module hooks for Label Help Test module.
  */
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Adds label help text to the core Article node form title field.
+ */
+function label_help_test_form_node_article_form_alter(&$form, &$form_state, $form_id) {
+  $form['title']['#label_help'] = t('Label help message for the Title field.');
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Adds label help text to the user login form fields and removes their
+ * descriptions.
+ */
+function label_help_test_form_user_login_form_alter(&$form, &$form_state, $form_id) {
+  $form['name']['#label_help'] = t('Enter your @s username.', [
+    '@s' => \Drupal::config('system.site')->get('name') ?? 'Drupal',
+  ]);
+  unset($form['name']['#description']);
+  $form['pass']['#label_help'] = t(
+    'Enter the password that accompanies your username.'
+  );
+  unset($form['pass']['#description']);
+}
+
+/**
+ * Implements hook_form_alter().
+ *
+ * Adds label help text to fields in our Test content type form.
+ *
+ * This hook implementation targets the test_label_help_core_fields content type
+ * forms and adds label help text to the core title field and custom fields
+ * (textfield and checkbox).
+ */
+function label_help_test_form_alter(&$form, &$form_state, $form_id) {
+  // Only affect the specified content type's add/edit forms.
+  if (!in_array($form_id, [
+    'node_test_label_help_core_fields_form',
+    'node_test_label_help_core_fields_edit_form',
+  ])) {
+    return;
+  }
+
+  // Add Label Help text to the Node Title field.
+  if (isset($form['title'])) {
+    $form['title']['#label_help'] = t('Label help message for the Title field.');
+  }
+
+  // Create a custom text field with Label Help text.
+  $form['field_lh_textfield'] = [
+    '#type' => 'textfield',
+    '#title' => t('Custom text field'),
+    '#label_help' => t('Label help message for the Custom text field.'),
+  ];
+
+  // Create a custom checkbox field with Label Help text.
+  $form['field_lh_checkbox'] = [
+    '#type' => 'checkbox',
+    '#title' => t('Custom checkbox field'),
+    '#label_help' => t('Label help message for the Custom checkbox field.'),
+  ];
+}
-- 
GitLab


From 2b4d424a695703b7426087e06c69bf932fca88ef Mon Sep 17 00:00:00 2001
From: James Wilson <jrwilson3@gmail.com>
Date: Mon, 23 Dec 2024 14:32:42 -0500
Subject: [PATCH 2/3] Allow #label_help on non-entity forms

---
 label_help.module | 51 +++++++++++++++++++++++------------------------
 1 file changed, 25 insertions(+), 26 deletions(-)

diff --git a/label_help.module b/label_help.module
index 87514f2..9027abb 100644
--- a/label_help.module
+++ b/label_help.module
@@ -54,44 +54,43 @@ function label_help_form_alter(&$form, &$form_state, $form_id) {
  * Custom process callback for modifying form elements with Label Help.
  */
 function label_help_process_form($element, FormStateInterface $form_state, &$form) {
-  $children = array_intersect_key($form, array_flip(Element::children($form)));
-  $form_object = $form_state->getFormObject();
-  if (!method_exists($form_object, 'getEntity')) {
-    return $element;
-  }
-  $method = new ReflectionMethod($form_object, 'getEntity');
-  if (!$method->isPublic()) {
-    return $element;
-  }
-
-  $form_entity = $form_object->getEntity();
-  if (!method_exists($form_entity, 'getFieldDefinition')) {
-    return $element;
-  }
-  $method = new ReflectionMethod($form_entity, 'getFieldDefinition');
-  if (!$method->isPublic()) {
-    return $element;
-  }
-
   $debug = Settings::get('label_help_debug', FALSE);
   $debug_dump = Settings::get('label_help_debug_dump', FALSE);
   $one_time_debug_warning = &drupal_static(__FUNCTION__);
+  $children = array_intersect_key($form, array_flip(Element::children($form)));
   foreach ($children as $key => $item) {
     $use_case = 0;
-    $field = $form_object->getEntity()->getFieldDefinition($key);
-
     $content = NULL;
     $fallback_use_case = FALSE;
 
     // There are two possible ways to add text content for Label Help:
-    // Option 1) via the Field UI module in the Drupal web interface.
-    if ($field && method_exists($field, 'getThirdPartySetting')) {
-      $content = $field->getThirdPartySetting('label_help', 'label_help_description');
-    }
-    // Option 2) via code, using a custom #label_help Form API property.
+    // Option 1) via code, using a custom #label_help Form API property.
     if (!empty($item['#label_help'])) {
       $content = $item['#label_help'];
     }
+    // Option 2) via the Field UI module in the Drupal web interface.
+    else {
+      $form_object = $form_state->getFormObject();
+      if (!method_exists($form_object, 'getEntity')) {
+        return $element;
+      }
+      $method = new ReflectionMethod($form_object, 'getEntity');
+      if (!$method->isPublic()) {
+        return $element;
+      }
+      $form_entity = $form_object->getEntity();
+      if (!method_exists($form_entity, 'getFieldDefinition')) {
+        return $element;
+      }
+      $method = new ReflectionMethod($form_entity, 'getFieldDefinition');
+      if (!$method->isPublic()) {
+        return $element;
+      }
+      $field = $form_entity->getFieldDefinition($key);
+      if ($field && method_exists($field, 'getThirdPartySetting')) {
+        $content = $field->getThirdPartySetting('label_help', 'label_help_description');
+      }
+    }
     if (is_null($content) || strlen($content) === 0) {
       continue;
     }
-- 
GitLab


From 2d2326fd90c2e17ba95dfc92ff79e69aa8492a90 Mon Sep 17 00:00:00 2001
From: James Wilson <jrwilson3@gmail.com>
Date: Mon, 23 Dec 2024 14:35:44 -0500
Subject: [PATCH 3/3] Remove login form example

---
 modules/label_help_test/label_help_test.module | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/modules/label_help_test/label_help_test.module b/modules/label_help_test/label_help_test.module
index 274dfa9..046d0ea 100644
--- a/modules/label_help_test/label_help_test.module
+++ b/modules/label_help_test/label_help_test.module
@@ -14,23 +14,6 @@ function label_help_test_form_node_article_form_alter(&$form, &$form_state, $for
   $form['title']['#label_help'] = t('Label help message for the Title field.');
 }
 
-/**
- * Implements hook_form_FORM_ID_alter().
- *
- * Adds label help text to the user login form fields and removes their
- * descriptions.
- */
-function label_help_test_form_user_login_form_alter(&$form, &$form_state, $form_id) {
-  $form['name']['#label_help'] = t('Enter your @s username.', [
-    '@s' => \Drupal::config('system.site')->get('name') ?? 'Drupal',
-  ]);
-  unset($form['name']['#description']);
-  $form['pass']['#label_help'] = t(
-    'Enter the password that accompanies your username.'
-  );
-  unset($form['pass']['#description']);
-}
-
 /**
  * Implements hook_form_alter().
  *
-- 
GitLab