src/Controller/AnnuaireController.php line 636

Open in your IDE?
  1. <?php
  2. declare (strict_types 1);
  3. /*
  4.  * Copyright (C) Office National de Publication et de Communication - All Rights Reserved
  5.  *
  6.  * Unauthorized copying of this file, via any medium is strictly prohibited by law
  7.  * This file is proprietary and confidential
  8.  */
  9. namespace App\Controller;
  10. use App\Entity\Faq;
  11. use App\Entity\Items;
  12. use App\Entity\Trace;
  13. use App\Entity\Ville;
  14. use App\Entity\Region;
  15. use App\Service\Slugify;
  16. use App\Service\Traceur;
  17. use App\Entity\Actualite;
  18. use App\Entity\Departement;
  19. use App\Service\Historique;
  20. use App\Service\PathBuilder;
  21. use App\Common\LieuInterface;
  22. use App\Elasticsearch\Engine;
  23. use App\Elasticsearch\Moteur;
  24. use App\Entity\ZonesInternat;
  25. use App\Entity\AncienneRegion;
  26. use App\Entity\ItemsInsertion;
  27. use App\Service\CrawlerDetect;
  28. use App\Service\UserTransient;
  29. use App\Elasticsearch\Parametres;
  30. use App\Repository\VilleRepository;
  31. use App\Repository\RegionRepository;
  32. use App\Repository\ActualiteRepository;
  33. use Doctrine\Persistence\ManagerRegistry;
  34. use App\Entity\SeoTexteReferencementDiplome;
  35. use Symfony\Component\HttpFoundation\Request;
  36. use Symfony\Component\HttpFoundation\Response;
  37. use Symfony\Component\Routing\RouterInterface;
  38. use Symfony\Component\Routing\Annotation\Route;
  39. use Symfony\Component\HttpFoundation\RequestStack;
  40. use Symfony\Component\HttpFoundation\Session\Session;
  41. use Symfony\Component\HttpKernel\HttpKernelInterface;
  42. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
  43. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  44. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  45. final class AnnuaireController extends AbstractController
  46. {
  47.     private const MAX Moteur::PER_PAGE_DEFAULT_2;
  48.     private const MAX_DIPLOME 60;
  49.     private const MAX_ACTUALITE 10;
  50.     /** @var Slugify */
  51.     private $slugify;
  52.     /** @var Moteur */
  53.     private $moteur;
  54.     /** @var UserTransient */
  55.     private $userTransient;
  56.     /** @var Historique */
  57.     private $historique;
  58.     /** @var CrawlerDetect */
  59.     private $crawlerDetect;
  60.     /** @var PathBuilder */
  61.     private $pathBuilder;
  62.     /** @var Traceur */
  63.     private $traceur;
  64.     private $engine;
  65.     /** @var ManagerRegistry */
  66.     private $doctrine;
  67.     private HttpKernelInterface $httpKernel;
  68.     private RequestStack $requestStack;
  69.     private RouterInterface $router;
  70.     public function __construct(
  71.         Slugify $slugify,
  72.         Moteur $moteur,
  73.         UserTransient $userTransient,
  74.         Historique $historique,
  75.         CrawlerDetect $crawlerDetect,
  76.         PathBuilder $pathBuilder,
  77.         Traceur $traceur,
  78.         Moteur $engine,
  79.         ManagerRegistry $doctrine,
  80.         HttpKernelInterface $httpKernel
  81.         RequestStack $requestStack,
  82.         RouterInterface $router
  83.     ) {
  84.         $this->slugify $slugify;
  85.         $this->moteur $moteur;
  86.         $this->userTransient $userTransient;
  87.         $this->historique $historique;
  88.         $this->crawlerDetect $crawlerDetect;
  89.         $this->pathBuilder $pathBuilder;
  90.         $this->traceur $traceur;
  91.         $this->engine $engine;
  92.         $this->doctrine $doctrine;
  93.         $this->httpKernel $httpKernel;
  94.         $this->requestStack $requestStack;
  95.         $this->router $router;
  96.     }
  97.     /**
  98.      * @Route("/annuaire", name="annuaire", methods={"GET"})
  99.      */
  100.     public function index(): Response
  101.     {
  102.         return $this->redirectToRoute('homepage', [], 301);
  103.     }
  104.     /**
  105.      * @Route("/annuaire/{quoi}", name="annuaire_quoi", methods={"GET"})
  106.      */
  107.     public function quoi(string $quoi): Response
  108.     {
  109.         return $this->redirectToRoute('enseignement-catholique', [], 301);
  110.     }
  111.     /**
  112.      * @Route(
  113.      *     "/annuaire-enseignement-catholique/{lieu}",
  114.      *     name="annuaire_catho",
  115.      *     methods={"GET"},
  116.      *     defaults={"typeOnglet"="annuaire-enseignement-catholique"}
  117.      * )
  118.      * @Route(
  119.      *     "/annuaire-enseignement-prive/{lieu}",
  120.      *     name="annuaire_prive",
  121.      *     methods={"GET"},
  122.      *     defaults={"typeOnglet"="annuaire-enseignement-prive"}
  123.      * )
  124.      *
  125.      * @Route(
  126.      *     "/annuaire/{quoi}/{lieu}",
  127.      *     name="annuaire_liste",
  128.      *     methods={"GET"}
  129.      * )
  130.      *
  131.      * @Route(
  132.      *     "/onglet/superieur/{sousTypeOnglet}/{niveauOnglet}",
  133.      *     name="annuaire_liste_par_onglet_sup",
  134.      *     methods={"GET"},
  135.      *     defaults={"niveauOnglet"="tout"}
  136.      * )
  137.      *
  138.      * @Route(
  139.      *     "/onglet/superieur/{sousTypeOnglet}/{niveauOnglet}/{localisation}",
  140.      *     name="annuaire_liste_par_onglet_sup_localisation",
  141.      *     methods={"GET"},
  142.      *     defaults={"niveauOnglet"="tout"}
  143.      * )
  144.      *
  145.      * @Route(
  146.      *     "/onglet/{typeOnglet}/{niveauOnglet}",
  147.      *     name="annuaire_liste_par_onglet",
  148.      *     methods={"GET"},
  149.      *     defaults={"niveauOnglet"="tout"}
  150.      * )
  151.      *
  152.      *
  153.      * @Route(
  154.      *     "/onglet/{typeOnglet}/{niveauOnglet}/{localisation}",
  155.      *     name="annuaire_liste_par_onglet_localisation",
  156.      *     methods={"GET"},
  157.      *     defaults={"niveauOnglet"="tout"}
  158.      * )
  159.      *
  160.      * @Cache(expires="+1 minute", public=false)
  161.      */
  162.     public function liste(Request $requeststring $quoi nullstring $lieu null,
  163.         $typeOnglet null$sousTypeOnglet null$niveauOnglet null$localisation null): Response {
  164.         $lieuTemp null;
  165.         $parametres = new Parametres();
  166.         // 2025 - redirection des liens du sidebar gauche catho > privé
  167.         $currentRoute $request->attributes->get('_route');
  168.         if ($currentRoute == "annuaire_catho") {
  169.             return $this->redirectToRoute('annuaire_prive', [
  170.                 "typeOnglet" => "annuaire-enseignement-prive",
  171.                 "lieu" => $lieu
  172.             ], 301);
  173.         }
  174.         // (sous-)Redirection de la racine "/onglet" vers "/ecoles-colleges-lycees"
  175.         $uri $request->getPathInfo();
  176.         if ($uri == "/onglet" || $uri == "/onglet/") {
  177.             $routeName 'enseignement-prive'// The route name you want to call
  178.             $routeParams $this->router->match($this->generateUrl($routeName));
  179.             $subRequest $request->duplicate([], null, ['_controller' => $routeParams['_controller']] + $routeParams);
  180.             return $this->httpKernel->handle($subRequestHttpKernelInterface::SUB_REQUEST);
  181.         }
  182.         // Bloquer les params bizarres non reconnus (exp : region, lang ...)
  183.         $getParams $request->query->all();
  184.         $acceptedGetParams = [
  185.             'page',
  186.             'filiere',
  187.             'diplome',
  188.             'eds',
  189.             'pTypeOnglet',
  190.             'pSousTypeOnglet',
  191.             'pNiveauOnglet',
  192.             'pQueryString',
  193.             'statut',
  194.             'autre',
  195.             'alternance',
  196.             'age',
  197.             'lva',
  198.             'lvb',
  199.             'lieu',
  200.             'emplacement',
  201.             'type',
  202.             'single',
  203.             'emplacement',
  204.             'id',
  205.             'onglet',
  206.             'departement',
  207.             'profil',
  208.             'niveau',
  209.             'utm_source',
  210.             'utm_medium',
  211.             'utm_campaign',
  212.             'utm_content',
  213.             'utm_term',
  214.             'utm_id',
  215.             'utm_adgroup',
  216.             'utm_adname',
  217.             'utm_adset',
  218.             'utm_adtype',
  219.             'utm_adgroupid',
  220.             'utm_adnameid',
  221.             'utm_adsetid',
  222.             'gclid',
  223.             'dclid',
  224.             'fbclid',
  225.             'twclid',
  226.             'msclkid',
  227.             '_gl',
  228.         ];
  229.         
  230.         if (count($getParams)) {
  231.             $getParams array_keys($getParams);
  232.             foreach ($getParams as $getParam) {
  233.                 if (!in_array($getParam$acceptedGetParams)) {
  234.                     throw $this->createNotFoundException("Cette page n'exite pas !");
  235.                 } else {
  236.                     // Si le param existe mais n'a aucune valeur => STOP
  237.                     $value $_GET[$getParam];
  238.                     if (!$value || empty($value))
  239.                         throw $this->createNotFoundException("Cette page n'exite pas !!");
  240.                     if (is_array($value) && count($value) == && $value[0] === "")
  241.                         throw $this->createNotFoundException("Cette page n'exite pas !!!");
  242.                 }
  243.             }
  244.         }
  245.         if ('filiere' == $sousTypeOnglet) {
  246.             return $this->redirectToRoute('annuaire_liste_par_onglet_sup', ['niveauOnglet' => 'tout'], 301);
  247.         }
  248.         /* 
  249.         Gérer les URLs qui fonctionnent mais qui ne devraient pas exister 
  250.         EXP : 
  251.             /onglet/ecole/belleville-69220/dorans-90400?niveau[]=02-ELEM
  252.                 belleville-69220 n'existe pas ! la bonne ville est belleville-en-beaujolais-69220
  253.             /onglet/ecole/saint-denis-89100/granges-la-ville-70400?niveau%5B0%5D=02-ELEM
  254.                 saint-denis-89100 n'existe pas ! la bonne ville est saint-denis-les-sens-89100
  255.         */
  256.         // dump("typeOnglet : $typeOnglet / niveauOnglet : $niveauOnglet /  localisation : $localisation");
  257.         switch ($typeOnglet) {
  258.             case 'ecole':
  259.                 if ( 
  260.                     !$this->slugify->revealLieu($niveauOnglet) && 
  261.                     $niveauOnglet != "maternelle" && 
  262.                     $niveauOnglet != "elementaire" && 
  263.                     $niveauOnglet != "tout"  
  264.                 )
  265.                     throw $this->createNotFoundException("URL interdite [1]");
  266.                 break;
  267.             case 'college':
  268.                 if ( 
  269.                     !$this->slugify->revealLieu($niveauOnglet) && 
  270.                     $niveauOnglet != "tout"  
  271.                 )
  272.                     throw $this->createNotFoundException("URL interdite [2]");
  273.                 break;
  274.             case 'lycee':
  275.                 if ( 
  276.                     !$this->slugify->revealLieu($niveauOnglet) && 
  277.                     $niveauOnglet != "general" && 
  278.                     $niveauOnglet != "technologique" && 
  279.                     $niveauOnglet != "tout"  
  280.                 )
  281.                     throw $this->createNotFoundException("URL interdite [3]");
  282.                 break;
  283.             
  284.             case 'professionnel':
  285.                 if ( 
  286.                     !$this->slugify->revealLieu($niveauOnglet) && 
  287.                     $niveauOnglet != "cap" && 
  288.                     $niveauOnglet != "bac-pro" && 
  289.                     $niveauOnglet != "formation-pro-continue" && 
  290.                     $niveauOnglet != "tout"  
  291.                 )
  292.                     throw $this->createNotFoundException("URL interdite [4]");
  293.                 break;
  294.         }
  295.         if (isset($localisation) && !empty($localisation) && !$this->slugify->revealLieu($localisation))
  296.             throw $this->createNotFoundException("URL interdite [5]");
  297.         // // Détecter les URLs non valides genre /onglet/ain-01/bretagne
  298.         // //                                     /onglet/{typeOnglet}/{niveauOnglet}
  299.         // $typeOnglet0 = $this->slugify->revealLieu($typeOnglet);
  300.         // $niveauOnglet0 = $this->slugify->revealLieu($niveauOnglet);
  301.         // if ($niveauOnglet0 instanceof LieuInterface && $typeOnglet0 instanceof LieuInterface)
  302.         //     return $this->redirectToRoute('', [], 301);
  303.         // Récupérer la queryString sous forme de texte afin de la passer aux localisation de la vue
  304.         $pathInfo $request->getPathInfo(); // Exp.:  "/enseignement--catholique/alsace"
  305.         $requestUri $request->getRequestUri(); // Exp.:  "/enseignement--catholique/alsace?statut%5B%5D=catholique";
  306.         $getQueryString str_replace($pathInfo""$requestUri);
  307.         // Pour les listes géo il faut supprimer le n° de page (si jamais on a pagination), sinon si par exp
  308.         // je suis en région page 10 et je sélectionne un dpt ça va faire 301 vers la racine
  309.         $uri $request->getRequestUri();// Get the current request URI
  310.         $queryString parse_url($uriPHP_URL_QUERY);// Parse the URI to extract the query parameters
  311.         if ($queryString
  312.         {
  313.             parse_str($queryString$params); // Parse the query string into an array
  314.             unset($params['page']); // Remove the parameter you want to delete
  315.             $newQueryString http_build_query($params); // Rebuild the query string
  316.             // Rebuild the URI with the new query string
  317.             $getQueryStringSafe strtok($uri'?') . '?' $newQueryString;
  318.             $getQueryStringSafe str_replace($pathInfo""$getQueryStringSafe);
  319.         } else {
  320.             $getQueryStringSafe $getQueryString;
  321.         }
  322.         $currentRoute $request->attributes->get('_route');
  323.         if ($currentRoute == "annuaire_liste_par_onglet_sup" || $currentRoute == "annuaire_liste_par_onglet_sup_localisation") {
  324.             $typeOnglet "superieur";   
  325.         }
  326.         if (
  327.             $currentRoute == "annuaire_liste_par_onglet" || 
  328.             $currentRoute == "annuaire_liste_par_onglet_localisation"
  329.         ) {
  330.             $goodTypeOnglet = ['ecole''college''lycee''professionnel''internat''formations-a-distance''autre'];
  331.             if (!in_array($typeOnglet$goodTypeOnglet)) {
  332.                 /* Note de keywo : on prends une catégorie au hasard et on redirige vers celle-ci (la + stratégique). Les laisser en 404 n’est pas idéal, Google continuera de les crawler. Soit on les redirige, soit on les mets en 410 pour que Google arrêtent de les crawler. Les redirections sont recommandées dans ce cas-là.
  333.                  */
  334.                 return $this->redirectToRoute('annuaire_liste_par_onglet', ['niveauOnglet' => 'tout''typeOnglet' => 'lycee'], 301);
  335.                 // throw $this->createNotFoundException("Cette page n'exite pas !");
  336.             }
  337.         }        
  338.         // Détecter les diplomes supérieur qui n'existent plus
  339.         // ATT : il faut chercher dans ItemsInsertion et non pas Items, car on peut le trouver dans ce dernier mais ça veut pas dire
  340.         // qu'on a des étabs qui proposent ce diplome
  341.         // RAPPEL : un diplime est un item de de niveau 4, une filière est aussi un item, mais de niv 3
  342.         if (
  343.             $sousTypeOnglet == "diplome" && (
  344.                 $currentRoute == "annuaire_liste_par_onglet_sup_localisation" ||
  345.                 $currentRoute == "annuaire_liste_par_onglet_sup" 
  346.             )
  347.         ) {
  348.             $diplome $niveauOnglet;
  349.             $itemDiplome $this->doctrine->getRepository(ItemsInsertion::class)->findOneBy(['identifiant'=>$diplome'niveau'=>4]);
  350.             if ($itemDiplome == null)
  351.                 return $this->redirectToRoute("annuaire_liste_par_onglet_sup", [], 301);
  352.         }          
  353.         $currentURL $request->getPathInfo();
  354.         // Le "---", comme le "tout", permet d'achapper à une recherche par mot clé, voir Moteur::filtreTexte()
  355.         if ($quoi == null) {
  356.             $quoi $typeOnglet '---' ?? $niveauOnglet '---' ?? 'tout';
  357.         }
  358.         if ($currentRoute != "annuaire_liste" && $currentRoute != "annuaire_catho" && $currentRoute != "annuaire_prive") {
  359.             // $quoi = ''; // Faut rien mettre ici
  360.             $parametres->disableQuoi true;
  361.             $lieu 'default'// Valeur par défaut, ATT doit exister dans aep.region
  362.             // Vérifier si on a choisi un lieu
  363.             $lieuTemp $this->slugify->revealLieu($localisation ?? $sousTypeOnglet ?? $niveauOnglet);
  364.             if ($lieuTemp) {
  365.                 $className get_class($lieuTemp);
  366.                 if (in_array($className, ['Region''Departement''Ville']));
  367.                 $lieu $localisation ?? $sousTypeOnglet ?? $niveauOnglet;
  368.             }
  369.         }
  370.         //
  371.         // Retrocompatibilité avec le slug lieu à l'ancienne
  372.         //
  373.         $rawLieu $lieu;
  374.         $lieu $this->slugify->revealLieu($lieu);
  375.         $quoi $this->slugify->revealQuoi($quoi);
  376.         //
  377.         // Rédirige vers la page d'accueil du $quoi si le lieu n'exixte pas
  378.         //
  379.         if (!$lieu) {
  380.             return $this->redirectToRoute(
  381.                 'annuaire_quoi',
  382.                 ['quoi' => $quoi->getSlug()],
  383.                 Response::HTTP_MOVED_PERMANENTLY
  384.             );
  385.         }
  386.         //
  387.         // Rédirige ancienne région vers sa nouvelle région
  388.         //
  389.         if ($lieu instanceof AncienneRegion) {
  390.             $region $lieu->getRegion();
  391.             $url $this->pathBuilder->buildAnnuaireListe($quoi$region);
  392.             return $this->redirect($url);
  393.         }
  394.         //
  395.         // Cherche des établissements
  396.         //
  397.         $isCrawler $this->crawlerDetect->isCrawler();
  398.         if ($currentRoute == "annuaire_liste") {
  399.             //
  400.             // Liste de résultat suite à une recherche par le moteur quoi/où
  401.             //
  402.             $parametres->setQuoiLieu($quoi$lieu);
  403.         } else {
  404.             //
  405.             // Liste de résultat depuis les onglets (menu principal)
  406.             // Si une localisation a déjà été définie il faut la garder comme valeur par défaut
  407.             //
  408.             if (!$lieu && $lieu->getSlug() != "default" || ($niveauOnglet == "tout" && $sousTypeOnglet == null)) {
  409.                 // Liste de toutes les régions, car le param lieu est obligatoire !
  410.                 $regions $this->getDoctrine()->getManager()->getRepository(Region::class)->findAll();
  411.                 $parametres->setQuoiLieu($quoi$lieu$regions); // Toutes les régions
  412.             } else {
  413.                 $parametres->setQuoiLieu($quoi$lieu);
  414.             }
  415.             //
  416.             // Appliquer les filtres
  417.             //
  418.             // avec les écoles on avait $niveauOnglet comme slug (maternelle/eleménatire), mais à un certain moment
  419.             // le form est passé en GET pur, mais récupérer cette var n'a pas été adapté
  420.             @$niveau $request->query->get('niveau');
  421.             $lesFiltres = [
  422.                 'typeOnglet' => $typeOnglet,
  423.                 'niveauOnglet' => isset($niveau) & !empty($niveau) ? $niveau[0] : $niveauOnglet,
  424.                 'sousTypeOnglet' => $sousTypeOnglet,
  425.                 'quoi' => $quoi,
  426.                 'lieu' => $lieu,
  427.             ];
  428.             // dump("typeOnglet: $typeOnglet / niveauOnglet: $niveauOnglet / sousTypeOnglet: $sousTypeOnglet");
  429.             // if ($lieu->getSlug() == "default")
  430.             //     throw $this->createNotFoundException("Cette page n'exite pas !");
  431.             $parametres $this->filtrer($parametres$request$lesFiltres$this->slugify);
  432.         }
  433.         $parametres->pageActuele $request->query->getInt('page'1);
  434.         $parametres->maxParPage $isCrawler self::MAX self::MAX;
  435.         $etablissements $this->moteur->cherche($parametres); 
  436.         $lastPage = (int) (ceil($etablissements->getTotalItemCount() / $etablissements->getItemNumberPerPage()));
  437.         if($lastPage && $parametres->pageActuele $lastPage){
  438.             if($currentRoute == 'annuaire_catho' or $currentRoute == 'annuaire_prive'){
  439.                 return $this->redirectToRoute(
  440.                     $currentRoute,
  441.                     ['lieu' => $lieu
  442.                     ]);
  443.             }
  444.             if($currentRoute == 'annuaire_liste'){
  445.                 return $this->redirectToRoute(
  446.                     $currentRoute,
  447.                     [
  448.                         'quoi' => $quoi,
  449.                         'lieu' => $lieu,
  450.                     ]);
  451.             }
  452.             if($currentRoute == 'annuaire_liste_par_onglet_sup'){
  453.                 return $this->redirectToRoute(
  454.                     $currentRoute,
  455.                     [   'sousTypeOnglet' => $sousTypeOnglet,
  456.                         'niveauOnglet' => $niveauOnglet,
  457.                     ]);
  458.             }
  459.             if($currentRoute == 'annuaire_liste_par_onglet_sup_localisation'){
  460.                 return $this->redirectToRoute(
  461.                     $currentRoute,
  462.                     [   'sousTypeOnglet' => $sousTypeOnglet,
  463.                         'niveauOnglet' => $niveauOnglet,
  464.                         'localisation' => $localisation,
  465.                     ]);
  466.             }
  467.             if($currentRoute == 'annuaire_liste_par_onglet'){
  468.                 return $this->redirectToRoute(
  469.                     $currentRoute,
  470.                     ['typeOnglet' => $typeOnglet,
  471.                         'niveauOnglet' => $niveauOnglet,
  472.                     ]);
  473.             }
  474.             if($currentRoute == 'annuaire_liste_par_onglet_localisation'){
  475.                 return $this->redirectToRoute(
  476.                     $currentRoute,
  477.                     ['typeOnglet' => $typeOnglet,
  478.                         'niveauOnglet' => $niveauOnglet,
  479.                         'localisation' => $localisation,
  480.                     ]);
  481.             }
  482.         }
  483.         //
  484.         // Contexte de recherche pour permettre naviger entre les fiches
  485.         //
  486.         $contextRecherche $this->moteur->createContext($parametres);
  487.         $this->userTransient->set(UserTransient::CONTEXTE_RECHERCHE$contextRecherche);
  488.         $repositoryRegion $this->getDoctrine()->getRepository(Region::class);
  489.         $repositoryDepartement $this->getDoctrine()->getRepository(Departement::class);
  490.         $repositoryVille $this->getDoctrine()->getRepository(Ville::class);
  491.         $regions $repositoryRegion->findAllVisibles($typeOnglet);
  492.         $departements $repositoryDepartement->findRelatifsAuLieu($lieu$typeOnglet);
  493.         
  494.         // Garder les villes avaec au moins un établissement
  495.         // Si on est dans une ville on doit modifier les paramètres afin que le lieu soit le département
  496.         $parametresVille = clone $parametres;
  497.         if ($lieu instanceof Ville) {
  498.             $laVille $lieu->getDepartement();
  499.             $parametresVille->setLieu($laVille);
  500.         }
  501.         $idsVilleContexte $this->moteur->getIdsVille($parametresVille); // Id unique des villes du contexte de recherche établissements actuel
  502.         $villes = ($lieu instanceof Departement || $lieu instanceof Ville) ? $repositoryVille->findRelatifsAuLieu($lieu$typeOnglet$idsVilleContexte) : null;
  503.         
  504.         $idsVilleContexte = \array_slice($idsVilleContexte0100);
  505.         $villesContexte $idsVilleContexte
  506.         $repositoryVille->findBy(['id' => $idsVilleContexte], ['libelle' => 'ASC'])
  507.         : [];
  508.         // $this->historique->addRecherche($quoi, $lieu, 'annuaire_liste');
  509.         $this->historique->addRecherche($quoi$lieu$currentRoute$requestUri);
  510.         //
  511.         // Les filtres
  512.         //
  513.         $niveaux $this->getDoctrine()->getRepository(Items::class)->getNiveaux($typeOnglet);
  514.         $idsFiltresContexte $this->moteur->getIdsFiltres($parametresVille);
  515.         $filieres $this->getDoctrine()->getRepository(Items::class)->getFilieresFiltred($this->ongletSlug2Id($typeOnglet$niveauOnglet), $idsFiltresContexte); 
  516.         $diplomes $request->query->get('filiere') ? 
  517.             $this->getDoctrine()->getRepository(Items::class)->getDiplomes($this->ongletSlug2Id($typeOnglet$niveauOnglet), $request->query->get('filiere'), $idsFiltresContexte) :
  518.             null;
  519.         //
  520.         // Les langues
  521.         //
  522.         $idsLvaContexte $this->moteur->getIdsLVx($parametresVille'lva');
  523.         $lva $this->getDoctrine()->getRepository(Items::class)->getLVx('LV1'$typeOnglet$idsLvaContexte);
  524.         $idsLvbContexte $this->moteur->getIdsLVx($parametresVille'lvb');
  525.         $lvb $this->getDoctrine()->getRepository(Items::class)->getLVx('LV2'$typeOnglet$idsLvbContexte);
  526.         //
  527.         // Enseignements de spécialités (pour les Lycées Généraux seulement)
  528.         //
  529.         $idsEdsContexte $this->moteur->getIdsEenseignementsDeSpecialite($parametresVille'lva');
  530.         $enseignementsDeSpecialite $this->getDoctrine()->getRepository(Items::class)->getEnseignementsDeSpecialite($idsEdsContexte);
  531.         // Traitement pour "onglet/internat/{lieu}" : trouver les types d'internat avec établissements
  532.         // pour ne pas afficher les types d'internat vides (ecole, college, lycee, pro, superieur)
  533.         $idsTypesInternat $this->moteur->getIdsTypesInternat($parametresVille);
  534.         
  535.         // Ne pas afficher les filtres et diplomes dans certains cas :
  536.         //  - onglet/superieur/niveau (tout)
  537.         //  - onglet/lucee (tout)
  538.         if (
  539.             ($typeOnglet == "superieur" && $niveauOnglet == "tout"
  540.             or ($typeOnglet == "superieur" && $sousTypeOnglet != "niveau"
  541.             or ($typeOnglet == "professionnel" && !in_array($niveauOnglet, ['cap''bac-pro''formation-pro-continue'])) 
  542.             // or ($typeOnglet == "lycee" && !in_array($niveauOnglet, ['technologique', 'general']))
  543.         ) {
  544.             $filieres $diplomes null;
  545.         }
  546.         if ($typeOnglet == "lycee" && $niveauOnglet != "technologique")
  547.             $filieres null;
  548.         if ($typeOnglet == "lycee" && $niveauOnglet == "general")
  549.             $filieres $diplomes null;
  550.             
  551.         // QueryString : tous les paramètres (les inputs du filtre)
  552.         $qs $request->query->all();
  553.         // Récupérer les anciens filtres
  554.         $queryString = \serialize($qs);
  555.         // Construire l'url sans localisation si on y est dedans
  556.         // Quand on choisi une localisation on ajoute la zone à la fin de l'url
  557.         // on l'enlève pour qu'elle puisse être utlisée par les autres lites (on en a 3 : région, dpt, ville)
  558.         // ceci fixe le pb de localisation du supérieur
  559.         if ($lieu && $lieu->getSlug() != "default" && !$localisation) {
  560.             $localisation $lieu->getSlug();
  561.         }
  562.         if ($localisation) {
  563.             $lieuTemp $this->slugify->revealLieu($localisation);
  564.         } elseif ($niveauOnglet) {
  565.             $lieuTemp $this->slugify->revealLieu($niveauOnglet);
  566.         } else {
  567.             $urls explode("/"$currentURL);
  568.             $localisationTemp end($urls);
  569.             $lieuTemp $this->slugify->revealLieu($localisationTemp ?? 'foobar');
  570.         }
  571.         if (
  572.             $lieuTemp != null &&
  573.             ($lieuTemp instanceof Region || $lieuTemp instanceof Departement || $lieuTemp instanceof Ville)
  574.         ) {
  575.             // Le dernier parmetre de l'url est bien une localisation, on la supprime pour retrouver l'url de l'onglet
  576.             $currentURL explode("/"$currentURL);
  577.             array_pop($currentURL);
  578.             $currentURL implode("/"$currentURL);
  579.         }
  580.         $diplomeLibelle = [];
  581.         if (in_array($typeOnglet, ['lycee''professionnel''superieur']))
  582.             $diplomeLibelle $this->getDoctrine()->getRepository(ItemsInsertion::class)->getDiplomeLibelle($niveauOnglet);
  583.         $region null;
  584.         $departement null;
  585.         $ville null;
  586.         $recherche_type null;
  587.         if ($lieu instanceof Ville) {
  588.             $recherche_type "niveau_ville";
  589.             $ville $lieu;
  590.             $departement $lieu->getDepartement();
  591.             $region $departement $departement->getRegion() : null;
  592.         } elseif ($lieu instanceof Departement) {
  593.             $recherche_type "niveau_departement";
  594.             $departement $lieu;
  595.             $region $lieu->getRegion();
  596.         } elseif ($lieu instanceof Region) {
  597.             $recherche_type "niveau_region";
  598.             $region $lieu;
  599.             if ($region && $region->getLibelle() == "DEFAULT") {
  600.                 $region null;
  601.                 $recherche_type null;
  602.             }
  603.         }
  604.         // SEO : ne pas indexer une page résultat vide
  605.         // $noindex = count($etablissements) == 0 ? true : false;
  606.         // maj : si 0 étabs => si page NON géolocalisée : on indexe, SINON on n'indexe pas
  607.         $noindex false;
  608.         if (count($etablissements) == 0) {
  609.             if ($lieu->getSlug() != "default") {
  610.                 // $noindex = true;
  611.                 $currentRoute $request->attributes->get('_route');
  612.                 switch ($currentRoute) {
  613.                     case 'annuaire_liste_par_onglet_sup':
  614.                     case 'annuaire_liste_par_onglet_sup_localisation':
  615.                         return $this->redirectToRoute('annuaire_liste_par_onglet_sup', [
  616.                                     "niveauOnglet" => "tout"//$niveauOnglet, // TODO : si c'est une ville ou dpt, rediriger vers la région
  617.                                     "sousTypeOnglet" => null,
  618.                                 ], 301);
  619.                         break;
  620.                     case 'annuaire_liste_par_onglet':
  621.                     case 'annuaire_liste_par_onglet_localisation':
  622.                         return $this->redirectToRoute('annuaire_liste_par_onglet', [
  623.                                     "typeOnglet" => $typeOnglet,
  624.                                     "niveauOnglet" => "tout"//$niveauOnglet, // TODO : si c'est une ville ou dpt, rediriger vers la région
  625.                                 ], 301);
  626.                         break;
  627.                     default:
  628.                         return $this->redirectToRoute('homepage', [], 301);
  629.                 }
  630.             }
  631.         } 
  632.         
  633.         // Recherche du bon texte de référencement
  634.         $formation self::ongletSlug2Id($typeOnglet$niveauOnglet);
  635.         // Vérifier si on est dans une liste par filière/secteur
  636.         $filiere $request->query->get('filiere'); // Ceci est un tableau
  637.         if ($filiere) {
  638.             // Protection des URLs
  639.             if (!is_array($filiere))
  640.                 throw new NotFoundHttpException("Cette page n'existe pas ??");
  641.             $filiere $filiere[0];
  642.         }
  643.         // On prend toujours le 1er !
  644.         // Vérifier si on est dans une liste par diplome
  645.         $diplome $request->query->get('diplome');
  646.         if ($diplome) {
  647.             // Protection des URLs
  648.             if (!is_array($diplome))
  649.                 throw new NotFoundHttpException("Cette page n'existe pas ???");
  650.             $diplome $diplome[0];
  651.             // Gérer le cas de ?diplome[]=bac-stav-sciences-et-technologies-de-l-agronomie-et-du-vivant--lyc-bactec-agri-bacstavvi 
  652.             if (strpos($diplome'--') !== false) {
  653.                 $temp = \explode("--"$diplome);
  654.                 $diplome strtoupper($temp[1]);
  655.                 return $this->redirectToRoute(
  656.                     'annuaire_liste_par_onglet'
  657.                     ['niveauOnglet' => $niveauOnglet'typeOnglet' => $typeOnglet'diplome[]' => $diplome],
  658.                     301
  659.                 );
  660.             }
  661.         } else {
  662.             // Gérer le cas où on tombe sur la page diplome depui un lien direct (et non pas des filtres)
  663.             if ($niveauOnglet && strpos($niveauOnglet'--') !== false) {
  664.                 $temp = \explode("--"$niveauOnglet);
  665.                 $diplome $temp[1];
  666.                 $formation $typeOnglet;
  667.                 return $this->redirectToRoute(
  668.                     'annuaire_liste_par_onglet'
  669.                     ['niveauOnglet' => $niveauOnglet'typeOnglet' => $typeOnglet'diplome[]' => $diplome],
  670.                     301
  671.                 );
  672.             }
  673.         }
  674.         // Vérifier que le dipôme existe bien
  675.         if ($diplome) {
  676.             $itemDiplome $this->getDoctrine()->getRepository(Items::class)->findOneById($diplome);
  677.             if (!$itemDiplome)
  678.                 return $this->redirectToRoute(
  679.                     'annuaire_liste_par_onglet'
  680.                     ['niveauOnglet' => $niveauOnglet'typeOnglet' => $typeOnglet],
  681.                     301
  682.                 );    
  683.         }
  684.         // Vérifier que la filiere existe bien
  685.         if ($filiere) {
  686.             $itemFiliere $this->getDoctrine()->getRepository(Items::class)->findOneById($filiere);
  687.             if (!$itemFiliere)
  688.                 return $this->redirectToRoute(
  689.                     'annuaire_liste_par_onglet'
  690.                     ['niveauOnglet' => $niveauOnglet'typeOnglet' => $typeOnglet],
  691.                     301
  692.                 );    
  693.         }        
  694.         // Pouvoir définir un slug pour lui affecter un text SeoTexteReferencementDiplome
  695.         if (
  696.             $formation === null || trim($formation) == "" ||
  697.             /* Un internat avec un niveau donné et qui ne soit pas un lieu : ecole|college|lycee|superieur */
  698.             ($typeOnglet == "internat" && $niveauOnglet != "tout" && $this->slugify->revealLieu($niveauOnglet) === null)
  699.         ) {
  700.             $formation $typeOnglet "-" $niveauOnglet;
  701.         }
  702.         // On fait un cas particulier pour lycee-general, on laisse les autres cas (LYC et LYC-BACTEC) car déjà utilisés dans la table Seo
  703.         if ($typeOnglet == "lycee" && $niveauOnglet != null && $niveauOnglet == "general") {
  704.             $formation "LYC-GEN";
  705.         }
  706.         list($seoTitre$seoTexte) = $this->getDoctrine()->getRepository(SeoTexteReferencementDiplome::class)->getTitreEtTexte($formation$filiere$diplome$lieu);
  707.         
  708.         if ($typeOnglet == "internat" && $lieu instanceof Region or $lieu instanceof Departement) {
  709.             $zone1 = ['Alsace''Champagne-Ardenne''Lorraine''Nord-Pas-de-Calais'];
  710.             $zone2 = ['Aquitaine''Limousin''Midi-Pyrénées''Poitou-Charentes'];
  711.             $zone3 = ['Bretagne''Normandie''Pays-de-Loire'];
  712.             $zone4 = ['Languedoc-Roussillon''Provence-Alpes-Côte-d\'Azur''Rhône-Alpes'];
  713.             $zone5 = ['Auvergne''Bourgogne''Centre''Franche-Comté'];
  714.             $zone6 = ['Ile-de-France'];
  715.             if ($lieu instanceof Region) {
  716.                 $regionInternat $lieu->getLibelle();
  717.             } else {
  718.                 $regionInternat $lieu->getRegion()->getLibelle();
  719.             }
  720.             $zone '';
  721.             if (\in_array($regionInternat$zone1)) {
  722.                 $zone 'Z1';
  723.             } elseif (\in_array($regionInternat$zone2)) {
  724.                 $zone 'Z2';
  725.             } elseif (\in_array($regionInternat$zone3)) {
  726.                 $zone 'Z3';
  727.             } elseif (\in_array($regionInternat$zone4)) {
  728.                 $zone 'Z4';
  729.             } elseif (\in_array($regionInternat$zone5)) {
  730.                 $zone 'Z5';
  731.             } elseif (\in_array($regionInternat$zone6)) {
  732.                 $zone 'Z6';
  733.             }
  734.             $internats $this->getDoctrine()->getRepository(ZonesInternat::class)->findByZone($zone);
  735.         }
  736.         // Récupère tous les diplômes des établissements
  737.         $itemsInsertions null;
  738.         if (in_array($typeOnglet, ['lycee''professionnel''superieur']))
  739.             $itemsInsertions $this->getDoctrine()->getRepository(ItemsInsertion::class)->getDiplomePlusByEtablissements($etablissements);
  740.         $contextSlug $this->get('router')->generate($request->attributes->get('_route'));
  741.         //Page
  742.         if ($request->query->getInt('page')) {
  743.             $contextSlug $this->get('router')->generate($request->attributes->get('_route'), ['page' => $request->query->get('page')]);
  744.         }
  745.         // $count = count($etablissements);
  746.         $count $this->moteur->count($parametres); 
  747.         // << IdKY mais ça retourne un faux nbr quand il n'y a aucun résultat
  748.         // ça renvoi _shards.total au lieu de hits.total (si le 2ème = 0  le 1er ne l'est pas !!! )
  749.         if(count($etablissements) == 0
  750.             $count 0;
  751.         // Découper le texte SEO en deux via le séparateur <hr /> à insérer depuis l'admin
  752.         $seoTextePart1 $seoTextePart2 $metadesc $seoParagId null;
  753.         $countSeo $count;
  754.         if ($seoTexte) {
  755.             $seoParagId $this->extractParagId($seoTexte);
  756.             if ($countSeo <=)
  757.                 $countSeo "";
  758.             $seoTexte str_replace('[nbr-etabs]'$countSeo$seoTexte); 
  759.             $seoTexte str_replace(['[region]''[dept]''[ville]'], $lieu->getLibelle(), $seoTexte); 
  760.             // Remove <div> and </div> tags, Aurlie adds them sametimes, idk why/how !!
  761.             $seoTexte preg_replace("/<\/?div[^>]*>/"""$seoTexte);
  762.             $parts preg_split("/<hr\s*\/?>/"$seoTexte); // gère <hr /> ou <hr/>
  763.             $seoTextePart1 $parts[0];
  764.             $seoTextePart2 $parts[1] ?? null ;
  765.             // Pour le metadesc
  766.             $metadesc $seoTextePart1;
  767.             $metadesc html_entity_decode($metadescENT_QUOTES);
  768.             $metadesc strip_tags($metadesc);
  769.             $metadesc trim(preg_replace('/\s+/'' '$metadesc));    // remove \r\n
  770.         }
  771.         //Context Create for navigation with next & prev
  772.         if($count 3000){
  773.             $context $this->engine->createContext($parametres);
  774.             $context->slug $contextSlug;
  775.             $this->userTransient->set(UserTransient::CONTEXTE_RECHERCHE$context);
  776.         }
  777.         // TODO : self::MAX requetes sql (INSERT) exécutées ici !! 
  778.         $this->traceur->add(Trace::ANNUAIRE_AFFICHAGE$etablissements);
  779.         // Redirect page 1 to root URL 
  780.         if(
  781.             $request->query->get('page') == '1' || 
  782.             $request->query->get('page') === '0' || 
  783.             (int) $request->query->get('page') < || 
  784.             (int) $request->query->get('page') > $etablissements->getPageCount()
  785.             ){
  786.                 return $this->redirectToRoute(
  787.                     'annuaire_liste_par_onglet'
  788.                     ['niveauOnglet' => $niveauOnglet'typeOnglet' => $typeOnglet],
  789.                     301
  790.                 ); 
  791.         }
  792.         // Pour vider le cache twig quand c nécessaire
  793.         $cacheId $typeOnglet "_" $niveauOnglet "_" $count "_" $this->moteur->genereGraine($parametres) . "_" $request->query->getInt('page');
  794.         // Pour seulement le bloc localisation, qui ne change pas tt les jours
  795.         $cacheIdLocalisation $lieu->getSlug();
  796.         // PoC : ne pas afficher les filieres sans étabs
  797.         // $filieresNew = null;
  798.         // foreach ($filieres as $filiere) {
  799.         //     $param = new Parametres();
  800.         //     $param->setQuoiLieu($filiere, $lieu);
  801.         //     $etabs = $this->moteur->count($param);
  802.         //     if ($etabs > 0)
  803.         //         $filieresNew[] = $filiere;
  804.         // }
  805.         // $filieres = $filieresNew;
  806.         // FAQ
  807.         $faqs $this->getDoctrine()->getRepository(Faq::class)->findBy([
  808.             'onglet' => $typeOnglet
  809.             'niveau' => $niveauOnglet != "tout" $niveauOnglet null
  810.             'filiere' => $request->query->get('filiere') ? $request->query->get('filiere')[0] : null
  811.             'diplome' => $request->query->get('diplome') ? $request->query->get('diplome')[0] : null
  812.             'visible' => true
  813.         ], ['ordre' => 'ASC''updatedAt' => 'DESC']);
  814.         // Pour dataLyer (plan de marquage)
  815.         if ($currentRoute == "annuaire_prive")
  816.             $listeType "annuaire_general";
  817.         else
  818.             $listeType "annuaire";
  819.         return $this->render('annuaire/liste.html.twig', [
  820.             'quoi' => $quoi,
  821.             'lieu' => $lieu,
  822.             
  823.             // Pour dataLayer
  824.             'region' => $region,
  825.             'departement' => $departement,
  826.             'ville' => $ville,
  827.             'recherche_type' => $recherche_type,
  828.             'regions' => $regions,
  829.             'departements' => $departements,
  830.             'villes' => $villes,
  831.             'villesContexte' => $villesContexte,
  832.             'parametres' => $parametres,
  833.             'etablissements' => $etablissements,
  834.             'isCrawler' => $isCrawler,
  835.             'niveaux' => $niveaux,
  836.             'filieres' => $filieres,
  837.             'diplomes' => $diplomes,
  838.             'itemsInsertions' => $itemsInsertions,
  839.             'lva' => $lva,  // Langues vivantes A/B
  840.             'lvb' => $lvb,  // Langues vivantes A/B
  841.             'diplomeLibelle' => $diplomeLibelle,
  842.             'enseignementsDeSpecialite' => $enseignementsDeSpecialite,
  843.             'typeOnglet' => $typeOnglet,
  844.             'sousTypeOnglet' => $sousTypeOnglet,
  845.             'niveauOnglet' => $niveauOnglet,
  846.             'queryString' => $queryString,
  847.             'getQueryString' => $getQueryString,
  848.             'getQueryStringSafe' => $getQueryStringSafe,
  849.             'currentURL' => $currentURL,
  850.             'noindex' => $noindex,
  851.             'seoTitre' => $seoTitre,
  852.             'seoTextePart1' => $seoTextePart1,
  853.             'seoTextePart2' => $seoTextePart2,
  854.             'metadesc' => $metadesc,
  855.             'seo_parag_id' => $seoParagId,
  856.             'formation' => $formation,
  857.             'count' => $count,
  858.             'internats' => $internats ?? null,
  859.             'pageOne' => $request->query->getInt('page') == Or $request->query->getInt('page') == true false,
  860.             'cache_id'       => $cacheId,
  861.             'cache_id_localisation'       => $cacheIdLocalisation,
  862.             'currentRoute' => $currentRoute,
  863.             'diplome' => $diplome,
  864.             'faqs' => $faqs,
  865.             'idsTypesInternat' => $idsTypesInternat// pour la liste des internats, afin de savoir quels items afficher dans l'aide au choix
  866.             'idsFiltresContexte' => $idsFiltresContexte,
  867.             'liste_type' => $listeType
  868.         ]);
  869.     }
  870.     /**
  871.      * @Route(
  872.      *     "/annuaire-voir-plus/{quoi}/{lieu}/{page}",
  873.      *     requirements={"page": "\d+"},
  874.      *     name="annuaire-liste-voir-plus",
  875.      *     methods={"GET"},
  876.      *     options = { "expose" = true }
  877.      * )
  878.      * @Cache(expires="+1 minute", public=false)
  879.      */
  880.     public function voirPlus(
  881.         Request $requeststring $quoistring $lieuint $page
  882.     ): Response {
  883.         $quoi $quoi == "*" "" $quoi;
  884.         $quoi $this->slugify->revealQuoi($quoi);
  885.         $lieu $this->slugify->revealLieu($lieu);
  886.         $typeOnglet $request->query->get('pTypeOnglet');
  887.         $sousTypeOnglet $request->query->get('pSousTypeOnglet');
  888.         $niveauOnglet $request->query->get('pNiveauOnglet');
  889.         $queryString $request->query->get('pQueryString');
  890.         //$qs = $serializer->deserialize($queryString, Request::class, 'json');
  891.         $qs = \unserialize($queryString);
  892.         $req = new Request();
  893.         $req->initialize($qs);
  894.         $parametres = new Parametres();
  895.         $parametres->pageActuele $page;
  896.         $parametres->maxParPage self::MAX;
  897.         if ($typeOnglet != "") { // Ce param existe toujours si on arrive depuis l'onglet !
  898.             // Appliquer les filtres
  899.             $lesFiltres = [
  900.                 'typeOnglet' => $typeOnglet,
  901.                 'niveauOnglet' => $niveauOnglet,
  902.                 'sousTypeOnglet' => $sousTypeOnglet,
  903.                 'quoi' => $quoi,
  904.                 'lieu' => $lieu,
  905.             ];
  906.             $parametres $this->filtrer($parametres$req$lesFiltres$this->slugify);
  907.             // $parametres->setQuoiLieu($quoi, $lieu);
  908.         } elseif (!empty($req)) {
  909.             // un résultat annuaire-catho/prive, on a besoin de $req (pour filtrer les catho)
  910.             $lesFiltres = [
  911.                 'typeOnglet' => "",
  912.                 'niveauOnglet' => "",
  913.                 'sousTypeOnglet' => "",
  914.                 'quoi' => $quoi,
  915.                 'lieu' => $lieu,
  916.             ];
  917.             $parametres $this->filtrer($parametres$req$lesFiltres$this->slugify);
  918.             $parametres->setQuoiLieu($quoi$lieu);
  919.         } else {
  920.             // Un résultat du quoi/où
  921.             $parametres->setQuoiLieu($quoi$lieu);
  922.         }
  923.         $etablissements $this->moteur->cherche($parametres);
  924.         $this->traceur->add(Trace::ANNUAIRE_AFFICHAGE$etablissements);
  925.         return $this->render('annuaire/liste-voir-plus.html.twig', [
  926.             'parametres' => $parametres,
  927.             'etablissements' => $etablissements,
  928.             'lieu' => $lieu,
  929.         ]);
  930.     }
  931.     /**
  932.      * @Route("/organismes-agrees", name="organismes-agrees", methods={"GET"})
  933.      */
  934.     public function organismesAgrees(): Response
  935.     {
  936.         $quoi $this->slugify->revealQuoi('selection-d-organismes-agrees');
  937.         // Cherche des établissements
  938.         $parametres = new Parametres();
  939.         $parametres->setQuoi($quoi);
  940.         $parametres->pageActuele 1;
  941.         $parametres->maxParPage 100;
  942.         $parametres->payantsSeulement true;
  943.         $etablissements $this->moteur->cherche($parametres);
  944.         // Récupere les actualités
  945.         /** @var ActualiteRepository $repositoryActualite */
  946.         $repositoryActualite $this->getDoctrine()->getRepository(Actualite::class);
  947.         $actualites $repositoryActualite->findByQuoiLieu($quoinullself::MAX_ACTUALITE);
  948.         return $this->render('annuaire/organismes-agrees.html.twig', [
  949.             'quoi' => $quoi,
  950.             'etablissements' => $etablissements,
  951.             'actualites' => $actualites,
  952.             'parametres' => $parametres,
  953.         ]);
  954.     }
  955.     // Renvoi le code en partant du slug (de l'url)
  956.     public static function ongletSlug2Id($typeOnglet$niveauOnglet)
  957.     {
  958.         switch ($typeOnglet) {
  959.             // Pour le SEO Onglet & Dipmome - Utilisé par SeoTexteReferencementDiplome::getTitreEtTexte pour retrouver
  960.             // le texte SEO de la liste (national/regional/departemental)
  961.             // Utilisé aussi pour trouver la liste des filières et des diplômes
  962.             case 'ecole':
  963.                 $res = [
  964.                     'maternelle' => 'ecole-maternelle-',
  965.                     'elementaire' => 'ecole-elementaire-',
  966.                     'tout' => 'ecole-',
  967.                 ];
  968.                 break;
  969.             case 'college':
  970.             case 'internat':
  971.             case 'annuaire-enseignement-catholique':
  972.             case 'annuaire-enseignement-prive':
  973.             case 'formations-a-distance':
  974.                 return $typeOnglet "-";
  975.                 break;
  976.             case 'lycee':
  977.                 $res = [
  978.                     'technologique' => 'LYC-BACTEC-',
  979.                     'general' => 'LYC-',
  980.                     'tout' => 'LYC-',
  981.                 ];
  982.                 break;
  983.             case 'professionnel':
  984.                 $res = [
  985.                     'cap' => 'LYCPRO-CAP-',
  986.                     'bac-pro' => 'LYCPRO-BACP-',
  987.                     'formation-pro-continue' => 'LYCPRO-FPC-',
  988.                     'tout' => 'LYCPRO-',
  989.                 ];
  990.                 break;
  991.             case 'superieur':
  992.                 $res = [
  993.                     'bac-2-bts' => 'PBAC-BAC2-',
  994.                     'bac-3-licence' => 'PBAC-BAC3-',
  995.                     'bac-4-bac-5-master' => 'PBAC-BAC45-',
  996.                     'ecoles-d-ingenieurs' => 'PBAC-ING-',
  997.                     'classes-preparatoires' => 'PBAC-PREPA-',
  998.                     'formation-professionnelle-continue' => 'PBAC-FPC-',
  999.                     'niveau' => 'PBAC-',
  1000.                 ];
  1001.                 break;
  1002.             default:
  1003.                 return '%';
  1004.         }
  1005.         return $res[$niveauOnglet] ?? $res['tout'] ?? null;
  1006.     }
  1007.     public static function filtrer(Parametres $parametresRequest $request, array $lesFiltres null$slugify null)
  1008.     {
  1009.         // Crée des variables à partir du tableau associatif
  1010.         extract($lesFiltres);
  1011.         $statut $request->query->get('statut'); // Ceci est un array
  1012.         if ($statut) {
  1013.             // Protection des URLs
  1014.             if (!is_array($statut))
  1015.                 throw new NotFoundHttpException("Cette page n'exite pas ?");
  1016.             if (\in_array('sous-contrat'$statut)) {
  1017.                 $parametres->sousContrat true;
  1018.             }
  1019.             if (\in_array('hors-contrat'$statut)) {
  1020.                 $parametres->sousContrat false;
  1021.             }
  1022.             if (\in_array('catholique'$statut)) {
  1023.                 $parametres->catholique true;
  1024.             }
  1025.             if (\in_array('laique'$statut)) {
  1026.                 $parametres->catholique false;
  1027.             }
  1028.         }
  1029.         $autre $request->query->get('autre'); // Ceci est un array
  1030.         if ($autre) {
  1031.             $parametres->filtresShouldMust "should";
  1032.             $parametres->addFiltres($autre);
  1033.         }
  1034.         $alternance $request->query->get('alternance'); // Ceci est un array
  1035.         if ($alternance) {
  1036.             // Protection des URLs
  1037.             if (!is_array($alternance))
  1038.                 throw new NotFoundHttpException("Cette page n'exite pas ?");
  1039.             if (\in_array('oui'$alternance)) {
  1040.                 $parametres->alternance true;
  1041.             }
  1042.             if (\in_array('non'$alternance)) {
  1043.                 $parametres->alternance false;
  1044.             }
  1045.         }
  1046.         // ECOLES
  1047.         if ('ecole' == $typeOnglet) {
  1048.             // Gestion des filtres
  1049.             $ages $request->query->get('age');
  1050.             if (!empty($ages)) {
  1051.                 // Protection des URLs
  1052.                 if (!is_array($ages))
  1053.                     throw new NotFoundHttpException("Cette page n'exite pas ?");
  1054.             
  1055.                 if (count($ages) == 1) {
  1056.                     $parametres->ageAdmission = (int) $ages[0];
  1057.                 }
  1058.             }
  1059.             if ('maternelle' == $niveauOnglet || '01-MATER' == $niveauOnglet) {
  1060.                 $parametres->types = ['01-MATER''03-PRIM'];
  1061.             } elseif ('elementaire' == $niveauOnglet || '02-ELEM' == $niveauOnglet) {
  1062.                 $parametres->types = ['02-ELEM''03-PRIM'];
  1063.             } elseif ('tout' == $niveauOnglet) {
  1064.                 $parametres->types = ['02-ELEM''03-PRIM''01-MATER'];
  1065.             } else {
  1066.                 // $niveauOnglet est un lieu : Dpt, région ou ville
  1067.                 $lieu $slugify->revealLieu($niveauOnglet);
  1068.                 if ( $lieu == null )
  1069.                     throw new NotFoundHttpException("Cette page n'exite pas !");
  1070.                 $parametres->setQuoiLieu($quoi$lieu);
  1071.                 $parametres->types = ['02-ELEM''03-PRIM''01-MATER'];
  1072.             }
  1073.         }
  1074.         // COLLEGES
  1075.         elseif ('college' == $typeOnglet) {
  1076.             if ('tout' == $niveauOnglet) {
  1077.                 $parametres->types = ['04-COLL'];
  1078.             } else {
  1079.                 $lieu $slugify->revealLieu($niveauOnglet);
  1080.                 $parametres->setQuoiLieu($quoi$lieu);
  1081.                 $parametres->types = ['04-COLL'];
  1082.             }
  1083.         }
  1084.         // LYCEES
  1085.         elseif ('lycee' == $typeOnglet) {
  1086.             if ('technologique' == $niveauOnglet) {
  1087.                 $parametres->types = ['06-LTECH''07-LEGT'];
  1088.             } elseif ('general' == $niveauOnglet) {
  1089.                 $parametres->types = ['05-LGEN''07-LEGT'];
  1090.             } elseif ('tout' == $niveauOnglet) {
  1091.                 $parametres->types = ['05-LGEN''06-LTECH''07-LEGT'];
  1092.             } else {
  1093.                 // $niveauOnglet est un lieu : Dpt, région ou ville
  1094.                 $lieu $slugify->revealLieu($niveauOnglet);
  1095.                 $parametres->setQuoiLieu($quoi$lieu);
  1096.                 $parametres->types = ['05-LGEN''06-LTECH''07-LEGT'];
  1097.             }
  1098.         }
  1099.         // PRO
  1100.         elseif ('professionnel' == $typeOnglet) {
  1101.             $parametres->types = ['08-LAGRI''09-LPROF''10-LEAP'];
  1102.             if ('cap' == $niveauOnglet) {
  1103.                 //$parametres->filtres = array_merge( ['LYCPRO-CAP'], $parametres->filtres);
  1104.                 $parametres->addFiltres(['LYCPRO-CAP-']);
  1105.             } elseif ('bac-pro' == $niveauOnglet) {
  1106.                 $parametres->addFiltres(['LYCPRO-BACP-']);
  1107.             } elseif ('formation-pro-continue' == $niveauOnglet) {
  1108.                 $parametres->addFiltres(['LYCPRO-FPC-']);
  1109.             } elseif ('tout' == $niveauOnglet) {
  1110.                 $parametres->types = ['08-LAGRI''09-LPROF''10-LEAP'];
  1111.             } else {
  1112.                 // $niveauOnglet est un lieu : Dpt, région ou ville
  1113.                 $lieu $slugify->revealLieu($niveauOnglet);
  1114.                 $parametres->setQuoiLieu($quoi$lieu);
  1115.                 $parametres->types = ['08-LAGRI''09-LPROF''10-LEAP'];
  1116.             }
  1117.         }
  1118.         // SUPERIEUR
  1119.         elseif ('superieur' == $typeOnglet) {
  1120.             $parametres->types = ['12-SUP'];
  1121.             // Les Niveaux
  1122.             if ("niveau" == $sousTypeOnglet) {
  1123.                 if ('bac-2-bts' == $niveauOnglet) {
  1124.                     $parametres->addFiltres(['SOUS_TYPE-BTSA']);
  1125.                 } elseif ('classes-preparatoires' == $niveauOnglet) {
  1126.                     $parametres->addFiltres(['SOUS_TYPE-EPRE']);
  1127.                 } elseif ('ecoles-d-ingenieurs' == $niveauOnglet) {
  1128.                     $parametres->addFiltres(['SOUS_TYPE-EING']);
  1129.                 } elseif ('bac-3-licence' == $niveauOnglet) {
  1130.                     $parametres->addFiltres(['PBAC-BAC3-']);
  1131.                 } elseif ('bac-4-bac-5-master' == $niveauOnglet) {
  1132.                     $parametres->addFiltres(['PBAC-BAC45-']);
  1133.                 } elseif ('formation-professionnelle-continue' == $niveauOnglet) {
  1134.                     $parametres->addFiltres(['PBAC-FPC']);
  1135.                 } elseif (null == $niveauOnglet) {
  1136.                     $lieu $slugify->revealLieu('default');
  1137.                     $parametres->setQuoiLieu($quoi$lieu);
  1138.                     $parametres->filtres = ['SOUS_TYPE-BTSA''SOUS_TYPE-EPRE''SOUS_TYPE-EING''PBAC-BAC3-''PBAC-BAC45-''PBAC-FPC'];
  1139.                     // $parametres->addFiltres(['SOUS_TYPE-BTSA', 'SOUS_TYPE-EPRE','SOUS_TYPE-EING', 'PBAC-BAC3-', 'PBAC-BAC45-', 'PBAC-FPC']);
  1140.                 }
  1141.             }
  1142.             // Les filières
  1143.             if ("filiere" == $sousTypeOnglet) {
  1144.                 // Si on filtre par diplomes on n'aura pas de non-participants dans la liste !
  1145.                 // $parametres->filtres = ['PBAC-'];
  1146.                 if ('commerce' == $niveauOnglet) {
  1147.                     $parametres->formations = ['PBAC-BAC2-CDV''PBAC-BAC3-CDV''PBAC-BAC45-CDV''PBAC-FPC-DISTRI''PBAC-PREPA-COM'];
  1148.                 } elseif ('audiovisuel' == $niveauOnglet) {
  1149.                     $parametres->formations = ['PBAC-BAC2-ART''PBAC-BAC3-ART''PBAC-BAC45-ART''PBAC-FPC-ART''PBAC-PREPA-ART'];
  1150.                 } elseif ('sciences' == $niveauOnglet) {
  1151.                     $parametres->formations = ['PBAC-BAC2-ENS''PBAC-BAC3-ENS''PBAC-BAC45-ENS''PBAC-FPC-ENS''PBAC-PREPA-ENS'];
  1152.                 } elseif ('medecine' == $niveauOnglet) { // peut être mieux changer par "santé" et regrouper medecine, pharmacie, infirmier ...
  1153.                     $parametres->formations = ['PBAC-PREPA-SASO''PBAC-FPC-SANT''PBAC-BAC3-SASO'];
  1154.                 } elseif ('ingenieur' == $niveauOnglet) {
  1155.                     $parametres->formations = ['PBAC-ING'];
  1156.                     // $parametres->addFiltres(['PBAC-ING']);
  1157.                 }
  1158.             }
  1159.             if ("diplome" == $sousTypeOnglet) {
  1160.                 if ("tout" != $niveauOnglet)
  1161.                 // $parametres->formations = [$niveauOnglet]; // je ne sais plus pq on passe par 'formations' alors que pour les diplomes lycée/pro on passe par 'filtres' !! En tout cas ça retourne le meme résultat
  1162.                 {
  1163.                     $parametres->addFiltres([$niveauOnglet]);
  1164.                 }
  1165.             }
  1166.             if ("" == $sousTypeOnglet) {
  1167.                 $lieu $slugify->revealLieu('default');
  1168.                 $parametres->setQuoiLieu($quoi$lieu);
  1169.                 $parametres->types = ['12-SUP'];
  1170.             }
  1171.         }
  1172.         // INTERNANT
  1173.         elseif ('internat' == $typeOnglet) {
  1174.             /*
  1175.             Pour trouver les internats pour lycée, il faut lister tous les lycée et on aura l'id internat de chacun dans
  1176.             la colonne 'Etablissement.Internats_Identifiant'
  1177.              */
  1178.             if ("ecole" == $niveauOnglet) {
  1179.                 $parametres->typesInternat = ['01-MATER''02-ELEM''03-PRIM'];
  1180.             } elseif ("college" == $niveauOnglet) {
  1181.                 $parametres->typesInternat = ['04-COLL'];
  1182.             } elseif ("lycee" == $niveauOnglet) {
  1183.                 $parametres->typesInternat = ['05-LGEN''06-LTECH''07-LEGT'];
  1184.             } elseif ("pro" == $niveauOnglet) {
  1185.                 $parametres->typesInternat = ['08-LAGRI''09-LPROF''10-LEAP'];
  1186.             } elseif ("superieur" == $niveauOnglet) {
  1187.                 $parametres->typesInternat = ['12-SUP'];
  1188.             } elseif ("tout" == $niveauOnglet) {
  1189.                 $parametres->typesInternat = ['01-MATER''02-ELEM''03-PRIM''04-COLL''05-LGEN''06-LTECH''07-LEGT''08-LAGRI''09-LPROF''10-LEAP''12-SUP''00-DEFAULT'];
  1190.             } else {
  1191.                 $parametres->typesInternat = ['01-MATER''02-ELEM''03-PRIM''04-COLL''05-LGEN''06-LTECH''07-LEGT''08-LAGRI''09-LPROF''10-LEAP''12-SUP''00-DEFAULT'];
  1192.                 $parametres->typeRecherche 'internat-geo';
  1193.                 // $niveauOnglet est un lieu : Dpt, région ou ville
  1194.                 $lieu $slugify->revealLieu($niveauOnglet);
  1195.                 $parametres->setQuoiLieu($quoi$lieu);
  1196.                 // $parametres->typesInternat = ['01-MATER', '02-ELEM', '03-PRIM', '04-COLL', '05-LGEN', '06-LTECH', '07-LEGT', '08-LAGRI', '09-LPROF', '10-LEAP', '12-SUP'];
  1197.                 // $parametres->typesInternat = ['04-COLL', '12-SUP'];
  1198.             }
  1199.         }
  1200.         // RATTRAPAGE SCOLAIRE
  1201.         elseif ('rattrapage-scolaire' == $typeOnglet) {
  1202.             $parametres->types = ['15-ERSCOL'];
  1203.         }
  1204.         // FORMATIONS A DISTANCE
  1205.         elseif ('formations-a-distance' == $typeOnglet) {
  1206.             $parametres->types = ['13-EDIST'];
  1207.         }
  1208.         // AUTRE - section fourre-tout
  1209.         elseif ('autre' == $typeOnglet) {
  1210.             if ('tout' == $niveauOnglet) {
  1211.                 $parametres->types = ['14-ELANG''15-ERSCOL''16-ESPEC'];
  1212.             } else {
  1213.                 $lieu $slugify->revealLieu($niveauOnglet);
  1214.                 $parametres->setQuoiLieu($quoi$lieu);
  1215.                 $parametres->types = ['14-ELANG''15-ERSCOL''16-ESPEC'];
  1216.             }
  1217.         }
  1218.         // Filtre par Filières et/ou Diplômes
  1219.         // Vu que ces champs sont en fonction du menu on peut écraser les filtres précédent (relatifs à un menu de l'onglet)
  1220.         // $filiere = $request->query->get('filiere'); // Ceci est un array
  1221.         // if ($filiere){
  1222.         //     $parametres->formations = $filiere;
  1223.         // }
  1224.         $filieres $request->query->get('filiere'); // Ceci est un array
  1225.         if ($filieres) {
  1226.             // Protection des URLs
  1227.             if (!is_array($filieres))
  1228.                 throw new NotFoundHttpException("Cette page n'exite pas ?");
  1229.             $parametres->types = array(); // On n'en a plus besoin car $filieres sont déjà filtrés
  1230.             $parametres->filtresShouldMust "should";
  1231.             $parametres->filtres $filieres;
  1232.         }
  1233.         $diplomes $request->query->get('diplome'); // Ceci est un array
  1234.         if ($diplomes) {
  1235.             // Protection des URLs
  1236.             if (!is_array($diplomes))
  1237.                 throw new NotFoundHttpException("Cette page n'existe pas ?!?");
  1238.             $parametres->filtresShouldMust "should";
  1239.             $parametres->filtres $diplomes;
  1240.         }
  1241.         // Langues vivantes
  1242.         $lva $request->query->get('lva'); 
  1243.         $lvb $request->query->get('lvb'); 
  1244.         if ($lva) {
  1245.             // Protection des URLs
  1246.             if (!is_array($lva))
  1247.                 throw new NotFoundHttpException("Cette page n'existe pas ??!");
  1248.             $parametres->lva $lva;
  1249.             // $parametres->participantsSeulement = true;
  1250.         }
  1251.         if ($lvb) {
  1252.             // Protection des URLs
  1253.             if (!is_array($lvb))
  1254.                 throw new NotFoundHttpException("Cette page n'existe pas !??");
  1255.             $parametres->lvb $lvb;
  1256.             // $parametres->participantsSeulement = true;
  1257.         }
  1258.         // EdS : Enseignements de spécialité
  1259.         $eds $request->query->get('eds'); 
  1260.         if ($eds) {
  1261.             $parametres->eds $eds;
  1262.             // $parametres->participantsSeulement = true;
  1263.         }        
  1264.         // annuaire complet catho/prive
  1265.         // Quand on affiche une liste générique (tous les types mélangés), le quoi est à "tout", le où est fixé, les autres sont vides
  1266.         // du coup le code précédent n'entre dans aucune condition et on n'appelle jamais le setQuoiLieu !
  1267.         if ($quoi->getSlug() == "tout") {
  1268.             $parametres->setQuoiLieu($quoi$lieu);
  1269.         } elseif ($lieu != null) {
  1270.             $parametres->setLieu($lieu);
  1271.         }
  1272.         return $parametres;
  1273.     }
  1274.     /**
  1275.      * En entrée on a le texte SEO avec les données de début, la fonction fait le chemin inverse et récupère l'id de l'item SEO (un seul pour tt la categ, textes gérés ici : /backend/admin/seo-texte-referencement-diplome/ )
  1276.      */
  1277.     private function extractParagId($seoText) {
  1278.         $pattern '/<!-- p#(NAT|REG|DPT|VIL)#(\d+) -->/';
  1279.         // Rechercher les correspondances dans le texte
  1280.         if (preg_match($pattern$seoText$matches))
  1281.             return $matches[2];
  1282.         return null;
  1283.     }
  1284. }