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
booking / includes / page-add-booking / add_booking__modal.php

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

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