PluginProbe
Booking Calendar / 11.5
Booking Calendar v11.5
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__modal.php

add_booking__modal.php in Booking Calendar 11.5, at includes/page-add-booking/add_booking__modal.php

705 lines 26.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Add Booking modal for Booking Listing and Timeline.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit, if accessed directly.
10 }
11
12 /**
13 * Class WPBC_Add_Booking_Modal
14 */
15 class WPBC_Add_Booking_Modal {
16
17 const AJAX_ACTION = 'WPBC_AJX_ADD_BOOKING_MODAL';
18
19 /**
20 * Print top toolbar button for opening the Add Booking popup.
21 *
22 * @param string $page_tag Current page tag.
23 * @param string $active_page_tab Current tab.
24 * @param string $active_page_subtab Current subtab.
25 *
26 * @return false|void
27 */
28 public static function print_top_toolbar_button( $page_tag, $active_page_tab, $active_page_subtab ) {
29
30 if ( ( 'wpbc' !== $page_tag ) || ! in_array( $active_page_tab, array( 'vm_booking_listing', 'vm_calendar' ), true ) ) {
31 return false;
32 }
33
34 if ( ! WPBC_Add_Booking_Component::current_user_can_add_booking() ) {
35 return false;
36 }
37
38 ?>
39 <div class="wpbc_ui_el__buttons_group wpbc_booking_listing__top_toolbar_group">
40 <a href="javascript:void(0);"
41 id="wpbc_booking_listing_add_booking_button"
42 class="button button-primary"
43 onclick="wpbc_boo_listing__click__add_booking_modal( { mode: 'add' } );"
44 title="<?php esc_attr_e( 'Create booking without leaving this view', 'booking' ); ?>">
45 <i class="menu_icon icon-1x wpbc-bi-plus"></i>&nbsp;
46 <?php esc_html_e( 'New booking', 'booking' ); ?>
47 </a>
48 </div>
49 <?php
50 }
51
52
53 /**
54 * Get template for modal window.
55 *
56 * @return void
57 */
58 public static function template_for_modal() {
59
60 $nonce = wp_create_nonce( strtolower( self::AJAX_ACTION ) . '_wpbcnonce' );
61 ?>
62 <span class="wpdevelop">
63 <div id="wpbc_modal__add_booking__section"
64 class="modal wpbc_popup_modal wpbc_modal_in_listing wpbc_modal__add_booking__section"
65 tabindex="-1"
66 role="dialog"
67 data-wpbc-add-booking-nonce="<?php echo esc_attr( $nonce ); ?>"
68 data-wpbc-add-booking-resource-id="">
69 <div class="modal-dialog modal-lg">
70 <div class="modal-content">
71 <div class="modal-header">
72 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
73 <div class="wpbc_modal__add_booking__header_main">
74 <h4 class="modal-title">
75 <span class="wpbc_modal__add_booking__title"><?php esc_html_e( 'Add booking', 'booking' ); ?></span>
76 <sup class="wpbc_modal__add_booking__booking_id wpbc_modal__booking_id__in_title"></sup>
77 </h4>
78 <div class="wpbc_modal__add_booking__controls">
79 <?php self::print_modal_resource_select(); ?>
80 <?php self::print_modal_booking_form_select(); ?>
81 <?php self::print_modal_allow_past_toggle(); ?>
82 </div>
83 </div>
84 </div>
85 <div class="modal-body">
86 <div id="wpbc_modal__add_booking__body" class="wpbc_modal__add_booking__body">
87 <?php self::print_loading_spinner(); ?>
88 </div>
89 </div>
90 <div class="modal-footer">
91 <div class="wpbc_modal__add_booking__footer_time_override" data-wpbc-add-booking-time-override-footer="1"></div>
92 <?php self::print_modal_send_emails_toggle(); ?>
93 <?php self::print_add_appointment_entry(); ?>
94 <a href="javascript:void(0)" id="wpbc_modal__add_booking__button_send" class="button button-primary" onclick="wpbc_boo_listing__submit__add_booking_modal();">
95 <?php esc_html_e( 'Add booking', 'booking' ); ?>
96 </a>
97 <a href="javascript:void(0)" class="button button-secondary" data-dismiss="modal">
98 <?php esc_html_e( 'Close', 'booking' ); ?>
99 </a>
100 </div>
101 </div><!-- /.modal-content -->
102 </div><!-- /.modal-dialog -->
103 </div><!-- /.modal -->
104 </span>
105 <?php
106 }
107
108
109 /**
110 * Print a feature-gated route to the Service-first administrator workflow.
111 *
112 * The standard Add Booking form remains the popup's primary action. This
113 * secondary route is hidden by the modal client whenever an existing booking
114 * is being edited.
115 *
116 * @return void
117 */
118 private static function print_add_appointment_entry() {
119 if (
120 ! function_exists( 'wpbc_is_11_5_features_enabled' )
121 || ! wpbc_is_11_5_features_enabled()
122 || ! function_exists( 'wpbc_add_appointment_page_get_url' )
123 || ! WPBC_Add_Booking_Component::current_user_can_add_booking()
124 ) {
125 return;
126 }
127 ?>
128 <a href="<?php echo esc_url( wpbc_add_appointment_page_get_url() ); ?>"
129 class="button button-secondary wpbc_modal__add_booking__appointment_entry"
130 data-wpbc-add-appointment-entry="1"
131 title="<?php esc_attr_e( 'Choose a Service and Provider before creating the booking', 'booking' ); ?>">
132 <i class="menu_icon icon-1x wpbc-bi-calendar-plus" aria-hidden="true"></i>
133 <?php esc_html_e( 'Add Appointment', 'booking' ); ?>
134 </a>
135 <?php
136 }
137
138
139 /**
140 * Print modal-scoped email notification toggle.
141 *
142 * The legacy Add Booking page uses #is_send_email_for_pending. Timeline uses the same id,
143 * so the modal needs its own id to avoid cross-toggling that page control.
144 *
145 * @return void
146 */
147 private static function print_modal_send_emails_toggle() {
148
149 $el_id = 'wpbc_modal__add_booking__is_send_email_for_pending';
150 $el_value = ( get_bk_option( 'booking_send_emails_off_addbooking' ) !== 'On' ) ? 'On' : 'Off';
151
152 $params_checkbox = array(
153 'id' => $el_id,
154 'name' => $el_id,
155 'label' => array( 'title' => __( 'Emails sending', 'booking' ), 'position' => 'right' ),
156 'style' => '',
157 'class' => '',
158 'disabled' => false,
159 'attr' => array(
160 'data-wpbc-add-booking-send-emails' => '1',
161 ),
162 'legend' => '',
163 'value' => $el_value,
164 'selected' => ( 'On' === $el_value ),
165 'hint' => array( 'title' => __( 'Send email notification to customer about this operation', 'booking' ), 'position' => 'top' ),
166 );
167 ?>
168 <div class="btn-group" style="position:static;margin:0 10px 0 0;display:inline-flex;vertical-align:middle;">
169 <?php wpbc_flex_toggle( $params_checkbox ); ?>
170 </div>
171 <?php
172 }
173
174
175 /**
176 * Print modal-scoped toggle for allowing bookings in the past.
177 *
178 * @return void
179 */
180 private static function print_modal_allow_past_toggle() {
181
182 $el_id = 'wpbc_modal__add_booking__allow_past';
183
184 $params_checkbox = array(
185 'id' => $el_id,
186 'name' => $el_id,
187 'label' => array( 'title' => __( 'Allow booking in the past', 'booking' ), 'position' => 'right' ),
188 'style' => '',
189 'class' => '',
190 'disabled' => false,
191 'attr' => array(
192 'data-wpbc-add-booking-allow-past' => '1',
193 ),
194 'legend' => '',
195 'value' => 'On',
196 'selected' => false,
197 'hint' => array( 'title' => __( 'Allow booking in the past', 'booking' ), 'position' => 'top' ),
198 );
199 ?>
200 <div class="wpbc_modal__add_booking__control wpbc_modal__add_booking__allow_past_control btn-group" style="position:static;margin:0 0 0 6px;display:inline-flex;vertical-align:middle;">
201 <?php wpbc_flex_toggle( $params_checkbox ); ?>
202 </div>
203 <?php
204 }
205
206
207 /**
208 * Print modal loading spinner.
209 *
210 * @return void
211 */
212 private static function print_loading_spinner() {
213 ?>
214 <div class="wpbc_spins_loading_container">
215 <div class="wpbc_booking_form_spin_loader">
216 <div class="wpbc_spins_loader_wrapper">
217 <div class="wpbc_spin_loader_one_new"></div>
218 </div>
219 </div>
220 <span><?php esc_html_e( 'Loading', 'booking' ); ?>...</span>
221 </div>
222 <?php
223 }
224
225
226 /**
227 * Print booking resource selector for the modal header.
228 *
229 * @return void
230 */
231 private static function print_modal_resource_select() {
232
233 $selected_resource = absint( wpbc_get_default_resource() );
234 $selected_resource = $selected_resource ? $selected_resource : 1;
235 $resources = self::get_booking_resource_options();
236 ?>
237 <label class="wpbc_modal__add_booking__control wpbc_modal__add_booking__resource_control" for="wpbc_modal__add_booking__resource_id">
238 <span><?php esc_html_e( 'Resource', 'booking' ); ?>:</span>
239 <select id="wpbc_modal__add_booking__resource_id" class="wpbc_modal__add_booking__resource_id">
240 <?php foreach ( $resources as $resource_id => $resource ) : ?>
241 <option value="<?php echo esc_attr( absint( $resource_id ) ); ?>" <?php selected( absint( $resource_id ), $selected_resource ); ?>>
242 <?php echo esc_html( $resource['title'] ); ?>
243 </option>
244 <?php endforeach; ?>
245 </select>
246 </label>
247 <?php
248 }
249
250
251 /**
252 * Print custom booking form selector for the modal header.
253 *
254 * @return void
255 */
256 private static function print_modal_booking_form_select() {
257
258 $form_options = self::get_booking_form_options();
259 if ( count( $form_options ) <= 1 ) {
260 return;
261 }
262 ?>
263 <label class="wpbc_modal__add_booking__control wpbc_modal__add_booking__form_control" for="wpbc_modal__add_booking__booking_form">
264 <span><?php esc_html_e( 'Booking Form', 'booking' ); ?>:</span>
265 <select id="wpbc_modal__add_booking__booking_form" class="wpbc_modal__add_booking__booking_form">
266 <?php foreach ( $form_options as $form_name => $form_title ) : ?>
267 <option value="<?php echo esc_attr( $form_name ); ?>">
268 <?php echo esc_html( $form_title ); ?>
269 </option>
270 <?php endforeach; ?>
271 </select>
272 </label>
273 <?php self::print_modal_booking_form_edit_link(); ?>
274 <?php
275 }
276
277
278 /**
279 * Print link to edit currently selected form in Forms Builder.
280 *
281 * @return void
282 */
283 private static function print_modal_booking_form_edit_link() {
284
285 if ( ! function_exists( 'wpbc_get_settings_url' ) ) {
286 return;
287 }
288
289 $base_url = add_query_arg(
290 array(
291 'tab' => 'builder_booking_form',
292 'form_name' => 'standard',
293 ),
294 wpbc_get_settings_url()
295 );
296 ?>
297 <a href="<?php echo esc_url( $base_url ); ?>"
298 class="wpbc_modal__add_booking__edit_form_link"
299 data-wpbc-add-booking-form-builder-url="<?php echo esc_url( remove_query_arg( 'form_name', $base_url ) ); ?>"
300 target="_blank"
301 rel="noopener noreferrer"
302 title="<?php esc_attr_e( 'Edit selected booking form', 'booking' ); ?>">
303 <i class="menu_icon icon-1x wpbc_icn_draw"></i>
304 <span><?php esc_html_e( 'Edit form', 'booking' ); ?></span>
305 </a>
306 <?php
307 }
308
309
310 /**
311 * Enqueue client booking-form scripts required by the modal body.
312 *
313 * @param string $where_to_load Load context.
314 *
315 * @return void
316 */
317 public static function enqueue_js_files( $where_to_load ) {
318
319 if ( ! self::is_supported_admin_page() || ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) {
320 return;
321 }
322
323 wp_enqueue_script( 'wpbc-main-client', wpbc_plugin_url( '/js/client.js' ), array( 'wpbc-datepick' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
324 wp_enqueue_script( 'wpbc_capacity', wpbc_plugin_url( '/includes/_capacity/_out/create_booking.js' ), array( 'wpbc-main-client' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
325 wp_enqueue_script( 'wpbc-times', wpbc_plugin_url( '/js/wpbc_times.js' ), array( 'wpbc-main-client' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
326 wp_enqueue_script( 'wpbc-time-selector', wpbc_plugin_url( '/js/wpbc_time-selector.js' ), array( 'wpbc-times' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
327 wp_enqueue_script( 'wpbc-imask', wpbc_plugin_url( '/vendors/imask/dist/imask.js' ), array( 'wpbc-main-client' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
328 wp_enqueue_script( 'wpbc-boo_listing_ajx_actions', wpbc_plugin_url( '/includes/page-bookings/_out/boo_listing__actions.js' ), array( 'wpbc_all', 'wpbc-modal' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
329
330 if ( 'On' === get_bk_option( 'booking_is_use_phone_validation' ) ) {
331 wp_enqueue_script( 'wpbc-iphone-validator', wpbc_plugin_url( '/js/wpbc_phone_validator.js' ), array( 'wpbc-imask' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) );
332 }
333 }
334
335
336 /**
337 * Enqueue front-end booking-form styles required by the modal body.
338 *
339 * @param string $where_to_load Load context.
340 *
341 * @return void
342 */
343 public static function enqueue_css_files( $where_to_load ) {
344
345 if ( ! self::is_supported_admin_page() || ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) {
346 return;
347 }
348
349 if ( function_exists( 'wpbc_enqueue_styles__front_end' ) ) {
350 wpbc_enqueue_styles__front_end();
351 }
352 }
353
354
355 /**
356 * AJAX: render Add Booking modal body.
357 *
358 * @return void
359 */
360 public static function ajax_render() {
361
362 check_ajax_referer( strtolower( self::AJAX_ACTION ) . '_wpbcnonce', 'nonce' );
363
364 if ( ! wpbc_is_mu_user_can_be_here( 'activated_user' ) ) {
365 wp_send_json_error( array( 'message' => __( 'You do not have access to this page.', 'booking' ) ), 403 );
366 }
367
368 $args = self::get_clean_request_args();
369
370 if ( ( 'add' === $args['mode'] ) && ! WPBC_Add_Booking_Component::current_user_can_add_booking() ) {
371 wp_send_json_error( array( 'message' => __( 'You do not have access to this page.', 'booking' ) ), 403 );
372 }
373
374 if ( empty( $args['resource_id'] ) ) {
375 $args['resource_id'] = wpbc_get_default_resource();
376 }
377
378 if ( empty( $args['resource_id'] ) ) {
379 wp_send_json_error( array( 'message' => __( 'Booking resource type is not defined.', 'booking' ) ), 400 );
380 }
381
382 if (
383 class_exists( 'wpdev_bk_multiuser' )
384 && ! wpbc_is_mu_user_can_be_here( 'resource_owner', $args['resource_id'] )
385 ) {
386 wp_send_json_error( array( 'message' => __( 'You do not have access to this booking resource.', 'booking' ) ), 403 );
387 }
388
389 if ( ( 'add' === $args['mode'] ) && ( '' === (string) $args['booking_form'] ) ) {
390 $args['booking_form'] = WPBC_Add_Booking_Component::get_default_booking_form_for_resource( $args['resource_id'], 'standard' );
391 $args['custom_booking_form'] = $args['booking_form'];
392 }
393
394 $html = self::render_component_with_legacy_request_context( $args );
395
396 wp_send_json_success(
397 array(
398 'html' => $html,
399 'resource_id' => absint( $args['resource_id'] ),
400 'booking_hash' => (string) $args['booking_hash'],
401 'mode' => (string) $args['mode'],
402 'title' => ( 'edit' === $args['mode'] ) ? __( 'Edit booking', 'booking' ) : __( 'Add booking', 'booking' ),
403 'button_title' => ( 'edit' === $args['mode'] ) ? __( 'Save booking', 'booking' ) : __( 'Add booking', 'booking' ),
404 'booking_id' => absint( $args['booking_id'] ),
405 'booking_form' => (string) $args['booking_form'],
406 'allow_past' => absint( $args['allow_past'] ),
407 'selected_dates_without_calendar' => (string) $args['selected_dates_without_calendar'],
408 'selected_dates' => (string) $args['selected_dates'],
409 'selected_date' => (string) $args['selected_date'],
410 'selected_time' => (string) $args['selected_time'],
411 'time_override_enabled' => absint( $args['time_override_enabled'] ),
412 'time_override_source' => (string) $args['time_override_source'],
413 'time_override_start' => (string) $args['time_override_start'],
414 'time_override_end' => (string) $args['time_override_end'],
415 )
416 );
417 }
418
419
420 /**
421 * Get sanitized request args.
422 *
423 * @return array
424 */
425 private static function get_clean_request_args() {
426
427 $mode = isset( $_POST['mode'] ) ? sanitize_key( wp_unslash( $_POST['mode'] ) ) : 'add'; // phpcs:ignore WordPress.Security.NonceVerification.Missing
428 $mode = in_array( $mode, array( 'add', 'edit' ), true ) ? $mode : 'add';
429
430 $booking_hash = isset( $_POST['booking_hash'] ) ? sanitize_text_field( wp_unslash( $_POST['booking_hash'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
431 $resource_id = isset( $_POST['resource_id'] ) ? absint( $_POST['resource_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
432 $booking_id = isset( $_POST['booking_id'] ) ? absint( $_POST['booking_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
433 $booking_form = isset( $_POST['booking_form'] ) ? sanitize_text_field( wp_unslash( $_POST['booking_form'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
434 $allow_past = isset( $_POST['allow_past'] ) ? absint( $_POST['allow_past'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
435 $selected_dates_without_calendar = isset( $_POST['selected_dates_without_calendar'] ) ? sanitize_text_field( wp_unslash( $_POST['selected_dates_without_calendar'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
436 $selected_dates = isset( $_POST['selected_dates'] ) ? sanitize_text_field( wp_unslash( $_POST['selected_dates'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
437 $selected_date = isset( $_POST['selected_date'] ) ? sanitize_text_field( wp_unslash( $_POST['selected_date'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
438 $selected_time = isset( $_POST['selected_time'] ) ? sanitize_text_field( wp_unslash( $_POST['selected_time'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
439 $time_override_enabled = isset( $_POST['time_override_enabled'] ) ? absint( $_POST['time_override_enabled'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
440 $time_override_source = isset( $_POST['time_override_source'] ) ? sanitize_key( wp_unslash( $_POST['time_override_source'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
441 $time_override_start = isset( $_POST['time_override_start'] ) ? self::sanitize_time_hm( wp_unslash( $_POST['time_override_start'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
442 $time_override_end = isset( $_POST['time_override_end'] ) ? self::sanitize_time_hm( wp_unslash( $_POST['time_override_end'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
443
444 if ( '' !== $booking_hash ) {
445 $hash_resource = wpbc_hash__get_booking_id__resource_id( $booking_hash );
446 if ( false === $hash_resource ) {
447 wp_send_json_error( array( 'message' => __( 'We could not find your booking. The link you used may be incorrect or has expired.', 'booking' ) ), 404 );
448 }
449
450 $booking_id = absint( $hash_resource[0] );
451 $resource_id = absint( $hash_resource[1] );
452 $mode = 'edit';
453 $allow_past = 1;
454 }
455
456 return array(
457 'mode' => $mode,
458 'resource_id' => $resource_id,
459 'booking_type' => $resource_id,
460 'booking_id' => $booking_id,
461 'booking_hash' => $booking_hash,
462 'booking_form' => $booking_form,
463 'custom_booking_form' => $booking_form,
464 'allow_past' => $allow_past ? 1 : 0,
465 'selected_dates_without_calendar' => $selected_dates_without_calendar,
466 'selected_dates' => $selected_dates,
467 'selected_date' => $selected_date,
468 'selected_time' => $selected_time,
469 'time_override_enabled' => ( $time_override_enabled && $time_override_start && $time_override_end ) ? 1 : 0,
470 'time_override_source' => $time_override_source,
471 'time_override_start' => $time_override_start,
472 'time_override_end' => $time_override_end,
473 'is_toolbar_visible' => false,
474 'is_booking_page_js' => false,
475 'is_booking_page_popover' => false,
476 'is_show_before_content_spacer'=> false,
477 'is_show_footer_email_toggle' => false,
478 'content_css_class' => 'add_booking_page_content wpbc_add_booking_component__in_modal',
479 'content_style' => 'width:100%;margin-bottom:20px;',
480 'is_echo' => 0,
481 );
482 }
483
484
485 /**
486 * Sanitize HH:MM time value.
487 *
488 * @param string $time_value Time value.
489 *
490 * @return string
491 */
492 private static function sanitize_time_hm( $time_value ) {
493
494 $time_value = trim( sanitize_text_field( (string) $time_value ) );
495
496 if ( ! preg_match( '/^([0-9]{1,2}):([0-9]{2})$/', $time_value, $matches ) ) {
497 return '';
498 }
499
500 $hour = absint( $matches[1] );
501 $minute = absint( $matches[2] );
502
503 if ( $hour > 24 || $minute > 59 || ( 24 === $hour && 0 !== $minute ) ) {
504 return '';
505 }
506
507 return sprintf( '%02d:%02d', $hour, $minute );
508 }
509
510
511 /**
512 * Render the component with a scoped legacy request context for older renderers that still read $_GET.
513 *
514 * @param array $args Component args.
515 *
516 * @return string
517 */
518 private static function render_component_with_legacy_request_context( $args ) {
519
520 $old_get = $_GET;
521 $old_request = $_REQUEST;
522 $old_request_uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
523
524 $query_args = array(
525 'page' => 'wpbc',
526 'tab' => 'add-booking',
527 'booking_type' => absint( $args['resource_id'] ),
528 'is_show_payment_form' => 'Off',
529 );
530
531 if ( '' !== $args['booking_hash'] ) {
532 $query_args['booking_hash'] = $args['booking_hash'];
533 $query_args['parent_res'] = 1;
534 }
535
536 if ( ! empty( $args['allow_past'] ) || ( '' !== $args['booking_hash'] ) ) {
537 $query_args['allow_past'] = 1;
538 }
539
540 if ( '' !== $args['booking_form'] ) {
541 $query_args['booking_form'] = $args['booking_form'];
542 }
543
544 foreach ( $query_args as $key => $value ) {
545 $_GET[ $key ] = $value;
546 $_REQUEST[ $key ] = $value;
547 }
548
549 $_SERVER['REQUEST_URI'] = wp_parse_url( admin_url( 'admin.php' ), PHP_URL_PATH ) . '?' . http_build_query( $query_args, '', '&' );
550
551 try {
552 return WPBC_Add_Booking_Component::render( $args );
553 } finally {
554 $_GET = $old_get;
555 $_REQUEST = $old_request;
556 $_SERVER['REQUEST_URI'] = $old_request_uri;
557 }
558 }
559
560
561 /**
562 * Get booking resource options for the modal selector.
563 *
564 * @return array
565 */
566 private static function get_booking_resource_options() {
567
568 $resources = array();
569
570 if ( function_exists( 'wpbc_get_all_booking_resources_list' ) ) {
571 $resources = wpbc_get_all_booking_resources_list();
572 }
573
574 if ( empty( $resources ) ) {
575 $default_resource = absint( wpbc_get_default_resource() );
576 $default_resource = $default_resource ? $default_resource : 1;
577 $resources = array(
578 $default_resource => array(
579 'title' => __( 'Default', 'booking' ),
580 'attr' => array(),
581 ),
582 );
583 }
584
585 return $resources;
586 }
587
588
589 /**
590 * Get booking form options for the modal selector.
591 *
592 * @return array
593 */
594 private static function get_booking_form_options() {
595
596 $options = array(
597 'standard' => __( 'Standard', 'booking' ),
598 );
599
600 if ( ! class_exists( 'WPBC_FE_Custom_Form_Helper' ) ) {
601 return $options;
602 }
603
604 $is_can = apply_bk_filter( 'multiuser_is_user_can_be_here', true, 'only_super_admin' );
605 if ( ( ! $is_can ) && ( 'On' !== get_bk_option( 'booking_is_custom_forms_for_regular_users' ) ) ) {
606 return $options;
607 }
608
609 $owner_user_id = WPBC_FE_Custom_Form_Helper::wpbc_mu__get_current__owner_user_id();
610 $forms = WPBC_FE_Custom_Form_Helper::get_custom_booking_forms_list(
611 array(
612 'include_standard' => false,
613 'owner_user_id' => $owner_user_id,
614 'statuses' => array( 'published' ),
615 'list_mode' => 'auto',
616 )
617 );
618
619 foreach ( $forms as $form ) {
620 if ( empty( $form['name'] ) ) {
621 continue;
622 }
623 $form_title = ! empty( $form['title'] ) ? $form['title'] : $form['name'];
624 $options[ $form['name'] ] = wpbc_lang( $form_title );
625 }
626
627 return $options;
628 }
629
630
631 /**
632 * Check if assets should be loaded for Booking Listing or Timeline view.
633 *
634 * @return bool
635 */
636 public static function is_supported_admin_page() {
637
638 if ( ! is_admin() ) {
639 return false;
640 }
641
642 if ( function_exists( 'wpbc_is_availability_page' ) && wpbc_is_availability_page() ) {
643 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
644 $requested_tab = isset( $_REQUEST['tab'] ) ? sanitize_key( wp_unslash( $_REQUEST['tab'] ) ) : '';
645 return ( 'time_slots_availability' === $requested_tab );
646 }
647
648 if ( function_exists( 'wpbc_is_bookings_page' ) ) {
649 if ( ! wpbc_is_bookings_page() ) {
650 return false;
651 }
652 } else {
653 $server_request_uri = ( isset( $_SERVER['REQUEST_URI'] ) ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
654 if ( ( false === strpos( $server_request_uri, 'page=wpbc' ) ) || ( false !== strpos( $server_request_uri, 'page=wpbc-' ) ) ) {
655 return false;
656 }
657 }
658
659 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
660 $requested_tab = isset( $_REQUEST['tab'] ) ? sanitize_key( wp_unslash( $_REQUEST['tab'] ) ) : '';
661 if ( '' !== $requested_tab ) {
662 return in_array( $requested_tab, array( 'vm_booking_listing', 'vm_calendar' ), true );
663 }
664
665 if ( function_exists( 'wpbc_get_default_saved_view_mode_for_wpbc_page' ) ) {
666 return in_array( wpbc_get_default_saved_view_mode_for_wpbc_page(), array( 'vm_booking_listing', 'vm_calendar' ), true );
667 }
668
669 return true;
670 }
671
672
673 /**
674 * Backward-compatible alias for existing Add Booking modal checks.
675 *
676 * @return bool
677 */
678 public static function is_booking_listing_admin_page() {
679
680 return self::is_supported_admin_page();
681 }
682 }
683
684 /**
685 * Check if Booking Listing or Timeline needs the Add Booking modal client assets.
686 *
687 * @return bool
688 */
689 if ( ! function_exists( 'wpbc_is_add_booking_modal_on_booking_listing_page' ) ) {
690 /**
691 * Check if Booking Listing or Timeline needs the Add Booking modal client assets.
692 *
693 * @return bool
694 */
695 function wpbc_is_add_booking_modal_on_booking_listing_page() {
696 return WPBC_Add_Booking_Modal::is_supported_admin_page();
697 }
698 }
699
700 add_action( 'wpbc_ui_el__top_nav__content_end', array( 'WPBC_Add_Booking_Modal', 'print_top_toolbar_button' ), 19, 3 );
701 add_action( 'wpbc_hook_booking_template__hidden_templates', array( 'WPBC_Add_Booking_Modal', 'template_for_modal' ) );
702 add_action( 'wpbc_enqueue_js_files', array( 'WPBC_Add_Booking_Modal', 'enqueue_js_files' ), 52 );
703 add_action( 'wpbc_enqueue_css_files', array( 'WPBC_Add_Booking_Modal', 'enqueue_css_files' ), 52 );
704 add_action( 'wp_ajax_' . WPBC_Add_Booking_Modal::AJAX_ACTION, array( 'WPBC_Add_Booking_Modal', 'ajax_render' ) );
705