<?php
namespace App\Controller\Client;
use App\Entity\Contact;
use App\Entity\ContactCreationSociete;
use App\Entity\ContactInvestissementImmo;
use App\Entity\ContactInvestissementImmoProperty;
use App\Entity\ContactInvestissementImmoPropertyCharge;
use App\Entity\EmailBlacklist;
use App\Form\ContactCreationSocieteType;
use App\Form\ContactInvestissementImmoType;
use App\Services\MoneticoService;
use App\Services\QueriesV2Manager;
use Psr\Log\LoggerInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig\Environment;
use App\Form\ContactType;
use App\Services\WebSite;
use App\Form\MiniBookType;
use App\Entity\ApplyRequest;
use App\Form\NewsletterType;
use App\Entity\AccountingFirm;
use App\Form\EbookDownloadType;
use App\Form\CompanyCreationType;
use App\Form\AnnouncementApplyType;
use App\Repository\AliasRepository;
use App\Services\SendContactEmail as CE;
use App\Repository\AccountingFirmRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\HttpFoundation\Response;
use App\Controller\Client\ClientWidgetController;
use App\Entity\ContactProfession;
use App\Form\ContactProfessionType;
use App\Form\ContactCustomType;
use App\Form\ContactEtreRappeleType;
use App\Repository\DynDataRepository;
use App\Repository\AnnouncementRepository;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Services\AccountingFirmResolver;
use Symfony\Contracts\Cache\CacheInterface;
abstract class AbstractClientController extends AbstractController
{
protected $accountingFirm;
protected $templateBase;
protected $mailer;
protected $request;
protected $redirect;
protected $formview;
protected $formsend;
protected $formlivreview;
protected $form_send_livre;
protected $formcompanyview;
protected $form_send_company;
protected $formprofessionview;
protected $formetrerappeleview;
protected $form_send_profession;
protected $form_send_etreRappele;
protected $formnewsletterview;
protected $form_send_newsletter;
protected $formminibookview;
protected $form_send_minibook;
protected $formrecrutementview;
protected $form_send_recrutement;
protected $formprevicreationview;
protected $form_send_previ_creation;
protected $formpreviimmoview;
protected $form_send_previ_immo;
protected $formcustomview;
protected $form_send_custom;
protected $CE;
protected $twig;
protected $site;
protected $dynData;
protected $dynDataArray;
protected $dynDataText;
protected $announcementMain;
protected $announcementSpontanee;
protected $serviceQMV2;
protected $moneticoService;
protected $theHost;
protected $logger;
protected $cache;
public function __construct(RequestStack $request, AccountingFirmRepository $accountingFirmRepository, AliasRepository $aliasrepository, MailerInterface $mailer, CE $CE, Environment $twig, WebSite $site, AnnouncementRepository $announcementRepository, DynDataRepository $dynDataRepository, QueriesV2Manager $serviceQMV2, MoneticoService $moneticoService, LoggerInterface $logger, AccountingFirmResolver $accountingFirmResolver, CacheInterface $cache)
{
$this->moneticoService = $moneticoService;
$this->logger = $logger;
$this->cache = $cache;
$theHost = $request->getCurrentRequest()->getHost();
$theHost = str_replace('www.', '', $theHost);
if (preg_match('/preview/', $request->getCurrentRequest()->get('_route'))) {
$theHost = $request->getCurrentRequest()->attributes->get('host');
}
// $theHost = 'cabinet-za.de';
// ✅ UTILISATION DU RESOLVER CENTRALISÉ - évite la duplication avec le Voter
$this->accountingFirm = $accountingFirmResolver->resolve();
// Gestion de la redirection si alias ou host non trouvé
if (is_null($this->accountingFirm)) {
$alias = $aliasrepository->findOneBy([
'name' => $theHost
]);
if (!is_null($alias)) {
$acID = $alias->getParameter()->getAccountingFirm()->getId();
$this->accountingFirm = $accountingFirmRepository->findOneBy([
'id' => $acID
]);
$this->redirect = $this->accountingFirm->getHost();
} else {
$this->redirect = 404;
}
}
$theHost = $this->accountingFirm->getHost();
$this->theHost = $theHost;
// ✅ OPTIMISATION : Cache des DynData avec relations hydratées
// On récupère directement depuis le repository (pas de cache d'entités Doctrine)
// car les relations lazy-loaded ne survivent pas à la sérialisation du cache
$this->dynData = $dynDataRepository->findAll();
// Filtrer par type - on garde les entités complètes avec relations hydratées
$this->dynDataArray = array_values(array_filter($this->dynData, fn($d) => $d->getType() === 'ARRAY'));
$this->dynDataText = array_values(array_filter($this->dynData, fn($d) => $d->getType() === 'TEXT'));
if (!empty($this->accountingFirm)) {
$this->announcementMain = $announcementRepository->findMyAnnouncementMain($this->accountingFirm);
$this->announcementSpontanee = $announcementRepository->findMyAnnouncementsSpontanee($this->accountingFirm);
}
$this->templateBase = '/' . $theHost . '/templates/';
$this->request = $request;
$this->mailer = $mailer;
$this->formsend = false;
$this->form_send_livre = false;
$this->form_send_company = false;
$this->form_send_newsletter = false;
$this->form_send_minibook = false;
$this->form_send_recrutement = false;
$this->form_send_custom = false;
$this->form_send_previ_creation = false;
$this->form_send_previ_immo = false;
$this->CE = $CE;
$this->twig = $twig;
$this->site = $site;
$this->serviceQMV2 = $serviceQMV2;
}
protected function render(string $view, array $parameters = [], Response $response = null, array $return = []): Response
{
// ✅ OPTIMISATION : Cache du fichier entrypoints.json (évite I/O disque + parsing JSON)
// Le cache sera automatiquement invalidé au prochain déploiement
$build = $this->cache->get('build_entrypoints', function() {
$filePath = $this->getParameter('kernel.project_dir') . '/public/build/entrypoints.json';
return json_decode(file_get_contents($filePath), true);
});
$this->twig->addGlobal('build', $build);
$this->twig->addGlobal('serverActuUrl', $this->site->getServerActuUrl());
// set redirection
if (!is_null($this->redirect)) {
if ($this->redirect == 404) {
return new Response("", 404);
die();
} else {
$this->redirect = "https://" . $this->redirect;
}
}
// Access from actualite-du-mois.php
if ($this->request && $this->request->getCurrentRequest() && $this->request->getCurrentRequest()->getBaseUrl() == "/actualite-du-mois.php") {
if ($this->redirectRouteV2($this->request->getCurrentRequest())) {
$redirect = $this->redirectRouteV2($this->request->getCurrentRequest());
$redirect = str_replace("actualite-du-mois.php", "", $redirect);
$redirect = str_replace("//", "/", $redirect);
} else {
$redirect = "/actualite-du-mois";
}
if (empty($this->redirect)) {
$this->redirect = "https://" . $this->request->getCurrentRequest()->getHttpHost() . $redirect;
} else {
$this->redirect = $this->redirect . $redirect;
}
}
// do redirection
if (!is_null($this->redirect)) {
return new RedirectResponse($this->redirect);
die();
}
// SETUP
$entityManager = $this->getDoctrine()->getManager();
// Contact
$form = $this->createForm(ContactType::class, null, ['cabinet' => $this->accountingFirm]);
$request = $this->get('request_stack')->getCurrentRequest();
$form->get('form_timestamp')->setData(time());
$form->get('route')->setData($request->attributes->get('_route'));
if ($request->attributes->get('_route') == 'previewprescripteur_client' || $request->attributes->get('_route') == 'prescripteur_client') {
$form->get('id_prescriber')->setData($request->attributes->get('id'));
}
$form->handleRequest($request);
$this->formview = $form->createView();
if ($form->isSubmitted() && $form->isValid()) {
$name = $form->get('name')->getData();
$email = $form->get('email')->getData();
$message = $form->get('message')->getData();
$fiveMinutesAgo = new \DateTime('-5 minutes');
$existingContact = $this->getDoctrine()->getRepository(Contact::class)->findRecentContactByName($name, $fiveMinutesAgo);
$submittedAt = (int) $form->get('form_timestamp')->getData();
$now = time();
$elapsedSeconds = $now - $submittedAt;
// Anti-spam : formulaire soumis trop vite
if ($elapsedSeconds < 3) {
// Ajout à la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
$entityManager = $this->getDoctrine()->getManager();
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if (!$blacklistedEmail) {
$blacklistedEmail = new EmailBlacklist();
$blacklistedEmail->setEmail($email);
$blacklistedEmail->setName($name);
$blacklistedEmail->setBlockCount(1);
} else {
$blacklistedEmail->incrementBlockCount();
}
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
// Détection message spam type "ClbNCSjWDTZMonBownuySkg"
if ($this->isGibberishMessage($message)) {
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
$entityManager = $this->getDoctrine()->getManager();
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if (!$blacklistedEmail) {
$blacklistedEmail = new EmailBlacklist();
$blacklistedEmail->setEmail($email);
$blacklistedEmail->setName($name);
$blacklistedEmail->setBlockCount(1);
} else {
$blacklistedEmail->incrementBlockCount();
}
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
// Vérifier si l'email est dans la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) && !$existingContact && stripos($message, "free") === false) {
$this->CE->sendContactEmail($form);
} elseif ($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) {
// Incrémenter le compteur de tentatives
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
}
$this->formsend = true;
}
// Contact Custom
$form_custom = $this->createForm(ContactCustomType::class, null, ['cabinet' => $this->accountingFirm]);
$form_custom->handleRequest($request);
$this->formcustomview = $form_custom->createView();
if ($form_custom->isSubmitted() && $form_custom->isValid()) {
$name = $form_custom->get('name')->getData();
$email = $form_custom->get('email')->getData();
$message = $form_custom->get('message')->getData();
// Vérifier si l'email est dans la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) && stripos($message, "free") === false) {
$this->CE->sendContactCustomEmail($form_custom);
} elseif ($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) {
// Incrémenter le compteur de tentatives
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
}
$this->form_send_custom = true;
}
// EbookDownload
$form_livre = $this->createForm(EbookDownloadType::class);
$form_livre->handleRequest($request);
$this->formlivreview = $form_livre->createView();
if ($form_livre->isSubmitted() && $form_livre->isValid()) {
$this->CE->sendEbookEmail($form_livre);
$this->form_send_livre = true;
}
// company
$form_company = $this->createForm(CompanyCreationType::class, null, ['cabinet' => $this->accountingFirm]);
$form_company->handleRequest($request);
$this->formcompanyview = $form_company->createView();
if ($form_company->isSubmitted() && $form_company->isValid()) {
$name = $form_company->get('name')->getData();
$email = $form_company->get('email')->getData();
// Vérifier si l'email est dans la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name))) {
$this->CE->sendCompanyEmail($form_company);
} elseif ($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) {
// Incrémenter le compteur de tentatives
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
}
$this->form_send_company = true;
}
// company
$form_profession = $this->createForm(ContactProfessionType::class, null, ['cabinet' => $this->accountingFirm]);
$form_profession->handleRequest($request);
$this->formprofessionview = $form_profession->createView();
if ($form_profession->isSubmitted() && $form_profession->isValid()) {
$name = $form_profession->get('name')->getData();
$email = $form_profession->get('email')->getData();
$message = $form_profession->get('message')->getData();
// Vérifier si l'email est dans la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) && stripos($message, "free") === false) {
$this->CE->sendContactProfessionEmail($form_profession);
} elseif ($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) {
// Incrémenter le compteur de tentatives
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
}
$this->form_send_profession = true;
}
// etre rappele
$form_etre_rappele = $this->createForm(ContactEtreRappeleType::class, null, ['cabinet' => $this->accountingFirm]);
$form_etre_rappele->handleRequest($request);
$this->formetrerappeleview = $form_etre_rappele->createView();
if ($form_etre_rappele->isSubmitted() && $form_etre_rappele->isValid())
{
$name = $form_etre_rappele->get('name')->getData();
$email = $form_etre_rappele->get('email')->getData();
// Vérifier si l'email est dans la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name))) {
$this->CE->sendContactEtreRappeleEmail($form_etre_rappele);
} elseif ($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) {
// Incrémenter le compteur de tentatives
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
}
$this->form_send_etreRappele = true;
}
// previ creation
$logFile = $this->getParameter('kernel.project_dir') . '/var/log/monprevi.log';
if (!is_dir(dirname($logFile))) {
@mkdir(dirname($logFile), 0775, true);
}
$log = function (string $message) use ($logFile) {
@file_put_contents(
$logFile,
sprintf("[%s] %s\n", (new \DateTimeImmutable())->format('Y-m-d H:i:s'), $message),
FILE_APPEND
);
};
if ($this->accountingFirm->getId() === 301 || $this->accountingFirm->getId() === 320) {
$log("Init Previ Creation: host={$this->theHost}, cabinet_id=" . ($this->accountingFirm ? $this->accountingFirm->getId() : 'null'));
}
try {
$contactCreationSociete = new ContactCreationSociete();
$contactCreationSociete->setCabinet($this->accountingFirm);
$contactCreationSociete->setCreatedAt(new \DateTimeImmutable('now'));
$form_previcreation = $this->createForm(ContactCreationSocieteType::class, $contactCreationSociete, ['cabinet' => $this->accountingFirm]);
$this->formprevicreationview = $form_previcreation->createView();
if ($this->accountingFirm->getId() === 301) {
$log("Previ Creation : Formulaire affiché");
}
if ($request->isMethod('POST') && $request->request->has($form_previcreation->getName())) {
$log("Previ Creation POST detecté pour form=" . $form_previcreation->getName());
$form_previcreation->handleRequest($request);
if ($form_previcreation->isSubmitted() && $form_previcreation->isValid()) {
$log("Previ Creation formulaire soumis et valide");
$startActivityAt = $form_previcreation->get('startActivityAt')->getData();
$fiscalYearEndAt = $form_previcreation->get('fiscalYearEndAt')->getData();
$log(sprintf(
"Previ Creation dates reçues: startActivityAt=%s, fiscalYearEndAt=%s",
$startActivityAt ? $startActivityAt->format('d/m/Y') : 'null',
$fiscalYearEndAt ? $fiscalYearEndAt->format('d/m/Y') : 'null'
));
$contactCreationSociete->setStartActivityAt($startActivityAt);
$contactCreationSociete->setFiscalYearEndAt($fiscalYearEndAt);
$name = $form_previcreation->get('name')->getData();
$email = $form_previcreation->get('email')->getData();
$log("Previ Creation nom reçu: {$name} {$email}");
// Vérifier si l'email est dans la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name))) {
$log("Blacklist check passed for email: {$email}");
try {
$entityManager->persist($contactCreationSociete);
$entityManager->flush();
} catch (\Throwable $e) {
$this->logger->error("❌ Erreur lors du persist/flush Previ Creation", [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'form_data_class' => get_class($form_previcreation->getData()),
'form_valid' => $form_previcreation->isValid(),
'form_errors' => (string) $form_previcreation->getErrors(true, false),
]);
throw $e;
}
$log("Previ Creation entité persistée id=" . $contactCreationSociete->getId());
$contactCreationSociete->setReference('PREVI_' . $contactCreationSociete->getId());
$entityManager->persist($contactCreationSociete);
$entityManager->flush();
$log("Previ Creation référence définie=" . $contactCreationSociete->getReference());
if ($contactCreationSociete->getPaymentMethod() === 'cb') {
$parameters = $this->accountingFirm->getParameters();
$price = ($contactCreationSociete->getCategory() == "Prévisionnel complet") ? "359,00" : "259,00";
$urlRetour = $this->generateUrl('monetico_return_client', ['id' => $contactCreationSociete->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
$urlNotif = $this->generateUrl('monetico_notification', [], UrlGeneratorInterface::ABSOLUTE_URL);
if (str_contains($this->request->getCurrentRequest()->get('_route'), 'preview')) {
$urlRetour = $this->generateUrl('previewmonetico_return_client', ['host' => $this->theHost, 'id' => $contactCreationSociete->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
$urlNotif = $this->generateUrl('previewmonetico_notification', ['host' => $this->theHost], UrlGeneratorInterface::ABSOLUTE_URL);
}
$log("Previ Creation paiement CB: price={$price}, reference=" . $contactCreationSociete->getReference() . ", url_retour={$urlRetour}, url_notif={$urlNotif}");
$params = [
'tpe' => $parameters->getMoneticoTpe(),
'societe' => $parameters->getMoneticoSociete(),
'hmac_key' => $parameters->getMoneticoCle(),
'url_retour' => $urlRetour,
'url_notif' => $urlNotif,
'montant' => $price,
'reference' => $contactCreationSociete->getReference(),
'email' => $contactCreationSociete->getEmail(),
'name' => $contactCreationSociete->getName(),
'firstname' => $contactCreationSociete->getFirstname(),
'address' => $contactCreationSociete->getSocietyAddress(),
'zipCode' => $contactCreationSociete->getSocietyZipCode(),
'city' => $contactCreationSociete->getSocietyCity(),
];
$log("Previ Creation génération du formulaire de paiement Monetico");
return new Response($this->moneticoService->generatePaymentForm($params));
}
$this->CE->sendPreviCreation($contactCreationSociete);
$this->form_send_previ_creation = true;
$log("Previ Creation email envoyé, référence=" . $contactCreationSociete->getReference());
$urlRetour = $this->generateUrl('monetico_return_client', ['id' => $contactCreationSociete->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
if (str_contains($this->request->getCurrentRequest()->get('_route'), 'preview')) {
$urlRetour = $this->generateUrl('previewmonetico_return_client', ['host' => $this->theHost, 'id' => $contactCreationSociete->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
}
$urlRetour .= "?reference=" . $contactCreationSociete->getReference();
$urlRetour .= "&code-retour=paiement";
$log("Previ Creation redirection vers {$urlRetour}");
return new RedirectResponse($urlRetour);
} elseif ($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) {
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
$log("Previ Creation email blacklisté: {$email}");
}
} else {
$log("Previ Creation formulaire non valide ou non soumis");
$this->logger->error("Previ Creation formulaire non valide ou non soumis", [
'form_data_class' => get_class($form_previcreation->getData()),
'form_valid' => $form_previcreation->isValid(),
'form_errors' => (string) $form_previcreation->getErrors(true, false),
]);
}
}
} catch (\Throwable $e) {
// ⚙️ On tente de récupérer le contenu du formulaire, même s'il est invalide
$formData = [];
try {
if (isset($form_previcreation) && $form_previcreation->isSubmitted()) {
// on extrait les données brutes + erreurs
$formData = [
'data' => $form_previcreation->getData(),
'submitted_data' => $request->request->all($form_previcreation->getName()),
'errors' => (string) $form_previcreation->getErrors(true, false),
];
}
} catch (\Throwable $innerE) {
// on logue aussi si jamais même la récupération échoue (par sécurité)
$this->logger->warning('Impossible d’extraire les données du formulaire dans le catch', [
'inner_message' => $innerE->getMessage(),
]);
}
// 🧾 Log complet de l’exception
$this->logger->error('❌ Exception non interceptée dans Previ Creation', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'request_uri' => $request->getRequestUri(),
'form_data' => $formData,
]);
// 🔁 selon ton besoin :
throw $e; // pour laisser Symfony gérer l'erreur (page 500)
}
// previ immo
if ($this->accountingFirm->getId() === 301) {
$log("Init Previ Immo: host={$this->theHost}, cabinet_id=" . ($this->accountingFirm ? $this->accountingFirm->getId() : 'null'));
}
try {
$contactInvestissementImmo = new ContactInvestissementImmo();
$contactInvestissementImmo->setAccountingFirm($this->accountingFirm);
$contactInvestissementImmo->setNumberProperties(1);
$contactInvestissementImmo->setCreatedAt(new \DateTimeImmutable('now'));
$form_previimmo = $this->createForm(ContactInvestissementImmoType::class, $contactInvestissementImmo, ['cabinet' => $this->accountingFirm]);
$this->formpreviimmoview = $form_previimmo->createView();
if ($this->accountingFirm->getId() === 301) {
$log("Previ Immo : Formulaire affiché");
}
if ($request->isMethod('POST') && $request->request->has($form_previimmo->getName())) {
$log("Previ Immo POST détecté pour form=" . $form_previimmo->getName());
$form_previimmo->handleRequest($request);
if ($form_previimmo->isSubmitted() && $form_previimmo->isValid()) {
$log("Previ Immo formulaire soumis et valide");
$name = $form_previimmo->get('name')->getData();
$email = $form_previimmo->get('email')->getData();
$log("Previ Immo nom reçu: {$name} {$email}");
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name))) {
$propertiesImmoData = $form_previimmo->get('propertiesImmo')->getData();
$propertiesChargesData = $form_previimmo->get('propertiesCharges')->getData();
$propertiesRentData = $form_previimmo->get('propertiesRent')->getData();
$log("Previ Immo propriétés reçues: nb=" . (is_iterable($propertiesImmoData) ? count($propertiesImmoData) : 0));
foreach ($propertiesImmoData as $index => $propertyData) {
$log("Previ Immo propriété index={$index} création");
$property = new ContactInvestissementImmoProperty();
$property->setSurface($propertyData['surface'] ?? '');
$property->setBiens($propertyData['biens'] ?? '');
$property->setRents($propertiesRentData[$index]['rent'] ?? '');
$property->setContactInvestissementImmo($contactInvestissementImmo);
if (isset($propertiesChargesData[$index]['charges']) && is_iterable($propertiesChargesData[$index]['charges'])) {
$log("Previ Immo propriété index={$index} charges nb=" . count($propertiesChargesData[$index]['charges']));
foreach ($propertiesChargesData[$index]['charges'] as $chargeData) {
$charge = new ContactInvestissementImmoPropertyCharge();
$charge->setName($chargeData['name'] ?? '');
$charge->setAmount($chargeData['amount'] ?? '');
$charge->setFrequency($chargeData['periodicite'] ?? '');
$charge->setContactInvestissementImmoProperty($property);
$entityManager->persist($charge);
$property->addCharge($charge);
}
}
$entityManager->persist($property);
$contactInvestissementImmo->getProperties()->add($property);
}
try {
$entityManager->persist($contactInvestissementImmo);
$entityManager->flush();
} catch (\Throwable $e) {
$this->logger->error("❌ Erreur lors du persist/flush Previ Immo", [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'form_data_class' => get_class($form_previimmo->getData()),
'form_valid' => $form_previimmo->isValid(),
'form_errors' => (string) $form_previimmo->getErrors(true, false),
]);
throw $e;
}
$log("Previ Immo entité persistée id=" . $contactInvestissementImmo->getId());
$contactInvestissementImmo->setReference('PREVI_IMMO_' . $contactInvestissementImmo->getId());
$entityManager->persist($contactInvestissementImmo);
$entityManager->flush();
$log("Previ Immo référence définie=" . $contactInvestissementImmo->getReference());
if ($contactInvestissementImmo->getPaymentMethod() === 'cb') {
$parameters = $this->accountingFirm->getParameters();
$price = "259,00";
$urlRetour = $this->generateUrl('monetico_return_client', ['id' => $contactInvestissementImmo->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
$urlNotif = $this->generateUrl('monetico_notification', [], UrlGeneratorInterface::ABSOLUTE_URL);
if (str_contains($this->request->getCurrentRequest()->get('_route'), 'preview')) {
$urlRetour = $this->generateUrl('previewmonetico_return_client', ['host' => $this->theHost, 'id' => $contactInvestissementImmo->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
$urlNotif = $this->generateUrl('previewmonetico_notification', ['host' => $this->theHost], UrlGeneratorInterface::ABSOLUTE_URL);
}
$log("Previ Immo paiement CB: price={$price}, reference=" . $contactInvestissementImmo->getReference());
$params = [
'tpe' => $parameters->getMoneticoTpe(),
'societe' => $parameters->getMoneticoSociete(),
'hmac_key' => $parameters->getMoneticoCle(),
'url_retour' => $urlRetour,
'url_notif' => $urlNotif,
'montant' => $price,
'reference' => $contactInvestissementImmo->getReference(),
'email' => $contactInvestissementImmo->getEmail(),
'name' => $contactInvestissementImmo->getName(),
'firstname' => $contactInvestissementImmo->getFirstname(),
'address' => $contactInvestissementImmo->getAdress(),
'zipCode' => $contactInvestissementImmo->getZipCode(),
'city' => $contactInvestissementImmo->getCity(),
];
$log("Previ Immo génération du formulaire de paiement Monetico");
return new Response($this->moneticoService->generatePaymentForm($params));
}
$this->CE->sendPreviImmo($contactInvestissementImmo);
$this->form_send_previ_immo = true;
$log("Previ Immo email envoyé, référence=" . $contactInvestissementImmo->getReference());
$urlRetour = $this->generateUrl('monetico_return_client', ['id' => $contactInvestissementImmo->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
if (str_contains($this->request->getCurrentRequest()->get('_route'), 'preview')) {
$urlRetour = $this->generateUrl('previewmonetico_return_client', ['host' => $this->theHost, 'id' => $contactInvestissementImmo->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
}
$urlRetour .= "?reference=" . $contactInvestissementImmo->getReference();
$urlRetour .= "&code-retour=paiement";
$log("Previ Immo redirection vers {$urlRetour}");
return new RedirectResponse($urlRetour);
} else {
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
$log("Previ Immo email blacklisté: {$email}");
}
} else {
$log("Previ Immo formulaire non valide ou non soumis");
}
}
} catch (\Throwable $e) {
// 🧾 Récupération sécurisée du contenu du formulaire
$formData = [];
try {
if (isset($form_previimmo) && $form_previimmo->isSubmitted()) {
$formData = [
'data' => $form_previimmo->getData(),
'submitted_data' => $request->request->all($form_previimmo->getName()),
'errors' => (string) $form_previimmo->getErrors(true, false),
];
}
} catch (\Throwable $innerE) {
$this->logger->warning('Impossible d’extraire les données du formulaire Previ Immo', [
'inner_message' => $innerE->getMessage(),
]);
}
// 🔥 Log complet de l’exception
$this->logger->error('❌ Exception non interceptée dans Previ Immo', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'request_uri' => $request->getRequestUri(),
'form_data' => $formData,
]);
return new Response("Une erreur interne est survenue", 500);
}
// newsletter
$form_newsletter = $this->createForm(NewsletterType::class, null, ['cabinet' => $this->accountingFirm]);
$form_newsletter->handleRequest($request);
$this->formnewsletterview = $form_newsletter->createView();
if ($form_newsletter->isSubmitted() && $form_newsletter->isValid()) {
$name = $form_newsletter->get('name')->getData();
$email = $form_newsletter->get('email')->getData();
// Vérifier si l'email est dans la blacklist
$blacklistRepo = $this->getDoctrine()->getRepository(EmailBlacklist::class);
if (!($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name))) {
$this->CE->sendNewsletterEmail($form_newsletter);
} elseif ($blacklistRepo->isEmailBlacklisted($email) || $blacklistRepo->isEmailBlacklisted($name)) {
// Incrémenter le compteur de tentatives
$blacklistedEmail = $blacklistRepo->findByEmail($email);
if ($blacklistedEmail) {
$blacklistedEmail->incrementBlockCount();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($blacklistedEmail);
$entityManager->flush();
}
}
$this->form_send_newsletter = true;
}
// minibook
$form_minibook = $this->createForm(MiniBookType::class);
$form_minibook->handleRequest($request);
$this->formminibookview = $form_minibook->createView();
if ($form_minibook->isSubmitted() && $form_minibook->isValid()) {
$this->CE->sendMiniEbookEmail($form_minibook);
$this->form_send_minibook = true;
}
// recrutement
$form_recrutement = $this->createForm(AnnouncementApplyType::class, null, ['cabinet' => $this->accountingFirm]);
$form_recrutement->handleRequest($request);
$this->formrecrutementview = $form_recrutement->createView();
if ($form_recrutement->isSubmitted() && $form_recrutement->isValid()) {
$this->CE->sendRecrutementEmail($form_recrutement);
$this->form_send_recrutement = true;
}
// Setup return data
$parameters['accountingFirm'] = $parameters['cabinet'] = $this->accountingFirm;
$parameters['parameters'] = $this->accountingFirm->getParameters();
$parameters['form'] = $this->formview;
$parameters['form_send'] = $this->formsend;
$parameters['form_livre'] = $this->formlivreview;
$parameters['form_send_livre'] = $this->form_send_livre;
$parameters['form_company'] = $this->formcompanyview;
$parameters['form_send_company'] = $this->form_send_company;
$parameters['form_newsletter'] = $this->formnewsletterview;
$parameters['form_send_newsletter'] = $this->form_send_newsletter;
$parameters['form_minibook'] = $this->formminibookview;
$parameters['form_send_minibook'] = $this->form_send_minibook;
$parameters['form_recrutement'] = $this->formrecrutementview;
$parameters['form_send_recrutement'] = $this->form_send_recrutement;
$parameters['form_profession'] = $this->formprofessionview;
$parameters['form_send_profession'] = $this->form_send_profession;
$parameters['form_etre_rappele'] = $this->formetrerappeleview;
$parameters['form_send_etre_rappele'] = $this->form_send_etreRappele;
$parameters['form_custom'] = $this->formcustomview;
$parameters['form_send_custom'] = $this->form_send_custom;
$parameters['form_previ_creation'] = $this->formprevicreationview;
$parameters['form_send_previ_creation'] = $this->form_send_previ_creation;
$parameters['form_previ_immo'] = $this->formpreviimmoview;
$parameters['form_send_previ_immo'] = $this->form_send_previ_immo;
if (isset($this->announcementMain[0])) {
$parameters['announcementMain'] = $this->announcementMain[0];
}
if (isset($this->announcementSpontanee[0])) {
$parameters['announcementSpontanee'] = $this->announcementSpontanee[0];
}
$parameters["DynData"] = [];
// ✅ OPTIMISATION : Éviter count() dans la boucle et appels répétés aux getters
// Utilisation de foreach au lieu de for avec count()
foreach ($this->dynDataText as $dynDataItem) {
$name = $dynDataItem->getName();
$key = str_replace(' ', '-', strtolower($name));
$parameters["DynData"][$key] = [
'name' => $name,
'data' => $dynDataItem->getData(),
'type' => $dynDataItem->getType(),
];
}
foreach ($this->dynDataArray as $dynDataItem) {
$name = $dynDataItem->getName();
$dataItems = $dynDataItem->getDataItems();
$dataItemsArray = [];
foreach ($dataItems as $item) {
$dataItemsArray[] = [
'titre' => $item->getTitle(),
'data' => $item->getData(),
];
}
$key = str_replace(' ', '-', strtolower($name));
$parameters["DynData"][$key] = [
'name' => $name,
'data' => $dataItemsArray,
'type' => $dynDataItem->getType(),
];
}
$host = $this->request->getCurrentRequest()->getHost();
if (in_array($host, ['prod.lagence.expert', 'frontdev.lagence.expert', '127.0.0.1'])) {
return parent::render($this->templateBase . $view, $parameters, $response);
} else if ($this->accountingFirm->getParameters()->isMaintenance()) {
return parent::render("/maintenance.html.twig", $parameters, $response);
} else if ($this->accountingFirm->getParameters()->isConstruction()) {
return parent::render("/maintenance.html.twig", $parameters, $response);
} else {
return parent::render($this->templateBase . $view, $parameters, $response);
}
}
private function isGibberishMessage(string $message): bool
{
$message = trim($message);
// Trop court = on laisse passer
if (mb_strlen($message) < 10) {
return false;
}
// Aucun espace → très suspect
if (strpos($message, ' ') === false) {
// Uniquement lettres/chiffres
if (preg_match('/^[a-zA-Z0-9]+$/', $message)) {
return true;
}
}
// Ratio voyelles / longueur
preg_match_all('/[aeiouyAEIOUY]/', $message, $matches);
$vowelCount = count($matches[0]);
$length = mb_strlen($message);
if ($vowelCount / $length < 0.2) {
return true;
}
return false;
}
protected function redirectRouteV2(Request $request, string $prefix = null): ?string
{
$redirect = null;
$p = $request->getRequestUri();
$pos = strpos($p, '?');
if ($pos !== false) {
$p = substr($p, 0, $pos + 1) . str_replace('?', '&', substr($p, $pos + 1));
}
$route = parse_url($p);
if (isset($route['query'])) {
parse_str($route['query'], $query);
$page = isset($query['p']) ? $query['p'] : null;
$id = isset($query['id']) ? $query['id'] : null;
$date = isset($query['date']) ? $query['date'] : null;
$search = isset($query['q']) ? $query['q'] : null;
if (!empty($page) && !is_null($page)) {
switch ($page) {
case 'transformation-digitale.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_transformation_digitale_show', ['id' => $id, 'slug' => 'actualite']);
} else {
$redirect = $this->generateUrl('client_widget_transformation_digitale_noid');
}
break;
case 'calendrier-fiscal.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_news_fisc_show', ['id' => $id]);
}
break;
case 'actualites-calendrier-fiscal.php':
if (!empty($date) && !is_null($date)) {
$redirect = $this->generateUrl('client_widget_news_fisc_list_show', ['date' => $date]);
}
break;
case 'actualite.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_news_juri_show', ['id' => $id, 'slug' => 'actualite']);
}
break;
case 'bien-etre.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_bien_etre_show', ['id' => $id, 'slug' => 'actualite']);
} else {
$redirect = $this->generateUrl('client_widget_bien_etre_noid');
}
break;
case 'actualite-cabinet.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_news_cabinet_show', ['id' => $id, 'slug' => 'actualite']);
}
break;
case 'recherche.php':
if (!empty($search) && !is_null($search)) {
$redirect = $this->generateUrl('client_widget_recherche', ['q' => $search]);
}
break;
case 'podcast.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_podcast_detail', ['id' => $id]);
} else {
$redirect = $this->generateUrl('client_widget_podcast_detail', ['id' => "list"]);
}
break;
case 'podcast-latest.php':
$podcats_latest = $this->serviceQMV2->getPodcastLatest();
$redirect = $this->generateUrl('client_widget_podcast_detail', ['id' => $podcats_latest[0]->getId()]);
break;
case 'infographie-rse.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_infographie_rse_detail', ['id' => $id]);
} else {
$redirect = $this->generateUrl('client_widget_infographie_rse_detail_noid');
}
break;
case 'participation.php':
$redirect = $this->generateUrl('client_widget_participation_pal');
break;
case 'journal.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_journal_show', ['id' => $id]);
} else {
$redirect = $this->generateUrl('client_widget_journal_noid');
}
break;
case 'aide.php':
if (!empty($id) && !is_null($id)) {
$redirect = $this->generateUrl('client_widget_aide_show', ['id' => $id]);
} else {
$redirect = $this->generateUrl('client_widget_aide_noid');
}
break;
case 'calendrier-juridique.php':
if ($date) {
$redirect = $this->generateUrl('client_widget_news_fisc_list_show', ['date' => $date]);
} else {
$redirect = $this->generateUrl('client_widget_calendrier_show');
}
break;
default:
// NOPE
break;
}
}
}
return $redirect ? $prefix . $redirect : $redirect;
}
}