PluginProbe
Booking Calendar / 11.4.3
Booking Calendar v11.4.3
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.4.3, at includes/page-add-booking/add_booking__modal.php

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