src/Repository/AgendaElementRepository.php line 164

Open in your IDE?
  1. <?php
  2. namespace App\Repository;
  3. use App\Entity\AgendaElement;
  4. use App\Entity\School;
  5. use App\Entity\SchoolYear;
  6. use App\Entity\User;
  7. use App\Entity\Subject;
  8. use App\Entity\TheClass;
  9. use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
  10. use Doctrine\Persistence\ManagerRegistry;
  11. /**
  12.  * @extends ServiceEntityRepository<AgendaElement>
  13.  *
  14.  * @method AgendaElement|null find($id, $lockMode = null, $lockVersion = null)
  15.  * @method AgendaElement|null findOneBy(array $criteria, array $orderBy = null)
  16.  * @method AgendaElement[]    findAll()
  17.  * @method AgendaElement[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
  18.  */
  19. class AgendaElementRepository extends ServiceEntityRepository
  20. {
  21.     public function __construct(ManagerRegistry $registry)
  22.     {
  23.         parent::__construct($registryAgendaElement::class);
  24.     }
  25.     public function findNearStartAtByClass(
  26.         TheClass $classe,
  27.         School $school,
  28.         ?SchoolYear $year null,
  29.     ): ?AgendaElement {
  30.         // 1. On centralise la Timezone pour éviter les décalages
  31.         $tz = new \DateTimeZone('Africa/Douala');
  32.         $now = new \DateTime('now'$tz);
  33.         // 2. Préparation des bornes (uniquement au format H:i:s pour SQL TIME)
  34.         // On cherche un cours dont la période [startAt, endAt] couvre l'heure actuelle
  35.         $currentTime $now->format('H:i:s');
  36.         // Si tu veux vraiment garder la marge de 5min pour "anticiper" ou "prolonger" :
  37.         $startPlus5 = (clone $now)->modify('+5 minutes')->format('H:i:s');
  38.         $startMinus5 = (clone $now)->modify('-5 minutes')->format('H:i:s');
  39.         // 3. Récupération du nom du jour en anglais (Monday, Tuesday...)
  40.         $dayName $now->format('l');
  41.         $qb $this->createQueryBuilder('ae')
  42.             ->leftJoin('ae.agendaDay''d')
  43.             // Logique : l'heure actuelle (+/- 5min) doit être comprise entre le début et la fin du cours
  44.             ->andWhere('TIME(ae.startAt) <= :plus5')
  45.             ->andWhere('TIME(ae.endAt) >= :minus5')
  46.             ->andWhere('ae.classe = :classe')
  47.             ->andWhere('ae.school = :school')
  48.             ->andWhere('ae.active = :active')
  49.             ->andWhere('d.nameEn = :dayName')
  50.             ->setParameters([
  51.                 'plus5'   => $startPlus5,
  52.                 'minus5'  => $startMinus5,
  53.                 'classe'  => $classe,
  54.                 'school'  => $school,
  55.                 'active'  => true,
  56.                 'dayName' => $dayName
  57.             ])
  58.             ->setMaxResults(1);
  59.         // Sans ce filtre, un AgendaElement d'une autre année scolaire (même
  60.         // classe/jour/créneau récurrent) pouvait être retourné à la place de
  61.         // celui de l'année réellement consultée par l'utilisateur.
  62.         if ($year !== null) {
  63.             $qb->andWhere('ae.year = :year')->setParameter('year'$year);
  64.         }
  65.         return $qb->getQuery()->getOneOrNullResult();
  66.     }
  67.     public function findNearStartAtByTeacherAndByClass(
  68.         User $prof,
  69.         TheClass $classe,
  70.         School $school,
  71.         ?SchoolYear $year null,
  72.     ): ?AgendaElement {
  73.         // 1. On fixe la Timezone pour tout le calcul
  74.         $tz = new \DateTimeZone('Africa/Douala');
  75.         $now = new \DateTime('now'$tz);
  76.         // 2. On récupère le nom du jour selon la Timezone de Douala
  77.         $dayName $now->format('l');
  78.         // 3. On extrait uniquement l'heure pour la comparaison SQL TIME
  79.         // On utilise des chaînes de caractères "H:i:s" pour éviter les conflits de dates (1970 vs 2024)
  80.         $startPlus5 = (clone $now)->modify('+5 minutes')->format('H:i:s');
  81.         $startMinus5 = (clone $now)->modify('-5 minutes')->format('H:i:s');
  82.         $qb $this->createQueryBuilder('ae')
  83.             ->leftJoin('ae.subject''s')
  84.             ->leftJoin('ae.agendaDay''d')
  85.             ->andWhere('s.prof = :prof')
  86.             ->andWhere('ae.school = :school')
  87.             ->andWhere('ae.classe = :classe')
  88.             ->andWhere('d.nameEn = :dayName')
  89.             // On utilise la fonction SQL TIME() pour ignorer la partie Date des colonnes
  90.             ->andWhere('TIME(ae.startAt) <= :startPlus5')
  91.             ->andWhere('TIME(ae.endAt) >= :startMinus5')
  92.             ->andWhere('ae.active = :active')
  93.             ->setParameters([
  94.                 'prof' => $prof,
  95.                 'school' => $school,
  96.                 'classe' => $classe,
  97.                 'dayName' => $dayName,
  98.                 'startPlus5' => $startPlus5,
  99.                 'startMinus5' => $startMinus5,
  100.                 'active' => true,
  101.             ])
  102.             ->setMaxResults(1);
  103.         // Voir le commentaire équivalent dans findNearStartAtByClass().
  104.         if ($year !== null) {
  105.             $qb->andWhere('ae.year = :year')->setParameter('year'$year);
  106.         }
  107.         return $qb->getQuery()->getOneOrNullResult();
  108.     }
  109.     public function findNearStartAtByTeacher(
  110.         User $prof,
  111.         School $school,
  112.     ): ?array {
  113.         // 1. On fixe la Timezone pour tout le calcul
  114.         $tz = new \DateTimeZone('Africa/Douala');
  115.         $now = new \DateTime('now'$tz);
  116.         // 2. On récupère le nom du jour selon la Timezone de Douala
  117.         $dayName $now->format('l');
  118.         // 3. On extrait uniquement l'heure pour la comparaison SQL TIME
  119.         // On utilise des chaînes de caractères "H:i:s" pour éviter les conflits de dates (1970 vs 2024)
  120.         $startPlus5 = (clone $now)->modify('+5 minutes')->format('H:i:s');
  121.         $startMinus5 = (clone $now)->modify('-5 minutes')->format('H:i:s');
  122.         return $this->createQueryBuilder('ae')
  123.             ->leftJoin('ae.subject''s')
  124.             ->leftJoin('ae.agendaDay''d')
  125.             ->andWhere('s.prof = :prof')
  126.             ->andWhere('ae.school = :school')
  127.             ->andWhere('d.nameEn = :dayName')
  128.             // On utilise la fonction SQL TIME() pour ignorer la partie Date des colonnes
  129.             ->andWhere('TIME(ae.startAt) <= :startPlus5')
  130.             ->andWhere('TIME(ae.endAt) >= :startMinus5')
  131.             ->andWhere('ae.active = :active')
  132.             ->setParameters([
  133.                 'prof' => $prof,
  134.                 'school' => $school,
  135.                 'dayName' => $dayName,
  136.                 'startPlus5' => $startPlus5,
  137.                 'startMinus5' => $startMinus5,
  138.                 'active' => true,
  139.             ])
  140.             ->getQuery()
  141.             ->getResult();
  142.     }
  143.     public function findByIdAndByDayAndBySubjectAndBySartAtAndByEndAt($elementId null$dayOfWeek$subjectId null$startAt$endAt)
  144.     {
  145.         $qb $this->createQueryBuilder('a')
  146.             ->join('a.agendaDay''d')
  147.             ->where('LOWER(d.nameEn) = :day')
  148.             ->andWhere('a.startAt = :startAt'// Suppression de l'espace après :
  149.             ->andWhere('a.endAt = :endAt')     // Utilisation de andWhere
  150.             ->setParameter('day'strtolower($dayOfWeek))
  151.             ->setParameter('startAt'$startAt instanceof \DateTimeInterface $startAt->format('H:i:s') : $startAt)
  152.             ->setParameter('endAt'$endAt instanceof \DateTimeInterface $endAt->format('H:i:s') : $endAt);
  153.         if (!empty($elementId)) {
  154.             $qb->andWhere('a.id = :id')
  155.             ->setParameter('id'$elementId);
  156.         }
  157.         if (!empty($subjectId)) {
  158.             $qb->join('a.subject''s')
  159.             ->andWhere('s.id = :subjectId')
  160.             ->setParameter('subjectId'$subjectId);
  161.         } else {
  162.             $qb->andWhere('a.subject IS NULL');
  163.         }
  164.         // IMPORTANT : On affecte le résultat à la variable
  165.         return $qb->getQuery()->getOneOrNullResult();
  166.     }
  167. //    /**
  168. //     * @return AgendaElement[] Returns an array of AgendaElement objects
  169. //     */
  170. //    public function findByExampleField($value): array
  171. //    {
  172. //        return $this->createQueryBuilder('a')
  173. //            ->andWhere('a.exampleField = :val')
  174. //            ->setParameter('val', $value)
  175. //            ->orderBy('a.id', 'ASC')
  176. //            ->setMaxResults(10)
  177. //            ->getQuery()
  178. //            ->getResult()
  179. //        ;
  180. //    }
  181. //    public function findOneBySomeField($value): ?AgendaElement
  182. //    {
  183. //        return $this->createQueryBuilder('a')
  184. //            ->andWhere('a.exampleField = :val')
  185. //            ->setParameter('val', $value)
  186. //            ->getQuery()
  187. //            ->getOneOrNullResult()
  188. //        ;
  189. //    }
  190. }