src/Controller/HomeController.php line 412

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