diff --git a/src/Controller/Security/AccountCreateController.php b/src/Controller/Security/AccountCreateController.php index 371708a..91a85b8 100644 --- a/src/Controller/Security/AccountCreateController.php +++ b/src/Controller/Security/AccountCreateController.php @@ -21,12 +21,15 @@ use App\MessageBus\CommandBus; use App\MessageBus\QueryBus; use App\MessageHandler\Command\Security\AccountCreateStep1CommandHandler; use App\Repository\ConfigurationRepository; +use libphonenumber\PhoneNumber; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\SecurityBundle\Security; +use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Contracts\Translation\TranslatorInterface; /** * @see AccountCreateActionStep1Test @@ -44,6 +47,7 @@ final class AccountCreateController extends AbstractController private readonly CommandBus $commandBus, private readonly Security $security, private readonly ConfigurationRepository $configurationRepository, + private readonly TranslatorInterface $translator, ) { $this->i18nPrefix = $this->getI18nPrefix(); } @@ -103,40 +107,55 @@ final class AccountCreateController extends AbstractController $configuration = $this->configurationRepository->getInstanceConfigurationOrCreate(); // nominal case: user found and token not expired $form = $this->createForm(AccountCreateStep2FormType::class, $user->setStep2Defaults())->handleRequest($request); - if ($form->isSubmitted() && $form->isValid()) { - /** @var User $user */ - $user = $form->getData(); - $user->setType(UserType::USER); - $this->commandBus->dispatch(new AccountCreateStep2Command($user)); - $this->security->login($user); // auto-log the user + if ($form->isSubmitted()) { + $phone = $form->get('phone')->getData() ?? ''; - // If user has pending invitations then redirect them to the first group - // found without doing the confirmation stuff, it must be done on the - // page group. - $group = $user->getMyGroupsAsInvited()->first(); - if ($group !== false) { - // If platform needs payment, redirect to payment - if ($configuration->getPaidMembership()) { - $successMessage = $this->i18nPrefix.'.step2.with_invitation.global_paid_membership.flash.success'; + if (!$phone instanceof PhoneNumber || $phone->getNationalNumber() === '') { + $form->get('phone')->addError( + new FormError($this->translator->trans('account_create.phone.empty.error', [], 'validators')) + ); + } + + if ($phone instanceof PhoneNumber && \strlen($phone->getNationalNumber() ?? '') < 8) { + $form->get('phone')->addError( + new FormError($this->translator->trans('account_create.phone.short.error', [], 'validators')) + ); + } + if ($form->isValid()) { + /** @var User $user */ + $user = $form->getData(); + $user->setType(UserType::USER); + $this->commandBus->dispatch(new AccountCreateStep2Command($user)); + $this->security->login($user); // auto-log the user + + // If user has pending invitations then redirect them to the first group + // found without doing the confirmation stuff, it must be done on the + // page group. + $group = $user->getMyGroupsAsInvited()->first(); + if ($group !== false) { + // If platform needs payment, redirect to payment + if ($configuration->getPaidMembership()) { + $successMessage = $this->i18nPrefix.'.step2.with_invitation.global_paid_membership.flash.success'; + $this->addFlashSuccess($successMessage); + + return $this->redirectToRoute('redirect_to_payment'); + } + $successMessage = $this->i18nPrefix.'.step2.with_invitation.flash.success'; $this->addFlashSuccess($successMessage); - return $this->redirectToRoute('redirect_to_payment'); + return $this->redirectToRoute('app_group_show_logged', $group->getRoutingParameters()); } - $successMessage = $this->i18nPrefix.'.step2.with_invitation.flash.success'; + + if ($configuration->getPaidMembership()) { + $successMessage = $this->i18nPrefix.'.step2.global_paid_membership.flash.success'; + } else { + $successMessage = $this->i18nPrefix.'.step2.flash.success'; + } + // otherwise go to the address form $this->addFlashSuccess($successMessage); - return $this->redirectToRoute('app_group_show_logged', $group->getRoutingParameters()); + return $this->redirectToRoute(MyAccountAction::ROUTE); } - - if ($configuration->getPaidMembership()) { - $successMessage = $this->i18nPrefix.'.step2.global_paid_membership.flash.success'; - } else { - $successMessage = $this->i18nPrefix.'.step2.flash.success'; - } - // otherwise go to the address form - $this->addFlashSuccess($successMessage); - - return $this->redirectToRoute(MyAccountAction::ROUTE); } return $this->render('pages/register/step2.html.twig', compact('form', 'user')); diff --git a/src/Controller/User/Account/EditProfileAction.php b/src/Controller/User/Account/EditProfileAction.php index 9380580..8a0613a 100644 --- a/src/Controller/User/Account/EditProfileAction.php +++ b/src/Controller/User/Account/EditProfileAction.php @@ -13,7 +13,9 @@ use App\Form\Type\User\EditProfileFormType; use App\Repository\UserRepository; use App\Tests\Functional\Controller\User\Account\EditProfileActionTest; use Doctrine\ORM\EntityManagerInterface; +use libphonenumber\PhoneNumber; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -21,6 +23,7 @@ use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter; use Symfony\Component\Security\Http\Attribute\CurrentUser; use Symfony\Component\Security\Http\Attribute\IsGranted; +use Symfony\Contracts\Translation\TranslatorInterface; /** * @see EditProfileActionTest @@ -34,6 +37,7 @@ final class EditProfileAction extends AbstractController private readonly UserRepository $userRepository, private readonly UserManager $userManager, private readonly EntityManagerInterface $entityManager, + private readonly TranslatorInterface $translator, ) { } @@ -45,14 +49,30 @@ final class EditProfileAction extends AbstractController public function __invoke(Request $request, #[CurrentUser] User $user): Response { $form = $this->createForm(EditProfileFormType::class, $user)->handleRequest($request); - if ($form->isSubmitted() && $form->isValid()) { - /** @var UploadedFile|null $avatar */ - $avatar = $form->get('avatar')->getData(); - $this->userManager->upload($avatar, $user); - $this->userRepository->save($user, true); - $this->addFlashSuccess($this->getI18nPrefix().'.flash.success'); + if ($form->isSubmitted()) { + $phone = $form->get('phone')->getData() ?? ''; - return $this->redirectToRoute(MyAccountAction::ROUTE); + if (!$phone instanceof PhoneNumber || $phone->getNationalNumber() === '') { + $form->get('phone')->addError( + new FormError($this->translator->trans('account_create.phone.empty.error', [], 'validators')) + ); + } + + if ($phone instanceof PhoneNumber && \strlen($phone->getNationalNumber() ?? '') < 8) { + $form->get('phone')->addError( + new FormError($this->translator->trans('account_create.phone.short.error', [], 'validators')) + ); + } + + if ($form->isValid()) { + /** @var UploadedFile|null $avatar */ + $avatar = $form->get('avatar')->getData(); + $this->userManager->upload($avatar, $user); + $this->userRepository->save($user, true); + $this->addFlashSuccess($this->getI18nPrefix().'.flash.success'); + + return $this->redirectToRoute(MyAccountAction::ROUTE); + } } // In case of error, we must reload the original firstname (to display it in navbar) diff --git a/tests/Functional/Controller/User/Account/EditProfileActionTest.php b/tests/Functional/Controller/User/Account/EditProfileActionTest.php index fcae901..518a54a 100644 --- a/tests/Functional/Controller/User/Account/EditProfileActionTest.php +++ b/tests/Functional/Controller/User/Account/EditProfileActionTest.php @@ -44,7 +44,7 @@ final class EditProfileActionTest extends WebTestCase $form->getName().'[category]' => TestReference::CATEGORY_OBJECT_1, $form->getName().'[description]' => 'description test', $form->getName().'[phone][country]' => 'FR', - $form->getName().'[phone][number]' => '', + $form->getName().'[phone][number]' => '634563424', $form->getName().'[smsNotifications]' => false, ]); @@ -53,7 +53,7 @@ final class EditProfileActionTest extends WebTestCase /** @var User $editedUser */ $editedUser = $repo->find(TestReference::USER_16); - self::assertNull($editedUser->getPhoneNumber()); + self::assertNotNull($editedUser->getPhoneNumber()); self::assertResponseRedirects(); $client->followRedirect(); diff --git a/translations/security/account_create/validators.fr.xlf b/translations/security/account_create/validators.fr.xlf index 5229d73..1c12cf8 100644 --- a/translations/security/account_create/validators.fr.xlf +++ b/translations/security/account_create/validators.fr.xlf @@ -26,6 +26,16 @@ Le nom du lieu est obligatoire + + account_create.phone.empty.error + Le numéro de téléphone est obligatoire + + + + account_create.phone.short.error + Veuillez indiquer un numéro de téléphone valide + +