Last active
December 8, 2015 08:07
-
-
Save apkoponen/ef66524fa666a24e0b33 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/includes/admin/class-wc-bookings-admin.php b/includes/admin/class-wc-bookings-admin.php | |
| index ca679ca..7c5fd38 100644 | |
| --- a/includes/admin/class-wc-bookings-admin.php | |
| +++ b/includes/admin/class-wc-bookings-admin.php | |
| @@ -28,6 +28,8 @@ class WC_Bookings_Admin { | |
| add_action( 'woocommerce_product_options_general_product_data', array( $this, 'booking_data' ) ); | |
| add_filter( 'product_type_options', array( $this, 'booking_product_type_options' ) ); | |
| add_action( 'load-options-general.php', array( $this, 'reset_ics_exporter_timezone_cache' ) ); | |
| + add_action( 'update_option', array($this, 'update_global_booking_availability'), 10, 3 ); // wc_global_booking_availability do_action( 'updated_option', $option, $old_value, $value ); | |
| + add_action( 'update_postmeta', array($this, 'update_booking_availablity'), 10, 4 ); // do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value ); _wc_booking_availability | |
| // Ajax | |
| add_action( 'wp_ajax_woocommerce_add_bookable_resource', array( $this, 'add_bookable_resource' ) ); | |
| @@ -709,6 +711,31 @@ class WC_Bookings_Admin { | |
| wp_cache_delete( 'wc_bookings_timezone_string' ); | |
| } | |
| } | |
| + | |
| + /** | |
| + * @VALU | |
| + * Flush saved minute blocks if global booking availability rules have changed. | |
| + */ | |
| + public function update_global_booking_availability($option, $old_value, $value ) { | |
| + if($option === 'wc_global_booking_availability') { | |
| + if($old_value !== $value) { | |
| + global $wpdb; | |
| + $wpdb->query("DELETE FROM " . $wpdb->postmeta . " WHERE meta_key = '_wc_booking_bookable_minute_blocks'"); | |
| + } | |
| + } | |
| + } | |
| + | |
| + /** | |
| + * @VALU | |
| + * Flush saved minute blocks if product or resource availability rules have changed. | |
| + */ | |
| + public function update_booking_availablity($meta_id, $object_id, $meta_key, $meta_value) { | |
| + if($meta_key === '_wc_booking_availability') { | |
| + if($meta_value !== get_post_meta($object_id, '_wc_booking_availability')) { | |
| + delete_post_meta($object_id, '_wc_booking_bookable_minute_blocks'); | |
| + } | |
| + } | |
| + } | |
| } | |
| new WC_Bookings_Admin(); | |
| diff --git a/includes/booking-form/class-wc-booking-form-date-picker.php b/includes/booking-form/class-wc-booking-form-date-picker.php | |
| old mode 100755 | |
| new mode 100644 | |
| index ff1cb9a..ec8aaf5 | |
| --- a/includes/booking-form/class-wc-booking-form-date-picker.php | |
| +++ b/includes/booking-form/class-wc-booking-form-date-picker.php | |
| @@ -111,6 +111,12 @@ class WC_Booking_Form_Date_Picker extends WC_Booking_Form_Picker { | |
| $fully_booked_days[ date( 'Y-n-j' ) ][0] = true; | |
| } | |
| + //@VALU Initialize times | |
| + $current_time = current_time( 'timestamp' ); | |
| + $strtotimes_ar = array( | |
| + "+1 day" => strtotime("+1 day", 0) | |
| + ); | |
| + | |
| // Use the existing bookings to find days which are fully booked | |
| foreach ( $existing_bookings as $existing_booking ) { | |
| $start_date = $existing_booking->start; | |
| @@ -122,8 +128,8 @@ class WC_Booking_Form_Date_Picker extends WC_Booking_Form_Picker { | |
| while ( $check_date < $end_date ) { | |
| $js_date = date( 'Y-n-j', $check_date ); | |
| - if ( $check_date < current_time( 'timestamp' ) ) { | |
| - $check_date = strtotime( "+1 day", $check_date ); | |
| + if ( $check_date < $current_time ) { | |
| + $check_date = $strtotimes_ar["+1 day"] + $check_date; | |
| continue; | |
| } | |
| @@ -131,7 +137,7 @@ class WC_Booking_Form_Date_Picker extends WC_Booking_Form_Picker { | |
| // Skip if we've already found this resource is unavailable | |
| if ( ! empty( $fully_booked_days[ $js_date ][ $resource_id ] ) ) { | |
| - $check_date = strtotime( "+1 day", $check_date ); | |
| + $check_date = $strtotimes_ar["+1 day"] + $check_date; | |
| continue; | |
| } | |
| @@ -158,7 +164,7 @@ class WC_Booking_Form_Date_Picker extends WC_Booking_Form_Picker { | |
| // Skip if we've already found this product is unavailable | |
| if ( ! empty( $fully_booked_days[ $js_date ] ) ) { | |
| - $check_date = strtotime( "+1 day", $check_date ); | |
| + $check_date = $strtotimes_ar["+1 day"] + $check_date; | |
| continue; | |
| } | |
| @@ -173,11 +179,11 @@ class WC_Booking_Form_Date_Picker extends WC_Booking_Form_Picker { | |
| $fully_booked_days[ $js_date ][0] = true; | |
| } | |
| } | |
| - $check_date = strtotime( "+1 day", $check_date ); | |
| + $check_date = $strtotimes_ar["+1 day"] + $check_date; | |
| } | |
| } | |
| $this->args['partially_booked_days'] = $partially_booked_days; | |
| $this->args['fully_booked_days'] = $fully_booked_days; | |
| } | |
| -} | |
| \ No newline at end of file | |
| +} | |
| diff --git a/includes/class-wc-bookings-controller.php b/includes/class-wc-bookings-controller.php | |
| old mode 100755 | |
| new mode 100644 | |
| diff --git a/includes/class-wc-product-booking-resource.php b/includes/class-wc-product-booking-resource.php | |
| index c4403b5..9bfaf73 100644 | |
| --- a/includes/class-wc-product-booking-resource.php | |
| +++ b/includes/class-wc-product-booking-resource.php | |
| @@ -10,6 +10,7 @@ class WC_Product_Booking_Resource { | |
| private $resource; | |
| private $product_id; | |
| + private $qty; | |
| /** | |
| * Constructor | |
| @@ -70,7 +71,11 @@ class WC_Product_Booking_Resource { | |
| * @return int | |
| */ | |
| public function get_qty() { | |
| - return get_post_meta( $this->get_id(), 'qty', true ); | |
| + //@VALU Save meta to resource | |
| + if(is_null($this->qty)) { | |
| + $this->qty = get_post_meta( $this->get_id(), 'qty', true ); | |
| + } | |
| + return $this->qty; | |
| } | |
| /** | |
| diff --git a/includes/class-wc-product-booking.php b/includes/class-wc-product-booking.php | |
| old mode 100755 | |
| new mode 100644 | |
| index 851e3f6..256ae1f | |
| --- a/includes/class-wc-product-booking.php | |
| +++ b/includes/class-wc-product-booking.php | |
| @@ -8,6 +8,11 @@ if ( ! defined( 'ABSPATH' ) ) { | |
| */ | |
| class WC_Product_Booking extends WC_Product { | |
| private $availability_rules = array(); | |
| + //@VALU | |
| + private $booking_resources = array(); | |
| + private $wc_booking_duration_unit_filtered; | |
| + private $min_date, $current_time; | |
| + private $bookable_minute_blocks; | |
| /** | |
| * Constructor | |
| @@ -114,7 +119,11 @@ class WC_Product_Booking extends WC_Product { | |
| * @return string | |
| */ | |
| public function get_duration_unit() { | |
| - return apply_filters( 'woocommerce_bookings_get_duration_unit', $this->wc_booking_duration_unit, $this ); | |
| + //@VALU Filter duration unit only once for the product | |
| + if( ! isset( $this->wc_booking_duration_unit_filtered ) ) { | |
| + $this->wc_booking_duration_unit_filtered = apply_filters( 'woocommerce_bookings_get_duration_unit', $this->wc_booking_duration_unit, $this ); | |
| + } | |
| + return $this->wc_booking_duration_unit_filtered; | |
| } | |
| /** | |
| @@ -252,26 +261,53 @@ class WC_Product_Booking extends WC_Product { | |
| * @return int | |
| */ | |
| public function get_min_timestamp_for_date( $start_date ) { | |
| + | |
| + //@VALU cache current time and offsets | |
| + $current_time = $this->get_current_time(); | |
| + | |
| if ( $min = $this->get_min_date() ) { | |
| - $today = ( date( 'y-m-d', $start_date ) === date( 'y-m-d', current_time( 'timestamp' ) ) ); | |
| - $timestamp = strtotime( ( $today ? '' : 'midnight ' ) . "+{$min['value']} {$min['unit']}", current_time( 'timestamp' ) ); | |
| + $today = ( date( 'y-m-d', $start_date ) === date( 'y-m-d', $current_time ) ); | |
| + $timestamp = strtotime( ( $today ? '' : 'midnight ' ) . "+{$min['value']} {$min['unit']}", $current_time ); | |
| } else { | |
| - $timestamp = current_time( 'timestamp' ); | |
| + $timestamp = $current_time; | |
| } | |
| + | |
| return $timestamp; | |
| } | |
| + /** | |
| + * Caching function for current_time to avoid extensive calls. | |
| + * | |
| + * @return int First time | |
| + */ | |
| + public function get_current_time() { | |
| + if( is_null( $this->current_time ) ) { | |
| + $this->current_time = current_time( 'timestamp' ); | |
| + } | |
| + return $this->current_time; | |
| + } | |
| + | |
| /** | |
| * Get Min date | |
| * @return array|bool | |
| */ | |
| public function get_min_date() { | |
| - $min_date['value'] = ! empty( $this->wc_booking_min_date ) ? apply_filters( 'woocommerce_bookings_min_date_value', absint( $this->wc_booking_min_date ), $this->id ) : 0; | |
| - $min_date['unit'] = ! empty( $this->wc_booking_min_date_unit ) ? apply_filters( 'woocommerce_bookings_min_date_unit', $this->wc_booking_min_date_unit, $this->id ) : 'month'; | |
| - if ( $min_date['value'] ) { | |
| - return $min_date; | |
| - } | |
| - return false; | |
| + //@VALU Cache to skip the filters | |
| + $min_date = $this->min_date; | |
| + | |
| + if( is_null( $this->min_date ) ) { | |
| + $this->min_date = array(); | |
| + $this->min_date['value'] = ! empty( $this->wc_booking_min_date ) ? apply_filters( 'woocommerce_bookings_min_date_value', absint( $this->wc_booking_min_date ), $this->id ) : 0; | |
| + $this->min_date['unit'] = ! empty( $this->wc_booking_min_date_unit ) ? apply_filters( 'woocommerce_bookings_min_date_unit', $this->wc_booking_min_date_unit, $this->id ) : 'month'; | |
| + | |
| + if ( $this->min_date['value'] ) { | |
| + $this->min_date = $min_date; | |
| + } else { | |
| + $this->min_date = false; | |
| + } | |
| + } | |
| + | |
| + return $this->min_date; | |
| } | |
| /** | |
| @@ -347,12 +383,23 @@ class WC_Product_Booking extends WC_Product { | |
| $id = absint( $id ); | |
| if ( $id ) { | |
| - $resource = get_post( $id ); | |
| - $relationship_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}wc_booking_relationships WHERE product_id = %d AND resource_id = %d", $this->id, $id ) ); | |
| + // @VALU Implement "cache" a.k.a. save the booking_resource to the current product to avoid unnecessary queries | |
| + $booking_resource_key = 'booking_resource_'.$id; | |
| + $booking_resource = false; | |
| + if(isset($this->booking_resources[$booking_resource_key])) { | |
| + return $this->booking_resources[$booking_resource_key]; | |
| + } else { | |
| + $resource = get_post( $id ); | |
| + $relationship_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}wc_booking_relationships WHERE product_id = %d AND resource_id = %d", $this->id, $id ) ); | |
| + | |
| + if ( is_object( $resource ) && $resource->post_type == 'bookable_resource' && 0 < $relationship_id ) { | |
| + $booking_resource = new WC_Product_Booking_Resource( $resource, $this->id ); | |
| + $this->booking_resources[$booking_resource_key] = $booking_resource; | |
| + } | |
| + } | |
| + | |
| + return $booking_resource; | |
| - if ( is_object( $resource ) && $resource->post_type == 'bookable_resource' && 0 < $relationship_id ) { | |
| - return new WC_Product_Booking_Resource( $resource, $this->id ); | |
| - } | |
| } | |
| return false; | |
| @@ -532,7 +579,7 @@ class WC_Product_Booking extends WC_Product { | |
| // Check all blocks availability | |
| foreach ( $blocks as $block ) { | |
| - $available_qty = $this->has_resources() && $booking_resource->has_qty() ? $booking_resource->get_qty() : $this->get_qty(); | |
| + $available_qty = $this->has_resources() && $booking_resource->has_qty() ? $booking_resource->get_qty() : $this->get_qty(); | |
| $qty_booked_in_block = 0; | |
| foreach ( $existing_bookings as $existing_booking ) { | |
| @@ -754,85 +801,31 @@ class WC_Product_Booking extends WC_Product { | |
| if ( in_array( $this->get_duration_unit(), array( 'day', 'minute', 'hour' ) ) ) { | |
| $check_date = $start_date; | |
| + // @VALU Initialize necessary variables outside of the while loop!!! | |
| + $min_date = $this->get_min_timestamp_for_date( $start_date ); | |
| + $product_min_date = $this->get_min_date(); | |
| + $product_max_date = $this->get_max_date(); | |
| + | |
| + //Initialize times | |
| + $current_time = $this->get_current_time(); | |
| + $strtotimes_ar = array( | |
| + "+1 day" => strtotime("+1 day", 0), | |
| + "+product_min_date" => strtotime("+{$product_min_date['value']} {$product_min_date['unit']}", 0), | |
| + "+product_max_date" => strtotime("+{$product_max_date['value']} {$product_max_date['unit']}", 0), | |
| + ); | |
| + | |
| + $booking_resource = $resource_id ? $this->get_resource( $resource_id ) : null; | |
| + $available_qty = $this->has_resources() && $booking_resource && $booking_resource->has_qty() ? $booking_resource->get_qty() : $this->get_qty(); | |
| + | |
| // <= fixes https://github.com/woothemes/woocommerce-bookings/issues/325 | |
| while ( $check_date <= $end_date ) { | |
| if ( in_array( $this->get_duration_unit(), array( 'day' ) ) && ! $this->check_availability_rules_against_date( $check_date, $resource_id ) ) { | |
| - $check_date = strtotime( "+1 day", $check_date ); | |
| + $check_date = $strtotimes_ar["+1 day"] + $check_date; | |
| continue; | |
| } | |
| - $booking_resource = $resource_id ? $this->get_resource( $resource_id ) : null; | |
| - $available_qty = $this->has_resources() && $booking_resource && $booking_resource->has_qty() ? $booking_resource->get_qty() : $this->get_qty(); | |
| - | |
| // For mins and hours find valid blocks within THIS DAY ($check_date) | |
| if ( in_array( $this->get_duration_unit(), array( 'minute', 'hour' ) ) ) { | |
| - $first_block_time_minute = $this->wc_booking_first_block_time ? ( date( 'H', strtotime( $this->wc_booking_first_block_time ) ) * 60 ) + date( 'i', strtotime( $this->wc_booking_first_block_time ) ) : 0; | |
| - $min_date = $this->get_min_timestamp_for_date( $start_date ); | |
| - | |
| - // Work out what minutes are actually bookable on this day | |
| - $bookable_minutes = $this->get_default_availability() ? range( $first_block_time_minute, 1440 ) : array(); | |
| - $rules = $this->get_availability_rules( $resource_id ); | |
| - | |
| - // Since we evaluate all time rules and don't break out when one matches, reverse the array | |
| - $rules = array_reverse( $rules ); | |
| - | |
| - foreach ( $rules as $rule ) { | |
| - $type = $rule[0]; | |
| - $rules = $rule[1]; | |
| - | |
| - if ( strrpos( $type, 'time' ) === 0 ) { | |
| - if ( ! empty( $rules['day'] ) ) { | |
| - if ( $rules['day'] != date( 'N', $check_date ) ) { | |
| - continue; | |
| - } | |
| - } | |
| - $from_hour = absint( date( 'H', strtotime( $rules['from'] ) ) ); | |
| - $from_min = absint( date( 'i', strtotime( $rules['from'] ) ) ); | |
| - $to_hour = absint( date( 'H', strtotime( $rules['to'] ) ) ); | |
| - $to_min = absint( date( 'i', strtotime( $rules['to'] ) ) ); | |
| - $minute_range = array( ( $from_hour * 60 ) + $from_min, ( $to_hour * 60 ) + $to_min ); | |
| - $merge_ranges = array(); | |
| - | |
| - if ( $minute_range[0] > $minute_range[1] ) { | |
| - $merge_ranges[] = array( $minute_range[0], 1440 ); | |
| - $merge_ranges[] = array( 0, $minute_range[1] ); | |
| - } else { | |
| - $merge_ranges[] = array( $minute_range[0], $minute_range[1] ); | |
| - } | |
| - | |
| - foreach ( $merge_ranges as $range ) { | |
| - if ( $bookable = $rules['rule'] ) { | |
| - // If this time range is bookable, add to bookable minutes | |
| - $bookable_minutes = array_merge( $bookable_minutes, range( $range[0], $range[1] ) ); | |
| - } else { | |
| - // If this time range is not bookable, remove from bookable minutes | |
| - $bookable_minutes = array_diff( $bookable_minutes, range( $range[0] + 1, $range[1] - 1 ) ); | |
| - } | |
| - } | |
| - } | |
| - } | |
| - | |
| - $bookable_minutes = array_unique( $bookable_minutes ); | |
| - sort( $bookable_minutes ); | |
| - | |
| - // Break bookable minutes into sequences - bookings cannot have breaks | |
| - $bookable_minute_blocks = array(); | |
| - $bookable_minute_block_from = current( $bookable_minutes ); | |
| - | |
| - foreach ( $bookable_minutes as $key => $minute ) { | |
| - if ( isset( $bookable_minutes[ $key + 1 ] ) ) { | |
| - if ( $bookable_minutes[ $key + 1 ] - 1 === $minute ) { | |
| - continue; | |
| - } else { | |
| - // There was a break in the sequence | |
| - $bookable_minute_blocks[] = array( $bookable_minute_block_from, $minute ); | |
| - $bookable_minute_block_from = $bookable_minutes[ $key + 1 ]; | |
| - } | |
| - } else { | |
| - // We're at the end of the bookable minutes | |
| - $bookable_minute_blocks[] = array( $bookable_minute_block_from, $minute ); | |
| - } | |
| - } | |
| // Create an array of already booked blocks | |
| $booked_blocks = array(); | |
| @@ -845,15 +838,21 @@ class WC_Product_Booking extends WC_Product { | |
| $booked_blocks = array_count_values( $booked_blocks ); | |
| + //@VALU Initialize midnight | |
| + $check_date_midnight = strtotime( "midnight", $check_date ); | |
| + | |
| + //Get bookable minute blocks for resource | |
| + $bookable_minute_blocks = $this->get_bookable_minute_blocks($check_date, $resource_id); | |
| + | |
| // Loop the blocks of bookable minutes and add a block if there is enough room to book | |
| foreach ( $bookable_minute_blocks as $time_block ) { | |
| - $time_block_start = strtotime( "midnight +{$time_block[0]} minutes", $check_date ); | |
| + $time_block_start = $time_block[0] * MINUTE_IN_SECONDS + $check_date_midnight; | |
| $minutes_in_block = $time_block[1] - $time_block[0]; | |
| $base_intervals_in_block = floor( $minutes_in_block / $base_interval ); | |
| for ( $i = 0; $i < $base_intervals_in_block; $i ++ ) { | |
| $from_interval = $i * $base_interval; | |
| - $start_time = strtotime( "+{$from_interval} minutes", $time_block_start ); | |
| + $start_time = $from_interval * MINUTE_IN_SECONDS + $time_block_start; | |
| // Break if start time is after the end date being calced, or if the start time is on the next day | |
| if ( $start_time > $end_date || date( 'ymd', $start_time ) !== date( 'ymd', $start_date ) ) { | |
| @@ -861,7 +860,7 @@ class WC_Product_Booking extends WC_Product { | |
| } | |
| // Must be in the future | |
| - if ( $start_time <= $min_date || $start_time <= current_time( 'timestamp' ) ) { | |
| + if ( $start_time <= $min_date || $start_time <= $current_time ) { | |
| continue; | |
| } | |
| @@ -870,10 +869,9 @@ class WC_Product_Booking extends WC_Product { | |
| } | |
| // make sure minute & hour blocks are not past minimum & max booking settings | |
| - $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_check_from = $strtotimes_ar["+product_min_date"] + $current_time; | |
| + $max_check_to = $strtotimes_ar["+product_max_date"] + $current_time; | |
| if ( $end_date < $min_check_from || $start_time > $max_check_to ) { | |
| continue; | |
| @@ -884,8 +882,8 @@ class WC_Product_Booking extends WC_Product { | |
| * @note Known issue - hour blocks cannot span multi-days | |
| */ | |
| $to_interval = $from_interval + $interval; | |
| - $end_time = strtotime( "+{$to_interval} minutes", $time_block_start ); | |
| - $time_block_end_time = strtotime( "midnight +{$time_block[1]} minutes", $check_date ); | |
| + $end_time = $to_interval * MINUTE_IN_SECONDS + $time_block_start; | |
| + $time_block_end_time = $time_block[1] * MINUTE_IN_SECONDS + $check_date_midnight; | |
| $loop_time = $start_time; | |
| // This checks all minutes in block for availability | |
| @@ -912,9 +910,9 @@ class WC_Product_Booking extends WC_Product { | |
| } | |
| // Check next day | |
| - $check_date = strtotime( "+1 day", $check_date ); | |
| + $check_date = $strtotimes_ar["+1 day"] + $check_date; | |
| } | |
| - | |
| + | |
| // For months, loop each month in the range to find blocks | |
| } elseif ( 'month' === $this->get_duration_unit() ) { | |
| @@ -943,6 +941,115 @@ class WC_Product_Booking extends WC_Product { | |
| return $blocks; | |
| } | |
| + /** | |
| + * Return bookable minute blocks. If the block does not exist, generate it. | |
| + * | |
| + * @param int $check_date time for the date to check | |
| + * @param int $resource_id ID of the resource to check | |
| + * @return Array | |
| + */ | |
| + public function get_bookable_minute_blocks($check_date, $resource_id = 0) { | |
| + // Initialize variables | |
| + $resource_key = 'resource_'.$resource_id; | |
| + $date_key = 'date_'.$check_date; | |
| + | |
| + if(is_null($this->bookable_minute_blocks)) { | |
| + $this->bookable_minute_blocks = get_post_meta($this->id, '_wc_booking_bookable_minute_blocks', true); | |
| + } | |
| + if(false === $this->bookable_minute_blocks) { | |
| + $this->bookable_minute_blocks = array(); | |
| + } | |
| + if(!isset($this->bookable_minute_blocks[$resource_key])) { | |
| + $this->bookable_minute_blocks[$resource_key] = array(); | |
| + } | |
| + | |
| + // Work out what minutes are actually bookable on this day | |
| + $first_block_time_minute = $this->wc_booking_first_block_time ? ( date( 'H', strtotime( $this->wc_booking_first_block_time ) ) * 60 ) + date( 'i', strtotime( $this->wc_booking_first_block_time ) ) : 0; | |
| + $bookable_minutes = $this->get_default_availability() ? range( $first_block_time_minute, 1440 ) : array(); | |
| + $rules = $this->get_availability_rules( $resource_id ); | |
| + | |
| + // Since we evaluate all time rules and don't break out when one matches, reverse the array | |
| + $rules = array_reverse( $rules ); | |
| + | |
| + // Check if block exists | |
| + if(isset($this->bookable_minute_blocks[$resource_key][$date_key])) { | |
| + return $this->bookable_minute_blocks[$resource_key][$date_key]; | |
| + } else { | |
| + foreach ($rules as $rule ) { | |
| + $type = $rule[0]; | |
| + $rules = $rule[1]; | |
| + | |
| + if ( strrpos( $type, 'time' ) === 0 ) { | |
| + if ( ! empty( $rules['day'] ) ) { | |
| + if ( $rules['day'] != date( 'N', $check_date ) ) { | |
| + continue; | |
| + } | |
| + } | |
| + $from_hour = absint( date( 'H', strtotime( $rules['from'] ) ) ); | |
| + $from_min = absint( date( 'i', strtotime( $rules['from'] ) ) ); | |
| + $to_hour = absint( date( 'H', strtotime( $rules['to'] ) ) ); | |
| + $to_min = absint( date( 'i', strtotime( $rules['to'] ) ) ); | |
| + $minute_range = array( ( $from_hour * 60 ) + $from_min, ( $to_hour * 60 ) + $to_min ); | |
| + $merge_ranges = array(); | |
| + | |
| + if ( $minute_range[0] > $minute_range[1] ) { | |
| + $merge_ranges[] = array( $minute_range[0], 1440 ); | |
| + $merge_ranges[] = array( 0, $minute_range[1] ); | |
| + } else { | |
| + $merge_ranges[] = array( $minute_range[0], $minute_range[1] ); | |
| + } | |
| + | |
| + foreach ( $merge_ranges as $range ) { | |
| + if ( $bookable = $rules['rule'] ) { | |
| + // If this time range is bookable, add to bookable minutes | |
| + $bookable_minutes = array_merge( $bookable_minutes, range( $range[0], $range[1] ) ); | |
| + } else { | |
| + // If this time range is not bookable, remove from bookable minutes | |
| + $bookable_minutes = array_diff( $bookable_minutes, range( $range[0] + 1, $range[1] - 1 ) ); | |
| + } | |
| + } | |
| + } | |
| + } | |
| + | |
| + $bookable_minutes = array_unique( $bookable_minutes ); | |
| + sort( $bookable_minutes ); | |
| + | |
| + // Break bookable minutes into sequences - bookings cannot have breaks | |
| + $bookable_minute_blocks = array(); | |
| + $bookable_minute_block_from = current( $bookable_minutes ); | |
| + | |
| + foreach ( $bookable_minutes as $key => $minute ) { | |
| + if ( isset( $bookable_minutes[ $key + 1 ] ) ) { | |
| + if ( $bookable_minutes[ $key + 1 ] - 1 === $minute ) { | |
| + continue; | |
| + } else { | |
| + // There was a break in the sequence | |
| + $bookable_minute_blocks[] = array( $bookable_minute_block_from, $minute ); | |
| + $bookable_minute_block_from = $bookable_minutes[ $key + 1 ]; | |
| + } | |
| + } else { | |
| + // We're at the end of the bookable minutes | |
| + $bookable_minute_blocks[] = array( $bookable_minute_block_from, $minute ); | |
| + } | |
| + } | |
| + //Save changes | |
| + $this->bookable_minute_blocks[$resource_key][$date_key] = $bookable_minute_blocks; | |
| + add_action('shutdown', array($this, 'save_bookable_minute_blocks')); | |
| + | |
| + return $this->bookable_minute_blocks[$resource_key][$date_key]; | |
| + } | |
| + } | |
| + | |
| + /** | |
| + * Save bookable minute blocks at the end of execution, because | |
| + * serialization of the array is extremely heavy. Load times bump about | |
| + * 10x if this is done every time when get_bookable_minute_blocks is | |
| + * called | |
| + */ | |
| + public function save_bookable_minute_blocks() { | |
| + update_post_meta($this->id, '_wc_booking_bookable_minute_blocks', $this->bookable_minute_blocks); | |
| + } | |
| + | |
| /** | |
| * Returns available blocks from a range of blocks by looking at existing bookings. | |
| * @param array $blocks The blocks we'll be checking availability for. | |
| diff --git a/includes/emails/class-wc-email-booking-confirmed.php b/includes/emails/class-wc-email-booking-confirmed.php | |
| index 79a2032..2adc062 100644 | |
| --- a/includes/emails/class-wc-email-booking-confirmed.php | |
| +++ b/includes/emails/class-wc-email-booking-confirmed.php | |
| @@ -52,6 +52,7 @@ class WC_Email_Booking_Confirmed extends WC_Email { | |
| unset( $this->replace[ $key ] ); | |
| } | |
| $this->find[] = '{product_title}'; | |
| + | |
| $this->replace[] = $this->object->get_product()->get_title(); | |
| if ( $this->object->get_order() ) { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment