<?php
namespace App\Controller;
use App\Entity\User;
use App\Entity\Autres;
use App\Entity\Adresse;
use App\Entity\AgentInterne;
use App\Entity\ChargeAssistance;
use App\Entity\ChargeFormation;
use App\Entity\Dae;
use App\Entity\Delegation;
use App\Entity\EnterprisePartenaire;
use App\Form\AutresType;
use App\Form\AdresseType;
use App\Entity\Entreprise;
use App\Entity\Partenaire;
use App\Entity\Particulier;
use App\Form\AgentInterneType;
use App\Form\ChargeAssistanceType;
use App\Form\ChargeFormationType;
use App\Form\EntrepriseType;
use App\Form\PartenaireNationalType;
use App\Form\DaeType;
use App\Form\PartenaireRegionalType;
use App\Form\PartenaireType;
use App\Form\ParticulierType;
use App\Security\EmailVerifier;
use App\Form\RegistrationFormType;
use App\Repository\UserRepository;
use Symfony\Component\Mime\Address;
use App\Repository\AdresseRepository;
use App\Repository\DelegationRepository;
use App\Repository\EnterprisePartenaireRepository;
use App\Repository\GouvernoratRepository;
use Doctrine\DBAL\Driver\Mysqli\Initializer\Charset;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
use Symfony\Component\String\Slugger\SluggerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
use App\Security\UsersAuthenticator;
use App\Service\FileUploader;
use App\Service\LegacyEmailVerificationTokenManager;
use App\Validator\Constraints\PasswordPolicy;
class RegistrationController extends AbstractController
{
private const PASSWORD_POLICY_REGEX = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/';
private EmailVerifier $emailVerifier;
private $request;
/**
* @var FileUploader
*/
protected $fileUploader;
/**
* @param RequestStack $request
*/
public function __construct(EmailVerifier $emailVerifier, RequestStack $request, FileUploader $fileUploader)
{
$this->emailVerifier = $emailVerifier;
$this->request = $request;
$this->fileUploader = $fileUploader;
}
#[Route('/register', name: 'app_register')]
public function register(
Request $request,
UserPasswordHasherInterface $userPasswordHasher,
EntityManagerInterface $entityManager,
UserRepository $userRepository,
GouvernoratRepository $gouvernoratRepository,
DelegationRepository $delegationRepository,
UserAuthenticatorInterface $userAuthenticator,
UsersAuthenticator $authenticator
): Response {
$form_view_array = [];
$requestedType = null;
$request = $this->request->getCurrentRequest();
$adresse = new Adresse();
$formAdr = $this->createForm(AdresseType::class);
$types = [
User::PARTIICULIER,
User::ENTREPRISE,
Partenaire::PARTENAIRE_NATIONAL,
Partenaire::PARTENAIRE_REGIONAL,
];
$instance_array = [
User::PARTIICULIER => new Particulier(),
User::ENTREPRISE => new Entreprise(),
Partenaire::PARTENAIRE_NATIONAL => new Partenaire(),
Partenaire::PARTENAIRE_REGIONAL => new Partenaire(),
User::AUTRES => new Autres(),
];
$form_type_array = [
User::ENTREPRISE => EntrepriseType::class,
User::PARTIICULIER => ParticulierType::class,
Partenaire::PARTENAIRE_REGIONAL => PartenaireRegionalType::class,
Partenaire::PARTENAIRE_NATIONAL => PartenaireNationalType::class,
User::AUTRES => AutresType::class,
];
$role_array = [
User::PARTIICULIER => 'ROLE_PARTICULIER',
User::ENTREPRISE => 'ROLE_ENTREPRISES',
Partenaire::PARTENAIRE_REGIONAL => 'ROLE_PARTENAIRES_REGIONAUX',
Partenaire::PARTENAIRE_NATIONAL => 'ROLE_PARTENAIRES_NATIONAUX',
User::AUTRES => 'ROLE_AUTRES',
];
$formAdr->handleRequest($request);
foreach ($types as $type) {
$instance = $instance_array[$type];
$form = $this->createForm($form_type_array[$type], $instance);
//$instance->addAdress(new Adresse());
$form_view_array[$type] = $form->createView();
$form->handleRequest($request);
if ($form->isSubmitted()) {
if (!$form->isValid()) {
foreach ($form->getErrors(true) as $error) {
return new JsonResponse([
'success' => false,
'message' => $error->getMessage(),
], Response::HTTP_OK, ['Content-Type', 'application/json']);
}
}
if ($type == "Entreprise" and count($instance->getAdresses()) > 0) {
foreach ($request->request->all()[strtolower($type)]['adresses'] as $i => $elem) {
$deleg = $delg = $delegationRepository->findOneBy(['id' => $elem['delegation']]);
$instance->getAdresses()[$i]->setDelegation($deleg);
$instance->getAdresses()[$i]->setUser($instance);
$instance->getAdresses()[$i]->setAdresse($elem['adresse']);
}
}
if ($type == "Entreprise" and $instance->getChargeFormations()) {
/** mapping of created User */
foreach ($instance->getChargeFormations() as $elem) {
$elem->setEntreprise($instance);
}
}
if (($type == "Partenaire_national" or $type == "Partenaire_regional") and $instance->getAdresses()) {
$adress = new Adresse();
$deleg = $delegationRepository->findOneBy(['id' => $request->request->all()[strtolower($type)]['delegation']]);
$gouv = $gouvernoratRepository->findOneBy(['id' => $request->request->all()[strtolower($type)]['gouvernorat']]);
$adress->setDelegation($deleg);
$adress->setGouvernorat($gouv);
$adress->setCodePostale($request->request->all()[strtolower($type)]['code_postale']);
$adress->setAdresse($request->request->all()[strtolower ($type)]['adresse']);
$instance->addAdress($adress);
}
if ($type == "Partenaire_national" or $type == "Partenaire_regional") {
$instance->setTypePartenaire($type);
/** mapping of created User */
foreach ($instance->getEnterprisePartenaires() as $elem) {
$elem->setEntreprisePartenaire($instance);
}
}
if (($type == "Autres" or $type == "Particulier") and $instance->getAdresses()) {
$adress = new Adresse();
$gouv = $gouvernoratRepository->findOneBy(['id' => $request->request->all()[strtolower($type)]['gouvernorat']]);
$adress->setGouvernorat($gouv);
$adress->setCodePostale($request->request->all()[strtolower($type)]['code_postale']);
$adress->setAdresse($request->request->all()[strtolower($type)]['adresse']);
$instance->addAdress($adress);
}
$requestedType = $type;
$requestedParams = $request->request->all()[strtolower($type)];
if ($form->get('plainPassword')->getData() != null) {
if (!preg_match(self::PASSWORD_POLICY_REGEX, (string) $form->get('plainPassword')->getData())) {
return new JsonResponse([
'success' => false,
'message' => PasswordPolicy::MESSAGE,
], Response::HTTP_OK, ['Content-Type', 'application/json']);
}
if (strcmp($form->get('plainPassword')->getData(), $form->get('confirmpassword')->getData()) == 0) {
if ($form->get('plainPassword')->getData() != null) {
$instance->setPassword(
$userPasswordHasher->hashPassword(
$instance,
$form->get('plainPassword')->getData()
)
);
}
} else {
return new JsonResponse([
'success' => false,
'message' => 'Les mots de passe ne sont pas identiques !'
], Response::HTTP_OK, ['Content-Type', 'application/json']);
}
}
// set roles
$instance->setRoles(array($role_array[$type]));
// set gouvernorat
if (array_key_exists('gouvernorat', $requestedParams)) {
$gouv = $gouvernoratRepository->findOneBy(['id' => $requestedParams['gouvernorat']]);
$adresse->setGouvernorat($gouv);
}
// set delegation if exist
if (array_key_exists('delegation', $requestedParams)) {
$delg = $delegationRepository->findOneBy(['id' => $requestedParams['delegation']]);
$adresse->setDelegation($delg);
}
// set adresse if exist
if (array_key_exists('adresse', $requestedParams)) {
$adresse->setAdresse($requestedParams['adresse']);
}
// set Localite if exist
if (array_key_exists('Localite', $requestedParams)) {
$adresse->setLocalite($requestedParams['Localite']);
}
// set code postale
if (array_key_exists('code_postale', $requestedParams)) {
$adresse->setCodePostale($requestedParams['code_postale']);
}
if (!$userRepository->findOneBy(['email' => $form->get('email')->getData()])) {
//dd($instance);
$entityManager->persist($instance);
$entityManager->flush();
// SEC-022 : abandon du JWT custom de vérification e-mail.
// Le lien signé est généré par verify-email-bundle.
$this->emailVerifier->sendEmailConfirmation(
'app_verify_email',
$instance,
(new TemplatedEmail())
->from(new Address($this->getParameter('EmailAdmin'), 'CNFCPP'))
->to($instance->getEmail())
->subject($this->trans('email.subject.account_activation'))
->htmlTemplate('emails/register_mail.html.twig')
->context([
'username' => $instance->getUsername(),
'_locale' => $request->getLocale(),
])
);
return new JsonResponse([
'success' => true,
'message' => 'Votre compte a été créé avec succès, vérifiez votre boite mail pour le confirmer!'
], Response::HTTP_OK, ['Content-Type', 'application/json']);
} else {
return new JsonResponse([
'success' => false,
'message' => 'Email existe déjà !'
], Response::HTTP_OK, ['Content-Type', 'application/json']);
}
}
}
return $this->render('registration/register.html.twig', [
'form_view_array' => $form_view_array,
'types' => $types,
'formAdr' => $formAdr->createView(),
'requestedType' => $requestedType
]);
}
#[Route('ajax/get/delegation', name: 'ajax_get_delegation')]
public function getDelegation(Request $request, TranslatorInterface $translator, EntityManagerInterface $em): JsonResponse
{
$delegations = $em
->getRepository(Delegation::class)
->getDelegationByGouvernaurat($request->query->get('gouvernorat_id'));
return new JsonResponse(json_encode($delegations));
}
#[Route('/verify/email', name: 'app_verify_email')]
public function verifyUserEmail(Request $request, UserRepository $userRepository, TranslatorInterface $translator): Response
{
$userId = $request->query->get('id');
if (null === $userId || !ctype_digit((string) $userId)) {
$this->addFlash('danger', $translator->trans('flash.token_invalid_expired'));
return $this->redirectToRoute('login');
}
$user = $userRepository->find((int) $userId);
if (!$user) {
$this->addFlash('danger', $translator->trans('flash.token_invalid_expired'));
return $this->redirectToRoute('login');
}
if ($user->isVerified()) {
$this->addFlash('warning', $translator->trans('flash.user_already_activated'));
return $this->redirectToRoute('login');
}
try {
$this->emailVerifier->handleEmailConfirmation($request, $user);
$this->addFlash('success', $translator->trans('flash.email_verified'));
} catch (VerifyEmailExceptionInterface $e) {
$this->addFlash('verify_email_error', $e->getReason());
return $this->redirectToRoute('login');
}
return $this->redirectToRoute('login');
}
#[Route('/verif/{token}', name: 'verify_user_legacy')]
public function verifyLegacyUserEmail(
string $token,
LegacyEmailVerificationTokenManager $legacyTokenManager,
UserRepository $userRepository,
EntityManagerInterface $entityManager,
TranslatorInterface $translator
): Response {
if (
!$legacyTokenManager->isValid($token)
|| $legacyTokenManager->isExpired($token)
|| !$legacyTokenManager->checkSignature($token, (string) $this->getParameter('kernel.secret'))
) {
$this->addFlash('danger', $translator->trans('flash.token_invalid_expired'));
return $this->redirectToRoute('login');
}
$payload = $legacyTokenManager->getPayload($token);
$legacyUserId = $payload['user_id'] ?? null;
if (!is_int($legacyUserId) && !(is_string($legacyUserId) && ctype_digit($legacyUserId))) {
$this->addFlash('danger', $translator->trans('flash.token_invalid_expired'));
return $this->redirectToRoute('login');
}
$user = $userRepository->find((int) $legacyUserId);
if (!$user) {
$this->addFlash('danger', $translator->trans('flash.token_invalid_expired'));
return $this->redirectToRoute('login');
}
if (!$user->isVerified()) {
$user->setIsVerified(true);
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', $translator->trans('flash.email_verified'));
} else {
$this->addFlash('warning', $translator->trans('flash.user_already_activated'));
}
return $this->redirectToRoute('login');
}
#[Route('/profil', name: 'app_profil')]
public function app_profil(
Request $request,
SluggerInterface $slugger,
EntityManagerInterface $entityManager,
ManagerRegistry $registry,
GouvernoratRepository $gouvernoratRepository,
DelegationRepository $delegationRepository,
UserPasswordHasherInterface $userPasswordHasher,
EnterprisePartenaireRepository $enterprisePartenaireRepository,
UserRepository $userRepository,
AdresseRepository $adresseRepository
): Response {
$AdresseRepository = $entityManager->getRepository(Adresse::class);
$adr = $AdresseRepository->findOneBy(['user' => $this->getUser()]);
// Vérification utilisateur connecté
if (!$this->getUser()) {
return $this->redirectToRoute('login');
}
// Création du formulaire en fonction du type d’utilisateur
$form = null;
if ($this->getUser() instanceof Partenaire) {
if ($this->getUser()->getTypePartenaire() === Partenaire::PARTENAIRE_REGIONAL) {
$form = $this->createForm(PartenaireRegionalType::class, $this->getUser());
} elseif ($this->getUser()->getTypePartenaire() === Partenaire::PARTENAIRE_NATIONAL) {
$form = $this->createForm(PartenaireNationalType::class, $this->getUser());
}
} elseif ($this->getUser() instanceof Particulier) {
$form = $this->createForm(ParticulierType::class, $this->getUser());
} elseif ($this->getUser() instanceof Entreprise) {
$form = $this->createForm(EntrepriseType::class, $this->getUser());
} elseif ($this->getUser() instanceof Autres) {
$form = $this->createForm(AutresType::class, $this->getUser());
} elseif ($this->getUser() instanceof Dae) {
$form = $this->createForm(DaeType::class, $this->getUser());
} elseif ($this->getUser() instanceof ChargeAssistance) {
$form = $this->createForm(ChargeAssistanceType::class, $this->getUser());
} elseif ($this->getUser() instanceof AgentInterne) {
$form = $this->createForm(AgentInterneType::class, $this->getUser());
}
// Si aucun formulaire trouvé → erreur explicite
if (!$form) {
throw $this->createNotFoundException('Aucun formulaire défini pour ce type d’utilisateur.');
}
// L'acceptation des CGU est requise à l'inscription uniquement, pas en modification de profil
if ($form->has('agreeTerms')) {
$form->remove('agreeTerms');
}
// Traitement du formulaire
$form->handleRequest($request);
if ($form->isSubmitted() && !$form->isValid()) {
foreach ($form->getErrors(true) as $error) {
return new JsonResponse([
'success' => false,
'message' => $error->getMessage(),
]);
}
}
if ($form->isSubmitted() && $form->isValid()) {
$data = $request->request->all();
if ($this->getUser() instanceof Particulier) {
$gouv = $gouvernoratRepository->find((int)$data['particulier']['gouvernorat']);
$adr->setGouvernorat($gouv);
$adr->setAdresse($data['particulier']['adresse']);
$adr->setCodePostale($data['particulier']['code_postale']);
} elseif ($this->getUser() instanceof Dae) {
$gouv = $gouvernoratRepository->find((int)$data['dae']['gouvernorat']);
$adr->setGouvernorat($gouv);
$adr->setAdresse($data['dae']['adresse']);
$adr->setCodePostale($data['dae']['code_postale']);
} elseif ($this->getUser() instanceof Entreprise) {
foreach ($this->getUser()->getChargeFormations() as $elem) {
$elem->setEntreprise($this->getUser());
}
} elseif ($this->getUser() instanceof Partenaire) {
$type = $this->getUser()->getTypePartenaire() === Partenaire::PARTENAIRE_NATIONAL
? "partenaire_national"
: "partenaire_regional";
$gouv = $gouvernoratRepository->find((int)$data[$type]['gouvernorat']);
$delg = $delegationRepository->find((int)$data[$type]['delegation']);
$adr->setGouvernorat($gouv);
$adr->setDelegation($delg);
$adr->setAdresse($data[$type]['adresse']);
$adr->setCodePostale($data[$type]['code_postale']);
$file = $request->files->get($type)['fileName'] ?? null;
if ($file) {
$newFileName = $this->fileUploader->upload($file, '/listEnt', 'docEnt');
$this->getUser()->setFileName($newFileName);
}
} elseif ($this->getUser() instanceof Autres) {
$gouv = $gouvernoratRepository->find((int)$data['autres']['gouvernorat']);
$adr->setGouvernorat($gouv);
$adr->setAdresse($data['autres']['adresse']);
$adr->setCodePostale($data['autres']['code_postale']);
}
// Vérification mot de passe
if ($form->get('plainPassword')->getData()) {
if (!preg_match(self::PASSWORD_POLICY_REGEX, (string) $form->get('plainPassword')->getData())) {
return new JsonResponse([
'success' => false,
'message' => PasswordPolicy::MESSAGE,
]);
}
if ($form->get('plainPassword')->getData() === $form->get('confirmpassword')->getData()) {
$this->getUser()->setPassword(
$userPasswordHasher->hashPassword(
$this->getUser(),
$form->get('plainPassword')->getData()
)
);
} else {
return new JsonResponse([
'success' => false,
'message' => 'Les mots de passe ne sont pas identiques !'
]);
}
}
$entityManager->persist($this->getUser());
$entityManager->flush();
return new JsonResponse([
'success' => true,
'message' => 'Profil mis à jour avec succès'
]);
}
return $this->render('registration/profil.html.twig', [
'profilForm' => $form->createView(),
'adr' => $adr
]);
}
#[Route('/renvoiverif', name: 'resend_verif')]
public function resendVerif(Request $request, TranslatorInterface $translator, UserRepository $userRepository): Response
{
$user = $this->getUser();
$redirectRoute = 'app_profil';
if (!$user) {
$redirectRoute = 'login';
$email = trim((string) $request->request->get('email', $request->query->get('email', '')));
if ('' !== $email) {
$user = $userRepository->findOneBy(['email' => $email]);
}
}
if (!$user) {
// Réponse neutre pour éviter l'énumération de comptes.
$this->addFlash('success', $translator->trans('flash.verification_email_sent'));
return $this->redirectToRoute($redirectRoute);
}
if ($user->isVerified()) {
$this->addFlash('warning', $translator->trans('flash.user_already_activated'));
return $this->redirectToRoute($redirectRoute);
}
$this->sendVerificationEmailForUser($user);
$this->addFlash('success', $translator->trans('flash.verification_email_sent'));
return $this->redirectToRoute($redirectRoute);
}
private function sendVerificationEmailForUser(User $user): void
{
$this->emailVerifier->sendEmailConfirmation(
'app_verify_email',
$user,
(new TemplatedEmail())
->from(new Address($this->getParameter('EmailAdmin'), 'CNFCPP'))
->to($user->getEmail())
->subject($this->trans('email.subject.account_activation'))
->htmlTemplate('emails/register_mail.html.twig')
->context([
'username' => $user->getUsername(),
'_locale' => $this->request->getCurrentRequest()?->getLocale() ?? 'fr',
])
);
}
protected function executeAction(Request $request): Response
{
// Récupérez les données soumises
$montant = $request->request->get('entreprise_montant');
// Effectuez la validation et l'enregistrement
if (floatval($montant) === 0) {
return new Response('Le montant ne peut pas être zéro.', 400);
}
// Effectuez l'enregistrement dans la base de données
return new Response('Enregistrement réussi !');
}
#[Route('/general-conditions', name: 'app_general_conditions')]
public function generalConditions(){
return $this->render('registration/general_conditions.html.twig', []);
}
}