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/calendar_load.php +151 -35 11.011.8.3 View file →
@@ -1,4 +1,4 @@
1 1 <?php
2 2 /**
3 3 * @file: wp-content/plugins/booking/includes/_capacity/calendar_load.php
4 4 */
@@ -44,13 +44,15 @@
44 44 }
45 45 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . " , 'calendar_scroll_to' , " . $calendar_scroll_to . " ); ";
46 46
47 47 // Set Start / End Date in Calendar (JSON encode => safe quotes).
48 - $params['calendar_dates_start'] = ( empty( $params['calendar_dates_start'] ) ) ? '' : (string) $params['calendar_dates_start'];
49 - $params['calendar_dates_end'] = ( empty( $params['calendar_dates_end'] ) ) ? '' : (string) $params['calendar_dates_end'];
48 + $params['calendar_dates_start'] = ( empty( $params['calendar_dates_start'] ) ) ? '' : (string) $params['calendar_dates_start'];
49 + $params['calendar_dates_end'] = ( empty( $params['calendar_dates_end'] ) ) ? '' : (string) $params['calendar_dates_end'];
50 + $params['classic_booking_context_token'] = empty( $params['classic_booking_context_token'] ) ? '' : (string) $params['classic_booking_context_token'];
50 51
51 52 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . " , 'calendar_dates_start' , " . wp_json_encode( $params['calendar_dates_start'] ) . " ); ";
52 - $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . " , 'calendar_dates_end' , " . wp_json_encode( $params['calendar_dates_end'] ) . " ); ";
53 + $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . " , 'calendar_dates_end' , " . wp_json_encode( $params['calendar_dates_end'] ) . " ); ";
54 + $start_script_code .= " _wpbc.booking__set_param_value( " . $resource_id . " , 'classic_booking_context_token' , " . wp_json_encode( $params['classic_booking_context_token'] ) . " ); ";
53 55
54 56 if ( ( '' !== $params['calendar_dates_start'] ) || ( '' !== $params['calendar_dates_end'] ) ) {
55 57 $start_script_code .= wpbc_get_localized_js__time_local( $params['calendar_dates_start'] );
56 58 }
@@ -66,9 +68,9 @@
66 68 $months_num = max( 1, min( 36, $months_num ) );
67 69 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . " , 'calendar_number_of_months' , " . wp_json_encode( (string) $months_num ) . " ); ";
68 70
69 71 // Days Selection.
70 - $days_selection_arr = wpbc__calendar__js_params__get_days_selection_arr();
72 + $days_selection_arr = wpbc__calendar__js_params__get_days_selection_arr();
71 73
72 74 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'days_select_mode', " . wp_json_encode( (string) $days_selection_arr['days_select_mode'] ) . " ); ";
73 75 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'fixed__days_num', " . intval( $days_selection_arr['fixed__days_num'] ) . " ); ";
74 76
@@ -75,12 +77,32 @@
75 77 // Keep legacy: these are stored as comma lists like "-1" or "0,1".
76 78 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'fixed__week_days__start', [" . $days_selection_arr['fixed__week_days__start'] . "] ); ";
77 79 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'dynamic__days_min', " . intval( $days_selection_arr['dynamic__days_min'] ) . " ); ";
78 80 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'dynamic__days_max', " . intval( $days_selection_arr['dynamic__days_max'] ) . " ); ";
79 - $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'dynamic__days_specific', [" . $days_selection_arr['dynamic__days_specific'] . "] ); ";
80 - $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'dynamic__week_days__start', [" . $days_selection_arr['dynamic__week_days__start'] . "] ); ";
81 -
82 - // Date / Time formats.
81 + $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'dynamic__days_specific', [" . $days_selection_arr['dynamic__days_specific'] . "] ); ";
82 + $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'dynamic__week_days__start', [" . $days_selection_arr['dynamic__week_days__start'] . "] ); ";
83 +
84 + // Informational help shown between the first and second clicks in range mode.
85 + // Integrations can disable it per calendar/resource without changing the selection engine.
86 + /**
87 + * Filters whether the two-click range-selection guidance is shown for a calendar.
88 + *
89 + * @param bool $is_enabled Whether guidance is enabled.
90 + * @param int $resource_id Booking resource ID.
91 + * @param array $params Calendar shortcode/render parameters.
92 + */
93 + $range_selection_guidance_default = function_exists( 'wpbc_frontend_messages__is_enabled' )
94 + ? wpbc_frontend_messages__is_enabled( 'message_range_selection_click_last_date' )
95 + : true;
96 + $range_selection_guidance_is_enabled = (bool) apply_filters(
97 + 'wpbc_calendar_range_selection_guidance_is_enabled',
98 + $range_selection_guidance_default,
99 + $resource_id,
100 + $params
101 + );
102 + $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'range_selection_guidance_is_enabled', " . ( $range_selection_guidance_is_enabled ? 'true' : 'false' ) . " ); ";
103 +
104 + // Date / Time formats.
83 105 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'booking_date_format', " . wp_json_encode( (string) get_bk_option( 'booking_date_format' ) ) . " ); ";
84 106 $start_script_code .= " _wpbc.calendar__set_param_value( " . $resource_id . ", 'booking_time_format', " . wp_json_encode( (string) get_bk_option( 'booking_time_format' ) ) . " ); ";
85 107
86 108 // Capacity | availability.
@@ -114,21 +136,28 @@
114 136
115 137 /**
116 138 * Get days selection parameters, which saved in database
117 139 *
118 - * @return array
119 - */
120 - function wpbc__calendar__js_params__get_days_selection_arr(){
140 + * @return array
141 + */
142 + function wpbc__calendar__js_params__get_days_selection_arr(){
121 143
122 144 $specific_days_selection = ( function_exists( 'wpbc_get_specific_range_dates__as_comma_list' ) )
123 145 ? wpbc_get_specific_range_dates__as_comma_list( get_bk_option( 'booking_range_selection_days_specific_num_dynamic' ) )
124 146 : '';
125 - $data_arr = array();
126 - // Modes :: Selection of Days
127 - $data_arr['days_select_mode'] = ( 'range' === get_bk_option('booking_type_of_day_selections') )
128 - ? get_bk_option('booking_range_selection_type')
129 - : get_bk_option( 'booking_type_of_day_selections');
130 - $data_arr['fixed__days_num'] = intval( get_bk_option( 'booking_range_selection_days_count' ) ); /* Number of days selection with 1 mouse click */
147 + $data_arr = array();
148 + // Modes :: Selection of Days.
149 + $day_selection_type = get_bk_option( 'booking_type_of_day_selections' );
150 + if ( 'range' === $day_selection_type ) {
151 + // Free/Personal use the unrestricted two-click range. Business Small+ can apply its saved range subtype/rules.
152 + $data_arr['days_select_mode'] = class_exists( 'wpdev_bk_biz_s' )
153 + ? get_bk_option( 'booking_range_selection_type' )
154 + : 'dynamic';
155 + } else {
156 + $data_arr['days_select_mode'] = $day_selection_type;
157 + }
158 + $fixed_days_num = absint( get_bk_option( 'booking_range_selection_days_count' ) );
159 + $data_arr['fixed__days_num'] = ( 0 < $fixed_days_num ) ? min( 180, $fixed_days_num ) : 3; /* Number of days selection with 1 mouse click */
131 160 $data_arr['fixed__week_days__start'] = get_bk_option( 'booking_range_start_day' ); /* { -1 - Any | 0 - Su, 1 - Mo, 2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat } */
132 161 $data_arr['dynamic__days_min'] = intval( get_bk_option( 'booking_range_selection_days_count_dynamic' ) ); /* Min. Number of days selection with 2 mouse clicks */
133 162 $data_arr['dynamic__days_max'] = intval( get_bk_option( 'booking_range_selection_days_max_count_dynamic' ) ); /* Max. Number of days selection with 2 mouse clicks */
134 163 $data_arr['dynamic__days_specific'] = $specific_days_selection; /* Example: '5,7' */
@@ -133,12 +162,15 @@
133 162 $data_arr['dynamic__days_max'] = intval( get_bk_option( 'booking_range_selection_days_max_count_dynamic' ) ); /* Max. Number of days selection with 2 mouse clicks */
134 163 $data_arr['dynamic__days_specific'] = $specific_days_selection; /* Example: '5,7' */
135 164 $data_arr['dynamic__week_days__start'] = get_bk_option( 'booking_range_start_day_dynamic' ); /* { -1 - Any | 0 - Su, 1 - Mo, 2 - Tu, 3 - We, 4 - Th, 5 - Fr, 6 - Sat } */
136 165
137 - // Fix about possible issue of downgrade from Paid to free version and try to use 'Range days' selection, which is not supports in that version. // FixIn: 10.4.0.4.
138 - if ( ( ! class_exists( 'wpdev_bk_biz_s' ) ) && ( in_array( $data_arr['days_select_mode'], array( 'dynamic', 'fixed' ) ) ) ) {
139 - $data_arr['days_select_mode'] = 'multiple';
140 - }
166 + // A fixed one-click range remains Business Small+. On downgrade, preserve the Range choice but use Free's unrestricted two-click mode.
167 + if ( ( ! class_exists( 'wpdev_bk_biz_s' ) ) && ( in_array( $data_arr['days_select_mode'], array( 'dynamic', 'fixed' ), true ) ) ) {
168 + $data_arr['days_select_mode'] = 'dynamic';
169 + $data_arr['dynamic__days_min'] = 1;
170 + $data_arr['dynamic__days_specific'] = '';
171 + $data_arr['dynamic__week_days__start'] = '-1';
172 + }
141 173
142 174 return $data_arr;
143 175 }
144 176
@@ -163,11 +195,13 @@
163 195 'start_month_calendar' => false,
164 196 'shortcode_options' => '',
165 197 'custom_form' => 'standard',
166 198 'calendar_dates_start' => '',
167 - 'calendar_dates_end' => '',
199 + 'calendar_dates_end' => '',
200 + 'classic_booking_context_token' => '',
168 201 'skip_general_availability' => 0,
169 - );
202 + 'calendar_request_overrides' => array(),
203 + );
170 204 $params = wp_parse_args( $params, $defaults );
171 205
172 206 // Resource ID.
173 207 $params['resource_id'] = absint( $params['resource_id'] );
@@ -222,11 +256,22 @@
222 256 'request_uri' => $server_request_uri,
223 257 'custom_form' => (string) $params['custom_form'],
224 258 'aggregate_resource_id_str' => implode( ',', (array) $params['aggregate_resource_id_arr'] ),
225 259 'aggregate_type' => (string) $aggregate_type,
226 - 'skip_general_availability' => (int) $params['skip_general_availability'],
260 + 'skip_general_availability' => (int) $params['skip_general_availability'],
261 + 'classic_booking_context_token' => (string) $params['classic_booking_context_token'],
227 262 );
228 263
264 + if ( ! empty( $params['calendar_request_overrides'] ) && is_array( $params['calendar_request_overrides'] ) ) {
265 + foreach ( $params['calendar_request_overrides'] as $override_key => $override_value ) {
266 + if ( 'allow_past' === $override_key ) {
267 + $params_for_request['allow_past'] = ! empty( $override_value ) ? 1 : 0;
268 + } elseif ( 0 === strpos( (string) $override_key, 'wpbc_settings_calendar_preview' ) ) {
269 + $params_for_request[ $override_key ] = $override_value;
270 + }
271 + }
272 + }
273 +
229 274 // Send Ajax request to load bookings.
230 275 $js_body .= " wpbc_calendar__load_data__ajx(" . wp_json_encode( $params_for_request ) . "); ";
231 276
232 277 // ---------------------------------------------------------------------
@@ -316,19 +361,76 @@
316 361 'user_id' => $user_id,
317 362 'request_rules_structure' => array(
318 363 'resource_id' => array( 'validate' => 'd', 'default' => 1 ), // 'digit_or_csd'
319 364 'booking_hash' => array( 'validate' => 's', 'default' => '' ),
320 - 'request_uri' => array( 'validate' => 's', 'default' => '' ),
321 - 'custom_form' => array( 'validate' => 's', 'default' => 'standard' ),
365 + 'request_uri' => array( 'validate' => 's', 'default' => '' ),
366 + 'custom_form' => array( 'validate' => 's', 'default' => 'standard' ),
367 + 'allow_past' => array( 'validate' => 'd', 'default' => 0 ),
368 + 'classic_booking_context_token' => array( 'validate' => 'strong', 'default' => '' ),
322 369 'aggregate_resource_id_str' => array( 'validate' => 'digit_or_csd', 'default' => '' ), // Comma separated string of resource ID, which was used in 'aggregate' parameter.
323 370 'aggregate_type' => array( 'validate' => 's', 'default' => 'all' ), // 'all' | 'bookings_only' // FixIn: 9.8.15.10.
324 371 'dates_to_check' => array( 'validate' => 'array', 'default' => '' ), // 'all' | 'bookings_only' // FixIn: 9.8.15.10.
325 372 'skip_general_availability' => array( 'validate' => 'd', 'default' => 0 ),
373 + 'wpbc_settings_calendar_preview' => array( 'validate' => 'd', 'default' => 0 ),
374 + 'wpbc_settings_calendar_preview_changeover' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
375 + 'wpbc_settings_calendar_preview_triangles' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'On' ),
376 + 'wpbc_settings_calendar_preview_recurrent_time' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
377 + 'wpbc_settings_calendar_preview_last_checkout' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
378 + 'wpbc_settings_calendar_preview_excerpt_on_pages' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
379 + 'wpbc_settings_calendar_preview_excerpt_pages' => array( 'validate' => 's', 'default' => '' ),
380 + 'wpbc_settings_calendar_preview_excerpt_resources' => array( 'validate' => 's', 'default' => '' ),
381 + 'wpbc_settings_calendar_preview_show_legend' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
382 + 'wpbc_settings_calendar_preview_legend_show_numbers' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
383 + 'wpbc_settings_calendar_preview_legend_vertical' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
384 + 'wpbc_settings_calendar_preview_legend_show_available' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
385 + 'wpbc_settings_calendar_preview_legend_text_available' => array( 'validate' => 's', 'default' => '' ),
386 + 'wpbc_settings_calendar_preview_legend_show_pending' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
387 + 'wpbc_settings_calendar_preview_legend_text_pending' => array( 'validate' => 's', 'default' => '' ),
388 + 'wpbc_settings_calendar_preview_legend_show_approved' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
389 + 'wpbc_settings_calendar_preview_legend_text_approved' => array( 'validate' => 's', 'default' => '' ),
390 + 'wpbc_settings_calendar_preview_legend_show_partially' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
391 + 'wpbc_settings_calendar_preview_legend_text_partially' => array( 'validate' => 's', 'default' => '' ),
392 + 'wpbc_settings_calendar_preview_legend_show_unavailable' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
393 + 'wpbc_settings_calendar_preview_legend_text_unavailable' => array( 'validate' => 's', 'default' => '' ),
394 + 'wpbc_settings_calendar_preview_disable_timeslots_tooltip' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
395 + 'wpbc_settings_calendar_preview_timeslot_word' => array( 'validate' => 's', 'default' => '' ),
396 + 'wpbc_settings_calendar_preview_show_availability_tooltip' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
397 + 'wpbc_settings_calendar_preview_availability_word' => array( 'validate' => 's', 'default' => '' ),
398 + 'wpbc_settings_calendar_preview_show_availability_cell' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
399 + 'wpbc_settings_calendar_preview_availability_cell_word' => array( 'validate' => 's', 'default' => '' ),
400 + 'wpbc_settings_calendar_preview_show_cost_tooltip' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
401 + 'wpbc_settings_calendar_preview_cost_word' => array( 'validate' => 's', 'default' => '' ),
402 + 'wpbc_settings_calendar_preview_show_cost_cell' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
403 + 'wpbc_settings_calendar_preview_cost_currency' => array( 'validate' => 's', 'default' => '' ),
404 + 'wpbc_settings_calendar_preview_show_booked_details' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ),
405 + 'wpbc_settings_calendar_preview_booked_details' => array( 'validate' => 's', 'default' => '' ),
326 406 )
327 407 )
328 408 );
329 - $request_prefix = 'calendar_request_params';
330 - $request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['search_params']['resource_id']
409 + $request_prefix = 'calendar_request_params';
410 + $request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['search_params']['resource_id']
411 + if ( ! empty( $request_params['classic_booking_context_token'] ) && function_exists( 'wpbc_classic_booking_context_validate_submission' ) ) {
412 + $classic_context = wpbc_classic_booking_context_validate_submission(
413 + $request_params['classic_booking_context_token'],
414 + $request_params['resource_id'],
415 + $request_params['dates_to_check'],
416 + $request_params['custom_form'],
417 + $request_params['aggregate_resource_id_str']
418 + );
419 + if ( ! is_wp_error( $classic_context ) ) {
420 + $request_params['allow_past'] = ! empty( $classic_context['allow_past'] ) ? 1 : 0;
421 + // Use the signed canonical set so equivalent wire shapes cannot change availability input.
422 + $request_params['aggregate_resource_id_str'] = implode( ',', $classic_context['aggregate_resource_ids'] );
423 + $request_params['dates_to_check'] = array(
424 + $classic_context['calendar_dates_start'],
425 + $classic_context['calendar_dates_end'],
426 + );
427 + } else {
428 + $request_params['allow_past'] = 0;
429 + }
430 + }
431 + $can_allow_past = ! empty( $request_params['allow_past'] );
432 + $request_params['allow_past'] = $can_allow_past ? 1 : 0;
331 433
332 434 if ( ! empty( $request_params['skip_general_availability'] ) ) {
333 435 $can_skip_general_availability = (
334 436 function_exists( 'wpbc_availability_general__get_manage_cap' )
@@ -357,14 +459,15 @@
357 459 unset( $aggregate_resource_id_arr[ $resource_id_key ] ); // Remove source booking resource from aggregate ARR. // FixIn: 9.8.15.10.
358 460 }
359 461 $aggregate_resource_id_arr = array_values($aggregate_resource_id_arr); // Reset keys
360 462
361 - $availability_per_days__params = array(
362 - 'resource_id' => $request_params['resource_id'],
363 - 'max_days_count' => $max_days_count,
364 - 'skip_booking_id' => $skip_booking_id,
365 - 'request_uri' => $request_params['request_uri'], // It different in Ajax requests than $server_request_uri . It's used for change-over days to detect for exception at specific pages
366 - 'custom_form' => $request_params['custom_form']
463 + $availability_per_days__params = array(
464 + 'resource_id' => $request_params['resource_id'],
465 + 'max_days_count' => $max_days_count,
466 + 'skip_booking_id' => $skip_booking_id,
467 + 'request_uri' => $request_params['request_uri'], // It different in Ajax requests than $server_request_uri . It's used for change-over days to detect for exception at specific pages
468 + 'custom_form' => $request_params['custom_form'],
469 + 'allow_past' => ! empty( $request_params['allow_past'] )
367 470 , 'additional_bk_types' => $aggregate_resource_id_arr // It is array of booking resources from aggregate parameter() // arrays | CSD | int // OPTIONAL
368 471 , 'aggregate_type' => $request_params['aggregate_type'] // It is string: 'all' | 'bookings_only' // OPTIONAL
369 472 , 'skip_general_availability' => $request_params['skip_general_availability']
370 473 // , 'as_single_resource' => true // get dates as for 'single resource' or 'parent' resource including bookings in all 'child booking resources'
@@ -395,9 +498,14 @@
395 498 // Get unavailable dates for calendar
396 499 // $availability_per_days__params['dates_to_check'] = array( '2025-01-01', '2025-12-31' ); // FixIn: 10.13.1.4.
397 500 global $wpbc__skip_get_bk_options;
398 501
399 - $previous_skip_get_bk_options = $wpbc__skip_get_bk_options;
502 + $previous_skip_get_bk_options = $wpbc__skip_get_bk_options;
503 + $previous_settings_calendar_preview_options = null;
504 + $is_settings_calendar_preview = (
505 + function_exists( 'wpbc_settings_calendar__is_calendar_load_preview_request_allowed' )
506 + && wpbc_settings_calendar__is_calendar_load_preview_request_allowed( $request_params )
507 + );
400 508 if ( ! empty( $availability_per_days__params['skip_general_availability'] ) ) {
401 509 $wpbc__skip_get_bk_options = array_unique(
402 510 array_merge(
403 511 (array) $wpbc__skip_get_bk_options,
@@ -404,11 +512,19 @@
404 512 wpbc__calendar__get_general_availability_option_names()
405 513 )
406 514 );
407 515 }
516 + if ( $is_settings_calendar_preview ) {
517 + $previous_settings_calendar_preview_options = wpbc_settings_calendar__preview_options_push(
518 + wpbc_settings_calendar__get_calendar_load_preview_options( $request_params )
519 + );
520 + }
408 521
409 522 $availability_per_days_arr = wpbc_get_availability_per_days_arr( $availability_per_days__params );
410 523 $wpbc__skip_get_bk_options = $previous_skip_get_bk_options;
524 + if ( $is_settings_calendar_preview ) {
525 + wpbc_settings_calendar__preview_options_pop( $previous_settings_calendar_preview_options );
526 + }
411 527
412 528
413 529 $ajx_data_arr = array( /**
414 530 * Send JSON. It will make "wp_json_encode" - so pass only array, and This function call wp_die( '', '', array( 'response' => null, ) ) .