PluginProbe
Booking Calendar / 11.8.3
Booking Calendar v11.8.3
11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 All 203 releases
← All changes | includes/_capacity/capacity.php +124 -19 10.15.611.8.3 View file →
@@ -554,9 +554,11 @@
554 554 'as_single_resource' => false, // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'.
555 555 'max_days_count' => wpbc_get_max_visible_days_in_calendar(), // 365.
556 556 'timeslots_to_check_intersect' => array(), // arr: '12:20 - 12:55', '13:00 - 14:00' ) // TODO: ? do we really need it, because below we get it from function.
557 557 'request_uri' => ( ( ( defined( 'DOING_AJAX' ) ) && ( DOING_AJAX ) ) ? $server_http_referer_uri : $server_request_uri ), // front-end: $server_request_uri | ajax: $server_http_referer_uri // It different in Ajax requests. It's used for change-over days to detect for exception at specific pages.
558 + 'allow_past' => false,
558 559 'custom_form' => '', // Required for checking all available time-slots and compare with booked time slots.
560 + 'force_check_from_today_unavailable' => false, // Optional admin tools can force relative availability checks inside explicit date ranges.
559 561 );
560 562
561 563 $params = wp_parse_args( $params, $defaults );
562 564
@@ -561,11 +563,12 @@
561 563 $params = wp_parse_args( $params, $defaults );
562 564
563 565 // FixIn: 10.7.1.2. //FixIn: 10.10.3.2.
564 566 if (
567 + ( ! empty( $params['allow_past'] ) ) ||
565 568 ( false !== strpos( $params['request_uri'], 'allow_past' ) ) ||
566 569 (
567 - ( false !== strpos( $params['request_uri'], 'page=wpbc-new' ) ) &&
570 + wpbc_is_new_booking_page_url( $params['request_uri'] ) &&
568 571 ( false !== strpos( $params['request_uri'], 'booking_hash' ) )
569 572 )
570 573 ) {
571 574 $params['dates_to_check'] = 'ALL';
@@ -620,10 +623,15 @@
620 623 // -----------------------------------------------------------------------------------------------------------------
621 624 // Main function to get "Bookings": ['2023-08-30'][ > resource_id < ][ > time_seconds_range < ] => booking_date_obj[ booking_id:45, approved:1, ...
622 625 $bookings__in_dates = wpbc_get__booked_dates__per_resources__arr( $params );
623 626
627 + // -----------------------------------------------------------------------------------------------------------------
628 + // Time slots availability blocks.
629 + // -----------------------------------------------------------------------------------------------------------------
630 + $availability_timeslots__in_dates = array(); // FixIn: 10.16.1.
624 631
625 632
633 +
626 634 // -----------------------------------------------------------------------------------------------------------------
627 635 // Booking > Availability page
628 636 // -----------------------------------------------------------------------------------------------------------------
629 637 $search_dates = $params['dates_to_check']; // 'CURDATE' | 'ALL' | [ "2023-08-03" , "2023-08-04" , "2023-08-05" ]
@@ -642,9 +650,28 @@
642 650 }
643 651 $unavailable_dates__per_resources__arr = wpbc_aggregate_merge_availability( $unavailable_dates__per_resources__arr,
644 652 $resource_id__with_children__arr,
645 653 $aggregate_resource_id_arr );
654 + // FixIn: 10.16.1.
655 + if ( function_exists( 'wpbc_availability_timeslots__get_intervals_for_resources' ) ) {
656 + $availability_timeslots__resource_ids = wpbc_get_unique_array_of_resources_id( $resource_id__with_children__arr, $aggregate_resource_id_arr );
657 + $availability_timeslots__in_dates = wpbc_availability_timeslots__get_intervals_for_resources(
658 + array(
659 + 'resource_id' => $availability_timeslots__resource_ids,
660 + 'dates_to_check' => $search_dates,
661 + 'max_days_count' => $params['max_days_count'],
662 + )
663 + );
646 664
665 + if ( function_exists( 'wpbc_availability_timeslots__aggregate_merge_intervals' ) ) {
666 + $availability_timeslots__in_dates = wpbc_availability_timeslots__aggregate_merge_intervals(
667 + $availability_timeslots__in_dates,
668 + $resource_id__with_children__arr,
669 + $aggregate_resource_id_arr
670 + );
671 + }
672 + }
673 +
647 674 // -----------------------------------------------------------------------------------------------------------------
648 675 // Booking > Resources > Availability page
649 676 // -----------------------------------------------------------------------------------------------------------------
650 677 $season_filters_availability = array();
@@ -661,14 +688,14 @@
661 688 // P a r a m e t e r s f o r L O O P
662 689 // -----------------------------------------------------------------------------------------------------------------
663 690
664 691 // - Is this Booking > Add booking page ? --------------------------------------------------------------------------
665 - $is_this_bap_page = ( false !== strpos( $params['request_uri'], 'page=wpbc-new' ) ) ? true : false;
692 + $is_this_bap_page = wpbc_is_new_booking_page_url( $params['request_uri'] );
666 693 $is_this_hash_page = ( false !== strpos( $params['request_uri'], 'booking_hash' ) ) ? true : false; // Set it to TRUE for adding booking in past at Booking > Add booking page
667 694
668 695 // FixIn: 10.7.1.2.
669 696 if ( ! $is_this_hash_page ) {
670 - $is_this_hash_page = ( false !== strpos( $params['request_uri'], 'allow_past' ) ) ? true : false;
697 + $is_this_hash_page = ( ( ! empty( $params['allow_past'] ) ) || ( false !== strpos( $params['request_uri'], 'allow_past' ) ) ) ? true : false;
671 698 }
672 699
673 700 if ( ( $is_this_bap_page ) && ( $is_this_hash_page ) ) { // Start days in calendar from = PAST
674 701 $params['dates_to_check'] = 'ALL';
@@ -697,12 +724,12 @@
697 724 } else if ( is_array( $params['dates_to_check'] ) ) {
698 725
699 726 $start_day_number = 1;
700 727
701 - $today_inix_timestamp = strtotime( $params['dates_to_check'][0] . ' 00:00:00' ); // '2023-09-03 00:00:00'
728 + $today_inix_timestamp = strtotime( $params['dates_to_check'][0] . ' 00:00:00 UTC' ); // '2023-09-03 00:00:00'
702 729
703 - $dif_in_days = strtotime( $params['dates_to_check'][ ( count( $params['dates_to_check'] ) - 1 ) ] . ' 00:00:00' )
704 - - strtotime( $params['dates_to_check'][0] . ' 00:00:00' );
730 + $dif_in_days = strtotime( $params['dates_to_check'][ ( count( $params['dates_to_check'] ) - 1 ) ] . ' 00:00:00 UTC' )
731 + - strtotime( $params['dates_to_check'][0] . ' 00:00:00 UTC' );
705 732
706 733 $dif_in_days = $dif_in_days / ( 24 * 60 * 60 );
707 734 $params['max_days_count'] = ceil( $dif_in_days ) + 1;
708 735 }
@@ -757,8 +784,9 @@
757 784 $availability_per_day[ $my_day_tag ]['statuses']['bookings_status'] = array(); // per each child booking resource
758 785 $availability_per_day[ $my_day_tag ]['summary'] = array();
759 786 $availability_per_day[ $my_day_tag ]['summary']['status_for_day'] = ''; // available | time_slots_booking | full_day_booking | ...
760 787 $availability_per_day[ $my_day_tag ]['summary']['status_for_bookings'] = ''; // pending | approved | CO: pending_pending | pending_approved | approved_pending | approved_approved
788 + $availability_per_day[ $my_day_tag ]['summary']['status_for_bookings_arr'] = array(); // Structured statuses array, e.g. array( 'approved', 'approved_approved' ).
761 789 $availability_per_day[ $my_day_tag ]['summary']['tooltip_times'] = '';
762 790 $availability_per_day[ $my_day_tag ]['summary']['tooltip_availability'] = '';
763 791 $availability_per_day[ $my_day_tag ]['summary']['tooltip_day_cost'] = '';
764 792 $availability_per_day[ $my_day_tag ]['summary']['tooltip_booking_details'] = '';
@@ -931,11 +959,20 @@
931 959
932 960 // =====================================================================================================
933 961 // Change over days =
934 962 // =====================================================================================================
963 + $is_booking_used_check_in_out_time = null;
964 + if ( function_exists( 'wpbc_settings_calendar__preview_is_changeover_enabled' ) ) {
965 + $is_booking_used_check_in_out_time = wpbc_settings_calendar__preview_is_changeover_enabled( $resource_id, $params['request_uri'] );
966 + }
967 + if ( null === $is_booking_used_check_in_out_time ) {
968 + $is_booking_used_check_in_out_time = (
969 + ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) )
970 + && ( wpbc_is_booking_used_check_in_out_time( $params['request_uri'], $resource_id ) )
971 + );
972 + }
935 973 if (
936 - ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) )
937 - && ( wpbc_is_booking_used_check_in_out_time( $params[ 'request_uri' ] ) )
974 + $is_booking_used_check_in_out_time
938 975 && ( ! $availability_per_day[ $my_day_tag ][ $resource_id ]->is_day_unavailable ) // And this date still free false
939 976 ) {
940 977
941 978 /**
@@ -1020,9 +1057,48 @@
1020 1057 }
1021 1058 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1022 1059 // B O O K I N G S - E n d
1023 1060 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1061 + // Working Time applies only to time-based booking forms: rangetime, start/end, or start/duration.
1062 + $working_time__timeslots_to_check_intersect = $as_seconds_timeslots_arr__to_check_intersect;
1063 + if ( empty( $working_time__timeslots_to_check_intersect ) && ! empty( $params['timeslots_to_check_intersect'] ) ) {
1064 + if ( ! is_array( $params['timeslots_to_check_intersect'] ) ) {
1065 + $params['timeslots_to_check_intersect'] = array( $params['timeslots_to_check_intersect'] );
1066 + }
1067 + $working_time__timeslots_to_check_intersect = array();
1068 + foreach ( $params['timeslots_to_check_intersect'] as $time_slot_readable ) {
1069 + $working_time__timeslots_to_check_intersect[] = wpbc_convert__readable_time_slot__to__time_range_in_seconds( $time_slot_readable );
1070 + }
1071 + }
1024 1072
1073 + if (
1074 + ! empty( $working_time__timeslots_to_check_intersect )
1075 + && function_exists( 'wpbc_working_time__get_non_working_intervals_for_date' )
1076 + && function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' )
1077 + ) {
1078 + $working_time__blocked_intervals = wpbc_working_time__get_non_working_intervals_for_date( $resource_id, $my_day_tag );
1079 +
1080 + if ( ! empty( $working_time__blocked_intervals ) ) {
1081 + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj(
1082 + $availability_per_day[ $my_day_tag ][ $resource_id ],
1083 + $working_time__blocked_intervals,
1084 + $working_time__timeslots_to_check_intersect
1085 + );
1086 + }
1087 + }
1088 +
1089 + // FixIn: 10.16.1.
1090 + if (
1091 + function_exists( 'wpbc_availability_timeslots__apply_blocks_to_availability_obj' )
1092 + && isset( $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ] )
1093 + ) {
1094 + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_availability_timeslots__apply_blocks_to_availability_obj(
1095 + $availability_per_day[ $my_day_tag ][ $resource_id ],
1096 + $availability_timeslots__in_dates[ $my_day_tag ][ $resource_id ],
1097 + $as_seconds_timeslots_arr__to_check_intersect
1098 + );
1099 + }
1100 +
1025 1101 //==========================================================================================================
1026 1102 // $availability_per_day[..]->_day_status = 'season_filter' | ...
1027 1103 //==========================================================================================================
1028 1104 // Booking > Resources > Availability page >>> 'season_filter'
@@ -1030,18 +1106,20 @@
1030 1106
1031 1107 // Booking > Availability page >>> 'resource_availability'
1032 1108 $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__resource_availability( $availability_per_day, $my_day_tag, $resource_id, $unavailable_dates__per_resources__arr );
1033 1109
1034 - // Week Days unavailable >>> 'weekday_unavailable'
1035 - $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id );
1110 + if ( empty( $params['skip_general_availability'] ) ) {
1111 + // Week Days unavailable >>> 'weekday_unavailable'
1112 + $availability_per_day[ $my_day_tag ][ $resource_id ] = wpbc_support_capacity__day_status__weekday_unavailable( $availability_per_day, $my_day_tag, $resource_id );
1113 + }
1036 1114
1037 1115 // if ( ( ! $is_this_bap_page ) || ( ! $is_this_hash_page ) ) {
1038 - if ( ( ! $is_this_bap_page ) && ( ! $is_this_hash_page ) ) {
1116 + if ( empty( $params['skip_general_availability'] ) && ( ! $is_this_bap_page ) && ( ! $is_this_hash_page ) ) {
1039 1117 // Do not apply these settings at Booking > Add booking page, when we edit booking - e.g. exist 'booking_hash'
1040 1118
1041 1119 // Skip checking unavailable from today, if defined the calendar_dates_start='2025-02-10' calendar_dates_end='2025-12-31' in shortcode. // FixIn: 10.13.1.4.
1042 1120 $is_skip_check__from_today_unavailable = false;
1043 - if ( is_array( $params['dates_to_check'] ) ) {
1121 + if ( is_array( $params['dates_to_check'] ) && empty( $params['force_check_from_today_unavailable'] ) ) {
1044 1122 if ( ( ( count( $params['dates_to_check'] ) ) > 0 ) && ( wpbc_is_date_less_than( $params['dates_to_check'][0], $my_day_tag ) ) ) {
1045 1123 $is_skip_check__from_today_unavailable = true;
1046 1124 }
1047 1125 if ( ( ( count( $params['dates_to_check'] ) ) > 1 ) && ( wpbc_is_date_higher_than( $params['dates_to_check'][1], $my_day_tag ) ) ) {
@@ -1179,8 +1257,9 @@
1179 1257 $temp_status[] = $bookings_status_element;
1180 1258 }
1181 1259 }
1182 1260 $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1261 + $temp_status_counts = array_count_values( $temp_status );
1183 1262 $temp_status = array_unique( $temp_status ); // Erase duplicates
1184 1263 $availability_per_this_day['summary']['status_for_day'] = $temp_status;
1185 1264
1186 1265 /**
@@ -1205,10 +1284,34 @@
1205 1284 // Priority: available > time_slots_booking > full_day_booking
1206 1285 // > season_filter > resource_availability
1207 1286 // > weekday_unavailable > from_today_unavailable > limit_available_from_today
1208 1287
1209 - // if at least one booking "available" then day has this status
1288 + // Capacity resources can be available even when every child has a check-in/out or full-day status.
1289 + $max_capacity = isset( $availability_per_this_day['max_capacity'] ) ? intval( $availability_per_this_day['max_capacity'] ) : 1;
1290 + $blocking_statuses = array(
1291 + 'full_day_booking',
1292 + 'season_filter',
1293 + 'resource_availability',
1294 + 'weekday_unavailable',
1295 + 'from_today_unavailable',
1296 + 'limit_available_from_today',
1297 + 'change_over',
1298 + );
1299 + $blocked_capacity = 0;
1300 + foreach ( $blocking_statuses as $blocking_status ) {
1301 + $blocked_capacity += isset( $temp_status_counts[ $blocking_status ] ) ? intval( $temp_status_counts[ $blocking_status ] ) : 0;
1302 + }
1303 + $booked_capacity__before_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_out'] ) ? intval( $temp_status_counts['check_out'] ) : 0 );
1304 + $booked_capacity__after_check_in = $blocked_capacity + ( isset( $temp_status_counts['check_in'] ) ? intval( $temp_status_counts['check_in'] ) : 0 );
1305 + $is_capacity_available_during_change_over = (
1306 + ( $max_capacity > 1 )
1307 + && ( $max_capacity > max( $booked_capacity__before_check_in, $booked_capacity__after_check_in ) )
1308 + && ( ! in_array( 'time_slots_booking', $availability_per_this_day['summary']['status_for_day'] ) )
1309 + );
1310 +
1311 + // if at least one resource is available then day has this status
1210 1312 if ( in_array( 'available', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'available';
1313 + } else if ( $is_capacity_available_during_change_over ) { $availability_per_this_day['summary']['status_for_day'] = 'available';
1211 1314 } else if ( in_array( 'time_slots_booking', $availability_per_this_day['summary']['status_for_day'] ) ) { $availability_per_this_day['summary']['status_for_day'] = 'time_slots_booking';
1212 1315 } else if ( ( ! in_array( 'check_out', $availability_per_this_day['summary']['status_for_day'] ) )
1213 1316 && ( in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) ) ) { $availability_per_this_day['summary']['status_for_day'] = 'check_in';
1214 1317 } else if ( ( ! in_array( 'check_in', $availability_per_this_day['summary']['status_for_day'] ) )
@@ -1234,19 +1337,21 @@
1234 1337 $temp_status[] = $bookings_status_element;
1235 1338 }
1236 1339 }
1237 1340 $temp_status = array_filter( $temp_status ); // All entries of array equal to FALSE (0, '', '0' ) will be removed.
1238 - $temp_status = array_unique( $temp_status );
1239 - $availability_per_this_day['summary']['status_for_bookings'] = $temp_status;
1341 + $temp_status = array_values( array_unique( $temp_status ) );
1240 1342
1343 + // Structured booking statuses contract. Keep numeric keys sequential so JSON encodes this as a JS array.
1344 + $availability_per_this_day['summary']['status_for_bookings_arr'] = $temp_status;
1345 +
1241 1346 // Priority: pending > approved > ''
1242 1347
1243 1348 // if at least one booking pending then day is pending
1244 - if ( in_array( 'pending', $availability_per_this_day['summary']['status_for_bookings'] ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending';
1245 - } else if ( in_array( 'pending_pending', $availability_per_this_day['summary']['status_for_bookings'] ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending_pending';
1349 + if ( in_array( 'pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending';
1350 + } else if ( in_array( 'pending_pending', $temp_status ) ) { $availability_per_this_day['summary']['status_for_bookings'] = 'pending_pending';
1246 1351 // Usual situations for change over days: pending_pending | pending_approved | approved_pending | approved_approved
1247 1352 } else {
1248 - $availability_per_this_day['summary']['status_for_bookings'] = implode( ' ', $availability_per_this_day['summary']['status_for_bookings'] );
1353 + $availability_per_this_day['summary']['status_for_bookings'] = implode( ' ', $temp_status );
1249 1354 }
1250 1355
1251 1356
1252 1357 // -------------------------------------------------------------------------------------------------------------
@@ -1939,5 +2044,5 @@
1939 2044 // * // , 'wpdev_active_locale' => 'en_US'
1940 2045 // * ) );
1941 2046 // .
1942 2047 // add_bk_filter('wpbc_add_new_booking_filter' , 'wpbc_add_new_booking' );
1943 -// TODO: recheck hooks in wpbc-dev-api.php
2048 +// TODO: recheck hooks in wpbc-dev-api.php