<?php
namespace App\Controller;
use App\Entity\User;
use App\Enums\MailerLiteGroupEnum;
use App\Event\FilterUserResponseEvent;
use App\Event\FormEvent;
use App\Event\FOSUserEvents;
use App\Event\GetResponseUserEvent;
use App\Form\RegistrationFormType;
use App\Repository\UserRepository;
use App\Security\EmailVerifier;
use App\Services\SendGrid\SendRegistrationLinkSendGridService;
use App\Services\UserService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
use SymfonyCasts\Bundle\VerifyEmail\VerifyEmailHelperInterface;
use Throwable;
class RegistrationController extends AbstractController
{
private EmailVerifier $emailVerifier;
private EntityManagerInterface $objectManager;
private EventDispatcherInterface $eventDispatcher;
private LoggerInterface $logger;
private UserService $userService;
private TranslatorInterface $translator;
private UserRepository $userRepository;
private SendRegistrationLinkSendGridService $sendRegistrationLinkSendGridService;
private VerifyEmailHelperInterface $verifyEmailHelper;
/**
* @param EmailVerifier $emailVerifier
* @param EntityManagerInterface $objectManager
* @param EventDispatcherInterface $eventDispatcher
* @param LoggerInterface $logger
* @param UserService $userService
* @param TranslatorInterface $translator
* @param UserRepository $userRepository
* @param SendRegistrationLinkSendGridService $sendRegistrationLinkSendGridService
* @param VerifyEmailHelperInterface $verifyEmailHelper
*/
public function __construct(
EmailVerifier $emailVerifier,
EntityManagerInterface $objectManager,
EventDispatcherInterface $eventDispatcher,
LoggerInterface $logger,
UserService $userService,
TranslatorInterface $translator,
UserRepository $userRepository,
SendRegistrationLinkSendGridService $sendRegistrationLinkSendGridService,
VerifyEmailHelperInterface $verifyEmailHelper
) {
$this->emailVerifier = $emailVerifier;
$this->objectManager = $objectManager;
$this->eventDispatcher = $eventDispatcher;
$this->logger = $logger;
$this->userService = $userService;
$this->translator = $translator;
$this->userRepository = $userRepository;
$this->sendRegistrationLinkSendGridService = $sendRegistrationLinkSendGridService;
$this->verifyEmailHelper = $verifyEmailHelper;
}
/**
* @param Request $request
* @return Response
* @throws Throwable
*/
#[Route('/register', name: 'register')]
public function register(Request $request): Response
{
$user = new User();
$user->setEnabled(true);
$event = new GetResponseUserEvent($user, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_INITIALIZE);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$event = new FormEvent($form, $request);
if ($form->isValid()) {
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_SUCCESS);
$user->setEnabled(false);
$this->userService->updateUser($user, $form);
$this->objectManager->persist($user);
$this->objectManager->flush();
$this->userService->subscribeUser($user, MailerLiteGroupEnum::getRegistrationGroup());
$this->logger->info(sprintf("New user registration: %s", $user));
$signatureComponents = $this->verifyEmailHelper->generateSignature(
'app_verify_email',
(string)$user->getId(),
$user->getEmail(),
['id' => $user->getId()]
);
$params = [
'link' => $signatureComponents->getSignedUrl()
];
$this->sendRegistrationLinkSendGridService->sendMail($user->getEmail(), $params);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('login');
$response = new RedirectResponse($url);
}
$this->eventDispatcher->dispatch(
new FilterUserResponseEvent($user, $request, $response),
FOSUserEvents::REGISTRATION_COMPLETED
);
return $response;
}
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_FAILURE);
if (null !== $response = $event->getResponse()) {
return $response;
}
}
return $this->render('registration/register.html.twig', [
'form' => $form->createView(),
]);
}
/**
* @param Request $request
* @return Response
*/
#[Route('/verify/email', name: 'app_verify_email')]
public function verifyUserEmail(Request $request): Response
{
$id = $request->get('id'); // retrieve the user id from the url
// Verify the user id exists and is not null
if (null === $id) {
return $this->redirectToRoute('login');
}
$user = $this->userRepository->find($id);
// Ensure the user exists in persistence
if (null === $user) {
return $this->redirectToRoute('login');
}
// validate email confirmation link, sets User::isVerified=true and persists
try {
$this->emailVerifier->handleEmailConfirmation($request, $user);
} catch (VerifyEmailExceptionInterface $exception) {
$this->addFlash(
'verify_email_error',
$this->translator->trans($exception->getReason(), [], 'VerifyEmailBundle')
);
return $this->redirectToRoute('register');
}
// @TODO Change the redirect on success and handle or remove the flash message in your templates
$this->addFlash('success', 'Vaša e-mail adresa je verifikovana.');
return $this->redirectToRoute('login');
}
}