<?php
namespace App\Controller;
use App\Entity\PrivateUser;
use App\Entity\ProUser;
use App\Entity\User;
use App\Form\Serializer\FormErrorsSerializer;
use App\Form\Type\Localized\PortugalRegistrationFormType;
use App\Form\Type\Localized\SpainRegistrationFormType;
use App\Form\Type\PrivateRegistrationStep2FormType;
use App\Form\Type\ProRegistrationStep1FormType;
use App\Form\Type\ProRegistrationStep2FormType;
use App\Form\Type\ProRegistrationStep3FormType;
use App\Mailer\TranslatableMailer;
use App\Service\PrivateUserRegistrationSession;
use App\Service\ProUserRegistrationSession;
use App\Twig\Extension\CountryExtension;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\Form\Factory\FactoryInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface as ObsoleteEventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class RegistrationController extends AbstractController
{
public function __construct(
protected EventDispatcherInterface $eventDispatcher,
ObsoleteEventDispatcherInterface $obsoleteEventDispatcher,
protected FactoryInterface $formFactory,
protected UserManagerInterface $userManager,
protected TokenStorageInterface $tokenStorage,
protected FormErrorsSerializer $formErrorsSerializer,
protected TranslatableMailer $translatableMailer,
protected TranslatorInterface $translator,
protected LoggerInterface $logger)
{
}
public function registerAction(Request $request): Response
{
$user = $this->userManager->createUser();
$user->setEnabled(true);
$event = new GetResponseUserEvent($user, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_INITIALIZE);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $this->formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_SUCCESS);
$this->userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $response), FOSUserEvents::REGISTRATION_COMPLETED);
return $response;
}
$event = new FormEvent($form, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_FAILURE);
if (null !== $response = $event->getResponse()) {
return $response;
}
}
return $this->render('@FOSUser/Registration/register.html.twig', [
'form' => $form->createView(),
]);
}
/**
* The users from Portugal and Spain have to perform another step to register.
*
* @see RegistrationController::registerPortugalAction
* @see RegistrationController::registerSpainAction()
*/
public function registerStepAction(
Request $request,
RouterInterface $router,
PrivateUserRegistrationSession $userRegistrationSession,
int $step
): Response {
if ($step < 1 || $step > 4) {
throw new NotFoundHttpException();
}
if (2 === $step) {
/** @var PrivateUser $user */
$user = $this->userManager->createUser(PrivateUser::class);
$form = $this->createForm(
PrivateRegistrationStep2FormType::class,
$user
);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var PrivateUser $user */
$user = $form->getData();
// special cases: registration for Spain or Portugal require more data,
// users are sent to another form
if (
in_array(strtolower((string) $user->getCountry()), [CountryExtension::COUNTRY_PORTUGAL, CountryExtension::COUNTRY_SPAIN], true)
) {
// create or overwrite the data in session, e.g. if the user choose the wrong country
// and get back on this step
$userRegistrationSession->save($user);
// redirect the user to the corresponding country
if (strtoupper(CountryExtension::COUNTRY_PORTUGAL) === $user->getCountry()) {
$path = $router->generate('fos_user_registration_register_portugal');
} else {
$path = $router->generate('fos_user_registration_register_spain');
}
return new RedirectResponse($path);
}
$event = new FormEvent($form, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_SUCCESS);
$this->userManager->updateUser($user);
/** @var RedirectResponse $response */
$response = $event->getResponse();
$this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $response), FOSUserEvents::REGISTRATION_COMPLETED);
return $response;
}
return $this->render('frontend/registration/step_2.html.twig', [
'form' => $form->createView(),
]);
} elseif (3 === $step) {
return $this->render('frontend/registration/step_3.html.twig');
} elseif (4 === $step) {
return $this->render('frontend/registration/step_4.html.twig');
}
return $this->render('frontend/registration/step_1.html.twig');
}
public function registerProAction(Request $request, int $step)
{
if ($step < 1 || $step > 3) {
throw new NotFoundHttpException();
}
$registrationManager = new ProUserRegistrationSession($request->getSession(), $this->userManager, $this->logger);
$user = $registrationManager->load();
/* @var User $user */
if (1 === $step && !$registrationManager->exists()) {
$this->eventDispatcher->dispatch(new UserEvent($user, $request), FOSUserEvents::REGISTRATION_INITIALIZE);
}
$form = $this->createForm(
[
1 => ProRegistrationStep1FormType::class,
2 => ProRegistrationStep2FormType::class,
3 => ProRegistrationStep3FormType::class,
][$step],
$user,
1 === $step ? ['locale' => $request->getLocale()] : []
);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
if ($step < 3) {
// Don't put attachments in session, we don't need them and it would break the registration manager
$registrationManager->save($user);
return new RedirectResponse($this->generateUrl('fos_user_registration_register_pro_step', ['step' => $step + 1]));
}
$event = new FormEvent($form, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_SUCCESS);
$this->userManager->updateUser($user);
/** @var RedirectResponse $response */
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $response), FOSUserEvents::REGISTRATION_COMPLETED);
$registrationManager->remove();
if ($request->isXmlHttpRequest()) {
return new JsonResponse([
'success' => true,
'url' => $event->getResponse()->getTargetUrl(),
]);
}
return $response;
}
return $this->render(
'/Registration/pro/step_'.$step.'.html.twig',
[
'form' => $form->createView(),
]
);
}
public function registerPortugalAction(
Request $request,
PrivateUserRegistrationSession $userRegistrationSession
) {
if (!$userRegistrationSession->exists()) {
throw new NotFoundHttpException('Pas d’inscription en cours');
}
/** @var PrivateUser $user */
$user = $userRegistrationSession->load();
$user->setEnabled(false);
$user->setNeedsTransaction(false);
$user->setLanguage('PT');
$this->eventDispatcher->dispatch(new UserEvent($user, $request), FOSUserEvents::REGISTRATION_INITIALIZE);
$form = $this->createForm(PortugalRegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$event = new FormEvent($form, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_SUCCESS);
$this->userManager->updateUser($user);
$userRegistrationSession->remove();
$response = $event->getResponse();
$this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $response), FOSUserEvents::REGISTRATION_COMPLETED);
return $response;
}
return $this->render(
'/Registration/register_portugal.html.twig',
[
'form' => $form->createView(),
]
);
}
public function registerSpainAction(
Request $request,
PrivateUserRegistrationSession $userRegistrationSession
) {
if (!$userRegistrationSession->exists()) {
throw new NotFoundHttpException('Pas d’inscription en cours');
}
/** @var PrivateUser $user */
$user = $userRegistrationSession->load();
$user->setNeedsTransaction(false);
$user->setLanguage('ES');
$this->eventDispatcher->dispatch(new UserEvent($user, $request), FOSUserEvents::REGISTRATION_INITIALIZE);
$form = $this->createForm(SpainRegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$event = new FormEvent($form, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_SUCCESS);
$user->setEnabled(false);
$this->userManager->updateUser($user);
$userRegistrationSession->remove();
$response = $event->getResponse();
$this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $response), FOSUserEvents::REGISTRATION_COMPLETED);
return $response;
}
return $this->render(
'/Registration/register_spain.html.twig',
[
'form' => $form->createView(),
]
);
}
/**
* Receive the confirmation token from user email provider.
*
* @return RedirectResponse|Response|null
*/
public function confirmAction(Request $request, $token): Response
{
$user = $this->userManager->findUserByConfirmationToken($token);
if (null === $user) {
return new RedirectResponse($this->generateUrl('fos_user_security_login'));
}
$user->setConfirmationToken(null);
$user->setEnabled(true);
$this->logger->info(sprintf('%s:%s User %s enabled', __CLASS__, __LINE__, $user->getId()));
$event = new GetResponseUserEvent($user, $request);
$this->eventDispatcher->dispatch($event, FOSUserEvents::REGISTRATION_CONFIRM);
$this->userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl(sprintf('fos_user_registration_confirmed%s', $user instanceof ProUser ? '_pro' : ''));
$response = new RedirectResponse($url);
}
// An email will be sent by the FOSUserEvents::REGISTRATION_CONFIRM event, don't send another one
if ($user && 'PT' !== $user->getCountry()) {
$this->sendValidationMessage($user);
}
$this->eventDispatcher->dispatch(new FilterUserResponseEvent($user, $request, $response), FOSUserEvents::REGISTRATION_CONFIRMED);
return $response;
}
// Tell the user to check his email provider.
public function checkEmailAction(Request $request): Response
{
$email = $request->getSession()->get('fos_user_send_confirmation_email/email');
$request->getSession()->remove('fos_user_send_confirmation_email/email');
$user = $this->userManager->findUserByEmail($email);
if (null === $user) {
throw new NotFoundHttpException(sprintf('The user with email "%s" does not exist', $email));
}
return $this->render('@FOSUser/Registration/check_email.html.twig', [
'user' => $user,
]);
}
// Tell the user his account is now confirmed and send him an email.
public function confirmedAction(Request $request): Response
{
$url = $this->generateUrl('fos_user_security_login');
$request->getSession()->getFlashBag()->add('success', $this->translator->trans('security.flash.account_created'));
return new RedirectResponse($url);
}
// Tell the user his account is now confirmed and send him an email.
public function confirmedProAction()
{
return $this->render('/Registration/confirmed_pro.html.twig');
}
// Display verification page
public function waitingVerificationAction()
{
return $this->render('/Registration/wait_verification.html.twig');
}
// Pro users need to wait account validation by VPAuto salesperson.
public function waitingValidationAction()
{
return $this->render('/Registration/wait.html.twig');
}
private function sendValidationMessage($user): void
{
$this->translatableMailer->send(
$user,
'/Mail/welcome.html.twig',
[]
);
}
}