2026-06-11 19:03:29 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use Reservair\Logger\Logger;
|
|
|
|
|
|
|
|
|
|
class RsvTimetableService {
|
|
|
|
|
private RsvTimetableRepository $repo;
|
|
|
|
|
|
|
|
|
|
public function __construct() {
|
|
|
|
|
$this->repo = new RsvTimetableRepository();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function get_all(?int $limit = null, int $skip = 0): array {
|
|
|
|
|
return $this->repo->get_all($limit, $skip);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function count_all(): int {
|
|
|
|
|
return $this->repo->count_all();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function get(int $id): ?RsvTimetable {
|
|
|
|
|
return $this->repo->get($id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function create(RsvTimetable $timetable): int {
|
|
|
|
|
return $this->repo->create($timetable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function update(int $id, RsvTimetable $timetable): int {
|
|
|
|
|
return $this->repo->update($id, $timetable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function get_all_maintainer_emails(): array {
|
|
|
|
|
return $this->repo->get_all_maintainer_emails();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function set_google_calendar_id(int $id, ?string $calendar_id): void {
|
|
|
|
|
$this->repo->set_google_calendar_id($id, $calendar_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function delete(int $id): int {
|
|
|
|
|
Logger::info('Deleting timetable: ' . $id);
|
|
|
|
|
return $this->repo->delete($id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function datetime_to_minutes(DateTime $dt): int {
|
|
|
|
|
$d = $dt->setTimezone(wp_timezone());
|
|
|
|
|
return (int) $d->format('G') * 60 + (int) $d->format('i');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return array<int,RsvTimetableAvailability> Availability on date
|
|
|
|
|
*/
|
|
|
|
|
public function get_availability_on_date(int $timetable_id, int $block_length, DateTime $date) : array {
|
|
|
|
|
/**
|
|
|
|
|
* Get available seats for the given date
|
|
|
|
|
* Keeps two stacks: capacities & reservations
|
|
|
|
|
*
|
|
|
|
|
* Goes from left to right in reservations and pushes to stack
|
|
|
|
|
*/
|
|
|
|
|
$capacities = (new RsvTimetableCapacityRepository())->get_capacities_for_date($timetable_id, $date);
|
|
|
|
|
$reservations = (new RsvTimetableReservationService())->get_reservations_on_date($timetable_id, $date);
|
|
|
|
|
|
|
|
|
|
$capacity_stack = [];
|
|
|
|
|
$reservation_stack = [];
|
|
|
|
|
|
|
|
|
|
$capacity_index = 0;
|
|
|
|
|
$reservation_index = 0;
|
|
|
|
|
|
|
|
|
|
$blocks_count = 24 * 60 / $block_length;
|
|
|
|
|
$blocks = array_fill(0, $blocks_count, 0);
|
|
|
|
|
|
|
|
|
|
$availabilities = [];
|
|
|
|
|
$availability_idx = 0;
|
|
|
|
|
|
|
|
|
|
for($i = 0; $i < $blocks_count; $i++) {
|
|
|
|
|
$reservation_stack = array_filter($reservation_stack, fn($reservation) =>
|
|
|
|
|
$this->datetime_to_minutes($reservation->end_utc) > $i * $block_length
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$capacity_stack = array_filter($capacity_stack, fn($capacity) =>
|
|
|
|
|
$capacity->end_time > $i * $block_length
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
while($reservation_index < count($reservations) && $this->datetime_to_minutes($reservations[$reservation_index]->start_utc) <= $i * $block_length) {
|
|
|
|
|
$reservation_stack[] = $reservations[$reservation_index];
|
|
|
|
|
$reservation_index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while($capacity_index < count($capacities) && $capacities[$capacity_index]->start_time <= $i * $block_length) {
|
|
|
|
|
$capacity_stack[] = $capacities[$capacity_index];
|
|
|
|
|
$capacity_index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$total_capacity = array_sum(array_map(fn($x) => $x->capacity, $capacity_stack));
|
|
|
|
|
|
|
|
|
|
if ($total_capacity > 0) {
|
|
|
|
|
if(count($availabilities) === $availability_idx) {
|
|
|
|
|
$availabilities[] = new RsvTimetableAvailability($i * $block_length, ($i + 1) * $block_length, $block_length, []);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-14 10:01:24 +02:00
|
|
|
$max_lead_time = empty($capacity_stack) ? 0 : max(array_map(fn($x) => $x->min_lead_time_minutes, $capacity_stack));
|
|
|
|
|
$availabilities[$availability_idx]->push_block($total_capacity - count($reservation_stack), $max_lead_time);
|
2026-06-11 19:03:29 +02:00
|
|
|
} else if($total_capacity === 0 && count($availabilities) !== $availability_idx) {
|
|
|
|
|
$availability_idx++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $availabilities;
|
|
|
|
|
}
|
|
|
|
|
}
|