Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BO - Notifications] Refactorisation envoi de mail #1134

Merged
merged 17 commits into from
Apr 11, 2023

Conversation

sfinx13
Copy link
Collaborator

@sfinx13 sfinx13 commented Apr 3, 2023

Ticket

#1139

Description

L'approche actuelle rend le code difficile à maintenir et à étendre car elle est très rigide et ne permet pas d'étendre la fonctionnalité d'envoi de base.
L'idée est de créer une hiérarchie de classes ou chaque classe correspond à un type de notification qui étend une classe principale qui encapsule la logique d'envoi.

Cela permet d'avoir une meilleur visibilité sur les différents mail envoyés et de rendre le code plus flexible, plus facile à maintenir et à étendre. On pourrait imaginer apporter des fonctionnalités supplémentaires sur un type de mail particulier.

Changements apportés

  • Remplacement de l'ancien service NotificationService par NotificationMailerRegistry qui est un registre qui contient l'ensemble des maiil de notification référencé par le tag symfony app.notification_mailer
  • Remplacement du tableau associatif par une classe NotificationMail pour encapsuler les données utile à l'envoi
        private readonly NotificationMailerType $type,
        private readonly array|string $to,
        private readonly ?string $fromEmail = null,
        private readonly ?string $fromFullname = null,
        private readonly ?string $message = null,
        private readonly ?Territory $territory = null,
        private readonly ?User $user = null,
        private readonly ?Signalement $signalement = null,
        private readonly ?\Throwable $event = null,
        private readonly mixed $attachment = null,
        private readonly ?string $motif = null,
        private readonly ?string $cronLabel = null,
        private readonly ?int $cronCount = null,
        private readonly array $params = [],
  • Définition des type d'email dans une énumération NotificationMailerType
  • Implémentation d'une classe abstraite qui va encapsuler la logique d'envoi AbstractNotificationMailer
  • Implémentation des 23 classes enfants héritant de AbstractNotificationMailer réparti selon une arborescence métier qui peut évoluer, aucune contrainte existe.
.
└── Mailer/
    ├── Mail/
    │   ├── Account/
    │   │   ├── AccountActivationNotificationMailer.php
    │   │   └── ...
    │   ├── Contact/
    │   │   ├── ContactFormMailer.php
    │   │   └── ....
    │   ├── Cron/
    │   │   ├── CronMailer.php
    │   │   └── ...
    │   ├── Error/
    │   │   ├── ErrorSignalementMailer.php
    │   │   └── ...
    │   ├── Signalement/
    │   │   ├── SignalementNewMailer.php
    │   │   └── ...
    │   ├── Suivi/
    │   │   ├── SuiviNewCommentBackMailer.php
    │   │   └── ....
    │   ├── AbstractNotificationMailer.php
    │   └── NotificationMailerInterface.php
    ├── NotificationMail.php
    ├── NotificationMailerRegistry.php
    └── NotificationMailerType.php

Comment envoyer un mail ?

Définir une constante dans NotificationMailerType.php pour identifier un email

enum NotificationMailerType
{
    ....
    case TYPE_INTERVENTION_NEW_DATE_VISITE_USAGER;
}

Créer une classe Mailer pour configurer un email

namespace App\Service\Mailer\Mail\Intervention;

// ....

class InterventionNewDateVisiteUsagerMailer extends AbstractNotificationMailer
{
    protected ?NotificationMailerType $mailerType = NotificationMailerType::TYPE_INTERVENTION_NEW_DATE_VISITE_USAGER;
    protected ?string $mailerSubject = 'Une visite de votre logement est prévue';
    protected ?string $mailerButtonText = 'Accéder à mon signalement';
    protected ?string $mailerTemplate = 'new_intervention_date_visite_usager_email';

    public function __construct(
        protected MailerInterface $mailer,
        protected ParameterBagInterface $parameterBag,
        protected LoggerInterface $logger
    ) {
        parent::__construct($this->mailer, $this->parameterBag, $this->logger);
    }
}

    public function getMailerParamsFromNotification(NotificationMail $notificationMail): array
    {
        $signalement = $notificationMail->getSignalement();
        return [
            'ref_signalement' => $signalement->getReference(),
        ];
    }

Envoyer un email

Injecter le service NotificationMailerRegistry et définir un objet Notification

#[Route('/edit-date-visite', name: 'edit_date_visite')]
    public function nomAction(
        NotificationMailerRegistry $notificationMailerRegistry,
        Signalement $signalement,
        Request $request
    ): Response {
                $notificationMailerRegistry->send(
                    new NotificationMail(
                        type: NotificationMailerType::TYPE_INTERVENTION_NEW_DATE_VISITE_USAGER,
                        to: 'john.doe@yopmail.com',
                        territory: $this->getUser()->getTerritory(),
                        signalement: $signalement
                    )
                );
        }
    }

Tests (22 emails)

Tester l'ensemble des cas métiers qui déclenche les 23 mails.

  • TYPE_ACCOUNT_ACTIVATION_FROM_BO;
  • TYPE_ACCOUNT_ACTIVATION_FROM_FO;
  • TYPE_ACCOUNT_ACTIVATION_REMINDER;
  • TYPE_ACCOUNT_DELETE;
  • TYPE_ACCOUNT_TRANSFER;
  • TYPE_ACCOUNT_REACTIVATION;
  • TYPE_LOST_PASSWORD;
  • TYPE_SIGNALEMENT_NEW;
  • TYPE_ASSIGNMENT_NEW;
  • TYPE_SIGNALEMENT_VALIDATION;
  • TYPE_SIGNALEMENT_REFUSAL;
  • TYPE_SIGNALEMENT_CLOSED_TO_USAGER;
  • TYPE_SIGNALEMENT_CLOSED_TO_PARTNERS;
  • TYPE_SIGNALEMENT_CLOSED_TO_PARTNER;
  • TYPE_SIGNALEMENT_FEEDBACK_USAGER;
  • TYPE_CONFIRM_RECEPTION;
  • TYPE_NEW_COMMENT_FRONT;
  • TYPE_NEW_COMMENT_BACK;
  • TYPE_CONTACT_FORM;
  • TYPE_ERROR_SIGNALEMENT;
  • TYPE_ERROR_SIGNALEMENT_NO_USER;
  • TYPE_CRON;

