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__page.php

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

1,189 lines 44.6 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 Content of Add New Booking
5 * @author wpdevelop
6 *
7 * @web-site https://wpbookingcalendar.com/
8 * @email info@wpbookingcalendar.com
9 *
10 * @modified 2015-10-31
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
15
16 /**
17 * Check whether the Add Booking inspector interface is enabled.
18 *
19 * The interface is part of 11.4.4 and is enabled by default. The filter keeps
20 * a narrow emergency fallback to the legacy toolbar for integrations that
21 * need additional migration time; it is not connected to the 11.5 flag.
22 *
23 * @return bool True when the 11.4.4 inspector interface should be used.
24 */
25 function wpbc_add_booking_page_is_inspector_enabled() {
26
27 return (bool) apply_filters( 'wpbc_add_booking_page_is_inspector_enabled', true );
28 }
29
30
31 /**
32 * Check whether the current request is the Add Booking administrator tab.
33 *
34 * @return bool True on WP Booking Calendar > Add Booking with the inspector UI enabled.
35 */
36 function wpbc_add_booking_page_is_active() {
37
38 if ( ! is_admin() || ! wpbc_add_booking_page_is_inspector_enabled() ) {
39 return false;
40 }
41
42 $page = isset( $_GET['page'] ) && ! is_array( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
43 $tab = isset( $_GET['tab'] ) && ! is_array( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
44
45 return 'wpbc' === $page && 'add-booking' === $tab;
46 }
47
48
49 /**
50 * Build a safe Add Booking URL while preserving the current resource, form,
51 * editing context, and calendar layout parameters.
52 *
53 * @param bool $allow_past Whether the resulting page should allow past dates.
54 *
55 * @return string Add Booking administrator URL.
56 */
57 function wpbc_add_booking_page_get_allow_past_url( $allow_past ) {
58
59 $url = wpbc_get_new_booking_url__base( array( 'allow_past' ) );
60
61 // Match the legacy toolbar when returning from a payment result state.
62 if ( ! empty( $_GET['is_show_payment_form'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
63 $url = add_query_arg( 'is_show_payment_form', 'Off', $url );
64 }
65
66 if ( $allow_past ) {
67 $url = add_query_arg( 'allow_past', '1', $url );
68 }
69
70 return $url;
71 }
72
73
74 /**
75 * Resolve a generated page asset, with a source fallback for development.
76 *
77 * Release packages use `_out`. The fallback keeps the page usable immediately
78 * after a source checkout and disappears automatically after asset compilation.
79 *
80 * @param string $file_name Asset file name without a directory.
81 *
82 * @return string Asset URL.
83 */
84 function wpbc_add_booking_page_get_asset_url( $file_name ) {
85
86 $file_name = sanitize_file_name( $file_name );
87 $folder = file_exists( __DIR__ . '/_out/' . $file_name ) ? '_out' : '_src';
88
89 return trailingslashit( plugins_url( '', __FILE__ ) ) . $folder . '/' . $file_name;
90 }
91
92
93 /**
94 * Enqueue source-built styles for the Add Booking inspector page only.
95 *
96 * @param string $where_to_load Booking Calendar asset context.
97 *
98 * @return void
99 */
100 function wpbc_add_booking_page_enqueue_css( $where_to_load ) {
101
102 if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! wpbc_add_booking_page_is_active() ) {
103 return;
104 }
105
106 wp_enqueue_style(
107 'wpbc-add-booking-page',
108 wpbc_add_booking_page_get_asset_url( 'add_booking_page.css' ),
109 array( 'wpbc-all-admin' ),
110 WP_BK_VERSION_NUM
111 );
112 }
113 add_action( 'wpbc_enqueue_css_files', 'wpbc_add_booking_page_enqueue_css', 73 );
114
115
116 /**
117 * Enqueue the inspector tab controller for the Add Booking page only.
118 *
119 * @param string $where_to_load Booking Calendar asset context.
120 *
121 * @return void
122 */
123 function wpbc_add_booking_page_enqueue_js( $where_to_load ) {
124
125 if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! wpbc_add_booking_page_is_active() ) {
126 return;
127 }
128
129 wp_enqueue_script(
130 'wpbc-add-booking-page',
131 wpbc_add_booking_page_get_asset_url( 'add_booking_page.js' ),
132 array( 'jquery', 'wpbc_all' ),
133 WP_BK_VERSION_NUM,
134 array( 'in_footer' => WPBC_JS_IN_FOOTER )
135 );
136 }
137 add_action( 'wpbc_enqueue_js_files', 'wpbc_add_booking_page_enqueue_js', 73 );
138
139
140 /**
141 * Show Content
142 * Update Content
143 * Define Slug
144 * Define where to show
145 */
146 class WPBC_Page_AddNewBooking extends WPBC_Page_Structure {
147
148
149 /**
150 * Published Booking Forms available to the current user.
151 *
152 * The value is loaded lazily because both the setup summary and selector use
153 * the same list during one page render.
154 *
155 * @var array<string,array<string,mixed>>|null
156 */
157 private $available_booking_forms = null;
158
159
160 /**
161 * Place Add Booking under the shared Bookings page.
162 *
163 * @return string Parent page slug.
164 */
165 public function in_page() {
166 return 'wpbc';
167 }
168
169 /**
170 * Register the page tab and its 11.4.4 inspector shell.
171 *
172 * @return array<string,array<string,mixed>> Page tab definition.
173 */
174 public function tabs() {
175
176 $is_can_add_booking = WPBC_Add_Booking_Component::current_user_can_add_booking();
177 $is_inspector_ui = wpbc_add_booking_page_is_inspector_enabled();
178
179 $tabs = array();
180 $tabs['add-booking'] = array(
181 'is_show_top_path' => true, // true | false. By default value is: true.
182 'is_show_top_navigation' => true,
183 'left_navigation__default_view_mode' => '', // FixIn:11.7.1.1: 'min', // '' | 'min' | 'compact' | 'max' | 'none'. By default value is: ''.
184 'right_vertical_sidebar__is_show' => $is_inspector_ui,
185 'right_vertical_sidebar__default_view_mode' => '',
186 'right_vertical_sidebar_compact__is_show' => $is_inspector_ui,
187 'page_title' => __( 'Add New Booking', 'booking' ), // Header - Title. If false, than hidden.
188 'page_description' => __( 'Manually add new bookings from the Admin Panel.', 'booking' ), // Header - Title Description. If false, than hidden.
189 'title' => __( 'Add booking', 'booking' ), // Title of TAB.
190 'hint' => __( 'Add booking', 'booking' ), // Hint.
191 'link' => '', // Can be skiped, then generated link based on Page and Tab tags. Or can be extenral link.
192 'position' => '', // Can be: 'left' | 'right' | ''.
193 'css_classes' => '', // this is CSS class(es).
194 'icon' => '', // Icon - link to the real PNG img.
195 'font_icon' => 'wpbc-bi-plus', // CSS definition of forn Icon.
196 'default' => true, // Is this tab activated by default or not: true || false.
197 'disabled' => ! $is_can_add_booking, // Is this tab disbaled: true || false.
198 'hided' => ! $is_can_add_booking, // Is this tab hided: true || false.
199 'subtabs' => array(),
200 );
201
202 return $tabs;
203 }
204
205
206 /**
207 * Render the compact Settings and Help controls for the right inspector.
208 *
209 * @return void
210 */
211 public function right_sidebar_compact_content() {
212
213 if ( ! wpbc_add_booking_page_is_inspector_enabled() ) {
214 return;
215 }
216
217 $tabs = array(
218 array(
219 'id' => 'wpbc_tab_add_booking_settings',
220 'panel_id' => 'wpbc_add_booking__inspector_settings',
221 'title' => __( 'Settings', 'booking' ),
222 'icon' => 'wpbc_icn_tune',
223 'selected' => true,
224 ),
225 array(
226 'id' => 'wpbc_tab_add_booking_help',
227 'panel_id' => 'wpbc_add_booking__inspector_help',
228 'title' => __( 'Help', 'booking' ),
229 'icon' => 'wpbc-bi-info-circle',
230 ),
231 );
232 $tabs = (array) apply_filters( 'wpbc_admin_add_booking_inspector_tabs', $tabs );
233
234 WPBC_UI_Sidebar_Panels::render_rightbar_tabs(
235 $tabs,
236 array(
237 'aria_label' => __( 'Add Booking Panels', 'booking' ),
238 'context' => 'add_booking',
239 'class' => 'wpbc_add_booking__rightbar_tabs',
240 )
241 );
242 }
243
244
245 /**
246 * Render the Builder-style right inspector panels.
247 *
248 * @return void
249 */
250 public function right_sidebar_content() {
251
252 if ( ! wpbc_add_booking_page_is_inspector_enabled() ) {
253 return;
254 }
255 ?>
256 <div class="wpbc_bfb__panel--library wpbc_rightbar_palette wpbc_add_booking__rightbar">
257 <?php
258 WPBC_UI_Sidebar_Panels::render_panel(
259 array(
260 'id' => 'wpbc_add_booking__inspector_settings',
261 'labelledby' => 'wpbc_tab_add_booking_settings',
262 'class' => 'wpbc_add_booking__inspector_settings',
263 ),
264 array( $this, 'render_settings_panel' )
265 );
266 WPBC_UI_Sidebar_Panels::render_panel(
267 array(
268 'id' => 'wpbc_add_booking__inspector_help',
269 'labelledby' => 'wpbc_tab_add_booking_help',
270 'class' => 'wpbc_add_booking__inspector_help',
271 'hidden' => true,
272 ),
273 array( $this, 'render_help_panel' )
274 );
275 do_action( 'wpbc_admin_add_booking_inspector_panels', $this );
276 ?>
277 </div>
278 <?php
279 }
280
281
282 /**
283 * Render all controls formerly shown in the Add Booking top toolbar.
284 *
285 * Native inspector markup preserves the established IDs, reload URLs, AJAX
286 * save endpoint, MultiUser visibility rules, and commercial behavior.
287 *
288 * @return void
289 */
290 public function render_settings_panel() {
291
292 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Booking Settings', 'booking' ), __( 'Configure this manual Booking and its calendar view.', 'booking' ) );
293 ?>
294 <div class="wpbc_bfb__inspector__body wpbc_add_booking__inspector_body">
295 <div class="wpbc_add_booking__top_actions wpbc_bfb__inspector__section--content wpbc_ui_el__buttons_group">
296 <?php if ( function_exists( 'wpbc_toolbar_btn__auto_fill' ) ) : ?>
297 <?php wpbc_toolbar_btn__auto_fill( array( 'submit_after_fill' => false ) ); ?>
298 <?php endif; ?>
299 <?php wpbc_toolbar_btn__add_new_booking(); ?>
300 <?php do_action( 'wpbc_admin_add_booking_primary_actions', $this ); ?>
301 </div>
302 <?php $this->render_booking_setup_summary(); ?>
303 <?php
304 WPBC_UI_Sidebar_Panels::render_collapsible_group(
305 array(
306 'id' => 'wpbc_add_booking_setup_group',
307 'group' => 'add-booking-setup',
308 'title' => __( 'Booking setup', 'booking' ),
309 'open' => false,
310 ),
311 array( $this, 'render_booking_setup_controls' )
312 );
313 WPBC_UI_Sidebar_Panels::render_collapsible_group(
314 array(
315 'id' => 'wpbc_add_booking_date_selection_group',
316 'group' => 'add-booking-date-selection',
317 'title' => __( 'Date selection', 'booking' ),
318 'open' => false,
319 ),
320 array( $this, 'render_date_selection_controls' )
321 );
322 WPBC_UI_Sidebar_Panels::render_collapsible_group(
323 array(
324 'id' => 'wpbc_add_booking_tools_group',
325 'group' => 'add-booking-tools',
326 'title' => __( 'Booking tools', 'booking' ),
327 'open' => false,
328 ),
329 array( $this, 'render_booking_tools_controls' )
330 );
331 WPBC_UI_Sidebar_Panels::render_collapsible_group(
332 array(
333 'id' => 'wpbc_add_booking_calendar_view_group',
334 'group' => 'add-booking-calendar-view',
335 'title' => __( 'Calendar view', 'booking' ),
336 'open' => false,
337 ),
338 array( $this, 'render_calendar_view_controls' )
339 );
340 do_action( 'wpbc_admin_add_booking_settings_panel', $this );
341 ?>
342 </div>
343 <?php
344 }
345
346
347 /**
348 * Render resource and Booking Form selectors.
349 *
350 * @return void
351 */
352 public function render_booking_setup_controls() {
353
354 $is_resource_rendered = $this->render_booking_resource_control();
355 $is_form_rendered = $this->render_booking_form_control();
356
357 if ( ! $is_resource_rendered && ! $is_form_rendered ) {
358 ?><p class="wpbc_add_booking__empty_setup"><?php esc_html_e( 'This Booking uses the default Booking resource and Standard Booking Form.', 'booking' ); ?></p><?php
359 }
360 do_action( 'wpbc_admin_add_booking_setup_panel', $this );
361 }
362
363
364 /**
365 * Render a compact summary of the current manual Booking configuration.
366 *
367 * Available settings are rendered as links that expand the correct inspector
368 * group and move keyboard focus to the corresponding control.
369 *
370 * @return void
371 */
372 private function render_booking_setup_summary() {
373
374 $resource_id = $this->get_selected_booking_resource_id();
375 $resource_title = function_exists( 'wpbc_get_resource_title' ) ? wpbc_get_resource_title( $resource_id ) : '';
376 $form_name = $this->get_selected_booking_form_name( $resource_id );
377 $days_mode = $this->get_current_days_selection_mode();
378 $send_emails = 'On' !== get_bk_option( 'booking_send_emails_off_addbooking' );
379 $allow_past = isset( $_GET['allow_past'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
380 $enabled_label = __( 'Enabled', 'booking' );
381 $disabled_label = __( 'Disabled', 'booking' );
382
383 if ( '' === trim( (string) $resource_title ) ) {
384 $resource_title = sprintf( __( 'Resource #%d', 'booking' ), $resource_id );
385 }
386
387 $form_title = 'standard' === $form_name ? __( 'Standard', 'booking' ) : wpbc_lang( $form_name );
388 ?>
389 <div class="wpbc_add_booking__setup_summary wpbc_bfb__inspector__section--content"
390 data-wpbc-add-booking-enabled-label="<?php echo esc_attr( $enabled_label ); ?>"
391 data-wpbc-add-booking-disabled-label="<?php echo esc_attr( $disabled_label ); ?>"
392 aria-label="<?php esc_attr_e( 'Current Booking setup', 'booking' ); ?>">
393 <div class="wpbc_add_booking__setup_summary_item">
394 <span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Booking resource', 'booking' ); ?></span>
395 <?php if ( $this->is_booking_resource_selector_available() || $this->is_booking_resource_upgrade_visible() ) : ?>
396 <a href="#select_booking_resource" class="wpbc_add_booking__setup_summary_link" data-wpbc-add-booking-open-group="add-booking-setup" data-wpbc-add-booking-focus="#select_booking_resource"><?php echo esc_html( $resource_title ); ?></a>
397 <?php else : ?>
398 <strong><?php echo esc_html( $resource_title ); ?></strong>
399 <?php endif; ?>
400 </div>
401 <div class="wpbc_add_booking__setup_summary_item">
402 <span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Booking Form', 'booking' ); ?></span>
403 <?php if ( ! empty( $this->get_available_booking_forms() ) ) : ?>
404 <a href="#select_booking_form" class="wpbc_add_booking__setup_summary_link" data-wpbc-add-booking-open-group="add-booking-setup" data-wpbc-add-booking-focus="#select_booking_form"><?php echo esc_html( $form_title ); ?></a>
405 <?php else : ?>
406 <strong><?php echo esc_html( $form_title ); ?></strong>
407 <?php endif; ?>
408 </div>
409 <div class="wpbc_add_booking__setup_summary_item">
410 <span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Date selection', 'booking' ); ?></span>
411 <a href="#wpbc_add_booking_date_selection_group"
412 class="wpbc_add_booking__setup_summary_link"
413 data-wpbc-add-booking-open-group="add-booking-date-selection"
414 data-wpbc-add-booking-focus="input[name='wpbc_add_booking_days_selection_mode']:checked"
415 data-wpbc-add-booking-summary="days-selection"
416 aria-label="<?php esc_attr_e( 'Change date-selection behavior', 'booking' ); ?>"><?php echo esc_html( $this->get_days_selection_mode_label( $days_mode ) ); ?></a>
417 </div>
418 <div class="wpbc_add_booking__setup_summary_item">
419 <span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Email notifications', 'booking' ); ?></span>
420 <a href="#wpbc_add_booking_tools_group"
421 class="wpbc_add_booking__setup_summary_link"
422 data-wpbc-add-booking-open-group="add-booking-tools"
423 data-wpbc-add-booking-focus="#is_send_email_for_pending"
424 data-wpbc-add-booking-summary="emails"
425 aria-label="<?php esc_attr_e( 'Change email notification setting', 'booking' ); ?>"><?php echo esc_html( $send_emails ? $enabled_label : $disabled_label ); ?></a>
426 </div>
427 <div class="wpbc_add_booking__setup_summary_item">
428 <span class="wpbc_add_booking__setup_summary_label"><?php esc_html_e( 'Allow booking in the past', 'booking' ); ?></span>
429 <a href="#wpbc_add_booking_tools_group"
430 class="wpbc_add_booking__setup_summary_link"
431 data-wpbc-add-booking-open-group="add-booking-tools"
432 data-wpbc-add-booking-focus="#is_allow_bookings_in_past"
433 data-wpbc-add-booking-summary="allow-past"
434 aria-label="<?php esc_attr_e( 'Change past-date Booking setting', 'booking' ); ?>"><?php echo esc_html( $allow_past ? $enabled_label : $disabled_label ); ?></a>
435 </div>
436 </div>
437 <?php
438 }
439
440
441 /**
442 * Render the page-local date-selection override as Calendar Settings radios.
443 *
444 * The radio values are not saved and do not reload the page. Add Booking
445 * JavaScript applies them directly to the currently rendered calendar.
446 *
447 * @return void
448 */
449 public function render_date_selection_controls() {
450
451 $resource_id = $this->get_selected_booking_resource_id();
452 $days_mode = $this->get_current_days_selection_mode();
453 $range_engine_mode = $this->get_current_range_engine_mode();
454 $single_label = __( 'Single day', 'booking' );
455 $multiple_label = __( 'Multiple days', 'booking' );
456 $range_label = class_exists( 'wpdev_bk_biz_s' ) ? __( 'Range days', 'booking' ) : __( 'Range days - 2 mouse clicks', 'booking' );
457 ?>
458 <div class="wpbc_calendar_radio_stack wpbc_add_booking__days_radio_stack"
459 data-wpbc-add-booking-days-selection="1"
460 data-wpbc-resource-id="<?php echo absint( $resource_id ); ?>"
461 data-wpbc-range-engine-mode="<?php echo esc_attr( $range_engine_mode ); ?>">
462 <label>
463 <input type="radio" name="wpbc_add_booking_days_selection_mode" value="single" data-wpbc-days-selection-label="<?php echo esc_attr( $single_label ); ?>" <?php checked( 'single', $days_mode ); ?> />
464 <span><?php echo esc_html( $single_label ); ?></span>
465 </label>
466 <label>
467 <input type="radio" name="wpbc_add_booking_days_selection_mode" value="multiple" data-wpbc-days-selection-label="<?php echo esc_attr( $multiple_label ); ?>" <?php checked( 'multiple', $days_mode ); ?> />
468 <span><?php echo esc_html( $multiple_label ); ?></span>
469 </label>
470 <label>
471 <input type="radio" name="wpbc_add_booking_days_selection_mode" value="range" data-wpbc-days-selection-label="<?php echo esc_attr( $range_label ); ?>" <?php checked( 'range', $days_mode ); ?> />
472 <span><?php echo esc_html( $range_label ); ?></span>
473 </label>
474 </div>
475 <p class="inspector__help"><?php esc_html_e( 'This temporary override applies immediately to this calendar. Changing the mode clears the currently selected dates but does not reload the page or modify saved Calendar and Booking Form settings.', 'booking' ); ?></p>
476 <?php
477 /**
478 * Fires after the Add Booking date-selection radio controls.
479 *
480 * @param WPBC_Page_AddNewBooking $page_instance Current Add Booking page object.
481 * @param string $days_mode Current normalized mode.
482 * @param int $resource_id Current Booking resource ID.
483 */
484 do_action( 'wpbc_admin_add_booking_date_selection_panel', $this, $days_mode, $resource_id );
485 }
486
487
488 /**
489 * Get the current global calendar mode normalized for the three radio choices.
490 *
491 * The selected Booking Form may apply its own mode after page initialization;
492 * the page JavaScript synchronizes the radios with that effective mode.
493 *
494 * @return string One of `single`, `multiple`, or `range`.
495 */
496 private function get_current_days_selection_mode() {
497
498 $days_selection_mode = function_exists( 'wpbc__calendar__js_params__get_days_selection_arr' )
499 ? wpbc__calendar__js_params__get_days_selection_arr()
500 : array( 'days_select_mode' => get_bk_option( 'booking_type_of_day_selections' ) );
501 $days_selection_mode = isset( $days_selection_mode['days_select_mode'] ) ? sanitize_key( (string) $days_selection_mode['days_select_mode'] ) : 'multiple';
502
503 if ( in_array( $days_selection_mode, array( 'fixed', 'dynamic', 'range' ), true ) ) {
504 return 'range';
505 }
506
507 return in_array( $days_selection_mode, array( 'single', 'multiple' ), true ) ? $days_selection_mode : 'multiple';
508 }
509
510
511 /**
512 * Get the range engine that the page should use when Range days is selected.
513 *
514 * Business Small and higher retain the configured fixed/dynamic subtype.
515 * Free and Personal use their normal unrestricted dynamic range.
516 *
517 * @return string Either `fixed` or `dynamic`.
518 */
519 private function get_current_range_engine_mode() {
520
521 if ( ! class_exists( 'wpdev_bk_biz_s' ) ) {
522 return 'dynamic';
523 }
524
525 $range_engine_mode = sanitize_key( (string) get_bk_option( 'booking_range_selection_type' ) );
526
527 return in_array( $range_engine_mode, array( 'fixed', 'dynamic' ), true ) ? $range_engine_mode : 'dynamic';
528 }
529
530
531 /**
532 * Get the translated label for a normalized date-selection mode.
533 *
534 * @param string $days_mode Normalized date-selection mode.
535 *
536 * @return string Translated mode label.
537 */
538 private function get_days_selection_mode_label( $days_mode ) {
539
540 if ( 'single' === $days_mode ) {
541 return __( 'Single day', 'booking' );
542 }
543
544 if ( 'range' === $days_mode ) {
545 return class_exists( 'wpdev_bk_biz_s' ) ? __( 'Range days', 'booking' ) : __( 'Range days - 2 mouse clicks', 'booking' );
546 }
547
548 return __( 'Multiple days', 'booking' );
549 }
550
551 /**
552 * Get the Booking resource selected for the current Add Booking page.
553 *
554 * @return int Positive Booking resource ID.
555 */
556 private function get_selected_booking_resource_id() {
557
558 if ( isset( $_GET['booking_type'] ) && ! is_array( $_GET['booking_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
559 $resource_id = absint( $_GET['booking_type'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
560 if ( $resource_id > 0 ) {
561 return $resource_id;
562 }
563 }
564
565 return 1;
566 }
567
568
569 /**
570 * Get the Booking Form selected explicitly or inherited from the resource.
571 *
572 * @param int $resource_id Booking resource ID used to resolve its default form.
573 *
574 * @return string Sanitized Booking Form slug.
575 */
576 private function get_selected_booking_form_name( $resource_id ) {
577
578 if ( isset( $_GET['booking_form'] ) && ! is_array( $_GET['booking_form'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
579 $form_name = sanitize_text_field( wp_unslash( $_GET['booking_form'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
580 if ( '' !== $form_name ) {
581 return $form_name;
582 }
583 }
584
585 return WPBC_Add_Booking_Component::get_default_booking_form_for_resource( $resource_id, 'standard' );
586 }
587
588
589 /**
590 * Check whether the resource selector can be used in the current context.
591 *
592 * Resource changes remain disabled while editing an existing Booking.
593 *
594 * @return bool True when the commercial resource selector is available.
595 */
596 private function is_booking_resource_selector_available() {
597
598 return empty( $_GET['booking_hash'] ) && class_exists( 'wpdev_bk_personal' ) && function_exists( 'wpbc_toolbar__get_resource_options_for_selection' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
599 }
600
601
602 /**
603 * Check whether the Free-version resource upgrade notice should be shown.
604 *
605 * The notice replaces the unavailable resource selector only while creating
606 * a new Booking. A user may dismiss it without affecting Booking behavior.
607 *
608 * @return bool True when the upgrade notice should be rendered.
609 */
610 private function is_booking_resource_upgrade_visible() {
611
612 if ( class_exists( 'wpdev_bk_personal' ) || ! empty( $_GET['booking_hash'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
613 return false;
614 }
615
616 if ( function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo() ) {
617 return true;
618 }
619
620 return ! function_exists( 'wpbc_is_dismissed_panel_visible' ) || wpbc_is_dismissed_panel_visible( 'wpbc_add_booking_resource_upgrade' );
621 }
622
623
624 /**
625 * Get published Booking Forms visible to the current user.
626 *
627 * @return array<string,array<string,mixed>> Available custom Booking Forms.
628 */
629 private function get_available_booking_forms() {
630
631 if ( null !== $this->available_booking_forms ) {
632 return $this->available_booking_forms;
633 }
634
635 $is_allowed = apply_bk_filter( 'multiuser_is_user_can_be_here', true, 'only_super_admin' );
636 if ( ! $is_allowed && 'On' !== get_bk_option( 'booking_is_custom_forms_for_regular_users' ) ) {
637 $this->available_booking_forms = array();
638 return $this->available_booking_forms;
639 }
640
641 $this->available_booking_forms = WPBC_FE_Custom_Form_Helper::get_custom_booking_forms_list(
642 array(
643 'include_standard' => false,
644 'owner_user_id' => WPBC_FE_Custom_Form_Helper::wpbc_mu__get_current__owner_user_id(),
645 'statuses' => array( 'published' ),
646 'list_mode' => 'auto',
647 )
648 );
649
650 if ( ! is_array( $this->available_booking_forms ) ) {
651 $this->available_booking_forms = array();
652 }
653
654 return $this->available_booking_forms;
655 }
656
657
658 /**
659 * Render the commercial Booking resource selector as a native inspector row.
660 *
661 * The legacy resource option provider remains the source of truth for parent,
662 * child, MultiUser, and edition-specific resource visibility. Only its toolbar
663 * HTML renderer is bypassed on this page.
664 *
665 * @return bool True when a resource selector was rendered.
666 */
667 private function render_booking_resource_control() {
668
669 if ( $this->is_booking_resource_upgrade_visible() ) {
670 return $this->render_booking_resource_upgrade_control();
671 }
672
673 // A resource cannot be switched while editing an existing Booking.
674 if ( ! $this->is_booking_resource_selector_available() ) {
675 return false;
676 }
677
678 $resource_options = wpbc_toolbar__get_resource_options_for_selection();
679 if ( empty( $resource_options ) || ! is_array( $resource_options ) ) {
680 return false;
681 }
682
683 $link_base = wpbc_get_new_booking_url__base( array( 'booking_type', 'booking_form', 'parent_res' ) ) . '&booking_type=';
684
685 $this->render_inspector_select_row(
686 array(
687 'id' => 'select_booking_resource',
688 'name' => 'select_booking_resource',
689 'label' => __( 'Booking resource', 'booking' ),
690 'options' => $resource_options,
691 'on_change' => 'window.location.href = ' . wp_json_encode( $link_base ) . ' + this.value;',
692 )
693 );
694
695 return true;
696 }
697
698
699 /**
700 * Render the Free-version resource explanation in place of the selector.
701 *
702 * @return bool True after the inspector control has been rendered.
703 */
704 private function render_booking_resource_upgrade_control() {
705
706 $dismiss_id = 'wpbc_add_booking_resource_upgrade';
707 $is_demo = function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo();
708 ?>
709 <div class="inspector__row wpbc_add_booking__resource_upgrade_row" id="<?php echo esc_attr( $dismiss_id ); ?>">
710 <span class="inspector__label"><?php esc_html_e( 'Booking resource', 'booking' ); ?></span>
711 <div class="inspector__control" id="select_booking_resource" tabindex="-1">
712 <div class="wpbc_add_booking__resource_upgrade_hint">
713 <a class="wpbc_pro_label" href="<?php echo esc_url( 'https://wpbookingcalendar.com/features/' ); ?>" target="_blank" rel="noopener noreferrer">Pro</a>
714 <?php if ( ! $is_demo && function_exists( 'wpbc_is_dismissed' ) ) : ?>
715 <span class="wpbc_add_booking__premium_dismiss">
716 <?php
717 wpbc_is_dismissed(
718 $dismiss_id,
719 array(
720 'title' => '&times;',
721 'hint' => __( 'Hide this option', 'booking' ),
722 'css' => 'float:none;',
723 )
724 );
725 ?>
726 </span>
727 <?php endif; ?>
728 <span class="wpbc_add_booking__resource_upgrade_description"><?php esc_html_e( 'The Free version has one default booking resource. To have multiple resources, please upgrade to a premium version.', 'booking' ); ?></span>
729 </div>
730 </div>
731 </div>
732 <?php
733
734 return true;
735 }
736
737
738 /**
739 * Render the available Booking Forms as a native inspector row.
740 *
741 * This follows the same MultiUser access rule and resource-default selection
742 * used by the legacy toolbar selector without mutating request data.
743 *
744 * @return bool True when a Booking Form selector was rendered.
745 */
746 private function render_booking_form_control() {
747
748 $booking_forms = $this->get_available_booking_forms();
749
750 if ( empty( $booking_forms ) || ! is_array( $booking_forms ) ) {
751 return false;
752 }
753
754 $resource_id = $this->get_selected_booking_resource_id();
755 $form_name = $this->get_selected_booking_form_name( $resource_id );
756
757 $form_options = array(
758 'standard' => array(
759 'title' => __( 'Standard', 'booking' ),
760 'selected' => 'standard' === $form_name,
761 ),
762 'custom_forms_open' => array(
763 'optgroup' => true,
764 'close' => false,
765 'title' => __( 'Custom Forms', 'booking' ),
766 ),
767 );
768
769 foreach ( $booking_forms as $booking_form ) {
770 $booking_form_name = isset( $booking_form['name'] ) ? sanitize_text_field( (string) $booking_form['name'] ) : '';
771 if ( '' === $booking_form_name ) {
772 continue;
773 }
774
775 $form_options[ $booking_form_name ] = array(
776 'title' => wpbc_lang( $booking_form_name ),
777 'selected' => $booking_form_name === $form_name,
778 );
779 }
780
781 $form_options['custom_forms_close'] = array(
782 'optgroup' => true,
783 'close' => true,
784 );
785
786 $link_base = wpbc_get_new_booking_url__base( array( 'booking_form' ) ) . '&booking_form=';
787
788 $this->render_inspector_select_row(
789 array(
790 'id' => 'select_booking_form',
791 'name' => 'select_booking_form',
792 'label' => __( 'Booking Form', 'booking' ),
793 'options' => $form_options,
794 'on_change' => 'window.location.href = ' . wp_json_encode( $link_base ) . ' + this.value;',
795 'after' => function () use ( $form_name ) {
796 $this->render_booking_form_edit_link( $form_name );
797 },
798 )
799 );
800
801 return true;
802 }
803
804
805 /**
806 * Render a Forms Builder link for the currently selected Booking Form.
807 *
808 * @param string $form_name Sanitized Booking Form slug.
809 *
810 * @return void
811 */
812 private function render_booking_form_edit_link( $form_name ) {
813
814 if ( ! function_exists( 'wpbc_get_settings_url' ) ) {
815 return;
816 }
817
818 $base_url = add_query_arg( 'tab', 'builder_booking_form', wpbc_get_settings_url() );
819 $edit_url = add_query_arg( 'form_name', $form_name, $base_url );
820 ?>
821 <a href="<?php echo esc_url( $edit_url ); ?>"
822 class="wpbc_modal__add_booking__edit_form_link wpbc_add_booking__edit_form_link"
823 data-wpbc-add-booking-form-builder-url="<?php echo esc_url( $base_url ); ?>"
824 target="_blank"
825 rel="noopener noreferrer"
826 title="<?php esc_attr_e( 'Edit selected booking form', 'booking' ); ?>">
827 <i class="menu_icon icon-1x wpbc_icn_draw" aria-hidden="true"></i>
828 <span><?php esc_html_e( 'Edit form', 'booking' ); ?></span>
829 </a>
830 <?php
831 }
832
833
834 /**
835 * Render one select field using the shared Builder-style inspector markup.
836 *
837 * Option arrays may contain the Booking Calendar toolbar option keys
838 * `title`, `class`, `disabled`, `selected`, and `optgroup`.
839 * An optional `after` callback renders related controls beneath the select.
840 *
841 * @param array $args Select field arguments.
842 *
843 * @return void
844 */
845 private function render_inspector_select_row( $args ) {
846
847 $args = wp_parse_args(
848 $args,
849 array(
850 'id' => '',
851 'name' => '',
852 'label' => '',
853 'options' => array(),
854 'value' => null,
855 'on_change' => '',
856 'after' => null,
857 )
858 );
859 ?>
860 <div class="inspector__row">
861 <label for="<?php echo esc_attr( $args['id'] ); ?>" class="inspector__label"><?php echo esc_html( $args['label'] ); ?></label>
862 <div class="inspector__control">
863 <select id="<?php echo esc_attr( $args['id'] ); ?>"
864 name="<?php echo esc_attr( $args['name'] ); ?>"
865 class="inspector__input"
866 <?php echo '' !== $args['on_change'] ? 'onchange="' . esc_attr( $args['on_change'] ) . '"' : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
867 autocomplete="off">
868 <?php $this->render_inspector_select_options( $args['options'], $args['value'] ); ?>
869 </select>
870 <?php
871 if ( is_callable( $args['after'] ) ) {
872 call_user_func( $args['after'] );
873 }
874 ?>
875 </div>
876 </div>
877 <?php
878 }
879
880
881 /**
882 * Render select options and optgroups from Booking Calendar option arrays.
883 *
884 * @param array $options Option definitions keyed by submitted value.
885 * @param string|int|null $selected_value Explicit selected value, or null to use each option's selected flag.
886 *
887 * @return void
888 */
889 private function render_inspector_select_options( $options, $selected_value = null ) {
890
891 foreach ( (array) $options as $option_value => $option_definition ) {
892 $option_definition = is_array( $option_definition ) ? $option_definition : array( 'title' => $option_definition );
893
894 if ( ! empty( $option_definition['optgroup'] ) ) {
895 if ( ! empty( $option_definition['close'] ) ) {
896 ?></optgroup><?php
897 } else {
898 ?><optgroup label="<?php echo esc_attr( isset( $option_definition['title'] ) ? $option_definition['title'] : '' ); ?>"><?php
899 }
900 continue;
901 }
902
903 $option_title = isset( $option_definition['title'] ) ? wp_strip_all_tags( html_entity_decode( (string) $option_definition['title'], ENT_QUOTES, get_bloginfo( 'charset' ) ) ) : '';
904 $is_selected = null === $selected_value ? ! empty( $option_definition['selected'] ) : (string) $selected_value === (string) $option_value;
905 ?>
906 <option value="<?php echo esc_attr( $option_value ); ?>"
907 class="<?php echo esc_attr( isset( $option_definition['class'] ) ? $option_definition['class'] : '' ); ?>"
908 <?php selected( $is_selected ); ?>
909 <?php disabled( ! empty( $option_definition['disabled'] ) ); ?>><?php echo esc_html( $option_title ); ?></option>
910 <?php
911 }
912 }
913
914
915 /**
916 * Render email and past-date controls.
917 *
918 * @return void
919 */
920 public function render_booking_tools_controls() {
921
922 $allow_past = isset( $_GET['allow_past'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
923 $allow_past_url = esc_url_raw( wpbc_add_booking_page_get_allow_past_url( true ) );
924 $normal_url = esc_url_raw( wpbc_add_booking_page_get_allow_past_url( false ) );
925 $send_emails = 'On' !== get_bk_option( 'booking_send_emails_off_addbooking' );
926 ?>
927 <?php
928 wpbc_render_admin_cost_correction_control(
929 array(
930 'input_id' => 'wpbc_add_booking_cost_correction',
931 'resource_id' => $this->get_selected_booking_resource_id(),
932 'wrapper_class' => 'inspector__row wpbc_add_booking__cost_correction',
933 'label_class' => 'inspector__label',
934 'control_class' => 'inspector__control',
935 'help_class' => 'description wpbc_bfb__help',
936 'help' => __( 'Leave the number empty to use the calculated Booking cost. Enter an exact total to replace the final cost for this Booking.', 'booking' ),
937 )
938 );
939 ?>
940 <div class="inspector__row inspector__row--toggle">
941 <div class="inspector__control">
942 <?php
943 wpbc_flex_toggle(
944 array(
945 'id' => 'is_send_email_for_pending',
946 'name' => 'is_send_email_for_pending',
947 'label' => array( 'title' => __( 'Emails sending', 'booking' ) ),
948 'value' => 'On',
949 'selected' => $send_emails,
950 'legend' => __( 'Send email notifications for this Booking', 'booking' ),
951 )
952 );
953 ?>
954 <p class="inspector__help"><?php esc_html_e( 'Send the normal Booking Calendar notifications when this Booking is created.', 'booking' ); ?></p>
955 </div>
956 </div>
957 <div class="inspector__row inspector__row--toggle">
958 <div class="inspector__control">
959 <?php
960 wpbc_flex_toggle(
961 array(
962 'id' => 'is_allow_bookings_in_past',
963 'name' => 'is_allow_bookings_in_past',
964 'label' => array( 'title' => __( 'Allow booking in the past', 'booking' ) ),
965 'value' => 'On',
966 'selected' => $allow_past,
967 'legend' => __( 'Allow booking in the past', 'booking' ),
968 'onchange' => 'window.location.href = this.checked ? ' . wp_json_encode( $allow_past_url ) . ' : ' . wp_json_encode( $normal_url ) . ';',
969 )
970 );
971 ?>
972 <p class="inspector__help"><?php esc_html_e( 'Use this only for historical or manually entered Bookings.', 'booking' ); ?></p>
973 </div>
974 </div>
975 <?php do_action( 'wpbc_admin_add_booking_tools_panel', $this ); ?>
976 <?php
977 }
978
979 /**
980 * Render per-user calendar sizing controls and their existing AJAX actions.
981 *
982 * @return void
983 */
984 public function render_calendar_view_controls() {
985
986 $user_calendar_options = $this->get_saved_user_calendar_settings();
987 $month_options = array_combine( range( 1, 12 ), range( 1, 12 ) );
988 $months_per_row = array( 0 => __( 'All', 'booking' ) ) + $month_options;
989
990 $this->render_inspector_select_row(
991 array(
992 'id' => 'calendar_months_count',
993 'name' => 'calendar_months_count',
994 'label' => __( 'Visible months', 'booking' ),
995 'options' => $month_options,
996 'value' => isset( $user_calendar_options['calendar_months_count'] ) ? absint( $user_calendar_options['calendar_months_count'] ) : 1,
997 )
998 );
999 $this->render_inspector_select_row(
1000 array(
1001 'id' => 'calendar_months_num_in_1_row',
1002 'name' => 'calendar_months_num_in_1_row',
1003 'label' => __( 'Number of months in one row', 'booking' ),
1004 'options' => $months_per_row,
1005 'value' => isset( $user_calendar_options['calendar_months_num_in_1_row'] ) ? absint( $user_calendar_options['calendar_months_num_in_1_row'] ) : 0,
1006 )
1007 );
1008
1009 $this->render_inspector_measurement_row(
1010 'calendar_width',
1011 __( 'Maximum width of calendar', 'booking' ),
1012 isset( $user_calendar_options['calendar_width'] ) ? $user_calendar_options['calendar_width'] : '',
1013 isset( $user_calendar_options['calendar_widthunits'] ) ? $user_calendar_options['calendar_widthunits'] : 'px',
1014 '100%'
1015 );
1016 $this->render_inspector_measurement_row(
1017 'calendar_cell_height',
1018 __( 'Calendar cell height', 'booking' ),
1019 isset( $user_calendar_options['calendar_cell_height'] ) ? $user_calendar_options['calendar_cell_height'] : '',
1020 isset( $user_calendar_options['calendar_cell_heightunits'] ) ? $user_calendar_options['calendar_cell_heightunits'] : 'px',
1021 '48px'
1022 );
1023 ?>
1024 <div class="wpbc_add_booking__panel_actions">
1025 <button type="button"
1026 id="toolbar_btn__calendar_options_save"
1027 class="button button-primary"
1028 onclick="var wpbc_calendar_options = { calendar_months_count: jQuery( '#calendar_months_count' ).val(), calendar_months_num_in_1_row: jQuery( '#calendar_months_num_in_1_row' ).val(), calendar_width: jQuery( '#calendar_width' ).val(), calendar_widthunits: jQuery( '#calendar_widthunits' ).val(), calendar_cell_height: jQuery( '#calendar_cell_height' ).val(), calendar_cell_heightunits: jQuery( '#calendar_cell_heightunits' ).val() }; wpbc_save_custom_user_data( <?php echo absint( wpbc_get_current_user_id() ); ?>, 'add_booking_calendar_options', jQuery.param( wpbc_calendar_options ), 1 );"><?php esc_html_e( 'Save', 'booking' ); ?></button>
1029 <button type="button"
1030 class="button button-secondary"
1031 onclick="jQuery( '#calendar_months_count' ).val( '1' ); jQuery( '#calendar_months_num_in_1_row' ).val( '0' ); jQuery( '#calendar_width' ).val( '0' ); jQuery( '#calendar_widthunits' ).val( 'px' ); jQuery( '#calendar_cell_height' ).val( '0' ); jQuery( '#calendar_cell_heightunits' ).val( 'px' ); jQuery( '#toolbar_btn__calendar_options_save' ).trigger( 'click' );"><?php esc_html_e( 'Reset', 'booking' ); ?></button>
1032 </div>
1033 <?php do_action( 'wpbc_admin_add_booking_calendar_view_panel', $this, $user_calendar_options ); ?>
1034 <?php
1035 }
1036
1037
1038 /**
1039 * Render a numeric calendar measurement and its unit selector.
1040 *
1041 * @param string $field_id Base HTML id and name.
1042 * @param string $label Visible field label.
1043 * @param string|int $value Saved numeric value.
1044 * @param string $unit Saved unit: `px` or `percent`.
1045 * @param string $placeholder Example value shown when empty.
1046 *
1047 * @return void
1048 */
1049 private function render_inspector_measurement_row( $field_id, $label, $value, $unit, $placeholder ) {
1050
1051 $unit = in_array( $unit, array( 'px', 'percent' ), true ) ? $unit : 'px';
1052 ?>
1053 <div class="inspector__row">
1054 <label for="<?php echo esc_attr( $field_id ); ?>" class="inspector__label"><?php echo esc_html( $label ); ?></label>
1055 <div class="inspector__control inspector__control--inline">
1056 <input id="<?php echo esc_attr( $field_id ); ?>" name="<?php echo esc_attr( $field_id ); ?>" type="number" min="0" step="1" value="<?php echo esc_attr( $value ); ?>" placeholder="<?php echo esc_attr( $placeholder ); ?>" class="inspector__input">
1057 <select id="<?php echo esc_attr( $field_id . 'units' ); ?>" name="<?php echo esc_attr( $field_id . 'units' ); ?>" class="inspector__input inspector__input--unit" autocomplete="off">
1058 <option value="px" <?php selected( 'px', $unit ); ?>>px</option>
1059 <option value="percent" <?php selected( 'percent', $unit ); ?>>%</option>
1060 </select>
1061 </div>
1062 </div>
1063 <?php
1064 }
1065
1066
1067 /**
1068 * Render contextual help in place of the legacy toolbar Help dropdown.
1069 *
1070 * @return void
1071 */
1072 public function render_help_panel() {
1073
1074 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Add Booking Help', 'booking' ), __( 'Create a Booking directly from the WordPress Admin Panel.', 'booking' ) );
1075 ?>
1076 <div class="wpbc_bfb__inspector__body wpbc_bfb__inspector__body--content wpbc_add_booking__help_body">
1077 <div class="wpbc_add_booking__hint">
1078 <span class="wpbc_icn_info_outline" aria-hidden="true"></span>
1079 <p><?php esc_html_e( 'Choose the Booking resource and form first. Changing either selector reloads this page so every field and calendar keeps the correct resource ID.', 'booking' ); ?></p>
1080 </div>
1081 <div class="wpbc_add_booking__help_section">
1082 <h4><?php esc_html_e( 'Recommended workflow', 'booking' ); ?></h4>
1083 <ol>
1084 <li><?php esc_html_e( 'Select the Booking resource and Booking Form.', 'booking' ); ?></li>
1085 <li><?php esc_html_e( 'Choose an available date or time and complete the customer fields.', 'booking' ); ?></li>
1086 <li><?php esc_html_e( 'Review email sending, then click Add booking.', 'booking' ); ?></li>
1087 </ol>
1088 </div>
1089 <div class="wpbc_add_booking__help_actions">
1090 <a class="button" href="https://wpbookingcalendar.com/faq/" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'FAQ', 'booking' ); ?></a>
1091 <a class="button" href="https://wpbookingcalendar.com/support/" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Support', 'booking' ); ?></a>
1092 </div>
1093 <?php do_action( 'wpbc_admin_add_booking_help_panel', $this ); ?>
1094 </div>
1095 <?php
1096 }
1097
1098
1099 /**
1100 * Render the legacy page or the released inspector presentation.
1101 *
1102 * Both presentations delegate the actual Booking Form to the same reusable
1103 * component, so calendar and submission behavior cannot diverge.
1104 *
1105 * @return void|false False when the current user cannot use the page.
1106 */
1107 public function content() {
1108
1109 do_action( 'wpbc_hook_add_booking_page_header', 'add_booking' ); // Define Notices Section and show some static messages, if needed.
1110
1111 if ( ! wpbc_is_mu_user_can_be_here( 'activated_user' ) ) {
1112 return false; // Check if MU user activated, otherwise show Warning message.
1113 }
1114
1115 if ( ! WPBC_Add_Booking_Component::current_user_can_add_booking() ) {
1116 return false;
1117 }
1118
1119 if ( ! wpbc_set_default_resource_to__get() ) {
1120 return false; // Define default booking resources for $_ GET and check if booking resource belong to user.
1121 }
1122
1123 if ( wpbc_add_booking_page_is_inspector_enabled() ) {
1124 ?>
1125 <div class="wpbc_add_booking_page" data-wpbc-add-booking-page="1">
1126 <div class="wpbc_add_booking__canvas">
1127 <?php
1128 WPBC_Add_Booking_Component::render(
1129 array(
1130 'is_toolbar_visible' => false,
1131 'is_show_before_content_spacer' => false,
1132 'is_show_footer_email_toggle' => false,
1133 'content_css_class' => 'add_booking_page_content wpbc_add_booking__form_content',
1134 'content_style' => '',
1135 )
1136 );
1137 ?>
1138 </div>
1139 </div>
1140 <?php
1141 } else {
1142 WPBC_Add_Booking_Component::render();
1143 }
1144
1145 do_action( 'wpbc_hook_add_booking_page_footer', 'add_booking' );
1146 }
1147
1148
1149 /**
1150 * Get Calendar Options of specific User
1151 *
1152 * @return array<string,mixed> Normalized calendar display options.
1153 */
1154 public function get_saved_user_calendar_options() {
1155
1156 return WPBC_Add_Booking_Component::get_saved_user_calendar_options();
1157 }
1158
1159
1160 /**
1161 * Get raw saved calendar fields used by the Add Booking inspector.
1162 *
1163 * @return array<string,mixed> Raw per-user calendar settings.
1164 */
1165 private function get_saved_user_calendar_settings() {
1166
1167 return WPBC_Add_Booking_Component::get_saved_user_calendar_settings();
1168 }
1169
1170 }
1171 add_action('wpbc_menu_created', array( new WPBC_Page_AddNewBooking() , '__construct') ); // Executed after creation of Menu
1172
1173 /**
1174 * Redirect legacy/main-menu Add Booking page to the Add Booking tab under Bookings.
1175 *
1176 * @param string $page_tag Current menu page tag.
1177 *
1178 * @return void
1179 */
1180 function wpbc_add_booking_menu_page__redirect_to_add_booking_tab( $page_tag ) {
1181
1182 if ( 'wpbc-new' !== $page_tag ) {
1183 return;
1184 }
1185
1186 wpbc_redirect( wpbc_get_new_booking_url() );
1187 }
1188 add_action( 'wpbc_page_structure_show', 'wpbc_add_booking_menu_page__redirect_to_add_booking_tab', 0 );
1189