* * @since 0.1.0 */ public function assert_cancellable( Booking $booking, DateTimeImmutable $now ): Result { if ( ! $booking->occupies_slot() ) { return Result::err( 'booking.not_cancellable', 'Booking is not in a cancellable state.' ); } if ( $this->cancel_window_hours > 0 ) { $deadline = $booking->start_utc()->modify( '-' . $this->cancel_window_hours . ' hours' ); if ( $now > $deadline ) { return Result::err( 'booking.cancel_window', 'Cancellation window has closed.' ); } } return Result::ok( null ); } /** * Whether reschedule is permitted. * * @param Booking $booking Booking. * @param DateTimeImmutable $now Instant UTC. * @return Result * * @since 0.1.0 */ public function assert_reschedulable( Booking $booking, DateTimeImmutable $now ): Result { if ( ! $booking->occupies_slot() ) { return Result::err( 'booking.not_reschedulable', 'Booking is not in a reschedulable state.' ); } if ( $this->reschedule_window_hours > 0 ) { $deadline = $booking->start_utc()->modify( '-' . $this->reschedule_window_hours . ' hours' ); if ( $now > $deadline ) { return Result::err( 'booking.reschedule_window', 'Reschedule window has closed.' ); } } return Result::ok( null ); } }