<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\RecoverPasswordFormType;
use App\Form\RegistrationFormType;
use App\Form\ResetPasswordFormType;
use App\Form\UpdateDetailsFormType;
use App\Service\EmailSender;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserController extends AbstractController
{
const MESSAGE_ACCOUNT_CREATED = "Before you can login, you must activate your account.\nPlease check your email and use the link provided to complete your registration.";
const MESSAGE_ACCOUNT_ACTIVATED = "Your account has now been activated.";
const MESSAGE_INVALID_TOKEN = "Your verification token was invalid.\n\nPlease retry using the link in your email.";
const MESSAGE_INVALID_EMAIL = "No user found with that email address.";
const MESSAGE_PASSWORD_RESET = "Please check your email and use the link provided to reset your password.";
/**
* @Route("/register/{token}", name="app_register")
* @param Request $request
* @param UserPasswordEncoderInterface $passwordEncoder
* @param EmailSender $sender
* @param string $token
* @return Response
*/
public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder, EmailSender $sender, string $token = null): Response
{
if ($token === null) {
$user = new User();
} else {
$user = $this->getDoctrine()
->getRepository(User::class)
->findOneByToken($token);
$user->setPassword('');
}
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->setPassword($passwordEncoder->encodePassword($user, $form->get('plainPassword')->getData()));
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$sender->sendVerificationEmail($user);
$this->addFlash('notice', self::MESSAGE_ACCOUNT_CREATED);
return $this->render('security/post-register.html.twig', []);
}
return $this->render('security/register.html.twig', [
'form' => $form->createView(),
]);
}
/**
* @Route("/verify/{token}", name="app_verify")
* @param string $token
* @return Response
*/
public function verify(string $token = null): Response
{
$user = $this->getDoctrine()->getRepository(User::class)->findOneByToken($token);
if ($user) {
$user->setVerified(true);
$user->setVerificationToken(null);
$this->getDoctrine()->getManager()->flush();
$this->addFlash('notice', self::MESSAGE_ACCOUNT_ACTIVATED);
} else {
$this->addFlash('error', self::MESSAGE_INVALID_TOKEN);
}
return $this->redirectToRoute('app_login');
}
/**
* @Route("/update-details", name="app_update_user")
* @param Request $request
* @param UserPasswordEncoderInterface $passwordEncoder
* @return Response
*/
public function update(Request $request, UserPasswordEncoderInterface $passwordEncoder): Response
{
$user = $this->getUser();
$form = $this->createForm(UpdateDetailsFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->setPassword($passwordEncoder->encodePassword($user, $form->get('plainPassword')->getData()));
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('dashboard');
}
return $this->render('security/register.html.twig', [
'form' => $form->createView(),
'update' => true,
]);
}
/**
* @Route("/recover-password", name="app_recover_password")
* @param Request $request
* @param EmailSender $sender
* @return Response
*/
public function recoverPassword(Request $request, EmailSender $sender): Response
{
$form = $this->createForm(RecoverPasswordFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $this->getDoctrine()
->getRepository(User::class)
->findOneBy([
'email' => $form->getData()['email'],
]);
if ($user) {
$user->setVerificationToken(uniqid());
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$sender->sendPasswordResetEmail($user);
$this->addFlash('notice', self::MESSAGE_PASSWORD_RESET);
return $this->redirectToRoute('app_login');
} else {
$this->addFlash('error', self::MESSAGE_INVALID_EMAIL);
}
}
return $this->render('security/recover-password.html.twig', [
'recoveryForm' => $form->createView(),
'user' => $user ?? null,
]);
}
/**
* @Route("/reset-password/{token}", name="app_reset_password")
* @param Request $request
* @param string $token
* @param UserPasswordEncoderInterface $passwordEncoder
* @return Response
*/
public function resetPassword(Request $request, UserPasswordEncoderInterface $passwordEncoder, string $token = null): Response
{
$form = $this->createForm(ResetPasswordFormType::class);
$form->handleRequest($request);
$user = $this->getDoctrine()->getRepository(User::class)->findOneByToken($token);
if ($user !== null && $form->isSubmitted() && $form->isValid()) {
$user
->setPassword($passwordEncoder->encodePassword($user, $form->get('plainPassword')->getData()))
->setVerificationToken(null);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('app_login');
}
return $this->render('security/reset-password.html.twig', [
'resetForm' => $form->createView(),
]);
}
}