<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\RegistrationFormType;
use App\Mailer\UserMailer;
use App\Security\AppMainAuthenticator;
use App\Security\EmailVerifier;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
class RegistrationController extends AbstractController
{
public function __construct(
private EmailVerifier $emailVerifier,
private EntityManagerInterface $entityManager,
private UserMailer $userMailer
) {
}
#[Route('/register', name: 'app_register')]
public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher): Response
{
if ($this->getUser()) {
return $this->redirectToRoute('app_home');
}
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// encode the plain password
$user->setPassword(
$userPasswordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
)
);
$informationForModeration = [];
foreach (RegistrationFormType::FIELD_EQUIPMENT_NAMES as $field) {
$informationForModeration[$field] = $form->get($field)->getData();
}
$user
->setRoles([User::ROLE_CLIENT])
->setInformationForModeration($informationForModeration)
// if user sign up from form register
// Don't need to force user changes password
->setForceChangePassword(false);
$this->entityManager->persist($user);
$this->entityManager->flush();
// generate a signed url and email it to the user
$isSentEmail = $this->userMailer->sendVerifyEmail($user, 'registration');
if ($isSentEmail) {
$user->setEmailSentAt(new \DateTimeImmutable());
$this->entityManager->persist($user);
$this->entityManager->flush();
$this->addFlash('success', 'User.Message.EmailValidation');
}
return $this->redirectToRoute(AppMainAuthenticator::LOGIN_ROUTE);
}
return $this->render('registration/register.html.twig', [
'registrationForm' => $form->createView(),
]);
}
#[Route('/verify/email', name: 'app_verify_email')]
public function verifyUserEmail(Request $request, TranslatorInterface $translator): Response
{
$path = $request->query->get('path');
if ($this->getUser()) {
return $this->redirectToRoute('app_home');
}
$id = $request->get('id');
// Verify the user id exists and is not null
if (null == $id) {
return $this->redirectToRoute('app_home');
}
$user = $this->entityManager->getRepository(User::class)->find($id);
// Ensure the user exists in persistence
if (null === $user) {
return $this->redirectToRoute('app_home');
}
// validate email confirmation link, sets User::isVerified=true and persists
try {
$this->emailVerifier->handleEmailConfirmation($request, $user);
} catch (VerifyEmailExceptionInterface $exception) {
$this->addFlash('danger', $translator->trans($exception->getReason(), [], 'VerifyEmailBundle'));
$request->getSession()->set('non_verified_email', $user->getEmail());
return $this->redirectToRoute('app_verify_resend_email');
}
$messageEnd = 'employeeCompany' === $path ? 'EmployeeCompany' : 'Default';
$this->addFlash('success', 'User.Message.EmailIsVerified.'.$messageEnd);
return $this->redirectToRoute(AppMainAuthenticator::LOGIN_ROUTE);
}
#[Route('/verify/resend', name: 'app_verify_resend_email', methods: ['GET', 'POST'])]
public function resendVerifyEmail(Request $request)
{
if ($this->getUser()) {
return $this->redirectToRoute('app_home');
}
if ('POST' === $request->getMethod()) {
$userEmail = $request->getSession()->get('non_verified_email');
if ($userEmail) {
$user = $this->entityManager->getRepository(User::class)->findOneBy([
'email' => $userEmail,
]);
// generate a signed url and email it to the user
$isSentEmail = $this->userMailer->sendVerifyEmail($user, 'registration');
if ($isSentEmail) {
$user->setEmailSentAt(new \DateTimeImmutable());
$this->entityManager->persist($user);
$this->entityManager->flush();
$this->addFlash('success', 'User.Message.EmailValidation');
}
return $this->redirectToRoute(AppMainAuthenticator::LOGIN_ROUTE);
}
}
return $this->render('registration/resend_verify_email.html.twig');
}
}