<?php
namespace App\Repository;
use App\Entity\AgendaElement;
use App\Entity\School;
use App\Entity\SchoolYear;
use App\Entity\User;
use App\Entity\Subject;
use App\Entity\TheClass;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<AgendaElement>
*
* @method AgendaElement|null find($id, $lockMode = null, $lockVersion = null)
* @method AgendaElement|null findOneBy(array $criteria, array $orderBy = null)
* @method AgendaElement[] findAll()
* @method AgendaElement[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class AgendaElementRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, AgendaElement::class);
}
public function findNearStartAtByClass(
TheClass $classe,
School $school,
): ?AgendaElement {
// 1. On centralise la Timezone pour éviter les décalages
$tz = new \DateTimeZone('Africa/Douala');
$now = new \DateTime('now', $tz);
// 2. Préparation des bornes (uniquement au format H:i:s pour SQL TIME)
// On cherche un cours dont la période [startAt, endAt] couvre l'heure actuelle
$currentTime = $now->format('H:i:s');
// Si tu veux vraiment garder la marge de 5min pour "anticiper" ou "prolonger" :
$startPlus5 = (clone $now)->modify('+5 minutes')->format('H:i:s');
$startMinus5 = (clone $now)->modify('-5 minutes')->format('H:i:s');
// 3. Récupération du nom du jour en anglais (Monday, Tuesday...)
$dayName = $now->format('l');
return $this->createQueryBuilder('ae')
->leftJoin('ae.agendaDay', 'd')
// Logique : l'heure actuelle (+/- 5min) doit être comprise entre le début et la fin du cours
->andWhere('TIME(ae.startAt) <= :plus5')
->andWhere('TIME(ae.endAt) >= :minus5')
->andWhere('ae.classe = :classe')
->andWhere('ae.school = :school')
->andWhere('ae.active = :active')
->andWhere('d.nameEn = :dayName')
->setParameters([
'plus5' => $startPlus5,
'minus5' => $startMinus5,
'classe' => $classe,
'school' => $school,
'active' => true,
'dayName' => $dayName
])
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
}
public function findNearStartAtByTeacherAndByClass(
User $prof,
TheClass $classe,
School $school,
): ?AgendaElement {
// 1. On fixe la Timezone pour tout le calcul
$tz = new \DateTimeZone('Africa/Douala');
$now = new \DateTime('now', $tz);
// 2. On récupère le nom du jour selon la Timezone de Douala
$dayName = $now->format('l');
// 3. On extrait uniquement l'heure pour la comparaison SQL TIME
// On utilise des chaînes de caractères "H:i:s" pour éviter les conflits de dates (1970 vs 2024)
$startPlus5 = (clone $now)->modify('+5 minutes')->format('H:i:s');
$startMinus5 = (clone $now)->modify('-5 minutes')->format('H:i:s');
return $this->createQueryBuilder('ae')
->leftJoin('ae.subject', 's')
->leftJoin('ae.agendaDay', 'd')
->andWhere('s.prof = :prof')
->andWhere('ae.school = :school')
->andWhere('ae.classe = :classe')
->andWhere('d.nameEn = :dayName')
// On utilise la fonction SQL TIME() pour ignorer la partie Date des colonnes
->andWhere('TIME(ae.startAt) <= :startPlus5')
->andWhere('TIME(ae.endAt) >= :startMinus5')
->andWhere('ae.active = :active')
->setParameters([
'prof' => $prof,
'school' => $school,
'classe' => $classe,
'dayName' => $dayName,
'startPlus5' => $startPlus5,
'startMinus5' => $startMinus5,
'active' => true,
])
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
}
public function findNearStartAtByTeacher(
User $prof,
School $school,
): ?array {
// 1. On fixe la Timezone pour tout le calcul
$tz = new \DateTimeZone('Africa/Douala');
$now = new \DateTime('now', $tz);
// 2. On récupère le nom du jour selon la Timezone de Douala
$dayName = $now->format('l');
// 3. On extrait uniquement l'heure pour la comparaison SQL TIME
// On utilise des chaînes de caractères "H:i:s" pour éviter les conflits de dates (1970 vs 2024)
$startPlus5 = (clone $now)->modify('+5 minutes')->format('H:i:s');
$startMinus5 = (clone $now)->modify('-5 minutes')->format('H:i:s');
return $this->createQueryBuilder('ae')
->leftJoin('ae.subject', 's')
->leftJoin('ae.agendaDay', 'd')
->andWhere('s.prof = :prof')
->andWhere('ae.school = :school')
->andWhere('d.nameEn = :dayName')
// On utilise la fonction SQL TIME() pour ignorer la partie Date des colonnes
->andWhere('TIME(ae.startAt) <= :startPlus5')
->andWhere('TIME(ae.endAt) >= :startMinus5')
->andWhere('ae.active = :active')
->setParameters([
'prof' => $prof,
'school' => $school,
'dayName' => $dayName,
'startPlus5' => $startPlus5,
'startMinus5' => $startMinus5,
'active' => true,
])
->getQuery()
->getResult();
}
public function findByIdAndByDayAndBySubjectAndBySartAtAndByEndAt($elementId = null, $dayOfWeek, $subjectId = null, $startAt, $endAt)
{
$qb = $this->createQueryBuilder('a')
->join('a.agendaDay', 'd')
->where('LOWER(d.nameEn) = :day')
->andWhere('a.startAt = :startAt') // Suppression de l'espace après :
->andWhere('a.endAt = :endAt') // Utilisation de andWhere
->setParameter('day', strtolower($dayOfWeek))
->setParameter('startAt', $startAt instanceof \DateTimeInterface ? $startAt->format('H:i:s') : $startAt)
->setParameter('endAt', $endAt instanceof \DateTimeInterface ? $endAt->format('H:i:s') : $endAt);
if (!empty($elementId)) {
$qb->andWhere('a.id = :id')
->setParameter('id', $elementId);
}
if (!empty($subjectId)) {
$qb->join('a.subject', 's')
->andWhere('s.id = :subjectId')
->setParameter('subjectId', $subjectId);
} else {
$qb->andWhere('a.subject IS NULL');
}
// IMPORTANT : On affecte le résultat à la variable
return $qb->getQuery()->getOneOrNullResult();
}
// /**
// * @return AgendaElement[] Returns an array of AgendaElement objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('a')
// ->andWhere('a.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('a.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?AgendaElement
// {
// return $this->createQueryBuilder('a')
// ->andWhere('a.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}