Vincent 3 jaren geleden
bovenliggende
commit
6ffaf153e3

+ 1 - 8
config/services.yaml

@@ -12,6 +12,7 @@ services:
             $internalFilesUploadUri: '%env(INTERNAL_FILES_DOWNLOAD_URI)%'
             $bindfileBufferFile: '%env(BIND_FILE_BUFFER_FILE)%'
             $contextAwareDataPersister: '@api_platform.doctrine.orm.data_persister'
+            $opentalentNoReplyEmailAddress: 'noreply@opentalent.fr'
 
     # Logging: a shorter version of the default monolog line formatter
     monolog.formatter.message:
@@ -46,14 +47,6 @@ services:
 
     Gaufrette\Filesystem: '@knp_gaufrette.filesystem_map'
 
-    App\Service\MailHub:
-        bind:
-            $opentalentNoReplyEmailAddress: 'noreply@opentalent.fr'
-
-    App\Service\Mailer\Mailer:
-        bind:
-            $opentalentNoReplyEmailAddress: 'noreply@opentalent.fr'
-
     #########################################
     ##  TAG Services ##
     _instanceof:

+ 1 - 1
old/Entity/Billing/BillPayment.php

@@ -1,6 +1,6 @@
 <?php
 
-namespace AppBundle\Entity\Billing;
+namespace App\Entity\Billing;
 
 use AppBundle\Entity\AccessAndFunction\Access;
 use AppBundle\Entity\Core\Tagg;

+ 26 - 0
src/Controller/AuditController.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Controller;
+
+use App\Entity\Organization\Parameters;
+use DH\Auditor\Provider\Doctrine\DoctrineProvider;
+use DH\Auditor\Provider\Doctrine\Persistence\Reader\Filter\SimpleFilter;
+use DH\Auditor\Provider\Doctrine\Persistence\Reader\Reader;
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Annotation\Route;
+
+class AuditController extends AbstractController
+{
+    #[Route('/audit_test', name: 'audit_test')]
+    public function index(DoctrineProvider $doctrineProvider): Response
+    {
+        $reader = new Reader($doctrineProvider);
+        $query = $reader
+            ->createQuery(Parameters::class)
+            ->addFilter(new SimpleFilter('object_id', 5755));
+
+        dd($query->execute());
+        return new Response('ok');
+    }
+}

+ 0 - 49
src/Controller/MailerController.php

@@ -1,49 +0,0 @@
-<?php
-
-namespace App\Controller;
-
-use App\Entity\Access\Access;
-use App\Entity\Organization\Parameters;
-use App\Message\Command\MailerCommand;
-use App\Service\Mailer\Model\TestModel;
-use DH\Auditor\Provider\Doctrine\DoctrineProvider;
-use DH\Auditor\Provider\Doctrine\Persistence\Reader\Filter\SimpleFilter;
-use DH\Auditor\Provider\Doctrine\Persistence\Reader\Query;
-use DH\Auditor\Provider\Doctrine\Persistence\Reader\Reader;
-use Doctrine\ORM\EntityManagerInterface;
-use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\Messenger\MessageBusInterface;
-use Symfony\Component\Routing\Annotation\Route;
-use DH\Auditor\Provider\Doctrine\Persistence\Reader\Filter\FilterInterface;
-
-class MailerController extends AbstractController
-{
-    #[Route('/mailer', name: 'app_mailer')]
-    public function index(MessageBusInterface $messageBus, EntityManagerInterface $entityManager, DoctrineProvider $doctrineProvider): Response
-    {
-//        $reader = new Reader($doctrineProvider);
-//        $query = $reader
-//            ->createQuery(Parameters::class)
-//            ->addFilter(new SimpleFilter('object_id', 5755));
-//
-//        dd($query->execute());
-//        return new Response('ok');
-//
-//
-//
-
-
-
-
-        $mailerModel = (new TestModel())
-            ->setAccessId(15)
-            ->setOrganizationId(498)
-            ->setSenderId(15);
-
-        $messageBus->dispatch(
-            new MailerCommand($mailerModel)
-        );
-        return new Response('ok');
-    }
-}

+ 2 - 6
src/DataProvider/Access/AccessProfileDataProvider.php

@@ -10,7 +10,6 @@ use App\ApiResources\Profile\AccessProfile;
 use App\Entity\Access\Access;
 use App\Service\Access\AccessProfileCreator;
 use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
