<?php
namespace App\Controller;
use App\Email\DefaultTemplatedEmail;
use App\Form\LoginRegistrationFormType;
use App\Repository\PartnerPendingRepository;
use App\Repository\UserRepository;
use Symfony\Component\Mime\Address;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use App\Entity\User;
use App\Entity\PartnerPending;
use App\Form\RegistrationFormType;
use App\Security\EmailVerifier;
use App\Service\Sms;
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 SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
class RegistrationController extends AbstractController
{
private EmailVerifier $emailVerifier;
public function __construct(EmailVerifier $emailVerifier)
{
$this->emailVerifier = $emailVerifier;
}
/**
* @Route("/self-validation", name="self_validating_authentication")
* @param Request $request
*
* @return Response
*/
public function selfValidation(Request $request): Response
{
return $this->json(true);
}
/**
* @Route("/login_register/{partnerToken?}", name="login_register")
* @param Request $request
* @param null $partnerToken
*
* @return Response
*/
public function login_register(TokenStorageInterface $tokenStorage, UserRepository $repoUser, Request $request, $partnerToken = null): Response
{
$session = $request->getSession();
$isComplaint = $request->get("complaint", "0") == "1";
if ($isComplaint && !$session->get("expressComplaintPrice")) {
return $this->redirectToRoute("express_complaint_x_prices");
}
if ($this->getUser()) {
if ($partnerToken) {
$session->invalidate();
$tokenStorage->setToken();
} else {
if ($isComplaint) {
return $this->redirectToRoute('express_complaint_x_identity');
} else {
return $this->redirectToRoute('user_home');
}
}
}
$session->remove("login_register_email");
$form = $this->createForm(LoginRegistrationFormType::class);
$form->handleRequest($request);
if ($isComplaint) {
$loginRoute = "login";
$registerRoute = "express_complaint_register";
$template = "ExpressComplaint/login_register.html.twig";
$viewParameters = [
'breadcrumbComplaintExpress' => 'inscription',
'navbarTitle' => $session->get('expressComplaintCategoryName'),
'progressValue' => 5,
];
$routeParameters = [
"complaint" => "1"
];
} else {
$loginRoute = "login";
$registerRoute = "register";
$template = "Registration/login_register.html.twig";
$viewParameters = [];
$routeParameters = [];
}
if ($form->isSubmitted() && $form->isValid()) {
$datas = $form->getData();
$email = $datas["email"];
$session->set('login_register_email', $email);
$user = $repoUser->findByEmail($email);
if ($user) {
return $this->redirectToRoute($loginRoute, $routeParameters);
}
return $this->redirectToRoute($registerRoute, ['partnerToken' => $partnerToken]);
}
return $this->render($template, array_merge(
[
'form' => $form->createView()
],
$viewParameters
));
// gets an attribute by name
// $foo = $session->get('foo');
}
/**
* @Route("/register/{partnerToken?}", name="register")
* @param Request $request
* @param UserPasswordHasherInterface $passwordHasher
* @param Sms $sms
* @param null $partnerToken
* @param TokenStorageInterface|null $tokenStorage
*
* @return Response
*/
public function register(
Request $request,
UserRepository $repoUser,
PartnerPendingRepository $repoPartnerPending,
UserPasswordHasherInterface $passwordHasher,
Sms $sms,
$partnerToken = null,
TokenStorageInterface $tokenStorage = null
): Response {
$session = $request->getSession();
// Redirect the user if they're already logged in
if ($this->getUser()) {
// If a user is logged in and we click on a link to create a new account
// (e.g.: the partner received an email but is opening the link from the same computer where a session for the other partner already exists)
// Then destroy the session to allow accessing the Registration Form
if (null !== $partnerToken) {
$session->invalidate();
$tokenStorage->setToken();
} else { // Otherwise, just redirect to user_home as a logged user shouldn't access the registration form
return $this->redirectToRoute('user_home');
}
}
$email = $session->get("login_register_email");
if (!$email) {
return $this->redirectToRoute('login_register');
}
if ($repoUser->findByEmail($email)) {
return $this->redirectToRoute('login');
}
// Otherwise, get the form to create a new account
$user = new User();
// If a user has invited their partner, a special registration link is generated so that the partner would not have to fill all fields
if ($partnerToken) {
//$partnerInfo = $repoPartnerPending->findOneByToken($partnerToken);
$partnerInfo = null;
// We found a partnerPending
if ($partnerInfo) {
$user
->setCivility($partnerInfo->getCivility())
->setFirstName($partnerInfo->getFirstname())
->setLastName($partnerInfo->getBirthname())
->setEmail($partnerInfo->getEmail())
->setPhoneNumber($partnerInfo->getPhoneNumber())
->setPartnerLead($partnerInfo->getPartner());
}
}
$user->setEmail($email);
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// encode the plain password
$user->setPassword(
$passwordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
)
);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
if ($partnerToken && $partnerInfo) {
// The one who sent a message to have a partnership with s.o else, should be linked to this new partner
$partner = $partnerInfo->getPartner();
$partner->setPartnerLead($user);
$entityManager->persist($partner);
// Delete the PartnerPending as it's been used
$entityManager->remove($partnerInfo);
$entityManager->flush();
}
// generate a signed url and email it to the user
$this->emailVerifier->sendEmailConfirmation(
'verify_email',
$user,
(new DefaultTemplatedEmail())
->to($user->getEmail())
->subject('Veuillez confirmer votre e-mail')
->htmlTemplate('Mail/welcome.html.twig')
);
$session->set('self_validating_authentication_options', [
'redirect_to' => 'user_email_confirmation',
'user_id' => $user->getId()
]);
$session->remove("login_register_email");
return $this->redirectToRoute('user_email_confirmation');
//return $this->redirectToRoute('self_validating_authentication');
}
return $this->render('Registration/register.html.twig', [
'form' => $form->createView(),
]);
}
/**
* @Route("/verify/email", name="verify_email")
* @param Request $request
* @param EntityManagerInterface $manager
*
* @return Response
*/
public function verifyUserEmail(Request $request, EntityManagerInterface $manager): Response
{
$id = $request->get('id');
if (null === $id) {
return $this->redirectToRoute('register');
}
$repository = $manager->getRepository(User::class);
$user = $repository->find($id);
if (null === $user) {
return $this->redirectToRoute('register');
}
// validate email confirmation link, sets User::isVerified=true and persists
try {
$this->emailVerifier->handleEmailConfirmation($request, $user);
} catch (VerifyEmailExceptionInterface $exception) {
$this->addFlash('verify_email_error', $exception->getReason());
return $this->redirectToRoute('register');
}
// @TODO Change the redirect on success and handle or remove the flash message in your templates
$this->addFlash('success', "Votre e-mail est vérifié et votre compte est maintenant validé.");
return $this->redirectToRoute('login');
}
}