src/Controller/SearchController.php line 85

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.         $data_offer_not_online $offerRepository->findOneBy(["slug" => '10294-developpeur-nuxeo-tt-java-j2ee-springboot']);
  862.         // DEFAULT OFFER IF NO FOUND
  863.         $noFound false;
  864.         // dd($data);
  865.         // Obtenez les données complètes si le nombre total d'offres est inférieur à 5
  866.         if (count($data) < 5) {
  867.             $data_all $this->offerIfNofound(['Toute la France'], $offerRepository,  $user && $user->isFreelance() ? [] : $contrats$order);
  868.             if (count($data) == 0) {
  869.                 $noFound true;
  870.                 if (($user && $user->isFreelance())) {
  871.                     $data $data_all;
  872.                 }
  873.             }
  874.         }
  875.         $highlightedMissions $this->getHighLightMission($data$request->query->get('page'));
  876.         $otherBoostMissions $this->getOtherBoostMission($data$request->query->get('page'), $entityManager);
  877.         // $offers = $paginator->paginate(
  878.         //     $data,
  879.         //     $request->query->getInt('page', $knpPage),
  880.         //     $knpPerPage
  881.         // );
  882.         if (count($data) < && count($data) > 0) {
  883.             $offers $data;
  884.             $data_all_offers $paginator->paginate(
  885.                 $data_all,
  886.                 $request->query->getInt('page'$knpPage),
  887.                 $knpPerPage
  888.             );
  889.         } else {
  890.             $data_all_offers = [];
  891.             $offers $paginator->paginate(
  892.                 $data,
  893.                 $request->query->getInt('page'$knpPage),
  894.                 $knpPerPage
  895.             );
  896.         }
  897.         // Build external company map by offer id for offers without linked society
  898.         $externalCompanies = [];
  899.         $collectOffers = function ($items) {
  900.             $out = [];
  901.             if (is_iterable($items)) {
  902.                 foreach ($items as $it) { $out[] = $it; }
  903.             }
  904.             return $out;
  905.         };
  906.         $allOfferObjects = [];
  907.         $allOfferObjects array_merge($allOfferObjectsis_array($data) ? $data : []);
  908.         $allOfferObjects array_merge($allOfferObjects, isset($data_all) && is_array($data_all) ? $data_all : []);
  909.         $allOfferObjects array_merge($allOfferObjects$collectOffers($offers));
  910.         $allOfferObjects array_merge($allOfferObjects$collectOffers($data_all_offers));
  911.         $allOfferObjects array_merge($allOfferObjects, isset($highlightedMissions) && is_array($highlightedMissions) ? $highlightedMissions : []);
  912.         $allOfferObjects array_merge($allOfferObjects, isset($otherBoostMissions) && is_array($otherBoostMissions) ? $otherBoostMissions : []);
  913.         foreach ($allOfferObjects as $off) {
  914.             if ($off instanceof Offer) {
  915.                 if ($off->getSociety() === null) {
  916.                     $siren method_exists($off'getSiren') ? $off->getSiren() : null;
  917.                     if ($siren) {
  918.                         $info $this->externalCompanyRepository->findCompanyBySiren($siren);
  919.                         if ($info) {
  920.                             $externalCompanies[$off->getId()] = $info;
  921.                         }
  922.                     }
  923.                 }
  924.             }
  925.         }
  926.         // Paginer $data_all
  927.         // $data_all_offers = $paginator->paginate(
  928.         //     $data_all,
  929.         //     $request->query->getInt('page', $knpPage),
  930.         //     $knpPerPage
  931.         // );
  932.         // $data_all_offers=[];
  933.         // template lié à url_libelle
  934.         // FLUSH OTHER BOOST DATE
  935.         $entityManager->flush();
  936.         $mission_region_spec = [
  937.             "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."],
  938.             "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."],
  939.             "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."],
  940.             "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."],
  941.             "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."],
  942.             "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."],
  943.             "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."],
  944.             "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."],
  945.         ];
  946.         // Variable pour stocker le titre slugifié
  947.         $title '';
  948.         $description '';
  949.         // if (!empty($template)){
  950.         //     foreach ($template as $temp){
  951.         //         $title = $temp->getTitle();
  952.         //         $description = $temp->getDescription();
  953.         //   }
  954.         // }
  955.         // Vérifier si la ville sélectionnée est une clé dans $mission_region_spec
  956.         if (array_key_exists($citySelected$mission_region_spec)) {
  957.             // Vérifier si la valeur correspond à celle dans $exeptedLocation
  958.             if ($mission_region_spec[$citySelected][0] == $exeptedLocation[0]) {
  959.                 // Créer le slug à partir de la ville sélectionnée
  960.                 $title $citySelected;
  961.                 $description $mission_region_spec[$citySelected][1];
  962.             }
  963.         }
  964.         if ($template != null) {
  965.             $template->setView($template->getView() + 1);
  966.             $entityManager->persist($template);
  967.             $entityManager->flush();
  968.         }
  969.         return $this->render('search/missions.html.twig', [
  970.             'description' => $description,
  971.             'title' => $title,
  972.             'template' => $template,
  973.             'regions' => FrenchRegion::REGION_DEPARTEMENT,
  974.             'contrats' => $contrats,
  975.             'salary' => $salary,
  976.             'defaultContrat' => $filteredContrats,
  977.             'offers' => $offers,
  978.             'data_all_offers' => $data_all_offers,
  979.             'offers_of_line' => $data_offer_not_online,
  980.             'order' => $order,
  981.             'keyword' => $keyword,
  982.             'location' => $location,
  983.             'category' => $category,
  984.             'minMax' => $minMax,
  985.             'offerViewed' => $offerViewed,
  986.             'keywordArray' => $keyword == '' ? [] : explode(','$keyword),
  987.             'isComing' => (bool)$this->getParameter('is_coming'),
  988.             'date_coming_soon' => $this->getParameter('date_coming_soon'),
  989.             'alert' => $alert,
  990.             'regionjson' => json_encode(FrenchRegion::REGION_DEPARTEMENTJSON_UNESCAPED_UNICODE),
  991.             'highlightedMissions' => $highlightedMissions ?? [],
  992.             'otherBoostMissions' => $otherBoostMissions ?? [],
  993.             'isFreelance' => $user && $user->isFreelance(),
  994.             'noFound' => $noFound,
  995.             'currentDate' => $currentDate,
  996.             'citySelected' => $citySelected,
  997.             'externalCompanies' => $externalCompanies,
  998.         ]);
  999.     }
  1000.     /**
  1001.      * changelog 2022-09-22 [FIX] (Anthony) Modifier le recherche par mobilité et re developper les tri sur la recherche
  1002.      *
  1003.      * @Route("/recherche-profils", name="freelance_search")
  1004.      *
  1005.      * @IsGranted("ROLE_USER")
  1006.      *
  1007.      * @param Request $request
  1008.      * @param ProfileRepository $profileRepository
  1009.      * @param ProfileVisitRepository $profileVisitRepository
  1010.      * @param PaginatorInterface $paginator
  1011.      * @param SkillRepository $skillRepository
  1012.      *
  1013.      * @return Response
  1014.      */
  1015.     public function freelance(
  1016.         Request                $request,
  1017.         ProfileRepository      $profileRepository,
  1018.         ProfileVisitRepository $profileVisitRepository,
  1019.         PaginatorInterface     $paginator,
  1020.         SkillRepository        $skillRepository,
  1021.         SocietyRepository      $societyRepository,
  1022.         Config                 $config
  1023.     ): Response {
  1024.         /* @var User $user */
  1025.         $user $this->getUser();
  1026.         if ($user && $user->isFreelance()) {
  1027.             return $this->redirectToRoute('dashboard');
  1028.         }
  1029.         $viewMonth = [];
  1030.         $closeToEndOfMonth false;
  1031.         $limitInMonth false;
  1032.         $society $user->getSociety();
  1033.         $packageDate $society->getPackageDate();
  1034.         if ($packageDate) {
  1035.             $packageExpireAt $society->getPackageExpireAt(); // Supposons que c'est un objet DateTime
  1036.             // Obtenir la date actuelle
  1037.             $currentDate = new DateTime();
  1038.             $dayOfPackage $packageDate->format('d');
  1039.             // Créer la date de début sur la base de la date du package
  1040.             $StartDate = new DateTime($currentDate->format('Y-m') . '-' $dayOfPackage); // Le même jour du mois actuel
  1041.             $StartDateFormatted $StartDate->format('Y-m-d'); // Format de la date de début
  1042.             // Créer la date de fin (même jour du mois suivant)
  1043.             $EndDate = (clone $StartDate)->modify('+1 month');
  1044.             $EndDateFormatted $EndDate->format('Y-m-d'); // Format de la date de fin
  1045.             // Create the EndDate + 1 month for the comparison
  1046.             $EndDatePlusOneMonth = (clone $EndDate)->modify('+1 month');
  1047.             // Check if packageExpireAt is between EndDate and EndDate + 1 month and the package is not 'month'
  1048.             $closeToEndOfMonth = (
  1049.                 $packageExpireAt >= $EndDate &&
  1050.                 $packageExpireAt <= $EndDatePlusOneMonth &&
  1051.                 $society->getPackage() !== 'month'
  1052.             );
  1053.             // Vérifier si la date d'expiration du package a été dépassée
  1054.             $limitInMonth $society->getPackage() !== 'month' && $packageExpireAt $EndDate && $packageExpireAt >= $EndDatePlusOneMonth;
  1055.             if ($packageExpireAt $EndDate) {
  1056.                 $viewMonth $profileVisitRepository->getProfileSocietyViewDailyByPeriod($society$StartDateFormatted$EndDateFormatted'month');
  1057.             }
  1058.         }
  1059.         if ($society) {
  1060.             if ($society->packageActive()) {
  1061.                 if ($society->packageActive()->isIsOnlyAnnonce()) {
  1062.                     $this->addFlash('package_error_annonce_only'" Vous ne pouvez pas consulter cette page avec votre accès.");
  1063.                     return $this->redirectToRoute('dashboard');
  1064.                 }
  1065.             }
  1066.         }
  1067.         $packageList $config->packageList();
  1068.         $packageKey $society->getPackage();
  1069.         if (array_key_exists($packageKey$packageList)) {
  1070.             $package $packageList[$packageKey];
  1071.             // renouvellement limit profileView à chaque mois
  1072.             if (!empty($viewMonth) && $viewMonth[0]['count'] == 0) {
  1073.                 $society->setProfileView($package['profileView']);
  1074.             }
  1075.         }
  1076.         $contrats $request->get('contrat', []);
  1077.         $order $request->get('order''pertinence');
  1078.         $location $request->get('mobility', []);
  1079.         $experiences $request->get('experiences', []);
  1080.         $keywords $request->get('search''');
  1081.         $max $request->get('max'0);
  1082.         $salary $request->get('salary'0);
  1083.         $favori $request->get('favori''false');
  1084.         $type $request->get('type''');
  1085.         $disponibility $request->get('disponibility''');
  1086.         $knpPage $request->get('page'1);
  1087.         $knpPerPage 10;
  1088.         if ($max == "") {
  1089.             $max 0.0;
  1090.         }
  1091.         if ($salary == "") {
  1092.             $salary 0.0;
  1093.         }
  1094.         /* @changelog 2022-09-22 [FIX] (Anthony) Permettre l'encapsulation de region, departement et vile sur la recherche par mobilité */
  1095.         // $data = $profileRepository->findBySearch($keywords, $location, $max, $type, $disponibility, $experiences, $order, $contrats, $salary, $favori, $this->getUser());
  1096.         // $data = $this->removeIntercontratExpied($data, $profileRepository, $societyRepository);
  1097.         // if (self::FILTER_PERTINENCE == $order) {
  1098.         //     $data = $this->filterDataKeywordByPertinence($data, $profileRepository, $skillRepository, $keywords);
  1099.         // }
  1100.         // /* @changeLog 2022-11-02 [FIX] (Anthony) Mise en place des intercontrats en une */
  1101.         // $highlightedProfiles = $this->getHighLightProfile($data, $request->query->get('page'));
  1102.         // $profiles = $paginator->paginate(
  1103.         //     $data,
  1104.         //     $request->query->getInt('page', $knpPage),
  1105.         //     $knpPerPage
  1106.         // );
  1107.         // 1. Récupérer le QueryBuilder (au lieu d'un tableau)
  1108.         $queryBuilder $profileRepository->findBySearchQueryBuilder(
  1109.             $keywords,
  1110.             $location,
  1111.             $max,
  1112.             $type,
  1113.             $disponibility,
  1114.             $experiences,
  1115.             $order,
  1116.             $contrats,
  1117.             $salary,
  1118.             $favori,
  1119.             $this->getUser()
  1120.         );
  1121.         // 2. Paginer directement sur le QueryBuilder
  1122.         $profilesPagination $paginator->paginate(
  1123.             $queryBuilder,
  1124.             $request->query->getInt('page'$knpPage),
  1125.             $knpPerPage
  1126.         );
  1127.         // 3. Récupérer seulement les profils de la page courante
  1128.         $profilesPage $profilesPagination->getItems();
  1129.         // 4. Appliquer les filtres lourds seulement sur la page courante
  1130.         $profilesPage $this->removeIntercontratExpied($profilesPage$profileRepository$societyRepository);
  1131.         // if (self::FILTER_PERTINENCE == $order) {
  1132.         //     $profilesPage = $this->filterDataKeywordByPertinence($profilesPage, $profileRepository, $skillRepository, $keywords);
  1133.         // }
  1134.         // 5. Optionnel : mettre à jour les items dans la pagination pour la vue
  1135.         $profilesPagination->setItems($profilesPage);
  1136.         // 6. Récupérer les profils mis en avant (sur la page filtrée)
  1137.         $highlightedProfiles $this->getHighLightProfile($profilesPage$request->query->get('page'));
  1138.         /* @changeLog 2022-11-10 [EVOL] (Anthony) Mise en place de la limitation de lecture de cv */
  1139.         $society $user->getSociety();
  1140.         $view $profileVisitRepository->countBySociety($society);
  1141.         /* Limitation de l'abonnement */
  1142.         $cycleStart null;
  1143.         $cycleEnd null;
  1144.         $activeCommande $society->packageActive();
  1145.         if ($activeCommande) {
  1146.             $cycleStart $activeCommande->getCreatedAt();
  1147.             $cycleEnd $activeCommande->getEndDate();
  1148.         } else {
  1149.             $packageDate $society->getPackageDate();
  1150.             if ($packageDate) {
  1151.                 $today = new \DateTime();
  1152.                 $dayOfPackage = (int)$packageDate->format('d');
  1153.                 $currentDay = (int)$today->format('d');
  1154.                 $startMonth $currentDay $dayOfPackage ? (clone $today)->modify('-1 month')->format('Y-m') : $today->format('Y-m');
  1155.                 $cycleStart = new \DateTime($startMonth '-' str_pad((string)$dayOfPackage2'0'STR_PAD_LEFT) . ' 00:00:00');
  1156.                 $cycleEnd = (clone $cycleStart)->modify('+1 month');
  1157.             }
  1158.         }
  1159.         $profileIds $profileVisitRepository->findDistinctProfileIdsBySocietyBetween($society$cycleStart$cycleEnd);
  1160.         $profileView count($profileIds);
  1161.         $profileViewByUser $profileVisitRepository->findByUser($user);
  1162.         $profileByUser = [];
  1163.         foreach ($profileViewByUser as $visit) {
  1164.             $profileByUser[] = $visit['id'];
  1165.         }
  1166.         /* Limitation journalière alignée à l'heure de début du package (fenêtre 24h) */
  1167.         $startAt date("Y-m-d") . ' 00:00:01';
  1168.         $endAt date("Y-m-d") . ' 23:59:59';
  1169.         $packageAnchor null;
  1170.         $activeCommande $society $society->packageActive() : null;
  1171.         if ($activeCommande) {
  1172.             $packageAnchor $activeCommande->getCreatedAt();
  1173.         } else if ($society) {
  1174.             $packageAnchor $society->getPackageDate();
  1175.         }
  1176.         if ($packageAnchor) {
  1177.             $now = new DateTime();
  1178.             $anchorTime $packageAnchor->format('H:i:s');
  1179.             $todayAnchor = new DateTime($now->format('Y-m-d') . ' ' $anchorTime);
  1180.             if ($now $todayAnchor) {
  1181.                 $todayAnchor->modify('-1 day');
  1182.             }
  1183.             $dailyStart $todayAnchor;
  1184.             $dailyEnd = (clone $dailyStart)->modify('+1 day');
  1185.             $startAt $dailyStart->format('Y-m-d H:i:s');
  1186.             $endAt $dailyEnd->format('Y-m-d H:i:s');
  1187.         }
  1188.         $ProfilesVisitDaily $profileVisitRepository->findBySocietyDaily($society$startAt$endAt);
  1189.         $profileDailyIds = [];
  1190.         foreach ($ProfilesVisitDaily as $visitDaily) {
  1191.             $profileDailyIds[] = $visitDaily['id'];
  1192.         }
  1193.         $profileViewDaily count(array_unique($profileDailyIds));
  1194.         $dayLimit 150;
  1195.         $packageLimit = ($society->getProfileView());
  1196.         $defaultContrat = ['Freelance''CDI''CDD''Alternance''Stage'];
  1197.         return $this->render('search/freelance.html.twig', [
  1198.             'profiles' => $profilesPagination,
  1199.             'defaultContrat' => $defaultContrat,
  1200.             'contrats' => $contrats,
  1201.             'keyword' => $keywords,
  1202.             'location' => $location,
  1203.             'max' => $max,
  1204.             'salary' => $salary,
  1205.             'order' => $order,
  1206.             'type' => $type,
  1207.             'keywordArray' => $keywords == '' ? [] : explode(','$keywords),
  1208.             'regions' => FrenchRegion::REGION_DEPARTEMENT,
  1209.             'regionjson' => json_encode(FrenchRegion::REGION_DEPARTEMENTJSON_UNESCAPED_UNICODE),
  1210.             'disponibilities' => Disponibility::LIST,
  1211.             'experiencies' => Experience::LIST_FOR_PROFILE,
  1212.             'experiences' => $experiences,
  1213.             'disponibility' => $disponibility,
  1214.             'highlightedProfiles' => $highlightedProfiles ?? [],
  1215.             'profileViewDaily' => $profileViewDaily,
  1216.             'profileView' => $profileView,
  1217.             'dayLimit' => $dayLimit,
  1218.             //'dayLimit' => 4,
  1219.             'packageLimit' => $packageLimit,
  1220.             // 'packageLimit' => 0,
  1221.             'closeToEndOfMonth' => $closeToEndOfMonth,
  1222.             'limitInMonth' => $limitInMonth,
  1223.             'endDatePackage' => $EndDate ?? null,
  1224.             'profileIds' => array_unique($profileIds),
  1225.             'profileViewByUser' => array_unique($profileByUser),
  1226.             'favori' => $favori
  1227.         ]);
  1228.     }
  1229.     /**
  1230.      * Récuperer la region et le departement
  1231.      *
  1232.      * @param $needle //"Le mot clé"
  1233.      * @param array $haystack //"Le tableau lequel on fait la recherche"
  1234.      *
  1235.      * @return array|bool
  1236.      */
  1237.     public
  1238.     function array_recursive_search_key_map(
  1239.         $needle,
  1240.         array $haystack
  1241.     ) {
  1242.         foreach ($haystack as $first_level_key => $value) {
  1243.             if ($needle === $value) {
  1244.                 return array($first_level_key);
  1245.             } elseif (is_array($value)) {
  1246.                 $callback $this->array_recursive_search_key_map($needle$value);
  1247.                 if ($callback) {
  1248.                     return array_merge(array($first_level_key), $callback);
  1249.                 }
  1250.             }
  1251.         }
  1252.         return false;
  1253.     }
  1254.     /**
  1255.      * changelog 2022-09-28 [FIX] (Anthony) Formatter les données de la mobilité
  1256.      *
  1257.      * @param array $haystack Les region et departement à rechercher
  1258.      * @param array $mobilities Les mobilités à rechercher
  1259.      *
  1260.      * @return array
  1261.      */
  1262.     private
  1263.     function getMobilities(
  1264.         $haystack,
  1265.         array $mobilities = []
  1266.     ): array {
  1267.         $results = ["Toute la France"];
  1268.         if (count($mobilities) == && array_values($mobilities)[0] != "Toute la France" && in_array($mobilities[0], FrenchRegion::REGION)) {
  1269.             foreach ($mobilities as $mobility) {
  1270.                 $results[] = $mobility;
  1271.             }
  1272.         } else {
  1273.             foreach ($mobilities as $mobility) {
  1274.                 $regionAndDepartment $this->array_recursive_search_key_map($mobility$haystack);
  1275.                 $results[] = $regionAndDepartment[self::REGION];
  1276.                 $results[] = $regionAndDepartment[self::DEPARTMENT];
  1277.             }
  1278.         }
  1279.         return $results;
  1280.     }
  1281.     /**
  1282.      * changelog 2022-09-22 [FIX] (Anthony) Formatter les données de la mobilité
  1283.      *
  1284.      * @param array $datas //Les region et departement à rechercher
  1285.      * @param $order //Filtre de la recherche
  1286.      * @param ProfileRepository $profileRepository //La classe profile repository
  1287.      * @param array $mobilities //Les mobilités à rechercher
  1288.      *
  1289.      * @return array
  1290.      */
  1291.     private
  1292.     function checkProfilesByMobility($datas$profileRepository$order$mobilities = [])
  1293.     {
  1294.         $results = ["Toute la France"];
  1295.         if (count($mobilities) == && array_values($mobilities)[0] == "Toute la France") {
  1296.             $data $profileRepository->findByMobility($order$results);
  1297.         } else if (count($mobilities) == && array_values($mobilities)[0] != "Toute la France" && in_array($mobilities[0], FrenchRegion::REGION)) {
  1298.             foreach ($mobilities as $mobility) {
  1299.                 $results[] = $mobility;
  1300.             }
  1301.             $data $profileRepository->findByMobility($order$results);
  1302.         } else {
  1303.             foreach ($mobilities as $mobility) {
  1304.                 $regionAndDepartment $this->array_recursive_search_key_map($mobility$datas);
  1305.                 $results[] = $regionAndDepartment[self::REGION];
  1306.                 $results[] = $regionAndDepartment[self::DEPARTMENT];
  1307.             }
  1308.             $data $profileRepository->findByMobility($orderarray_unique($results));
  1309.         }
  1310.         return $data;
  1311.     }
  1312.     /**
  1313.      * changelog 2022-09-27 [FIX] (Anthony) Formatter les données des missions par mot clé
  1314.      *
  1315.      * @param array $keywords //Les mots clé à rechercher
  1316.      * @param OfferRepository $offerRepository //La classe offer repository
  1317.      * @param $order //Filtre de la recherche
  1318.      *
  1319.      * @return array
  1320.      */
  1321.     private
  1322.     function checkOfferByKeword($keywords$offerRepository$order)
  1323.     {
  1324.         $data $offerRepository->findByKeyword($keywords$order);
  1325.         return $data;
  1326.     }
  1327.     /**
  1328.      * changelog 2022-09-26 [FIX] (Anthony) Formatter les données des freelances par mot clé
  1329.      *
  1330.      * @param  $keywords // Les mots clé à rechercher
  1331.      * @param ProfileRepository $profileRepository //La classe profile repository
  1332.      * @param $order // Filtre de la recherche
  1333.      *
  1334.      * @return array
  1335.      */
  1336.     private
  1337.     function checkProfilesByKeword($keywordsProfileRepository $profileRepository$order): array
  1338.     {
  1339.         return $profileRepository->findByKeyword($keywords$order);
  1340.     }
  1341.     /**
  1342.      * changelog 2022-09-26 [FIX] (Anthony) Formatter les données par type
  1343.      *
  1344.      * @param $type //Le type du profile
  1345.      * @param ProfileRepository $profileRepository //La classe profile repository
  1346.      * @param $order //Filtre de la recherche
  1347.      *
  1348.      * @return array
  1349.      */
  1350.     private
  1351.     function checkProfilesByType($typeProfileRepository $profileRepository$order): array
  1352.     {
  1353.         $data $profileRepository->findByType($type$order);
  1354.         return $data;
  1355.     }
  1356.     /**
  1357.      * changelog 2022-09-26 [FIX] (Anthony) Formater les données de la disponibilité
  1358.      *
  1359.      * @param $disponibility //La disponibilité du profile
  1360.      * @param ProfileRepository $profileRepository //La classe profile repository
  1361.      * @param $order //Filtre de la recherche
  1362.      *
  1363.      * @return array
  1364.      */
  1365.     private
  1366.     function checkProfilesByDisponibility($disponibilityProfileRepository $profileRepository$order): array
  1367.     {
  1368.         $data $profileRepository->findByDisponibility($disponibility$order);
  1369.         return $data;
  1370.     }
  1371.     /**
  1372.      * changelog 2022-09-26 [FIX] (Anthony) Formater les données de la TJM
  1373.      *
  1374.      * @param $cost //La TJM du profile
  1375.      * @param ProfileRepository $profileRepository //La classe profile repository
  1376.      * @param $order //Filtre de la recherche
  1377.      *
  1378.      * @return array
  1379.      */
  1380.     private
  1381.     function checkProfilesByCost($costProfileRepository $profileRepository$order): array
  1382.     {
  1383.         $data $profileRepository->findByCost($cost$order);
  1384.         return $data;
  1385.     }
  1386.     /**
  1387.      * changelog 2022-09-23 [FIX] (Anthony) Supprimé les doublons du tableau d'objet
  1388.      *
  1389.      * @param       $array //Le tableau d'objet
  1390.      * @param       $keep_key_assoc
  1391.      *
  1392.      * @return array
  1393.      */
  1394.     private
  1395.     function my_array_unique($array$keep_key_assoc false)
  1396.     {
  1397.         $duplicate_keys = array();
  1398.         $tmp = array();
  1399.         foreach ($array as $key => $val) {
  1400.             // convert objects to arrays, in_array() does not support objects
  1401.             if (is_object($val))
  1402.                 $val = (array)$val;
  1403.             if (!in_array($val$tmp))
  1404.                 $tmp[] = $val;
  1405.             else
  1406.                 $duplicate_keys[] = $key;
  1407.         }
  1408.         foreach ($duplicate_keys as $key)
  1409.             unset($array[$key]);
  1410.         return $keep_key_assoc $array array_values($array);
  1411.     }
  1412.     private function removeIntercontratExpied($dataProfileRepository $profileRepositorySocietyRepository $societyRepository)
  1413.     {
  1414.         // Filtrer la liste des profils
  1415.         return array_filter($data, function ($profile) use ($societyRepository) {
  1416.             // Vérifie si le profil est en intercontrat
  1417.             if ($profile->isIntercontrat) {
  1418.                 // Récupère la société associée au profil
  1419.                 $society $societyRepository->findOneBy(['user' => $profile->user]);
  1420.                 // Vérifie si la société existe et si son package est expiré
  1421.                 if ($society && $society->getPackageExpireAt() < new \DateTime()) {
  1422.                     // Exclure ce profil (retourne false pour ne pas l'inclure)
  1423.                     return false;
  1424.                 }
  1425.             }
  1426.             // Inclure ce profil
  1427.             return true;
  1428.         });
  1429.     }
  1430.     /**
  1431.      * changelog 2022-09-23 [FIX] (Anthony) Filtrer les données freelances par mot clé par pertinence
  1432.      *
  1433.      * @param       $data // Les données à filtrer
  1434.      * @param ProfileRepository $profileRepository // La classe profile repository
  1435.      * @param SkillRepository $skillRepository // La classe skill repository
  1436.      * @param       $keyword // Les mots clé
  1437.      *
  1438.      * @return array
  1439.      */
  1440.     private
  1441.     function filterDataKeywordByPertinence($dataProfileRepository $profileRepositorySkillRepository $skillRepository$keyword): array
  1442.     {
  1443.         $dataTitle = [];
  1444.         $dataName = [];
  1445.         $dataAbout = [];
  1446.         $keyword explode(' '$keyword);
  1447.         foreach ($data as $profile) {
  1448.             foreach ($keyword as $key) {
  1449.                 $isCheckInTitle stripos($profile->title$key);
  1450.                 if ($isCheckInTitle > -1) {
  1451.                     $dataTitle[] = $profileRepository->find($profile->id);
  1452.                     continue;
  1453.                 }
  1454.             }
  1455.             $skillsData $skillRepository->findBy(['profile' => $profile]);
  1456.             $skillName = [];
  1457.             foreach ($skillsData as $skill) {
  1458.                 $skillName[] = $skill->name;
  1459.             }
  1460.             $skillName implode(','$skillName);
  1461.             foreach ($keyword as $key) {
  1462.                 $isCheckInSkill stripos($skillName$key);
  1463.                 if ($isCheckInSkill > -1) {
  1464.                     $dataName[] = $profileRepository->find($profile->id);
  1465.                     continue;
  1466.                 }
  1467.             }
  1468.             if (!empty($profile->about)) {
  1469.                 foreach ($keyword as $key) {
  1470.                     $isCheckInAbout stripos($profile->about$key);
  1471.                     if ($isCheckInAbout > -1) {
  1472.                         $dataAbout[] = $profileRepository->find($profile->id);
  1473.                         continue;
  1474.                     }
  1475.                 }
  1476.             }
  1477.             if (!empty($profile->cvText)) {
  1478.                 foreach ($keyword as $key) {
  1479.                     $isCheckInAbout stripos($profile->cvText$key);
  1480.                     if ($isCheckInAbout > -1) {
  1481.                         $dataAbout[] = $profileRepository->find($profile->id);
  1482.                         continue;
  1483.                     }
  1484.                 }
  1485.             }
  1486.         }
  1487.         $dataTitle $this->my_array_unique($dataTitle);
  1488.         $dataName $this->my_array_unique($dataName);
  1489.         $dataAbout $this->my_array_unique($dataAbout);
  1490.         $dataTitleName array_merge($dataTitle$dataName);
  1491.         $dataFilter array_merge($dataTitleName$dataAbout);
  1492.         $dataFilter $this->my_array_unique($dataFilter);
  1493.         return $dataFilter;
  1494.     }
  1495.     /**
  1496.      * changelog 2022-09-27 [FIX] (Anthony) Filtrer les données freelances par mot clé par pertinence
  1497.      *
  1498.      * @param       $data //Les données à filtrer
  1499.      * @param OfferRepository $offerRepository //La classe offer repository
  1500.      * @param       $keyword //Les mots clé
  1501.      *
  1502.      * @return array
  1503.      */
  1504.     private
  1505.     function filterOfferByPertinence($data$offerRepository$keyword)
  1506.     {
  1507.         $dataTitle = [];
  1508.         $dataDescription = [];
  1509.         $keyword explode(' '$keyword);
  1510.         foreach ($data as $offer) {
  1511.             foreach ($keyword as $kwd) {
  1512.                 $isCheckInTitle stripos($offer->title$kwd);
  1513.                 if ($isCheckInTitle > -1) {
  1514.                     $dataTitle[] = $offerRepository->find($offer->id);
  1515.                     continue;
  1516.                 }
  1517.             }
  1518.             if (!empty($offer->description)) {
  1519.                 foreach ($keyword as $kwd) {
  1520.                     $isCheckInDesc stripos($offer->description$kwd);
  1521.                     if ($isCheckInDesc > -1) {
  1522.                         $dataDescription[] = $offerRepository->find($offer->id);
  1523.                         continue;
  1524.                     }
  1525.                 }
  1526.             }
  1527.         }
  1528.         $dataTitle $this->my_array_unique($dataTitle);
  1529.         $dataDescription $this->my_array_unique($dataDescription);
  1530.         $dataFilter array_merge($dataTitle$dataDescription);
  1531.         $dataFilter $this->my_array_unique($dataFilter);
  1532.         return $dataFilter;
  1533.     }
  1534.     /**
  1535.      * changelog 2022-09-23 [FIX] (Anthony) Filtrer les données par mobilité par pertinence
  1536.      *
  1537.      * @param       $data //Les données à filtrer
  1538.      * @param ProfileRepository $profileRepository //La classe profile repository
  1539.      * @param       $locations //Les mobilités
  1540.      *
  1541.      * @return array
  1542.      */
  1543.     private
  1544.     function filterDataMobilityByPertinence($dataProfileRepository $profileRepository$locations): array
  1545.     {
  1546.         $mobilities = [];
  1547.         foreach ($locations as $mobility) {
  1548.             $regionAndDepartment $this->array_recursive_search_key_map($mobilityFrenchRegion::REGION_DEPARTEMENT_WITH_ALL);
  1549.             $mobilities['region'][] = $regionAndDepartment[self::REGION];
  1550.             $mobilities['departement'][] = $regionAndDepartment[self::DEPARTMENT];
  1551.         }
  1552.         $dataDepartement = [];
  1553.         $dataRegion = [];
  1554.         $dataFrance = [];
  1555.         foreach ($data as $profile) {
  1556.             foreach ($mobilities['departement'] as $departement) {
  1557.                 if (in_array($departement$profile->mobility)) {
  1558.                     $dataDepartement[] = $profileRepository->find($profile->id);
  1559.                     continue;
  1560.                 }
  1561.             }
  1562.             foreach ($mobilities['region'] as $region) {
  1563.                 if (in_array($region$profile->mobility)) {
  1564.                     $dataRegion[] = $profileRepository->find($profile->id);
  1565.                     continue;
  1566.                 }
  1567.             }
  1568.             if (in_array('Toute la France'$profile->mobility)) {
  1569.                 $dataFrance[] = $profileRepository->find($profile->id);
  1570.                 continue;
  1571.             }
  1572.         }
  1573.         $dataRegionDepartement array_merge($dataDepartement$dataRegion);
  1574.         $dataFilter array_merge($dataRegionDepartement$dataFrance);
  1575.         return $dataFilter;
  1576.     }
  1577.     private
  1578.     function shuffleData($data)
  1579.     {
  1580.         if (!is_array($data)) return $data;
  1581.         $keys array_keys($data);
  1582.         shuffle($keys);
  1583.         $random = array();
  1584.         foreach ($keys as $key)
  1585.             $random[$key] = $data[$key];
  1586.         return $random;
  1587.     }
  1588.     private
  1589.     function getHighLightProfile($data$page)
  1590.     {
  1591.         $highLightProfile = [];
  1592.         foreach ($data as $profile) {
  1593.             if (is_null($profile->isHighlight)) {
  1594.                 continue;
  1595.             }
  1596.             $highLightProfile[] = $profile;
  1597.         }
  1598.         if (isset($page) && $page 1) {
  1599.             $highLightProfile = [];
  1600.         }
  1601.         $highLightProfile $this->shuffleData($highLightProfile);
  1602.         return array_slice($highLightProfile02);
  1603.     }
  1604.     private
  1605.     function getOfferOpenSociety($data$user)
  1606.     {
  1607.         $offerOpenSociety = [];
  1608.         foreach ($data as $mission) {
  1609.             if ($mission->open_society == false && $user->type == 'society') {
  1610.                 continue;
  1611.             }
  1612.             $offerOpenSociety[] = $mission;
  1613.         }
  1614.         return $offerOpenSociety;
  1615.     }
  1616.     /**
  1617.      * @param Offer[] $data
  1618.      * @param int|null $page
  1619.      * @return Offer[]
  1620.      */
  1621.     private
  1622.     function getHighLightMission(array $data$page): array
  1623.     {
  1624.         $currentDate = new DateTime();
  1625.         $highLightMission = [];
  1626.         foreach ($data as $mission) {
  1627.             if (!$mission->priorize || $mission->getExpireAt() < $currentDate) {
  1628.                 continue;
  1629.             }
  1630.             $highLightMission[] = $mission;
  1631.         }
  1632.         if (isset($page) && $page 1) {
  1633.             $highLightMission = [];
  1634.         }
  1635.         $highLightMission $this->shuffleData($highLightMission);
  1636.         return array_slice($highLightMission02);
  1637.     }
  1638.     /**
  1639.      * @param Offer[] $data
  1640.      * @param int|null $page
  1641.      * @param EntityManagerInterface $entityManager
  1642.      * @return Offer[]
  1643.      */
  1644.     private
  1645.     function getOtherBoostMission(
  1646.         array                  $data,
  1647.         ?int                   $page,
  1648.         EntityManagerInterface $entityManager
  1649.     ): array {
  1650.         if (isset($page) && $page 1) {
  1651.             return [];
  1652.         }
  1653.         $currentDate = new DateTime();
  1654.         $otherBoostMission = [];
  1655.         foreach ($data as $mission) {
  1656.             if ($mission->getExpireAt() < $currentDate) {
  1657.                 continue;
  1658.             }
  1659.             if (!$mission->getDaily() && !$mission->getWeekly()) {
  1660.                 continue;
  1661.             }
  1662.             if ($mission->getDaily()) {
  1663.                 // Récupère la date et l'heure de création (createAt)
  1664.                 $createdAt $mission->getCreatedAt();
  1665.                 $lastRemonte $mission->getDateRemonter();
  1666.                 // Crée un nouvel objet DateTime basé sur l'heure de `createAt` mais avec la date du jour
  1667.                 $now = new DateTime(); // La date actuelle
  1668.                 $remonteTime = new DateTime($now->format('Y-m-d') . ' ' $createdAt->format('H:i:s')); // Date du jour avec l'heure de `createAt`
  1669.                 // Si c'est l'heure du remonté, on met à jour la date de remontée
  1670.                 // Compare uniquement les heures et minutes
  1671.                 if ($now->format('H:i') === $remonteTime->format('H:i')) {
  1672.                     if (!$lastRemonte || $lastRemonte->format('Y-m-d') !== $now->format('Y-m-d')) {
  1673.                         // Met à jour la date de remontée
  1674.                         $mission->setDateRemonter($remonteTime);
  1675.                         $entityManager->persist($mission);
  1676.                     }
  1677.                     $otherBoostMission[] = $mission;
  1678.                 }
  1679.                 continue;
  1680.             }
  1681.             // Vérifier si la date de dernière remontée est null ou si elle est plus ancienne qu'une semaine
  1682.             if ($mission->getWeekly()) {
  1683.                 $now = new DateTime();
  1684.                 $lastRemontDate $mission->getDateRemonter(); // Dernière date de remontée
  1685.                 $createdAt $mission->getCreatedAt(); // Date et heure de création
  1686.                 $currentDate = new DateTime(); // Date actuelle
  1687.                 $oneWeekAgo = (clone $currentDate)->modify('-1 week'); // Date d'une semaine en arrière
  1688.                 // Vérifier si une semaine s'est écoulée depuis la dernière remontée
  1689.                 if (($lastRemontDate === null || $lastRemontDate $oneWeekAgo)) {
  1690.                     $remonteTime = new DateTime($now->format('Y-m-d') . ' ' $createdAt->format('H:i:s')); // Date du jour avec l'heure de `createAt`
  1691.                     if ($currentDate->format('H:i') === $createdAt->format('H:i')) {
  1692.                         // Effectuer la remontée (ajouter la mission à la liste pour la journée)
  1693.                         $otherBoostMission[] = $mission// Ajouter à la liste de remontée
  1694.                     }
  1695.                     if (!$lastRemontDate || $lastRemontDate->format('Y-m-d') !== $now->format('Y-m-d')) {
  1696.                         // Mettre à jour la date de remontée pour marquer la remontée
  1697.                         $mission->setDateRemonter($remonteTime);
  1698.                         // Persister les modifications
  1699.                         $entityManager->persist($mission);
  1700.                         $entityManager->flush(); // Sauvegarder les changements dans la base de données
  1701.                     }
  1702.                 }
  1703.             }
  1704.         }
  1705.         $otherBoostMission $this->shuffleData($otherBoostMission);
  1706.         return array_slice($otherBoostMission05);
  1707.     }
  1708. }