<?php
namespace App\Controller;
use App\DTO\ForgetPasswordDT0;
use App\Entity\User;
use App\Entity\Category;
use App\Form\PasswordForgetType;
use App\Form\PasswordResetType;
use App\Form\RegistrationFormType;
use App\Security\App\Security\LoginFormAuthenticator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class RegistrationController extends AbstractController
{
/**
*
* @Route("/forgotpassword" , name="forgotpassword")
*/
public function forgotpassword(Request $request, EntityManagerInterface $em,UserPasswordEncoderInterface $passwordEncoder,AuthorizationCheckerInterface $securityContext, \Swift_Mailer $mailer,AuthenticationUtils $authenticationUtils)
{
$forget=new ForgetPasswordDT0();
$formForgotPwd = $this->createForm(PasswordForgetType::class, $forget);
return $this->render('refonte/Authentification/password/forgotPassword.html.twig',
[
'formForgotPwd' => $formForgotPwd->createView(),
]);
}
/**
*
* @Route("/login" , name="login_new")
*/
public function loginNew(Request $request, EntityManagerInterface $em,UserPasswordEncoderInterface $passwordEncoder,AuthorizationCheckerInterface $securityContext, \Swift_Mailer $mailer,AuthenticationUtils $authenticationUtils){
if ($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
$user = $this->getUser();
return $this->redirectToRoute('publication_index', ['id' => $user->getId(), 'firstname' => $user->getFirstName(), "lastname" => $user->getLastName()]);
}
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('refonte/Authentification/login.html.twig',
[
'form' => $form->createView(),
'last_username' => $lastUsername,
'error' => $error,
]);
}
/**
*
* @Route("/authentification" , name="registre_user")
*/
public function formulaire(Request $request, EntityManagerInterface $em,UserPasswordEncoderInterface $passwordEncoder,AuthorizationCheckerInterface $securityContext, \Swift_Mailer $mailer,AuthenticationUtils $authenticationUtils)
{
$referer = $request->headers->get('referer');
$refererPath = parse_url($referer, PHP_URL_PATH);
$paths=['/query','/authors'];
if(in_array($refererPath,$paths)) {
if ($refererPath == "/query") {
$message = "You need to log in to access more journal details";
}
if ($refererPath == "/authors") {
$message = "You need to log in to access more author details";
}
$this->addFlash('info', $message);
}
return $this->render('refonte/Authentification/registration-form.html.twig');
}
/**
* @Route("/user-registration", name="register")
*/
public function register(
Request $request,
EntityManagerInterface $em,
UserPasswordEncoderInterface $passwordEncoder,
AuthorizationCheckerInterface $securityContext,
\Swift_Mailer $mailer,
AuthenticationUtils $authenticationUtils,
SessionInterface $session
) {
// Redirect authenticated users to homepage
if ($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
return $this->redirectToRoute('homepage');
}
// Initialize forms
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
// Handle registration form submission
if ($form->isSubmitted() && $form->isValid()) {
// Check if email already exists
$email = $form->get('email')->getData();
$recaptcha=$request->get('g-recaptcha-response');
$mailExist = $em->getRepository(User::class)->findOneBy(['email' => $email]);
if ($mailExist) {
$this->addFlash('error', 'Email already exists');
return $this->render('refonte/Authentification/register.html.twig', [
'form' => $form->createView(),
'categories' => $em->getRepository(Category::class)->findAll(),
]);
}
if(!$recaptcha){
$this->addFlash('error', 'Please check the recaptcha');
return $this->render('refonte/Authentification/register.html.twig', [
'form' => $form->createView(),
'categories' => $em->getRepository(Category::class)->findAll(),
]);
}
// Check email format
if (substr_count($email, '.') > 2) {
$this->addFlash('error', 'Email format must be valid (e.g., email@example.com)');
return $this->render('refonte/Authentification/register.html.twig', [
'form' => $form->createView(),
'categories' => $em->getRepository(Category::class)->findAll(),
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
]);
}
// Process favorite categories
$favoriteCategories = $form->get('categories')->getData();
$favoriteCategories = preg_replace('/\s+/', ' ', $favoriteCategories);
if ($favoriteCategories) {
$favoriteCategories = explode(',', $favoriteCategories);
// trim to remove white spaces in array elements
$favoriteCategories = array_map('trim', $favoriteCategories);
foreach ($favoriteCategories as $categoryName) {
$categoryEntity = $em->getRepository(Category::class)->findOneBy(['name' => $categoryName]);
if ($categoryEntity) {
$user->addCategory($categoryEntity);
}
}
}
// Encode password
$encodedPassword = $passwordEncoder->encodePassword($user, $form->get('password')->getData());
$user->setPassword($encodedPassword);
// Process full name
$fullName = trim($form->get('fullName')->getData());
$firstname = $fullName;
$lastname = $fullName;
if (str_contains($fullName, ' ')) {
$fullNameParts = explode(' ', $fullName);
$firstname = $fullNameParts[0];
if (count($fullNameParts) > 1) {
$lastname = implode(' ', array_slice($fullNameParts, 1));
}
}
$user->setFirstName($firstname);
$user->setLastName($lastname);
$user->setFullName("$firstname $lastname");
// Set other user details
$user->setGender($form->get('gender')->getData() ? strtoupper($form->get('gender')->getData()[0]) : null);
$user->setBirthday($form->get('birthday')->getData());
$user->setCountry($form->get('country')->getData());
$user->setPhone($form->get('phone')->getData());
$user->addRole('ROLE_USER');
$user->setCreatedAt(new \DateTime());
// Generate verification token
$verificationToken = rand(-2147483648, 2147483647);
$user->setToken($verificationToken);
// Persist user to the database
$em->persist($user);
$em->flush();
// Send verification email
$fromEmail = getenv('ADMIN_EMAIL');
$body = $this->renderView('email/verification_code.html.twig', [
'verificationCode' => $verificationToken,
"email"=>$user->getEmail(),
]);
$emailMessage = (new \Swift_Message('Confirmation of your ResearchGuide registration'))
->setFrom($fromEmail)
->setTo($user->getEmail())
->setBody($body, 'text/html');
$mailer->send($emailMessage);
// Store unverified user email in session
$session->set('unverified_user_email', $user->getEmail());
// Redirect to verification page
return $this->redirectToRoute('verification_page');
} elseif ($form->isSubmitted() && !$form->isValid()) {
$success = false;
}
// Render the registration page
return $this->render('refonte/Authentification/register.html.twig', [
'form' => $form->createView(),
'categories' => $em->getRepository(Category::class)->findAll(),
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
]);
}
/**
*
* @Route("/media-registration" , name="registre_user_media")
*/
public function registerMedia(Request $request){
$em = $this->getDoctrine()->getManager();
$email= $request->query->get('email');
$user = $em->getRepository(User::class)->findOneBy(['email' => $email]);
$form = $this->createForm(PasswordResetType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $this->setUserPasswordAndSalt($form->getData(), $form);
$this->saveEntities();
}
return $this->render('connexion/register_media.html.twig', ['form'=> $form->createView()]);
}
/**
*
* @Route("/verify_email" , name="verify_email")
*/
public function verifyEmail(Request $request, UserPasswordEncoderInterface $passwordEncoder,GuardAuthenticatorHandler $guardHandler,LoginFormAuthenticator $authenticator)
{
$em = $this->getDoctrine()->getManager();
$code = $request->query->get('code');
$user = $em->getRepository(User::class)->findOneBy(['token' => $code]);
if ($user) {
$user->setIsVerified(true);
$user->setToken(null);
$em->persist($user);
$em->flush();
$guardHandler->authenticateUserAndHandleSuccess(
$user, // L'utilisateur nouvellement créé
$request, // La requête en cours
$authenticator, // L'authenticator utilisé
'guidejournal' // Le firewall configuré dans security.yaml
);
// $this->addFlash('success', 'Your email has been verified successfully');
return $this->redirectToRoute('homepage');
} else {
$this->addFlash('error', 'Invalid email');
}
return $this->redirectToRoute('login_new');
}
/**
*
* @Route("/reset-password" , name="reset-password" , methods={"POST"})
*/
public function resetPasswordForm(Request $request,EntityManagerInterface $em, \Swift_Mailer $mailer,SessionInterface $session)
{
$forget=new ForgetPasswordDT0();
$formForgotPwd = $this->createForm(PasswordForgetType::class, $forget);
$formForgotPwd->handleRequest($request);
if ($formForgotPwd->isSubmitted() && $formForgotPwd->isValid()) {
$emailForget = $request->request->get('password_forget')['emailForget'];
$token = $request->request->get('password_forget')['_token'];
$user=$em->getRepository(User::class)->findOneBy(['email' => $emailForget]);
if($user && (!$user->getIsDeleted() && !$user->getDeletedAt())){
$user->setToken($token);
$user->setIsVerified(false);
$em->persist($user);
$em->flush();
$fromEmail=getenv("ADMIN_EMAIL");
$body = $this->renderView('email/password-forget-email.html.twig', ['user' => $user]);
$email = (new \Swift_Message())
->setFrom($fromEmail)
->setTo($emailForget)
->setSubject('Reset password')
->setBody($body, 'text/html');
$mailer->send($email);
$session->set('reset_email', $user->getEmail());
return $this->redirectToRoute('verification_page_email_forgot');
}else{
$this->addFlash('error', 'This email does not exist');
return $this->redirectToRoute('forgotpassword');
}
}
return $this->render('refonte/Authentification/password/forgotPassword.html.twig',['formForgotPwd' => $formForgotPwd->createView(),]);
}
/**
*
* @Route("/reset_password" , name="reset_password")
*/
public function resetPassword(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$em = $this->getDoctrine()->getManager();
$email = $request->query->get('email');
$user = $em->getRepository(User::class)->findOneBy(['email' => $email]);
$form = $this->createForm(PasswordResetType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$email=$form->get('email')->getData();
if(!$email){
$this->addFlash('error', 'Email is required');
return $this->render('refonte/Authentification/password/newPassword.html.twig', ['form'=> $form->createView(),'email'=>$email]);
}
$user = $em->getRepository(User::class)->findOneBy(['email' => $email]);
$encodedPassword = $passwordEncoder->encodePassword($user, $form->get('password')->getData());
if($passwordEncoder->isPasswordValid($user, $form->get('password')->getData())){
$this->addFlash('error', 'Your new password must be different to previously used passwords.');
return $this->render('refonte/Authentification/password/newPassword.html.twig', ['form'=> $form->createView(),'email'=>$email]);
}
$user->setPassword($encodedPassword);
$newVerificationToken = rand(-2147483648, 2147483647);
$user->setToken($newVerificationToken);
$em->persist($user);
$em->flush();
// login the user after password reset
// $this->addFlash('success', 'Your password has been reset successfully');
// return $this->redirectToRoute('login_new');
return $this->render('refonte/Authentification/password/newPassword-verified.html.twig', ['user'=> $user]);
}
return $this->render('refonte/Authentification/password/newPassword.html.twig', ['form'=> $form->createView(),'email'=>$email]);
}
/**
* @Route("/verification", name="verification_page")
*/
public function verification(SessionInterface $session, EntityManagerInterface $em)
{
$email = $session->get('unverified_user_email');
if (!$email) {
return $this->redirectToRoute('register'); // Redirect to registration if no email is found
}
$user = $em->getRepository(User::class)->findOneBy(['email' => $email]);
if (!$user) {
return $this->redirectToRoute('register'); // Redirect to registration if user does not exist
}
return $this->render('refonte/Authentification/verification/verification.html.twig', [
'user' => $user,
]);
}
/**
* @Route("/verification-email-forgot", name="verification_page_email_forgot")
*/
public function verificationEmailForgot(SessionInterface $session, EntityManagerInterface $em){
$email = $session->get('reset_email');
$user = $em->getRepository(User::class)->findOneBy(['email' => $email]);
if (!$user) {
$this->addFlash('error', 'This email does not exist');
}
return $this->render('refonte/Authentification/verification/verification-email-forgot.html.twig', [
'user' => $user,
]);
}
/**
* @Route("/resend-verification-forgot-password", name="resend_verification_forgot_password")
*/
public function resendVerificationForgotPassword(SessionInterface $session, EntityManagerInterface $em, \Swift_Mailer $mailer){
// Get user email from session
$email = $session->get('reset_email');
$user=$em->getRepository(User::class)->findOneBy(['email' => $email]);
if($user){
$fromEmail=getenv("ADMIN_EMAIL");
$body = $this->renderView('email/password-forget-email.html.twig', ['user' => $user]);
$email = (new \Swift_Message())
->setFrom($fromEmail)
->setTo($email)
->setSubject('Reset password')
->setBody($body, 'text/html');
$mailer->send($email);
}
return $this->redirectToRoute('verification_page_email_forgot');
}
/**
* @Route("/resend-verification", name="resend_verification")
*/
public function resendVerification(SessionInterface $session, EntityManagerInterface $em, \Swift_Mailer $mailer)
{
$email = $session->get('unverified_user_email');
if (!$email) {
return $this->redirectToRoute('register'); // Redirect to registration if no email is found
}
$user = $em->getRepository(User::class)->findOneBy(['email' => $email]);
if (!$user) {
return $this->redirectToRoute('register'); // Redirect to registration if user does not exist
}
// Generate a new verification token
$newVerificationToken = rand(-2147483648, 2147483647);
$user->setToken($newVerificationToken);
$em->persist($user);
$em->flush();
// Send verification email
$fromEmail = getenv("ADMIN_EMAIL");
$body = $this->renderView('email/verification_code.html.twig', ['verificationCode' => $newVerificationToken,'user'=>$user]);
$emailMessage = (new \Swift_Message())
->setFrom($fromEmail)
->setTo($user->getEmail())
->setSubject('Resend: Confirmation of your ResearchGuide registration')
->setBody($body, 'text/html');
$mailer->send($emailMessage);
$this->addFlash('success', 'A new verification email has been sent to your email address.');
return $this->redirectToRoute('verification_page');
}
/**
* @Route("/pre_verify_email", name="pre_verify_email")
*/
public function preVerifyEmail(Request $request)
{
$code=$request->request->get('code');
if($code){
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository(User::class)->findOneBy(['token' => $code]);
if ($user) {
return $this->render('refonte/Authentification/verification/email-verified.html.twig', ['user' => $user]);
}
}
return $this->redirectToRoute('login_new');
}
}