-use Symfony\Component\Security\Core\Exception\AuthenticationException;
 use Symfony\Component\Security\Core\Security;
 
 /**
@@ -37,14 +36,11 @@ final class AccessProfileDataProvider implements ItemDataProviderInterface, Rest
         $originalAccess = null;
 
         $token = $this->security->getToken();
+
         if($token instanceof SwitchUserToken){
             $originalAccess = $token->getOriginalToken()->getUser();
         }
 
-        try {
-            return $this->accessProfileCreator->getAccessProfile($access, $originalAccess);
-        } catch (\Exception $e) {
-            return null;
-        }
+        return $this->accessProfileCreator->getAccessProfile($access, $originalAccess);
     }
 }

+ 1 - 5
src/DataProvider/Cotisation/CotisationDataProvider.php

@@ -25,10 +25,6 @@ final class CotisationDataProvider implements ItemDataProviderInterface, Restric
 
     public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?Cotisation
     {
-        try {
-            return $this->cotisationCreator->getCotisation($id);
-        } catch (\Exception $e) {
-            return null;
-        }
+        return $this->cotisationCreator->getCotisation($id);
     }
 }

+ 0 - 68
src/Service/MailHub.php

@@ -1,68 +0,0 @@
-<?php
-
-namespace App\Service;
-
-use App\Entity\Access\Access;
-use App\Entity\Organization\Organization;
-use App\Service\Access\Utils as AccessUtils;
-use App\Service\Core\ContactPointUtils;
-use Symfony\Bridge\Twig\Mime\TemplatedEmail;
-use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
-use Symfony\Component\Mailer\MailerInterface;
-use Symfony\Component\Mime\Address;
-
-class MailHub
-{
-    public function __construct(
-        private MailerInterface $mailer,
-        private string $opentalentNoReplyEmailAddress,
-        private ContactPointUtils $contactPointUtils,
-        private AccessUtils $accessUtils
-    ) {}
-
-    /**
-     * Sends an automatic 'do-not-reply'-type email to the user
-     *
-     * NB: These emails are not registered in the DB
-     *
-     * @param Access $access
-     * @param string $subject
-     * @param string $template
-     * @param array $data
-     * @throws TransportExceptionInterface
-     */
-    public function sendAutomaticEmailTo(Access $access, string $subject, string $template, array $data): void
-    {
-        $contactPoint = $this->contactPointUtils->getPersonContactPointPrincipal($access);
-        if ($contactPoint === null || empty($contactPoint->getEmail()) || $contactPoint->getEmailInvalid()) {
-            throw new \RuntimeException('Access has no principal email address, abort');
-        }
-        /** @noinspection NullPointerExceptionInspection */
-        $to = new Address($contactPoint->getEmail(), $access->getPerson()->getFullName() ?? $access->getPerson()->getUsername());
-
-        $context = ['_to' => $to];
-        $context = array_merge($context, $data);
-
-        $email = (new TemplatedEmail())
-            ->from($this->opentalentNoReplyEmailAddress)
-            ->to($to)
-            ->subject($subject)
-            ->htmlTemplate('@templates/emails/' . $template . '.html.twig')
-            ->context($context);
-
-        $this->mailer->send($email);
-    }
-
-    /**
-     * Sends an automatic 'do-not-reply'-type email to the admin of the organization
-     * @throws TransportExceptionInterface
-     */
-    public function sendAutomaticEmailToAdmin(Organization $organization, string $subject, string $template, array $data): void
-    {
-        $admin = $this->accessUtils->findAdminFor($organization);
-        if ($admin === null) {
-            throw new \RuntimeException('No admin found for organization ' . $organization->getId());
-        }
-        $this->sendAutomaticEmailTo($admin, $subject, $template, $data);
-    }
-}

+ 1 - 1
src/Service/Mailer/Builder/AbstractBuilder.php

