PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
11.8.4 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 All 204 releases
← All changes | includes/_capacity/where_to_save.php +133 -11 10.1011.8.4 View file →
@@ -6,8 +6,33 @@
6 6 // Check where to save the booking
7 7 // ---------------------------------------------------------------------------------------------------------------------
8 8
9 9 /**
10 + * Check if these dates contain marker '2981-01-13', which is means that this booking was submited without dates - as Contact Form.
11 + *
12 + * @param array|string $dates_sql_arr - array of SQL dates.
13 + *
14 + * @return bool
15 + */
16 +function wpbc_is_these_dates__for__no_dates( $dates_sql_arr ){
17 +
18 + // FixIn: 2981-01-13 13 Jan 2981.
19 +
20 + if ( is_array( $dates_sql_arr ) ) {
21 + foreach ( $dates_sql_arr as $date_ymd ) {
22 + if ( '2981-01-13' === gmdate( 'Y-m-d', mysql2date( 'U', $date_ymd ) ) ) {
23 + return true;
24 + }
25 + }
26 + } elseif ( '2981-01-13' === gmdate( 'Y-m-d', mysql2date( 'U', $dates_sql_arr ) ) ) {
27 + return true;
28 + }
29 +
30 + return false;
31 +}
32 +
33 +
34 +/**
10 35 * Get booking resources for each selected date, where we can save the booking, or false if we can not save it
11 36 *
12 37 * @param array $params = [
13 38 * 'resource_id' => 2
@@ -29,10 +54,12 @@
29 54 $server_request_uri = ( ( isset( $_SERVER['REQUEST_URI'] ) ) ? sanitize_text_field( $_SERVER['REQUEST_URI'] ) : '' ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */
30 55 $server_http_referer_uri = ( ( isset( $_SERVER['HTTP_REFERER'] ) ) ? sanitize_text_field( $_SERVER['HTTP_REFERER'] ) : '' ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */
31 56 $defaults = array(
32 57 '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
58 + 'allow_past' => false,
33 59 'as_single_resource' => false,
34 60 'is_use_booking_recurrent_time' => ( 'On' === get_bk_option( 'booking_recurrent_time' ) ),
61 + 'time_override_source' => '',
35 62 'aggregate_resource_id_arr' => array(),
36 63 'custom_form' => '' //FixIn: 10.0.0.10 // Required for checking all available time-slots and compare with booked time slots
37 64 );
38 65 $local_params = wp_parse_args( $local_params, $defaults );
@@ -47,9 +74,13 @@
47 74 $local_params['time_as_his_arr'] = array(
48 75 wpbc_transform__seconds__in__24_hours_his( $time_as_seconds_arr[0] ),
49 76 wpbc_transform__seconds__in__24_hours_his( $time_as_seconds_arr[1] )
50 77 );
51 -
78 + // FixIn: 2981-01-13 13 Jan 2981
79 + $availability_per_days_arr__params = array();
80 + if ( ( ! empty( $local_params['dates_only_sql_arr'] ) ) && ( is_array( $local_params['dates_only_sql_arr'] ) ) && ( '2981-01-13' === $local_params['dates_only_sql_arr'][0] ) ) {
81 + $availability_per_days_arr__params['is_days_always_available'] = true;
82 + }
52 83 // If we are using the unavailable before/after booking dates, then we need to extend "$local_params['dates_only_sql_arr']" to such dates.
53 84 if ( function_exists( 'wpbc__extend_checking_dates_range__if_used__extra_seconds__before_after' ) ) {
54 85 $maybe_extended__dates_to_check_arr = wpbc__extend_checking_dates_range__if_used__extra_seconds__before_after( $local_params['dates_only_sql_arr'] );
55 86 } else {
@@ -55,21 +86,55 @@
55 86 } else {
56 87 $maybe_extended__dates_to_check_arr = $local_params['dates_only_sql_arr'];
57 88 }
58 89 // [ "dates": [ "2023-11-05": [ "day_availability":4, ... "2": [ "is_day_unavailable":false, ...]], '2023-11-06':[...] ] ,"resources_id_arr__in_dates":[2,12,10,11]}
59 - $availability_per_days = wpbc_get_availability_per_days_arr( array(
90 +
91 + $availability_per_days = wpbc_get_availability_per_days_arr( wp_parse_args( array(
60 92 'resource_id' => $local_params['resource_id'],
61 93 'skip_booking_id' => $local_params['skip_booking_id'],
62 94 'dates_to_check' => $maybe_extended__dates_to_check_arr,
63 95 'request_uri' => $local_params['request_uri'],
96 + 'allow_past' => ! empty( $local_params['allow_past'] ),
64 97 'as_single_resource' => $local_params['as_single_resource'], // default FALSE :: get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources' .
65 98 'additional_bk_types' => $local_params['aggregate_resource_id_arr'],
66 99 'aggregate_type' => empty( $local_params['aggregate_type'] ) ? 'bookings_only' : $local_params['aggregate_type'], //TODO: this parameter does not transfer during saving, so here will be always default value 'bookings_only' // FixIn: 10.0.0.7.
67 100 'custom_form' => $local_params['custom_form'], // FixIn: 10.0.0.10.
68 - ) );
101 + ) , $availability_per_days_arr__params ) );
69 102
103 + // A contact form has no calendar and uses one synthetic date only to satisfy the booking storage schema.
104 + // Keep its requested resource, because calendar availability rules do not apply to a no-date submission.
105 + $is_no_dates_booking = ( is_array( $local_params['dates_only_sql_arr'] ) && ( 1 === count( $local_params['dates_only_sql_arr'] ) ) &&
106 + wpbc_is_these_dates__for__no_dates( $local_params['dates_only_sql_arr'] ) );
107 + if ( $is_no_dates_booking ) {
108 + $requested_resource_id = absint( $local_params['resource_id'] );
109 + $loaded_resource_ids = isset( $availability_per_days['resources_id_arr__in_dates'] ) ? array_map( 'absint', (array) $availability_per_days['resources_id_arr__in_dates'] ) : array();
110 +
111 + if ( ( 0 === $requested_resource_id ) || ! in_array( $requested_resource_id, $loaded_resource_ids, true ) ) {
112 + return array(
113 + 'result' => 'error',
114 + 'message' => 'Wrong ID of booking resource: ' . $requested_resource_id,
115 + );
116 + }
117 +
118 + $storage_resource_ids = array_values(
119 + array_unique( array_merge( array( $requested_resource_id ), $loaded_resource_ids ) )
120 + );
121 + $resources_in_dates = array_fill_keys(
122 + array_values( $local_params['dates_only_sql_arr'] ),
123 + $storage_resource_ids
124 + );
125 +
126 + return array(
127 + 'result' => 'ok',
128 + 'resources_in_dates' => $resources_in_dates,
129 + 'time_to_book' => $local_params['time_as_his_arr'],
130 + 'main__resource_id' => $requested_resource_id,
131 + );
132 + }
133 +
70 134 // Get value of how many booking resources to book
71 135 $how_many_items_to_book = $local_params['how_many_items_to_book'];
136 +
72 137 // -------------------------------------------------------------------------------------------------------------
73 138 // [ 2023-10-18: [ 0:[ resource_id: 2, is_available: true, booked__seconds: [], booked__readable: [], time_to_book__seconds: [ 36030, 39570 ], time_to_book__readable: "10:00:00", "11:00:00" ] ], 1: [...], 2: [...], 3: [...] ], 2023-10-25: [...], 2023-11-25: [...] ]
74 139 $available_slots = wpbc__get_available_slots__for_selected_dates_times__bl( array(
75 140 'dates_sql__arr' => $local_params['dates_only_sql_arr'],
@@ -74,14 +139,15 @@
74 139 $available_slots = wpbc__get_available_slots__for_selected_dates_times__bl( array(
75 140 'dates_sql__arr' => $local_params['dates_only_sql_arr'],
76 141 'time_as_seconds_arr' => $local_params['time_as_seconds_arr'],
77 142 'is_use_booking_recurrent_time' => $local_params['is_use_booking_recurrent_time'],
143 + 'time_override_source' => $local_params['time_override_source'],
78 144 'availability_per_days' => $availability_per_days
79 145 ) );
80 146
81 147 $main__resource_id = 0;
82 148 // == In SAME 'child' booking resources ============================================================
83 - if ( 'On' === get_bk_option( 'booking_is_dissbale_booking_for_different_sub_resources' ) ) {
149 + if ( class_exists( 'wpdev_bk_biz_l' ) && ( 'On' === get_bk_option( 'booking_is_dissbale_booking_for_different_sub_resources' ) ) ) {
84 150
85 151 $availability_in_same_child_resources = $availability_per_days['resources_id_arr__in_dates'];
86 152
87 153 foreach ( $availability_per_days['resources_id_arr__in_dates'] as $child_resource_id ) {
@@ -119,13 +185,13 @@
119 185 } else {
120 186 // Bad not save
121 187 return array(
122 188 'result' => 'error',
123 - 'message' => __( 'These dates and times in this calendar are already booked or unavailable.', 'booking' )
189 + 'message' => wpbc_frontend_messages__get( 'message_dates_times_unavailable', array(), $local_params['resource_id'] )
124 190 . ' <br> '
125 - . __( 'It is not possible to store this sequence of the dates into the one same resource.' , 'booking' )
191 + . wpbc_frontend_messages__get( 'message_cannot_save_in_one_resource', array(), $local_params['resource_id'] )
126 192 . ' <br> '
127 - . __( 'Please choose alternative date(s), times, or adjust the number of slots booked.' , 'booking' )
193 + . wpbc_frontend_messages__get( 'message_choose_alternative_dates', array(), $local_params['resource_id'] )
128 194 . ' <a href="javascript:void(0)" onclick="'
129 195 .'jQuery( this ).next().toggle();'
130 196 .'jQuery( this).hide();'
131 197 .'jQuery( this ).parents(\'.wpbc_alert_message\').parent().on(\'hide\',function(even){jQuery(this).show();});'
@@ -168,11 +234,11 @@
168 234 // Bad not save
169 235 // We can not store booking in this date day_sql_key2, number of available child booking resources less than required
170 236 return array(
171 237 'result' => 'error',
172 - 'message' => __( 'These dates and times in this calendar are already booked or unavailable.', 'booking' )
238 + 'message' => wpbc_frontend_messages__get( 'message_dates_times_unavailable', array(), $local_params['resource_id'] )
173 239 . ' <br> '
174 - . __( 'Please choose alternative date(s), times, or adjust the number of slots booked.' , 'booking' )
240 + . wpbc_frontend_messages__get( 'message_choose_alternative_dates', array(), $local_params['resource_id'] )
175 241 . ' <a href="javascript:void(0)" onclick="'
176 242 .'jQuery( this ).next().toggle();'
177 243 .'jQuery( this).hide();'
178 244 .'jQuery( this ).parents(\'.wpbc_alert_message\').parent().on(\'hide\',function(even){jQuery(this).show();});'
@@ -185,8 +251,9 @@
185 251 . sprintf( __( 'Booking can not be saved in this date %1$s, number of available (single or child) booking resource(s) (%2$d) less than required (%3$d).', 'booking' )
186 252 , $day_sql_key2, count( $available_res_in_day_arr ), $how_many_items_to_book )
187 253 . '</strong><hr><code>'
188 254 . wp_json_encode( $available_slots )
255 + // . wp_json_encode( $local_params, $availability_per_days )
189 256 . '</code></p>'
190 257 . '</div>'
191 258
192 259 );
@@ -236,8 +303,9 @@
236 303 $defaults = array(
237 304 'dates_sql__arr' => array(),
238 305 'time_as_seconds_arr' => array(),
239 306 'availability_per_days' => array(),
307 + 'time_override_source' => '',
240 308 'is_use_booking_recurrent_time' => ( 'On' === get_bk_option( 'booking_recurrent_time' ) )
241 309 );
242 310 $params = wp_parse_args( $params, $defaults );
243 311
@@ -283,9 +351,9 @@
283 351 $date_bookings_obj = $params['availability_per_days']['dates'][ $sql_class_day ];
284 352
285 353 foreach ( $params['availability_per_days']['resources_id_arr__in_dates'] as $child_resource_id ) {
286 354
287 - $merged_seconds_arr = wpbc_get__booking_obj__merged_seconds_arr( $date_bookings_obj[ $child_resource_id ] );
355 + $merged_seconds_arr = wpbc_get__booking_obj__merged_seconds_arr( $date_bookings_obj[ $child_resource_id ], $params['time_override_source'] );
288 356
289 357 $is_intersect = wpbc_is_intersect__merged_seconds_arr__and__seconds_arr( $merged_seconds_arr['merged_seconds'], $this_date_time_as_seconds_arr );
290 358
291 359 $this_date_available_resource = array(
@@ -329,10 +397,24 @@
329 397 * 'merged_seconds' => $merged_seconds,
330 398 * 'merged_readable' => $merged_readable
331 399 * ]
332 400 */
333 - function wpbc_get__booking_obj__merged_seconds_arr( $date_booking_obj ) {
401 + function wpbc_get__booking_obj__merged_seconds_arr( $date_booking_obj, $time_override_source = '' ) {
334 402
403 + $is_times_availability_full_day_status = (
404 + ( 'times_availability' === $time_override_source )
405 + && ( ! empty( $date_booking_obj->is_day_unavailable ) )
406 + && ( ! empty( $date_booking_obj->_day_status ) )
407 + && ( 'full_day_booking' === $date_booking_obj->_day_status )
408 + );
409 +
410 + if ( $is_times_availability_full_day_status ) {
411 + $merged_seconds_arr = wpbc_get__booking_obj__booked_details_seconds_arr( $date_booking_obj );
412 + if ( ! empty( $merged_seconds_arr['merged_seconds'] ) ) {
413 + return $merged_seconds_arr;
414 + }
415 + }
416 +
335 417 if ( $date_booking_obj->is_day_unavailable ){
336 418 $merged_seconds = array( array( 0, 24 * 60 * 60 ) ); // Unavailable
337 419 $merged_readable = array( wpbc_transform_timerange__seconds_arr__in__formated_hours( array( 0, 24 * 60 * 60 ) ) );
338 420 } else {
@@ -343,8 +425,48 @@
343 425 return array(
344 426 'merged_seconds' => $merged_seconds,
345 427 'merged_readable' => $merged_readable
346 428 );
429 + }
430 +
431 +
432 + /**
433 + * Rebuild real booked intervals from details after capacity marks the whole day unavailable.
434 + *
435 + * @param object $date_booking_obj Availability object for a date/resource.
436 + *
437 + * @return array
438 + */
439 + function wpbc_get__booking_obj__booked_details_seconds_arr( $date_booking_obj ) {
440 +
441 + $seconds_arr = array();
442 + $readable_arr = array();
443 +
444 + if ( empty( $date_booking_obj->__booked__times__details ) || ! is_array( $date_booking_obj->__booked__times__details ) ) {
445 + return array(
446 + 'merged_seconds' => array(),
447 + 'merged_readable' => array(),
448 + );
449 + }
450 +
451 + foreach ( $date_booking_obj->__booked__times__details as $time_key => $details ) {
452 + if ( '0' === (string) $time_key || false === strpos( (string) $time_key, '-' ) ) {
453 + $seconds_arr[] = array( 0, 24 * 60 * 60 );
454 + } else {
455 + $seconds_arr[] = wpbc_transform_timerange__s_range__in__seconds_arr( $time_key );
456 + }
457 + }
458 +
459 + $seconds_arr = wpbc_merge_intersected_intervals( $seconds_arr );
460 +
461 + foreach ( $seconds_arr as $booked_time_slots__in_seconds ) {
462 + $readable_arr[] = wpbc_transform_timerange__seconds_arr__in__formated_hours( $booked_time_slots__in_seconds );
463 + }
464 +
465 + return array(
466 + 'merged_seconds' => $seconds_arr,
467 + 'merged_readable' => $readable_arr,
468 + );
347 469 }
348 470
349 471
350 472 /**