PluginProbe
Booking Calendar / 11.8
Booking Calendar v11.8
11.9 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 All 205 releases
booking / includes / page-add-booking / add_booking__component.php

add_booking__component.php in Booking Calendar 11.8, at includes/page-add-booking/add_booking__component.php

468 lines 18.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php /**
2 * @version 1.0
3 * @package Booking Calendar
4 * @category Reusable Add Booking component
5 */
6
7 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
8
9 /**
10 * Reusable renderer for the Booking > Add Booking experience.
11 *
12 * The admin page calls this without args, so legacy $_GET driven behavior stays intact.
13 * Future embedded contexts can pass explicit args, which are always preferred over $_GET.
14 */
15 class WPBC_Add_Booking_Component {
16
17 /**
18 * Check if current user can access the Add Booking workflow.
19 *
20 * @return bool
21 */
22 public static function current_user_can_add_booking() {
23
24 $user_role = get_bk_option( 'booking_user_role_addbooking' );
25 $cap = 'read';
26
27 if ( class_exists( 'WPBC_Admin_Menus' ) && isset( WPBC_Admin_Menus::$capability[ $user_role ] ) ) {
28 $cap = WPBC_Admin_Menus::$capability[ $user_role ];
29 } elseif ( class_exists( 'WPBC_Admin_Menus' ) && isset( WPBC_Admin_Menus::$capability['subscriber'] ) ) {
30 $cap = WPBC_Admin_Menus::$capability['subscriber'];
31 }
32
33 return current_user_can( $cap );
34 }
35
36 /**
37 * Render the component and echo by default.
38 *
39 * @param array $args Component options.
40 *
41 * @return string|void
42 */
43 public static function render( $args = array() ) {
44
45 $args = self::normalize_args( $args );
46 $is_echo = ( ! empty( $args['is_echo'] ) );
47
48 ob_start();
49
50 ?><span class="wpdevelop"><?php // BS UI CSS Class.
51
52 if ( ! empty( $args['is_booking_page_js'] ) ) {
53 wpbc_js_for_bookings_page(); // JavaScript functions.
54 }
55
56 if ( ! empty( $args['is_toolbar_visible'] ) ) {
57 wpbc_add_new_booking_toolbar(
58 array(
59 'resource_id' => $args['_is_explicit_resource_id'] ? $args['resource_id'] : null,
60 'booking_form' => $args['_is_explicit_booking_form'] ? $args['custom_booking_form'] : null,
61 )
62 );
63 }
64
65 ?></span><!-- wpdevelop class --><?php
66
67 if ( ! empty( $args['is_show_before_content_spacer'] ) ) {
68 ?><div class="clear" style="height:40px;"></div><?php
69 }
70
71 ?><div class="<?php echo esc_attr( $args['content_css_class'] ); ?>" style="<?php echo esc_attr( $args['content_style'] ); ?>"><?php
72
73 self::print_context_js( $args );
74
75 WPBC_FE_Render::render_booking_form(
76 array(
77 'resource_id' => $args['resource_id'],
78 'cal_count' => $args['cal_count'],
79 'is_echo' => 1,
80 'custom_booking_form' => $args['custom_booking_form'],
81 'selected_dates_without_calendar' => $args['selected_dates_without_calendar'],
82 'start_month_calendar' => $args['start_month_calendar'],
83 'shortcode_param__options' => $args['shortcode_param__options'],
84 'calendar_dates_start' => $args['calendar_dates_start'],
85 'calendar_dates_end' => $args['calendar_dates_end'],
86 'booking_hash' => $args['booking_hash'],
87 )
88 );
89
90 ?></div><?php
91
92 if ( ! empty( $args['is_show_footer_email_toggle'] ) ) {
93 ?><hr /><?php
94 wpbc_toolbar_is_send_emails_btn_duplicated();
95 }
96
97 if ( ! empty( $args['is_booking_page_popover'] ) ) {
98 wpbc_bs_javascript_popover(); // JS Popover.
99 }
100
101 $html = ob_get_clean();
102
103 if ( $is_echo ) {
104 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
105 return;
106 }
107
108 return $html;
109 }
110
111
112 /**
113 * Normalize component args.
114 *
115 * Explicit args are preferred first. Empty/non-provided args fall back to legacy $_GET behavior.
116 *
117 * @param array $args Component options.
118 *
119 * @return array
120 */
121 private static function normalize_args( $args ) {
122
123 $defaults = array(
124 'resource_id' => null,
125 'booking_type' => null,
126 'booking_form' => null,
127 'custom_booking_form' => null,
128 'calendar_options' => null,
129 'cal_count' => null,
130 'calendar_months_count' => null,
131 'shortcode_param__options' => null,
132 'selected_dates_without_calendar' => null,
133 'start_month_calendar' => false,
134 'calendar_dates_start' => '',
135 'calendar_dates_end' => '',
136 'booking_hash' => '',
137 'allow_past' => null,
138 'selected_dates' => '',
139 'selected_date' => '',
140 'selected_time' => '',
141 'time_override_enabled' => 0,
142 'time_override_source' => '',
143 'time_override_start' => '',
144 'time_override_end' => '',
145 'is_toolbar_visible' => true,
146 'is_booking_page_js' => true,
147 'is_booking_page_popover' => true,
148 'is_show_before_content_spacer' => true,
149 'is_show_footer_email_toggle' => true,
150 'content_css_class' => 'add_booking_page_content',
151 'content_style' => 'width:100%;margin-bottom:100px;',
152 'is_echo' => 1,
153 );
154 $args = wp_parse_args( $args, $defaults );
155
156 $args['_is_explicit_resource_id'] = ( ( null !== $args['resource_id'] ) && ( absint( $args['resource_id'] ) > 0 ) )
157 || ( ( null !== $args['booking_type'] ) && ( absint( $args['booking_type'] ) > 0 ) );
158 $args['_is_explicit_booking_form'] = ( ( null !== $args['custom_booking_form'] ) && ( '' !== (string) $args['custom_booking_form'] ) )
159 || ( ( null !== $args['booking_form'] ) && ( '' !== (string) $args['booking_form'] ) );
160
161 $resource_id = self::get_explicit_or_get_resource_id( $args );
162 $form_name = self::get_explicit_or_get_booking_form( $args, $resource_id );
163
164 $calendar_params = self::get_calendar_params( $args );
165
166 $args['resource_id'] = $resource_id;
167 $args['custom_booking_form'] = $form_name;
168 $args['cal_count'] = $calendar_params['months_number'];
169 $args['shortcode_param__options'] = $calendar_params['shortcode_param__options'];
170
171 $args['selected_dates_without_calendar'] = ( null !== $args['selected_dates_without_calendar'] ) ? (string) $args['selected_dates_without_calendar'] : '';
172 $args['calendar_dates_start'] = (string) $args['calendar_dates_start'];
173 $args['calendar_dates_end'] = (string) $args['calendar_dates_end'];
174 $args['booking_hash'] = ( '' !== (string) $args['booking_hash'] ) ? sanitize_text_field( wp_unslash( (string) $args['booking_hash'] ) ) : ( isset( $_GET['booking_hash'] ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
175 $args['allow_past'] = ( null !== $args['allow_past'] ) ? ( ! empty( $args['allow_past'] ) ? 1 : 0 ) : ( isset( $_GET['allow_past'] ) ? 1 : 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
176 $args['selected_dates'] = sanitize_text_field( wp_unslash( (string) $args['selected_dates'] ) );
177 $args['selected_date'] = sanitize_text_field( wp_unslash( (string) $args['selected_date'] ) );
178 $args['selected_time'] = sanitize_text_field( wp_unslash( (string) $args['selected_time'] ) );
179 $args['time_override_enabled'] = ! empty( $args['time_override_enabled'] ) ? 1 : 0;
180 $args['time_override_source'] = sanitize_key( wp_unslash( (string) $args['time_override_source'] ) );
181 $args['time_override_start'] = sanitize_text_field( wp_unslash( (string) $args['time_override_start'] ) );
182 $args['time_override_end'] = sanitize_text_field( wp_unslash( (string) $args['time_override_end'] ) );
183
184 return $args;
185 }
186
187
188 /**
189 * Print per-render context that legacy front-end JavaScript reads from the global _wpbc object.
190 *
191 * @param array $args Component options.
192 *
193 * @return void
194 */
195 private static function print_context_js( $args ) {
196
197 $booking_hash = isset( $args['booking_hash'] ) ? (string) $args['booking_hash'] : '';
198 $admin_booking_nonce = self::current_user_can_add_booking() ? wp_create_nonce( 'wpbc_admin_booking_create' ) : '';
199 $allow_past_date_arr = self::get_allow_past_min_date_arr( $args );
200 $context = array(
201 'resource_id' => absint( $args['resource_id'] ),
202 'selected_dates_without_calendar' => (string) $args['selected_dates_without_calendar'],
203 'selected_dates' => (string) $args['selected_dates'],
204 'selected_date' => (string) $args['selected_date'],
205 'selected_time' => (string) $args['selected_time'],
206 'time_override_enabled' => absint( $args['time_override_enabled'] ),
207 'time_override_source' => (string) $args['time_override_source'],
208 'time_override_start' => (string) $args['time_override_start'],
209 'time_override_end' => (string) $args['time_override_end'],
210 'allow_past' => ! empty( $args['allow_past'] ) ? 1 : 0,
211 );
212 ?>
213 <script type="text/javascript">
214 window.wpbc_add_booking_component_context = <?php echo wp_json_encode( $context ); ?>;
215 if ( 'undefined' !== typeof _wpbc ) {
216 _wpbc.set_other_param( 'this_page_booking_hash', <?php echo wp_json_encode( $booking_hash ); ?> );
217 _wpbc.set_other_param( 'this_page_allow_past', <?php echo wp_json_encode( ! empty( $args['allow_past'] ) ? 1 : 0 ); ?> );
218 _wpbc.set_other_param( 'this_page_allow_past_arr', <?php echo wp_json_encode( $allow_past_date_arr ); ?> );
219 _wpbc.set_other_param( 'this_page_admin_booking_nonce', <?php echo wp_json_encode( $admin_booking_nonce ); ?> );
220 }
221 </script>
222 <?php
223 }
224
225
226 /**
227 * Get minimum date array for modal/admin contexts that allow selecting past days.
228 *
229 * @param array $args Component options.
230 *
231 * @return array
232 */
233 public static function get_allow_past_min_date_arr( $args ) {
234
235 if ( empty( $args['allow_past'] ) && empty( $args['booking_hash'] ) ) {
236 return array();
237 }
238
239 if (
240 ! function_exists( 'wpbc_get_max_visible_days_in_calendar' )
241 || ! function_exists( 'wpbc_datetime_localized__use_wp_timezone' )
242 || ! function_exists( 'wpbc_csv_numbers_to_int_array' )
243 ) {
244 return array();
245 }
246
247 $gmt_time = gmdate( 'Y-m-d H:i:s', strtotime( '-' . intval( wpbc_get_max_visible_days_in_calendar() ) . ' days' ) );
248 $local_csv = wpbc_datetime_localized__use_wp_timezone( $gmt_time, 'Y,m,d,H,i' );
249
250 return wpbc_csv_numbers_to_int_array( $local_csv );
251 }
252
253
254 /**
255 * Resolve booking resource id: explicit component args first, then legacy $_GET.
256 *
257 * @param array $args Component options.
258 *
259 * @return int
260 */
261 private static function get_explicit_or_get_resource_id( $args ) {
262
263 if ( ( null !== $args['resource_id'] ) && ( absint( $args['resource_id'] ) > 0 ) ) {
264 return absint( $args['resource_id'] );
265 }
266
267 if ( ( null !== $args['booking_type'] ) && ( absint( $args['booking_type'] ) > 0 ) ) {
268 return absint( $args['booking_type'] );
269 }
270
271 if ( isset( $_GET['booking_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
272 return intval( $_GET['booking_type'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
273 }
274
275 return 1;
276 }
277
278
279 /**
280 * Resolve default booking form for specific booking resource.
281 *
282 * @param int $resource_id Booking resource ID.
283 * @param string $default_form Fallback form name.
284 *
285 * @return string
286 */
287 public static function get_default_booking_form_for_resource( $resource_id, $default_form = 'standard' ) {
288
289 $resource_id = absint( $resource_id );
290 $default_form = ( '' !== (string) $default_form ) ? (string) $default_form : 'standard';
291
292 if ( $resource_id <= 0 ) {
293 return sanitize_text_field( wp_unslash( $default_form ) );
294 }
295
296 $default_custom_form_name = '';
297 if ( function_exists( 'apply_bk_filter' ) ) {
298 $default_custom_form_name = apply_bk_filter( 'wpbc_get_default_custom_form', '', $resource_id );
299 }
300
301 if (
302 ( '' === (string) $default_custom_form_name )
303 && class_exists( 'WPBC_FE_Custom_Form_Helper' )
304 && method_exists( 'WPBC_FE_Custom_Form_Helper', 'get_default_custom_form__for__booking_resource' )
305 ) {
306 $default_custom_form_name = WPBC_FE_Custom_Form_Helper::get_default_custom_form__for__booking_resource( $resource_id );
307 }
308
309 $default_custom_form_name = sanitize_text_field( wp_unslash( (string) $default_custom_form_name ) );
310
311 return ( '' !== $default_custom_form_name ) ? $default_custom_form_name : sanitize_text_field( wp_unslash( $default_form ) );
312 }
313
314
315 /**
316 * Resolve booking form: explicit component args first, then legacy $_GET, then resource default.
317 *
318 * @param array $args Component options.
319 * @param int $resource_id Booking resource ID.
320 *
321 * @return string
322 */
323 private static function get_explicit_or_get_booking_form( $args, $resource_id = 0 ) {
324
325 if ( ( null !== $args['custom_booking_form'] ) && ( '' !== (string) $args['custom_booking_form'] ) ) {
326 return sanitize_text_field( wp_unslash( (string) $args['custom_booking_form'] ) );
327 }
328
329 if ( ( null !== $args['booking_form'] ) && ( '' !== (string) $args['booking_form'] ) ) {
330 return sanitize_text_field( wp_unslash( (string) $args['booking_form'] ) );
331 }
332
333 if ( WPBC_GET_Request::has_non_empty_get( 'booking_form' ) ) {
334 return WPBC_GET_Request::get_sanitized( 'booking_form' );
335 }
336
337 return self::get_default_booking_form_for_resource( $resource_id, 'standard' );
338 }
339
340
341 /**
342 * Resolve calendar settings for the component.
343 *
344 * @param array $args Component options.
345 *
346 * @return array
347 */
348 private static function get_calendar_params( $args ) {
349
350 if ( null !== $args['calendar_options'] && is_array( $args['calendar_options'] ) ) {
351 $calendar_options = self::format_calendar_options( $args['calendar_options'] );
352 } else {
353 $calendar_options = self::get_saved_user_calendar_options();
354 }
355
356 if ( null !== $args['calendar_months_count'] ) {
357 $calendar_options['months_number'] = absint( $args['calendar_months_count'] );
358 }
359
360 if ( null !== $args['cal_count'] ) {
361 $calendar_options['months_number'] = absint( $args['cal_count'] );
362 }
363
364 if ( empty( $calendar_options['months_number'] ) ) {
365 $calendar_options['months_number'] = 1;
366 }
367
368 if ( null !== $args['shortcode_param__options'] ) {
369 $shortcode_param__options = (string) $args['shortcode_param__options'];
370 } else {
371 $shortcode_param__options = '{calendar' . $calendar_options['options_param'] . '}';
372 }
373
374 return array(
375 'months_number' => absint( $calendar_options['months_number'] ),
376 'shortcode_param__options' => $shortcode_param__options,
377 );
378 }
379
380
381 /**
382 * Get Calendar Options of specific User.
383 *
384 * @return array Number of months and calendar options parameter.
385 */
386 public static function get_saved_user_calendar_options() {
387
388 return self::format_calendar_options( self::get_saved_user_calendar_settings() );
389 }
390
391
392 /**
393 * Get the raw per-user Add Booking calendar settings.
394 *
395 * The inspector needs the individual saved fields, while
396 * get_saved_user_calendar_options() preserves the renderer-formatted public
397 * result used by the Booking Form component.
398 *
399 * @return array<string,mixed> Raw saved calendar settings.
400 */
401 public static function get_saved_user_calendar_settings() {
402
403 $user_calendar_options = get_user_option( 'booking_custom_' . 'add_booking_calendar_options', wpbc_get_current_user_id() );
404
405 if ( false === $user_calendar_options ) {
406 $user_calendar_options = array();
407 } else {
408 $user_calendar_options = maybe_unserialize( $user_calendar_options );
409 }
410
411 return is_array( $user_calendar_options ) ? $user_calendar_options : array();
412 }
413
414
415 /**
416 * Convert calendar option values to the shortcode option string used by the renderer.
417 *
418 * @param array $user_calendar_options Raw calendar options.
419 *
420 * @return array
421 */
422 private static function format_calendar_options( $user_calendar_options ) {
423
424 $defaults = array(
425 'calendar_months_count' => 1,
426 'calendar_months_num_in_1_row' => 0,
427 'calendar_width' => '',
428 'calendar_widthunits' => 'px',
429 'calendar_cell_height' => '',
430 'calendar_cell_heightunits' => 'px',
431 );
432
433 $user_calendar_options = wp_parse_args( (array) $user_calendar_options, $defaults );
434
435 if ( ! empty( $user_calendar_options['calendar_months_count'] ) ) {
436 $selected_calendar_months_count = intval( $user_calendar_options['calendar_months_count'] );
437 } else {
438 $selected_calendar_months_count = 1;
439 }
440
441 if ( ! empty( $user_calendar_options['calendar_months_num_in_1_row'] ) ) {
442 $option_months_num_in_row = ' months_num_in_row=' . intval( $user_calendar_options['calendar_months_num_in_1_row'] );
443 } else {
444 $option_months_num_in_row = '';
445 }
446
447 if ( ! empty( $user_calendar_options['calendar_width'] ) ) {
448 $unit_value = ( esc_attr( $user_calendar_options['calendar_widthunits'] ) == 'percent' ) ? '%' : esc_attr( $user_calendar_options['calendar_widthunits'] );
449 $option_width = ' width=' . intval( $user_calendar_options['calendar_width'] ) . $unit_value;
450 $option_width .= ' strong_width=' . intval( $user_calendar_options['calendar_width'] ) . $unit_value; // FixIn: 9.3.1.6.
451 } else {
452 $option_width = '';
453 }
454
455 if ( ! empty( $user_calendar_options['calendar_cell_height'] ) ) {
456 $unit_value = ( esc_attr( $user_calendar_options['calendar_cell_heightunits'] ) == 'percent' ) ? '%' : esc_attr( $user_calendar_options['calendar_cell_heightunits'] );
457 $option_cell_height = ' cell_height=' . intval( $user_calendar_options['calendar_cell_height'] ) . $unit_value;
458 } else {
459 $option_cell_height = '';
460 }
461
462 return array(
463 'months_number' => $selected_calendar_months_count,
464 'options_param' => $option_months_num_in_row . $option_width . $option_cell_height,
465 );
466 }
467 }
468