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 +98 -13 10.15.711.8.4 View file →
@@ -54,10 +54,12 @@
54 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 */
55 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 */
56 56 $defaults = array(
57 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,
58 59 'as_single_resource' => false,
59 60 'is_use_booking_recurrent_time' => ( 'On' === get_bk_option( 'booking_recurrent_time' ) ),
61 + 'time_override_source' => '',
60 62 'aggregate_resource_id_arr' => array(),
61 63 'custom_form' => '' //FixIn: 10.0.0.10 // Required for checking all available time-slots and compare with booked time slots
62 64 );
63 65 $local_params = wp_parse_args( $local_params, $defaults );
@@ -90,8 +92,9 @@
90 92 'resource_id' => $local_params['resource_id'],
91 93 'skip_booking_id' => $local_params['skip_booking_id'],
92 94 'dates_to_check' => $maybe_extended__dates_to_check_arr,
93 95 'request_uri' => $local_params['request_uri'],
96 + 'allow_past' => ! empty( $local_params['allow_past'] ),
94 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' .
95 98 'additional_bk_types' => $local_params['aggregate_resource_id_arr'],
96 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.
97 100 'custom_form' => $local_params['custom_form'], // FixIn: 10.0.0.10.
@@ -96,16 +99,42 @@
96 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.
97 100 'custom_form' => $local_params['custom_form'], // FixIn: 10.0.0.10.
98 101 ) , $availability_per_days_arr__params ) );
99 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 +
100 134 // Get value of how many booking resources to book
101 135 $how_many_items_to_book = $local_params['how_many_items_to_book'];
102 136
103 - // FixIn: 2981-01-13 13 Jan 2981.
104 - if ( ( ! empty( $local_params['dates_only_sql_arr'] ) ) && ( wpbc_is_these_dates__for__no_dates( $local_params['dates_only_sql_arr'] ) ) ) {
105 - $how_many_items_to_book = 0;
106 - }
107 -
108 137 // -------------------------------------------------------------------------------------------------------------
109 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: [...] ]
110 139 $available_slots = wpbc__get_available_slots__for_selected_dates_times__bl( array(
111 140 'dates_sql__arr' => $local_params['dates_only_sql_arr'],
@@ -110,14 +139,15 @@
110 139 $available_slots = wpbc__get_available_slots__for_selected_dates_times__bl( array(
111 140 'dates_sql__arr' => $local_params['dates_only_sql_arr'],
112 141 'time_as_seconds_arr' => $local_params['time_as_seconds_arr'],
113 142 'is_use_booking_recurrent_time' => $local_params['is_use_booking_recurrent_time'],
143 + 'time_override_source' => $local_params['time_override_source'],
114 144 'availability_per_days' => $availability_per_days
115 145 ) );
116 146
117 147 $main__resource_id = 0;
118 148 // == In SAME 'child' booking resources ============================================================
119 - 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' ) ) ) {
120 150
121 151 $availability_in_same_child_resources = $availability_per_days['resources_id_arr__in_dates'];
122 152
123 153 foreach ( $availability_per_days['resources_id_arr__in_dates'] as $child_resource_id ) {
@@ -155,13 +185,13 @@
155 185 } else {
156 186 // Bad not save
157 187 return array(
158 188 'result' => 'error',
159 - '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'] )
160 190 . ' <br> '
161 - . __( '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'] )
162 192 . ' <br> '
163 - . __( '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'] )
164 194 . ' <a href="javascript:void(0)" onclick="'
165 195 .'jQuery( this ).next().toggle();'
166 196 .'jQuery( this).hide();'
167 197 .'jQuery( this ).parents(\'.wpbc_alert_message\').parent().on(\'hide\',function(even){jQuery(this).show();});'
@@ -204,11 +234,11 @@
204 234 // Bad not save
205 235 // We can not store booking in this date day_sql_key2, number of available child booking resources less than required
206 236 return array(
207 237 'result' => 'error',
208 - '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'] )
209 239 . ' <br> '
210 - . __( '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'] )
211 241 . ' <a href="javascript:void(0)" onclick="'
212 242 .'jQuery( this ).next().toggle();'
213 243 .'jQuery( this).hide();'
214 244 .'jQuery( this ).parents(\'.wpbc_alert_message\').parent().on(\'hide\',function(even){jQuery(this).show();});'
@@ -273,8 +303,9 @@
273 303 $defaults = array(
274 304 'dates_sql__arr' => array(),
275 305 'time_as_seconds_arr' => array(),
276 306 'availability_per_days' => array(),
307 + 'time_override_source' => '',
277 308 'is_use_booking_recurrent_time' => ( 'On' === get_bk_option( 'booking_recurrent_time' ) )
278 309 );
279 310 $params = wp_parse_args( $params, $defaults );
280 311
@@ -320,9 +351,9 @@
320 351 $date_bookings_obj = $params['availability_per_days']['dates'][ $sql_class_day ];
321 352
322 353 foreach ( $params['availability_per_days']['resources_id_arr__in_dates'] as $child_resource_id ) {
323 354
324 - $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'] );
325 356
326 357 $is_intersect = wpbc_is_intersect__merged_seconds_arr__and__seconds_arr( $merged_seconds_arr['merged_seconds'], $this_date_time_as_seconds_arr );
327 358
328 359 $this_date_available_resource = array(
@@ -366,10 +397,24 @@
366 397 * 'merged_seconds' => $merged_seconds,
367 398 * 'merged_readable' => $merged_readable
368 399 * ]
369 400 */
370 - 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 = '' ) {
371 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 +
372 417 if ( $date_booking_obj->is_day_unavailable ){
373 418 $merged_seconds = array( array( 0, 24 * 60 * 60 ) ); // Unavailable
374 419 $merged_readable = array( wpbc_transform_timerange__seconds_arr__in__formated_hours( array( 0, 24 * 60 * 60 ) ) );
375 420 } else {
@@ -380,8 +425,48 @@
380 425 return array(
381 426 'merged_seconds' => $merged_seconds,
382 427 'merged_readable' => $merged_readable
383 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 + );
384 469 }
385 470
386 471
387 472 /**