@github-advanced-security
Copy link

You have successfully added a new SonarCloud configuration ``. As part of the setup process, we have scanned this repository and found no existing alerts. In the future, you will see all code scanning alerts on the repository Security tab.

@sfinx13 sfinx13 changed the title Move notificationService in Mailer folder [BO - Notifications] Revoir les notifications + architecture envoi de mail Apr 3, 2023
@sfinx13 sfinx13 changed the title [BO - Notifications] Revoir les notifications + architecture envoi de mail [BO - Notifications] Revoir les notifications + refactorisation envoi de mail Apr 4, 2023
@sfinx13 sfinx13 changed the title [BO - Notifications] Revoir les notifications + refactorisation envoi de mail [BO - Notifications] Refactorisation envoi de mail Apr 4, 2023
NotificationMailerType::TYPE_CRON,
$this->parameterBag->get('admin_email'),
[
'cron_label' => 'demande de feedback à l\'usager',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plus besoin de passer l'url, elle est passé en tant que paramètre par défaut

@@ -23,7 +23,7 @@
<tbody>
<tr style="text-align: center;width: 100%">
<td>
<a href="{{ lien_suivi|raw }}" target="_blank" rel="noopener">{{ btnText|capitalize }}</a></td>
<a href="{{ lien_suivi|raw }}" target="_blank" rel="noopener">{{ btntext|capitalize }}</a></td>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Il y'avait les deux variables btnText et btntext j'ai gardé celui ou il y'avais moins de fichier à modifier

@sfinx13 sfinx13 marked this pull request as ready for review April 6, 2023 11:49
@@ -34,36 +41,27 @@ public function validationResponseSignalement(Signalement $signalement, Request
$signalement->setCodeSuivi(md5(uniqid()));
$toRecipients = $signalement->getMailUsagers();
foreach ($toRecipients as $toRecipient) {
$notificationService->send(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avant @emilschn

),
],
$signalement->getTerritory()
$notificationMailerRegistry->send(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apres @emilschn la construction des paramètres se fait dans la classe dorénavant dans la majorité des cas, il reste toujours possible de passer des paramètres.

Copy link
Collaborator

@hmeneuvrier hmeneuvrier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J'ai refait une passe de tests, j'ai mis mes commentaires

@@ -36,7 +36,7 @@ security:
signature_properties: [id, email]
default_target_path: login_creation_pass
failure_path: login_activation_fail
max_uses: 1
max_uses: 3
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aujourd'hui deux systèmes de reset-password cohabite, mise à jour de la configuration afin de permettre aux utilisateurs de cliquer au max 3 fois sur le lien.
Pour info LoginLink est utilisé de maniere détourné car cela sert à faire de la connexion sans mot de passe et non à générer des liens de reset-password. Doit être remplacer par le système qui a été mis en place coté BO

@@ -1,91 +0,0 @@
<?php

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jamais utilisé depuis 8 mois

territory: $user->getTerritory(),
user: $user,
params: [
'nb_signalements' => $userItem['nb_signalements'],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seulement 2 mails ont un tableau associatif passé en paramètre celui ci et celui d'ESABORA

@@ -63,63 +58,6 @@ public function countByStatusForUser($user, Territory|null $territory, Qualifica
->getResult();
}

public function findByStatusAndOrCityForUser(User|UserInterface|null $user, array $options, int|null $export): Paginator|array
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plus utilisé depuis la livraison de la 1.6.0

{
}

abstract public function getMailerParamsFromNotification(NotificationMail $notificationMail): array;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Il est obligatoire d'implementer getMailerParamsFromNotification même si vous n'avez pas de paramètre à utiliser ce qui est assez rare dans ce cas la, passez un tableau vide comme dans AccountDeleteMailer

return $this->parameterBag->get('host_url').$this->urlGenerator->generate($route, $params);
}

public function updateMailerSubjectFromNotification(NotificationMail $notificationMail): void
Copy link
Collaborator Author

@sfinx13 sfinx13 Apr 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si vous devez avoir un objet avec des paramètres implémenter updateMailerSubjectFromNotification

];
}

public function updateMailerSubjectFromNotification(NotificationMail $notificationMail): void
Copy link
Collaborator Author

@sfinx13 sfinx13 Apr 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour gérer les placeholder dans un objet de mail


class NotificationMail
{
public function __construct(
Copy link
Collaborator Author

@sfinx13 sfinx13 Apr 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Porte les paramètres, peut être amené à évoluer si ces paramètre ne permettent pas de récupérer l'info dont on a besoin

@emilschn
Copy link
Collaborator

Pour moi, c'est ok sur les fonctionnalités re-testées.

@hmeneuvrier
Copy link
Collaborator

ok pour moi aussi !

@sfinx13 sfinx13 force-pushed the feature/853-review-notifications branch from 8451018 to 3402bc5 Compare April 11, 2023 13:44
@sonarcloud
Copy link

sonarcloud bot commented Apr 11, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 4 Code Smells

No Coverage information No Coverage information
2.6% 2.6% Duplication

@hmeneuvrier hmeneuvrier merged commit 58434bf into develop Apr 11, 2023
@hmeneuvrier hmeneuvrier deleted the feature/853-review-notifications branch April 11, 2023 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants