src/PaaBundle/Controller/RestController.php line 91

Open in your IDE?
  1. <?php
  2. namespace App\PaaBundle\Controller;
  3. // LG 20231027 déac use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  4. use Symfony\Component\HttpFoundation\Request;
  5. use Symfony\Component\HttpFoundation\Response;
  6. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  7. use App\PaaBundle\Security\PaaVoter;
  8. // LG 20231027 déac use App\PaaBundle\Component\Paa\Paa_Constantes;
  9. // LG 20220629 début
  10. use Doctrine\Common\Annotations\AnnotationReader;
  11. use Symfony\Component\Serializer\Serializer;
  12. // LG 20231027 déac use Symfony\Component\Serializer\Annotation\MaxDepth;
  13. // LG 20231027 déac use Symfony\Component\Serializer\Encoder\JsonEncode;
  14. use Symfony\Component\Serializer\Encoder\JsonEncoder;
  15. use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
  16. use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
  17. use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
  18. use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
  19. use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
  20. // LG 20220629 fin
  21. // LG 20221222 début (pour decomposeRessource)
  22. $lsFich dirname(dirname(__FILE__)) . '/Component/Paa/ressources.php';
  23. require_once $lsFich;
  24. // LG 20221222 fin
  25. class RestController extends PAABaseController {
  26.     // Récupération du JSON des données d'une ligne d'une table
  27.     // Besoin de token : cf. \applicationPAA\app\config\security.yml
  28.     /**
  29.      * @Security("has_role('ROLE_USER')")
  30.      */
  31.     // LG 20180622
  32.     public function getJSONEntityAction(Request $request$psNomTable$piId) {
  33.         if ($LoginResponse $this->RedirectIfDisconnected($request'ROLE_USER'$request->headers->get('referer'))) {
  34.             // L'utilisateur en cours n'est pas authéntifié, ou sa session a expiré
  35.             // On retourne à la page appellante
  36.             return $LoginResponse;
  37.         }
  38.         $em $this->getDoctrineManager();
  39.         $entity $em->getRepository("PaaBundle:" $psNomTable)->find($piId);
  40.         if ($entity !== null) {
  41.             $entity->setEntityManager($em);
  42.         }
  43.         $data $this->get('serializer')->serialize($entity'json');
  44.         $response = new Response($data);
  45.         $response->headers->set('Content-Type''application/json');
  46.         return $response;
  47.     }
  48.     // LG 20221219
  49.     public function getJSONPlanningAction(Request $request) {
  50.         if ($LoginResponse $this->RedirectIfDisconnected($request'ROLE_USER'$request->headers->get('referer'))) {
  51.             // L'utilisateur en cours n'est pas authentifié, ou sa session a expiré
  52.             // On retourne à la page appellante
  53.             return $LoginResponse;
  54.         }
  55.         if (!$this->isGranted(PaaVoter::VOIR "Planning")) {
  56.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour visualiser ces données"}');
  57.             $response->headers->set('Content-Type''application/json');
  58.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour visualiser ces données");
  59.             return $response;
  60.         }
  61.         $lsFich dirname(dirname(__FILE__)) . '/Component/Paa/planning.php';
  62.         require_once $lsFich;
  63.         $lsQueryString $request->getQueryString();
  64.         $loConnexion $this->getDoctrineConnection();
  65.         $lbKO = !Planning_RtvJSONPlanning($lsQueryString$loConnexion$thistrue$lsData$lsErreur);
  66.         $response = new Response($lsData);
  67.         if ($lbKO) {
  68.             $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR$lsErreur);
  69.         } else {
  70.             $response->headers->set('Content-Type''application/json');
  71.         }
  72.         return $response ;
  73.     }
  74.     // LG 20180622
  75.     // Récupération du JSON des données d'une ligne d'une table de ressources
  76.     // Besoin de token : cf. \applicationPAA\app\config\security.yml
  77.     public function getJSONEntitiesAction(Request $requeststring $psNomTablestring $psParametres) {
  78.         if ($LoginResponse $this->RedirectIfDisconnected($request'ROLE_USER'$request->headers->get('referer'))) {
  79.             // L'utilisateur en cours n'est pas authentifié, ou sa session a expiré
  80.             // On retourne à la page appellante
  81.             return $LoginResponse;
  82.         }
  83.         if (!$this->isGranted(PaaVoter::VOIR $psNomTable)) {
  84.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour visualiser ces données"}');
  85.             $response->headers->set('Content-Type''application/json');
  86.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour visualiser ces données");
  87.             return $response;
  88.         }
  89.         
  90.         // Récupérer la liste des entités convertie en JSON 
  91.         $lbKO false ;
  92.         $lsErreur "" ;
  93.         $lsData $this->getJSONEntities($request$psNomTable$psParametres) ;
  94.     
  95.         $response = new Response($lsData);
  96.         if ($lbKO) {
  97.             $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR$lsErreur);
  98.         } else {
  99.             $response->headers->set('Content-Type''application/json');
  100.         }
  101.         return $response;
  102.     }
  103.     // LG 20180622
  104.     // Récupération du JSON des données d'une ligne d'une table de ressources
  105.     public function getJSONEntities(Request $requeststring $psNomTablestring $psParametres) {
  106.         $laIgnoredAttributes = [] ;     // Liste des attributs qu'on a pas besoin de sérialiser
  107.         $laParametresPOST $request->request->all() ;
  108.         $lbPourCbo false ;
  109.         if (isset($laParametresPOST["pourCbo"]) && $laParametresPOST["pourCbo"]) {
  110.             // On demande un remplissage pour cbo
  111.             $lbPourCbo true ;
  112.             // Si la demande concerne des intervenants/usagers/groupes/salles, forcer le passage comme si on demandait "Ressources"
  113.             if (in_array(ucwords($psNomTable), ["Intervenants""Usagers""Groupes""Salles""Etablissements"])) {
  114.                 $psParametres $psParametres?$psParametres."&":"" ;
  115.                 $psParametres .= "cType_Res=" strtoupper(substr($psNomTable01)) ;
  116.                 if (isset($laParametresPOST["selectedItem"]) && $laParametresPOST["selectedItem"]) {
  117. // LG 20240826 début
  118. //                    $psParametres .= "&cLstResForcées=" . $laParametresPOST["selectedItem"] ;
  119.                     if (is_array($laParametresPOST["selectedItem"])) {
  120.                         $lsLstResForcées "" ;
  121.                         foreach($laParametresPOST["selectedItem"] as $liId_Res) {
  122.                             if ($lsLstResForcées$lsLstResForcées .= "," ;
  123.                             $lsLstResForcées .= $liId_Res ;
  124.                         }
  125.                     } else {
  126.                         $lsLstResForcées $laParametresPOST["selectedItem"] ;
  127.                     }
  128.                     $psParametres .= "&cLstResForcées=" $lsLstResForcées ;
  129. // LG 20240826 fin
  130.                 }
  131.                 $psNomTable "Ressources" ;
  132.             }
  133.         }
  134.         $lbKO false;
  135.         if (isset($request->query->all()["psNomTable"])) {
  136.             // On a fourni le nom de table dans le queryString
  137.             $psNomTable $request->query->all()["psNomTable"] ;
  138.         }
  139.         if (ucwords($psNomTable) == 'Ressources' || ucwords($psNomTable) == 'RessourcesIgnoreParticipantes' || ucwords($psNomTable) == 'RessourcesPourActi') {
  140.             // Dans ce cas particulier, si iActi est défini dans les paramètres, il faut construire un JSON + complexe
  141.             // Cas obsolètes
  142.             if (ucwords($psNomTable) == 'RessourcesPourActi') {
  143.                 // CAS OBSOLETE ????
  144.                 $this->logAppelObsolète("getJSONEntitiesAction, psTable = 'RessourcesPourActi'") ;     // LG 20221219              
  145.             }
  146.             if (ucwords($psNomTable) == 'RessourcesIgnoreParticipantes') {
  147.                 // CAS OBSOLETE ????
  148.                 $this->logAppelObsolète("getJSONEntitiesAction, psTable = 'RessourcesIgnoreParticipantes'") ;     // LG 20221219              
  149.             }
  150.             // La fonction function ajax_FillcbcRessources fournit les paramètres en GET dans le queryString : on doit ajouter ces paramètres à ceux reçus éventuellement dans psParamètres
  151.             $lsQueryString $request->getQueryString();
  152.             if ($lsQueryString) {
  153.                 $psParametres $lsQueryString "&" $psParametres ;
  154.             }
  155.             $laQueryString = array();
  156.             parse_str($lsQueryString$laQueryString);
  157.             if (isset($laQueryString["iActi"]) && $laQueryString["iActi"] && !strpos($psParametres"IgnoreIActi")) {
  158.                 // Cas particulier
  159.                 // On a fourni une activité : on va aussi vouloir 
  160.                 //    * la liste des ressources compétentes ou participant à l'activité
  161.                 //    * la liste des ressources participant à l'activité
  162.                 $lsJSONRessourcesCompétentes $this->getJSONEntities($request"Ressources"$psParametres "&IgnoreIActi=1");      // Ajouter "IgnoreIActi=1" pour éviter la récurrence
  163.                 $lsJSONRessourcesParticipantes $this->getJSONEntities($request"ParticipantsAActi"$psParametres);               
  164.                 $lsData '{"Compétentes": ' $lsJSONRessourcesCompétentes
  165.                         ', "Participantes": ' $lsJSONRessourcesParticipantes '}';
  166.                 return $lsData ;
  167.             }
  168. // // LG 20240826 début
  169. //             if (isset($laQueryString["cType_Res"]) && $laQueryString["cType_Res"] == "M") {
  170. //                 // Cas particulier des matières
  171. //                 $psNomTable = "matieres" ;
  172. //                 $lbPourCbo = true ;
  173. //             }
  174. // // LG 20240826 fin
  175.         
  176.         // Récupérer le liste des entités
  177.         $entities $this->getEntities($psNomTable$psParametres);
  178.     
  179.         if (ucwords($psNomTable) == 'Usagers') {
  180.             // Liste des usagers pour une combobox
  181.             // CAS OBSOLETE ????
  182.             $this->logAppelObsolète("getJSONEntitiesAction, psTable = 'Usagers'") ;     // LG 20221219
  183.             $lbPourCbo true ;
  184.         }
  185.         if ($lbPourCbo) {
  186.             $repo $this->getDoctrineRepository("PaaBundle:" $psNomTable) ;
  187. // LG 20240826 début
  188. //            $laIgnoredAttributes = $repo->getAllFields($repo->getAllFieldsPourCbo()) ;      // tous les champs inutiles pour les cbos
  189.             $loEntiteModele null ;
  190.             if (count($entities)) $loEntiteModele $entities[0] ;
  191.             $laIgnoredAttributes $repo->getAllFields($repo->getAllFieldsPourCbo(), $loEntiteModele) ;      // tous les champs inutiles pour les cbos
  192. // LG 20240826 fin
  193.         }
  194.         if (isset($laParametresPOST["lstFlds"]) && $lsLstFlds $laParametresPOST["lstFlds"]) {
  195.             $repo $this->getDoctrineRepository("PaaBundle:" $psNomTable) ;
  196.             $laFlds explode(","$lsLstFlds) ;
  197.             $laIgnoredAttributes $repo->getAllFields($laFlds) ;      // tous les champs inutiles pour les cbos
  198.         }
  199.         if (!isset($lsData)) {
  200.             // La chaine de caractères à renvoyer n'a pas encore été déterminée : la déterminer maintenant en sérialisant $entities
  201.             // certaines classes génèrent une référence circulaire (par exemple caisses référence contacts, qui références caisses, etc.)
  202.             // De plus, il faut ignorer certains attributs, qui ne sont pas accessibles dans ce contexte (par exemple, ceux qui demandent que l'entité connaisse son entityManager)
  203.             if (in_array(ucwords($psNomTable), ['Salles''Intervenants''Usagers''Groupes''Etablissements'])) {
  204.                 // Inutile de récupérer les activités
  205.                 $laIgnoredAttributes array_merge($laIgnoredAttributes, ['activites''listeContrats']) ;
  206.             } else if (ucwords($psNomTable) == 'Caisses') { 
  207.                 $laIgnoredAttributes array_merge($laIgnoredAttributes, ['listeContacts''type']) ;       // Pour les caisses, on n'a pas besoin de ces attributs, qui chargent des sous-entités inutiles pour ce que l'on a à en faire pour l'instant
  208. // LG 20240419 old            } else if (ucwords($psNomTable) == 'CaissesPersonnes') {
  209.             } else if (ucwords($psNomTable) == 'Caissespersonnes') {
  210.                 $laIgnoredAttributes array_merge($laIgnoredAttributes, ['icaisse']) ;                     // Pour les contacts de caisses, on n'a pas besoin de ces attributs, qui chargent des sous-entités inutiles pour ce que l'on a à en faire pour l'instant
  211.             
  212.             if (ucwords($psNomTable) =='Groupes') {
  213.                 $laIgnoredAttributes array_merge($laIgnoredAttributes, ['listeGroupesUsagers']) ;
  214.             }
  215.             
  216.             $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
  217.             $circularReferenceHandler = function ($object$format$context) {
  218.                 return $object->getId();
  219.             };
  220.             $defaultContext = [
  221.                 AbstractObjectNormalizer::CIRCULAR_REFERENCE_HANDLER => $circularReferenceHandler,
  222.                 AbstractObjectNormalizer::CIRCULAR_REFERENCE_LIMIT => 1,
  223.                 AbstractNormalizer::IGNORED_ATTRIBUTES => $laIgnoredAttributes
  224.             ];
  225.             $normalizer = new ObjectNormalizer($classMetadataFactorynullnullnullnullnull$defaultContext);
  226.             $serializer = new Serializer(array($normalizer), array(new JsonEncoder()));
  227.             $entitiesNormalized $serializer->normalize($entitiesnull);
  228.             $lsData $serializer->serialize($entitiesNormalized'json') ;
  229.         }
  230.         return $lsData ;
  231.     }
  232.     // MC 20201021
  233.     // recupere la semaine select et la valeur du checkbox pour le transmetre au repository qui sert a modifier la valeur de lValidee
  234.     // Appellé par la requette ajax apres le clic sur le bouton checkbox semaine validee 
  235.     // Retoune le status, ok si l'action c'est bien passer et ko sinon
  236. // LG 20240524 old    public function setEtatSemaineAction(Request $request, $piSem, $pbValue) {
  237.     public function setEtatSemaineAction(Request $request$piSem$pbValue$pbAutoriseCreation) {
  238.         if ($LoginResponse $this->RedirectIfDisconnected($request'ROLE_USER'$request->headers->get('referer'))) {
  239.             // L'utilisateur en cours n'est pas authéntifié, ou sa session a expiré
  240.             // On retourne à la page appellante
  241.             return $LoginResponse;
  242.         }
  243.         $lbValue = ($pbValue && $pbValue === "true") ;
  244.         $lbSemaineNonCréée false ;
  245. // LG 20240612 début
  246. //        $lbOK = $this->getDoctrineRepository("PaaBundle:etablissementsSemaines")->valideSemaine($piSem, $lbValue, $pbAutoriseCreation, $lbSemaineNonCréée);
  247.         $lsMsgErr "" ;
  248.         $lbOK $this->getDoctrineRepository("PaaBundle:etablissementsSemaines")->valideSemaine($piSem$lbValue$pbAutoriseCreation$lbSemaineNonCréée$lsMsgErr);
  249. // LG 20240612 fin
  250.         if ($lbOK) {
  251.             $lsJSONRep '{"status": "ok"}' ;
  252.         } else if ($lbSemaineNonCréée) {
  253.             // La semaine n'est pas encore créée et on n'autorise pas la création automatique : il faut demander à l'utilisateur s'il confirme la création par défaut
  254.             $lsJSONRep '{"Dialogue": {"Message": "La semaine à valider n\'est pas encore créée. Souhatez-vous la créer maintenant avec les options par défaut ?"'
  255.                             ', "Titre":"Valider la semaine"'
  256.                             ', "Boutons": [{"text":"OK", "id": "cmdParticipation", "focused": true, "Action":"valideSemaine_AvecCreation"}'
  257.                             ', {"text":"Annuler", "class":"cmdCancel", "id": "cmdAnnuler", "Action":"valideSemaine_Annule"}]}'
  258.                             ', "DemandeInitiale": ""'
  259.                             ', "DialogueEnCours": "ConfirmeSuppression"'
  260.                             '}';
  261.         } else {
  262. // LG 20240612 old            $lsJSONRep = '{"status": "ko"}' ;
  263.             $lsJSONRep '{"status": "ko", "message": "' $lsMsgErr '"}' ;
  264.         }
  265.         $response = new Response($lsJSONRepResponse::HTTP_OK, array('content-type' => 'text/json'));
  266.         return $response;
  267.     }
  268.     // MC 20201211
  269. // LG 20240528 old    public function getStatutSemainesAction(Request $request, $pdDebut, $pdFin) {
  270.     // $pdDebut                 : date ou semaine de début
  271.     // $pdFin                   : date ou semaine de fin
  272.     // ($pbCheckLstClasses)     : true pour vérifier aussi la liste des classes présentes (en comparaison avec ce qu'elle était lors de la création éventuelle)
  273.     public function getStatutSemainesAction(Request $request$pdDebut$pdFin$pbCheckLstClasses false) {
  274.         if ($LoginResponse $this->RedirectIfDisconnected($request'ROLE_USER'$request->headers->get('referer'))) {
  275.             // L'utilisateur en cours n'est pas authéntifié, ou sa session a expiré
  276.             // On retourne à la page appellante
  277.             return $LoginResponse;
  278.         }
  279. // LG 20240528 old        $laStatuValid = $this->getDoctrineRepository("PaaBundle:etablissementsSemaines")->getStatutSemaines($pdDebut, $pdFin);
  280.         $laStatuValid $this->getDoctrineRepository("PaaBundle:etablissementsSemaines")->getStatutSemaines($pdDebut$pdFin$pbCheckLstClasses);
  281.         $myJSON json_encode($laStatuValid);
  282.         $response = new Response(
  283.                 $myJSONResponse::HTTP_OK, array('content-type' => 'text/json')
  284.         );
  285.         return $response;
  286.     }
  287.     //MC 20210727
  288.     public function getJSONTypesAbsencesAction($psIdRessource) {
  289.         $em $this->getDoctrineManager();
  290.         $repository $em->getRepository("PaaBundle:actibases");
  291.         $laTypeAbsence $repository->getActivitesAbsencesRessourcesJSON($psIdRessource);
  292.         $response = new Response(
  293.                 $laTypeAbsenceResponse::HTTP_OK, array('content-type' => 'text/json')
  294.         );
  295.         return $response;
  296.     }
  297.     // Nettoyer les données du planning
  298.     // $data : tableau contenant 
  299.         // "dDébut        : date de début de nettoyage (incluse)
  300.         // "dFin"        : date de fin de nettoyage (incluse)
  301.         // "iGroupeAB"    : groupe d'activités de base pour lequel il faut nettoyer
  302.     // &$pcLog            : pour retour du message d'erreur
  303.     // LG 20211214
  304.     function nettoiePlanningAction(Request $request) {
  305.         if (!$this->isGranted(PaaVoter::MODIFIER "séances")) {
  306.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  307.             $response->headers->set('Content-Type''application/json');
  308.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  309.             return $response;
  310.         }
  311.         $data $request->request->all();
  312.         $em $this->getDoctrineManager();
  313.         $repo $em->getRepository("PaaBundle:seances");
  314.         try {
  315.             $repo->nettoiePlanning($data$lcLog) ;
  316.             $loResponse = new Response('{"status": "OK"}'Response::HTTP_OK, array('content-type' => 'text/json')) ;
  317.         } catch (\Exception $e) {
  318.             $loResponse = new Response('{"status": "KO", "msgErreur": "' json_encode($e->getMessage(), JSON_HEX_APOS) . '"}'Response::HTTP_OK, array('content-type' => 'text/json')) ;
  319.             $this->Log("Erreur lors du nettoyage du planning : " $e->getMessage(), "critical"true) ;
  320.         }
  321.         return $loResponse ;
  322.         
  323.     }
  324.     // Modifier le type d'absence d'une ressource sur une semaine
  325.     // Les paramètres sont passés en POST : 
  326.     // {
  327.     //     aLstRes: [{idRes: "I1022", nomRes: "toto",{idRes: "U55589", nomRes: "tata"}]
  328.     //     , aSemaines: [3761, 3762) ] 
  329.     //     , lExceptionnel: true
  330.     //     , iSemType: -1
  331.     // }
  332.     // LG 20221215
  333.     function setTypeAbsenceAction(Request $request) {
  334.         if (!$this->isGranted(PaaVoter::MODIFIER "RendHoraireExceptionnel")) {
  335.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  336.             $response->headers->set('Content-Type''application/json');
  337.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  338.             return $response;
  339.         }
  340.         $lbOK true ;
  341.         $liNbEchecs ;
  342.         $liNbSuccès ;
  343.         $lsMsgEchecs "" ;
  344.         $laParams $request->request->all() ;
  345.         $liTypeAbs $laParams["iSemType"] ;
  346.         if ($laParams["lExceptionnel"]) {
  347.             // Pour passer en "semaine exceptionnelle, on doit passer idSemType / 100 à setTypeAbsence
  348.             if (!is_numeric($liTypeAbs)) $liTypeAbs = -;  // LG 20230412
  349.             $liTypeAbs $liTypeAbs 100 ;
  350.         }
  351.         $laSemaines $laParams["aSemaines"] ;
  352.         $lsLstSemaines "" ;
  353.         $lsLstSemainesValidées "" ;       // LG 20240612
  354.         $loRepoEtablissementsSemaines $this->getDoctrineManager()->getRepository("PaaBundle:etablissementsSemaines") ;
  355.         foreach($laSemaines as $liSem) {
  356. // LG 20240612 début
  357.             if ($loRepoEtablissementsSemaines->estSemaineValidee((int)$liSem)) {
  358.                 $lsLstSemainesValidées.= $liSem ;
  359.             }
  360. // LG 20240612 fin            
  361.             $lsLstSemaines .= $liSem ",";
  362.         }
  363. // LG 20240612 début
  364.         if ($lsLstSemainesValidées) {
  365.             $lsRep "{\"status\": \"KO\", \"message\": \"Il n'est pas possible de modifier le type d'absence d'une ressource pour une semaine validée : il vous faut la dévalider au préalable.\"}" ;
  366.             $loResponse = new Response($lsRepResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  367.             return $loResponse ;
  368.         }
  369. // LG 20240612 fin
  370.         
  371.         $laRessources $laParams["aLstRes"] ;
  372.         foreach($laRessources as $loRes) {
  373.             $lsRes $loRes["idRes"] ;
  374.             decomposeRessource($lsRes$lsTypeRes$liIdRes) ;
  375.             // Poser le type d'horaires demandé pour cette ressource
  376.             $lbRes $this->getDoctrineManager()->getRepository("PaaBundle:ressources")->setTypeAbsence($lsTypeRes$liIdRes$lsLstSemaines$liTypeAbs);
  377.             if ($lbRes) {
  378.                 $liNbSuccès ++ ;
  379.                 $lsMsgEchecs .= "Succès de la mise à jour pour " $loRes["nomRes"] . ".<br>" ;
  380.             } else {
  381.                 // La modification a échoué pour cette ressource
  382.                 $liNbEchecs ++ ;
  383.                 $lsMsgEchecs .= "Echec de la mise à jour pour " $loRes["nomRes"] . ".<br>" ;
  384.             }
  385.         }
  386.         // Construction de la réponse
  387.         if ($liNbEchecs == 0) {
  388.             // Tout a réussi
  389.             $lsRep '{"status": "OK"}' ;
  390.         } else if ($liNbSuccès == 0) {
  391.             // Tout a échoué
  392.             $lsRep "{\"status\": \"KO\", \"message\": \"Echec de la mise à jour\"}" ;
  393.         } else {
  394.             // Mélange de succès et d'échecs
  395.             $lsRep "{\"status\": \"KO\", \"message\": \"Certaines mises à jour ont échoué : <br>$lsMsgEchecs\"}" ;
  396.         }
  397.         $loResponse = new Response($lsRepResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  398.         return $loResponse ;
  399.     }
  400. // LG 20230118 passé de TestController Début
  401.     //HL 20211014 DEBUT
  402. // LG 20230118 old    private function addEntity(array $paPostdata, $psNomTable) {
  403.     private function addEntity(array $paPostdata$psNomTable$pbAutoriseUtiliseExistant false) {
  404.         
  405.         $em $this->getDoctrineManager();
  406.         $repo $em->getRepository("PaaBundle:" $psNomTable);
  407.         $className $repo->getClassName();
  408.         $loEntite = new $className($em);
  409.         
  410.         foreach($paPostdata as $key => $value) {
  411.             $lsNomMethode 'set'.str_replace(' '''ucwords(str_replace('_'' '$key)));
  412.             if (method_exists($loEntite$lsNomMethode)) {
  413.                 if ($psNomTable == 'users' && $key == 'password') {
  414.                     // Pour les users, il faut encoder le mdp s'il a changé
  415.                     // A noter que ca semble fait dans D:\Luc\Dev\DevWeb\Symfony\applicationPAA\src\PaaBundle\Controller\UserController.php, qui n'est utilisé nulle part
  416.                     $pwd $paPostdata[$key];
  417.                     $encoder $this->get("security.password_encoder");
  418.                     $paPostdata[$key] = $encoder->encodePassword($loEntite$pwd);
  419.                 }
  420.                 $loEntite->$lsNomMethode($paPostdata[$key]);
  421.             }
  422.         }
  423.         try {       // LG 20230118
  424.             $em->persist($loEntite);
  425.             $em->flush();
  426. // LG 20230118 début
  427.         } catch (\Doctrine\DBAL\Exception\UniqueConstraintViolationException $e)  {
  428.             // Gestion du cas des violations de contraintes unique
  429.             if ($pbAutoriseUtiliseExistant) {
  430.                 // On accepte la récupération de l'entité pré-existante qui viole la contrainte d'unicité
  431.                 // Récupérer cette entité
  432.                 /* Le message d'erreur contient un texte du type : 
  433.                 "SQLSTATE[23505]: Unique violation: 7 ERROR:  duplicate key value violates unique constraint "u_actibases_cnom"
  434.                 DETAIL:  Key (cnom, isousgroupe)=(Education, pédagogie, apprentissages              , -9) already exists."
  435.                 */
  436.                 $lsDetails explode("DETAIL:  "$e->getMessage())[1] ;
  437. // LG 20230901 début
  438.                 // Résolution du problème de présence de parenthèses ou de virules dans les champs caractère impliqués dans cette erreur
  439.                 $laCorrections = [] ;
  440.                 foreach($paPostdata as $lsFld => $lvValue) {
  441.                     if (strpos($lsDetailsstrtolower($lsFld))) {
  442.                         // Ce champ est sans doutes présent dans la liste des champs incriminés
  443.                         if (strpos($lvValue",") || strpos($lvValue"(") || strpos($lvValue")")) {
  444.                             // La valeur correspondant à ce champ contient des caractères interdits
  445.                             $lvValueCorr $lvValue ;
  446.                             $lvValueCorr str_replace(",""@VIRGULE@"$lvValueCorr);
  447.                             $lvValueCorr str_replace("(""@PARENTHESEOUVRANTE@"$lvValueCorr);
  448.                             $lvValueCorr str_replace(")""@PARENTHESEFERMANTE@"$lvValueCorr);
  449.                             $laCorrections[$lvValue] = $lvValueCorr ;
  450.                             // Remplacer dans le texte des détails
  451.                             $lsDetails str_replace($lvValue$lvValueCorr$lsDetails) ;
  452.                         }
  453.                     }
  454.                 }
  455. // LG 20230901 fin                
  456.                 if ($lsDetails) {
  457.                     if (preg_match_all('~\(([^()]*)\)~'$lsDetails$laMatches)) {
  458.                         // Déterminer les critères de recherche de l'entité qui fait doublon
  459.                         // laMatches a la forme : "[0: [0: ["(cinitiales)", 1:"(ECH       )"], 1: [0:"cinitiales", 1:"ECH       "]]
  460.                         $laDétails $laMatches[1] ;
  461. // LG 20230901 début
  462. //                        $loEntite = $repo->getEntityByUniqueConstraint($laDétails[0], $laDétails[1]) ;
  463.                         $lsLstFlds $laDétails[0] ;
  464.                         $laFlds explode(","$lsLstFlds) ;
  465.                         $lsLstValues $laDétails[1] ;
  466.                         $laValues explode(","$lsLstValues) ;
  467.                         foreach($laCorrections as $lsOrignial => $lsCorrigé) {
  468.                             for ($i 0$i count($laValues); $i++) {
  469.                                 $laValues[$i] = str_replace($lsCorrigé$lsOrignial$laValues[$i]) ;
  470.                             }
  471.                         }
  472.                         // Retrouver l'entité correspondant à ces critères
  473.                         $loEntite $repo->getEntityByUniqueConstraint($laFlds$laValues) ;
  474. // LG 20230901 fin
  475.                         if (!$loEntite) {
  476.                             throw new \Exception("Impossible de trouver l'entité violant la contrainte unique " $e->getMessage()) ;            
  477.                         }
  478.                     } else {
  479.                         throw new \Exception("Impossible de trouver les informations sur l'entité cause de l'exception de contrainte unique " $e->getMessage()) ;            
  480.                     }
  481.                 } else {
  482.                     throw new \Exception("Impossible de trouver le détail de l'exception de contrainte unique " $e->getMessage()) ;
  483.                 }
  484.             } else {
  485.                 // On n'accepte pas la récupération d'un élément existant
  486.                 throw $e ;
  487.             }
  488. // LG 20230118 fin
  489.             
  490.         } catch (\Exception $e)  {
  491.             // Cas d'exception non prévu
  492.             throw $e ;
  493.         }        
  494.         return $loEntite ;
  495.     }
  496.     
  497.     public function addEntityAction(Request $request$psNomTable) {
  498.         
  499. // LG 20230118 old        $loEntite = $this->addEntity($request->request->all(), $psNomTable);
  500.         $loEntite $this->addEntity($request->request->all(), $psNomTable$request->query->get("pbAutoriseUtiliseExistant"));
  501.         
  502.         $response = new Response(
  503.                 '{"status": "OK", "idEntite": ' $loEntite->getId() . '}'Response::HTTP_OK, array('content-type' => 'text/json')
  504.         );
  505.         return $response ;      // LG 20230830
  506.         
  507.     }
  508. // LG 20230118 passé de TestController fin
  509. // CB 20230301 début
  510.     // Permuter les rangs de deux groupes
  511.     public function permuteGroupesAction($piIdGroupe1$piIdGroupe2) {
  512.         $em $this->getDoctrineManager();
  513.         $repo $em->getRepository("PaaBundle:groupes");
  514. // -        $loGroupe1 = $repo->find($piIdGroupe1) ;
  515. //         $loGroupe2 = $repo->find($piIdGroupe2) ;
  516. //         $lsMsg = "" ;
  517. //         if (!$loGroupe1) {
  518. //             if ($lsMsg) $lsMsg .= ", " ;
  519. //             $lsMsg .= "Erreur : le groupe $piIdGroupe1 n'existe pas" ;
  520. //         }
  521. //         if (!$loGroupe2) {
  522. //             if ($lsMsg) $lsMsg .= ", " ;
  523. //             $lsMsg .= "Erreur : le groupe $piIdGroupe2 n'existe pas" ;
  524. //         }
  525. //         if ($lsMsg) {
  526. //             // Il y a eu une erreur
  527. //             $lsJSON = '{"status": "KO", "message": "' . $lsMsg . '}' ;
  528. //         } else {
  529. //             // Pas d'erreur, on peut permuter
  530. //             $liTmp = $loGroupe1->getIRang() ;
  531. //             $loGroupe1->setIRang($loGroupe2->getIRang()) ;
  532. //             $loGroupe2->setIRang($liTmp) ;
  533. //             $em->persist($loGroupe1);
  534. //             $em->persist($loGroupe2);
  535. //             $em->flush();
  536. //             $lsJSON = '{"status": "OK", "piIdGroupe1": ' . $piIdGroupe1 . ', "piIdGroupe2": ' . $piIdGroupe2 . '}' ;
  537. //         }
  538.         $lsMsgErr "" ;
  539.         if ($repo->permuteGroupes($piIdGroupe1$piIdGroupe2$lsMsgErr)) {
  540.             $lsJSON '{"status": "OK", "piIdGroupe1": ' $piIdGroupe1 ', "piIdGroupe2": ' $piIdGroupe2 '}' ;
  541.         } else {
  542.             $lsJSON '{"status": "KO", "message": "' $lsMsgErr '}' ;
  543.         }
  544.         $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  545.         return $response;
  546.     }
  547. // CB 20230301 fin
  548. // LG 20240430 old    public function getPlanFormationAction(Request $request, $psIdRes, $pdDebut, $pdFin) {
  549.     public function getPlanFormationAction(Request $request$psIdRes$pdDebut$pdFin$pbAfficheSemainesAbsences) {
  550.         if (!$this->isGranted(PaaVoter::VOIR "PlansFormation")) {
  551.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  552.             $response->headers->set('Content-Type''application/json');
  553.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  554.             return $response;
  555.         }
  556.         decomposeRessource($psIdRes$lsType_Res$liId_Res) ;
  557.         if ($lsType_Res !== "G") {
  558.             $lsJSON '{"status": "KO", "message": "Cette fonction n\'est disponible que pour les groupes"}' ;           
  559.         } else {
  560.             $em $this->getDoctrineManager() ;
  561.             $r $em->getRepository("PaaBundle:groupes") ;
  562.             try {
  563. // LG 20240430 old                $loPF = $r->getPlanFormation($liId_Res, $pdDebut, $pdFin) ;
  564.                 $loPF $r->getPlanFormation($liId_Res$pdDebut$pdFin$pbAfficheSemainesAbsences) ;
  565.                 $loRep = ["status" => "OK""data" => $loPF] ;
  566.                 $lsJSON json_encode($loRep) ;
  567.             } catch(\Exception $e) {
  568.                 $lsMsg $e->getMessage() ;
  569.                 $lsJSON '{"status": "KO", "message": ' json_encode($lsMsg) . '}' ;
  570.             }
  571.         }
  572.         $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  573.         return $response;
  574.     }
  575.     public function savePlanFormationAction(Request $request$psIdRes) {
  576.         if (!$this->isGranted(PaaVoter::MODIFIER "PlansFormation")) {
  577.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  578.             $response->headers->set('Content-Type''application/json');
  579.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  580.             return $response;
  581.         }
  582.         decomposeRessource($psIdRes$lsType_Res$liId_Res) ;
  583.         if ($lsType_Res !== "G") {
  584.             $lsJSON '{"status": "KO", "message": "Cette fonction n\'est disponible que pour les groupes"}' ;           
  585.         } else {
  586.             $em $this->getDoctrineManager() ;
  587.             $r $em->getRepository("PaaBundle:groupes") ;
  588.             $laData $request->request->all() ;
  589.             try {
  590.                 $lsRep $r->savePlanFormation($liId_Res$laData) ;
  591.                 if ($lsRep) {
  592.                     // Erreur lors de l'enregsitrement
  593.                     $lsJSON '{"status": "KO", "message": ' json_encode($lsRep) . '}' ;
  594.                 } else {
  595.                     // OK
  596.                     $lsJSON '{"status": "OK"}' ;
  597.                 }
  598.             } catch(\Exception $e) {
  599.                 $lsMsg $e->getMessage() ;
  600.                 $lsJSON '{"status": "KO", "message": ' json_encode($lsMsg) . '}' ;
  601.             }
  602.         }
  603. //         $lsJSON = '{"status": "OK", "message": "coucou, votre demande d\'enregistrement de données concerne le groupe ' . $psIdRes . '"}' ;
  604.         $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  605.         return $response;
  606.     }
  607.     // LG 20240516
  608.     public function getPrésencesClassesAction(Request $request$pdDebut$pdFin) {
  609.         if (!$this->isGranted(PaaVoter::VOIR "PrésencesClasses")) {
  610.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  611.             $response->headers->set('Content-Type''application/json');
  612.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  613.             return $response;
  614.         }
  615.         $em $this->getDoctrineManager() ;
  616.         $r $em->getRepository("PaaBundle:groupes") ;
  617.         try {
  618.             $loPF $r->getPrésencesClasses($pdDebut$pdFin) ;
  619.             $loRep = ["status" => "OK""data" => $loPF] ;
  620.             $lsJSON json_encode($loRep) ;
  621.         } catch(\Exception $e) {
  622.             $lsMsg $e->getMessage() ;
  623.             $lsJSON '{"status": "KO", "message": ' json_encode($lsMsg) . '}' ;
  624.         }
  625.         $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  626.         return $response;
  627.     }
  628.     public function getListeCreneauxAction(Request $request$pdDebut$pdFin$psLstRes) {
  629.         if (!$this->isGranted(PaaVoter::VOIR "séances")) {
  630.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  631.             $response->headers->set('Content-Type''application/json');
  632.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  633.             return $response;
  634.         }
  635.         
  636.         $em $this->getDoctrineManager();
  637.         $loRepoSeances $em->getRepository("PaaBundle:seances") ;
  638.         $laCreneaux $loRepoSeances->rtvCurCréneaux($psLstRes$pdDebut$pdFintrue /*$pbInclSimulationHorairesType*/) ;
  639.         $lsJSON json_encode($laCreneaux);
  640.         $lsJSON '{"status": "OK", "data": ' $lsJSON '}' ;
  641.         $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  642.         return $response;
  643.     }
  644.     /** Créer pour un groupe et une semaine une collection complète de créneaux horaires
  645.     * $piIdGroupe
  646.     * $piSemaine
  647.     *($psLstHoraires)       : chaine de caractères de la forme "<Hdeb>-<HFin>[;<Hdeb>-<HFin>[...]]", exemple : '8-10; 10:15-12:15; 13:45-15:45; 16-18'
  648.     * Valeur de retour : message d'erreur éventuel (vide si succès)
  649.     * LG 20231027
  650.     */ 
  651.     public function creeCreneauxStandardAction(Request $request$piIdGroupe$piSemaine$psLstHoraires) {
  652.         if (!$this->isGranted(PaaVoter::MODIFIER "séances")) {
  653.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  654.             $response->headers->set('Content-Type''application/json');
  655.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  656.             return $response;
  657.         }
  658.         
  659.         $em $this->getDoctrineManager();
  660.         $loRepoSeances $em->getRepository("PaaBundle:seances") ;
  661.         $lvRep $loRepoSeances->creeCreneauxStandard($piIdGroupe$piSemaine$psLstHoraires) ;
  662.         if ($lvRep) {
  663.             // Messagd d'erreur non vide
  664.             $lsJSON '{"status": "KO", "message": ' json_encode($lvRep) . '}' ;
  665.             $response = new Response($lsJSONResponse::HTTP_BAD_REQUEST, array('content-type' => 'text/json')) ;
  666.         } else {
  667.             $lsJSON '{"status": "OK"}' ;
  668.             $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  669.         }        
  670.         return $response;
  671.     }
  672.     /** Copier les créneaux horaires d'un groupe vers un autre et/ou d'un jour vers l'autre
  673.     * $piIdGroupeSource     : Id du groupe source de la copie
  674.     * $piIdGroupeDest       : Id du groupe destination de la copie
  675.     * $piSemaineSource      : semaine des horaires source
  676.     * $piSemaineDest        : semaine des horaires destination
  677.     * ($piJourSource)       : journée source des horaires à copier (dft = 0 : toutes, 1= lundi)
  678.     * ($piJourDest)         : journée destination des horaires (dft = 0 : toutes, 1= lundi)
  679.     * Valeur de retour : message d'erreur éventuel (vide si succès)
  680.     * LG 20231027
  681.     */ 
  682.     public function copieCreneauxAction(Request $request$piIdGroupeSource$piIdGroupeDest$piSemaineSource$piSemaineDest$piJourSource=0$piJourDest=0) {
  683.         if (!$this->isGranted(PaaVoter::MODIFIER "séances")) {
  684.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  685.             $response->headers->set('Content-Type''application/json');
  686.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  687.             return $response;
  688.         }
  689.         
  690.         $em $this->getDoctrineManager();
  691.         $loRepoSeances $em->getRepository("PaaBundle:seances") ;
  692.         $lvRep $loRepoSeances->copieCreneaux($piIdGroupeSource$piIdGroupeDest$piSemaineSource$piSemaineDest$piJourSource$piJourDest) ;
  693.         if ($lvRep) {
  694.             // Messagd d'erreur non vide
  695.             $lsJSON '{"status": "KO", "message": ' json_encode($lvRep) . '}' ;
  696.             $response = new Response($lsJSONResponse::HTTP_BAD_REQUEST, array('content-type' => 'text/json')) ;
  697.         } else {
  698.             $lsJSON '{"status": "OK"}' ;
  699.             $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  700.         }        
  701.         return $response;
  702.     
  703.     }
  704.     // LG 20240305
  705.     function prochaineEcheanceUsagerAction(Request $request$piIdUsager) {
  706.         if (!$this->isGranted(PaaVoter::VOIR "usagers")) {
  707.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  708.             $response->headers->set('Content-Type''application/json');
  709.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  710.             return $response;
  711.         }
  712.         $em $this->getDoctrineManager();
  713.         $loRepoUsagers $em->getRepository("PaaBundle:usagers") ;
  714.         $laData $loRepoUsagers->getProchaineEchéanceUsager($piIdUsager) ;
  715.         $lsData json_encode($laData) ;
  716.         $lsJSON '{"status": "OK", "data": ' $lsData '}' ;
  717.         $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  718.         return $response ;
  719.     }
  720.     // LG 20240826
  721.     function getValeursDftMatiereAction(Request $request$piIdMatiere) {
  722.         if (!$this->isGranted(PaaVoter::VOIR "activites")) {
  723.             $response = new Response('{"status": "KO", "message": "Vous ne disposez pas des droits nécessaires pour effectuer cette action."}');
  724.             $response->headers->set('Content-Type''application/json');
  725.             $response->setStatusCode(Response::HTTP_FORBIDDEN"Vous ne disposez pas des droits nécessaires pour effectuer cette action.");
  726.             return $response;
  727.         }
  728.         $em $this->getDoctrineManager();
  729.         $loRepo $em->getRepository(\App\PaaBundle\Entity\matieres::class) ;
  730.         $loMatiere $loRepo->find($piIdMatiere) ;
  731.         $laSousGroupes $loMatiere->getSousGroupes() ;
  732.         $laData["iMatiere"] = $loMatiere->getId() ;
  733.         $laData["aSousGroupes"] = $loMatiere->getSousGroupesArray() ;
  734.         $laData["aIntervenants"] = [$loMatiere->getIintervenant()] ;
  735.         $laData["aSalles"] = [] ;
  736.         $laData["nPrevuSem"] = ;
  737.         $laData["nHeuresMax"] = ;
  738.         $lsData json_encode($laData) ;
  739.         $lsJSON '{"status": "OK", "data": ' $lsData '}' ;
  740.         $response = new Response($lsJSONResponse::HTTP_OK, array('content-type' => 'text/json')) ;
  741.         return $response ;
  742.         
  743.     }
  744. }