From ea7102434ba09d893fce998e55d5bb7dde430ca1 Mon Sep 17 00:00:00 2001
From: berramou <azedine.berramou@gmail.com>
Date: Fri, 21 Mar 2025 00:24:06 +0100
Subject: [PATCH 1/6] Issue #3266538: Possibility to configure spam words
 directly in the field

---
 src/Form/BlockwordsConfigurationSettings.php  | 156 ------------------
 .../BlockWordsWebformHandler.php              |  64 ++++++-
 webform_spam_words.info.yml                   |   3 +-
 webform_spam_words.install                    |  47 ++++++
 webform_spam_words.links.menu.yml             |   5 -
 webform_spam_words.routing.yml                |   7 -
 6 files changed, 108 insertions(+), 174 deletions(-)
 delete mode 100644 src/Form/BlockwordsConfigurationSettings.php
 delete mode 100644 webform_spam_words.links.menu.yml
 delete mode 100644 webform_spam_words.routing.yml

diff --git a/src/Form/BlockwordsConfigurationSettings.php b/src/Form/BlockwordsConfigurationSettings.php
deleted file mode 100644
index 73e6261..0000000
--- a/src/Form/BlockwordsConfigurationSettings.php
+++ /dev/null
@@ -1,156 +0,0 @@
-<?php
-
-namespace Drupal\webform_spam_words\Form;
-
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Config\TypedConfigManagerInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Form\ConfigFormBase;
-use Drupal\Core\Form\FormStateInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Returns responses for webform block spam words.
- */
-class BlockwordsConfigurationSettings extends ConfigFormBase {
-
-  /**
-   * Constructs a settings controller.
-   *
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The factory for configuration objects.
-   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager
-   *   The typed config service.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
-   *   The module handler.
-   */
-  public function __construct(
-    ConfigFactoryInterface $config_factory,
-    TypedConfigManagerInterface $typedConfigManager,
-    protected ModuleHandlerInterface $moduleHandler,
-  ) {
-    parent::__construct($config_factory, $typedConfigManager);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('config.factory'),
-      $container->get('config.typed'),
-      $container->get('module_handler')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function getEditableConfigNames() {
-    return ['webform_spam_words.settings'];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-    return 'wsw_settings_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-
-    if ($this->moduleHandler->moduleExists('webform')) {
-
-      // Get values from settings.
-      $spam_words = $this->config('webform_spam_words.settings')->get('spam_words') ? implode(PHP_EOL, $this->config('webform_spam_words.settings')->get('spam_words')) : 'SEO';
-      $spam_text_message = $this->config('webform_spam_words.settings')->get('spam_text_message') ? $this->config('webform_spam_words.settings')->get('spam_text_message') : 'Unable to submit form. Please contact the site administrator, if the problem persists.';
-      $spam_field_name = $this->config('webform_spam_words.settings')->get('spam_field_name') ? $this->config('webform_spam_words.settings')->get('spam_field_name') : 'message';
-
-      // Webform Block Spam Words Configuration.
-      $form['config'] = [
-        '#type' => 'fieldset',
-        '#title' => $this->t('Webform Spam words Configuration'),
-        '#collapsible' => TRUE,
-        '#collapsed' => FALSE,
-      ];
-
-      $form['config']['spam_words'] = [
-        '#type' => 'textarea',
-        '#required' => TRUE,
-        '#title' => $this->t('Webform Spam words'),
-        '#default_value' => $spam_words,
-        '#description' => $this->t('Each Webform spam words should be on a separate line.'),
-      ];
-
-      $form['config']['spam_text_message'] = [
-        '#type' => 'textfield',
-        '#title' => $this->t('Webform Error Message'),
-        '#default_value' => $spam_text_message,
-        '#required' => TRUE,
-        '#description' => $this->t("Please enter your error message, it shows on webform if it's failed. So, the spammers don't know your exact webform error message."),
-      ];
-
-      $form['config']['spam_field_name'] = [
-        '#type' => 'textfield',
-        '#required' => TRUE,
-        '#title' => $this->t('Webform Field name(s)'),
-        '#default_value' => $spam_field_name,
-        '#description' => $this->t('Please enter your webform field(s). If you have more than one field, separate them with commas. For Example: message, email, name'),
-      ];
-
-      // Store the keys we want to save in configuration when form is submitted.
-      $keys_to_save = array_keys($form['config']);
-      foreach ($keys_to_save as $key => $key_to_save) {
-        if (strpos($key_to_save, '#') !== FALSE) {
-          unset($keys_to_save[$key]);
-        }
-      }
-      $form_state->setStorage(['keys' => $keys_to_save]);
-
-      $form['actions']['#type'] = 'container';
-      $form['actions']['submit'] = [
-        '#type' => 'submit',
-        '#value' => $this->t('Save configuration'),
-      ];
-    }
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, FormStateInterface $form_state) {
-
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-    $config = $this->config('webform_spam_words.settings');
-    $storage = $form_state->getStorage();
-
-    // Save configuration items from FormState values.
-    foreach ($form_state->getValues() as $key => $value) {
-      if (in_array($key, $storage['keys'])) {
-        if ($key == 'spam_words') {
-          $config->set($key, explode(PHP_EOL, trim($value)));
-        }
-        else {
-          $config->set($key, $value);
-        }
-      }
-    }
-
-    // Save config settings.
-    $config->save();
-
-    // Message.
-    $this->messenger()->addMessage($this->t('The configuration has been saved.'));
-  }
-
-}
diff --git a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
index 2f62334..b0e376c 100644
--- a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
+++ b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
@@ -31,12 +31,60 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
    */
   public function defaultConfiguration() {
     return [
-      'spam_words' => 'SEO',
+      'spam_words' => [
+        'SEO',
+        'Digital Marketing',
+        'Click Here',
+        'unsubscribe',
+        'FREE',
+        'trial',
+      ],
       'spam_text_message' => $this->t('Unable to submit form. Please contact the site administrator, if the problem persists.'),
       'spam_field_name' => 'message',
     ];
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $form['spam_words'] = [
+      '#type' => 'textarea',
+      '#required' => TRUE,
+      '#title' => $this->t('Webform Spam words'),
+      '#default_value' => implode(PHP_EOL, $this->configuration['spam_words'] ?? []),
+      '#description' => $this->t('Each Webform spam words should be on a separate line.'),
+    ];
+
+    $form['spam_text_message'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Webform Error Message'),
+      '#default_value' => $this->configuration['spam_text_message'],
+      '#required' => TRUE,
+      '#description' => $this->t("Please enter your error message, it shows on webform if it's failed. So, the spammers don't know your exact webform error message."),
+    ];
+
+    $form['spam_field_name'] = [
+      '#type' => 'textfield',
+      '#required' => TRUE,
+      '#title' => $this->t('Webform Field name(s)'),
+      '#default_value' => $this->configuration['spam_field_name'],
+      '#description' => $this->t('Please enter your webform field(s). If you have more than one field, separate them with commas. For Example: message, email, name'),
+    ];
+
+    return $this->setSettingsParents($form);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+    parent::submitConfigurationForm($form, $form_state);
+    $this->configuration['spam_words'] = explode(PHP_EOL, trim($form_state->getValue('spam_words')));
+    $this->configuration['spam_text_message'] = $form_state->getValue('spam_text_message');
+    $this->configuration['spam_field_name'] = $form_state->getValue('spam_field_name');
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -46,7 +94,7 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
     if (is_array($fields)) {
       foreach ($fields as $value) {
         $field = trim($value);
-        $this->validateSpam($form_state, $field, $this->configuration['spam_words'], $this->configuration['spam_text_message']);
+        $this->validateSpam($form_state, $field, $this->configuration['spam_words'] ?? [], $this->configuration['spam_text_message'] ?? "");
       }
     }
 
@@ -54,9 +102,17 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
 
   /**
    * Validate Webform spam words.
+   *
+   * @param \Drupal\Core\Form\FormStateInterface $formState
+   *   Form state object.
+   * @param string $field
+   *   Field to check on if contain spam word.
+   * @param array $spam_words
+   *   List of spam words.
+   * @param string $spam_words_error
+   *   Error message to display.
    */
-  private function validateSpam(FormStateInterface $formState, $field, $spam_words, $spam_words_error) {
-
+  private function validateSpam(FormStateInterface $formState, string $field, array $spam_words, string $spam_words_error): void {
     $spam_error = FALSE;
     $field_value = $formState->getValue($field);
     $field_value = (is_array($field_value) && isset($field_value['value'])) ? $field_value['value'] : $field_value;
diff --git a/webform_spam_words.info.yml b/webform_spam_words.info.yml
index 1079e42..8849328 100644
--- a/webform_spam_words.info.yml
+++ b/webform_spam_words.info.yml
@@ -3,6 +3,5 @@ description: 'Provides the ability to block spam words for webform fields.'
 package: 'Webform'
 type: module
 core_version_requirement: ^10.3 || ^11.0
-configure: webform_spam_words.config
 dependencies:
-  - 'webform:webform'
+  - webform:webform
diff --git a/webform_spam_words.install b/webform_spam_words.install
index 8035da1..233046d 100644
--- a/webform_spam_words.install
+++ b/webform_spam_words.install
@@ -5,6 +5,9 @@
  * Installation hooks for Webform spam words module.
  */
 
+use Drupal\webform\Entity\Webform;
+use Drupal\webform\WebformInterface;
+
 /**
  * Implements hook_install().
  */
@@ -12,3 +15,47 @@ function webform_spam_words_install() {
   // Assign a weight 1 higher than webform module.
   module_set_weight('webform_block_words', 1);
 }
+
+/**
+ * Update WSW handlers configurations from old settings.
+ */
+function webform_spam_words_update_11101(&$sandbox) {
+  // Get values from Webform spam words settings.
+  $wsw_config = \Drupal::configFactory()->getEditable('webform_spam_words.settings');
+  $wsw_settings = $wsw_config->getRawData();
+
+  // Return early if there is no WSW settings yet.
+  if (empty($wsw_settings)) {
+    return;
+  }
+
+  // Load all webforms.
+  $webforms = Webform::loadMultiple();
+
+  foreach ($webforms as $webform) {
+    // Check if the webform is valid.
+    if (!$webform instanceof WebformInterface) {
+      continue;
+    }
+
+    // Get the handlers for the webform.
+    $handlers = $webform->getHandlers();
+    foreach ($handlers as $handler) {
+      if ($handler->getHandlerId() === 'webform_spam_words') {
+        $configuration = $handler->getConfiguration();
+        $configuration['settings']['spam_words'] = $wsw_settings['spam_words'];
+        $configuration['settings']['spam_text_message'] = $wsw_settings['spam_text_message'];
+        $configuration['settings']['spam_field_name'] = $wsw_settings['spam_field_name'];
+        // Save the updated configuration.
+        $handler->setConfiguration($configuration);
+        break;
+      }
+    }
+
+    // Save the webform to persist changes.
+    $webform->save();
+  }
+
+  // Delete old settings.
+  $wsw_config->delete();
+}
diff --git a/webform_spam_words.links.menu.yml b/webform_spam_words.links.menu.yml
deleted file mode 100644
index b0d5f67..0000000
--- a/webform_spam_words.links.menu.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-webform_spam_words.admin:
-  title: 'Webform spam words settings'
-  description: 'Configuration page for webform spam words.'
-  parent: system.admin_config_development
-  route_name: webform_spam_words.config
diff --git a/webform_spam_words.routing.yml b/webform_spam_words.routing.yml
deleted file mode 100644
index 62d75bd..0000000
--- a/webform_spam_words.routing.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-webform_spam_words.config:
-  path: '/admin/config/webform/webform-spam-words'
-  defaults:
-    _form: '\Drupal\webform_spam_words\Form\BlockwordsConfigurationSettings'
-    _title: 'Webform Spam words'
-  requirements:
-    _permission: 'administer webform+edit webform spam words'
-- 
GitLab


From 81a0b2a1ba68b5fd91c3919177d814a09a6ca479 Mon Sep 17 00:00:00 2001
From: berramou <azedine.berramou@gmail.com>
Date: Sat, 22 Mar 2025 00:27:27 +0100
Subject: [PATCH 2/6] Issue #3266538: Add Possibility to configure spam words
 directly in the field

---
 .../install/webform_spam_words.settings.yml   |  9 --
 .../BlockWordsWebformHandler.php              | 96 +++++++++----------
 webform_spam_words.install                    | 10 +-
 3 files changed, 51 insertions(+), 64 deletions(-)
 delete mode 100644 config/install/webform_spam_words.settings.yml

diff --git a/config/install/webform_spam_words.settings.yml b/config/install/webform_spam_words.settings.yml
deleted file mode 100644
index 546686c..0000000
--- a/config/install/webform_spam_words.settings.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-spam_words:
-  - SEO
-  - 'Digital Marketing'
-  - 'Click Here'
-  - unsubscribe
-  - FREE
-  - trial
-spam_text_message: 'Unable to submit form. Please contact the site administrator, if the problem persists.'
-spam_field_name: message
diff --git a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
index b0e376c..847a159 100644
--- a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
+++ b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
@@ -26,78 +26,80 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
 
   use StringTranslationTrait;
 
+  /**
+   * Allowed Webform fields types that support Spam words.
+   */
+  const ALLOWED_WSW_FIELDS = ['textfield', 'textarea', 'text_format'];
+
   /**
    * {@inheritdoc}
    */
-  public function defaultConfiguration() {
+  public function defaultConfiguration(): array {
     return [
       'spam_words' => [
-        'SEO',
-        'Digital Marketing',
-        'Click Here',
-        'unsubscribe',
-        'FREE',
-        'trial',
+        'message' => [
+          'SEO',
+          'Digital Marketing',
+          'Click Here',
+          'unsubscribe',
+          'FREE',
+          'trial111',
+        ],
       ],
       'spam_text_message' => $this->t('Unable to submit form. Please contact the site administrator, if the problem persists.'),
-      'spam_field_name' => 'message',
     ];
   }
 
   /**
    * {@inheritdoc}
    */
-  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
-    $form['spam_words'] = [
-      '#type' => 'textarea',
-      '#required' => TRUE,
-      '#title' => $this->t('Webform Spam words'),
-      '#default_value' => implode(PHP_EOL, $this->configuration['spam_words'] ?? []),
-      '#description' => $this->t('Each Webform spam words should be on a separate line.'),
-    ];
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
+    $webform = $this->getWebform();
+    $elements = $webform->getElementsDecodedAndFlattened();
+    $text_fields = array_filter($elements, function ($element) {
+      return in_array($element['#type'], self::ALLOWED_WSW_FIELDS);
+    });
+
+    foreach ($text_fields as $name => $text_field) {
+      $form['spam_words'][$name] = [
+        '#type' => 'textarea',
+        '#required' => FALSE,
+        '#title' => $this->t('Webform Spam words for "%name" field', ['%name' => $text_field['#title']]),
+        '#default_value' => implode(PHP_EOL, $this->configuration['spam_words'][$name] ?? []),
+        '#description' => $this->t('Each Webform spam words should be on a separate line.'),
+      ];
+    }
 
     $form['spam_text_message'] = [
       '#type' => 'textfield',
-      '#title' => $this->t('Webform Error Message'),
+      '#title' => $this->t('Error Message for Spam Detection'),
       '#default_value' => $this->configuration['spam_text_message'],
       '#required' => TRUE,
       '#description' => $this->t("Please enter your error message, it shows on webform if it's failed. So, the spammers don't know your exact webform error message."),
     ];
 
-    $form['spam_field_name'] = [
-      '#type' => 'textfield',
-      '#required' => TRUE,
-      '#title' => $this->t('Webform Field name(s)'),
-      '#default_value' => $this->configuration['spam_field_name'],
-      '#description' => $this->t('Please enter your webform field(s). If you have more than one field, separate them with commas. For Example: message, email, name'),
-    ];
-
     return $this->setSettingsParents($form);
   }
 
   /**
    * {@inheritdoc}
    */
-  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
     parent::submitConfigurationForm($form, $form_state);
-    $this->configuration['spam_words'] = explode(PHP_EOL, trim($form_state->getValue('spam_words')));
+    foreach ($form_state->getValue('spam_words') as $field => $spam_words) {
+      $this->configuration['spam_words'][$field] = explode(PHP_EOL, trim($spam_words));
+    }
     $this->configuration['spam_text_message'] = $form_state->getValue('spam_text_message');
-    $this->configuration['spam_field_name'] = $form_state->getValue('spam_field_name');
   }
 
   /**
    * {@inheritdoc}
    */
-  public function validateForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
-
-    $fields = explode(',', trim($this->configuration['spam_field_name']));
-    if (is_array($fields)) {
-      foreach ($fields as $value) {
-        $field = trim($value);
-        $this->validateSpam($form_state, $field, $this->configuration['spam_words'] ?? [], $this->configuration['spam_text_message'] ?? "");
-      }
+  public function validateForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission): void {
+    $spam_words = $this->configuration['spam_words'] ?? [];
+    foreach ($spam_words as $field => $words) {
+      $this->validateSpam($form_state, $field, $words ?? [], $this->configuration['spam_text_message'] ?? "");
     }
-
   }
 
   /**
@@ -112,11 +114,9 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
    * @param string $spam_words_error
    *   Error message to display.
    */
-  private function validateSpam(FormStateInterface $formState, string $field, array $spam_words, string $spam_words_error): void {
-    $spam_error = FALSE;
+  private function validateSpam(FormStateInterface &$formState, string $field, array $spam_words, string $spam_words_error): void {
     $field_value = $formState->getValue($field);
-    $field_value = (is_array($field_value) && isset($field_value['value'])) ? $field_value['value'] : $field_value;
-    $value = (!empty($field_value) && !is_array($field_value)) ? Html::escape(mb_strtolower($field_value)) : NULL;
+    $value = is_array($field_value) ? ($field_value['value'] ?? NULL) : Html::escape(mb_strtolower($field_value));
 
     // Skip empty unique fields or arrays.
     if (empty($value) || is_array($value)) {
@@ -127,19 +127,13 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
     $value = preg_replace('/\s+/', ' ', $value);
 
     foreach ($spam_words as $word) {
+      if (empty($word)) {
+        continue;
+      }
       if (strpos($value, mb_strtolower(trim($word))) !== FALSE) {
-        $spam_error = TRUE;
+        $formState->setErrorByName($field, $this->t('@spam_words_error', ['@spam_words_error' => $spam_words_error]));
       }
     }
-
-    // Show web form error.
-    if ($spam_error) {
-      $formState->setErrorByName($field, $this->t('@spam_words_error', ['@spam_words_error' => $spam_words_error]));
-    }
-    else {
-      $formState->setValue($field, $formState->getValue($field));
-    }
-
   }
 
 }
diff --git a/webform_spam_words.install b/webform_spam_words.install
index 233046d..bb640d0 100644
--- a/webform_spam_words.install
+++ b/webform_spam_words.install
@@ -19,9 +19,10 @@ function webform_spam_words_install() {
 /**
  * Update WSW handlers configurations from old settings.
  */
-function webform_spam_words_update_11101(&$sandbox) {
+function webform_spam_words_update_11106(&$sandbox) {
   // Get values from Webform spam words settings.
-  $wsw_config = \Drupal::configFactory()->getEditable('webform_spam_words.settings');
+  $wsw_config = \Drupal::configFactory()
+    ->getEditable('webform_spam_words.settings');
   $wsw_settings = $wsw_config->getRawData();
 
   // Return early if there is no WSW settings yet.
@@ -43,9 +44,10 @@ function webform_spam_words_update_11101(&$sandbox) {
     foreach ($handlers as $handler) {
       if ($handler->getHandlerId() === 'webform_spam_words') {
         $configuration = $handler->getConfiguration();
-        $configuration['settings']['spam_words'] = $wsw_settings['spam_words'];
+        foreach ($wsw_settings['spam_field_name'] as $field_name => $spam_field_name) {
+          $configuration['settings']['spam_words'][$field_name] = $wsw_settings['spam_words'];
+        }
         $configuration['settings']['spam_text_message'] = $wsw_settings['spam_text_message'];
-        $configuration['settings']['spam_field_name'] = $wsw_settings['spam_field_name'];
         // Save the updated configuration.
         $handler->setConfiguration($configuration);
         break;
-- 
GitLab


From 1f6f1c68f876d60634c5cc86263f9182fb89804c Mon Sep 17 00:00:00 2001
From: berramou <azedine.berramou@gmail.com>
Date: Sat, 22 Mar 2025 00:37:16 +0100
Subject: [PATCH 3/6] Fix some wording

---
 src/Plugin/WebformHandler/BlockWordsWebformHandler.php | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
index 847a159..f42bd7a 100644
--- a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
+++ b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
@@ -5,7 +5,6 @@ namespace Drupal\webform_spam_words\Plugin\WebformHandler;
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\webform\Annotation\WebformHandler;
 use Drupal\webform\Plugin\WebformHandlerBase;
 use Drupal\webform\WebformSubmissionInterface;
 
@@ -43,7 +42,7 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
           'Click Here',
           'unsubscribe',
           'FREE',
-          'trial111',
+          'trial',
         ],
       ],
       'spam_text_message' => $this->t('Unable to submit form. Please contact the site administrator, if the problem persists.'),
@@ -64,15 +63,15 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
       $form['spam_words'][$name] = [
         '#type' => 'textarea',
         '#required' => FALSE,
-        '#title' => $this->t('Webform Spam words for "%name" field', ['%name' => $text_field['#title']]),
+        '#title' => $this->t('Spam words for "%name" field', ['%name' => $text_field['#title']]),
         '#default_value' => implode(PHP_EOL, $this->configuration['spam_words'][$name] ?? []),
-        '#description' => $this->t('Each Webform spam words should be on a separate line.'),
+        '#description' => $this->t('Each spam words should be on a separate line.'),
       ];
     }
 
     $form['spam_text_message'] = [
       '#type' => 'textfield',
-      '#title' => $this->t('Error Message for Spam Detection'),
+      '#title' => $this->t('Error message for spam detection'),
       '#default_value' => $this->configuration['spam_text_message'],
       '#required' => TRUE,
       '#description' => $this->t("Please enter your error message, it shows on webform if it's failed. So, the spammers don't know your exact webform error message."),
-- 
GitLab


From fd4160fe55c3c69ba2c962b01033accd42482eee Mon Sep 17 00:00:00 2001
From: berramou <azedine.berramou@gmail.com>
Date: Sat, 22 Mar 2025 00:43:25 +0100
Subject: [PATCH 4/6] Add some comments

---
 src/Plugin/WebformHandler/BlockWordsWebformHandler.php | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
index f42bd7a..fea8bc5 100644
--- a/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
+++ b/src/Plugin/WebformHandler/BlockWordsWebformHandler.php
@@ -54,11 +54,14 @@ class BlockWordsWebformHandler extends WebformHandlerBase {
    */
   public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
     $webform = $this->getWebform();
+    // Get webform elements.
     $elements = $webform->getElementsDecodedAndFlattened();
+    // Filter elements to get only the allowed field types.
     $text_fields = array_filter($elements, function ($element) {
       return in_array($element['#type'], self::ALLOWED_WSW_FIELDS);
     });
 
+    // Iterate over the allowed fields and add spam words configuration.
     foreach ($text_fields as $name => $text_field) {
       $form['spam_words'][$name] = [
         '#type' => 'textarea',
-- 
GitLab


From b2379995dabe48afb37da05e6a8c1773521be347 Mon Sep 17 00:00:00 2001
From: berramou <azedine.berramou@gmail.com>
Date: Sat, 22 Mar 2025 01:07:23 +0100
Subject: [PATCH 5/6] Adapt hook update for new config structure

---
 webform_spam_words.install | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/webform_spam_words.install b/webform_spam_words.install
index bb640d0..a98646e 100644
--- a/webform_spam_words.install
+++ b/webform_spam_words.install
@@ -19,7 +19,7 @@ function webform_spam_words_install() {
 /**
  * Update WSW handlers configurations from old settings.
  */
-function webform_spam_words_update_11106(&$sandbox) {
+function webform_spam_words_update_11101(&$sandbox) {
   // Get values from Webform spam words settings.
   $wsw_config = \Drupal::configFactory()
     ->getEditable('webform_spam_words.settings');
@@ -43,8 +43,8 @@ function webform_spam_words_update_11106(&$sandbox) {
     $handlers = $webform->getHandlers();
     foreach ($handlers as $handler) {
       if ($handler->getHandlerId() === 'webform_spam_words') {
-        $configuration = $handler->getConfiguration();
-        foreach ($wsw_settings['spam_field_name'] as $field_name => $spam_field_name) {
+        $field_names = explode(',', trim($wsw_settings['spam_field_name'] ?? ""));
+        foreach ($field_names as $field_name) {
           $configuration['settings']['spam_words'][$field_name] = $wsw_settings['spam_words'];
         }
         $configuration['settings']['spam_text_message'] = $wsw_settings['spam_text_message'];
@@ -54,8 +54,14 @@ function webform_spam_words_update_11106(&$sandbox) {
       }
     }
 
-    // Save the webform to persist changes.
-    $webform->save();
+    try {
+      // Save the webform to persist changes.
+      $webform->save();
+    }
+    catch (\Exception $e) {
+      // Log the error.
+      \Drupal::logger('webform_spam_words')->error($e->getMessage());
+    }
   }
 
   // Delete old settings.
-- 
GitLab


From 7d03008c70de9e8b3f537968cf0af62ec9e27596 Mon Sep 17 00:00:00 2001
From: berramou <azedine.berramou@gmail.com>
Date: Thu, 27 Mar 2025 01:34:22 +0100
Subject: [PATCH 6/6] Add Schema file for the handler

---
 config/schema/webform_spam_words.schema.yml | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 config/schema/webform_spam_words.schema.yml

diff --git a/config/schema/webform_spam_words.schema.yml b/config/schema/webform_spam_words.schema.yml
new file mode 100644
index 0000000..a2bc945
--- /dev/null
+++ b/config/schema/webform_spam_words.schema.yml
@@ -0,0 +1,17 @@
+webform.handler.webform_spam_words:
+  type: mapping
+  label: 'Webform Spam Words'
+  mapping:
+    spam_words:
+      type: mapping
+      label: 'Spam words by field'
+      mapping:
+        message:
+          type: sequence
+          label: 'Spam words for message field'
+          sequence:
+            type: string
+            label: 'Spam word'
+    spam_text_message:
+      type: string
+      label: 'Error message for spam detection'
-- 
GitLab