$overlapping Locked overlapping bookings. * @param DateTimeImmutable $start_utc Proposed start. * @param int $service_id Proposed service. * @param int $attendees Requested attendees. * @param int $capacity_max Service capacity_max. * @param int|null $exclude_id Optional booking to ignore (reschedule). * * @since 0.1.0 */ public function is_taken( array $overlapping, DateTimeImmutable $start_utc, int $service_id, int $attendees, int $capacity_max, ?int $exclude_id = null, ): bool { if ( $capacity_max < 1 ) { return true; } if ( 1 === $capacity_max ) { foreach ( $overlapping as $existing ) { if ( null !== $exclude_id && $existing->id() === $exclude_id ) { continue; } if ( ! $existing->occupies_slot() ) { continue; } return true; } return false; } $used = 0; foreach ( $overlapping as $existing ) { if ( null !== $exclude_id && $existing->id() === $exclude_id ) { continue; } if ( ! $existing->occupies_slot() ) { continue; } if ( $existing->service_id() !== $service_id ) { // Different service overlapping the buffer blocks entirely for group slots. return true; } if ( $existing->start_utc()->getTimestamp() !== $start_utc->getTimestamp() ) { return true; } $used += $existing->attendees(); } return ( $used + $attendees ) > $capacity_max; } }