src/Controller/SearchController.php line 274

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Enum\ContratType;
  4. use App\Entity\Enum\Disponibility;
  5. use App\Entity\Enum\Experience;
  6. use App\Entity\Enum\FrenchRegion;
  7. use App\Entity\Offer;
  8. use App\Entity\Profile;
  9. use App\Entity\Publication;
  10. use App\Entity\PublicationImage;
  11. use App\Entity\User;
  12. use App\Repository\OfferAlertRepository;
  13. use App\Repository\ExternalCompanyRepository;
  14. use App\Repository\OfferRepository;
  15. use App\Repository\PackageRepository;
  16. use App\Repository\ProfileRepository;
  17. use App\Repository\ProfileVisitRepository;
  18. use App\Repository\PublicationRepository;
  19. use App\Repository\SkillRepository;
  20. use App\Repository\SocietyRepository;
  21. use App\UseCase\Package\Config;
  22. use App\UseCase\Statistics\ProfileViewStats;
  23. use DateTime;
  24. use Doctrine\ORM\EntityManagerInterface;
  25. use Knp\Component\Pager\PaginatorInterface;
  26. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  27. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  28. use Symfony\Component\HttpFoundation\Request;
  29. use Symfony\Component\HttpFoundation\Response;
  30. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  31. use Symfony\Component\Routing\Annotation\Route;
  32. class SearchController extends AbstractController
  33. {
  34.     private ExternalCompanyRepository $externalCompanyRepository;
  35.     public function __construct(ExternalCompanyRepository $externalCompanyRepository)
  36.     {
  37.         $this->externalCompanyRepository $externalCompanyRepository;
  38.     }
  39.     /* @changelog 2022-09-22 [FIX] (Anthony) Constante pour la recherche par mobilité */
  40.     const REGION 0;
  41.     const DEPARTMENT 1;
  42.     const FILTER_PERTINENCE 'pertinence';
  43.     const FILTER_DISPONIBILITY 'disponibilité';
  44.     const FILTER_CONNEXION 'connexion';
  45.     private function transformURL($maChaine): array
  46.     {
  47.         $resultat = [];
  48.         
  49.         // Décoder l'URL encodée (gère les caractères spéciaux comme %, &, #, etc.)
  50.         // Utiliser rawurldecode pour décoder correctement les caractères encodés
  51.         // rawurldecode ne lance pas d'exception, mais peut retourner des résultats inattendus
  52.         // si la chaîne contient des séquences d'encodage mal formées
  53.         
  54.         // Vérifier si la chaîne contient des caractères % non encodés (problème potentiel)
  55.         // Si c'est le cas, les remplacer par "percent" pour éviter les erreurs
  56.         if (preg_match('/%(?![0-9A-Fa-f]{2})/'$maChaine)) {
  57.             // La chaîne contient un % qui n'est pas suivi de deux chiffres hexadécimaux
  58.             // Remplacer % par "percent" pour éviter les erreurs de décodage
  59.             $maChaine str_replace('%''percent'$maChaine);
  60.         }
  61.         
  62.         // Décoder l'URL
  63.         $decoded rawurldecode($maChaine);
  64.         
  65.         // Remplacer "percent" par % dans le résultat décodé
  66.         $decoded str_replace('percent''%'$decoded);
  67.         
  68.         // Remplacer les tirets par des espaces
  69.         $resultat['search'] = str_replace('-'' '$decoded);
  70.         return $resultat;
  71.     }
  72.     /**
  73.      * @param array $location
  74.      * @param OfferRepository $offerRepository
  75.      * @return Offer[]
  76.      */
  77.     private function offerIfNofound(
  78.         array           $location,
  79.         OfferRepository $offerRepository,
  80.         array           $contrats = [],
  81.         string          $order
  82.     ): array {
  83.         $defaultSearch "";
  84.         $defaultCategorie null;
  85.         $defaultMinMax 0;
  86.         $defaultSalary 0;
  87.         /** @var Offer[] $defaultOffer */
  88.         $defaultOffer $offerRepository->findBySearch(
  89.             "",
  90.             [],
  91.             $defaultMinMax,
  92.             $defaultCategorie,
  93.             $defaultSalary,
  94.             $order,
  95.             $contrats
  96.         );
  97.         if (count($defaultOffer) == 0) {
  98.             $location $this->findParentCities($locationFrenchRegion::REGION_DEPARTEMENT);
  99.             $defaultOffer $offerRepository->findBySearch(
  100.                 $defaultSearch,
  101.                 $location,
  102.                 $defaultMinMax,
  103.                 $defaultCategorie,
  104.                 $defaultSalary,
  105.                 $defaultOrder,
  106.                 $contrats
  107.             );
  108.         }
  109.         return $defaultOffer;
  110.     }
  111.     /**
  112.      * @param array $citiesToFind
  113.      * @param array $countries
  114.      * @return array
  115.      */
  116.     private function findParentCities(array $citiesToFind, array $countries): array
  117.     {
  118.         $foundCountries = [];
  119.         if (in_array("All UAE"$citiesToFind)) {
  120.             return ["All UAE"];
  121.         }
  122.         foreach ($citiesToFind as $city) {
  123.             // Parcourir chaque pays dans le premier array
  124.             foreach ($countries as $country => $cities) {
  125.                 if ($country == $city) {
  126.                     $foundCountries[] = $country;
  127.                     break;
  128.                 }
  129.                 // Vérifier si la ville se trouve dans ce pays
  130.                 if (isset($cities[$city])) {
  131.                     $foundCountries[] = $country;
  132.                     break; // Sortir de la boucle dès qu'on a trouvé le pays
  133.                 }
  134.             }
  135.         }
  136.         return $foundCountries;
  137.     }
  138.     /**
  139.      *
  140.      * @Route("/missions-freelance", name="mission_search_default")
  141.      *
  142.      * @param Request $request
  143.      * @param OfferRepository $offerRepository
  144.      * @param OfferAlertRepository $offerAlertRepository
  145.      * @param PaginatorInterface $paginator
  146.      * @param EntityManagerInterface $entityManager
  147.      * @param SessionInterface $session
  148.      * @return Response
  149.      */
  150.     public function missionDefault(
  151.         Request                $request,
  152.         OfferRepository        $offerRepository,
  153.         OfferAlertRepository   $offerAlertRepository,
  154.         PaginatorInterface     $paginator,
  155.         EntityManagerInterface $entityManager,
  156.         SessionInterface       $session
  157.     ): Response {
  158.         return $this->missionSearch(
  159.             $request,
  160.             $offerRepository,
  161.             $offerAlertRepository,
  162.             $paginator,
  163.             $entityManager,
  164.             $session,
  165.             ""
  166.         );
  167.     }
  168.     /**
  169.      *
  170.      * @Route("/emploi", name="emploi_search_default")
  171.      *
  172.      * @param Request $request
  173.      * @param OfferRepository $offerRepository
  174.      * @param OfferAlertRepository $offerAlertRepository
  175.      * @param PaginatorInterface $paginator
  176.      * @param EntityManagerInterface $entityManager
  177.      * @param SessionInterface $session
  178.      * @return Response
  179.      */
  180.     public function emploiDefault(
  181.         Request                $request,
  182.         OfferRepository        $offerRepository,
  183.         OfferAlertRepository   $offerAlertRepository,
  184.         PaginatorInterface     $paginator,
  185.         EntityManagerInterface $entityManager,
  186.         SessionInterface       $session
  187.     ): Response {
  188.         return $this->missionSearch(
  189.             $request,
  190.             $offerRepository,
  191.             $offerAlertRepository,
  192.             $paginator,
  193.             $entityManager,
  194.             $session,
  195.             ""
  196.         );
  197.     }
  198.     /**
  199.      *
  200.      * @Route("/freelance-france", name="page_special_freelance_france")
  201.      *
  202.      * @param PublicationRepository $publicationRepository
  203.      * @return Response
  204.      */
  205.     public function pagesFrance(
  206.         PublicationRepository $publicationRepository
  207.     ): Response {
  208.         $publication $publicationRepository->findOneBy(['slug' => "freelance-france"]);
  209.         return $this->render('page/page.html.twig', [
  210.             'publication' => $publication,
  211.         ]);
  212.     }
  213.     /**
  214.      *
  215.      * @Route("/freelance-definition", name="page_special_freelance_definition")
  216.      *
  217.      * @param PublicationRepository $publicationRepository
  218.      * @return Response
  219.      */
  220.     public function pagesDefinition(
  221.         PublicationRepository $publicationRepository
  222.     ): Response {
  223.         $publication $publicationRepository->findOneBy(['slug' => "freelance-definition"]);
  224.         return $this->render('page/page.html.twig', [
  225.             'publication' => $publication,
  226.         ]);
  227.     }
  228.     /**
  229.      *
  230.      * @Route("/freelance-informatique", name="page_special_freelance_informatique")
  231.      *
  232.      * @param PublicationRepository $publicationRepository
  233.      * @return Response
  234.      */
  235.     public function pagesinformatique(
  236.         PublicationRepository $publicationRepository
  237.     ): Response {
  238.         $publication $publicationRepository->findOneBy(['slug' => "freelance-informatique"]);
  239.         return $this->render('page/page.html.twig', [
  240.             'publication' => $publication,
  241.         ]);
  242.     }
  243.     /**
  244.      *
  245.      * @Route("/freelance-jobs", name="page_special_freelance_jobs")
  246.      *
  247.      * @param PublicationRepository $publicationRepository
  248.      * @return Response
  249.      */
  250.     public function pagesJobs(
  251.         PublicationRepository $publicationRepository
  252.     ): Response {
  253.         $publication $publicationRepository->findOneBy(['slug' => "freelance-jobs"]);
  254.         return $this->render('page/page.html.twig', [
  255.             'publication' => $publication,
  256.         ]);
  257.     }
  258.     /**
  259.      *
  260.      * @Route("/freelance-info", name="page_special_info")
  261.      *
  262.      * @param PublicationRepository $publicationRepository
  263.      * @return Response
  264.      */
  265.     public function missionInfo(
  266.         PublicationRepository $publicationRepository
  267.     ): Response {
  268.         $publication $publicationRepository->findOneBy(['slug' => "freelance-info"]);
  269.         return $this->render('page/page.html.twig', [
  270.             'publication' => $publication,
  271.         ]);
  272.     }
  273.     /**
  274.      *
  275.      *  PAGE SPECIAL POUR L'AFFICHAGE D'UNE INFO
  276.      *
  277.      * @Route("/emploi-paris", name="mission_search_paris")
  278.      *
  279.      * @param Request $request
  280.      * @param OfferRepository $offerRepository
  281.      * @param OfferAlertRepository $offerAlertRepository
  282.      * @param PaginatorInterface $paginator
  283.      * @param EntityManagerInterface $entityManager
  284.      * @param SessionInterface $session
  285.      * @return Response
  286.      */
  287.     public function freelanceParis(
  288.         Request                $request,
  289.         OfferRepository        $offerRepository,
  290.         OfferAlertRepository   $offerAlertRepository,
  291.         PaginatorInterface     $paginator,
  292.         EntityManagerInterface $entityManager,
  293.         SessionInterface       $session
  294.     ): Response {
  295.         return $this->missionSearch(
  296.             $request,
  297.             $offerRepository,
  298.             $offerAlertRepository,
  299.             $paginator,
  300.             $entityManager,
  301.             $session,
  302.             "",
  303.             ['75 Paris'],
  304.             "Paris"
  305.         );
  306.     }
  307.     /**
  308.      *
  309.      * @Route("/emploi-lille", name="mission_search_lille")
  310.      *
  311.      * @param Request $request
  312.      * @param OfferRepository $offerRepository
  313.      * @param OfferAlertRepository $offerAlertRepository
  314.      * @param PaginatorInterface $paginator
  315.      * @param EntityManagerInterface $entityManager
  316.      * @param SessionInterface $session
  317.      * @return Response
  318.      */
  319.     public function missionLille(
  320.         Request                $request,
  321.         OfferRepository        $offerRepository,
  322.         OfferAlertRepository   $offerAlertRepository,
  323.         PaginatorInterface     $paginator,
  324.         EntityManagerInterface $entityManager,
  325.         SessionInterface       $session
  326.     ): Response {
  327.         return $this->missionSearch(
  328.             $request,
  329.             $offerRepository,
  330.             $offerAlertRepository,
  331.             $paginator,
  332.             $entityManager,
  333.             $session,
  334.             "",
  335.             ['59 Nord'],
  336.             "Lille"
  337.         );
  338.     }
  339.     /**
  340.      *
  341.      * @Route("/emploi-nice", name="mission_search_nice")
  342.      *
  343.      * @param Request $request
  344.      * @param OfferRepository $offerRepository
  345.      * @param OfferAlertRepository $offerAlertRepository
  346.      * @param PaginatorInterface $paginator
  347.      * @param EntityManagerInterface $entityManager
  348.      * @param SessionInterface $session
  349.      * @return Response
  350.      */
  351.     public function missionNice(
  352.         Request                $request,
  353.         OfferRepository        $offerRepository,
  354.         OfferAlertRepository   $offerAlertRepository,
  355.         PaginatorInterface     $paginator,
  356.         EntityManagerInterface $entityManager,
  357.         SessionInterface       $session
  358.     ): Response {
  359.         return $this->missionSearch(
  360.             $request,
  361.             $offerRepository,
  362.             $offerAlertRepository,
  363.             $paginator,
  364.             $entityManager,
  365.             $session,
  366.             "",
  367.             ['06 Alpes-Maritimes'],
  368.             "Nice"
  369.         );
  370.     }
  371.     /**
  372.      *
  373.      * @Route("/emploi-bordeaux", name="mission_search_bordeaux")
  374.      *
  375.      * @param Request $request
  376.      * @param OfferRepository $offerRepository
  377.      * @param OfferAlertRepository $offerAlertRepository
  378.      * @param PaginatorInterface $paginator
  379.      * @param EntityManagerInterface $entityManager
  380.      * @param SessionInterface $session
  381.      * @return Response
  382.      */
  383.     public function missionBordeaux(
  384.         Request                $request,
  385.         OfferRepository        $offerRepository,
  386.         OfferAlertRepository   $offerAlertRepository,
  387.         PaginatorInterface     $paginator,
  388.         EntityManagerInterface $entityManager,
  389.         SessionInterface       $session
  390.     ): Response {
  391.         return $this->missionSearch(
  392.             $request,
  393.             $offerRepository,
  394.             $offerAlertRepository,
  395.             $paginator,
  396.             $entityManager,
  397.             $session,
  398.             "",
  399.             ['33 Gironde'],
  400.             "Bordeaux"
  401.         );
  402.     }
  403.     /**
  404.      *
  405.      * @Route("/emploi-marseille", name="mission_search_marseille")
  406.      *
  407.      * @param Request $request
  408.      * @param OfferRepository $offerRepository
  409.      * @param OfferAlertRepository $offerAlertRepository
  410.      * @param PaginatorInterface $paginator
  411.      * @param EntityManagerInterface $entityManager
  412.      * @param SessionInterface $session
  413.      * @return Response
  414.      */
  415.     public function missionMarseille(
  416.         Request                $request,
  417.         OfferRepository        $offerRepository,
  418.         OfferAlertRepository   $offerAlertRepository,
  419.         PaginatorInterface     $paginator,
  420.         EntityManagerInterface $entityManager,
  421.         SessionInterface       $session
  422.     ): Response {
  423.         return $this->missionSearch(
  424.             $request,
  425.             $offerRepository,
  426.             $offerAlertRepository,
  427.             $paginator,
  428.             $entityManager,
  429.             $session,
  430.             "",
  431.             ['13 Bouches-du-Rhône'],
  432.             "Marseille"
  433.         );
  434.     }
  435.     /**
  436.      *
  437.      * @Route("/emploi-nantes", name="mission_search_nantes")
  438.      *
  439.      * @param Request $request
  440.      * @param OfferRepository $offerRepository
  441.      * @param OfferAlertRepository $offerAlertRepository
  442.      * @param PaginatorInterface $paginator
  443.      * @param EntityManagerInterface $entityManager
  444.      * @param SessionInterface $session
  445.      * @return Response
  446.      */
  447.     public function missionNantes(
  448.         Request                $request,
  449.         OfferRepository        $offerRepository,
  450.         OfferAlertRepository   $offerAlertRepository,
  451.         PaginatorInterface     $paginator,
  452.         EntityManagerInterface $entityManager,
  453.         SessionInterface       $session
  454.     ): Response {
  455.         return $this->missionSearch(
  456.             $request,
  457.             $offerRepository,
  458.             $offerAlertRepository,
  459.             $paginator,
  460.             $entityManager,
  461.             $session,
  462.             "",
  463.             ['44 Loire-Atlantique'],
  464.             "Nantes"
  465.         );
  466.     }
  467.     /**
  468.      *
  469.      * @Route("/emploi-toulouse", name="mission_search_toulouse")
  470.      *
  471.      * @param Request $request
  472.      * @param OfferRepository $offerRepository
  473.      * @param OfferAlertRepository $offerAlertRepository
  474.      * @param PaginatorInterface $paginator
  475.      * @param EntityManagerInterface $entityManager
  476.      * @param SessionInterface $session
  477.      * @return Response
  478.      */
  479.     public function missionToulouse(
  480.         Request                $request,
  481.         OfferRepository        $offerRepository,
  482.         OfferAlertRepository   $offerAlertRepository,
  483.         PaginatorInterface     $paginator,
  484.         EntityManagerInterface $entityManager,
  485.         SessionInterface       $session
  486.     ): Response {
  487.         return $this->missionSearch(
  488.             $request,
  489.             $offerRepository,
  490.             $offerAlertRepository,
  491.             $paginator,
  492.             $entityManager,
  493.             $session,
  494.             "",
  495.             ['31 Haute-Garonne'],
  496.             "Toulouse"
  497.         );
  498.     }
  499.     /**
  500.      *
  501.      * @Route("/emploi-lyon", name="mission_search_lyon")
  502.      *
  503.      * @param Request $request
  504.      * @param OfferRepository $offerRepository
  505.      * @param OfferAlertRepository $offerAlertRepository
  506.      * @param PaginatorInterface $paginator
  507.      * @param EntityManagerInterface $entityManager
  508.      * @param SessionInterface $session
  509.      * @return Response
  510.      */
  511.     public function missionLyon(
  512.         Request                $request,
  513.         OfferRepository        $offerRepository,
  514.         OfferAlertRepository   $offerAlertRepository,
  515.         PaginatorInterface     $paginator,
  516.         EntityManagerInterface $entityManager,
  517.         SessionInterface       $session
  518.     ): Response {
  519.         return $this->missionSearch(
  520.             $request,
  521.             $offerRepository,
  522.             $offerAlertRepository,
  523.             $paginator,
  524.             $entityManager,
  525.             $session,
  526.             "",
  527.             ['69 Rhône'],
  528.             "Lyon"
  529.         );
  530.     }
  531.     /**
  532.      *
  533.      * @Route("/freelance-{url_libelle}", name="mission_search", requirements={"url_libelle"=".*"})
  534.      *
  535.      * @param Request $request
  536.      * @param OfferRepository $offerRepository
  537.      * @param OfferAlertRepository $offerAlertRepository
  538.      * @param PaginatorInterface $paginator
  539.      * @param EntityManagerInterface $entityManager
  540.      * @param SessionInterface $session
  541.      * @param string|null $url_libelle
  542.      * @return Response
  543.      */
  544.     public function mission(
  545.         Request                $request,
  546.         OfferRepository        $offerRepository,
  547.         OfferAlertRepository   $offerAlertRepository,
  548.         PaginatorInterface     $paginator,
  549.         EntityManagerInterface $entityManager,
  550.         SessionInterface       $session,
  551.         ?string                $url_libelle ""
  552.     ): Response {
  553.         return $this->missionSearch(
  554.             $request,
  555.             $offerRepository,
  556.             $offerAlertRepository,
  557.             $paginator,
  558.             $entityManager,
  559.             $session,
  560.             $url_libelle
  561.         );
  562.     }
  563.     /**
  564.      *
  565.      * @Route("/stage-{url_libelle}", name="stage_search", requirements={"url_libelle"=".*"})
  566.      *
  567.      * @param Request $request
  568.      * @param OfferRepository $offerRepository
  569.      * @param OfferAlertRepository $offerAlertRepository
  570.      * @param PaginatorInterface $paginator
  571.      * @param EntityManagerInterface $entityManager
  572.      * @param SessionInterface $session
  573.      * @param string|null $url_libelle
  574.      * @return Response
  575.      */
  576.     public function stage(
  577.         Request                $request,
  578.         OfferRepository        $offerRepository,
  579.         OfferAlertRepository   $offerAlertRepository,
  580.         PaginatorInterface     $paginator,
  581.         EntityManagerInterface $entityManager,
  582.         SessionInterface       $session,
  583.         ?string                $url_libelle ""
  584.     ): Response {
  585.         return $this->missionSearch(
  586.             $request,
  587.             $offerRepository,
  588.             $offerAlertRepository,
  589.             $paginator,
  590.             $entityManager,
  591.             $session,
  592.             $url_libelle
  593.         );
  594.     }
  595.     /**
  596.      *
  597.      * @Route("/alternance-{url_libelle}", name="alternance_search", requirements={"url_libelle"=".*"})
  598.      *
  599.      * @param Request $request
  600.      * @param OfferRepository $offerRepository
  601.      * @param OfferAlertRepository $offerAlertRepository
  602.      * @param PaginatorInterface $paginator
  603.      * @param EntityManagerInterface $entityManager
  604.      * @param SessionInterface $session
  605.      * @param string|null $url_libelle
  606.      * @return Response
  607.      */
  608.     public function alternance(
  609.         Request                $request,
  610.         OfferRepository        $offerRepository,
  611.         OfferAlertRepository   $offerAlertRepository,
  612.         PaginatorInterface     $paginator,
  613.         EntityManagerInterface $entityManager,
  614.         SessionInterface       $session,
  615.         ?string                $url_libelle ""
  616.     ): Response {
  617.         return $this->missionSearch(
  618.             $request,
  619.             $offerRepository,
  620.             $offerAlertRepository,
  621.             $paginator,
  622.             $entityManager,
  623.             $session,
  624.             $url_libelle
  625.         );
  626.     }
  627.     /**
  628.      *
  629.      * @Route("/emploi-{url_libelle}", name="emploi_search", requirements={"url_libelle"=".*"})
  630.      *
  631.      * @param Request $request
  632.      * @param OfferRepository $offerRepository
  633.      * @param OfferAlertRepository $offerAlertRepository
  634.      * @param PaginatorInterface $paginator
  635.      * @param EntityManagerInterface $entityManager
  636.      * @param SessionInterface $session
  637.      * @param string|null $url_libelle
  638.      * @return Response
  639.      */
  640.     public function emploi(
  641.         Request                $request,
  642.         OfferRepository        $offerRepository,
  643.         OfferAlertRepository   $offerAlertRepository,
  644.         PaginatorInterface     $paginator,
  645.         EntityManagerInterface $entityManager,
  646.         SessionInterface       $session,
  647.         ?string                $url_libelle ""
  648.     ): Response {
  649.         return $this->missionSearch(
  650.             $request,
  651.             $offerRepository,
  652.             $offerAlertRepository,
  653.             $paginator,
  654.             $entityManager,
  655.             $session,
  656.             $url_libelle
  657.         );
  658.     }
  659.     /**
  660.      *
  661.      * @Route("/offres-{url_libelle}", name="offre_search", requirements={"url_libelle"=".*"})
  662.      *
  663.      * @param Request $request
  664.      * @param OfferRepository $offerRepository
  665.      * @param OfferAlertRepository $offerAlertRepository
  666.      * @param PaginatorInterface $paginator
  667.      * @param EntityManagerInterface $entityManager
  668.      * @param SessionInterface $session
  669.      * @param string|null $url_libelle
  670.      * @return Response
  671.      */
  672.     public function offre(
  673.         Request                $request,
  674.         OfferRepository        $offerRepository,
  675.         OfferAlertRepository   $offerAlertRepository,
  676.         PaginatorInterface     $paginator,
  677.         EntityManagerInterface $entityManager,
  678.         SessionInterface       $session,
  679.         ?string                $url_libelle ""
  680.     ): Response {
  681.         return $this->missionSearch(
  682.             $request,
  683.             $offerRepository,
  684.             $offerAlertRepository,
  685.             $paginator,
  686.             $entityManager,
  687.             $session,
  688.             $url_libelle
  689.         );
  690.     }
  691.     private function missionSearch(
  692.         Request                $request,
  693.         OfferRepository        $offerRepository,
  694.         OfferAlertRepository   $offerAlertRepository,
  695.         PaginatorInterface     $paginator,
  696.         EntityManagerInterface $entityManager,
  697.         SessionInterface       $session,
  698.         ?string                $url_libelle "",
  699.         ?array                 $exeptedLocation = [],
  700.         ?string                $citySelected null
  701.     ): Response {
  702.         $session->remove('previous_url');
  703.         // dd($request->get('contrat'));
  704.         $currentDate = new DateTime();
  705.         /* @var User $user */
  706.         $user $this->getUser();
  707.         if ($user) {
  708.             if ($user->isFreelance() && !$user->hasProfile()) {
  709.                 return $this->redirectToRoute('dashboard');
  710.             }
  711.         }
  712.         // DEFAULT SEARCH
  713.         $defaultSearch "";
  714.         $defaultLocation $exeptedLocation;
  715.         $defaultCategorie null;
  716.         $defaultMinMax 0;
  717.         $defaultSalary 0;
  718.         $defaultOrder $user !== null 'pertinence' 'desc';
  719.         $defaultContrat = ['Freelance''CDI''CDD''Alternance''Stage'];
  720.         // Récupérer les types de contrats uniques dans les missions
  721.         $existingContrats $offerRepository->createQueryBuilder('o')
  722.             ->select('DISTINCT o.contrats')
  723.             ->where('o.contrats IS NOT NULL')
  724.             ->getQuery()
  725.             ->getResult();
  726.         $contratsList = [];
  727.         foreach ($existingContrats as $row) {
  728.             if (is_array($row['contrats'])) {
  729.                 $contratsList array_merge($contratsList$row['contrats']);
  730.             }
  731.         }
  732.         // Supprimer les doublons de contrats et filtrer selon $defaultContrat
  733.         $contratsList array_unique($contratsList);
  734.         $filteredContrats array_intersect($defaultContrat$contratsList);
  735.         $contrats = [];
  736.         // DELETE SESSION
  737.         if ($request->getMethod() == 'GET' && !$url_libelle && !$request->query->get('page')) {
  738.             if ($session->has('s_location')) {
  739.                 $session->remove('s_location');
  740.             }
  741.             if ($session->has('s_categorie')) {
  742.                 $session->remove('s_categorie');
  743.             }
  744.             if ($session->has('s_minMax')) {
  745.                 $session->remove('s_minMax');
  746.             }
  747.             if ($session->has('s_order')) {
  748.                 $session->remove('s_order');
  749.             }
  750.             if ($session->has('s_contrat')) {
  751.                 $session->remove('s_contrat');
  752.             }
  753.             if ($session->has('s_salary')) {
  754.                 $session->remove('s_salary');
  755.             }
  756.         }
  757.         if ($request->getMethod() == "GET") {
  758.             $urlData $this->transformURL($url_libelle);
  759.             $defaultSearch $urlData['search'] ?? "";
  760.             // GET FROM SESSION
  761.             $page $request->query->getInt('page');
  762.             if ($page != 0) {
  763.                 $defaultLocation $session->get('s_location') ?? $defaultLocation;
  764.                 $defaultCategorie $session->get('s_categorie') ?? $defaultCategorie;
  765.                 $defaultMinMax $session->get('s_minMax') ?? $defaultMinMax;
  766.                 $defaultOrder $session->get('s_order') ?? $defaultOrder;
  767.                 $contrats $session->get('s_contrat') ?? $contrats;
  768.                 $salary $session->get('s_salary') ?? $defaultSalary;
  769.             }
  770.         }
  771.         $order $request->request->get('order'$defaultOrder);
  772.         /** @var array $location */
  773.         $location $request->request->get('location'$defaultLocation);
  774.         $keyword $request->request->get('search'$defaultSearch);
  775.         $minMax $request->request->get('min'$defaultMinMax);
  776.         $category $request->request->get('category'$defaultCategorie);
  777.         $contrats $request->request->get('contrat'$contrats);
  778.         $salary $request->request->get('salary'$defaultSalary);
  779.         // SET SESSION ON POST
  780.         if ($request->getMethod() == "POST") {
  781.             $session->set('s_location'$location);
  782.             $session->set('s_categorie'$category);
  783.             $session->set('s_minMax'$minMax);
  784.             $session->set('s_order'$order);
  785.             $session->set('s_contrat'$contrats);
  786.             $session->set('s_salary'$salary);
  787.         }
  788.         $loc implode(', '$location);
  789.         $cont implode(', '$contrats);
  790.         $alert $offerAlertRepository->findOneBy([
  791.             'keyword' => $keyword,
  792.             'localisation' => $loc,
  793.             'remote' => $category,
  794.             'min_tjm' => $minMax == null $minMax,
  795.             'contrats' => $cont,
  796.             'user' => $user,
  797.         ]);
  798.         $knpPage $request->get('page'1);
  799.         $knpPerPage 10;
  800.         // Correction : forcer la page à 1 lors d'un POST (modification de filtre)
  801.         if ($request->getMethod() === 'POST') {
  802.             $knpPage 1;
  803.         }
  804.         $offerViewed = [];
  805.         if ($user) {
  806.             $offerViewed array_map(
  807.                 function ($visit) {
  808.                     return $visit->getOffer()->getId();
  809.                 },
  810.                 $user->getOfferVisits()->toArray()
  811.             );
  812.         }
  813.         if ($minMax == '') {
  814.             $minMax 0;
  815.         }
  816.         if ($salary == '') {
  817.             $salary 0;
  818.         }
  819.         if ($user !== null && !$user->isFreelance()) {
  820.             $contrats = ["Freelance"];
  821.         }
  822.         if ($request->getPathInfo() == '/missions-freelance') {
  823.             $template $entityManager->getRepository(Publication::class)->findOneBy([
  824.                 'template' => true,
  825.                 'slug' => 'mission-freelance'
  826.             ]);
  827.         } elseif ($request->getPathInfo() == '/emploi') {
  828.             $contrats = ['CDI''CDD''Alternance''Stage'];
  829.             $template $entityManager->getRepository(Publication::class)->findOneBy([
  830.                 'template' => true,
  831.                 'slug' => 'emploi'
  832.             ]);
  833.         } elseif ($request->getPathInfo() == '/alternance') {
  834.             $contrats = ['Alternance'];
  835.             $template $entityManager->getRepository(Publication::class)->findOneBy([
  836.                 'template' => true,
  837.                 'slug' => 'alternance'
  838.             ]);
  839.         } elseif ($request->getPathInfo() == '/stage') {
  840.             $contrats = ['Stage'];
  841.             $template $entityManager->getRepository(Publication::class)->findOneBy([
  842.                 'template' => true,
  843.                 'slug' => 'stage'
  844.             ]);
  845.         } elseif (preg_match('#^/emploi-[\w-]+$#'$request->getPathInfo())) {
  846.             $contrats = ['CDI''CDD''Alternance''Stage'];
  847.             $slug $url_libelle == "" str_replace('/'''$request->getPathInfo()) : 'emploi-' $url_libelle;
  848.             $template $entityManager->getRepository(Publication::class)->findOneBy([
  849.                 'template' => true,
  850.                 'slug' => $slug
  851.             ]);
  852.         } else {
  853.             $template $entityManager->getRepository(Publication::class)->findOneBy([
  854.                 'template' => true,
  855.                 'slug' => 'freelance-' $url_libelle
  856.             ]);
  857.         }
  858.         // dd($salary);
  859.         /** @var Offer[] $data */
  860.         $data $offerRepository->findBySearch($keyword$location$minMax$category$salary$order$contrats/*, $user !== null && $user->isFreelance()*/);
  861.         // dd($data);
  862.         $data_offer_not_online $offerRepository->findOneBy(["slug" => '10294-developpeur-nuxeo-tt-java-j2ee-springboot']);
  863.         // DEFAULT OFFER IF NO FOUND
  864.         $noFound false;
  865.         // dd($data);
  866.         // Obtenez les données complètes si le nombre total d'offres est inférieur à 5
  867.         if (count($data) < 5) {
  868.             $data_all $this->offerIfNofound(['Toute la France'], $offerRepository,  $user && $user->isFreelance() ? [] : $contrats$order);
  869.             if (count($data) == 0) {
  870.                 $noFound true;
  871.                 if (($user && $user->isFreelance())) {
  872.                     $data $data_all;
  873.                 }
  874.             }
  875.         }
  876.         $highlightedMissions $this->getHighLightMission($data$request->query->get('page'));
  877.         $otherBoostMissions $this->getOtherBoostMission($data$request->query->get('page'), $entityManager);
  878.         // $offers = $paginator->paginate(
  879.         //     $data,
  880.         //     $request->query->getInt('page', $knpPage),
  881.         //     $knpPerPage
  882.         // );
  883.         if (count($data) < && count($data) > 0) {
  884.             $offers $data;
  885.             $data_all_offers $paginator->paginate(
  886.                 $data_all,
  887.                 $request->query->getInt('page'$knpPage),
  888.                 $knpPerPage
  889.             );
  890.         } else {
  891.             $data_all_offers = [];
  892.             $offers $paginator->paginate(
  893.                 $data,
  894.                 $request->query->getInt('page'$knpPage),
  895.                 $knpPerPage
  896.             );
  897.         }
  898.         // Build external company map by offer id for offers without linked society
  899.         $externalCompanies = [];
  900.         $collectOffers = function ($items) {
  901.             $out = [];
  902.             if (is_iterable($items)) {
  903.                 foreach ($items as $it) { $out[] = $it; }
  904.             }
  905.             return $out;
  906.         };
  907.         $allOfferObjects = [];
  908.         $allOfferObjects array_merge($allOfferObjectsis_array($data) ? $data : []);
  909.         $allOfferObjects array_merge($allOfferObjects, isset($data_all) && is_array($data_all) ? $data_all : []);
  910.         $allOfferObjects array_merge($allOfferObjects$collectOffers($offers));
  911.         $allOfferObjects array_merge($allOfferObjects$collectOffers($data_all_offers));
  912.         $allOfferObjects array_merge($allOfferObjects, isset($highlightedMissions) && is_array($highlightedMissions) ? $highlightedMissions : []);
  913.         $allOfferObjects array_merge($allOfferObjects, isset($otherBoostMissions) && is_array($otherBoostMissions) ? $otherBoostMissions : []);
  914.         foreach ($allOfferObjects as $off) {
  915.             if ($off instanceof Offer) {
  916.                 if ($off->getSociety() === null) {
  917.                     $siren method_exists($off'getSiren') ? $off->getSiren() : null;
  918.                     if ($siren) {
  919.                         $info $this->externalCompanyRepository->findCompanyBySiren($siren);
  920.                         if ($info) {
  921.                             $externalCompanies[$off->getId()] = $info;
  922.                         }
  923.                     }
  924.                 }
  925.             }
  926.         }
  927.         // Paginer $data_all
  928.         // $data_all_offers = $paginator->paginate(
  929.         //     $data_all,
  930.         //     $request->query->getInt('page', $knpPage),
  931.         //     $knpPerPage
  932.         // );
  933.         // $data_all_offers=[];
  934.         // template lié à url_libelle
  935.         // FLUSH OTHER BOOST DATE
  936.         $entityManager->flush();
  937.         $mission_region_spec = [
  938.             "Nantes" => ["44 Loire-Atlantique""Mission freelance et offres d'emploi sur Nantes et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Nantes comme aux Pays de la Loire, de nombreuses missions sont disponibles."],
  939.             "Lyon" => ["69 Rhône""Mission freelance et offres d'emploi sur Lyon et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Lyon comme en Auvergne-Rhône-Alpes, de nombreuses missions sont disponibles."],
  940.             "Toulouse" => ["31 Haute-Garonne""Mission freelance et offres d'emploi sur Toulouse et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Toulouse comme en Occitanie, de nombreuses missions sont disponibles."],
  941.             "Marseille" => ["13 Bouches-du-Rhône""Mission freelance et offres d'emploi sur Marseille et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Marseille comme en Provence-Alpes-Côte d'Azur, de nombreuses missions sont disponibles."],
  942.             "Nice" => ["06 Alpes-Maritimes""Mission freelance et offres d'emploi sur Nice et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Nice comme en Provence-Alpes-Côte d'Azur, de nombreuses missions sont disponibles."],
  943.             "Bordeux" => ["33 Gironde""Mission freelance et offres d'emploi sur Bordeaux et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Bordeaux comme en Nouvelle-Aquitaine, de nombreuses missions sont disponibles."],
  944.             "Lille" => ["59 Nord""Mission freelance et offres d'emploi sur Lille et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Lille comme en Hauts-de-France, de nombreuses missions sont disponibles."],
  945.             "Paris" => ["75 Paris""Mission freelance et offres d'emploi sur Paris et sur toute la France. Avec ou sans télétravail, de moyenne et longue durée, à Paris comme en Ile-de-France, de nombreuses missions sont disponibles."],
  946.         ];
  947.         // Variable pour stocker le titre slugifié
  948.         $title '';
  949.         $description '';
  950.         // if (!empty($template)){
  951.         //     foreach ($template as $temp){
  952.         //         $title = $temp->getTitle();
  953.         //         $description = $temp->getDescription();
  954.         //   }
  955.         // }
  956.         // Vérifier si la ville sélectionnée est une clé dans $mission_region_spec
  957.         if (array_key_exists($citySelected$mission_region_spec)) {
  958.             // Vérifier si la valeur correspond à celle dans $exeptedLocation
  959.             if ($mission_region_spec[$citySelected][0] == $exeptedLocation[0]) {
  960.                 // Créer le slug à partir de la ville sélectionnée
  961.                 $title $citySelected;
  962.                 $description $mission_region_spec[$citySelected][1];
  963.             }
  964.         }
  965.         if ($template != null) {
  966.             $template->setView($template->getView() + 1);
  967.             $entityManager->persist($template);
  968.             $entityManager->flush();
  969.         }
  970.         return $this->render('search/missions.html.twig', [
  971.             'description' => $description,
  972.             'title' => $title,
  973.             'template' => $template,
  974.             'regions' => FrenchRegion::REGION_DEPARTEMENT,
  975.             'contrats' => $contrats,
  976.             'salary' => $salary,
  977.             'defaultContrat' => $filteredContrats,
  978.             'offers' => $offers,
  979.             'data_all_offers' => $data_all_offers,
  980.             'offers_of_line' => $data_offer_not_online,
  981.             'order' => $order,
  982.             'keyword' => $keyword,
  983.             'location' => $location,
  984.             'category' => $category,
  985.             'minMax' => $minMax,
  986.             'offerViewed' => $offerViewed,
  987.             'keywordArray' => $keyword == '' ? [] : explode(','$keyword),
  988.             'isComing' => (bool)$this->getParameter('is_coming'),
  989.             'date_coming_soon' => $this->getParameter('date_coming_soon'),
  990.             'alert' => $alert,
  991.             'regionjson' => json_encode(FrenchRegion::REGION_DEPARTEMENTJSON_UNESCAPED_UNICODE),
  992.             'highlightedMissions' => $highlightedMissions ?? [],
  993.             'otherBoostMissions' => $otherBoostMissions ?? [],
  994.             'isFreelance' => $user && $user->isFreelance(),
  995.             'noFound' => $noFound,
  996.             'currentDate' => $currentDate,
  997.             'citySelected' => $citySelected,
  998.             'externalCompanies' => $externalCompanies,
  999.         ]);
  1000.     }
  1001.     /**
  1002.      * changelog 2022-09-22 [FIX] (Anthony) Modifier le recherche par mobilité et re developper les tri sur la recherche
  1003.      *
  1004.      * @Route("/recherche-profils", name="freelance_search")
  1005.      *
  1006.      * @IsGranted("ROLE_USER")
  1007.      *
  1008.      * @param Request $request
  1009.      * @param ProfileRepository $profileRepository
  1010.      * @param ProfileVisitRepository $profileVisitRepository
  1011.      * @param PaginatorInterface $paginator
  1012.      * @param SkillRepository $skillRepository
  1013.      *
  1014.      * @return Response
  1015.      */
  1016.     public function freelance(
  1017.         Request                $request,
  1018.         ProfileRepository      $profileRepository,
  1019.         ProfileVisitRepository $profileVisitRepository,
  1020.         PaginatorInterface     $paginator,
  1021.         SkillRepository        $skillRepository,
  1022.         SocietyRepository      $societyRepository,
  1023.         Config                 $config
  1024.     ): Response {
  1025.         /* @var User $user */
  1026.         $user $this->getUser();
  1027.         if ($user && $user->isFreelance()) {
  1028.             return $this->redirectToRoute('dashboard');
  1029.         }
  1030.         $viewMonth = [];
  1031.         $closeToEndOfMonth false;
  1032.         $limitInMonth false;
  1033.         $society $user->getSociety();
  1034.         $packageDate $society->getPackageDate();
  1035.         if ($packageDate) {
  1036.             $packageExpireAt $society->getPackageExpireAt(); // Supposons que c'est un objet DateTime
  1037.             // Obtenir la date actuelle
  1038.             $currentDate = new DateTime();
  1039.             $dayOfPackage $packageDate->format('d');
  1040.             // Créer la date de début sur la base de la date du package
  1041.             $StartDate = new DateTime($currentDate->format('Y-m') . '-' $dayOfPackage); // Le même jour du mois actuel
  1042.             $StartDateFormatted $StartDate->format('Y-m-d'); // Format de la date de début
  1043.             // Créer la date de fin (même jour du mois suivant)
  1044.             $EndDate = (clone $StartDate)->modify('+1 month');
  1045.             $EndDateFormatted $EndDate->format('Y-m-d'); // Format de la date de fin
  1046.             // Create the EndDate + 1 month for the comparison
  1047.             $EndDatePlusOneMonth = (clone $EndDate)->modify('+1 month');
  1048.             // Check if packageExpireAt is between EndDate and EndDate + 1 month and the package is not 'month'
  1049.             $closeToEndOfMonth = (
  1050.                 $packageExpireAt >= $EndDate &&
  1051.                 $packageExpireAt <= $EndDatePlusOneMonth &&
  1052.                 $society->getPackage() !== 'month'
  1053.             );
  1054.             // Vérifier si la date d'expiration du package a été dépassée
  1055.             $limitInMonth $society->getPackage() !== 'month' && $packageExpireAt $EndDate && $packageExpireAt >= $EndDatePlusOneMonth;
  1056.             if ($packageExpireAt $EndDate) {
  1057.                 $viewMonth $profileVisitRepository->getProfileSocietyViewDailyByPeriod($society$StartDateFormatted$EndDateFormatted'month');
  1058.             }
  1059.         }
  1060.         if ($society) {
  1061.             if ($society->packageActive()) {
  1062.                 if ($society->packageActive()->isIsOnlyAnnonce()) {
  1063.                     $this->addFlash('package_error_annonce_only'" Vous ne pouvez pas consulter cette page avec votre accès.");
  1064.                     return $this->redirectToRoute('dashboard');
  1065.                 }
  1066.             }
  1067.         }
  1068.         $packageList $config->packageList();
  1069.         $packageKey $society->getPackage();
  1070.         if (array_key_exists($packageKey$packageList)) {
  1071.             $package $packageList[$packageKey];
  1072.             // renouvellement limit profileView à chaque mois
  1073.             if (!empty($viewMonth) && $viewMonth[0]['count'] == 0) {
  1074.                 $society->setProfileView($package['profileView']);
  1075.             }
  1076.         }
  1077.         $contrats $request->get('contrat', []);
  1078.         $order $request->get('order''pertinence');
  1079.         $location $request->get('mobility', []);
  1080.         $experiences $request->get('experiences', []);
  1081.         $keywords $request->get('search''');
  1082.         $max $request->get('max'0);
  1083.         $salary $request->get('salary'0);
  1084.         $favori $request->get('favori''false');
  1085.         $type $request->get('type''');
  1086.         $disponibility $request->get('disponibility''');
  1087.         $knpPage $request->get('page'1);
  1088.         $knpPerPage 10;
  1089.         if ($max == "") {
  1090.             $max 0.0;
  1091.         }
  1092.         if ($salary == "") {
  1093.             $salary 0.0;
  1094.         }
  1095.         /* @changelog 2022-09-22 [FIX] (Anthony) Permettre l'encapsulation de region, departement et vile sur la recherche par mobilité */
  1096.         // $data = $profileRepository->findBySearch($keywords, $location, $max, $type, $disponibility, $experiences, $order, $contrats, $salary, $favori, $this->getUser());
  1097.         // $data = $this->removeIntercontratExpied($data, $profileRepository, $societyRepository);
  1098.         // if (self::FILTER_PERTINENCE == $order) {
  1099.         //     $data = $this->filterDataKeywordByPertinence($data, $profileRepository, $skillRepository, $keywords);
  1100.         // }
  1101.         // /* @changeLog 2022-11-02 [FIX] (Anthony) Mise en place des intercontrats en une */
  1102.         // $highlightedProfiles = $this->getHighLightProfile($data, $request->query->get('page'));
  1103.         // $profiles = $paginator->paginate(
  1104.         //     $data,
  1105.         //     $request->query->getInt('page', $knpPage),
  1106.         //     $knpPerPage
  1107.         // );
  1108.         // 1. Récupérer le QueryBuilder (au lieu d'un tableau)
  1109.         $queryBuilder $profileRepository->findBySearchQueryBuilder(
  1110.             $keywords,
  1111.             $location,
  1112.             $max,
  1113.             $type,
  1114.             $disponibility,
  1115.             $experiences,
  1116.             $order,
  1117.             $contrats,
  1118.             $salary,
  1119.             $favori,
  1120.             $this->getUser()
  1121.         );
  1122.         // 2. Paginer directement sur le QueryBuilder
  1123.         $profilesPagination $paginator->paginate(
  1124.             $queryBuilder,
  1125.             $request->query->getInt('page'$knpPage),
  1126.             $knpPerPage
  1127.         );
  1128.         // 3. Récupérer seulement les profils de la page courante
  1129.         $profilesPage $profilesPagination->getItems();
  1130.         // 4. Appliquer les filtres lourds seulement sur la page courante
  1131.         $profilesPage $this->removeIntercontratExpied($profilesPage$profileRepository$societyRepository);
  1132.         // if (self::FILTER_PERTINENCE == $order) {
  1133.         //     $profilesPage = $this->filterDataKeywordByPertinence($profilesPage, $profileRepository, $skillRepository, $keywords);
  1134.         // }
  1135.         // 5. Optionnel : mettre à jour les items dans la pagination pour la vue
  1136.         $profilesPagination->setItems($profilesPage);
  1137.         // 6. Récupérer les profils mis en avant (sur la page filtrée)
  1138.         $highlightedProfiles $this->getHighLightProfile($profilesPage$request->query->get('page'));
  1139.         /* @changeLog 2022-11-10 [EVOL] (Anthony) Mise en place de la limitation de lecture de cv */
  1140.         $society $user->getSociety();
  1141.         $view $profileVisitRepository->countBySociety($society);
  1142.         /* Limitation de l'abonnement */
  1143.         $cycleStart null;
  1144.         $cycleEnd null;
  1145.         $activeCommande $society->packageActive();
  1146.         if ($activeCommande) {
  1147.             $cycleStart $activeCommande->getCreatedAt();
  1148.             $cycleEnd $activeCommande->getEndDate();
  1149.         } else {
  1150.             $packageDate $society->getPackageDate();
  1151.             if ($packageDate) {
  1152.                 $today = new \DateTime();
  1153.                 $dayOfPackage = (int)$packageDate->format('d');
  1154.                 $currentDay = (int)$today->format('d');
  1155.                 $startMonth $currentDay $dayOfPackage ? (clone $today)->modify('-1 month')->format('Y-m') : $today->format('Y-m');
  1156.                 $cycleStart = new \DateTime($startMonth '-' str_pad((string)$dayOfPackage2'0'STR_PAD_LEFT) . ' 00:00:00');
  1157.                 $cycleEnd = (clone $cycleStart)->modify('+1 month');
  1158.             }
  1159.         }
  1160.         $profileIds $profileVisitRepository->findDistinctProfileIdsBySocietyBetween($society$cycleStart$cycleEnd);
  1161.         $profileView count($profileIds);
  1162.         $profileViewByUser $profileVisitRepository->findByUser($user);
  1163.         $profileByUser = [];
  1164.         foreach ($profileViewByUser as $visit) {
  1165.             $profileByUser[] = $visit['id'];
  1166.         }
  1167.         /* Limitation journalière alignée à l'heure de début du package (fenêtre 24h) */
  1168.         $startAt date("Y-m-d") . ' 00:00:01';
  1169.         $endAt date("Y-m-d") . ' 23:59:59';
  1170.         $packageAnchor null;
  1171.         $activeCommande $society $society->packageActive() : null;
  1172.         if ($activeCommande) {
  1173.             $packageAnchor $activeCommande->getCreatedAt();
  1174.         } else if ($society) {
  1175.             $packageAnchor $society->getPackageDate();
  1176.         }
  1177.         if ($packageAnchor) {
  1178.             $now = new DateTime();
  1179.             $anchorTime $packageAnchor->format('H:i:s');
  1180.             $todayAnchor = new DateTime($now->format('Y-m-d') . ' ' $anchorTime);
  1181.             if ($now $todayAnchor) {
  1182.                 $todayAnchor->modify('-1 day');
  1183.             }
  1184.             $dailyStart $todayAnchor;
  1185.             $dailyEnd = (clone $dailyStart)->modify('+1 day');
  1186.             $startAt $dailyStart->format('Y-m-d H:i:s');
  1187.             $endAt $dailyEnd->format('Y-m-d H:i:s');
  1188.         }
  1189.         $ProfilesVisitDaily $profileVisitRepository->findBySocietyDaily($society$startAt$endAt);
  1190.         $profileDailyIds = [];
  1191.         foreach ($ProfilesVisitDaily as $visitDaily) {
  1192.             $profileDailyIds[] = $visitDaily['id'];
  1193.         }
  1194.         $profileViewDaily count(array_unique($profileDailyIds));
  1195.         $dayLimit 150;
  1196.         $packageLimit = ($society->getProfileView());
  1197.         $defaultContrat = ['Freelance''CDI''CDD''Alternance''Stage'];
  1198.         return $this->render('search/freelance.html.twig', [
  1199.             'profiles' => $profilesPagination,
  1200.             'defaultContrat' => $defaultContrat,
  1201.             'contrats' => $contrats,
  1202.             'keyword' => $keywords,
  1203.             'location' => $location,
  1204.             'max' => $max,
  1205.             'salary' => $salary,
  1206.             'order' => $order,
  1207.             'type' => $type,
  1208.             'keywordArray' => $keywords == '' ? [] : explode(','$keywords),
  1209.             'regions' => FrenchRegion::REGION_DEPARTEMENT,
  1210.             'regionjson' => json_encode(FrenchRegion::REGION_DEPARTEMENTJSON_UNESCAPED_UNICODE),
  1211.             'disponibilities' => Disponibility::LIST,
  1212.             'experiencies' => Experience::LIST_FOR_PROFILE,
  1213.             'experiences' => $experiences,
  1214.             'disponibility' => $disponibility,
  1215.             'highlightedProfiles' => $highlightedProfiles ?? [],
  1216.             'profileViewDaily' => $profileViewDaily,
  1217.             'profileView' => $profileView,
  1218.             'dayLimit' => $dayLimit,
  1219.             //'dayLimit' => 4,
  1220.             'packageLimit' => $packageLimit,
  1221.             // 'packageLimit' => 0,
  1222.             'closeToEndOfMonth' => $closeToEndOfMonth,
  1223.             'limitInMonth' => $limitInMonth,
  1224.             'endDatePackage' => $EndDate ?? null,
  1225.             'profileIds' => array_unique($profileIds),
  1226.             'profileViewByUser' => array_unique($profileByUser),
  1227.             'favori' => $favori
  1228.         ]);
  1229.     }
  1230.     /**
  1231.      * Récuperer la region et le departement
  1232.      *
  1233.      * @param $needle //"Le mot clé"
  1234.      * @param array $haystack //"Le tableau lequel on fait la recherche"
  1235.      *
  1236.      * @return array|bool
  1237.      */
  1238.     public
  1239.     function array_recursive_search_key_map(
  1240.         $needle,
  1241.         array $haystack
  1242.     ) {
  1243.         foreach ($haystack as $first_level_key => $value) {
  1244.             if ($needle === $value) {
  1245.                 return array($first_level_key);
  1246.             } elseif (is_array($value)) {
  1247.                 $callback $this->array_recursive_search_key_map($needle$value);
  1248.                 if ($callback) {
  1249.                     return array_merge(array($first_level_key), $callback);
  1250.                 }
  1251.             }
  1252.         }
  1253.         return false;
  1254.     }
  1255.     /**
  1256.      * changelog 2022-09-28 [FIX] (Anthony) Formatter les données de la mobilité
  1257.      *
  1258.      * @param array $haystack Les region et departement à rechercher
  1259.      * @param array $mobilities Les mobilités à rechercher
  1260.      *
  1261.      * @return array
  1262.      */
  1263.     private
  1264.     function getMobilities(
  1265.         $haystack,
  1266.         array $mobilities = []
  1267.     ): array {
  1268.         $results = ["Toute la France"];
  1269.         if (count($mobilities) == && array_values($mobilities)[0] != "Toute la France" && in_array($mobilities[0], FrenchRegion::REGION)) {
  1270.             foreach ($mobilities as $mobility) {
  1271.                 $results[] = $mobility;
  1272.             }
  1273.         } else {
  1274.             foreach ($mobilities as $mobility) {
  1275.                 $regionAndDepartment $this->array_recursive_search_key_map($mobility$haystack);
  1276.                 $results[] = $regionAndDepartment[self::REGION];
  1277.                 $results[] = $regionAndDepartment[self::DEPARTMENT];
  1278.             }
  1279.         }
  1280.         return $results;
  1281.     }
  1282.     /**
  1283.      * changelog 2022-09-22 [FIX] (Anthony) Formatter les données de la mobilité
  1284.      *
  1285.      * @param array $datas //Les region et departement à rechercher
  1286.      * @param $order //Filtre de la recherche
  1287.      * @param ProfileRepository $profileRepository //La classe profile repository
  1288.      * @param array $mobilities //Les mobilités à rechercher
  1289.      *
  1290.      * @return array
  1291.      */
  1292.     private
  1293.     function checkProfilesByMobility($datas$profileRepository$order$mobilities = [])
  1294.     {
  1295.         $results = ["Toute la France"];
  1296.         if (count($mobilities) == && array_values($mobilities)[0] == "Toute la France") {
  1297.             $data $profileRepository->findByMobility($order$results);
  1298.         } else if (count($mobilities) == && array_values($mobilities)[0] != "Toute la France" && in_array($mobilities[0], FrenchRegion::REGION)) {
  1299.             foreach ($mobilities as $mobility) {
  1300.                 $results[] = $mobility;
  1301.             }
  1302.             $data $profileRepository->findByMobility($order$results);
  1303.         } else {
  1304.             foreach ($mobilities as $mobility) {
  1305.                 $regionAndDepartment $this->array_recursive_search_key_map($mobility$datas);
  1306.                 $results[] = $regionAndDepartment[self::REGION];
  1307.                 $results[] = $regionAndDepartment[self::DEPARTMENT];
  1308.             }
  1309.             $data $profileRepository->findByMobility($orderarray_unique($results));
  1310.         }
  1311.         return $data;
  1312.     }
  1313.     /**
  1314.      * changelog 2022-09-27 [FIX] (Anthony) Formatter les données des missions par mot clé
  1315.      *
  1316.      * @param array $keywords //Les mots clé à rechercher
  1317.      * @param OfferRepository $offerRepository //La classe offer repository
  1318.      * @param $order //Filtre de la recherche
  1319.      *
  1320.      * @return array
  1321.      */
  1322.     private
  1323.     function checkOfferByKeword($keywords$offerRepository$order)
  1324.     {
  1325.         $data $offerRepository->findByKeyword($keywords$order);
  1326.         return $data;
  1327.     }
  1328.     /**
  1329.      * changelog 2022-09-26 [FIX] (Anthony) Formatter les données des freelances par mot clé
  1330.      *
  1331.      * @param  $keywords // Les mots clé à rechercher
  1332.      * @param ProfileRepository $profileRepository //La classe profile repository
  1333.      * @param $order // Filtre de la recherche
  1334.      *
  1335.      * @return array
  1336.      */
  1337.     private
  1338.     function checkProfilesByKeword($keywordsProfileRepository $profileRepository$order): array
  1339.     {
  1340.         return $profileRepository->findByKeyword($keywords$order);
  1341.     }
  1342.     /**
  1343.      * changelog 2022-09-26 [FIX] (Anthony) Formatter les données par type
  1344.      *
  1345.      * @param $type //Le type du profile
  1346.      * @param ProfileRepository $profileRepository //La classe profile repository
  1347.      * @param $order //Filtre de la recherche
  1348.      *
  1349.      * @return array
  1350.      */
  1351.     private
  1352.     function checkProfilesByType($typeProfileRepository $profileRepository$order): array
  1353.     {
  1354.         $data $profileRepository->findByType($type$order);
  1355.         return $data;
  1356.     }
  1357.     /**
  1358.      * changelog 2022-09-26 [FIX] (Anthony) Formater les données de la disponibilité
  1359.      *
  1360.      * @param $disponibility //La disponibilité du profile
  1361.      * @param ProfileRepository $profileRepository //La classe profile repository
  1362.      * @param $order //Filtre de la recherche
  1363.      *
  1364.      * @return array
  1365.      */
  1366.     private
  1367.     function checkProfilesByDisponibility($disponibilityProfileRepository $profileRepository$order): array
  1368.     {
  1369.         $data $profileRepository->findByDisponibility($disponibility$order);
  1370.         return $data;
  1371.     }
  1372.     /**
  1373.      * changelog 2022-09-26 [FIX] (Anthony) Formater les données de la TJM
  1374.      *
  1375.      * @param $cost //La TJM du profile
  1376.      * @param ProfileRepository $profileRepository //La classe profile repository
  1377.      * @param $order //Filtre de la recherche
  1378.      *
  1379.      * @return array
  1380.      */
  1381.     private
  1382.     function checkProfilesByCost($costProfileRepository $profileRepository$order): array
  1383.     {
  1384.         $data $profileRepository->findByCost($cost$order);
  1385.         return $data;
  1386.     }
  1387.     /**
  1388.      * changelog 2022-09-23 [FIX] (Anthony) Supprimé les doublons du tableau d'objet
  1389.      *
  1390.      * @param       $array //Le tableau d'objet
  1391.      * @param       $keep_key_assoc
  1392.      *
  1393.      * @return array
  1394.      */
  1395.     private
  1396.     function my_array_unique($array$keep_key_assoc false)
  1397.     {
  1398.         $duplicate_keys = array();
  1399.         $tmp = array();
  1400.         foreach ($array as $key => $val) {
  1401.             // convert objects to arrays, in_array() does not support objects
  1402.             if (is_object($val))
  1403.                 $val = (array)$val;
  1404.             if (!in_array($val$tmp))
  1405.                 $tmp[] = $val;
  1406.             else
  1407.                 $duplicate_keys[] = $key;
  1408.         }
  1409.         foreach ($duplicate_keys as $key)
  1410.             unset($array[$key]);
  1411.         return $keep_key_assoc $array array_values($array);
  1412.     }
  1413.     private function removeIntercontratExpied($dataProfileRepository $profileRepositorySocietyRepository $societyRepository)
  1414.     {
  1415.         // Filtrer la liste des profils
  1416.         return array_filter($data, function ($profile) use ($societyRepository) {
  1417.             // Vérifie si le profil est en intercontrat
  1418.             if ($profile->isIntercontrat) {
  1419.                 // Récupère la société associée au profil
  1420.                 $society $societyRepository->findOneBy(['user' => $profile->user]);
  1421.                 // Vérifie si la société existe et si son package est expiré
  1422.                 if ($society && $society->getPackageExpireAt() < new \DateTime()) {
  1423.                     // Exclure ce profil (retourne false pour ne pas l'inclure)
  1424.                     return false;
  1425.                 }
  1426.             }
  1427.             // Inclure ce profil
  1428.             return true;
  1429.         });
  1430.     }
  1431.     /**
  1432.      * changelog 2022-09-23 [FIX] (Anthony) Filtrer les données freelances par mot clé par pertinence
  1433.      *
  1434.      * @param       $data // Les données à filtrer
  1435.      * @param ProfileRepository $profileRepository // La classe profile repository
  1436.      * @param SkillRepository $skillRepository // La classe skill repository
  1437.      * @param       $keyword // Les mots clé
  1438.      *
  1439.      * @return array
  1440.      */
  1441.     private
  1442.     function filterDataKeywordByPertinence($dataProfileRepository $profileRepositorySkillRepository $skillRepository$keyword): array
  1443.     {
  1444.         $dataTitle = [];
  1445.         $dataName = [];
  1446.         $dataAbout = [];
  1447.         $keyword explode(' '$keyword);
  1448.         foreach ($data as $profile) {
  1449.             foreach ($keyword as $key) {
  1450.                 $isCheckInTitle stripos($profile->title$key);
  1451.                 if ($isCheckInTitle > -1) {
  1452.                     $dataTitle[] = $profileRepository->find($profile->id);
  1453.                     continue;
  1454.                 }
  1455.             }
  1456.             $skillsData $skillRepository->findBy(['profile' => $profile]);
  1457.             $skillName = [];
  1458.             foreach ($skillsData as $skill) {
  1459.                 $skillName[] = $skill->name;
  1460.             }
  1461.             $skillName implode(','$skillName);
  1462.             foreach ($keyword as $key) {
  1463.                 $isCheckInSkill stripos($skillName$key);
  1464.                 if ($isCheckInSkill > -1) {
  1465.                     $dataName[] = $profileRepository->find($profile->id);
  1466.                     continue;
  1467.                 }
  1468.             }
  1469.             if (!empty($profile->about)) {
  1470.                 foreach ($keyword as $key) {
  1471.                     $isCheckInAbout stripos($profile->about$key);
  1472.                     if ($isCheckInAbout > -1) {
  1473.                         $dataAbout[] = $profileRepository->find($profile->id);
  1474.                         continue;
  1475.                     }
  1476.                 }
  1477.             }
  1478.             if (!empty($profile->cvText)) {
  1479.                 foreach ($keyword as $key) {
  1480.                     $isCheckInAbout stripos($profile->cvText$key);
  1481.                     if ($isCheckInAbout > -1) {
  1482.                         $dataAbout[] = $profileRepository->find($profile->id);
  1483.                         continue;
  1484.                     }
  1485.                 }
  1486.             }
  1487.         }
  1488.         $dataTitle $this->my_array_unique($dataTitle);
  1489.         $dataName $this->my_array_unique($dataName);
  1490.         $dataAbout $this->my_array_unique($dataAbout);
  1491.         $dataTitleName array_merge($dataTitle$dataName);
  1492.         $dataFilter array_merge($dataTitleName$dataAbout);
  1493.         $dataFilter $this->my_array_unique($dataFilter);
  1494.         return $dataFilter;
  1495.     }
  1496.     /**
  1497.      * changelog 2022-09-27 [FIX] (Anthony) Filtrer les données freelances par mot clé par pertinence
  1498.      *
  1499.      * @param       $data //Les données à filtrer
  1500.      * @param OfferRepository $offerRepository //La classe offer repository
  1501.      * @param       $keyword //Les mots clé
  1502.      *
  1503.      * @return array
  1504.      */
  1505.     private
  1506.     function filterOfferByPertinence($data$offerRepository$keyword)
  1507.     {
  1508.         $dataTitle = [];
  1509.         $dataDescription = [];
  1510.         $keyword explode(' '$keyword);
  1511.         foreach ($data as $offer) {
  1512.             foreach ($keyword as $kwd) {
  1513.                 $isCheckInTitle stripos($offer->title$kwd);
  1514.                 if ($isCheckInTitle > -1) {
  1515.                     $dataTitle[] = $offerRepository->find($offer->id);
  1516.                     continue;
  1517.                 }
  1518.             }
  1519.             if (!empty($offer->description)) {
  1520.                 foreach ($keyword as $kwd) {
  1521.                     $isCheckInDesc stripos($offer->description$kwd);
  1522.                     if ($isCheckInDesc > -1) {
  1523.                         $dataDescription[] = $offerRepository->find($offer->id);
  1524.                         continue;
  1525.                     }
  1526.                 }
  1527.             }
  1528.         }
  1529.         $dataTitle $this->my_array_unique($dataTitle);
  1530.         $dataDescription $this->my_array_unique($dataDescription);
  1531.         $dataFilter array_merge($dataTitle$dataDescription);
  1532.         $dataFilter $this->my_array_unique($dataFilter);
  1533.         return $dataFilter;
  1534.     }
  1535.     /**
  1536.      * changelog 2022-09-23 [FIX] (Anthony) Filtrer les données par mobilité par pertinence
  1537.      *
  1538.      * @param       $data //Les données à filtrer
  1539.      * @param ProfileRepository $profileRepository //La classe profile repository
  1540.      * @param       $locations //Les mobilités
  1541.      *
  1542.      * @return array
  1543.      */
  1544.     private
  1545.     function filterDataMobilityByPertinence($dataProfileRepository $profileRepository$locations): array
  1546.     {
  1547.         $mobilities = [];
  1548.         foreach ($locations as $mobility) {
  1549.             $regionAndDepartment $this->array_recursive_search_key_map($mobilityFrenchRegion::REGION_DEPARTEMENT_WITH_ALL);
  1550.             $mobilities['region'][] = $regionAndDepartment[self::REGION];
  1551.             $mobilities['departement'][] = $regionAndDepartment[self::DEPARTMENT];
  1552.         }
  1553.         $dataDepartement = [];
  1554.         $dataRegion = [];
  1555.         $dataFrance = [];
  1556.         foreach ($data as $profile) {
  1557.             foreach ($mobilities['departement'] as $departement) {
  1558.                 if (in_array($departement$profile->mobility)) {
  1559.                     $dataDepartement[] = $profileRepository->find($profile->id);
  1560.                     continue;
  1561.                 }
  1562.             }
  1563.             foreach ($mobilities['region'] as $region) {
  1564.                 if (in_array($region$profile->mobility)) {
  1565.                     $dataRegion[] = $profileRepository->find($profile->id);
  1566.                     continue;
  1567.                 }
  1568.             }
  1569.             if (in_array('Toute la France'$profile->mobility)) {
  1570.                 $dataFrance[] = $profileRepository->find($profile->id);
  1571.                 continue;
  1572.             }
  1573.         }
  1574.         $dataRegionDepartement array_merge($dataDepartement$dataRegion);
  1575.         $dataFilter array_merge($dataRegionDepartement$dataFrance);
  1576.         return $dataFilter;
  1577.     }
  1578.     private
  1579.     function shuffleData($data)
  1580.     {
  1581.         if (!is_array($data)) return $data;
  1582.         $keys array_keys($data);
  1583.         shuffle($keys);
  1584.         $random = array();
  1585.         foreach ($keys as $key)
  1586.             $random[$key] = $data[$key];
  1587.         return $random;
  1588.     }
  1589.     private
  1590.     function getHighLightProfile($data$page)
  1591.     {
  1592.         $highLightProfile = [];
  1593.         foreach ($data as $profile) {
  1594.             if (is_null($profile->isHighlight)) {
  1595.                 continue;
  1596.             }
  1597.             $highLightProfile[] = $profile;
  1598.         }
  1599.         if (isset($page) && $page 1) {
  1600.             $highLightProfile = [];
  1601.         }
  1602.         $highLightProfile $this->shuffleData($highLightProfile);
  1603.         return array_slice($highLightProfile02);
  1604.     }
  1605.     private
  1606.     function getOfferOpenSociety($data$user)
  1607.     {
  1608.         $offerOpenSociety = [];
  1609.         foreach ($data as $mission) {
  1610.             if ($mission->open_society == false && $user->type == 'society') {
  1611.                 continue;
  1612.             }
  1613.             $offerOpenSociety[] = $mission;
  1614.         }
  1615.         return $offerOpenSociety;
  1616.     }
  1617.     /**
  1618.      * @param Offer[] $data
  1619.      * @param int|null $page
  1620.      * @return Offer[]
  1621.      */
  1622.     private
  1623.     function getHighLightMission(array $data$page): array
  1624.     {
  1625.         $currentDate = new DateTime();
  1626.         $highLightMission = [];
  1627.         foreach ($data as $mission) {
  1628.             if (!$mission->priorize || $mission->getExpireAt() < $currentDate) {
  1629.                 continue;
  1630.             }
  1631.             $highLightMission[] = $mission;
  1632.         }
  1633.         if (isset($page) && $page 1) {
  1634.             $highLightMission = [];
  1635.         }
  1636.         $highLightMission $this->shuffleData($highLightMission);
  1637.         return array_slice($highLightMission02);
  1638.     }
  1639.     /**
  1640.      * @param Offer[] $data
  1641.      * @param int|null $page
  1642.      * @param EntityManagerInterface $entityManager
  1643.      * @return Offer[]
  1644.      */
  1645.     private
  1646.     function getOtherBoostMission(
  1647.         array                  $data,
  1648.         ?int                   $page,
  1649.         EntityManagerInterface $entityManager
  1650.     ): array {
  1651.         if (isset($page) && $page 1) {
  1652.             return [];
  1653.         }
  1654.         $currentDate = new DateTime();
  1655.         $otherBoostMission = [];
  1656.         foreach ($data as $mission) {
  1657.             if ($mission->getExpireAt() < $currentDate) {
  1658.                 continue;
  1659.             }
  1660.             if (!$mission->getDaily() && !$mission->getWeekly()) {
  1661.                 continue;
  1662.             }
  1663.             if ($mission->getDaily()) {
  1664.                 // Récupère la date et l'heure de création (createAt)
  1665.                 $createdAt $mission->getCreatedAt();
  1666.                 $lastRemonte $mission->getDateRemonter();
  1667.                 // Crée un nouvel objet DateTime basé sur l'heure de `createAt` mais avec la date du jour
  1668.                 $now = new DateTime(); // La date actuelle
  1669.                 $remonteTime = new DateTime($now->format('Y-m-d') . ' ' $createdAt->format('H:i:s')); // Date du jour avec l'heure de `createAt`
  1670.                 // Si c'est l'heure du remonté, on met à jour la date de remontée
  1671.                 // Compare uniquement les heures et minutes
  1672.                 if ($now->format('H:i') === $remonteTime->format('H:i')) {
  1673.                     if (!$lastRemonte || $lastRemonte->format('Y-m-d') !== $now->format('Y-m-d')) {
  1674.                         // Met à jour la date de remontée
  1675.                         $mission->setDateRemonter($remonteTime);
  1676.                         $entityManager->persist($mission);
  1677.                     }
  1678.                     $otherBoostMission[] = $mission;
  1679.                 }
  1680.                 continue;
  1681.             }
  1682.             // Vérifier si la date de dernière remontée est null ou si elle est plus ancienne qu'une semaine
  1683.             if ($mission->getWeekly()) {
  1684.                 $now = new DateTime();
  1685.                 $lastRemontDate $mission->getDateRemonter(); // Dernière date de remontée
  1686.                 $createdAt $mission->getCreatedAt(); // Date et heure de création
  1687.                 $currentDate = new DateTime(); // Date actuelle
  1688.                 $oneWeekAgo = (clone $currentDate)->modify('-1 week'); // Date d'une semaine en arrière
  1689.                 // Vérifier si une semaine s'est écoulée depuis la dernière remontée
  1690.                 if (($lastRemontDate === null || $lastRemontDate $oneWeekAgo)) {
  1691.                     $remonteTime = new DateTime($now->format('Y-m-d') . ' ' $createdAt->format('H:i:s')); // Date du jour avec l'heure de `createAt`
  1692.                     if ($currentDate->format('H:i') === $createdAt->format('H:i')) {
  1693.                         // Effectuer la remontée (ajouter la mission à la liste pour la journée)
  1694.                         $otherBoostMission[] = $mission// Ajouter à la liste de remontée
  1695.                     }
  1696.                     if (!$lastRemontDate || $lastRemontDate->format('Y-m-d') !== $now->format('Y-m-d')) {
  1697.                         // Mettre à jour la date de remontée pour marquer la remontée
  1698.                         $mission->setDateRemonter($remonteTime);
  1699.                         // Persister les modifications
  1700.                         $entityManager->persist($mission);
  1701.                         $entityManager->flush(); // Sauvegarder les changements dans la base de données
  1702.                     }
  1703.                 }
  1704.             }
  1705.         }
  1706.         $otherBoostMission $this->shuffleData($otherBoostMission);
  1707.         return array_slice($otherBoostMission05);
  1708.     }
  1709. }