From a5b526c5a34934a5d4d608a51ecb3e21a3db61e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Wed, 10 Jun 2026 14:22:48 +0200 Subject: [PATCH] feat: integrate with new bpn-connect api for ical feeds --- .../Classes/Service/IcalService.php | 167 ++++++++---------- 1 file changed, 69 insertions(+), 98 deletions(-) diff --git a/public/typo3conf/ext/ep_products/Classes/Service/IcalService.php b/public/typo3conf/ext/ep_products/Classes/Service/IcalService.php index be97b8a1..869c3af6 100644 --- a/public/typo3conf/ext/ep_products/Classes/Service/IcalService.php +++ b/public/typo3conf/ext/ep_products/Classes/Service/IcalService.php @@ -1,4 +1,5 @@ contingentRepository = $contingentRepository; + $this->apiClient = $apiClient; } /** @@ -60,90 +61,73 @@ class IcalService implements SingletonInterface */ public function createContingentsFeed(Hotel $hotel): string { - $now = new \DateTime('now'); - try { - $events = $this->contingentRepository->getEvents( - $now, - null, - ['hotel' => $hotel] - ); - } - catch (DBALException $e) { - $events = []; + $calendarRows = []; + $hotelCode = trim((string) $hotel->getCode()); + + if ($hotelCode !== '') { + $dateFrom = new \DateTimeImmutable('today'); + $dateTo = $dateFrom->add(new \DateInterval(self::FEED_HORIZON))->sub(new \DateInterval('P1D')); + + try { + $calendar = $this->apiClient->getCalendar($hotelCode, $dateFrom, $dateTo); + $calendarRows = isset($calendar['data']) && is_array($calendar['data']) ? $calendar['data'] : []; + } catch (\Throwable $e) { + $calendarRows = []; + } } $this->createCalendarInstance(); - - $this->generateOccupancyItems($events); - $this->generateBlockedItems($events); + $this->generateUnavailableItems($calendarRows); try { - $feed = $this->vcalendar->vtimezonePopulate()->createCalendar(); - } - catch (\Exception $e) { - $feed = ''; - } - - return $feed; - } - - /** - * @param array $events - */ - protected function generateOccupancyItems(array $events): void - { - $occupancy = null; - - foreach ($events as $event) { - /** @var Contingent $event */ - if (null === $occupancy) { - $item = [ - 'from' => $event->getBegin(), - 'occupancy' => $event->getOccupancy(), - ]; - } elseif ($occupancy !== $event->getOccupancy()) { - $item['to'] = $event->getEnd(); - $this->addOccupancyItem($item); - $item = [ - 'from' => $event->getBegin(), - 'occupancy' => $event->getOccupancy(), - ]; - } - - $occupancy = $event->getOccupancy(); - } - - if (isset($event) && !isset($item['to'])) { - $item['to'] = $event->getEnd(); - $this->addOccupancyItem($item); + return $this->vcalendar->vtimezonePopulate()->createCalendar(); + } catch (\Exception $e) { + return ''; } } /** - * @param array $events + * @param array $calendarRows */ - protected function generateBlockedItems(array $events): void + protected function generateUnavailableItems(array $calendarRows): void { - $item = null; + usort($calendarRows, function (array $left, array $right): int { + return strcmp((string) ($left['date'] ?? ''), (string) ($right['date'] ?? '')); + }); - foreach ($events as $event) { - /** @var Contingent $event */ - $isBlocked = Contingent::STATUS_BLOCKED === $event->getStatus() || Contingent::STATUS_ONREQUEST === $event->getStatus(); - $isUnavailable = 0 === $event->getAvailable(); - if (null === $item && ($isBlocked || $isUnavailable)) { - $item = [ - 'from' => $event->getBegin(), - ]; - } elseif (true === is_array($item) && Contingent::STATUS_OK === $event->getStatus()) { - $item['to'] = $event->getEnd(); - $this->addBlockedItem($item); - $item = null; + $blockStart = null; + $lastDate = null; + + foreach ($calendarRows as $row) { + if (!isset($row['date'])) { + continue; + } + + $date = new \DateTimeImmutable($row['date']); + $lastDate = $date; + + if ($this->isUnavailableStatus($row['status'] ?? 'OK')) { + if (null === $blockStart) { + $blockStart = $date; + } + + continue; + } + + if (null !== $blockStart) { + $this->addBlockedItem([ + 'from' => $blockStart, + 'to' => $date, + ]); + $blockStart = null; } } - if (isset($event) && null !== $item && !isset($item['to'])) { - $item['to'] = $event->getEnd(); - $this->addBlockedItem($item); + if (null !== $blockStart && null !== $lastDate) { + $this->addBlockedItem([ + 'from' => $blockStart, + 'to' => $lastDate->add(new \DateInterval('P1D')), + ]); } } @@ -157,34 +141,21 @@ class IcalService implements SingletonInterface ->newVevent() ->setDtstart($item['from']) ->setDtend($item['to']) - ->setSummary('Unavailable') + ->setSummary(self::SUMMARY_UNAVAILABLE) ; - } - catch (\Exception $e) { + } catch (\Exception $e) { } } /** - * @param array $item + * @param mixed $status + * @return bool */ - protected function addOccupancyItem(array $item): void + protected function isUnavailableStatus($status): bool { - if (0 === $item['occupancy']) { - return; - } + $status = strtoupper(trim((string) $status)); - $summary = sprintf('Part-occupied:%d', $item['occupancy']); - - try { - $this->vcalendar - ->newVevent() - ->setDtstart($item['from']) - ->setDtend($item['to']) - ->setSummary($summary) - ; - } - catch (\Exception $e) { - } + return in_array($status, [ 'BLOCKED', 'ON_REQUEST', 'ONREQUEST' ], true); } protected function createCalendarInstance(): void