I would like to be able to fix the start times of booking blocks, so rather than it being an hour from the next available minute, it’s an hour from a fixed collection of times, such as 10am, 12pm, 2pm etc.
I have already amended the code to make this work for my particular case, using the following changes:
/includes/data-objects/class-wc-product-booking.php
function get_bookable_minute_blocks_for_date()
Just before this line:
// Loop ranges looking for slots within
foreach ( $bookable_ranges as $minutes ) {
I add the line:
$allowed_minutes = array(480,600,720,840,960);
This is an array of the minutes to start bookings from (8am,10am,12pm…).
Within the foreach loop I add the following:
foreach($allowed_minutes as $range_minute_check) {
if ($range_start > $range_minute_check) {
continue;
}
else {
if ($minutes[1] <= $range_minute_check) {
continue 2;
}
$range_start = $range_minute_check;
break;
}
}
That whole function now looks like this:
protected function get_bookable_minute_blocks_for_date( $check_date, $start_date, $end_date, $bookable_ranges, $intervals, $resource_id, $minutes_not_available, $get_past_times = false ) {
// blocks as in an array of slots. $slot_start_times
$blocks = array();
// boring interval stuff
$interval = $intervals[0];
$base_interval = $intervals[1];
// get a time stamp to check from
// and get a time stamp to check to
$product_min_date = $this->get_min_date();
$product_max_date = $this->get_max_date();
$min_check_from = strtotime( “+{$product_min_date[‘value’]} {$product_min_date[‘unit’]}”, current_time( ‘timestamp’ ) );
$max_check_to = strtotime( “+{$product_max_date[‘value’]} {$product_max_date[‘unit’]}”, current_time( ‘timestamp’ ) );
$min_date = wc_bookings_get_min_timestamp_for_day( $start_date, $product_min_date[‘value’], $product_min_date[‘unit’] );
$available_qty = $this->get_available_quantity( $resource_id );
$current_time_stamp = current_time( ‘timestamp’ );
$availability = $this->get_default_availability();
// if we have a buffer, we will shift all times accordingly by changing the from_interval
// e.g. 60 min buffer shifts [ 480, 600, 720 ] into [ 480, 660, 840 ]
$buffer = $this->get_buffer_period_minutes() ?: 0;
// if adjacency is enabled, multiply the buffer by 2 (see https://woocommerce.com/document/creating-a-bookable-product/#section-8)
if ( $this->get_apply_adjacent_buffer() ) {
$buffer *= 2;
}
//START AMPERSAND ADDITION
$allowed_minutes = array(480,600,720,840,960);
//END AMPERSAND ADDITION
// Loop ranges looking for slots within
foreach ( $bookable_ranges as $minutes ) {
$range_start = $minutes[0];
//START AMPERSAND ADDITION
foreach($allowed_minutes as $range_minute_check) {
if ($range_start > $range_minute_check) {
continue;
}
else {
if ($minutes[1] <= $range_minute_check) {
continue 2;
}
$range_start = $range_minute_check;
break;
}
}
//END AMPERSAND ADDITION
$range_end = $minutes[1];
if ( 'hour' === $this->get_duration_unit() ) {
// Adding 1 minute to round up to a full hour.
$range_end += 1;
}
$range_start_time = strtotime( “midnight +{$range_start} minutes”, $check_date );
$range_end_time = strtotime( “midnight +{$range_end} minutes”, $check_date );
$minutes_for_range = $range_end – $range_start;
$base_intervals_in_block = floor( $minutes_for_range / $base_interval );
for ( $i = 0; $i <= $base_intervals_in_block; $i ++ ) {
$from_interval = $i * ( $base_interval + $buffer );
$to_interval = $from_interval + $interval + $buffer;
$to_interval_no_buffer = $from_interval + $interval;
$start_time = strtotime( "+{$from_interval} minutes", $range_start_time );
$end_time = strtotime( "+{$to_interval} minutes", $range_start_time );
$end_time_no_buffer = strtotime( "+{$to_interval_no_buffer} minutes", $range_start_time );
// Break if start time is after the end date being calculated.
if ( $start_time > $end_date ) {
break 2;
}
// Must be in the future
if ( ( $start_time < $min_date || $start_time <= $current_time_stamp ) && ! $get_past_times ) {
continue;
}
$interval_not_bookable = false;
// Check if any minute of block is not within not available minutes.
for ( $t = $start_time; $t < $end_time; $t += 60 ) {
if ( isset( $minutes_not_available[ $t ] ) && $minutes_not_available[ $t ] >= $available_qty ) {
$interval_not_bookable = true;
break;
}
}
if ( $interval_not_bookable ) {
continue;
}
// Make sure minute & hour blocks are not past minimum & max booking settings.
if ( ( $end_time < $min_check_from || $start_time > $max_check_to ) && ! $get_past_times ) {
continue;
}
/*
* We check only if the booking time will fit.
* We should check with buffer time added but unfortunatelly doing this will cause a regression.
* Time slots at the end of the day with buffers going over the day end will not be present.
*/
if ( $end_time_no_buffer > $range_end_time ) {
continue;
}
// Make sure slot doesn’t start after the end date.
if ( $start_time > $end_date ) {
continue;
}
/*
* If default availability is NO/False then it means the minutes we’re looking at has already been
* generated by using the rules so there’s no need to test availability again.
*/
if ( $availability
&& ! WC_Product_Booking_Rule_Manager::check_availability_rules_against_time( $start_time, $end_time, $resource_id, $this, $availability ) ) {
continue;
}
if ( ! in_array( $start_time, $blocks ) ) {
$blocks[] = $start_time;
}
}
}
return $blocks;
}
If this could somehow be integrated as an option it woul save me editing the core files each time and no doubt help others with this additional flexibility.
Thanks
Open
Last updated: May 29, 2020
0 comments
Log in to comment on this feature request.