From d283a20d6f94885140ebd27870f0bc5ac4d7c6f1 Mon Sep 17 00:00:00 2001
From: Camille Simiand <camille.simiand@tetras-libre.fr>
Date: Thu, 10 Mar 2022 11:16:04 +0100
Subject: [PATCH] Refacto retrieving email addresses

---
 src/Controller/UserController.php             | 13 ++-------
 src/Form/EditUserProfileFormType.php          | 28 ++++++++++++++++---
 .../PendingEmailAddressRepository.php         | 21 ++++----------
 src/Repository/UserRepository.php             | 20 ++++---------
 4 files changed, 38 insertions(+), 44 deletions(-)

diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php
index b7c5bf8..89f7eca 100755
--- a/src/Controller/UserController.php
+++ b/src/Controller/UserController.php
@@ -7,7 +7,6 @@ use App\Entity\User;
 use App\Form\EditPasswordFormType;
 use App\Form\EditUserProfileFormType;
 use App\Repository\PendingEmailAddressRepository;
-use App\Repository\UserRepository;
 use Doctrine\ORM\EntityManagerInterface;
 use Symfony\Bridge\Twig\Mime\TemplatedEmail;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@@ -24,8 +23,7 @@ class UserController extends AbstractController
     public function __construct(
         private EntityManagerInterface $entity_manager,
         private TranslatorInterface $translator,
-        private PendingEmailAddressRepository $pending_email_address_repository,
-        private UserRepository $user_repository
+        private PendingEmailAddressRepository $pending_email_address_repository
     ) {
     }
 
@@ -61,17 +59,10 @@ class UserController extends AbstractController
             $this->entity_manager->remove($last_pending_email_address);
         }
 
-        $users_emails = $this->user_repository->getAllEmails();
-        $pending_email_addresses = $this->pending_email_address_repository->getAllEmails();
-
         $form = $this->createForm(
             EditUserProfileFormType::class,
             $current_user,
-            [
-                'current_email_address' => $current_user->getEmail(),
-                'users_emails' => $users_emails,
-                'pending_emails' => $pending_email_addresses
-            ]
+            ['current_email_address' => $current_user->getEmail()]
         );
         $form->handleRequest($request);
 
diff --git a/src/Form/EditUserProfileFormType.php b/src/Form/EditUserProfileFormType.php
index 0f0a03b..a13cd5b 100755
--- a/src/Form/EditUserProfileFormType.php
+++ b/src/Form/EditUserProfileFormType.php
@@ -3,6 +3,8 @@
 namespace App\Form;
 
 use App\Entity\User;
+use App\Repository\PendingEmailAddressRepository;
+use App\Repository\UserRepository;
 use Symfony\Component\Form\AbstractType;
 use Symfony\Component\Form\Extension\Core\Type\EmailType;
 use Symfony\Component\Form\Extension\Core\Type\PasswordType;
@@ -17,8 +19,22 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
 
 class EditUserProfileFormType extends AbstractType
 {
+    private UserRepository $user_repository;
+    private PendingEmailAddressRepository $pending_email_address_repository;
+
+    public function __construct(
+        UserRepository $user_repository,
+        PendingEmailAddressRepository $pending_email_address_repository
+    ) {
+        $this->user_repository = $user_repository;
+        $this->pending_email_address_repository = $pending_email_address_repository;
+    }
+
     public function buildForm(FormBuilderInterface $builder, array $options): void
     {
+        $user_repository = $this->user_repository;
+        $pending_email_address_repository = $this->pending_email_address_repository;
+
         $builder
             ->add(
                 'firstName',
@@ -48,13 +64,17 @@ class EditUserProfileFormType extends AbstractType
                         new Assert\Email(),
                         new Assert\Callback(
                             ['callback' => static function (
-                                ?string $value,
+                                string $value,
                                 ExecutionContextInterface $context
-                            ) use ($options) {
+                            ) use (
+                                $options,
+                                $user_repository,
+                                $pending_email_address_repository
+                            ) {
                                 if (
                                     $value !== $options['current_email_address'] &&
-                                    (in_array($value, $options['users_emails']) ||
-                                        in_array($value, $options['pending_emails']))
+                                    ($user_repository->emailExists($value) ||
+                                        $pending_email_address_repository->emailIsReserved($value))
                                 ) {
                                     $context
                                         ->buildViolation(message: 'user.email.unique')
diff --git a/src/Repository/PendingEmailAddressRepository.php b/src/Repository/PendingEmailAddressRepository.php
index dbc3379..19e82ea 100644
--- a/src/Repository/PendingEmailAddressRepository.php
+++ b/src/Repository/PendingEmailAddressRepository.php
@@ -7,8 +7,6 @@ use App\Entity\User;
 use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 use Doctrine\Persistence\ManagerRegistry;
 
-use function PHPUnit\Framework\assertInstanceOf;
-
 /**
  * @method PendingEmailAddress|null find($id, $lockMode = null, $lockVersion = null)
  * @method PendingEmailAddress|null findOneBy(array $criteria, array $orderBy = null)
@@ -33,19 +31,12 @@ class PendingEmailAddressRepository extends ServiceEntityRepository
             ;
     }
 
-    /**
-     * @return string[]
-     */
-    public function getAllEmails(): array
+    public function emailIsReserved(string $email): bool
     {
-        $all_pending_email_addresses = $this->findAll();
-        $all_emails = [];
-
-        foreach ($all_pending_email_addresses as $pending_email_address) {
-            assertInstanceOf(PendingEmailAddress::class, $pending_email_address);
-            $all_emails[] = $pending_email_address->getEmail();
-        }
-
-        return $all_emails;
+        return $this->createQueryBuilder('p')
+                ->andWhere('p.email = :email')
+                ->setParameter('email', $email)
+                ->getQuery()
+                ->getOneOrNullResult() !== null;
     }
 }
diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php
index 476ef81..8996ca4 100755
--- a/src/Repository/UserRepository.php
+++ b/src/Repository/UserRepository.php
@@ -4,8 +4,6 @@ namespace App\Repository;
 
 use App\Entity\User;
 use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
-use Doctrine\DBAL\Exception;
-use Doctrine\DBAL\Exception\DatabaseObjectNotFoundException;
 use Doctrine\Persistence\ManagerRegistry;
 use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
 use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
@@ -73,18 +71,12 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
             ->getResult();
     }
 
-    /**
-     * @return string[]
-     */
-    public function getAllEmails(): array
+    public function emailExists(string $email): bool
     {
-        $all_users = $this->findAll();
-        $all_emails = [];
-
-        foreach ($all_users as $user) {
-            $all_emails[] = $user->getEmail();
-        }
-
-        return $all_emails;
+        return $this->createQueryBuilder('r')
+                ->andWhere('r.email = :email')
+                ->setParameter('email', $email)
+                ->getQuery()
+                ->getOneOrNullResult() !== null;
     }
 }
-- 
GitLab