From 7d6cc69dbc96b9dda732ba602e97f9d5a13ca509 Mon Sep 17 00:00:00 2001
From: "yves.fierville" <yves.fierville@kleegroup.com>
Date: Wed, 18 Oct 2023 15:34:46 +0200
Subject: [PATCH 1/8] Add format check on topic value

---
 src/Form/SettingsForm.php | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php
index 4d128e8..d342be2 100644
--- a/src/Form/SettingsForm.php
+++ b/src/Form/SettingsForm.php
@@ -105,12 +105,14 @@ class SettingsForm extends ConfigFormBase {
       '#type' => 'textfield',
       '#title' => $this->t('Topic'),
       '#description' => $this->t(
-        'Topics are strings that can be used to replace a pending messages with a new message
+        'The string must contain only alphanumeric characters.
+        Topics are strings that can be used to replace a pending messages with a new message
         if they have matching topic names. This is useful in scenarios where multiple messages
         are sent while a device is offline, and you really only want a user to see the latest
         message when the device is turned on.'
       ),
       '#maxlength' => 32,
+      '#pattern' => '[a-zA-Z0-9]+',
       '#default_value' => $config->get('topic') ?: '',
     ];
     $form['options']['batchSize'] = [
-- 
GitLab


From 53d5dc2f4f2a9575a281d0d95dc256951677526d Mon Sep 17 00:00:00 2001
From: "yves.fierville" <yves.fierville@kleegroup.com>
Date: Wed, 18 Oct 2023 16:47:28 +0200
Subject: [PATCH 2/8] Add topic management on notification send

---
 src/Service/WebPushManager.php | 14 ++++++--------
 src/Service/WebPushSender.php  | 10 ++++++----
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/Service/WebPushManager.php b/src/Service/WebPushManager.php
index 1b8005b..aca75f4 100644
--- a/src/Service/WebPushManager.php
+++ b/src/Service/WebPushManager.php
@@ -54,9 +54,6 @@ class WebPushManager {
     $this->queueWorkerManager = $queue_worker_manager;
   }
 
-  /**
-   * {@inheritdoc}
-   */
   /**
    * Send the notification to the queue.
    *
@@ -70,20 +67,20 @@ class WebPushManager {
    *   The icon url of the notification.
    * @param string $urgency
    *   The urgency of the notification.
+   * @param string $topic
+   *   The topic of the notification.
    */
   public function sendNotification(
     string $title,
     string $body,
     string $url = '',
     string $icon = '',
-    string $urgency = ''
+    string $urgency = '',
+    string $topic = ''
   ): void {
     if (empty($url)) {
       $url = Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString();
     }
-    if (empty($icon)) {
-      // TODO get default icon.
-    }
     $pushData = [
       'content' => [
         'title' => $title,
@@ -92,7 +89,8 @@ class WebPushManager {
         'url' => $url
       ],
       'options' => [
-        'urgency' => $urgency
+        'urgency' => $urgency,
+        'topic' => $topic,
       ],
     ];
 
diff --git a/src/Service/WebPushSender.php b/src/Service/WebPushSender.php
index 660dcae..f66505c 100644
--- a/src/Service/WebPushSender.php
+++ b/src/Service/WebPushSender.php
@@ -154,15 +154,17 @@ class WebPushSender {
    *
    * @param array $pushData
    *   The data content.
-   * @param string $urgency
+   * @param array $optionsCustom
    *   The notification urgency.
    */
-  protected function prepareSubscriptions(array $pushData, string $urgency = ''): void {
+  protected function prepareSubscriptions(array $pushData, array $optionsCustom = []): void {
     $listSubscriptions = $this->entityStorage->loadMultiple();
     foreach ($listSubscriptions as $subscription) {
       $webSubscription = $this->buildSubscription($subscription, $pushData);
       $options = $this->webPush->getDefaultOptions();
-      $options['urgency'] = $urgency ? $urgency : $options['urgency'];
+
+      $options['urgency'] = array_key_exists('urgency', $optionsCustom) ? $optionsCustom['urgency'] : $options['urgency'];
+      $options['topic'] = array_key_exists('topic', $optionsCustom) ? $optionsCustom['topic'] : $options['topic'];
       try {
         $this->webPush->queueNotification(
           $webSubscription['subscription'],
@@ -209,7 +211,7 @@ class WebPushSender {
    */
   public function sendNotification(array $pushData): void {
     $this->singletonWebPush();
-    $this->prepareSubscriptions($pushData['content'], $pushData['options']['urgency']);
+    $this->prepareSubscriptions($pushData['content'], $pushData['options']);
 
     // Send the queued items by prepareSubscriptions().
     // And check message for each notifications.
-- 
GitLab


From c146ccd5919874a76676be0b5d2ea3944c0d4ea5 Mon Sep 17 00:00:00 2001
From: "yves.fierville" <yves.fierville@kleegroup.com>
Date: Wed, 18 Oct 2023 16:56:27 +0200
Subject: [PATCH 3/8] Update readme

---
 README.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index f6592d0..5fe9443 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,8 @@ Security optimization:
     'Notification Body',
     'noticiation-redirect-url',
     'notification-icon-url',
-    \Drupal\web_push\Service\WebPushSender::URGENCY_HIGH
+    \Drupal\web_push\Service\WebPushSender::URGENCY_HIGH,
+    'myTopic' // Only alphanumeric character, limited to 32 characters.
   );
 ```
 
-- 
GitLab


From 2caa6c900c4ca3623b9c4cd80acddaa1d0760879 Mon Sep 17 00:00:00 2001
From: Yves Fierville <63185-yfiervil@users.noreply.drupalcode.org>
Date: Tue, 24 Oct 2023 12:49:30 +0000
Subject: [PATCH 4/8] Fix empty string

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

diff --git a/src/Service/WebPushSender.php b/src/Service/WebPushSender.php
index f66505c..5d8d8d0 100644
--- a/src/Service/WebPushSender.php
+++ b/src/Service/WebPushSender.php
@@ -163,8 +163,8 @@ class WebPushSender {
       $webSubscription = $this->buildSubscription($subscription, $pushData);
       $options = $this->webPush->getDefaultOptions();
 
-      $options['urgency'] = array_key_exists('urgency', $optionsCustom) ? $optionsCustom['urgency'] : $options['urgency'];
-      $options['topic'] = array_key_exists('topic', $optionsCustom) ? $optionsCustom['topic'] : $options['topic'];
+      $options['urgency'] = array_key_exists('urgency', $optionsCustom) && $optionsCustom['urgency'] ? $optionsCustom['urgency'] : $options['urgency'];
+      $options['topic'] = array_key_exists('topic', $optionsCustom) && $optionsCustom['topic'] ? $optionsCustom['topic'] : $options['topic'];
       try {
         $this->webPush->queueNotification(
           $webSubscription['subscription'],
-- 
GitLab


From 24811a8dbbe383b2c0efad0e6f20c16516de0efd Mon Sep 17 00:00:00 2001
From: Yves Fierville <63185-yfiervil@users.noreply.drupalcode.org>
Date: Fri, 15 Dec 2023 13:58:45 +0000
Subject: [PATCH 5/8] 3408712 - Feature - The ability to pass subscription IDs

---
 README.md                      | 6 ++++--
 src/Service/WebPushManager.php | 7 ++++++-
 src/Service/WebPushSender.php  | 7 ++++---
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 5fe9443..e30109d 100644
--- a/README.md
+++ b/README.md
@@ -42,13 +42,15 @@ Security optimization:
 
 ## Example
 ```
- \Drupal::service('web_push.manager')->sendNotification(
+  $subscriptionIds = [1, 2, 3]; // There can be any logic for obtaining subscription IDs.
+  \Drupal::service('web_push.manager')->sendNotification(
     'Notification Title',
     'Notification Body',
     'noticiation-redirect-url',
     'notification-icon-url',
     \Drupal\web_push\Service\WebPushSender::URGENCY_HIGH,
-    'myTopic' // Only alphanumeric character, limited to 32 characters.
+    'myTopic', // Only alphanumeric character, limited to 32 characters.
+    $subscriptionIds // Can be Null to send to every subscription.
   );
 ```
 
diff --git a/src/Service/WebPushManager.php b/src/Service/WebPushManager.php
index aca75f4..640a376 100644
--- a/src/Service/WebPushManager.php
+++ b/src/Service/WebPushManager.php
@@ -69,6 +69,9 @@ class WebPushManager {
    *   The urgency of the notification.
    * @param string $topic
    *   The topic of the notification.
+   * @param array|null $subscriptionIds
+   *   The subscriptions ids or NULL for all.
+   *
    */
   public function sendNotification(
     string $title,
@@ -76,7 +79,8 @@ class WebPushManager {
     string $url = '',
     string $icon = '',
     string $urgency = '',
-    string $topic = ''
+    string $topic = '',
+    ?array $subscriptionIds = NULL
   ): void {
     if (empty($url)) {
       $url = Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString();
@@ -92,6 +96,7 @@ class WebPushManager {
         'urgency' => $urgency,
         'topic' => $topic,
       ],
+      'subscriptionIds' => $subscriptionIds
     ];
 
     $worker = $this->queueWorkerManager->createInstance('web_push');
diff --git a/src/Service/WebPushSender.php b/src/Service/WebPushSender.php
index 5d8d8d0..fc2a44a 100644
--- a/src/Service/WebPushSender.php
+++ b/src/Service/WebPushSender.php
@@ -156,9 +156,10 @@ class WebPushSender {
    *   The data content.
    * @param array $optionsCustom
    *   The notification urgency.
+   * @param array|null $subscriptionIds
    */
-  protected function prepareSubscriptions(array $pushData, array $optionsCustom = []): void {
-    $listSubscriptions = $this->entityStorage->loadMultiple();
+  protected function prepareSubscriptions(array $pushData, array $optionsCustom = [], ?array $subscriptionIds = NULL): void {
+    $listSubscriptions = $this->entityStorage->loadMultiple($subscriptionIds);
     foreach ($listSubscriptions as $subscription) {
       $webSubscription = $this->buildSubscription($subscription, $pushData);
       $options = $this->webPush->getDefaultOptions();
@@ -211,7 +212,7 @@ class WebPushSender {
    */
   public function sendNotification(array $pushData): void {
     $this->singletonWebPush();
-    $this->prepareSubscriptions($pushData['content'], $pushData['options']);
+    $this->prepareSubscriptions($pushData['content'], $pushData['options'], $pushData['subscriptionIds']);
 
     // Send the queued items by prepareSubscriptions().
     // And check message for each notifications.
-- 
GitLab


From 1fb479d266ee756d56d5757b712b8b6e7461371d Mon Sep 17 00:00:00 2001
From: Project Update Bot
 <66574-Project-Update-Bot@users.noreply.drupalcode.org>
Date: Thu, 11 Apr 2024 14:39:10 +0000
Subject: [PATCH 6/8] Automated Project Update Bot fixes

---
 web_push.info.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/web_push.info.yml b/web_push.info.yml
index 11906ca..c9f296d 100644
--- a/web_push.info.yml
+++ b/web_push.info.yml
@@ -3,7 +3,7 @@ description: Sends web push notifications to users.
 package: Notification
 
 type: module
-core_version_requirement: ^9.5 || ^10
+core_version_requirement: ^9.5 || ^10 || ^11
 
 dependencies:
   - drupal:rest
-- 
GitLab


From ee817bde11bcfe97e7ed18865b48b091da980c08 Mon Sep 17 00:00:00 2001
From: "yves.fierville" <yves.fierville@kleegroup.com>
Date: Thu, 11 Apr 2024 17:40:04 +0200
Subject: [PATCH 7/8] Fix PHPCS

---
 src/Controller/WebPushController.php          | 11 ++++-------
 src/Entity/Subscription.php                   |  3 +--
 src/Entity/SubscriptionListBuilder.php        |  5 ++---
 src/Form/SecurityForm.php                     |  4 ++--
 src/Form/SettingsForm.php                     |  4 ++--
 src/Form/SubscriptionDeleteForm.php           | 10 +++-------
 src/Form/TestNotification.php                 | 11 ++---------
 src/Form/VAPIDForm.php                        | 19 ++++++++++---------
 src/Plugin/Block/WebPushBlock.php             |  2 +-
 src/Plugin/QueueWorker/WebPushQueueWorker.php |  3 ++-
 .../rest/resource/SubscriptionResource.php    | 12 +++++-------
 src/Service/AuthenticationHelper.php          | 13 +++++++++----
 src/Service/WebPushManager.php                |  7 +++----
 src/Service/WebPushSender.php                 | 17 ++++++++---------
 web_push.links.tasks.yml                      |  2 +-
 web_push.module                               |  5 +++++
 16 files changed, 60 insertions(+), 68 deletions(-)

diff --git a/src/Controller/WebPushController.php b/src/Controller/WebPushController.php
index cee8a79..785e3e0 100644
--- a/src/Controller/WebPushController.php
+++ b/src/Controller/WebPushController.php
@@ -5,8 +5,6 @@ namespace Drupal\web_push\Controller;
 use Drupal\Core\Cache\CacheableResponse;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Extension\ModuleHandler;
-use Drupal\Core\Url;
-use Drupal\web_push\Form\SettingsForm;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -17,6 +15,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 class WebPushController extends ControllerBase {
 
   /**
+   * The module handler service.
+   *
    * @var \Drupal\Core\Extension\ModuleHandler
    */
   protected $moduleHandler;
@@ -40,12 +40,11 @@ class WebPushController extends ControllerBase {
     );
   }
 
-
   /**
    * Get the service worker javascript handler.
    *
    * @return \Drupal\Core\Cache\CacheableResponse
-   *  The service worker content.
+   *   The service worker content.
    */
   public function serviceWorker() {
     // Get the actual module path.
@@ -57,9 +56,7 @@ class WebPushController extends ControllerBase {
       'Content-Type' => 'application/javascript',
       'Service-Worker-Allowed' => '/',
     ]);
-    // TODO add cache metadata
-    // $response->addCacheableDependency($cacheable_metadata);
-
+    // @todo add cache metadata
     return $response;
   }
 
diff --git a/src/Entity/Subscription.php b/src/Entity/Subscription.php
index 012486b..5d65101 100644
--- a/src/Entity/Subscription.php
+++ b/src/Entity/Subscription.php
@@ -2,9 +2,9 @@
 
 namespace Drupal\web_push\Entity;
 
-use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
 
 /**
  * Defines the Notification subscription entity.
@@ -134,5 +134,4 @@ class Subscription extends ContentEntityBase {
     return $fields;
   }
 
-
 }
diff --git a/src/Entity/SubscriptionListBuilder.php b/src/Entity/SubscriptionListBuilder.php
index d5cc9d7..621d53a 100644
--- a/src/Entity/SubscriptionListBuilder.php
+++ b/src/Entity/SubscriptionListBuilder.php
@@ -3,11 +3,11 @@
 namespace Drupal\web_push\Entity;
 
 use Drupal\Core\Datetime\DateFormatterInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityListBuilder;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides a list controller for web_push_subscription entity.
@@ -51,7 +51,6 @@ class SubscriptionListBuilder extends EntityListBuilder {
     );
   }
 
-
   /**
    * {@inheritdoc}
    *
@@ -78,4 +77,4 @@ class SubscriptionListBuilder extends EntityListBuilder {
     return $row + parent::buildRow($entity);
   }
 
-}
\ No newline at end of file
+}
diff --git a/src/Form/SecurityForm.php b/src/Form/SecurityForm.php
index e1af22d..1318b56 100644
--- a/src/Form/SecurityForm.php
+++ b/src/Form/SecurityForm.php
@@ -59,7 +59,7 @@ class SecurityForm extends ConfigFormBase {
    */
   protected function getEditableConfigNames() {
     return [
-      static::$configId
+      static::$configId,
     ];
   }
 
@@ -98,7 +98,7 @@ class SecurityForm extends ConfigFormBase {
     ];
 
     $form['actions'] = [
-      '#type' => 'actions'
+      '#type' => 'actions',
     ];
     $form['actions']['save'] = [
       '#type' => 'submit',
diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php
index d342be2..623a7f1 100644
--- a/src/Form/SettingsForm.php
+++ b/src/Form/SettingsForm.php
@@ -61,7 +61,7 @@ class SettingsForm extends ConfigFormBase {
    */
   protected function getEditableConfigNames() {
     return [
-      static::$configId
+      static::$configId,
     ];
   }
 
@@ -142,7 +142,7 @@ class SettingsForm extends ConfigFormBase {
     ];
 
     $form['actions'] = [
-      '#type' => 'actions'
+      '#type' => 'actions',
     ];
     $form['actions']['save'] = [
       '#type' => 'submit',
diff --git a/src/Form/SubscriptionDeleteForm.php b/src/Form/SubscriptionDeleteForm.php
index b3a6ea4..7e2bb71 100644
--- a/src/Form/SubscriptionDeleteForm.php
+++ b/src/Form/SubscriptionDeleteForm.php
@@ -1,10 +1,5 @@
 <?php
 
-/**
- * @file
- * Contains \Drupal\web_push\Form\SubscriptionDeleteForm.
- */
-
 namespace Drupal\web_push\Form;
 
 use Drupal\Core\Entity\ContentEntityConfirmFormBase;
@@ -22,7 +17,7 @@ class SubscriptionDeleteForm extends ContentEntityConfirmFormBase {
    * {@inheritdoc}
    */
   public function getQuestion() {
-    return $this->t('Are you sure you want to delete entity %token?', array('%token' => $this->entity->getToken()));
+    return $this->t('Are you sure you want to delete entity %token?', ['%token' => $this->entity->getToken()]);
   }
 
   /**
@@ -58,4 +53,5 @@ class SubscriptionDeleteForm extends ContentEntityConfirmFormBase {
     // Redirect to term list after delete.
     $form_state->setRedirect('entity.web_push_subscription.collection');
   }
-}
\ No newline at end of file
+
+}
diff --git a/src/Form/TestNotification.php b/src/Form/TestNotification.php
index 67e0a10..3f8c2de 100644
--- a/src/Form/TestNotification.php
+++ b/src/Form/TestNotification.php
@@ -113,13 +113,6 @@ class TestNotification extends FormBase {
     return $form;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, FormStateInterface $form_state) {
-    parent::validateForm($form, $form_state);
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -133,10 +126,10 @@ class TestNotification extends FormBase {
         'title' => $form_state->getValue('title'),
         'body' => $form_state->getValue('body'),
         'icon' => $form_state->getValue('icon'),
-        'url' => $url
+        'url' => $url,
       ],
       'options' => [
-        'urgency' => ''
+        'urgency' => '',
       ],
     ];
 
diff --git a/src/Form/VAPIDForm.php b/src/Form/VAPIDForm.php
index 422b0b2..f21559d 100644
--- a/src/Form/VAPIDForm.php
+++ b/src/Form/VAPIDForm.php
@@ -39,6 +39,8 @@ class VAPIDForm extends ConfigFormBase {
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The factory for configuration objects.
+   * @param \Drupal\web_push\Service\AuthenticationHelper $authentication_helper
+   *   The authentication service helper.
    */
   public function __construct(
     ConfigFactoryInterface $config_factory,
@@ -71,7 +73,7 @@ class VAPIDForm extends ConfigFormBase {
    */
   protected function getEditableConfigNames() {
     return [
-      static::$configId
+      static::$configId,
     ];
   }
 
@@ -99,25 +101,24 @@ class VAPIDForm extends ConfigFormBase {
       '#type' => 'textfield',
       '#title' => $this->t('Public Key'),
       '#description' => $this->t('(recommended) uncompressed public key P-256 encoded in Base64-URL'),
-      '#default_value' => $config->get('publicKey')
+      '#default_value' => $config->get('publicKey'),
     ];
     $form['VAPID']['privateKey'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Private Key'),
       '#description' => $this->t('(recommended) in fact the secret multiplier of the private key encoded in Base64-URL'),
-      '#default_value' => $config->get('privateKey')
+      '#default_value' => $config->get('privateKey'),
     ];
 
     // No method to add PEM file, PEM file is not recommended.
     // @see https://github.com/web-push-libs/web-push-php#authentication-vapid.
-
     $form['actions'] = [
-      '#type' => 'actions'
+      '#type' => 'actions',
     ];
     $form['actions']['generate'] = [
       '#type' => 'submit',
       '#value' => $this->t('Generate and Save VAPID Keys'),
-      '#submit' => ['::generateVAPIDKeys']
+      '#submit' => ['::generateVAPIDKeys'],
     ];
     $form['actions']['save'] = [
       '#type' => 'submit',
@@ -130,12 +131,12 @@ class VAPIDForm extends ConfigFormBase {
   /**
    * Save the keys in config.
    *
-   * @param $publicKey
+   * @param string $publicKey
    *   The public key to save.
-   * @param $privateKey
+   * @param string $privateKey
    *   The private key to save.
    */
-  private function saveKeys($publicKey, $privateKey): void {
+  private function saveKeys(string $publicKey, string $privateKey): void {
     $config = $this->config(static::$configId);
     $config
       ->set('publicKey', $publicKey)
diff --git a/src/Plugin/Block/WebPushBlock.php b/src/Plugin/Block/WebPushBlock.php
index dc60972..e4651f0 100644
--- a/src/Plugin/Block/WebPushBlock.php
+++ b/src/Plugin/Block/WebPushBlock.php
@@ -79,7 +79,7 @@ class WebPushBlock extends BlockBase implements ContainerFactoryPluginInterface
    * {@inheritdoc}
    */
   public function build() {
-    $build =  [
+    $build = [
       '#theme' => 'web_push_subscription',
       '#attached' => ['library' => ['web_push/manual_subscrition']],
     ];
diff --git a/src/Plugin/QueueWorker/WebPushQueueWorker.php b/src/Plugin/QueueWorker/WebPushQueueWorker.php
index 8c65eb2..94fd03e 100644
--- a/src/Plugin/QueueWorker/WebPushQueueWorker.php
+++ b/src/Plugin/QueueWorker/WebPushQueueWorker.php
@@ -64,4 +64,5 @@ class WebPushQueueWorker extends QueueWorkerBase implements ContainerFactoryPlug
   public function processItem($pushData) {
     $this->sender->sendNotification($pushData);
   }
-}
\ No newline at end of file
+
+}
diff --git a/src/Plugin/rest/resource/SubscriptionResource.php b/src/Plugin/rest/resource/SubscriptionResource.php
index 75ec549..2438921 100644
--- a/src/Plugin/rest/resource/SubscriptionResource.php
+++ b/src/Plugin/rest/resource/SubscriptionResource.php
@@ -8,9 +8,9 @@ use Drupal\Core\Flood\FloodInterface;
 use Drupal\rest\Plugin\ResourceBase;
 use Drupal\rest\ResourceResponse;
 use Drupal\web_push\Form\SecurityForm;
-use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
 
 /**
  * Provides a resource for Subscription.
@@ -59,10 +59,8 @@ class SubscriptionResource extends ResourceBase {
    *   The available serialization formats.
    * @param \Psr\Log\LoggerInterface $logger
    *   A logger instance.
-   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
-   *   A current user instance.
-   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
-   *   A current user instance.
+   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
+   *   An entity type manager instance.
    * @param \Drupal\Core\Flood\FloodInterface $flood
    *   The flood service.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
@@ -133,7 +131,7 @@ class SubscriptionResource extends ResourceBase {
     if (!empty($key) && !empty($token) && !empty($endpoint)) {
       $ids = $this->entityStorage->loadByProperties([
         'key' => $key,
-        'token' => $token
+        'token' => $token,
       ]);
       if (empty($ids)) {
         $subscription = $this->entityStorage->create([
@@ -149,6 +147,6 @@ class SubscriptionResource extends ResourceBase {
     }
 
     return new ResourceResponse('OK', 200);
-
   }
+
 }
diff --git a/src/Service/AuthenticationHelper.php b/src/Service/AuthenticationHelper.php
index de66867..5ce11ed 100644
--- a/src/Service/AuthenticationHelper.php
+++ b/src/Service/AuthenticationHelper.php
@@ -8,6 +8,9 @@ use Drupal\web_push\Form\VAPIDForm;
 use Minishlink\WebPush\VAPID;
 use Psr\Log\LoggerInterface;
 
+/**
+ * The athentication service helper.
+ */
 class AuthenticationHelper {
 
   /**
@@ -37,13 +40,13 @@ class AuthenticationHelper {
     $this->config = $config_factory->get(VAPIDForm::$configId);
   }
 
-
   /**
    * Generate Keys.
    *
    * @return array
+   *   The VAPID keys.
    */
-  public function genrateKeys() {
+  public function genrateKeys(): array {
     try {
       return VAPID::createVapidKeys();
     }
@@ -57,14 +60,16 @@ class AuthenticationHelper {
    * Build the authentitcation for push.
    *
    * @return array
+   *   The auth informations.
    */
-  public function getAuth() {
+  public function getAuth(): array {
     return [
       'VAPID' => [
         'subject' => Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString(),
         'publicKey' => $this->config->get('publicKey'),
         'privateKey' => $this->config->get('privateKey'),
-      ]
+      ],
     ];
   }
+
 }
diff --git a/src/Service/WebPushManager.php b/src/Service/WebPushManager.php
index 640a376..c4c6416 100644
--- a/src/Service/WebPushManager.php
+++ b/src/Service/WebPushManager.php
@@ -3,8 +3,8 @@
 namespace Drupal\web_push\Service;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Url;
 use Drupal\Core\Queue\QueueWorkerManagerInterface;
+use Drupal\Core\Url;
 use Drupal\web_push\Form\SettingsForm;
 use Psr\Log\LoggerInterface;
 
@@ -71,7 +71,6 @@ class WebPushManager {
    *   The topic of the notification.
    * @param array|null $subscriptionIds
    *   The subscriptions ids or NULL for all.
-   *
    */
   public function sendNotification(
     string $title,
@@ -90,13 +89,13 @@ class WebPushManager {
         'title' => $title,
         'body' => $body,
         'icon' => $icon,
-        'url' => $url
+        'url' => $url,
       ],
       'options' => [
         'urgency' => $urgency,
         'topic' => $topic,
       ],
-      'subscriptionIds' => $subscriptionIds
+      'subscriptionIds' => $subscriptionIds,
     ];
 
     $worker = $this->queueWorkerManager->createInstance('web_push');
diff --git a/src/Service/WebPushSender.php b/src/Service/WebPushSender.php
index fc2a44a..ca4295b 100644
--- a/src/Service/WebPushSender.php
+++ b/src/Service/WebPushSender.php
@@ -7,10 +7,9 @@ use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityTypeManager;
 use Drupal\web_push\Entity\Subscription;
 use Drupal\web_push\Form\SettingsForm;
-use Drupal\web_push\Service\AuthenticationHelper;
 use Minishlink\WebPush\MessageSentReport;
-use Minishlink\WebPush\WebPush;
 use Minishlink\WebPush\Subscription as WebPushSubscription;
+use Minishlink\WebPush\WebPush;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
 
@@ -106,13 +105,13 @@ class WebPushSender {
       'TTL' => $this->config->get('ttl'),
       'urgency' => $this->config->get('urgency'),
       'topic' => $this->config->get('topic'),
-      'batchSize' => (int) $this->config->get('batchSize')
+      'batchSize' => (int) $this->config->get('batchSize'),
     ];
     try {
       $this->webPush = new WebPush($auth, $options);
       $this->webPush->setDefaultOptions($options);
       // @see https://github.com/web-push-libs/web-push-php#reusing-vapid-headers.
-      $this->webPush->setReuseVAPIDHeaders(true);
+      $this->webPush->setReuseVAPIDHeaders(TRUE);
     }
     catch (\ErrorException $e) {
       $this->logger->error($e->getMessage());
@@ -122,7 +121,7 @@ class WebPushSender {
   /**
    * Build the Subscription Notification to send.
    *
-   * @param Subscription $subscription
+   * @param \Drupal\web_push\Entity\Subscription $subscription
    *   The Drupal subscription details.
    * @param array $pushData
    *   The data to send.
@@ -134,7 +133,7 @@ class WebPushSender {
     $webSubscription['subscription'] = WebPushSubscription::create([
       'endpoint' => $subscription->getEndpoint(),
       'publicKey' => $subscription->getPublicKey(),
-      'authToken' => $subscription->getToken()
+      'authToken' => $subscription->getToken(),
     ]);
     // Check the URL to avoid redirection outside the site.
     $urlHost = parse_url($pushData['url'], PHP_URL_HOST);
@@ -157,6 +156,7 @@ class WebPushSender {
    * @param array $optionsCustom
    *   The notification urgency.
    * @param array|null $subscriptionIds
+   *   List of subscription Ids to load.
    */
   protected function prepareSubscriptions(array $pushData, array $optionsCustom = [], ?array $subscriptionIds = NULL): void {
     $listSubscriptions = $this->entityStorage->loadMultiple($subscriptionIds);
@@ -182,7 +182,7 @@ class WebPushSender {
   /**
    * Manage action on result event.
    *
-   * @param MessageSentReport $report
+   * @param \Minishlink\WebPush\MessageSentReportMessageSentReport $report
    *   The result of the notification send.
    */
   protected function manageReport(MessageSentReport $report): void {
@@ -196,9 +196,8 @@ class WebPushSender {
     }
     if ($report->isSubscriptionExpired()) {
       // Get the subscription to delete.
-      // TODO : optimize to avoid the load of one entity by one.
       $subscriptionList = $this->entityStorage->loadByProperties(['endpoint' => $endpoint]);
-      foreach($subscriptionList as $subscription) {
+      foreach ($subscriptionList as $subscription) {
         $subscription->delete();
       }
     }
diff --git a/web_push.links.tasks.yml b/web_push.links.tasks.yml
index 63f6cf5..169248e 100644
--- a/web_push.links.tasks.yml
+++ b/web_push.links.tasks.yml
@@ -2,4 +2,4 @@ entity.dictionary_term.delete_confirm:
   route_name: entity.web_push_subscription.delete_form
   base_route: entity.web_push_subscription.collection
   title: Delete
-  weight: 10
\ No newline at end of file
+  weight: 10
diff --git a/web_push.module b/web_push.module
index e8c5c90..4d88990 100644
--- a/web_push.module
+++ b/web_push.module
@@ -1,5 +1,10 @@
 <?php
 
+/**
+ * @file
+ * Primary module hooks for Web Push module.
+ */
+
 use Drupal\Core\Url;
 use Drupal\web_push\Form\SettingsForm;
 use Drupal\web_push\Form\VAPIDForm;
-- 
GitLab


From 1a5744d5b149c63441794357644354c6e2403614 Mon Sep 17 00:00:00 2001
From: Aleix Quintana <22647-kinta@users.noreply.drupalcode.org>
Date: Wed, 9 Jul 2025 14:51:50 +0000
Subject: [PATCH 8/8] Edit composer.json

---
 composer.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/composer.json b/composer.json
index 3f3e12f..e67df5b 100644
--- a/composer.json
+++ b/composer.json
@@ -16,7 +16,7 @@
     "ext-mbstring": "*",
     "ext-curl": "*",
     "ext-openssl": "*",
-    "minishlink/web-push": "^8.0"
+    "minishlink/web-push": "^9.0"
   },
   "require-dev": {
     "phpunit/phpunit": "5.*"
-- 
GitLab