src/Controller/Apollon/DefaultPublicController.php line 359

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Apollon;
  3. use App\Entity\Apollon\Brick;
  4. use App\Entity\Apollon\EditorialContent;
  5. use App\Entity\Apollon\NewsBlog;
  6. use App\Entity\Apollon\Showcase;
  7. use App\Entity\Apollon\Website;
  8. use App\Entity\Apollon\WebsiteInstance;
  9. use App\Entity\Apollon\WebsitePage;
  10. use App\Entity\Apollon\WebsiteTemplate;
  11. use App\Entity\Asclepios\Appointment;
  12. use App\Entity\Asclepios\Clinic;
  13. use App\Entity\Asclepios\Order;
  14. use App\Entity\Athena\User;
  15. use App\Service\Apollon\AksimetService;
  16. use App\Service\Apollon\BrickService;
  17. use App\Service\Apollon\ModulePageService;
  18. use App\Service\Apollon\MRVVetoService;
  19. use App\Service\Apollon\ParametersService;
  20. use App\Service\Apollon\WebsiteTemplateService;
  21. use App\Service\Asclepios\ClinicService;
  22. use App\Service\Asclepios\OrderService;
  23. use App\Service\Athena\DashboardService;
  24. use App\Service\Apollon\WebsiteService;
  25. use App\Service\Helios\HeliosService;
  26. use Random\RandomException;
  27. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  28. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  29. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  30. use Symfony\Component\HttpFoundation\Cookie;
  31. use Symfony\Component\HttpFoundation\JsonResponse;
  32. use Symfony\Component\HttpFoundation\Request;
  33. use Symfony\Component\HttpFoundation\Response;
  34. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  35. use Symfony\Component\Mailer\MailerInterface;
  36. use Symfony\Component\Mime\Email;
  37. use Symfony\Component\Routing\Annotation\Route;
  38. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  39. use Symfony\Component\Security\Core\Security;
  40. use Doctrine\ORM\EntityManagerInterface;
  41. use Symfony\Component\HttpFoundation\HeaderUtils;
  42. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  43. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  44. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  45. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface as HttpClientTransportExceptionInterface;
  46. use Symfony\Contracts\HttpClient\HttpClientInterface;
  47. use Symfony\Contracts\Translation\TranslatorInterface;
  48. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  49. use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
  50. class DefaultPublicController extends AbstractController
  51. {
  52.     const BANNED_CONTACT_WORDS = [
  53.         'click here',
  54.         'download now',
  55.         'subscribe',
  56.         'join now',
  57.         'register',
  58.         'sign up',
  59.         'get started',
  60.         'act now',
  61.         'don\'t miss out',
  62.         'apply here',
  63.         'try now',
  64.         'learn more',
  65.         'find out',
  66.         'check out',
  67.         'read more',
  68.         'start now',
  69.         'visit our website',
  70.         'use this link',
  71.         'click this link',
  72.         'follow this link',
  73.         'update your info',
  74.         'claim your offer',
  75.         'redeem now',
  76.         'access now',
  77.         'activate now',
  78.         'get yours',
  79.         'shop now',
  80.         'order now',
  81.         'buy now',
  82.         'take action',
  83.         'see more',
  84.         'view more',
  85.         'unveil',
  86.         'unlock',
  87.         'reveal',
  88.         'avail now',
  89.         'participate now',
  90.         'enroll now',
  91.         'reserve now',
  92.         'save now',
  93.         'keep up',
  94.         'catch up',
  95.         'check in',
  96.         'log in',
  97.         'log on',
  98.         'reach out',
  99.         'contact us',
  100.         'email us',
  101.         'call now',
  102.         'message us',
  103.         'life-changing',
  104.         'once in a lifetime',
  105.         'unbelievable',
  106.         'miracle',
  107.         'revolutionary',
  108.         'amazing',
  109.         'incredible',
  110.         'fantastic',
  111.         'extraordinary',
  112.         'never before seen',
  113.         'jaw-dropping',
  114.         'groundbreaking',
  115.         'unprecedented',
  116.         'mind-blowing',
  117.         'astounding',
  118.         'sensational',
  119.         'staggering',
  120.         'phenomenal',
  121.         'marvelous',
  122.         'breathtaking',
  123.         'spectacular',
  124.         'top-notch',
  125.         'ultimate',
  126.         'premier',
  127.         'exclusive',
  128.         'exceptional',
  129.         'elite',
  130.         'superior',
  131.         'unmatched',
  132.         'unrivaled',
  133.         'perfect',
  134.         'optimal',
  135.         'best',
  136.         'greatest',
  137.         'no. 1',
  138.         'leading',
  139.         'foremost',
  140.         'paramount',
  141.         'supreme',
  142.         'transcendent',
  143.         'magnificent',
  144.         'majestic',
  145.         'epic',
  146.         'legendary',
  147.         'iconic',
  148.         'unique',
  149.         'genuine',
  150.         'authentic',
  151.         'certified',
  152.         'official',
  153.         'real',
  154.         'proven',
  155.         'tested',
  156.         'trusted',
  157.         'reliable',
  158.         'secure',
  159.         'safe',
  160.         'effective',
  161.         'efficient',
  162.         'powerful',
  163.         'strong',
  164.         'potent',
  165.         'intense',
  166.         'massive',
  167.         'huge',
  168.         'enormous',
  169.         'giant',
  170.         'immense',
  171.         'vast',
  172.         'expansive',
  173.         'comprehensive',
  174.         'extensive',
  175.         'wide-ranging',
  176.         'all-encompassing',
  177.         'complete',
  178.         'maximum',
  179.         'absolute',
  180.         'sheer',
  181.         'utter',
  182.         'ultimate',
  183.         'money',
  184.         'cash',
  185.         'profit',
  186.         'dollar',
  187.         '$',
  188.         'income',
  189.         'earnings',
  190.         'payday',
  191.         'salary',
  192.         'revenue',
  193.         'returns',
  194.         'dividend',
  195.         'capital',
  196.         'financial freedom',
  197.         'wealth',
  198.         'rich',
  199.         'millionaire',
  200.         'billionaire',
  201.         'money-making',
  202.         'cash back',
  203.         'cash bonus',
  204.         'cash advance',
  205.         'quick cash',
  206.         'fast cash',
  207.         'easy money',
  208.         'extra income',
  209.         'additional income',
  210.         'double your income',
  211.         'triple your income',
  212.         'make money',
  213.         'earn cash',
  214.         'earn money',
  215.         'passive income',
  216.         'investment',
  217.         'invest',
  218.         'payout',
  219.         'fund',
  220.         'funding',
  221.         'grant',
  222.         'financial independence',
  223.         'tax',
  224.         'deduction',
  225.         'save money',
  226.         'saving',
  227.         'savings',
  228.         'financial gain',
  229.         'financial success',
  230.         'secure your finances',
  231.         'economic',
  232.         'economical',
  233.         'profitable',
  234.         'profits',
  235.         'bank',
  236.         'banking',
  237.         'bankroll',
  238.         'fortune',
  239.         'jackpot',
  240.         'windfall',
  241.         'bet',
  242.         'betting',
  243.         'wager',
  244.         'financial windfall',
  245.         'budget',
  246.         'budgetary',
  247.         'low cost',
  248.         'cost-effective',
  249.         'price',
  250.         'priced',
  251.         'cheap',
  252.         'cheaper',
  253.         'cheapest',
  254.         'discount',
  255.         'discounted',
  256.         'offer',
  257.         'promotion',
  258.         'sale',
  259.         'deal',
  260.         'bargain',
  261.         'value',
  262.         'valuable',
  263.         'inexpensive',
  264.         'cut-rate',
  265.         'slash prices',
  266.         'owner',
  267.         'quick thought',
  268.         'your website',
  269.         'great content',
  270.         'engaging',
  271.         'site abandon',
  272.         'software',
  273.         'advertising',
  274.         'ad rejections',
  275.         'your ads',
  276.         'flat rate',
  277.         'scaling',
  278.         'affiliate',
  279.         'campaign',
  280.     ];
  281.     private BrickService $brickService;
  282.     private DashboardService $dashboardService;
  283.     private MRVVetoService $mrvvetoService;
  284.     private EntityManagerInterface $entityManager;
  285.     private HeliosService $heliosService;
  286.     private HttpClientInterface $client;
  287.     private MailerInterface $mailer;
  288.     private ModulePageService $modulePageService;
  289.     private OrderService $orderService;
  290.     private ParametersService $parameterService;
  291.     private Security $security;
  292.     private TranslatorInterface $translator;
  293.     private WebsiteService $websiteService;
  294.     private TokenStorageInterface $tokenStorage;
  295.     private ?User $user;
  296.     private ?array $address;
  297.     private string $prefix;
  298.     private ?string $preview;
  299.     private int $isAdmin 0;
  300.     private ?Request $request;
  301.     private ?Website $website;
  302.     private array $message = [];
  303.     private bool $iframe;
  304.     private bool $finalPreviewInIframe;
  305.     private array $args;
  306.     private string $page;
  307.     private ClinicService $clinicService;
  308.     private WebsiteTemplateService $websiteTemplateService;
  309.     public function __construct(
  310.         BrickService           $brickService,
  311.         DashboardService       $dashboardService,
  312.         MRVVetoService         $mrvvetoService,
  313.         EntityManagerInterface $entityManager,
  314.         HeliosService          $heliosService,
  315.         HttpClientInterface    $client,
  316.         MailerInterface        $mailer,
  317.         ModulePageService      $modulePageService,
  318.         OrderService           $orderService,
  319.         ParametersService      $parameterService,
  320.         Security               $security,
  321.         TranslatorInterface    $translator,
  322.         WebsiteService         $websiteService,
  323.         TokenStorageInterface  $tokenStorage,
  324.         ClinicService          $clinicService,
  325.         WebsiteTemplateService $websiteTemplateService,
  326.         private AksimetService $aksimetService
  327.     )
  328.     {
  329.         $this->brickService $brickService;
  330.         $this->dashboardService $dashboardService;
  331.         $this->mrvvetoService $mrvvetoService;
  332.         $this->entityManager $entityManager;
  333.         $this->heliosService $heliosService;
  334.         $this->client $client;
  335.         $this->mailer $mailer;
  336.         $this->modulePageService $modulePageService;
  337.         $this->orderService $orderService;
  338.         $this->parameterService $parameterService;
  339.         $this->security $security;
  340.         $this->translator $translator;
  341.         $this->websiteService $websiteService;
  342.         $this->tokenStorage $tokenStorage;
  343.         $this->finalPreviewInIframe false;
  344.         $this->prefix '';
  345.         $this->clinicService $clinicService;
  346.         $this->websiteTemplateService $websiteTemplateService;
  347.         $this->user null;
  348.         $this->address = [];
  349.     }
  350.     public function index(Request $requeststring $page ''): Response
  351.     {
  352.         $this->request $request;
  353.         $this->iframe = isset($_SERVER['HTTP_SEC_FETCH_DEST']) && $_SERVER['HTTP_SEC_FETCH_DEST'] === 'iframe';
  354.         $this->preview null;
  355.         if ($this->iframe) {
  356.             if (count($preview explode(','$request->query->get('preview'''))) == 2) {
  357.                 $this->preview $preview[0];
  358.                 $this->isAdmin $preview[1];
  359.             }
  360.         }
  361.         $this->args explode('/'$page);
  362.         $this->page array_shift($this->args);
  363.         $this->website $this->websiteService->getWebsiteFromDomainName($this->request->getHost());
  364.         return $this->mainRender();
  365.     }
  366.     #[Route('/public/digital/websiteTemplate/{websiteTemplate}/livePreview/{page}'name'adminDigitalWebsiteTemplateLivePreview'requirements: ['page' => '.+'])]
  367.     public function preview(Request $requestWebsiteTemplate $websiteTemplate$page ''): Response
  368.     {
  369.         $this->request $request;
  370.         $this->iframe = isset($_SERVER['HTTP_SEC_FETCH_DEST']) && $_SERVER['HTTP_SEC_FETCH_DEST'] === 'iframe';
  371.         $this->preview md5(microtime());
  372.         $this->prefix '/public/digital/websiteTemplate/' $websiteTemplate->getId() . '/livePreview';
  373.         $this->args explode('/'$page);
  374.         $this->page array_shift($this->args);
  375.         $this->website = new Website();
  376.         $this->website->setTemplate($websiteTemplate);
  377.         $this->website->setPreviewToken($this->preview);
  378.         if ($websiteInstance $this->entityManager->getRepository(WebsiteInstance::class)->findOneByTemplate($websiteTemplate)) {
  379.             $this->website->setColorTheme($websiteInstance->getColortheme());
  380.             $this->website->setPrimaryColor($websiteInstance->getPrimaryColor());
  381.             $this->website->setSecondaryColor($websiteInstance->getSecondaryColor());
  382.         }
  383.         return $this->mainRender();
  384.     }
  385.     #[Route('/public/digital/websiteTemplate/{websiteTemplate}/{uuid}/livePreviewWithClinic/{page}'name'adminDigitalWebsiteTemplateLivePreviewWithClinic'requirements: ['page' => '.+'])]
  386.     public function previewWithClinic(Request $requestWebsiteTemplate $websiteTemplate$uuid$page ''): Response
  387.     {
  388.         $this->request $request;
  389.         $this->iframe = isset($_SERVER['HTTP_SEC_FETCH_DEST']) && $_SERVER['HTTP_SEC_FETCH_DEST'] === 'iframe';
  390.         $this->preview md5(microtime());
  391.         $this->prefix '/public/digital/websiteTemplate/' $websiteTemplate->getId() . '/' $uuid '/livePreviewWithClinic';
  392.         $this->args explode('/'$page);
  393.         $this->page array_shift($this->args);
  394.         $this->website = new Website();
  395.         $this->website->setTemplate($websiteTemplate);
  396.         $this->website->setPreviewToken($this->preview);
  397.         if ($websiteInstance $this->entityManager->getRepository(WebsiteInstance::class)->findOneByTemplate($websiteTemplate)) {
  398.             $this->website->setColorTheme($websiteInstance->getColortheme());
  399.             $this->website->setPrimaryColor($websiteInstance->getPrimaryColor());
  400.             $this->website->setSecondaryColor($websiteInstance->getSecondaryColor());
  401.         }
  402.         if ($showcase $this->entityManager->getRepository(Showcase::class)->findOneByUuid($uuid)) {
  403.             $this->website->setClinic($showcase->getClinic());
  404.         }
  405.         return $this->mainRender();
  406.     }
  407.     #[Route('/public/digital/websiteTemplate/{websiteTemplate}/{uuid}/finalPreviewWrapper'name'adminDigitalWebsiteTemplateFinalPreviewWrapper')]
  408.     public function finalPreviewWrapper(WebsiteTemplate $websiteTemplate$uuid): Response
  409.     {
  410.         return $this->render('Apollon/Showcase/finalPreviewWrapper.html.twig', [
  411.             'url' => $this->generateUrl('adminDigitalWebsiteTemplateFinalPreview', [
  412.                 'websiteTemplate' => $websiteTemplate->getId(),
  413.                 'uuid' => $uuid,
  414.             ],
  415.                 UrlGeneratorInterface::ABSOLUTE_URL)
  416.         ]);
  417.     }
  418.     #[Route('/public/digital/websiteTemplate/{websiteTemplate}/{uuid}/finalPreview/{page}'name'adminDigitalWebsiteTemplateFinalPreview'requirements: ['page' => '.+'])]
  419.     public function finalPreview(Request $requestWebsiteTemplate $websiteTemplate$uuid$page ''): Response
  420.     {
  421.         $this->request $request;
  422.         $this->iframe = isset($_SERVER['HTTP_SEC_FETCH_DEST']) && $_SERVER['HTTP_SEC_FETCH_DEST'] === 'iframe';
  423.         $this->finalPreviewInIframe true;
  424.         $this->preview '';
  425.         $this->prefix '/public/digital/websiteTemplate/' $websiteTemplate->getId() . '/' $uuid '/finalPreview';
  426.         $this->args explode('/'$page);
  427.         $this->page array_shift($this->args);
  428.         $this->website = new Website();
  429.         $this->website->setTemplate($websiteTemplate);
  430.         $this->website->setPreviewToken(md5(microtime()));
  431.         if ($websiteInstance $this->entityManager->getRepository(WebsiteInstance::class)->findOneByTemplate($websiteTemplate)) {
  432.             $this->website->setColorTheme($websiteInstance->getColortheme());
  433.             $this->website->setPrimaryColor($websiteInstance->getPrimaryColor());
  434.             $this->website->setSecondaryColor($websiteInstance->getSecondaryColor());
  435.         }
  436.         if ($showcase $this->entityManager->getRepository(Showcase::class)->findOneByUuid($uuid)) {
  437.             $this->website->setClinic($showcase->getClinic());
  438.         }
  439.         return $this->mainRender();
  440.     }
  441.     public function mainRender(): Response
  442.     {
  443.         $this->fillUserInformations();
  444.         if (
  445.             ($this->website) &&
  446.             (
  447.                 !$this->iframe ||
  448.                 $this->finalPreviewInIframe ||
  449.                 (
  450.                     $this->preview &&
  451.                     $this->website->getPreviewToken() === $this->preview
  452.                 )
  453.             )
  454.         ) {
  455.             if ($this->website->getMaintenance() && is_null($this->user)) {
  456.                 $response = new Response(
  457.                     $this->renderView('Apollon/maintenance.html.twig', [
  458.                         'website' => $this->website,
  459.                         'error' => '',
  460.                     ]), 503
  461.                 );
  462.                 $response->headers->clearCookie('auto_login''/'$this->request->getHost());
  463.                 return $response;
  464.             }
  465.             try {
  466.                 $this->request->getSession()->set('maybeNewContactFormToken'bin2hex(random_bytes(32)));
  467.             } catch (RandomException $e) {
  468.                 $this->request->getSession()->set('maybeNewContactFormToken''12345678123456781234567812345678');
  469.             }
  470.             $this->message $this->handleContactForm();
  471.             $response = match ($this->page) {
  472.                 '' => $this->homepage(),
  473.                 'prendre-rendez-vous' => $this->appointment(),
  474.                 'mon-compte''mon-compte-order''mon-compte-rdv' => $this->myAccount($this->page),
  475.                 'mon-compte-password''mon-compte-forget''mon-compte-creation' => $this->myAccount($this->pagefalse),
  476.                 'mentions-legales' => $this->legalNotice(),
  477.                 'disconnect' => $this->disconnect(),
  478.                 'getSSOCookie' => $this->getSSOCookie(),
  479.                 'getCartCookie' => $this->getCartCookie(),
  480.                 'sitemap' => $this->generateWebSiteSiteMaps(),
  481.                 'robots.txt' => $this->generateRobotsTxt(),
  482.                 'condititons-generales' => $this->getGeneralConditionPageLink(),
  483.                 default => $this->renderPage(),
  484.             };
  485.             if ($response->getStatusCode() === 200) {
  486.                 $this->request->getSession()->set('contactFormToken'$this->request->getSession()->get('maybeNewContactFormToken'));
  487.             }
  488.             return $response;
  489.         }
  490.         if ($this->request->getHost() === $this->getParameter('pro.domain_name')) {
  491.             $fetch = ('fetch' === $this->request->headers->get('A-Sending-Method'));
  492.             try {
  493.                 $forbidden $this->renderView($fetch 'Athena/errorFetch.html.twig' 'Athena/error.html.twig', ['url' => $this->getParameter('pro.domain_name')]);
  494.             } catch (\Exception $e) {
  495.                 $forbidden $e->getMessage();
  496.             }
  497.             if ($fetch) {
  498.                 return new JsonResponse(['a-main' => $forbidden], 403);
  499.             } else {
  500.                 return new Response($forbidden403);
  501.             }
  502.         } else {
  503.             return $this->renderNotFoundPage();
  504.         }
  505.     }
  506.     public function getSSOCookie(): BinaryFileResponse
  507.     {
  508.         $response = new BinaryFileResponse(realpath($this->getParameter('kernel.project_dir')) . '/public/olympe/invisible_pixel.png');
  509.         if (
  510.             isset($this->args[0]) &&
  511.             isset($this->args[1]) &&
  512.             ($user $this->entityManager->getRepository(User::class)->find($this->args[0])) &&
  513.             ($user->getTempTokenForSSO() === $this->args[1])
  514.         ) {
  515.             $response->headers->setCookie(Cookie::create('auto_login'$user->getEmail() . ':' bin2hex(md5($this->request->getHost() . $user->getId() . $this->args[1])), time() + 3600 24 30'/'$this->request->getHost(), truetruefalseCookie::SAMESITE_NONE));
  516.         }
  517.         return $response;
  518.     }
  519.     public function getCartCookie(): BinaryFileResponse
  520.     {
  521.         $response = new BinaryFileResponse(realpath($this->getParameter('kernel.project_dir')) . '/public/olympe/invisible_pixel.png');
  522.         if (isset($this->args[0])) {
  523.             $response->headers->setCookie(Cookie::create('cart_number_products'$this->args[0], time() + 3600 24 30'/'$this->request->getHost(), truetruefalseCookie::SAMESITE_NONE));
  524.         }
  525.         return $response;
  526.     }
  527.     private function renderPage(): Response
  528.     {
  529.         $header $this->decodeArgs();
  530.         foreach ($this->website->getPages() as $websitePage) {
  531.             if ($websitePage->getPage()?->getCategory()?->getPagePath() === $this->page) {
  532.                 $addon = [
  533.                     'websitePage' => $websitePage,
  534.                     'metaTitle' => $websitePage->getMetaTitle(),
  535.                     'metaDescription' => $websitePage->getMetaDescription(),
  536.                     'dark' => $this->website->getTemplate()->getDarkenPrimaryColor(),
  537.                 ];
  538.                 return $this->wrappedPage(array_merge(
  539.                     count($header) > ?
  540.                         $header :
  541.                         ['title' => $websitePage->getLabel()],
  542.                     $addon),
  543.                     $this->modulePageService->renderModulePage($websitePage$this->website$this->args$this->preview$this->prefix$this->message$this->isAdmin)
  544.                 );
  545.             }
  546.         }
  547.         return $this->renderNotFoundPage();
  548.     }
  549.     private function decodeArgs(): array
  550.     {
  551.         $header = [];
  552.         $decoder $this->getParameter('arg_decoder');
  553.         foreach ($this->args as $key => $val) {
  554.             $datas explode('-'$val);
  555.             if (
  556.                 isset($datas[0]) &&
  557.                 isset($decoder[$datas[0]]) &&
  558.                 isset($decoder[$datas[0]]['entity']) &&
  559.                 $decoder[$datas[0]]['entity'] &&
  560.                 isset($decoder[$datas[0]]['method']) &&
  561.                 $decoder[$datas[0]]['method'] &&
  562.                 isset($datas[1]) &&
  563.                 is_numeric($datas[1])
  564.             ) {
  565.                 if ($value $this->getDoctrine()->getManager()->getRepository($decoder[$datas[0]]['entity'])?->{$decoder[$datas[0]]['method']}($datas[1])) {
  566.                     unset($this->args[$key]);
  567.                     $this->args[$datas[0]] = $value;
  568.                     if (count($header) === 0) {
  569.                         $header $this->websiteService->getHeaderForPublicWrappedPage($value);
  570.                     }
  571.                 }
  572.             }
  573.         }
  574.         return $header;
  575.     }
  576.     private function handleContactForm(): array
  577.     {
  578.         $session $this->request->getSession();
  579.         if (
  580.             isset($_POST['contactFormToken']) &&
  581.             $_POST['contactFormToken'] == $session->get('contactFormToken') &&
  582.             $this->website->getClinic() &&
  583.             $this->website->getClinic()->getEmail()
  584.         ) {
  585.             if ($this->testRecaptcha()) {
  586.                 $content '';
  587.                 if (isset($_POST['firstname']) && isset($_POST['lastname']) && isset($_POST['email']) && isset($_POST['message'])) {
  588.                     $content $_POST['firstname'] . ' ' $_POST['lastname'] . ' vous a envoyé un message depuis le formulaire de contact de votre site web.<br/><br/>
  589.                                 Son email : ' $_POST['email'] . '<br/><br/>
  590.                                 Voici son message :<br/>' $_POST['message'];
  591.                 } else {
  592.                     foreach ($_POST as $key => $val) {
  593.                         if (!in_array($key, ['contactFormToken''form-request'])) {
  594.                             $content .= $key ' : ' $val "\r\n";
  595.                         }
  596.                     }
  597.                 }
  598.                 $email = (new TemplatedEmail())
  599.                     ->from('nepasrepondre@clubvet.fr')
  600.                     ->to($this->website->getClinic()->getEmailContactForm() ?? $this->website->getClinic()->getEmail())
  601.                     ->subject('Mail reçu du site web' . ($_POST['form-request'] ? ' : ' $_POST['form-request'] : ''))
  602.                     ->htmlTemplate('Apollon/Email/genericMail.html.twig')
  603.                     ->context([
  604.                         'base_url' => $this->request->getScheme() . '://' $this->request->getHttpHost() . $this->request->getBasePath(),
  605.                         'content' => $content,
  606.                     ]);
  607.                 try {
  608.                     $this->mailer->send($email);
  609.                     return ['status' => 'ok''message' => 'Mail envoyé !'];
  610.                 } catch (TransportExceptionInterface $e) {
  611.                     return ['status' => 'error''message' => $e->getMessage()];
  612.                 }
  613.             } else {
  614.                 return ['status' => 'error''message' => 'Vous êtes un robot !'];
  615.             }
  616.         }
  617.         return [];
  618.     }
  619.     private function testRecaptcha(): bool
  620.     {
  621.         if (isset($_POST['messageSubject']) && $_POST['messageSubject'] != '') {
  622.             return false;
  623.         }
  624.         $message trim(($_POST['message'] ?? ''));
  625.         if (empty($message) || $this->containsBannedWord($message)) {
  626.             return false;
  627.         }
  628.         if (
  629.             ($secret $this->website->getRecaptchaSecretKey()) &&
  630.             isset($_POST['g-recaptcha-response']) &&
  631.             ($captcha $_POST['g-recaptcha-response'])
  632.         ) {
  633.             $file realpath($this->getParameter('kernel.project_dir')) . '/private/recaptcha_log.txt';
  634.             file_put_contents($filedate('Y-m-d H:i:s') . ' - ' $this->website->getDomainName() . ' - 'FILE_APPEND);
  635.             $response file_get_contents(
  636.                 "https://www.google.com/recaptcha/api/siteverify?secret=" $secret .
  637.                 "&response=" $captcha .
  638.                 "&remoteip=" $_SERVER['REMOTE_ADDR']
  639.             );
  640.             file_put_contents($file$response "\r\n"FILE_APPEND);
  641.             $response json_decode($response);
  642.             if ($response->success != true) {
  643.                 return false;
  644.             }
  645.             try {
  646.                 $spamScore $this->aksimetService->getSpamScore(
  647.                     $message,
  648.                     $this->request->getClientIp() ?? '',
  649.                     $this->request->headers->get('User-Agent') ?? '',
  650.                     $_POST['email'] ?? '',
  651.                     trim(($_POST['firstname'] ?? '') . ' ' . ($_POST['lastname'] ?? '')),
  652.                     'contact‑form',
  653.                     new \DateTime('now')
  654.                 );
  655.                 if ($spamScore === 2) {
  656.                     return false;
  657.                 }
  658.             } catch (HttpClientTransportExceptionInterface $e) {
  659.                 // ignore voluntary
  660.             }
  661.             return true;
  662.         }
  663.         return false;
  664.     }
  665.     /**
  666.      * Check if the message contains banned words
  667.      * @param string $message The message to check
  668.      * @return bool True if the message is valid, False if it contains banned words
  669.      */
  670.     private function containsBannedWord(string $message): bool
  671.     {
  672.         $message trim($message);
  673.         if (empty($message)) {
  674.             return false;
  675.         }
  676.         // Protection against XSS attacks
  677.         $message htmlspecialchars($messageENT_QUOTES'UTF-8');
  678.         $message mb_strtolower($message);
  679.         foreach (self::BANNED_CONTACT_WORDS as $bannedWord) {
  680.             if (empty($bannedWord)) {
  681.                 continue;
  682.             }
  683.             $bannedWord mb_strtolower(trim($bannedWord));
  684.             $pattern '/(?:^|[^\p{L}\p{N}])' preg_quote($bannedWord'/') . '(?:[^\p{L}\p{N}]|$)/u';
  685.             if (preg_match($pattern$message)) {
  686.                 return true;
  687.             }
  688.         }
  689.         return false;
  690.     }
  691.     /*
  692.     ## Methods that serve different pages of the public website
  693.     */
  694.     private function homepage(): Response
  695.     {
  696.         $html $this->renderView('Apollon/base.html.twig', [
  697.             'body' => $this->websiteService->renderHTML($this->websitetrue$this->message$this->preview$this->prefix$this->isAdmin),
  698.             'website' => $this->website,
  699.             'contactFormToken' => $this->request->getSession()->get('contactFormToken'),
  700.             'preview' => $this->preview,
  701.             'prefix' => $this->prefix,
  702.             'websiteTemplateFonts' => $this->websiteTemplateService->getFonts($this->website->getTemplate()),
  703.         ]);
  704.         if ($this->request->getSession()->has('askForSSOCookie')) {
  705.             $this->addCookieImgToHtml($html);
  706.         }
  707.         $response = new Response($html200);
  708.         $response->headers->clearCookie('auto_login''/'$this->request->getHost());
  709.         return $response;
  710.     }
  711.     private function wrappedPage(array $headerstring $content$code 200): Response
  712.     {
  713.         $html $this->renderView('Apollon/page.html.twig'array_merge($header, [
  714.             'header' => $this->brickService->renderHeaderHTML($this->websitepreview$this->previewprefix$this->prefixpage$this->pageisAdmin$this->isAdmin),
  715.             'content' => $content,
  716.             'aside' => $this->brickService->renderAsideHTML($this->websitepreview$this->previewprefix$this->prefixpage$this->pageisAdmin$this->isAdmin),
  717.             'footer' => $this->brickService->renderFooterHTML($this->websitepreview$this->previewprefix$this->prefixpage$this->pageisAdmin$this->isAdmin),
  718.             'website' => $this->website,
  719.             'preview' => $this->preview,
  720.             'prefix' => $this->prefix,
  721.             'websiteTemplateFonts' => $this->website?->getTemplate() ? $this->websiteTemplateService->getFonts($this->website->getTemplate()) : [],
  722.         ]));
  723.         if ($this->request->getSession()->has('askForSSOCookie')) {
  724.             $this->addCookieImgToHtml($html);
  725.         }
  726.         $response = new Response($html$code);
  727.         $response->headers->clearCookie('auto_login''/'$this->request->getHost());
  728.         return $response;
  729.     }
  730.     private function addCookieImgToHtml(&$html)
  731.     {
  732.         try {
  733.             $response $this->client->request(
  734.                 'GET',
  735.                 $this->getParameter('prestashop.url') .
  736.                 '/module/cvs_connect_sso/getSSOToken?customer_email=' .
  737.                 $this->user?->getEmail()
  738.             );
  739.             $html .= '<img src="' .
  740.                 $this->getParameter('prestashop.url') .
  741.                 '/module/cvs_connect_sso/getSSOCookie?customer_email=' .
  742.                 $this->user?->getEmail() .
  743.                 '&token=' $response->getContent() . '" alt=""/>';
  744.         } catch (HttpClientTransportExceptionInterface|ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) {
  745.         }
  746.     }
  747.     private function appointment(): Response
  748.     {
  749.         if (!empty($this->website->getPrimaryColor()))
  750.             $primaryColor str_replace("#"""$this->website->getPrimaryColor());
  751.         else
  752.             $primaryColor str_replace("#"""$this->website->getColorTheme()?->getPrimaryColor()?->getRgbCode());
  753.         if (!empty($this->website->getSecondaryColor()))
  754.             $secondaryColor str_replace("#"""$this->website->getSecondaryColor());
  755.         else
  756.             $secondaryColor str_replace("#"""$this->website->getColorTheme()?->getSecondaryColor()?->getRgbCode());
  757.         return $this->wrappedPage(
  758.             ['title' => 'Prendre rendez-vous'],
  759.             $this->renderView(
  760.                 'Apollon/RendezVousVeto/monrendezvousveto.html.twig',
  761.                 [
  762.                     'environment' => $this->parameterService->getParameter('mon_rendez_vous_veto_environment')->getValue(),
  763.                     'url' => $this->parameterService->getParameter('mon_rendez_vous_veto_url')->getValue(),
  764.                     'identifier' => $this->website->getClinic()->getRendezvousvetoId(),
  765.                     'primaryColor' => $primaryColor,
  766.                     'secondaryColor' => $secondaryColor,
  767.                     'rdvEnabled' => $this->website->getClinic()->getClubvetRdv(),
  768.                     'website' => $this->website,
  769.                 ]
  770.             )
  771.         );
  772.     }
  773.     private function myAccount(string $linkbool $userNeeded true): Response
  774.     {
  775.         if ($userNeeded) {
  776.             if (is_null($this->user)) {
  777.                 return $this->wrappedPage(
  778.                     ['title' => 'Mon Compte'],
  779.                     $this->renderView('Apollon/MonCompte/login.html.twig', [])
  780.                 );
  781.             }
  782.         } else {
  783.             if (!is_null($this->user)) {
  784.                 return $this->wrappedPage(
  785.                     ['title' => 'Mon compte'],
  786.                     $this->renderView(
  787.                         'Apollon/MonCompte/myaccount.html.twig',
  788.                         [
  789.                             'website' => $this->website,
  790.                             'user' => $this->user,
  791.                             'urlShop' => $this->parameterService->getParameter('url_cvs_shop')->getValue(),
  792.                             'rdvs' => $this->dashboardService->getCustomerRDVs(),
  793.                             'oldRdvs' => $this->dashboardService->getCustomerRDVs(true),
  794.                             'orders' => $this->dashboardService->getOrdersInPreparation(),
  795.                             'oldOrders' => $this->dashboardService->getOrdersInPreparation(true),
  796.                         ]
  797.                     )
  798.                 );
  799.             }
  800.         }
  801.         return match ($link) {
  802.             'mon-compte' => $this->myAccountindex(),
  803.             'mon-compte-order' => $this->myAccountOrder(),
  804.             'mon-compte-rdv' => $this->myAccountAppointment(),
  805.             'mon-compte-forget' => $this->myAccountForget(),
  806.             'mon-compte-password' => $this->myAccountPassword(),
  807.             'mon-compte-creation' => $this->myAccountCreation(),
  808.         };
  809.     }
  810.     private function myAccountIndex(): Response
  811.     {
  812.         return $this->wrappedPage(
  813.             ['title' => 'Mon Compte'],
  814.             $this->renderView(
  815.                 'Apollon/MonCompte/myaccount.html.twig',
  816.                 [
  817.                     'website' => $this->website,
  818.                     'user' => $this->user,
  819.                     'address' => $this->address,
  820.                     'urlShop' => $this->parameterService->getParameter('url_cvs_shop')?->getValue(),
  821.                     'rdvs' => $this->dashboardService->getCustomerRDVs(),
  822.                     'oldRdvs' => $this->dashboardService->getCustomerRDVs(true),
  823.                     'orders' => $this->dashboardService->getOrdersInPreparation(),
  824.                     'oldOrders' => $this->dashboardService->getOrdersInPreparation(true),
  825.                     'error' => $this->request->request->has('maj_user_public') ? $this->majInfoUser() : '',
  826.                     'user_found' => isset($_POST['search_user']) ?
  827.                         $this->entityManager->getRepository(User::class)->searchUserPublic($_POST['word_search']) :
  828.                         null,
  829.                 ]
  830.             )
  831.         );
  832.     }
  833.     private function myAccountOrder(): Response
  834.     {
  835.         if (
  836.             $this->request->query->has('id') &&
  837.             ($order $this->entityManager->getRepository(Order::class)->find($this->request->query->get('id')))
  838.         ) {
  839.             $this->fileName $order->getReference() . '.pdf';
  840.             $this->file $this->orderService->generateInvoicePDF($order);
  841.             $response = new Response($this->file);
  842.             $disposition HeaderUtils::makeDisposition(
  843.                 HeaderUtils::DISPOSITION_ATTACHMENT,
  844.                 $this->fileName
  845.             );
  846.             $response->headers->set('Content-Disposition'$disposition);
  847.             return $response;
  848.         }
  849.         return new Response();
  850.     }
  851.     private function myAccountAppointment(): Response
  852.     {
  853.         return $this->wrappedPage(
  854.             ['title' => 'Mon Compte'],
  855.             $this->renderView(
  856.                 'Apollon/MonCompte/myaccount.html.twig',
  857.                 [
  858.                     'website' => $this->website,
  859.                     'user' => $this->user,
  860.                     'address' => $this->address,
  861.                     'urlShop' => $this->parameterService->getParameter('url_cvs_shop')?->getValue(),
  862.                     'rdvs' => $this->dashboardService->getCustomerRDVs(),
  863.                     'oldRdvs' => $this->dashboardService->getCustomerRDVs(true),
  864.                     'orders' => $this->dashboardService->getOrdersInPreparation(),
  865.                     'oldOrders' => $this->dashboardService->getOrdersInPreparation(true),
  866.                     'errorRdvs' => $this->cancelAppointment(),
  867.                     'user_found' => null,
  868.                 ]
  869.             )
  870.         );
  871.     }
  872.     private function myAccountForget(): Response
  873.     {
  874.         $error '';
  875.         if ($email $this->request->request->get('email')) {
  876.             $baseurl $this->request->getScheme() . '://' $this->request->getHttpHost() . $this->request->getBasePath();
  877.             $user $this->entityManager->getRepository(User::class)->findOneByEmail($email);
  878.             if (empty($user)) {
  879.                 $error "Aucun compte utilisateur n'existe avec cet e-mail. Veuillez vous inscrire.";
  880.             } else {
  881.                 if ($user->getActive()) {
  882.                     $res $this->heliosService->updateUser([], $usertrue'user');
  883.                     $emailToSend = (new TemplatedEmail())
  884.                         ->from('nepasrepondre@clubvet.fr')
  885.                         ->to($email)
  886.                         ->priority(Email::PRIORITY_HIGH)
  887.                         ->subject('Réinitialisation de votre mot de passe')
  888.                         ->htmlTemplate('Apollon/Email/forgottenMDP.html.twig')
  889.                         ->context([
  890.                             'base_url' => $baseurl,
  891.                             'url' => $baseurl '/mon-compte-password?email=' $email '&token=' $res->getToken()
  892.                         ]);
  893.                     try {
  894.                         $this->mailer->send($emailToSend);
  895.                         $error "L'email a été envoyé.";
  896.                     } catch (TransportExceptionInterface $e) {
  897.                         $error "L'e-mail n'a pas été envoyé, veuillez réessayer : " $baseurl '/mon-compte-password?email=' $email '&token=' $res->getToken();
  898.                     }
  899.                 } else {
  900.                     $error "L'utilisateur associé à cet e-mail a été désactivé! Contactez l'administrateur du site.";
  901.                 }
  902.             }
  903.         }
  904.         return $this->wrappedPage(
  905.             ['title' => 'Mon Compte'],
  906.             $this->renderView(
  907.                 'Apollon/MonCompte/forget.html.twig',
  908.                 [
  909.                     'error' => $error,
  910.                     'email' => $email
  911.                 ]
  912.             )
  913.         );
  914.     }
  915.     private function myAccountPassword(): Response
  916.     {
  917.         $email $this->request->query->get('email');
  918.         $token $this->request->query->get('token');
  919.         $error "";
  920.         if (empty($email) || empty($token)) {
  921.             $error "Vous ne disposez pas des privilèges pour changer de mot de passe!";
  922.         } else {
  923.             $pwd $this->request->request->get('password');
  924.             $repwd $this->request->request->get('repassword');
  925.             if (!empty($pwd) && !empty($repwd)) {
  926.                 $error $this->majPassword();
  927.                 if (empty($error)) {
  928.                     return $this->wrappedPage(
  929.                         ['title' => 'Mon Compte'],
  930.                         $this->renderView('Apollon/MonCompte/login.html.twig', [])
  931.                     );
  932.                 }
  933.             }
  934.         }
  935.         return $this->wrappedPage(
  936.             ['title' => 'Mon Compte'],
  937.             $this->renderView(
  938.                 'Apollon/MonCompte/remember.html.twig',
  939.                 [
  940.                     'error' => $error,
  941.                     'email' => $email
  942.                 ]
  943.             )
  944.         );
  945.     }
  946.     private function myAccountCreation(): Response
  947.     {
  948.         $error "";
  949.         $civilite 1;
  950.         $firstname "";
  951.         $lastname "";
  952.         $email "";
  953.         $num "";
  954.         $adr "";
  955.         $cp "";
  956.         $city "";
  957.         if ($this->request->request->has('create_user_public')) {
  958.             $civilite $this->request->request->get('civilite');
  959.             $firstname $this->request->request->get('firstname');
  960.             $lastname $this->request->request->get('lastname');
  961.             $email $this->request->request->get('email');
  962.             $num $this->request->request->get('numero');
  963.             $adr $this->request->request->get('adr');
  964.             $cp $this->request->request->get('cp');
  965.             $city $this->request->request->get('city');
  966.             $error $this->createUser();
  967.             if (empty($error)) {
  968.                 return $this->wrappedPage(
  969.                     ['title' => 'Mon Compte'],
  970.                     $this->renderView('Apollon/MonCompte/login.html.twig', [
  971.                         'success' => 'Votre compte a bien été créé!'
  972.                     ])
  973.                 );
  974.             }
  975.         }
  976.         return $this->wrappedPage(
  977.             ['title' => 'Mon Compte'],
  978.             $this->renderView(
  979.                 'Apollon/MonCompte/createuser.html.twig',
  980.                 [
  981.                     'error' => $error,
  982.                     'civilite' => $civilite,
  983.                     'firstname' => $firstname,
  984.                     'lastname' => $lastname,
  985.                     'email' => $email,
  986.                     'num' => $num,
  987.                     'adr' => $adr,
  988.                     'cp' => $cp,
  989.                     'city' => $city
  990.                 ]
  991.             )
  992.         );
  993.     }
  994.     private function cancelAppointment(): string
  995.     {
  996.         if (!$this->request->query->has('event_id')) {
  997.             return 'Pas d\'identifiant passé en paramètre';
  998.         }
  999.         $id $this->request->query->get('event_id');
  1000.         if (is_null($appointment $this->entityManager->getRepository(Appointment::class)->findOneByEventId($id))) {
  1001.             return "Ce rendez-vous n'existe pas!";
  1002.         }
  1003.         if ($appointment->getClubvetCustomerId() != $this->user->getId()) {
  1004.             return "Ce rendez-vous ne vous appartient pas!";
  1005.         }
  1006.         return $this->mrvvetoService->cancelAppointment(
  1007.             $appointment,
  1008.             $this->website->getClinic(),
  1009.             $id,
  1010.             $this->request,
  1011.             $this->user,
  1012.             $this->mailer
  1013.         );
  1014.     }
  1015.     private function majInfoUser()
  1016.     {
  1017.         $firstname $this->request->request->get('firstname');
  1018.         $lastname $this->request->request->get('lastname');
  1019.         $email $this->request->request->get('email');
  1020.         $num $this->request->request->get('numero');
  1021.         $adr $this->request->request->get('adr');
  1022.         $cp $this->request->request->get('cp');
  1023.         $city $this->request->request->get('city');
  1024.         if (!$this->isName($firstname)) {
  1025.             return 'Votre prénom est invalide';
  1026.         }
  1027.         if (!$this->isName($lastname)) {
  1028.             return 'Votre nom est invalide';
  1029.         }
  1030.         $userRepository $this->entityManager->getRepository(User::class);
  1031.         if ($this->user->getEmail() == $email)
  1032.             $newUser NULL;
  1033.         else
  1034.             $newUser $userRepository->findOneByEmail($email);
  1035.         if ($newUser === NULL) {
  1036.             $customer['lastname'] = $lastname;
  1037.             $customer['firstname'] = $firstname;
  1038.             $customer['email'] = $email;
  1039.             $customer['other']['id_gender'] = $this->user->getOther()['id_gender'];
  1040.             $customer['other']['veterinaire'] = $this->website->getClinic()->getPrestashopId();
  1041.             $customer['other']['address'][0]['alias'] = 'Mon adresse';
  1042.             $customer['other']['address'][0]['company'] = '';
  1043.             $customer['other']['address'][0]['lastname'] = $lastname;
  1044.             $customer['other']['address'][0]['firstname'] = $firstname;
  1045.             $customer['other']['address'][0]['id_country'] = 8;
  1046.             $customer['other']['address'][0]['id_state'] = 0;
  1047.             $customer['other']['address'][0]['address1'] = $adr;
  1048.             $customer['other']['address'][0]['address2'] = "";
  1049.             $customer['other']['address'][0]['postcode'] = $cp;
  1050.             $customer['other']['address'][0]['city'] = $city;
  1051.             $customer['other']['address'][0]['other'] = "";
  1052.             $customer['other']['address'][0]['phone'] = "";
  1053.             $customer['other']['address'][0]['phone_mobile'] = $num;
  1054.             $this->heliosService->tracker(
  1055.                 'Front site public',
  1056.                 'Clubvet Pro -> SSO',
  1057.                 $this->translator->trans(
  1058.                     'helios.controller.helios.msg_modification_user_public',
  1059.                     ['email' => $email],
  1060.                     'Helios'
  1061.                 )
  1062.             );
  1063.             $res $this->heliosService->updateUser($customer$this->usertrue'user');
  1064.             if ($res->getId() !== NULL) {
  1065.                 $this->user $res;
  1066.                 if (array_key_exists('address'$this->user->getOther()))
  1067.                     $this->address $this->user->getOther()['address'][0];
  1068.                 $this->heliosService->dispatcherUserRequest(
  1069.                     $res,
  1070.                     'user_info'
  1071.                 );
  1072.                 return "";
  1073.             } else {
  1074.                 return "L'utilisateur n'a pas été modifié.";
  1075.             }
  1076.         } else {
  1077.             return "Un compte utilisateur existe avec la nouvelle adresse email.";
  1078.         }
  1079.     }
  1080.     private function majPassword()
  1081.     {
  1082.         $email $this->request->query->get('email');
  1083.         $token $this->request->query->get('token');
  1084.         $pwd $this->request->request->get('password');
  1085.         $repwd $this->request->request->get('repassword');
  1086.         if ($pwd === $repwd) {
  1087.             $userRepository $this->entityManager->getRepository(User::class);
  1088.             $user $userRepository->findOneByEmail($email);
  1089.             if (empty($user)) {
  1090.                 return "Aucun compte utilisateur n'existe avec cet e-mail. Veuillez vous inscrire.";
  1091.             } else {
  1092.                 if ($user->getActive()) {
  1093.                     if ($user->getToken() == $token) {
  1094.                         $data['password'] = $pwd;
  1095.                         $res $this->heliosService->updateUser($data$usertrue'user');
  1096.                         if ($res->getId() !== NULL) {
  1097.                             $this->heliosService->dispatcherUserRequest(
  1098.                                 $res,
  1099.                                 'user_info',
  1100.                                 $data['password']
  1101.                             );
  1102.                             return "";
  1103.                         } else {
  1104.                             return "Le mot de passe n'a pas été modifié.";
  1105.                         }
  1106.                     } else {
  1107.                         return "Votre token n'est plus valide ou n'existe pas!";
  1108.                     }
  1109.                 } else {
  1110.                     return "L'utilisateur associé à cet e-mail a été désactivé! Contactez l'administrateur du site.";
  1111.                 }
  1112.             }
  1113.         } else {
  1114.             return "Les mots de passe ne sont pas identiques!";
  1115.         }
  1116.     }
  1117.     private function createUser()
  1118.     {
  1119.         $civilite $this->request->request->get('civilite');
  1120.         $firstname $this->request->request->get('firstname');
  1121.         $lastname $this->request->request->get('lastname');
  1122.         $password $this->request->request->get('password');
  1123.         $repassword $this->request->request->get('repassword');
  1124.         $email $this->request->request->get('email');
  1125.         $num $this->request->request->get('numero');
  1126.         $adr $this->request->request->get('adr');
  1127.         $cp $this->request->request->get('cp');
  1128.         $city $this->request->request->get('city');
  1129.         if (!$this->isName($firstname)) {
  1130.             return 'Votre prénom est invalide';
  1131.         }
  1132.         if (!$this->isName($lastname)) {
  1133.             return 'Votre nom est invalide';
  1134.         }
  1135.         $userRepository $this->entityManager->getRepository(User::class);
  1136.         $user $userRepository->findOneByEmail($email);
  1137.         if ($user === NULL) {
  1138.             if ($password === $repassword) {
  1139.                 $customer['lastname'] = $lastname;
  1140.                 $customer['firstname'] = $firstname;
  1141.                 $customer['email'] = $email;
  1142.                 $customer['password'] = $password;
  1143.                 $customer['other']['id_gender'] = $civilite;
  1144.                 $customer['other']['veterinaire'] = $this->website->getClinic()->getPrestashopId();
  1145.                 $customer['other']['address'][0]['alias'] = 'Mon adresse';
  1146.                 $customer['other']['address'][0]['company'] = '';
  1147.                 $customer['other']['address'][0]['lastname'] = $lastname;
  1148.                 $customer['other']['address'][0]['firstname'] = $firstname;
  1149.                 $customer['other']['address'][0]['id_country'] = 8;
  1150.                 $customer['other']['address'][0]['id_state'] = 0;
  1151.                 $customer['other']['address'][0]['address1'] = $adr;
  1152.                 $customer['other']['address'][0]['address2'] = "";
  1153.                 $customer['other']['address'][0]['postcode'] = $cp;
  1154.                 $customer['other']['address'][0]['city'] = $city;
  1155.                 $customer['other']['address'][0]['other'] = "";
  1156.                 $customer['other']['address'][0]['phone'] = "";
  1157.                 $customer['other']['address'][0]['phone_mobile'] = $num;
  1158.                 $this->heliosService->tracker(
  1159.                     'Front site public',
  1160.                     'Clubvet Pro -> SSO',
  1161.                     $this->translator->trans(
  1162.                         'helios.controller.helios.msg_creation_user_front_public',
  1163.                         ['email' => $email],
  1164.                         'Helios'
  1165.                     )
  1166.                 );
  1167.                 $res $this->heliosService->createUser($customer);
  1168.                 if ($res->getId() !== NULL) {
  1169.                     $this->heliosService->dispatcherUserRequest(
  1170.                         $res,
  1171.                         'user_info',
  1172.                         $customer['password']
  1173.                     );
  1174.                     return "";
  1175.                 } else {
  1176.                     return "L'utilisateur n'a pas été créé.";
  1177.                 }
  1178.             } else {
  1179.                 return "Les mots de passe ne sont pas identiques.";
  1180.             }
  1181.         } else {
  1182.             return "Un compte utilisateur existe avec cet e-mail. Veuillez faire un rappel de mot de passe si vous l'avez oublié.";
  1183.         }
  1184.     }
  1185.     private function disconnect()
  1186.     {
  1187.         $token = new AnonymousToken('default''anon.');
  1188.         $this->tokenStorage->setToken($token);
  1189.         $this->request->getSession()->invalidate();
  1190.         return $this->wrappedPage(
  1191.             ['title' => 'Mon Compte'],
  1192.             $this->renderView('Apollon/MonCompte/login.html.twig', [])
  1193.         );
  1194.     }
  1195.     public function isName($name): bool
  1196.     {
  1197.         return preg_match($this->cleanNonUnicodeSupport('/^[^0-9!<>,;?=+()@#"°{}_$%:]*$/u'), stripslashes($name));
  1198.     }
  1199.     public function cleanNonUnicodeSupport($pattern): string
  1200.     {
  1201.         return preg_replace('/\\\[px]\{[a-z]{1,2}\}|(\/[a-z]*)u([a-z]*)$/i''$1$2'$pattern);
  1202.     }
  1203.     private function legalNotice(): Response
  1204.     {
  1205.         $legalRepresentatives = [];
  1206.         if ($this->website->getClinic()) {
  1207.             foreach ($this->website->getClinic()->getClinicEmployeeClinics() as $employee) {
  1208.                 if ($employee->getOwner()) {
  1209.                     $legalRepresentatives[] = $employee->getClinicEmployee()?->getFirstname() . ' ' strtoupper($employee->getClinicEmployee()?->getLastname());
  1210.                 }
  1211.             }
  1212.         }
  1213.         return $this->wrappedPage(
  1214.             ['title' => 'Mentions légales et données personnelles'],
  1215.             $this->renderView('Apollon/LegalNotice/legalNotice.html.twig', [
  1216.                 'clinic_sign' => $this->website->getClinic()?->getSign() ?? 'Sans nom',
  1217.                 'clinic_address' => $this->website->getClinic()?->getAddress() ?? '---',
  1218.                 'clinic_postal_code' => $this->website->getClinic()?->getPostalCode() ?? '---',
  1219.                 'clinic_city' => $this->website->getClinic()?->getCity() ?? '---',
  1220.                 'clinic_type' => strtolower($this->website->getClinic()?->getType()?->getLabel() ?? 'Clinique'),
  1221.                 'clinic_kind' => $this->website->getClinic()?->getType()?->getKind() ?? 'f',
  1222.                 'clinic_owners' => implode(', '$legalRepresentatives),
  1223.                 'clinic_url' => $this->website->getUrl(),
  1224.                 'clinic_domain_name' => $this->website->getDomainName(),
  1225.                 'clinic_recaptcha' => $this->website->getRecaptchaSecretKey(),
  1226.                 'clinic_ga' => $this->website->getGoogleAnalyticsKey(),
  1227.             ])
  1228.         );
  1229.     }
  1230.     private function renderNotFoundPage(): Response
  1231.     {
  1232.         return $this->wrappedPage(
  1233.             ['title' => 'Vous êtes perdu•e ?'],
  1234.             $this->renderView('Apollon/notFound.html.twig'),
  1235.             404
  1236.         );
  1237.     }
  1238.     public function generateWebSiteSiteMaps(): Response
  1239.     {
  1240.         $results = [];
  1241.         $clinicPages $this->clinicService->getClinicPages($this->website->getClinic(), 1000);
  1242.         $clinicTipSheets $this->clinicService->getClinicTipSheets($this->website->getClinic(), 1000);
  1243.         $pages $this->getDoctrine()->getRepository(WebsitePage::class)->findByWebsiteTemplate($this->website->getTemplate(), ['weight' => 'ASC']);
  1244.         foreach ($pages as $page) {
  1245.             $results[] = ['websitePage' => $page'subLinks' => $this->websiteService->getSubLinks($page$this->website->getClinic())];
  1246.         }
  1247.         $xml '<?xml version="1.0" encoding="UTF-8"?>';
  1248.         $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
  1249.         $xml .= '<url>';
  1250.         $xml .= '<loc>https://' $this->website->getDomainName() . '</loc>';
  1251.         $xml .= '<lastmod>' date('Y-m-d') . '</lastmod>';
  1252.         $xml .= '</url>';
  1253.         foreach ($results as $result) {
  1254.             $xml .= '<url>';
  1255.             $xml .= '<loc>https://' $this->website->getDomainName() . '/' $result['websitePage']->getPage()->getCategory()->getPagePath() . '</loc>';
  1256.             $xml .= '<lastmod>' date('Y-m-d') . '</lastmod>';
  1257.             $xml .= '</url>';
  1258.         }
  1259.         if ($this->displayNewsOnSitmap()) {
  1260.             $clinicBlogs $this->clinicService->getClinicNewsBlog($this->website->getClinic(), 1000);
  1261.             if ($clinicBlogs) {
  1262.                 if ($clinicBlogs['news']) {
  1263.                     foreach ($clinicBlogs['news'] as $newsBlog) {
  1264.                         $xml .= '<url>';
  1265.                         $xml .= '<loc>https://' $this->website->getDomainName() . '/actualites/article-' $newsBlog->getId() . '-' $newsBlog->getSlug() . '</loc>';
  1266.                         $xml .= '<lastmod>' date('Y-m-d') . '</lastmod>';
  1267.                         $xml .= '</url>';
  1268.                     }
  1269.                 }
  1270.             }
  1271.         }
  1272.         if ($clinicTipSheets) {
  1273.             if ($clinicTipSheets['sheets']) {
  1274.                 foreach ($clinicTipSheets['sheets'] as $clinicTipSheet) {
  1275.                     $xml .= '<url>';
  1276.                     $xml .= '<loc>https://' $this->website->getDomainName() . '/fiches-conseil/fiche-' $clinicTipSheet->getId() . '-' $clinicTipSheet->getSlug() . '</loc>';
  1277.                     $xml .= '<lastmod>' date('Y-m-d') . '</lastmod>';
  1278.                     $xml .= '</url>';
  1279.                 }
  1280.             }
  1281.         }
  1282.         if ($clinicPages) {
  1283.             foreach ($clinicPages as $clinicPage) {
  1284.                 $xml .= '<url>';
  1285.                 $xml .= '<loc>https://' $this->website->getDomainName() . '/pages/page-' $clinicPage->getId() . '-' $clinicPage->getSlug() . '</loc>';
  1286.                 $xml .= '<lastmod>' date('Y-m-d') . '</lastmod>';
  1287.                 $xml .= '</url>';
  1288.             }
  1289.         }
  1290.         $xml .= '</urlset>';
  1291.         $response = new Response($xml);
  1292.         $response->headers->set('Content-Type''xml');
  1293.         return $response;
  1294.     }
  1295.     public function generateRobotsTxt(): Response
  1296.     {
  1297.         return new Response("User-agent: *\r\nAllow: /\r\n\r\nSitemap: https://{$this->website->getDomainName()}/sitemap");
  1298.     }
  1299.     private function getGeneralConditionPageLink(): Response
  1300.     {
  1301.         $legalRepresentatives = [];
  1302.         if ($this->website->getClinic()) {
  1303.             foreach ($this->website->getClinic()->getClinicEmployeeClinics() as $employee) {
  1304.                 if ($employee->getOwner()) {
  1305.                     $legalRepresentatives[] = $employee->getClinicEmployee()?->getFirstname() . ' ' strtoupper($employee->getClinicEmployee()?->getLastname());
  1306.                 }
  1307.             }
  1308.         }
  1309.         $editorialContent $this->entityManager->getRepository(EditorialContent::class)
  1310.             ->findOneBy(
  1311.                 [
  1312.                     'isGeneralConditionPage' => true,
  1313.                     'clinic' => $this->website->getClinic()
  1314.                 ]
  1315.             );
  1316.         return $this->wrappedPage(
  1317.             ['title' => 'Conditions générales'],
  1318.             $this->renderView('Apollon/GeneralCondition/generalCondition.twig', [
  1319.                 'clinic_sign' => $this->website->getClinic()?->getSign() ?? 'Sans nom',
  1320.                 'clinic_address' => $this->website->getClinic()?->getAddress() ?? '---',
  1321.                 'clinic_postal_code' => $this->website->getClinic()?->getPostalCode() ?? '---',
  1322.                 'clinic_city' => $this->website->getClinic()?->getCity() ?? '---',
  1323.                 'clinic_type' => strtolower($this->website->getClinic()?->getType()?->getLabel() ?? 'Clinique'),
  1324.                 'clinic_kind' => $this->website->getClinic()?->getType()?->getKind() ?? 'f',
  1325.                 'clinic_owners' => implode(', '$legalRepresentatives),
  1326.                 'clinic_url' => $this->website->getUrl(),
  1327.                 'clinic_domain_name' => $this->website->getDomainName(),
  1328.                 'clinic_recaptcha' => $this->website->getRecaptchaSecretKey(),
  1329.                 'clinic_ga' => $this->website->getGoogleAnalyticsKey(),
  1330.                 'page' => $editorialContent
  1331.             ])
  1332.         );/*
  1333.         if ($this->website->getClinic() && $editorialContent = $this->entityManager->getRepository(EditorialContent::class)->findOneBy(['isGeneralConditionPage'=>true, 'clinic'=>$this->website->getClinic()])) {
  1334.             $website = $this->entityManager->getRepository(Website::class)->findOneBy(['clinic'=>$this->website->getClinic()->getId()]);
  1335.             return $website ? $website->getUrl().$editorialContent->getUrl(): '';
  1336.         }
  1337.         return '';*/
  1338.     }
  1339.     public function displayNewsOnSitmap()
  1340.     {
  1341.         if ($template $this->website->getTemplate()) {
  1342.             if (
  1343.                 $template->getMain() &&
  1344.                 ($module $this->getDoctrine()->getRepository(Brick::class)->find($template->getMain()->getId()))
  1345.             ) {
  1346.                 foreach ($module->getBricks() as $brick) {
  1347.                     if ($brick->getModule()?->getCategory()->getPagePath() == 'actualites') {
  1348.                         return true;
  1349.                     }
  1350.                 }
  1351.             }
  1352.             foreach ($template->getPages() as $page) {
  1353.                 if ($page->getPage()->getCategory()->getPagePath() == 'actualites') {
  1354.                     return true;
  1355.                 }
  1356.             }
  1357.         }
  1358.         return false;
  1359.     }
  1360.     private function fillUserInformations(): void
  1361.     {
  1362.         if (is_null($this->user)) {
  1363.             $this->user $this->security->getUser();
  1364.             $this->address =
  1365.                 (
  1366.                     $this->user &&
  1367.                     !empty($this->user->getOther())
  1368.                     && array_key_exists('address'$this->user->getOther())
  1369.                 ) ?
  1370.                     $this->user->getOther()['address'][0] :
  1371.                     [];
  1372.         }
  1373.     }
  1374. }