src/Controller/HomeController.php line 27

  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Metier;
  4. use App\Entity\Secteur;
  5. use App\Entity\Etablissement;
  6. use App\Entity\DirectionRegionale;
  7. use App\Entity\Candidature;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  10. use Symfony\Component\HttpFoundation\Request;
  11. use Symfony\Component\HttpFoundation\Response;
  12. use Symfony\Component\HttpFoundation\JsonResponse;
  13. use Symfony\Component\Routing\Annotation\Route;
  14. class HomeController extends AbstractController
  15. {
  16.     public const ETABLISSEMENTS_ACTIFS_NOMS = [
  17.         'BANOUREBO''KOFFIBAM''EGLIN MOTOBE''EGLIN DABOU'
  18.         'EGLIN N\'DOUCI''MARABAM''BANACI''EGLIN AGBOVILLE'
  19.         'TIABAM''EGLIN AZAGUIE''PACOBO''BACIBAM''GRAND NIEKY'
  20.         'SPADI''FERME DE BEOUMI''ONO''BANDAMA''SCB GRAND FLEUVE'
  21.         'BANACOMOE''BBSA'
  22.     ];
  23.     private $entityManager;
  24.     public function __construct(EntityManagerInterface $entityManager)
  25.     {
  26.         $this->entityManager $entityManager;
  27.     }
  28.     #[Route('/'name'app_home')]
  29.     public function index(Request $request): Response
  30.     {
  31.         // Paramètres pour les métiers
  32.         $pageMetier $request->query->getInt('page-metier'1);
  33.         $limitMetier 6;
  34.         $rechercheMetier $request->query->get('recherche-metier''');
  35.         $secteurId $request->query->get('secteur-id''');
  36.         // Paramètres pour les Ã©tablissements
  37.         $pageEtablissement $request->query->getInt('page-etablissement'1);
  38.         $limitEtablissement 6;
  39.         $rechercheEtablissement $request->query->get('recherche-etablissement''');
  40.         $directionId $request->query->get('direction-id''');
  41.         // ========== REQUÊTE POUR LES MÉTIERS ==========
  42.         // [FILTRE ACTIF] Seuls les métiers rattachés Ã  l'établissement ETABLISSEMENT_ACTIF_ID sont affichés.
  43.         // Pour réafficher tous les métiers, supprimez le ->andWhere('e.id = :etablissementActifId') ci-dessous.
  44.         $metierQuery $this->entityManager->getRepository(Metier::class)
  45.             ->createQueryBuilder('m')
  46.             ->leftJoin('m.secteur''s')
  47.             ->leftJoin('m.etablissementMetiers''em')
  48.             ->leftJoin('em.etablissement''e')
  49.             ->addSelect('s''em''e')
  50.             ->andWhere('e.id IN (116) OR e.nom IN (:etablissementsActifs)')      // <-- FILTRE Ã‰TABLISSEMENT
  51.             ->setParameter('etablissementsActifs'self::ETABLISSEMENTS_ACTIFS_NOMS);
  52.         if (!empty($rechercheMetier)) {
  53.             $metierQuery->andWhere('m.nom LIKE :recherche')
  54.                 ->setParameter('recherche''%' $rechercheMetier '%');
  55.         }
  56.         if (!empty($secteurId)) {
  57.             $metierQuery->andWhere('s.id = :secteurId')
  58.                 ->setParameter('secteurId'$secteurId);
  59.         }
  60.         // Compter le total des métiers
  61.         $totalMetiers = (clone $metierQuery)
  62.             ->select('COUNT(DISTINCT m.id)')
  63.             ->getQuery()
  64.             ->getSingleScalarResult();
  65.         // Récupérer les métiers paginés
  66.         $metiers $metierQuery
  67.             ->select('m''s''em''e')
  68.             ->setFirstResult(($pageMetier 1) * $limitMetier)
  69.             ->setMaxResults($limitMetier)
  70.             ->orderBy('m.nom''ASC')
  71.             ->getQuery()
  72.             ->getResult();
  73.         // ========== REQUÊTE POUR LES Ã‰TABLISSEMENTS ==========
  74.         // [FILTRE ACTIF] Un seul Ã©tablissement est affiché sur la page d'accueil.
  75.         // Pour réafficher tous les Ã©tablissements, supprimez le ->andWhere('e.id = :etablissementActifId') ci-dessous
  76.         // et décommentez les blocs originaux (directionId, rechercheEtablissement, pagination).
  77.         // Restaurer la pagination et les filtres tout en gardant les Ã©tablissements actifs
  78.         $countQuery $this->entityManager->getRepository(Etablissement::class)
  79.             ->createQueryBuilder('e')
  80.             ->select('COUNT(DISTINCT e.id)')
  81.             ->where('e.id IN (116) OR e.nom IN (:etablissementsActifs)')
  82.             ->setParameter('etablissementsActifs'self::ETABLISSEMENTS_ACTIFS_NOMS);
  83.         if (!empty($directionId)) {
  84.             $countQuery->leftJoin('e.localite''l')->leftJoin('l.directionRegionale''d')
  85.                 ->andWhere('d.id = :directionId')->setParameter('directionId'$directionId);
  86.         }
  87.         if (!empty($rechercheEtablissement)) {
  88.             $countQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche''%' $rechercheEtablissement '%');
  89.         }
  90.         $totalEtablissements $countQuery->getQuery()->getSingleScalarResult();
  91.         $idQuery $this->entityManager->getRepository(Etablissement::class)
  92.             ->createQueryBuilder('e')
  93.             ->select('e.id')
  94.             ->addSelect('(CASE WHEN e.id = 116 THEN 0 ELSE 1 END) AS HIDDEN sort_priority')
  95.             ->where('e.id IN (116) OR e.nom IN (:etablissementsActifs)')
  96.             ->setParameter('etablissementsActifs'self::ETABLISSEMENTS_ACTIFS_NOMS)
  97.             ->orderBy('sort_priority''ASC')
  98.             ->addOrderBy('e.nom''ASC');
  99.         if (!empty($directionId)) {
  100.             $idQuery->leftJoin('e.localite''l')->leftJoin('l.directionRegionale''d')
  101.                 ->andWhere('d.id = :directionId')->setParameter('directionId'$directionId);
  102.         }
  103.         if (!empty($rechercheEtablissement)) {
  104.             $idQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche''%' $rechercheEtablissement '%');
  105.         }
  106.         $ids $idQuery->setFirstResult(($pageEtablissement 1) * $limitEtablissement)
  107.             ->setMaxResults($limitEtablissement)->getQuery()->getResult();
  108.         $etablissementIds array_column($ids'id');
  109.         // Récupérer les Ã©tablissements complets paginés
  110.         $etablissements = [];
  111.         if (!empty($etablissementIds)) {
  112.             $etablissements $this->entityManager->getRepository(Etablissement::class)
  113.                 ->createQueryBuilder('e')
  114.                 ->leftJoin('e.localite''l')
  115.                 ->leftJoin('l.directionRegionale''d')
  116.                 ->leftJoin('e.etablissementMetiers''em')
  117.                 ->leftJoin('em.metier''m')
  118.                 ->addSelect('l''d''em''m')
  119.                 ->where('e.id IN (:ids)')
  120.                 ->setParameter('ids'$etablissementIds)
  121.                 ->getQuery()
  122.                 ->getResult();
  123.             
  124.             // Re-trier selon l'ordre des IDs
  125.             usort($etablissements, function($a$b) use ($etablissementIds) {
  126.                 return array_search($a->getId(), $etablissementIds) - array_search($b->getId(), $etablissementIds);
  127.             });
  128.         }
  129.         // Données pour les filtres
  130.         $secteurs $this->entityManager->getRepository(Secteur::class)
  131.             ->findBy([], ['nom' => 'ASC']);
  132.         $directions $this->entityManager->getRepository(DirectionRegionale::class)
  133.             ->findBy([], ['nom' => 'ASC']);
  134.         // Statistiques globales
  135.         $stats = [
  136.             'metiers' => $this->entityManager->getRepository(Metier::class)->count([]),
  137.             'etablissements' => $this->entityManager->getRepository(Etablissement::class)->count([]),
  138.             'secteurs' => $this->entityManager->getRepository(Secteur::class)->count([]),
  139.             'places' => $this->getTotalPlaces(),
  140.             'candidatures' => $this->entityManager->getRepository(Candidature::class)->count([])
  141.         ];
  142.         $partenaires $this->getPartenaires();
  143.         return $this->render('index.html.twig', [
  144.             // Données pour les métiers
  145.             'metiers' => $metiers,
  146.             'secteurs' => $secteurs,
  147.             'totalMetiers' => $totalMetiers,
  148.             'limitMetier' => $limitMetier,
  149.             'pageMetierActuelle' => $pageMetier,
  150.             'rechercheMetier' => $rechercheMetier,
  151.             'secteurSelectionne' => $secteurId,
  152.             // Données pour les Ã©tablissements
  153.             'etablissements' => $etablissements,
  154.             'directions' => $directions,
  155.             'totalEtablissements' => $totalEtablissements,
  156.             'limitEtablissement' => $limitEtablissement,
  157.             'pageEtablissementActuelle' => $pageEtablissement,
  158.             'rechercheEtablissement' => $rechercheEtablissement,
  159.             'directionSelectionnee' => $directionId,
  160.             // Statistiques globales
  161.             'stats' => $stats,
  162.             'partenaires' => $partenaires,
  163.         ]);
  164.     }
  165.     private function getTotalPlaces(): int
  166.     {
  167.         $conn $this->entityManager->getConnection();
  168.         $sql 'SELECT SUM(nbrplace) as total FROM etablissement_metier';
  169.         $result $conn->executeQuery($sql)->fetchAssociative();
  170.         return (int) ($result['total'] ?? 0);
  171.     }
  172.     #[Route('/load-metiers'name'app_load_metiers'methods: ['GET'])]
  173.     public function loadMetiers(Request $request): JsonResponse
  174.     {
  175.         $page $request->query->getInt('page'1);
  176.         $limit $request->query->getInt('limit'6);
  177.         $recherche $request->query->get('recherche''');
  178.         $secteurId $request->query->get('secteur''');
  179.         // [FILTRE ACTIF] Seuls les métiers de l'établissement actif sont chargés via AJAX.
  180.         // Pour revenir Ã  tous les métiers, supprimez ->andWhere('e.id = :etablissementActifId').
  181.         $query $this->entityManager->getRepository(Metier::class)
  182.             ->createQueryBuilder('m')
  183.             ->leftJoin('m.secteur''s')
  184.             ->leftJoin('m.etablissementMetiers''em')
  185.             ->leftJoin('em.etablissement''e')
  186.             ->addSelect('s''em''e')
  187.             ->andWhere('e.id IN (116) OR e.nom IN (:etablissementsActifs)')      // <-- FILTRE Ã‰TABLISSEMENT
  188.             ->setParameter('etablissementsActifs'self::ETABLISSEMENTS_ACTIFS_NOMS);
  189.         if (!empty($recherche)) {
  190.             $query->andWhere('m.nom LIKE :recherche')
  191.                 ->setParameter('recherche''%' $recherche '%');
  192.         }
  193.         if (!empty($secteurId)) {
  194.             $query->andWhere('s.id = :secteurId')
  195.                 ->setParameter('secteurId'$secteurId);
  196.         }
  197.         // Compter le total
  198.         $total = (clone $query)
  199.             ->select('COUNT(DISTINCT m.id)')
  200.             ->getQuery()
  201.             ->getSingleScalarResult();
  202.         // Récupérer les IDs paginés (pas de join collection pour Ã©viter l'effet Cartésien)
  203.         $idQuery = clone $query;
  204.         $ids array_column(
  205.             $idQuery->select('m.id')
  206.                 ->setFirstResult(($page 1) * $limit)
  207.                 ->setMaxResults($limit)
  208.                 ->orderBy('m.nom''ASC')
  209.                 ->getQuery()
  210.                 ->getResult(),
  211.             'id'
  212.         );
  213.         // Charger les entités complètes uniquement pour ces IDs
  214.         $metiers = [];
  215.         if (!empty($ids)) {
  216.             $metiers $this->entityManager->getRepository(Metier::class)
  217.                 ->createQueryBuilder('m')
  218.                 ->leftJoin('m.secteur''s')
  219.                 ->leftJoin('m.etablissementMetiers''em')
  220.                 ->leftJoin('em.etablissement''e')
  221.                 ->addSelect('s''em''e')
  222.                 ->where('m.id IN (:ids)')
  223.                 ->setParameter('ids'$ids)
  224.                 ->orderBy('m.nom''ASC')
  225.                 ->getQuery()
  226.                 ->getResult();
  227.         }
  228.         return $this->json([
  229.             'html' => $this->renderView('partials/_metiers_cards.html.twig', [
  230.                 'metiers' => $metiers,
  231.             ]),
  232.             'total' => $total,
  233.             'page' => $page,
  234.             'limit' => $limit
  235.         ]);
  236.     }
  237.     #[Route('/load-etablissements'name'app_load_etablissements'methods: ['GET'])]
  238.     public function loadEtablissements(Request $request): JsonResponse
  239.     {
  240.         // [FILTRE ACTIF] Endpoint AJAX limité Ã  l'établissement actif.
  241.         // Pour revenir Ã  tous les Ã©tablissements, décommentez l'ancien code ci-dessous
  242.         // et supprimez le bloc "NOUVEAU".
  243.         $page $request->query->getInt('page'1);
  244.         $limit $request->query->getInt('limit'6);
  245.         $directionId $request->query->get('direction''');
  246.         $recherche $request->query->get('recherche''');
  247.         $countQuery $this->entityManager->getRepository(Etablissement::class)
  248.             ->createQueryBuilder('e')
  249.             ->select('COUNT(DISTINCT e.id)')
  250.             ->where('e.id IN (116) OR e.nom IN (:etablissementsActifs)')
  251.             ->setParameter('etablissementsActifs'self::ETABLISSEMENTS_ACTIFS_NOMS);
  252.         if (!empty($directionId)) {
  253.             $countQuery->leftJoin('e.localite''l')->leftJoin('l.directionRegionale''d')
  254.                 ->andWhere('d.id = :directionId')->setParameter('directionId'$directionId);
  255.         }
  256.         if (!empty($recherche)) {
  257.             $countQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche''%' $recherche '%');
  258.         }
  259.         $total $countQuery->getQuery()->getSingleScalarResult();
  260.         $idQuery $this->entityManager->getRepository(Etablissement::class)
  261.             ->createQueryBuilder('e')
  262.             ->select('e.id')
  263.             ->addSelect('(CASE WHEN e.id = 116 THEN 0 ELSE 1 END) AS HIDDEN sort_priority')
  264.             ->where('e.id IN (116) OR e.nom IN (:etablissementsActifs)')
  265.             ->setParameter('etablissementsActifs'self::ETABLISSEMENTS_ACTIFS_NOMS)
  266.             ->orderBy('sort_priority''ASC')
  267.             ->addOrderBy('e.nom''ASC');
  268.         if (!empty($directionId)) {
  269.             $idQuery->leftJoin('e.localite''l')->leftJoin('l.directionRegionale''d')
  270.                 ->andWhere('d.id = :directionId')->setParameter('directionId'$directionId);
  271.         }
  272.         if (!empty($recherche)) {
  273.             $idQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche''%' $recherche '%');
  274.         }
  275.         $ids $idQuery->setFirstResult(($page 1) * $limit)->setMaxResults($limit)->getQuery()->getResult();
  276.         $etablissementIds array_column($ids'id');
  277.         $etablissements = [];
  278.         if (!empty($etablissementIds)) {
  279.             $etablissements $this->entityManager->getRepository(Etablissement::class)
  280.                 ->createQueryBuilder('e')
  281.                 ->leftJoin('e.localite''l')
  282.                 ->leftJoin('l.directionRegionale''d')
  283.                 ->leftJoin('e.etablissementMetiers''em')
  284.                 ->leftJoin('em.metier''m')
  285.                 ->addSelect('l''d''em''m')
  286.                 ->where('e.id IN (:ids)')
  287.                 ->setParameter('ids'$etablissementIds)
  288.                 ->getQuery()
  289.                 ->getResult();
  290.             
  291.             usort($etablissements, function($a$b) use ($etablissementIds) {
  292.                 return array_search($a->getId(), $etablissementIds) - array_search($b->getId(), $etablissementIds);
  293.             });
  294.         }
  295.         return $this->json([
  296.             'html' => $this->renderView('partials/_etablissements_cards.html.twig', [
  297.                 'etablissements' => $etablissements,
  298.             ]),
  299.             'total' => $total,
  300.             'page' => $page,
  301.             'limit' => $limit
  302.         ]);
  303.     }
  304.     private function getPartenaires(): array
  305.     {
  306.         return [
  307.             [
  308.                 'nom' => 'Banque Mondiale',
  309.                 'image' => 'image/partenaire/worldbank.png',
  310.                 'lien' => 'https://www.banquemondiale.org'
  311.             ],
  312.             [
  313.                 'nom' => 'BCP Emploi',
  314.                 'image' => 'image/partenaire/bcp.png',
  315.                 'lien' => 'http://www.pejedec.org/'
  316.             ]
  317.         ];
  318.     }
  319.     #[Route('/etablissements'name'app_etablissements_list')]
  320.     public function etablissementsList(Request $request): Response
  321.     {
  322.         $recherche $request->query->get('recherche''');
  323.         $directionId $request->query->get('direction''');
  324.         $idQuery $this->entityManager->getRepository(Etablissement::class)
  325.             ->createQueryBuilder('e')
  326.             ->select('e.id')
  327.             ->orderBy('e.nom''ASC');
  328.         if (!empty($directionId)) {
  329.             $idQuery->leftJoin('e.localite''l')
  330.                 ->leftJoin('l.directionRegionale''d')
  331.                 ->andWhere('d.id = :directionId')
  332.                 ->setParameter('directionId'$directionId);
  333.         }
  334.         if (!empty($recherche)) {
  335.             $idQuery->andWhere('e.nom LIKE :recherche')
  336.                 ->setParameter('recherche''%' $recherche '%');
  337.         }
  338.         $ids array_column($idQuery->getQuery()->getResult(), 'id');
  339.         $etablissements = [];
  340.         if (!empty($ids)) {
  341.             $etablissements $this->entityManager->getRepository(Etablissement::class)
  342.                 ->createQueryBuilder('e')
  343.                 ->leftJoin('e.localite''l')
  344.                 ->leftJoin('l.directionRegionale''d')
  345.                 ->leftJoin('e.etablissementMetiers''em')
  346.                 ->leftJoin('em.metier''m')
  347.                 ->addSelect('l''d''em''m')
  348.                 ->where('e.id IN (:ids)')
  349.                 ->setParameter('ids'$ids)
  350.                 ->orderBy('e.nom''ASC')
  351.                 ->getQuery()
  352.                 ->getResult();
  353.         }
  354.         $directions $this->entityManager->getRepository(DirectionRegionale::class)
  355.             ->findBy([], ['nom' => 'ASC']);
  356.         return $this->render('etablissement/list.html.twig', [
  357.             'etablissements' => $etablissements,
  358.             'directions' => $directions,
  359.             'total' => count($ids),
  360.             'recherche' => $recherche,
  361.             'directionSelectionnee' => $directionId,
  362.         ]);
  363.     }
  364.     #[Route('/metiers'name'app_metiers_list')]
  365.     public function metiersList(Request $request): Response
  366.     {
  367.         $recherche $request->query->get('recherche''');
  368.         $secteurId $request->query->get('secteur''');
  369.         // Step 1: get IDs only (no collection joins) to avoid Cartesian product in memory
  370.         $idQuery $this->entityManager->getRepository(Metier::class)
  371.             ->createQueryBuilder('m')
  372.             ->select('m.id')
  373.             ->leftJoin('m.secteur''s')
  374.             ->orderBy('m.nom''ASC');
  375.         if (!empty($recherche)) {
  376.             $idQuery->andWhere('m.nom LIKE :recherche')
  377.                 ->setParameter('recherche''%' $recherche '%');
  378.         }
  379.         if (!empty($secteurId)) {
  380.             $idQuery->andWhere('s.id = :secteurId')
  381.                 ->setParameter('secteurId'$secteurId);
  382.         }
  383.         $ids array_column($idQuery->getQuery()->getResult(), 'id');
  384.         // Step 2: load full entities with joins only for the matched IDs
  385.         $metiers = [];
  386.         if (!empty($ids)) {
  387.             $metiers $this->entityManager->getRepository(Metier::class)
  388.                 ->createQueryBuilder('m')
  389.                 ->leftJoin('m.secteur''s')
  390.                 ->leftJoin('m.etablissementMetiers''em')
  391.                 ->leftJoin('em.etablissement''e')
  392.                 ->addSelect('s''em''e')
  393.                 ->where('m.id IN (:ids)')
  394.                 ->setParameter('ids'$ids)
  395.                 ->orderBy('m.nom''ASC')
  396.                 ->getQuery()
  397.                 ->getResult();
  398.         }
  399.         $secteurs $this->entityManager->getRepository(Secteur::class)
  400.             ->findBy([], ['nom' => 'ASC']);
  401.         return $this->render('metier/list.html.twig', [
  402.             'metiers' => $metiers,
  403.             'secteurs' => $secteurs,
  404.             'total' => count($ids),
  405.             'recherche' => $recherche,
  406.             'secteurSelectionne' => $secteurId,
  407.         ]);
  408.     }
  409. }