@@ -81,7 +81,7 @@ class AbstractBuilder implements AbstractBuilderInterface
 
         if($target instanceof Access){
             $emailRecipient->setAccess($target);
-            $emailRecipient->setName($target->getPerson()->getFullName());
+            $emailRecipient->setName($target->getPerson()->getFullName() ?? $target->getOrganization()->getName());
             $this->setMailToRecipient($this->contactPointRepository->getByTypeAndPerson($contactPointType, $target->getPerson()), $emailRecipient);
         }else if ($target instanceof Organization){
             $emailRecipient->setOrganization($target);

+ 71 - 0
src/Service/Mailer/Builder/SubDomainChangeBuilder.php

@@ -0,0 +1,71 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Mailer\Builder;
+
+use App\Entity\Access\Access;
+use App\Entity\Organization\Organization;
+use App\Entity\Organization\Subdomain;
+use App\Enum\Core\ContactPointTypeEnum;
+use App\Enum\Core\EmailSendingTypeEnum;
+use App\Service\Access\Utils as AccessUtils;
+use App\Service\Mailer\Email;
+use App\Service\Mailer\Model\MailerModelInterface;
+use App\Service\Mailer\Model\SubdomainChangeModel;
+use App\Tests\Service\Mailer\Builder\SubDomainChangeBuilderTest;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\ORM\EntityManagerInterface;
+use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
+
+/**
+ * Classe SubDomainChangeBuilder qui est chargé de construire l'Email qui sera envoyé
+ */
+class SubDomainChangeBuilder extends AbstractBuilder implements BuilderInterface
+{
+    public function __construct(
+        private EntityManagerInterface $entityManager,
+        private string $opentalentNoReplyEmailAddress,
+        private AccessUtils $accessUtils
+    )
+    {
+    }
+
+    public function support(MailerModelInterface $mailerModel): bool
+    {
+        return $mailerModel instanceof SubdomainChangeModel;
+    }
+
+    /**
+     * @param SubdomainChangeModel $mailerModel
+     * @return ArrayCollection
+     *
+     * @see SubDomainChangeBuilderTest::testBuild()
+     */
+    public function build(MailerModelInterface $mailerModel): ArrayCollection
+    {
+        $subdomain = $this->entityManager->getRepository(Subdomain::class)->find($mailerModel->getSubdomainId());
+        $organization = $this->entityManager->getRepository(Organization::class)->find($mailerModel->getOrganizationId());
+        $author = $this->entityManager->getRepository(Access::class)->find($mailerModel->getSenderId());
+        $admin = $this->accessUtils->findAdminFor($organization);
+
+        $context = [
+            'access' => $admin,
+            'organization' => $organization,
+            'subdomain' => $subdomain,
+            'url' => $mailerModel->getUrl()
+        ];
+        $content = $this->render('subdomain', $context);
+
+        $email= (new Email())
+            ->setEmailEntity($this->buildEmailEntity( 'Nouveau sous domaine: ' . $subdomain->getSubdomain(), $author, $content))
+            ->setContent($content)
+            ->setFrom($this->opentalentNoReplyEmailAddress)
+            ->setNameFrom($organization->getName())
+        ;
+        $this->addRecipient($email, $admin, EmailSendingTypeEnum::TO()->getValue(), ContactPointTypeEnum::PRINCIPAL()->getValue());
+
+        $emails = new ArrayCollection();
+        $emails->add($email);
+        return $emails;
+    }
+}

+ 0 - 61
src/Service/Mailer/Builder/TestBuilder.php

@@ -1,61 +0,0 @@
-<?php
-declare(strict_types=1);
-
-namespace App\Service\Mailer\Builder;
-
-use App\Entity\Access\Access;
-use App\Entity\Organization\Organization;
-use App\Enum\Core\ContactPointTypeEnum;
-use App\Enum\Core\EmailSendingTypeEnum;
-use App\Service\Mailer\Email;
-use App\Service\Mailer\Model\MailerModelInterface;
-use App\Service\Mailer\Model\TestModel;
-use Doctrine\Common\Collections\ArrayCollection;
-use Doctrine\ORM\EntityManagerInterface;
-use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
-
-/**
- * Classe ... qui ...
- */
-class TestBuilder extends AbstractBuilder implements BuilderInterface
-{
-    public function __construct(
-        private EntityManagerInterface $entityManager
-    )
-    {
-    }
-
-    public function support(MailerModelInterface $mailerModel): bool
-    {
-        return $mailerModel instanceof TestModel;
-    }
-
-    /**
-     * @param TestModel $mailerModel
-     * @return ArrayCollection
-     */
-    public function build(MailerModelInterface $mailerModel): ArrayCollection
-    {
-        $organization = $this->entityManager->getRepository(Organization::class)->find($mailerModel->getOrganizationId());
-        $access = $this->entityManager->getRepository(Access::class)->find($mailerModel->getAccessId());
-
-        $emails = new ArrayCollection();
-
-        $context = ['organization' => $organization];
-        $content = $this->render('test', $context);
-
-        $email= (new Email())
-            ->setEmailEntity($this->buildEmailEntity('Mon sujet', $access, $content))
-            ->setContent($content)
-            ->setFrom('vincent.guffon@2iopenservice.fr')
-        ;
-
-        $this->addRecipient($email, $access, EmailSendingTypeEnum::TO()->getValue(), ContactPointTypeEnum::PRINCIPAL()->getValue());
-        $this->addRecipient($email, $organization, EmailSendingTypeEnum::TO()->getValue(), ContactPointTypeEnum::PRINCIPAL()->getValue());
-        $this->addRecipient($email, "vincent.guffon@gmail.com", EmailSendingTypeEnum::TO()->getValue());
-
-        $emails->add($email);
-
-        return $emails;
-    }
-}

+ 12 - 0
src/Service/Mailer/Email.php

@@ -12,6 +12,7 @@ use Doctrine\Common\Collections\ArrayCollection;
 class Email implements EmailInterface
 {
     private string $from;
+    private string $nameFrom;
     private EmailEntity $emailEntity;
     private string $content;
     private ArrayCollection $emailRecipients;
@@ -32,6 +33,17 @@ class Email implements EmailInterface
         return $this;
     }
 
+    public function getNameFrom(): string
+    {
+        return $this->nameFrom;
+    }
+
+    public function setNameFrom(string $nameFrom): self
+    {
+        $this->nameFrom = $nameFrom;
+        return $this;
+    }
+
     public function getEmailEntity(): EmailEntity
     {
         return $this->emailEntity;

+ 17 - 5
src/Service/Mailer/Mailer.php

@@ -93,6 +93,8 @@ class Mailer
 
         $this->setAntiSpam($email, $symfonyMail->getTo());
 
+        $this->setSymfonyEmailContent($symfonyMail, $email);
+
         $this->addHeaders($symfonyMail, $email);
 
         // @todo
@@ -135,18 +137,28 @@ class Mailer
      * @see MailerTest::testCreateSymfonyEmail()
      */
     public function createSymfonyEmail(Email $email): SymfonyEmail{
-        $addressMailFrom = new Address($email->getFrom(), $email->getEmailEntity()->getAuthor()->getPerson()->getFullName());
+        $addressMailFrom = new Address($email->getFrom(), $email->getNameFrom());
 
         return (new SymfonyEmail())
             ->from($addressMailFrom)
             ->replyTo($addressMailFrom)
             ->returnPath(Address::create("mail.report@opentalent.fr"))
             ->subject($email->getEmailEntity()->getAbout())
-            ->html($email->getContent())
-            ->text($this->stringsUtils->convertHtmlToText($email->getContent()))
             ;
     }
 
+    /**
+     * @param SymfonyEmail $symfonyEmail
+     * @param Email $email
+     *
+     * @see MailerTest::testSetSymfonyEmailContent()
+     */
+    public function setSymfonyEmailContent(SymfonyEmail $symfonyEmail, Email $email){
+        $symfonyEmail
+            ->html($email->getContent())
+            ->text($this->stringsUtils->convertHtmlToText($email->getContent()));
+    }
+
     /**
      * Créer le Templated Email contenant le rapport d'envoi
      * @param ArrayCollection $emails
@@ -170,7 +182,7 @@ class Mailer
                     'unDelivered' => $unDelivered
                 ]
             )
-            ->addTo(new Address($email->getFrom(), $email->getEmailEntity()->getAuthor()->getPerson()->getFullName()))
+            ->addTo(new Address($email->getFrom(), $email->getNameFrom()))
         ;
     }
 
@@ -237,7 +249,7 @@ class Mailer
      * @see MailerTest::testReduceEmailsCollectionInPreproduction()
      */
     public function reduceEmailsCollectionInPreproduction(ArrayCollection $emailsCollection): ArrayCollection {
-        if($this->environnement->get(EnvironnementVarEnum::APP_ENV()->getValue()) !== 'prod') {
+        if($emailsCollection->count() > 20 && $this->environnement->get(EnvironnementVarEnum::APP_ENV()->getValue()) !== 'prod') {
             $startEmails = $emailsCollection->slice(0, 10);
             $endEmails = $emailsCollection->slice($emailsCollection->count() - 11, 10);
             return new ArrayCollection([...$startEmails, ...$endEmails]);

+ 44 - 0
src/Service/Mailer/Model/SubdomainChangeModel.php

@@ -0,0 +1,44 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Mailer\Model;
+
+/**
+ * Classe SubdomainChangeModel qui conserve les données pour construire le mail lors du changement de nom de domaine
+ */
+class SubdomainChangeModel extends AbstractMailerModel implements MailerModelInterface
+{
+    private int $organizationId;
+    private int $subdomainId;
+    private string $url;
+
+    public function __construct()
+    {}
+
+    public function setOrganizationId(int $organizationId) : self{
+        $this->organizationId = $organizationId;
+        return $this;
+    }
+
+    public function getOrganizationId(): int {
+        return $this->organizationId;
+    }
+
+    public function setSubdomainId(int $subdomainId): self {
+        $this->subdomainId = $subdomainId;
+        return $this;
+    }
+
+    public function getSubdomainId(): int{
+        return $this->subdomainId;
+    }
+
+    public function setUrl(string $url): self {
+        $this->url = $url;
+        return $this;
+    }
+
+    public function getUrl(): string{
+        return $this->url;
+    }
+}

+ 0 - 34
src/Service/Mailer/Model/TestModel.php

@@ -1,34 +0,0 @@
-<?php
-declare(strict_types=1);
-
-namespace App\Service\Mailer\Model;
-
-/**
- * Classe ... qui ...
- */
-class TestModel extends AbstractMailerModel implements MailerModelInterface
-{
-    private int $accessId;
-    private int $organizationId;
-
-    public function __construct()
-    {}
-
-    public function setAccessId(int $accessId) : self{
-        $this->accessId = $accessId;
-        return $this;
-    }
-
-    public function getAccessId(): int {
-        return $this->accessId;
-    }
-
-    public function setOrganizationId(int $organizationId): self {
-        $this->organizationId = $organizationId;
-        return $this;
-    }
-
-    public function getOrganizationId(): int{
-        return $this->organizationId;
-    }
-}

+ 23 - 16
src/Service/OnChange/Organization/OnSubdomainChange.php

@@ -3,23 +3,26 @@
 namespace App\Service\OnChange\Organization;
 
 use App\Entity\Organization\Subdomain;
+use App\Message\Command\MailerCommand;
 use App\Message\Command\Typo3\Typo3UpdateCommand;
 use App\Service\Access\Utils as AccessUtils;
+use App\Service\Mailer\Model\SubdomainChangeModel;
 use App\Service\MailHub;
 use App\Service\OnChange\OnChangeContext;
 use App\Service\OnChange\OnChangeDefault;
 use App\Service\Organization\Utils as OrganizationUtils;
 use App\Service\Typo3\BindFileService;
+use App\Tests\Service\OnChange\Organization\OnSubdomainChangeTest;
 use Symfony\Component\Messenger\MessageBusInterface;
+use Symfony\Component\Security\Core\Security;
 
 class OnSubdomainChange extends OnChangeDefault
 {
     public function __construct(
         private OrganizationUtils $organizationUtils,
-        private AccessUtils $accessUtils,
-        private MailHub $mailHub,
         private BindFileService $bindFileService,
-        private MessageBusInterface $messageBus
+        private MessageBusInterface $messageBus,
+        private Security $security
     ) {}
 
     /** @noinspection PhpParameterNameChangedDuringInheritanceInspection */
@@ -69,22 +72,26 @@ class OnSubdomainChange extends OnChangeDefault
     }
 
     /**
-     * @throws \Exception
+     * @param Subdomain $subdomain
+     * @see OnSubdomainChangeTest::testSendEmailAfterSubdomainChange()
      */
     public function sendEmailAfterSubdomainChange(Subdomain $subdomain): void
     {
-
-        $admin = $this->accessUtils->findAdminFor($subdomain->getOrganization());
-
-        $this->mailHub->sendAutomaticEmailToAdmin(
-            $subdomain->getOrganization(),
-            'Nouveau sous domaine: ' . $subdomain->getSubdomain(),
-            'subdomain',
-            [
-                'access' => $admin,
-                'subdomain' => $subdomain,
-                'url' => $this->organizationUtils->getOrganizationWebsite($subdomain->getOrganization())
-            ]
+        $this->messageBus->dispatch(
+            new MailerCommand($this->getMailModel($subdomain))
         );
     }
+
+    /**
+     * @param Subdomain $subdomain
+     * @return SubdomainChangeModel
+     * @see OnSubdomainChangeTest::testGetMailModel()
+     */
+    public function getMailModel(Subdomain $subdomain): SubdomainChangeModel{
+        return (new SubdomainChangeModel())
+            ->setSenderId($this->security->getUser()->getId())
+            ->setOrganizationId($subdomain->getOrganization()->getId())
+            ->setSubdomainId($subdomain->getId())
+            ->setUrl($this->organizationUtils->getOrganizationWebsite($subdomain->getOrganization()));
+    }
 }

+ 2 - 1
src/Service/Organization/OrganizationProfileCreator.php

@@ -67,7 +67,8 @@ class OrganizationProfileCreator
         $organizationProfile
             ->setId($organization->getId())
             ->setName($organization->getName())
-            ->setWebsite($this->organizationUtils->getOrganizationWebsite($organization));
+            ->setWebsite($this->organizationUtils->getOrganizationWebsite($organization))
+        ;
 
         return $organizationProfile;
     }

+ 4 - 0
src/Service/Utils/StringsUtils.php

@@ -28,6 +28,8 @@ class StringsUtils
      * @param string $string
      * @param string $sep
      * @return string
+     *
+     * @see StringsUtilsTest::testCamelToSnake()
      */
     public static function camelToSnake(string $string, string $sep = "_"): string {
         return strtolower(
@@ -42,6 +44,8 @@ class StringsUtils
     /**
      * @param string $html
      * @return string
+     *
+     * @see StringsUtilsTest::testConvertHtmlToText()
      */
     public function convertHtmlToText(string $html): string
     {

+ 8 - 5
templates/emails/base.html.twig

@@ -38,11 +38,14 @@
             </row>
         {% endblock %}
 
-
-        {% block content %}
-            {{ content }}
-        {% endblock %}
-
+        <row>
+            <columns small="12">
+                <spacer size="10"></spacer>
+                    {% block content %}
+                    {% endblock %}
+                <spacer size="10"></spacer>
+            </columns>
+        </row>
 
         {% block antispam %}
             <row>

+ 27 - 13
templates/emails/subdomain.html.twig

@@ -1,17 +1,31 @@
-{% if  access.adminAccess %}
-Cher administrateur de {{access.organization.name}},
-{% else %}
-Cher {{access.person.givenName}} {{access.person.name}},
-{% endif %}
-votre demande d'activation du sous-domaine '{{ subdomain.subdomain }}' a été prise en compte et sera effective d'ici quelques minutes.
+{% extends 'emails/base.html.twig' %}
 
-Votre site sera dè lors accessible à l'adresse suivante :
+{% block content %}
 
-<a href="{{url}}">{{url}}</a>
+    <p>
+        {% if  access.adminAccess %}
+            Cher administrateur de {{access.organization.name}},
+        {% else %}
+            Cher {{access.person.givenName}} {{access.person.name}},
+        {% endif %}
+    </p>
+    <p>
+        Votre demande d'activation du sous-domaine '{{ subdomain.subdomain }}' a été prise en compte et sera effective d'ici quelques minutes.
+    </p>
 
-{% if  access.adminAccess %}
-Notez que votre identifiant est désormais : {{access.person.username}}
-Votre mot de passe reste inchangé.
-{% endif %}
+    <p>
+        Votre site sera dè lors accessible à l'adresse suivante :
+        <br/>
+        <a href="{{url}}">{{url}}</a>
+    </p>
 
-{% include '@templates/layout/noreply/footer.html.twig' with {'name': _to.name, 'email': _to.address } only %}
+
+    {% if  access.adminAccess %}
+        <p>
+            Notez que votre identifiant est désormais : {{access.person.username}}
+            <br />
+            Votre mot de passe reste inchangé.
+        </p>
+    {% endif %}
+
+{% endblock %}

+ 0 - 6
templates/layout/noreply/footer.html.twig

@@ -1,6 +0,0 @@
-Merci !<br>
-L'équipe Opentalent<br>
-<hr/>
-<em>Cet e-mail a été envoyé automatiquement. Merci de ne pas y répondre.<br>
-    Cet e-mail a été adressé à :<br>
-    {{name}} <{{email}}></em>

+ 0 - 124
tests/Service/MailHubTest.php

@@ -1,124 +0,0 @@
-<?php /** @noinspection PhpUnhandledExceptionInspection */
-
-namespace App\Tests\Service;
-
-use App\Entity\Access\Access;
-use App\Entity\Core\ContactPoint;
-use App\Entity\Organization\Organization;
-use App\Entity\Person\Person;
-use App\Service\Access\Utils as AccessUtils;
-use App\Service\Core\ContactPointUtils;
-use App\Service\MailHub;
-use PHPUnit\Framework\TestCase;
-use Symfony\Bridge\Twig\Mime\TemplatedEmail;
-use Symfony\Component\Mailer\MailerInterface;
-
-class MailHubTest extends TestCase
-{
-    private MailerInterface $mailer;
-    private string $opentalentNoReplyEmailAddress;
-    private ContactPointUtils $contactPointUtils;
-    private AccessUtils $accessUtils;
-
-    public function setUp(): void {
-        $this->mailer = $this->getMockBuilder(MailerInterface::class)->disableOriginalConstructor()->getMock();
-        $this->opentalentNoReplyEmailAddress = 'noreply@opentalent.fr';
-        $this->contactPointUtils = $this->getMockBuilder(ContactPointUtils::class)->disableOriginalConstructor()->getMock();
-        $this->accessUtils = $this->getMockBuilder(AccessUtils::class)->disableOriginalConstructor()->getMock();
-    }
-
-    /**
-     * @see MailHub::sendAutomaticEmailTo()
-     */
-    public function testSendAutomaticEmailTo(): void
-    {
-        $mailerHub = $this->getMockBuilder(MailHub::class)
-            ->setConstructorArgs([$this->mailer, $this->opentalentNoReplyEmailAddress, $this->contactPointUtils, $this->accessUtils])
-            ->setMethodsExcept(['sendAutomaticEmailTo'])
-            ->getMock();
-
-        $contactPoint = $this->getMockBuilder(ContactPoint::class)->disableOriginalConstructor()->getMock();
-        $contactPoint->method('getEmail')->willReturn('mail@domain.net');
-
-        $person = $this->getMockBuilder(Person::class)->disableOriginalConstructor()->getMock();
-        $person->method('getFullName')->willReturn('Don Diego de la Vega');
-        $person->method('getUsername')->willReturn('zorro2000');
-
-        $access = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
-        $access->method('getPerson')->willReturn($person);
-
-        $this->contactPointUtils->expects(self::once())->method('getPersonContactPointPrincipal')->willReturn($contactPoint);
-
-        $this->mailer
-            ->expects(self::once())
-            ->method('send')
-            ->with(self::isInstanceOf(TemplatedEmail::class));
-
-        $mailerHub->sendAutomaticEmailTo($access, 'subject', 'a_template', []);
-    }
-
-    /**
-     * @see MailHub::sendAutomaticEmailTo()
-     */
-    public function testSendAutomaticEmailToButNoAddress(): void
-    {
-        $mailerHub = $this->getMockBuilder(MailHub::class)
-            ->setConstructorArgs([$this->mailer, $this->opentalentNoReplyEmailAddress, $this->contactPointUtils, $this->accessUtils])
-            ->setMethodsExcept(['sendAutomaticEmailTo'])
-            ->getMock();
-
-        $access = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
-
-        $this->contactPointUtils->expects(self::once())->method('getPersonContactPointPrincipal')->willReturn(null);
-
-        $this->expectException(\RuntimeException::class);
-
-        $mailerHub->sendAutomaticEmailTo($access, 'subject', 'a_template', []);
-    }
-
-    /**
-     * @see MailHub::sendAutomaticEmailToAdmin()
-     */
-    public function testSendAutomaticEmailToAdmin(): void
-    {
-        $mailerHub = $this->getMockBuilder(MailHub::class)
-            ->setConstructorArgs([$this->mailer, $this->opentalentNoReplyEmailAddress, $this->contactPointUtils, $this->accessUtils])
-            ->setMethodsExcept(['sendAutomaticEmailToAdmin'])
-            ->getMock();
-
-        $organization = $this->getMockBuilder(Organization::class)->disableOriginalConstructor()->getMock();
-        $admin = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
-
-        $this->accessUtils->expects(self::once())->method('findAdminFor')->with($organization)->willReturn($admin);
-
-        $mailerHub
-            ->expects(self::once())
-            ->method('sendAutomaticEmailTo')
-            ->with($admin, 'subject', 'template', []);
-
-        $mailerHub->sendAutomaticEmailToAdmin($organization, 'subject', 'template', []);
-    }
-
-    /**
-     * @see MailHub::sendAutomaticEmailToAdmin()
-     */
-    public function testSendAutomaticEmailToAdminButNoAdmin(): void
-    {
-        $mailerHub = $this->getMockBuilder(MailHub::class)
-            ->setConstructorArgs([$this->mailer, $this->opentalentNoReplyEmailAddress, $this->contactPointUtils, $this->accessUtils])
-            ->setMethodsExcept(['sendAutomaticEmailToAdmin'])
-            ->getMock();
-
-        $organization = $this->getMockBuilder(Organization::class)->disableOriginalConstructor()->getMock();
-
-        $this->accessUtils
-            ->expects(self::once())
-            ->method('findAdminFor')
-            ->with($organization)
-            ->willReturn(null);
-
-        $this->expectException(\RuntimeException::class);
-
-        $mailerHub->sendAutomaticEmailToAdmin($organization, 'subject', 'template', []);
-    }
-}

+ 116 - 0
tests/Service/Mailer/Builder/SubDomainChangeBuilderTest.php

@@ -0,0 +1,116 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Tests\Service\Mailer\Builder;
+
+use App\Entity\Access\Access;
+use App\Entity\Organization\Organization;
+use App\Entity\Organization\Subdomain;
+use App\Repository\Access\AccessRepository;
+use App\Repository\Organization\OrganizationRepository;
+use App\Repository\Organization\SubdomainRepository;
+use App\Service\Access\Utils as AccessUtils;
+use App\Service\Mailer\Builder\SubDomainChangeBuilder;
+use App\Service\Mailer\Email;
+use App\Service\Mailer\Mailer;
+use App\Service\Mailer\Model\SubdomainChangeModel;
+use Doctrine\ORM\EntityManagerInterface;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Classe SubDomainChangeBuilderTest qui test le service SubDomainChangeBuilder
+ */
+class SubDomainChangeBuilderTest extends TestCase
+{
+    private MockObject|EntityManagerInterface $entityManager;
+    private string $opentalentNoReplyEmailAddress = 'no-reply@opentalent.fr';
+    private MockObject|AccessUtils $accessUtils;
+
+    public function setUp(): void
+    {
+        $this->entityManager = $this->getMockBuilder(EntityManagerInterface::class)->disableOriginalConstructor()->getMock();
+        $this->accessUtils = $this->getMockBuilder(AccessUtils::class)->disableOriginalConstructor()->getMock();
+    }
+
+    /**
+     * subDomainChangeBuilder mock maker
+     * @param string $methodUnderTest
+     * @return Mailer|MockObject
+     */
+    private function makeSubDomainChangeBuilderMock(string $methodUnderTest): SubDomainChangeBuilder | MockObject
+    {
+        $subDomainChangeBuilder = $this->getMockBuilder(SubDomainChangeBuilder::class)
+            ->setConstructorArgs([
+                $this->entityManager,
+                $this->opentalentNoReplyEmailAddress,
+                $this->accessUtils
+            ])
+            ->setMethodsExcept([$methodUnderTest])
+            ->getMock();
+
+        return $subDomainChangeBuilder;
+    }
+
+    /**
+     * @see SubDomainChangeBuilder::build()
+     */
+    public function testBuild()
+    {
+        $subDomainChangeBuilder = $this->makeSubDomainChangeBuilderMock('build');
+
+        $subdomain = $this->getMockBuilder(Subdomain::class)->disableOriginalConstructor()->getMock();
+        $organization = $this->getMockBuilder(Organization::class)->disableOriginalConstructor()->getMock();
+        $organization->method('getName')->willReturn('Mon organisation');
+        $access = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
+
+        $mailerModel = $this->getMockBuilder(SubdomainChangeModel::class)->disableOriginalConstructor()->getMock();
+        $mailerModel->method('getSubdomainId')->willReturn(1);
+        $mailerModel->method('getOrganizationId')->willReturn(1);
+        $mailerModel->method('getSenderId')->willReturn(1);
+
+        $subdomainRepository = $this->getMockBuilder(SubdomainRepository::class)->disableOriginalConstructor()->getMock();
+        $subdomainRepository->expects(self::once())->method('find')->with($mailerModel->getSubdomainId())->willReturn($subdomain);
+        $organizationRepository = $this->getMockBuilder(OrganizationRepository::class)->disableOriginalConstructor()->getMock();
+        $organizationRepository->expects(self::once())->method('find')->with($mailerModel->getOrganizationId())->willReturn($organization);
+        $accessRepository = $this->getMockBuilder(AccessRepository::class)->disableOriginalConstructor()->getMock();
+        $accessRepository->expects(self::once())->method('find')->with($mailerModel->getSenderId())->willReturn($access);
+
+        $this->entityManager
+            ->expects(self::exactly(3))
+            ->method('getRepository')
+            ->withConsecutive([Subdomain::class], [Organization::class], [Access::class])
+            ->willReturnOnConsecutiveCalls($subdomainRepository, $organizationRepository, $accessRepository)
+            ;
+
+        $this->accessUtils
+            ->expects(self::once())
+            ->method('findAdminFor')
+            ->with($organization)
+            ->willReturn($access)
+        ;
+
+        $context = [
+            'access' => $access,
+            'organization' => $organization,
+            'subdomain' => $subdomain,
+            'url' => $mailerModel->getUrl()
+        ];
+        $content = 'contenu';
+        $subDomainChangeBuilder
+            ->expects(self::once())
+            ->method('render')
+            ->with('subdomain', $context)
+            ->willReturn($content)
+        ;
+
+        $emailsCollection = $subDomainChangeBuilder->build($mailerModel);
+
+        $this->assertCount(1, $emailsCollection);
+        $email = $emailsCollection->first();
+        $this->assertInstanceOf(Email::class, $email);
+        $this->assertEquals('contenu', $email->getContent());
+        $this->assertEquals($this->opentalentNoReplyEmailAddress, $email->getFrom());
+        $this->assertEquals($organization->getName(), $email->getNameFrom());
+    }
+}

+ 37 - 1
tests/Service/Mailer/MailerTest.php

@@ -171,6 +171,12 @@ class MailerTest extends TestCase
             ->with($email, $symfonyEmail->getTo())
         ;
 
+        $mailer
+            ->expects(self::once())
+            ->method('setSymfonyEmailContent')
+            ->with($symfonyEmail, $email)
+        ;
+
         $mailer
             ->expects(self::once())
             ->method('addHeaders')
@@ -215,6 +221,7 @@ class MailerTest extends TestCase
         $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
         $email->method('getEmailEntity')->willReturn($emailEntity);
         $email->method('getFrom')->willReturn('foo.bar@opentalent.fr');
+        $email->method('getNameFrom')->willReturn('Bill');
 
         $reportEmail = $mailer->createReportEmail(new ArrayCollection([$email]));
 
@@ -307,6 +314,13 @@ class MailerTest extends TestCase
         $arrayReduced = $mailer->reduceEmailsCollectionInPreproduction(new ArrayCollection($array));
 
         $this->assertCount(20, $arrayReduced->toArray());
+
+        $array = [];
+        for($i=0; $i<=9; $i++){
+            $array[] = $i;
+        }
+        $arrayReduced = $mailer->reduceEmailsCollectionInPreproduction(new ArrayCollection($array));
+        $this->assertCount(10, $arrayReduced->toArray());
     }
 
     /**
@@ -355,17 +369,39 @@ class MailerTest extends TestCase
 
         $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
         $email->method('getFrom')->willReturn('foo.bar@opentalent.fr');
+        $email->method('getNameFrom')->willReturn('Ben Yolo');
         $email->method('getEmailEntity')->willReturn($emailEntity);
         $email->method('getContent')->willReturn('contenu');
 
-        $addressMailFrom = new Address($email->getFrom(), $email->getEmailEntity()->getAuthor()->getPerson()->getFullName());
+        $addressMailFrom = new Address($email->getFrom(), $email->getNameFrom());
         $symfonyMail = $mailer->createSymfonyEmail($email);
         $this->assertInstanceOf(SymfonyEmail::class, $symfonyMail);
         $this->assertEquals($symfonyMail->getFrom(), [$addressMailFrom]);
         $this->assertEquals($symfonyMail->getReplyTo(), [$addressMailFrom]);
         $this->assertEquals($symfonyMail->getReturnPath(), Address::create("mail.report@opentalent.fr"));
         $this->assertEquals($symfonyMail->getSubject(), $emailEntity->getAbout());
+    }
+
+    /**
+     * @see Mailer::setSymfonyEmailContent()
+     */
+    public function testSetSymfonyEmailContent(){
+        $mailer = $this->makeMailerMock('setSymfonyEmailContent');
+
+        $email = $this->getMockBuilder(Email::class)->disableOriginalConstructor()->getMock();
+        $email->method('getContent')->willReturn('contenu');
+
+        $this->stringsUtils
+            ->expects(self::once())
+            ->method('convertHtmlToText')
+            ->willReturn($email->getContent());
+
+        $symfonyMail = new SymfonyEmail();
+
+        $mailer->setSymfonyEmailContent($symfonyMail, $email);
+
         $this->assertEquals($symfonyMail->getHtmlBody(), $email->getContent());
+        $this->assertEquals($symfonyMail->getTextBody(), $email->getContent());
     }
 
     /**

+ 45 - 26
tests/Service/OnChange/Organization/OnSubdomainChangeTest.php

@@ -5,9 +5,9 @@ namespace App\Tests\Service\OnChange\Organization;
 use App\Entity\Access\Access;
 use App\Entity\Organization\Organization;
 use App\Entity\Organization\Subdomain;
+use App\Message\Command\MailerCommand;
 use App\Message\Command\Typo3\Typo3UpdateCommand;
-use App\Service\Access\Utils as AccessUtils;
-use App\Service\MailHub;
+use App\Service\Mailer\Model\SubdomainChangeModel;
 use App\Service\OnChange\OnChangeContext;
 use App\Service\OnChange\Organization\OnSubdomainChange;
 use App\Service\Organization\Utils as OrganizationUtils;
@@ -17,27 +17,26 @@ use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Messenger\Envelope;
 use Symfony\Component\Messenger\MessageBusInterface;
+use Symfony\Component\Security\Core\Security;
 
 class OnSubdomainChangeTest extends TestCase
 {
     private OrganizationUtils $organizationUtils;
-    private AccessUtils $accessUtils;
-    private MailHub $mailHub;
+    private Security $security;
     private BindFileService $bindFileService;
     private MessageBusInterface $messageBus;
 
     public function setUp():void
     {
         $this->organizationUtils = $this->getMockBuilder(OrganizationUtils::class)->disableOriginalConstructor()->getMock();
-        $this->accessUtils = $this->getMockBuilder(AccessUtils::class)->disableOriginalConstructor()->getMock();
-        $this->mailHub = $this->getMockBuilder(MailHub::class)->disableOriginalConstructor()->getMock();
+        $this->security = $this->getMockBuilder(Security::class)->disableOriginalConstructor()->getMock();
         $this->bindFileService = $this->getMockBuilder(BindFileService::class)->disableOriginalConstructor()->getMock();
         $this->messageBus = $this->getMockBuilder(MessageBusInterface::class)->disableOriginalConstructor()->getMock();
     }
 
     private function makeOnSubdomainChangeMock(string $methodName): MockObject | OnSubdomainChange {
         return $this->getMockBuilder(OnSubdomainChange::class)
-            ->setConstructorArgs([$this->organizationUtils, $this->accessUtils, $this->mailHub, $this->bindFileService, $this->messageBus])
+            ->setConstructorArgs([$this->organizationUtils, $this->bindFileService, $this->messageBus, $this->security])
             ->setMethodsExcept([$methodName])
             ->getMock();
     }
@@ -221,15 +220,32 @@ class OnSubdomainChangeTest extends TestCase
     public function testSendEmailAfterSubdomainChange(): void {
         $onSubdomainChange = $this->makeOnSubdomainChangeMock('sendEmailAfterSubdomainChange');
 
-        $admin = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
+        $subdomain = $this->getMockBuilder(Subdomain::class)->disableOriginalConstructor()->getMock();
+        $subdomainChangeModel = $this->getMockBuilder(SubdomainChangeModel::class)->disableOriginalConstructor()->getMock();
 
-        $organization = $this->getMockBuilder(Organization::class)->disableOriginalConstructor()->getMock();
+        $onSubdomainChange
+            ->expects(self::once())
+            ->method('getMailModel')
+            ->with($subdomain)
+            ->willReturn($subdomainChangeModel);
 
-        $subdomain = $this->getMockBuilder(Subdomain::class)->disableOriginalConstructor()->getMock();
-        $subdomain->expects(self::once())->method('getSubdomain')->willReturn('mysubdomain');
-        $subdomain->expects(self::exactly(3))->method('getOrganization')->willReturn($organization);
+        $this->messageBus
+            ->expects(self::once())
+            ->method('dispatch')
+            ->with(self::isInstanceOf(MailerCommand::class))
+            ->willReturn(new Envelope(new MailerCommand($subdomainChangeModel)));
+
+        $onSubdomainChange->sendEmailAfterSubdomainChange($subdomain);
+    }
 
-        $this->accessUtils->expects(self::once())->method('findAdminFor')->with($organization)->willReturn($admin);
+    /**
+     * @see OnSubdomainChange::getMailModel()
+     */
+    public function testGetMailModel(): void {
+        $onSubdomainChange = $this->makeOnSubdomainChangeMock('getMailModel');
+
+        $organization = $this->getMockBuilder(Organization::class)->disableOriginalConstructor()->getMock();
+        $organization->expects(self::once())->method('getId')->willReturn(1);
 
         $this->organizationUtils
             ->expects(self::once())
@@ -237,20 +253,23 @@ class OnSubdomainChangeTest extends TestCase
             ->with($organization)
             ->willReturn('mysubdomain.opentalent.fr');
 
-        $this->mailHub
+        $access = $this->getMockBuilder(Access::class)->disableOriginalConstructor()->getMock();
+        $access->expects(self::once())->method('getId')->willReturn(1);
+        $this->security
             ->expects(self::once())
-            ->method('sendAutomaticEmailToAdmin')
-            ->with(
-                $organization,
-                'Nouveau sous domaine: mysubdomain',
-                'subdomain',
-                [
-                    'access' => $admin,
-                    'subdomain' => $subdomain,
-                    'url' => 'mysubdomain.opentalent.fr'
-                ]
-            );
+            ->method('getUser')
+            ->willReturn($access);
 
-        $onSubdomainChange->sendEmailAfterSubdomainChange($subdomain);
+        $subdomain = $this->getMockBuilder(Subdomain::class)->disableOriginalConstructor()->getMock();
+        $subdomain->expects(self::exactly(2))->method('getOrganization')->willReturn($organization);
+        $subdomain->expects(self::once())->method('getId')->willReturn(1);
+
+        $mailerModel = $onSubdomainChange->getMailModel($subdomain);
+
+        $this->assertInstanceOf(SubdomainChangeModel::class, $mailerModel);
+        $this->assertEquals($mailerModel->getSenderId(), 1);
+        $this->assertEquals($mailerModel->getOrganizationId(), 1);
+        $this->assertEquals($mailerModel->getSubdomainId(), 1);
+        $this->assertEquals($mailerModel->getUrl(), 'mysubdomain.opentalent.fr');
     }
 }

+ 7 - 0
tests/Service/Utils/StringsUtilsTest.php

@@ -22,4 +22,11 @@ class StringsUtilsTest extends TestCase
         $this->assertEquals("foo-bar", StringsUtils::camelToSnake("FooBar", '-'));
         $this->assertEquals("foo_bar", StringsUtils::camelToSnake("fooBar"));
     }
+
+    /**
+     * @see StringsUtils::convertHtmlToText()
+     */
+    public function testConvertHtmlToText(): void {
+        $this->assertEquals("contenu", (new StringsUtils())->convertHtmlToText("<p>contenu</p>"));
+    }
 }