<?php
namespace App\Controller\Front;
use App\DataTransferObject\CreateUserRequest;
use App\Entity\User;
use App\Event\Account\UserCreationFinalizedEvent;
use App\Exception\ExistingAccountException;
use App\Exception\ExistingEmailException;
use App\Exception\OldAccountException;
use App\Exception\UserNotFoundException;
use App\Form\Account\CreationType;
use App\Manager\UserActivator;
use App\Manager\UserManager;
use App\Repository\App\UserRepository;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/mon-compte")
*/
class AccountCreationController extends AbstractAccountController
{
/** @var UserActivator */
protected $userActivator;
/** @var UserRepository */
protected $userRepository;
public function __construct(
UserManager $userManager,
EventDispatcherInterface $dispatcher,
TranslatorInterface $translator,
TokenStorageInterface $tokenStorage,
RequestStack $requestStack,
UserActivator $userActivator,
UserRepository $userRepository
) {
parent::__construct($userManager, $dispatcher, $translator, $tokenStorage, $requestStack);
$this->userActivator = $userActivator;
$this->userRepository = $userRepository;
}
/**
* @Route("/initialisation", name="account_creation")
*/
public function initializeCreation(Request $request): Response
{
$data = new CreateUserRequest();
$form = $this->createForm(CreationType::class, $data);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = null;
try {
$user = $this->userManager->createFromRequest($data);
} catch (UserNotFoundException $e) {
return $this->displayUserCreationError(
$form,
$this->transFront('account_creation.step1.message.user_not_found.html')
);
} catch (ExistingEmailException $e) {
return $this->displayUserCreationError(
$form,
$this->transFront('account_creation.step1.message.existing_email')
);
} catch (OldAccountException $e) {
return $this->displayUserCreationSuccess(
$this->userManager->create($data),
$this->transFront('account_creation.step1.message.old_account')
);
} catch (ExistingAccountException $e) {
return $this->manageExistingAccountCreation($form);
}
return $this->displayUserCreationSuccess($user, $this->transFront('account_creation.step1.message.success'));
}
return $this->render('front/account/creation/form.html.twig', ['form' => $form->createView()]);
}
/**
* @Route("/finalisation/{passwordCreationToken}", name="account_creation_step2")
*/
public function finalizeCreation(Request $request, string $passwordCreationToken): Response
{
return $this->createPassword(
$request,
$passwordCreationToken,
$this->transFront('account_creation.step2.page_title'),
$this->transFront('account_creation.label_step'),
2,
2,
$this->transFront('account_creation.step2.message.success'),
UserCreationFinalizedEvent::class,
'account_creation.step2.form.submit',
true
);
}
/**
* @Route("/mise-a-jour", name="account_update")
*/
public function initializeImport(): Response
{
return $this->render('front/account/import/message.html.twig');
}
protected function displayUserCreationSuccess(User $user, string $message): Response
{
$this->getDoctrine()->getManager()->persist($user);
$this->userActivator->sendActivation($user);
return $this->render('front/account/creation/step1_success.html.twig', [
'page_title' => $this->transFront('account_creation.step1.page_title'),
'step_title' => $this->transFront('account_creation.step1.title'),
'confirmationMessage' => $message,
]);
}
protected function displayUserCreationError(FormInterface $form, string $message): Response
{
$this->addFlash('error', $message);
return $this->render('front/account/creation/form.html.twig', ['form' => $form->createView()]);
}
protected function manageExistingAccountCreation(FormInterface $form): Response
{
$user = $this->userRepository->findOneBy([
'customerNumber' => $form->get('customerNumber')->getData(),
'activated' => false,
]);
if ($user instanceof User) {
return $this->reactivateUser($user, $form);
}
return $this->displayUserCreationError(
$form,
$this->transFront(
'account_creation.step1.message.existing_account',
['{url}' => $this->generateUrl('app_login')]
)
);
}
protected function reactivateUser(User $user, FormInterface $form): Response
{
$email = $form->get('email')->getData();
if (0 == $this->userRepository->countOtherCustomerWithEmail($user->getCustomerNumber(), $email)) {
$user->setEmail($email);
return $this->displayUserCreationSuccess(
$user,
$this->transFront(
'account_creation.step1.message.existing_account_activation.html',
['{url}' => $this->generateUrl('app_login')]
)
);
}
return $this->displayUserCreationError(
$form,
$this->transFront('account_creation.step1.message.existing_email')
);
}
}