Deprecated: Constant E_STRICT is deprecated in /home/pastorz/old-espace-client/vendor/symfony/error-handler/ErrorHandler.php on line 58

Deprecated: Constant E_STRICT is deprecated in /home/pastorz/old-espace-client/vendor/symfony/error-handler/ErrorHandler.php on line 76
Symfony Profiler

src/Service/EstimationBookingService.php line 141

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Entity\Booking;
  4. use App\Entity\BookingConfig;
  5. use App\Entity\BookingConfigDate;
  6. use App\Entity\BookingConfigHour;
  7. use App\Entity\EstimationRequest;
  8. use DateInterval;
  9. use DatePeriod;
  10. use DateTime;
  11. use DateTimeInterface;
  12. use Doctrine\Common\Collections\ArrayCollection;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use Exception;
  15. class EstimationBookingService
  16. {
  17.     private EntityManagerInterface $em;
  18.     private BookingConfig $config;
  19.     private int $slotLength;
  20.     private array $days;
  21.     /**
  22.      * @param EntityManagerInterface $em
  23.      */
  24.     public function __construct(EntityManagerInterface $em)
  25.     {
  26.         $this->em $em;
  27.         $this->config $this->getConfig();
  28.         $this->slotLength $this->config->getSlotLength();
  29.         $this->days array_map(fn(BookingConfigHour $hour) => $hour->getDay(), $this->em->getRepository(BookingConfigHour::class)->findBy(['bookingConfig' => $this->config], ['day' => 'ASC']));
  30.     }
  31.     public function getConfig()
  32.     {
  33.         return $this->em->getRepository(BookingConfig::class)->findOneByType('estimation');
  34.     }
  35.     public function getDay(DateTimeInterface $date): ?BookingConfigHour
  36.     {
  37.         return $this->em->getRepository(BookingConfigHour::class)->findOneBy(['bookingConfig' => $this->config'day' => $date->format('N')]);
  38.     }
  39.     public function check(Booking $booking): bool
  40.     {
  41.         return $this->getSlots($booking->getDate(), $booking->getEstimationRequest())
  42.             ->filter(fn(array $slot) => $slot['enable'])
  43.             ->map(fn(array $slot) => $slot['datetime']->format('H:i'))
  44.             ->contains($booking->getTime()->format('H:i'));
  45.     }
  46.     /**
  47.      * @param DateTimeInterface $date
  48.      * @param EstimationRequest|null $estimationRequest
  49.      * @return ArrayCollection
  50.      */
  51.     public function getSlots(DateTimeInterface $dateEstimationRequest $estimationRequest null): ArrayCollection
  52.     {
  53.         $this->cleanBookings();
  54.         $day $this->getDay($date);
  55.         if (!$day) {
  56.             return new ArrayCollection();
  57.         }
  58.         $slots = array();
  59.         $now = new DateTime();
  60.         $startMorningHour = (clone $date)->setTime($day->getMorningStart()->format('H'), $day->getMorningStart()->format('i'));
  61.         $endMorningHour = (clone $date)->setTime($day->getMorningEnd()->format('H'), $day->getMorningEnd()->format('i'));
  62.         $startAfternoonHour = (clone $date)->setTime($day->getAfternoonStart()->format('H'), $day->getAfternoonStart()->format('i'));
  63.         $endAfternoonHour = (clone $date)->setTime($day->getAfternoonEnd()->format('H'), $day->getAfternoonEnd()->format('i'));
  64.         $startHour max($now$startMorningHour);
  65.         $period = new DatePeriod($startMorningHourDateInterval::createFromDateString($this->slotLength ' minutes'), $endAfternoonHour);
  66.         foreach ($period as $dt) {
  67.             if ($dt > (clone $endMorningHour)->modify('-' $this->slotLength ' minutes') && $dt $startAfternoonHour) {
  68.                 continue;
  69.             }
  70.             $dtEnable $dt >= $startHour && $this->isAvailable($dt);
  71.             if ($estimationRequest && !$this->isBooked($dt$estimationRequest) && $estimationRequest->getBooking() && $estimationRequest->getBooking()->bookingDateTime($dt)) {
  72.                 $dtEnable true;
  73.             }
  74.             $slots[] = array(
  75.                 'datetime' => $dt,
  76.                 'enable' => $dtEnable
  77.             );
  78.         }
  79.         return new ArrayCollection($slots);
  80.     }
  81.     public function cleanBookings()
  82.     {
  83.         $this->em->getRepository(Booking::class)->createQueryBuilder('b')
  84.             ->delete()
  85.             ->where('b.confirmed = 0')
  86.             ->andWhere('b.updatedAt < :datetime')
  87.             ->setParameter('datetime', (new DateTime())->modify('-30 minutes'))
  88.             ->getQuery()->getResult();
  89.     }
  90.     public function isAvailable(DateTimeInterface $dt): bool
  91.     {
  92.         return !$this->isBooked($dt) && !$this->getExcludedSlotsOfDay($dt)->contains($dt->format(DateTimeInterface::ATOM));
  93.     }
  94.     public function isBooked(DateTimeInterface $dt, ?EstimationRequest $estimationRequest null): bool
  95.     {
  96.         $qb $this->em->getRepository(Booking::class)->createQueryBuilder('b')
  97.             ->where('b.date = :date')
  98.             ->andWhere('b.time = :time')
  99.             ->andWhere('b.bookingConfig = :bookingConfig')
  100.             ->setParameter('date'$dt->format('Y-m-d'))
  101.             ->setParameter('time'$dt->format('H:i:s'))
  102.             ->setParameter('bookingConfig'$this->config);
  103.         if ($estimationRequest) {
  104.             $qb->andWhere('b.estimationRequest != :estimationRequest')
  105.                 ->setParameter('estimationRequest'$estimationRequest->getId());
  106.         }
  107.         return !empty($qb->getQuery()->getResult());
  108.     }
  109.     public function getExcludedSlotsOfDay(DateTimeInterface $date null): ArrayCollection
  110.     {
  111.         $excludedSlots = new ArrayCollection();
  112.         foreach ($this->config->getExcludeDates() as $excludedDate) {
  113.             if ($excludedDate->getDateEnd() && $excludedDate->getDateStart()->format('Y-m-d') == $excludedDate->getDateEnd()->format('Y-m-d')) {
  114.                 $period = new DatePeriod($excludedDate->getDateStart(), DateInterval::createFromDateString($this->slotLength ' minutes'), $excludedDate->getDateEnd());
  115.                 foreach ($period as $dt) {
  116.                     $excludedSlots->add($dt->format(DateTimeInterface::ATOM));
  117.                 }
  118.             }
  119.         }
  120.         if ($date) {
  121.             foreach ($this->config->getExcludeSlots() as $excludedSlot) {
  122.                 if ($excludedSlot->getDay() == $date->format('N')) {
  123.                     $timeStart = (clone $date)->setTime($excludedSlot->getTimeStart()->format('H'), $excludedSlot->getTimeStart()->format('i'));
  124.                     $timeEnd = (clone $date)->setTime($excludedSlot->getTimeEnd()->format('H'), $excludedSlot->getTimeEnd()->format('i'));
  125.                     $period = new DatePeriod($timeStartDateInterval::createFromDateString($this->slotLength ' minutes'), $timeEnd);
  126.                     foreach ($period as $dt) {
  127.                         $excludedSlots->add($dt->format(DateTimeInterface::ATOM));
  128.                     }
  129.                 }
  130.             }
  131.             $period = new DatePeriod($this->getClosestsSlot(new DateTime()), DateInterval::createFromDateString($this->slotLength ' minutes'), (new DateTime())->modify('+3 hours'));
  132.             foreach ($period as $dt) {
  133.                 $excludedSlots->add($dt->format(DateTimeInterface::ATOM));
  134.             }
  135.         }
  136.         return $excludedSlots;
  137.     }
  138.     public function getClosestsSlot(DateTimeInterface $dt): DateTimeInterface
  139.     {
  140.         $minutes $dt->format('i');
  141.         $dt->setTime($dt->format('H'), $minutes);
  142.         $minutes $minutes round($minutes 10) * 10;
  143.         return $dt->modify('-' $minutes ' minutes');
  144.     }
  145.     /**
  146.      * @throws Exception
  147.      */
  148.     public function getExcludedDates(?EstimationRequest $estimationRequest null): ArrayCollection
  149.     {
  150.         $excludedDates = new ArrayCollection();
  151.         foreach ($this->config->getExcludeDates() as $excludedDate) {
  152.             if (!$excludedDate->getDateEnd()) {
  153.                 $excludedDates->add($excludedDate->getDateStart()->format(DateTimeInterface::ATOM));
  154.                 continue;
  155.             }
  156.             if ($excludedDate->getDateStart()->format('Y-m-d') == $excludedDate->getDateEnd()->format('Y-m-d')) {
  157.                 continue;
  158.             }
  159.             $period = new DatePeriod($excludedDate->getDateStart(), DateInterval::createFromDateString("1 day"), $excludedDate->getDateEnd()->modify('+1 day'));
  160.             foreach ($period as $dt) {
  161.                 $excludedDates->add($dt->format(DateTimeInterface::ATOM));
  162.             }
  163.         }
  164.         if (($firstSlot = new DateTime($this->firstAvailableSlot($estimationRequest)))->setTime(00)->format('Y-m-d') != ($now = new DateTime())->setTime(00)->format('Y-m-d')) {
  165.             $period = new DatePeriod($nowDateInterval::createFromDateString("1 day"), $firstSlot);
  166.             foreach ($period as $dt) {
  167.                 $excludedDates->add($dt->format(DateTimeInterface::ATOM));
  168.             }
  169.         }
  170.         return $excludedDates;
  171.     }
  172.     /**
  173.      * @throws Exception
  174.      */
  175.     public function firstAvailableSlot(?EstimationRequest $estimationRequest null): ?string
  176.     {
  177.         $date = new DateTime();
  178.         if ($estimationRequest && $estimationRequest->getBooking() && !$estimationRequest->getBooking()->isExpired()) {
  179.             if ($estimationRequest->getBooking()->isConfirmed()) {
  180.                 $date $estimationRequest->getBooking()->getSlot();
  181.             }
  182.             if ($history $estimationRequest->getBooking()->getHistory()) {
  183.                 $date = new DateTime(end($history));
  184.             }
  185.         }
  186.         $periodStart /*$date->format('Y-m-d') == (new DateTime())->format('Y-m-d') ? $date->modify('+3 hours') :*/
  187.             $date;
  188.         $period = new DatePeriod($periodStartDateInterval::createFromDateString("1 day"), (new DateTime())->modify('+1 year'));
  189.         $excludedDates $this->config->getExcludeDates();
  190.         $excludedDates $excludedDates->filter(fn(BookingConfigDate $configDate) => !$configDate->getDateEnd())
  191.             ->map(fn(BookingConfigDate $configDate) => $configDate->getDateStart()->format(DateTimeInterface::ATOM));
  192.         foreach ($period as $dt) {
  193.             $dt->setTime(00);
  194.             if ($excludedDates->contains($dt->format(DateTimeInterface::ATOM))) {
  195.                 continue;
  196.             }
  197.             $slots $this->getSlots($dt)->filter(fn(array $slot) => $slot['enable'] === true);
  198.             if (!$slots->isEmpty()) {
  199.                 return $slots->first()['datetime']->format(DateTimeInterface::ATOM);
  200.             }
  201.         }
  202.         return null;
  203.     }
  204.     public function getExcludedDays(): array
  205.     {
  206.         return array_diff(array_keys(BookingConfigHour::DAYS_OF_WEEK), $this->days);
  207.     }
  208.     /**
  209.      * @param EstimationRequest $estimationRequest
  210.      * @return bool
  211.      */
  212.     public function canBook(EstimationRequest $estimationRequest): bool
  213.     {
  214.         if ($estimationRequest->getBooking() && $estimationRequest->getBooking()->isConfirmed()) {
  215.             return $estimationRequest->getBooking()->getDate()->format('Y-m-d') >= (new DateTime())->format('Y-m-d');
  216.         }
  217.         return true;
  218.     }
  219. }