<?php
namespace App\EventSubscriber;
use CalendarBundle\CalendarEvents;
use CalendarBundle\Entity\Event;
use CalendarBundle\Event\CalendarEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\Security;
// Repositories
use App\Repository\Authorization\AssignmentRepository;
use App\Repository\Planning\BookingRepository;
use App\Repository\Planning\UnavailabilityRepository;
class CalendarSubscriber implements EventSubscriberInterface {
private AssignmentRepository $assignmentRepository;
private BookingRepository $bookingRepository;
private RequestStack $_requestStack;
private RoleHierarchyInterface $roleHierarchy;
private UnavailabilityRepository $unavailabilityRepository;
private UrlGeneratorInterface $router;
private Security $security;
/**
* Attribution des valeurs par défaut lors de la construction.
*
* @param AssignmentRepository $assignmentRepository Repository des associations.
* @param BookingRepository $bookingRepository Repository des planning.
* @param RequestStack $requestStack Stack de la requête.
* @param RoleHierarchyInterface $roleHierarchy Interface des hiérarchies des rôles.
* @param UnavailabilityRepository $unavailabilityRepository Repository des indisponibilité.
* @param UrlGeneratorInterface $router Interface de générateur URL.
* @param Security $security Sécurité de Symfony.
*/
public function __construct(
AssignmentRepository $assignmentRepository,
BookingRepository $bookingRepository,
RequestStack $requestStack,
RoleHierarchyInterface $roleHierarchy,
UnavailabilityRepository $unavailabilityRepository,
UrlGeneratorInterface $router,
Security $security
) {
$this->assignmentRepository = $assignmentRepository;
$this->bookingRepository = $bookingRepository;
$this->_requestStack = $requestStack;
$this->roleHierarchy = $roleHierarchy;
$this->unavailabilityRepository = $unavailabilityRepository;
$this->router = $router;
$this->security = $security;
}
/**
* Récupère les événements enregistrés et les affiches dans le calendrier
*
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
CalendarEvents::SET_DATA => 'onCalendarSetData',
];
}
/**
* Crée les événements sur l'intervalle de temps en cours sur le calendrier
*
* @var CalendarEvent $setDataEvent Evenement de calendrier contenant les périodes de temps affichés
* @return void
*/
public function onCalendarSetData(
CalendarEvent $setDataEvent
)
{
$bookings = [];
$start = $setDataEvent->getStart();
$end = $setDataEvent->getEnd();
// Nous vérifions les rôles de l'utilisateur actuellement connecté
$user = $this->security->getUser();
$userRoles = $this->roleHierarchy->getReachableRoleNames($user->getRoles());
//Etablissement de la requête de récupération de Booking
$query = $this->bookingRepository
->createQueryBuilder('booking')
->join('booking.establishment', 'establishment')
->where('booking.bookingStart BETWEEN :start AND :end OR booking.bookingEnd BETWEEN :start AND :end')
->setParameter('start', $start->format('Y-m-d H:i:s'))
->setParameter('end', $end->format('Y-m-d H:i:s'));
// Nous récupérons tous les Bookings si nous avons le rôle "ROLE_GESTION" ou plus
if (in_array("ROLE_GESTION", $userRoles)) {
$bookings = $query->getQuery()->getResult();
} else if (in_array("ROLE_PF_CFT", $userRoles)) {
// Sinon, si nous avons au moins le rôle "ROLE_PF_CFT", nous affichons tous les bookings liés à nos établissements
$userAssignments = $this->assignmentRepository->findActiveEstablishment($user);
$userEstablishments = [];
$i = 1;
foreach ($userAssignments as $userAssignment) {
$userEstablishments[$i] = $userAssignment->getEstablishment();
$i += 1;
}
$bookings = $query
->andWhere(('establishment IN (:userEstablishments)'))
->setParameter('userEstablishments', $userEstablishments)
->getQuery()->getResult();
}
$listGestion = [];
foreach ($bookings as $booking) {
$bookingEvent = new Event(
$booking->getLastname() . " " . $booking->getFirstname(),
$booking->getBookingStart(),
$booking->getBookingEnd() // If the end date is null or not defined, an all-day event is created.
);
if ($booking->getUser()) {
$user = $booking->getUser();
// Envoyer les couleurs via extendedProps
$bookingEvent->addOption('extendedProps', [
'userBackgroundColor' => $user->getBackgroundColor(),
'userBorderColor' => $user->getBorderColor(),
'userTextColor' => $user->getTextColor(),
'status' => $booking->getStatus() // Assurez-vous que $booking->getStatus() renvoie un statut valide (ex: 'validé', 'annulé', etc.)
]);
$userId = $user->getId();
// Vérifier si l'utilisateur est déjà dans le tableau
if (!array_key_exists($userId, $listGestion)) {
// Ajouter l'utilisateur dans le tableau avec son id comme clé
$listGestion[$userId] = [
'firstname' => $user->getFirstname(),
'lastname' => $user->getLastname(),
'background' => $user->getBackgroundColor(),
'border' => $user->getBorderColor(),
'color' => $user->getTextColor(),
];
}
} else {
// Envoyer les couleurs par défaut via extendedProps
$bookingEvent->addOption('extendedProps', [
'userBackgroundColor' => 'white',
'userBorderColor' => 'black',
'userTextColor' => 'black',
'status' => $booking->getStatus() // Assurez-vous que $booking->getStatus() renvoie un statut valide (ex: 'validé', 'annulé', etc.)
]);
}
// Ajout du statut dans extendedProps
// $bookingEvent->addOption('extendedProps', [
// 'status' => $booking->getStatus() // Assurez-vous que $booking->getStatus() renvoie un statut valide (ex: 'validé', 'annulé', etc.)
// ]);
$bookingEvent->addOption(
'url',
$this->router->generate('booking_view', [
'id' => $booking->getId(),
])
);
// Add the event to the CalendarEvent to fill the calendar
$setDataEvent->addEvent($bookingEvent);
}
// Stocke le tableau $listGestion dans la session
$this->_requestStack->getSession()->set('listGestion', $listGestion);
if (in_array("ROLE_GESTION", $userRoles)) {
// Ajout des événements d'indisponibilités
$unavailabilities = $this->unavailabilityRepository
->createQueryBuilder('unavailability')
->where('(unavailability.unavailabilityStart BETWEEN :start AND :end)
OR (unavailability.unavailabilityEnd BETWEEN :start AND :end)
OR (:start BETWEEN unavailability.unavailabilityStart AND unavailability.unavailabilityEnd)')
->setParameter('start', $start->format('Y-m-d H:i:s'))
->setParameter('end', $end->format('Y-m-d H:i:s'))
->getQuery()->getResult();
foreach ($unavailabilities as $unavailability) {
$startDate = $unavailability->getUnavailabilityStart();
$endDate = $unavailability->getUnavailabilityEnd();
$unavailabilityEvent = new Event(
$unavailability->getUnavailabilityTitle(),
$startDate,
$endDate
);
// Add custom options to events
$unavailabilityEvent->setOptions([
// 'backgroundColor' => 'gray',
// 'borderColor' => 'gray',
// 'display' => 'flex',
'classNames' => ['custom-unavailability']
]);
$unavailabilityEvent->addOption(
'url',
$this->router->generate('unavailability_view', [
'id' => $unavailability->getId(),
])
);
// Add the event to the CalendarEvent to fill the calendar
$setDataEvent->addEvent($unavailabilityEvent);
}
}
}
}