PluginProbe
Booking Calendar / 11.3
Booking Calendar v11.3
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 10.11.2 All 203 releases
booking / includes / page-setup / setup_profiles.php

setup_profiles.php in Booking Calendar 11.3, at includes/page-setup/setup_profiles.php

898 lines 32.8 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 * @description Booking profile helpers for Setup Wizard.
4 * @category Setup Wizard
5 */
6
7 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly.
8
9 /**
10 * Store the WPBC admin fullscreen preference for the current user.
11 *
12 * The top navigation fullscreen button stores this value through WPBC_User_Custom_Data_Saver as
13 * "booking_custom_is_full_screen" => array( 'value' => 'On|Off' ). Setup routing happens before redirects, so the
14 * wizard updates the same preference server-side when it moves between internal and external setup screens.
15 *
16 * @param bool $is_full_screen Whether WPBC admin pages should open in fullscreen mode.
17 *
18 * @return bool
19 */
20 function wpbc_setup_wizard__set_full_screen_mode_for_current_user( $is_full_screen ) {
21
22 $user_id = wpbc_get_current_user_id();
23
24 if ( empty( $user_id ) ) {
25 return false;
26 }
27
28 return update_user_option(
29 $user_id,
30 'booking_custom_is_full_screen',
31 array( 'value' => $is_full_screen ? 'On' : 'Off' )
32 );
33 }
34
35 /**
36 * Get persisted wizard choices.
37 *
38 * @return array
39 */
40 function wpbc_setup_wizard__get_booking_wizard_data() {
41
42 $wizard_data = get_bk_option( 'booking_wizard_data' );
43
44 return ( empty( $wizard_data ) || ( ! is_array( $wizard_data ) ) ) ? array() : $wizard_data;
45 }
46
47 /**
48 * Get selected booking type from wizard history or current options.
49 *
50 * @param array|null $wizard_data Wizard data.
51 *
52 * @return string
53 */
54 function wpbc_setup_wizard__get_selected_booking_type( $wizard_data = null ) {
55
56 if ( null === $wizard_data ) {
57 $wizard_data = wpbc_setup_wizard__get_booking_wizard_data();
58 }
59
60 if (
61 isset( $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_types'] )
62 && ( ! empty( $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_types'] ) )
63 ) {
64 return (string) $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_types'];
65 }
66
67 if ( 'On' === get_bk_option( 'booking_range_selection_time_is_active' ) ) {
68 return 'changeover_multi_dates_bookings';
69 }
70
71 if ( 'single' === get_bk_option( 'booking_type_of_day_selections' ) ) {
72 return 'time_slots_appointments';
73 }
74
75 return 'full_days_bookings';
76 }
77
78 /**
79 * Get selected appointment mode from wizard history or current options.
80 *
81 * @param array|null $wizard_data Wizard data.
82 *
83 * @return string
84 */
85 function wpbc_setup_wizard__get_selected_appointments_type( $wizard_data = null ) {
86
87 if ( null === $wizard_data ) {
88 $wizard_data = wpbc_setup_wizard__get_booking_wizard_data();
89 }
90
91 if (
92 isset( $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_appointments_type'] )
93 && ( ! empty( $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_appointments_type'] ) )
94 ) {
95 return (string) $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_appointments_type'];
96 }
97
98 return 'rangetime';
99 }
100
101 /**
102 * Convert selected booking type to a setup profile.
103 *
104 * @param array|null $wizard_data Wizard data.
105 *
106 * @return string
107 */
108 function wpbc_setup_wizard__get_selected_profile( $wizard_data = null ) {
109
110 $booking_type = wpbc_setup_wizard__get_selected_booking_type( $wizard_data );
111
112 if ( 'time_slots_appointments' === $booking_type ) {
113 return ( 'durationtime' === wpbc_setup_wizard__get_selected_appointments_type( $wizard_data ) ) ? 'duration_appointments' : 'time_slots';
114 }
115
116 if ( 'changeover_multi_dates_bookings' === $booking_type ) {
117 return 'changeover';
118 }
119
120 return 'full_day';
121 }
122
123 /**
124 * Check whether profile uses booking times.
125 *
126 * @param string|null $profile Profile.
127 *
128 * @return bool
129 */
130 function wpbc_setup_wizard__is_time_based_profile( $profile = null ) {
131
132 $profile = ( null === $profile ) ? wpbc_setup_wizard__get_selected_profile() : $profile;
133
134 return in_array( $profile, array( 'time_slots', 'duration_appointments' ), true );
135 }
136
137 /**
138 * Check whether profile uses changeover mode.
139 *
140 * @param string|null $profile Profile.
141 *
142 * @return bool
143 */
144 function wpbc_setup_wizard__is_changeover_profile( $profile = null ) {
145
146 $profile = ( null === $profile ) ? wpbc_setup_wizard__get_selected_profile() : $profile;
147
148 return ( 'changeover' === $profile );
149 }
150
151 /**
152 * Get the internal setup wizard route before profile-specific external pages.
153 *
154 * @return array
155 */
156 function wpbc_setup_wizard__get_intro_route() {
157
158 $route = array( 'welcome' );
159 if ( ! wpbc_is_this_demo() ) {
160 $route[] = 'general_info';
161 }
162 $route[] = 'date_time_formats';
163 $route[] = 'bookings_types';
164
165 return $route;
166 }
167
168 /**
169 * Get profile-specific setup route matrix after "Booking Type".
170 *
171 * Steps 1-4 stay inside the setup wizard. Every route below starts with the shared Booking Form and Date Selection
172 * configuration, then branches only where the selected booking profile needs different existing WPBC admin pages.
173 *
174 * @return array
175 */
176 function wpbc_setup_wizard__get_profile_route_map() {
177
178 $full_day_route = array(
179 'form_structure',
180 'date_selection',
181 'date_availability',
182 'color_theme',
183 'wizard_publish',
184 'get_started',
185 );
186
187 $changeover_route = array(
188 'form_structure',
189 'date_selection',
190 'changeover_days',
191 'date_availability',
192 'color_theme',
193 'wizard_publish',
194 'get_started',
195 );
196
197 $time_based_route = array(
198 'form_structure',
199 'date_selection',
200 'working_time',
201 'time_slots_availability',
202 'color_theme',
203 'wizard_publish',
204 'get_started',
205 );
206
207 return array(
208 'full_day' => $full_day_route,
209 'changeover' => $changeover_route,
210 'time_slots' => $time_based_route,
211 'duration_appointments' => $time_based_route,
212 );
213 }
214
215 /**
216 * Get profile-specific setup route after "Booking Type".
217 *
218 * @param string|null $profile Profile.
219 * @param bool|null $is_bfb_enabled Deprecated. Kept for backward-compatible calls.
220 *
221 * @return array
222 */
223 function wpbc_setup_wizard__get_profile_route( $profile = null, $is_bfb_enabled = null ) {
224
225 $profile = ( null === $profile ) ? wpbc_setup_wizard__get_selected_profile() : $profile;
226 $route_map = wpbc_setup_wizard__get_profile_route_map();
227 $route = isset( $route_map[ $profile ] ) ? $route_map[ $profile ] : $route_map['full_day'];
228
229 if ( wpbc_is_this_demo() && 'changeover' !== $profile ) {
230 $route = array_values( array_diff( $route, array( 'wizard_publish' ) ) );
231 }
232
233 return $route;
234 }
235
236 /**
237 * Get the next setup step from the current profile route.
238 *
239 * @param string $current_step Current step name.
240 *
241 * @return string
242 */
243 function wpbc_setup_wizard__get_next_step_name( $current_step ) {
244
245 $route = array_merge( wpbc_setup_wizard__get_intro_route(), wpbc_setup_wizard__get_profile_route() );
246
247 $current_step_index = array_search( $current_step, $route, true );
248
249 if ( false === $current_step_index ) {
250 return '';
251 }
252
253 return isset( $route[ $current_step_index + 1 ] ) ? $route[ $current_step_index + 1 ] : '';
254 }
255
256 /**
257 * Check whether the step is rendered inside the setup wizard page.
258 *
259 * @param string $step_name Step name.
260 *
261 * @return bool
262 */
263 function wpbc_setup_wizard__is_internal_step( $step_name ) {
264
265 return in_array( $step_name, array( 'welcome', 'general_info', 'date_time_formats', 'bookings_types' ), true );
266 }
267
268 /**
269 * Detect the external setup step from the current WPBC admin page request.
270 *
271 * @return string
272 */
273 function wpbc_setup_wizard__detect_step_from_admin_request() {
274
275 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
276 $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
277 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
278 $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : '';
279 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
280 $scroll_to_section = isset( $_GET['scroll_to_section'] ) ? sanitize_key( wp_unslash( $_GET['scroll_to_section'] ) ) : '';
281 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
282 $wpbc_ag_open = isset( $_GET['wpbc_ag_open'] ) ? sanitize_key( wp_unslash( $_GET['wpbc_ag_open'] ) ) : '';
283 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
284 $wpbc_calendar_section = isset( $_GET['wpbc_calendar_section'] ) ? sanitize_key( wp_unslash( $_GET['wpbc_calendar_section'] ) ) : '';
285
286 if ( 'wpbc-settings' === $page ) {
287 if ( 'builder_booking_form' === $tab ) {
288 return 'form_structure';
289 }
290
291 if ( 'form' === $tab ) {
292 return 'form_structure';
293 }
294
295 if ( 'calendar_settings' === $tab ) {
296 if ( 'changeover_times' === $wpbc_calendar_section ) {
297 return 'changeover_days';
298 }
299 return 'date_selection';
300 }
301
302 if ( 'wpbc_general_settings_calendar_tab' === $scroll_to_section ) {
303 return 'date_selection';
304 }
305
306 if ( 'themes' === $tab ) {
307 return 'color_theme';
308 }
309 }
310
311 if ( 'wpbc-availability' === $page ) {
312 if ( 'time_slots_availability' === $tab ) {
313 return 'time_slots_availability';
314 }
315
316 if ( 'working_time' === $wpbc_ag_open ) {
317 return 'working_time';
318 }
319
320 return 'date_availability';
321 }
322
323 if ( 'wpbc-resources' === $page ) {
324 return 'wizard_publish';
325 }
326
327 return '';
328 }
329
330 /**
331 * Detect an external setup step from an admin URL.
332 *
333 * @param string $url URL.
334 *
335 * @return string
336 */
337 function wpbc_setup_wizard__detect_step_from_admin_url( $url ) {
338
339 if ( empty( $url ) ) {
340 return '';
341 }
342
343 $url_parts = wp_parse_url( $url );
344 if ( empty( $url_parts['query'] ) ) {
345 return '';
346 }
347
348 $query_args = array();
349 wp_parse_str( $url_parts['query'], $query_args );
350
351 $page = isset( $query_args['page'] ) ? sanitize_key( $query_args['page'] ) : '';
352 $tab = isset( $query_args['tab'] ) ? sanitize_key( $query_args['tab'] ) : '';
353 $scroll_to_section = isset( $query_args['scroll_to_section'] ) ? sanitize_key( $query_args['scroll_to_section'] ) : '';
354 $wpbc_ag_open = isset( $query_args['wpbc_ag_open'] ) ? sanitize_key( $query_args['wpbc_ag_open'] ) : '';
355 $wpbc_calendar_section = isset( $query_args['wpbc_calendar_section'] ) ? sanitize_key( $query_args['wpbc_calendar_section'] ) : '';
356
357 if ( 'wpbc-settings' === $page ) {
358 if ( 'builder_booking_form' === $tab ) {
359 return 'form_structure';
360 }
361
362 if ( 'form' === $tab ) {
363 return 'form_structure';
364 }
365
366 if ( 'calendar_settings' === $tab ) {
367 if ( 'changeover_times' === $wpbc_calendar_section ) {
368 return 'changeover_days';
369 }
370 return 'date_selection';
371 }
372
373 if ( 'wpbc_general_settings_calendar_tab' === $scroll_to_section ) {
374 return 'date_selection';
375 }
376
377 if ( 'themes' === $tab ) {
378 return 'color_theme';
379 }
380 }
381
382 if ( 'wpbc-availability' === $page ) {
383 if ( 'time_slots_availability' === $tab ) {
384 return 'time_slots_availability';
385 }
386
387 if ( 'working_time' === $wpbc_ag_open ) {
388 return 'working_time';
389 }
390
391 return 'date_availability';
392 }
393
394 if ( 'wpbc-resources' === $page ) {
395 return 'wizard_publish';
396 }
397
398 return '';
399 }
400
401 /**
402 * Get human-readable setup step title.
403 *
404 * @param string $step_name Step name.
405 *
406 * @return string
407 */
408 function wpbc_setup_wizard__get_step_title( $step_name ) {
409
410 $step_titles = array(
411 'welcome' => __( 'Welcome', 'booking' ),
412 'general_info' => __( 'General Info', 'booking' ),
413 'date_time_formats' => __( 'Dates and Times', 'booking' ),
414 'bookings_types' => __( 'Booking Type', 'booking' ),
415 'date_selection' => __( 'Date Selection', 'booking' ),
416 'changeover_days' => __( 'Changeover Days', 'booking' ),
417 'working_time' => __( 'Working Time', 'booking' ),
418 'time_slots_availability' => __( 'Time Slots', 'booking' ),
419 'date_availability' => __( 'Date Availability', 'booking' ),
420 'form_structure' => __( 'Booking Form', 'booking' ),
421 'color_theme' => __( 'Color Theme', 'booking' ),
422 'wizard_publish' => __( 'Publish', 'booking' ),
423 'get_started' => __( 'Get Started', 'booking' ),
424 );
425
426 return isset( $step_titles[ $step_name ] ) ? $step_titles[ $step_name ] : $step_name;
427 }
428
429 /**
430 * Get action-oriented setup step heading shown in the floating setup bar.
431 *
432 * @param string $step_name Step name.
433 *
434 * @return string
435 */
436 function wpbc_setup_wizard__get_step_heading( $step_name ) {
437
438 $step_headings = array(
439 'welcome' => __( 'Start the initial setup', 'booking' ),
440 'general_info' => __( 'Confirm your business details', 'booking' ),
441 'date_time_formats' => __( 'Choose date and time formats', 'booking' ),
442 'bookings_types' => __( 'Choose the main booking workflow', 'booking' ),
443 'form_structure' => __( 'Select and save the booking form template', 'booking' ),
444 'date_selection' => __( 'Set how visitors select dates', 'booking' ),
445 'changeover_days' => __( 'Configure changeover days', 'booking' ),
446 'working_time' => __( 'Define when bookings can start and end', 'booking' ),
447 'time_slots_availability' => __( 'Review availability for appointment slots', 'booking' ),
448 'date_availability' => __( 'Set date availability rules', 'booking' ),
449 'color_theme' => __( 'Choose the calendar appearance', 'booking' ),
450 'wizard_publish' => __( 'Publish the booking form on your site', 'booking' ),
451 'get_started' => __( 'Complete setup and manage bookings', 'booking' ),
452 );
453
454 return isset( $step_headings[ $step_name ] ) ? $step_headings[ $step_name ] : wpbc_setup_wizard__get_step_title( $step_name );
455 }
456
457 /**
458 * Get setup step guidance shown in the floating setup bar.
459 *
460 * @param string $step_name Step name.
461 *
462 * @return string
463 */
464 function wpbc_setup_wizard__get_step_description( $step_name ) {
465
466 $step_descriptions = array(
467 'welcome' => __( 'Begin the guided setup. You can leave the wizard at any time and continue later from the setup bar.', 'booking' ),
468 'general_info' => __( 'Review the business name, contact details, and basic information used while preparing the booking configuration.', 'booking' ),
469 'date_time_formats' => __( 'Pick the date and time display formats that should be used in the admin panel, booking form, and customer-facing messages.', 'booking' ),
470 'bookings_types' => __( 'Select whether bookings use full days, appointment time slots, or changeover-style date ranges. This choice controls the next configuration steps.', 'booking' ),
471 'form_structure' => __( 'Open the form template chooser, select the template that matches your booking type, and save the Booking Form page before continuing.', 'booking' ),
472 'date_selection' => __( 'Choose whether visitors can select one day, multiple individual days, or an available date range in the calendar. Save the General Settings page after changing this option.', 'booking' ),
473 'changeover_days' => __( 'Enable and review check-in/check-out changeover days, including diagonal or vertical markings and related changeover options.', 'booking' ),
474 'working_time' => __( 'Set the daily working hours that should be available for bookings. These hours are used as the base schedule for time-based availability.', 'booking' ),
475 'time_slots_availability' => __( 'Check the generated appointment slots and adjust any slot-specific availability rules before choosing the calendar appearance.', 'booking' ),
476 'date_availability' => __( 'Set which weekdays, dates, booking windows, and buffer rules should be available or unavailable for visitors.', 'booking' ),
477 'color_theme' => __( 'Choose the calendar skin and visual style so the booking form fits your site before you publish it.', 'booking' ),
478 'wizard_publish' => __( 'Use the Publish buttons for each booking resource to insert the booking form into an existing page, create a new page, or copy the shortcode.', 'booking' ),
479 'get_started' => __( 'Finish the setup wizard. After this, the setup bar will disappear and you can start managing bookings normally.', 'booking' ),
480 );
481
482 return isset( $step_descriptions[ $step_name ] ) ? $step_descriptions[ $step_name ] : '';
483 }
484
485 /**
486 * Get external setup step UI integration matrix.
487 *
488 * Each entry describes how the floating setup bar should connect a wizard step
489 * to an existing WPBC admin page: what to open, what to scroll/highlight, which
490 * form/save control belongs to this step, and which JS events mean the external
491 * page has saved successfully.
492 *
493 * @return array
494 */
495 function wpbc_setup_wizard__get_step_ui_matrix() {
496
497 return array(
498 'form_structure' => array(
499 'save_behavior' => 'manual_save_required',
500 'target_selector' => '.wpbc_admin_page__tab__builder_booking_form, #wpbc_form_field_free',
501 'scroll_selector' => '.wpbc_bfb_popup_modal__forms_loading_section:visible, #wpbc_form_field_free:visible, .wpbc_admin_page__tab__builder_booking_form:visible',
502 'highlight_selector' => '.wpbc_bfb_popup_modal__forms_loading_section:visible, #wpbc_form_field_free:visible, .wpbc_admin_page__tab__builder_booking_form:visible',
503 'form_selector' => '#wpbc_form_field_free',
504 'save_selector' => '#wpbc_form_field_free .wpbc_submit_button_trigger, #wpbc_form_field_free .wpbc_submit_button, [onclick*="wpbc_bfb__ajax_save_current_form"], [data-wpbc-bfb-save-source]',
505 'save_events' => 'wpbc:bfb:form:ajax_saved,wpbc:bfb:form:saved,wpbc:bfb:save:done,wpbc:bfb:ajax_saved,wpbc:setup-wizard:step-saved',
506 ),
507 'date_selection' => array(
508 'save_behavior' => 'manual_save_required',
509 'target_selector' => '.wpbc_admin_page__tab__calendar_settings, [data-wpbc-calendar-page="1"], .wpbc_tr_set_gen_booking_type_of_day_selections, #wpbc_general_settings_calendar_metabox',
510 'scroll_selector' => '[data-wpbc-calendar-page="1"]:visible, .wpbc_admin_page__tab__calendar_settings:visible, .wpbc_tr_set_gen_booking_type_of_day_selections:visible, #wpbc_general_settings_calendar_metabox:visible',
511 'highlight_selector' => '[data-wpbc-calendar-page="1"]:visible, .wpbc_admin_page__tab__calendar_settings:visible, .wpbc_tr_set_gen_booking_type_of_day_selections:visible, #wpbc_general_settings_calendar_metabox:visible',
512 'form_selector' => '[data-wpbc-calendar-settings-form="1"], #wpbc_general_settings_form',
513 'save_selector' => '[data-wpbc-calendar-save="1"], #wpbc_general_settings_form .wpbc_submit_button_trigger, #wpbc_general_settings_form .wpbc_submit_button',
514 'save_events' => 'wpbc:setup-wizard:step-saved',
515 ),
516 'changeover_days' => array(
517 'save_behavior' => 'manual_save_required',
518 'target_selector' => '[data-group="settings-calendar-time"], [data-wpbc-calendar-changeover-settings="1"], [name="booking_range_selection_time_is_active"], [data-wpbc-calendar-page="1"]',
519 'scroll_selector' => '[data-group="settings-calendar-time"]:visible, [data-wpbc-calendar-changeover-settings="1"]:visible, [name="booking_range_selection_time_is_active"]:visible, [data-wpbc-calendar-page="1"]:visible',
520 'highlight_selector' => '[data-group="settings-calendar-time"]:visible, [data-wpbc-calendar-changeover-settings="1"]:visible, [name="booking_range_selection_time_is_active"]:visible',
521 'form_selector' => '[data-wpbc-calendar-settings-form="1"]',
522 'save_selector' => '[data-wpbc-calendar-save="1"]',
523 'save_events' => 'wpbc:setup-wizard:step-saved',
524 ),
525 'working_time' => array(
526 'save_behavior' => 'manual_save_required',
527 'target_selector' => '[data-group="general-availability-working-time"], .wpbc_ag_working_time_block, .wpbc_admin_page__tab__general_availability',
528 'scroll_selector' => '[data-group="general-availability-working-time"]:visible, .wpbc_ag_working_time_block:visible, [data-wpbc-ag-settings-form="1"]:visible',
529 'highlight_selector' => '[data-group="general-availability-working-time"]:visible, .wpbc_ag_working_time_block:visible',
530 'form_selector' => '[data-wpbc-ag-settings-form="1"]',
531 'save_selector' => '[data-wpbc-ag-save="1"]',
532 'save_events' => 'wpbc:availability-general:settings-saved,wpbc:setup-wizard:step-saved',
533 'open_action' => 'availability_section',
534 ),
535 'time_slots_availability' => array(
536 'save_behavior' => 'link_only',
537 'target_selector' => '.wpbc_admin_page__tab__time_slots_availability, .wpbc_ts_page',
538 'scroll_selector' => '.wpbc_admin_page__tab__time_slots_availability:visible, .wpbc_ts_page:visible',
539 'highlight_selector' => '.wpbc_admin_page__tab__time_slots_availability:visible, .wpbc_ts_page:visible',
540 ),
541 'date_availability' => array(
542 'save_behavior' => 'manual_save_required',
543 'target_selector' => '[data-group="general-availability-weekdays"], .wpbc_admin_page__tab__general_availability, [data-wpbc-ag-settings-form="1"]',
544 'scroll_selector' => '[data-group="general-availability-weekdays"]:visible, [data-wpbc-ag-settings-form="1"]:visible',
545 'highlight_selector' => '[data-group="general-availability-weekdays"]:visible, [data-wpbc-ag-settings-form="1"]:visible',
546 'form_selector' => '[data-wpbc-ag-settings-form="1"]',
547 'save_selector' => '[data-wpbc-ag-save="1"]',
548 'save_events' => 'wpbc:availability-general:settings-saved,wpbc:setup-wizard:step-saved',
549 'open_action' => 'availability_section',
550 ),
551 'color_theme' => array(
552 'save_behavior' => 'manual_save_required',
553 'target_selector' => '.wpbc_admin_page__tab__themes, [data-wpbc-theme-page="1"]',
554 'scroll_selector' => '[data-wpbc-theme-page="1"]:visible, .wpbc_admin_page__tab__themes:visible',
555 'highlight_selector' => '[data-wpbc-theme-page="1"]:visible, .wpbc_admin_page__tab__themes:visible',
556 'form_selector' => '[data-wpbc-theme-settings-form="1"]',
557 'save_selector' => '[data-wpbc-theme-save="1"]',
558 'save_events' => 'wpbc:setup-wizard:step-saved',
559 ),
560 'wizard_publish' => array(
561 'save_behavior' => 'link_only',
562 'target_selector' => '.ui_group__publish_btn, .wpbc_resource_field__publish, .wpbc_resource_publish, .wpbc_publish_resources, .wpbc_resource_shortcode, [data-wpbc-resource-publish], #wpbc_booking_resource_table, .wpbc_admin_page',
563 'scroll_selector' => '.ui_group__publish_btn:visible, .wpbc_resource_field__publish:visible, .wpbc_resource_publish:visible, .wpbc_publish_resources:visible, .wpbc_resource_shortcode:visible, [data-wpbc-resource-publish]:visible, #wpbc_booking_resource_table:visible',
564 'highlight_selector' => '.ui_group__publish_btn:visible, .wpbc_resource_field__publish:visible, .wpbc_resource_publish:visible, .wpbc_publish_resources:visible, .wpbc_resource_shortcode:visible, [data-wpbc-resource-publish]:visible, #wpbc_booking_resource_table:visible',
565 'open_action' => 'publish_area',
566 ),
567 'get_started' => array(
568 'save_behavior' => 'complete',
569 'target_selector' => '.wpbc_admin_page',
570 'scroll_selector' => '.wpbc_admin_page:visible',
571 'highlight_selector' => '.wpbc_admin_page:visible',
572 ),
573 );
574 }
575
576 /**
577 * Get one UI integration value from the external setup step matrix.
578 *
579 * @param string $step_name Step name.
580 * @param string $key Matrix key.
581 *
582 * @return string
583 */
584 function wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, $key ) {
585
586 $ui_matrix = wpbc_setup_wizard__get_step_ui_matrix();
587
588 return ( isset( $ui_matrix[ $step_name ][ $key ] ) ) ? (string) $ui_matrix[ $step_name ][ $key ] : '';
589 }
590
591 /**
592 * Get save behavior for external setup step.
593 *
594 * @param string $step_name Step name.
595 *
596 * @return string
597 */
598 function wpbc_setup_wizard__get_step_save_behavior( $step_name ) {
599
600 $save_behavior = wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'save_behavior' );
601
602 return ( ! empty( $save_behavior ) ) ? $save_behavior : 'link_only';
603 }
604
605 /**
606 * Get DOM selector to highlight/scroll on external setup pages.
607 *
608 * @param string $step_name Step name.
609 *
610 * @return string
611 */
612 function wpbc_setup_wizard__get_step_target_selector( $step_name ) {
613
614 return wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'target_selector' );
615 }
616
617 /**
618 * Get DOM selector to scroll on external setup pages.
619 *
620 * @param string $step_name Step name.
621 *
622 * @return string
623 */
624 function wpbc_setup_wizard__get_step_scroll_selector( $step_name ) {
625
626 $scroll_selector = wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'scroll_selector' );
627
628 return ( ! empty( $scroll_selector ) ) ? $scroll_selector : wpbc_setup_wizard__get_step_target_selector( $step_name );
629 }
630
631 /**
632 * Get DOM selector to highlight on external setup pages.
633 *
634 * @param string $step_name Step name.
635 *
636 * @return string
637 */
638 function wpbc_setup_wizard__get_step_highlight_selector( $step_name ) {
639
640 $highlight_selector = wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'highlight_selector' );
641
642 return ( ! empty( $highlight_selector ) ) ? $highlight_selector : wpbc_setup_wizard__get_step_target_selector( $step_name );
643 }
644
645 /**
646 * Get page open action for external setup pages.
647 *
648 * @param string $step_name Step name.
649 *
650 * @return string
651 */
652 function wpbc_setup_wizard__get_step_open_action( $step_name ) {
653
654 return wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'open_action' );
655 }
656
657 /**
658 * Get browser events that confirm an external setup page save.
659 *
660 * @param string $step_name Step name.
661 *
662 * @return string
663 */
664 function wpbc_setup_wizard__get_step_save_events( $step_name ) {
665
666 return wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'save_events' );
667 }
668
669 /**
670 * Get DOM selector for the existing page form related to the setup step.
671 *
672 * @param string $step_name Step name.
673 *
674 * @return string
675 */
676 function wpbc_setup_wizard__get_step_form_selector( $step_name ) {
677
678 return wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'form_selector' );
679 }
680
681 /**
682 * Get selector for the existing page save button related to the setup step.
683 *
684 * @param string $step_name Step name.
685 *
686 * @return string
687 */
688 function wpbc_setup_wizard__get_step_save_selector( $step_name ) {
689
690 return wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'save_selector' );
691 }
692
693 /**
694 * Add setup guide context to a target URL.
695 *
696 * @param string $url URL.
697 * @param string $step_name Step name.
698 *
699 * @return string
700 */
701 function wpbc_setup_wizard__add_setup_context_to_url( $url, $step_name ) {
702
703 return add_query_arg(
704 array(
705 'wpbc_setup' => '1',
706 'wpbc_setup_step' => $step_name,
707 ),
708 $url
709 );
710 }
711
712 /**
713 * Get the Form Builder template search key for the selected booking type.
714 *
715 * @return string
716 */
717 function wpbc_setup_wizard__get_bfb_template_search_key() {
718
719 $booking_wizard_data_arr = get_bk_option( 'booking_wizard_data' );
720 if (
721 empty( $booking_wizard_data_arr )
722 || ! is_array( $booking_wizard_data_arr )
723 || empty( $booking_wizard_data_arr['save_and_continue__bookings_types'] )
724 || ! is_array( $booking_wizard_data_arr['save_and_continue__bookings_types'] )
725 ) {
726 return '';
727 }
728
729 $booking_type = isset( $booking_wizard_data_arr['save_and_continue__bookings_types']['wpbc_swp_booking_types'] )
730 ? $booking_wizard_data_arr['save_and_continue__bookings_types']['wpbc_swp_booking_types']
731 : '';
732 $url_sep = defined( 'WPBC_BFB_TEMPLATE_SEARCH_OR_SEPARATOR_URL' ) ? WPBC_BFB_TEMPLATE_SEARCH_OR_SEPARATOR_URL : '^';
733
734 if ( 'full_days_bookings' === $booking_type ) {
735 return 'full-days' . $url_sep . 'dates_form';
736 }
737
738 if ( 'time_slots_appointments' === $booking_type ) {
739 if ( 'rangetime' === wpbc_setup_wizard__get_selected_appointments_type( $booking_wizard_data_arr ) ) {
740 return 'times' . $url_sep . 'time slots';
741 }
742
743 return 'appointments' . $url_sep . 'service';
744 }
745
746 if ( 'changeover_multi_dates_bookings' === $booking_type ) {
747 return 'changeover' . $url_sep . 'triangles';
748 }
749
750 return '';
751 }
752
753 /**
754 * Get the existing admin page URL that should handle a setup step.
755 *
756 * @param string $step_name Step name.
757 *
758 * @return string
759 */
760 function wpbc_setup_wizard__get_step_target_url( $step_name ) {
761
762 if ( wpbc_setup_wizard__is_internal_step( $step_name ) ) {
763 return add_query_arg( 'current_step', $step_name, wpbc_get_setup_wizard_page_url() );
764 }
765
766 switch ( $step_name ) {
767 case 'date_selection':
768 $url = function_exists( 'wpbc_get_settings_calendar_url' )
769 ? wpbc_get_settings_calendar_url()
770 : wpbc_get_settings_url() . '&tab=calendar_settings';
771 $url = add_query_arg( 'wpbc_calendar_section', 'days_selection', $url );
772 break;
773
774 case 'changeover_days':
775 $url = function_exists( 'wpbc_get_settings_calendar_url' )
776 ? wpbc_get_settings_calendar_url()
777 : wpbc_get_settings_url() . '&tab=calendar_settings';
778 $url = add_query_arg( 'wpbc_calendar_section', 'changeover_times', $url );
779 break;
780
781 case 'working_time':
782 $url = function_exists( 'wpbc_get_general_availability_url' )
783 ? wpbc_get_general_availability_url()
784 : admin_url( 'admin.php?page=wpbc-availability&tab=general_availability' );
785 $url = add_query_arg( 'wpbc_ag_open', 'working_time', $url );
786 break;
787
788 case 'time_slots_availability':
789 $url = function_exists( 'wpbc_get_time_slots_availability_url' )
790 ? wpbc_get_time_slots_availability_url()
791 : admin_url( 'admin.php?page=wpbc-availability&tab=time_slots_availability' );
792 break;
793
794 case 'date_availability':
795 $url = function_exists( 'wpbc_get_general_availability_url' )
796 ? wpbc_get_general_availability_url()
797 : admin_url( 'admin.php?page=wpbc-availability&tab=general_availability' );
798 $url = add_query_arg( 'wpbc_ag_open', 'weekdays', $url );
799 break;
800
801 case 'form_structure':
802 $is_bfb_enabled = ( class_exists( 'WPBC_Frontend_Settings' ) && (bool) WPBC_Frontend_Settings::is_bfb_enabled( null ) );
803
804 $url = $is_bfb_enabled
805 ? wpbc_get_settings_url() . '&tab=builder_booking_form'
806 : wpbc_get_settings_url() . '&tab=form';
807 if ( $is_bfb_enabled ) {
808 $template_search_key = wpbc_setup_wizard__get_bfb_template_search_key();
809 if ( ! empty( $template_search_key ) ) {
810 $url = add_query_arg( 'auto_open_template', $template_search_key, $url );
811 }
812 }
813 break;
814
815 case 'color_theme':
816 $url = function_exists( 'wpbc_get_settings_themes_url' )
817 ? wpbc_get_settings_themes_url()
818 : wpbc_get_settings_url() . '&tab=themes';
819 break;
820
821 case 'wizard_publish':
822 $url = wpbc_get_resources_url() . '#wpbc_booking_resource_table';
823 break;
824
825 case 'get_started':
826 $url = wpbc_get_bookings_url() . '&tab=vm_booking_listing';
827 break;
828
829 default:
830 $url = wpbc_get_setup_wizard_page_url();
831 break;
832 }
833
834 return wpbc_setup_wizard__add_setup_context_to_url( $url, $step_name );
835 }
836
837 /**
838 * Get URL that completes an external setup step and redirects to the next mapped step.
839 *
840 * @param string $step_name Step name.
841 *
842 * @return string
843 */
844 function wpbc_setup_wizard__get_step_continue_url( $step_name ) {
845
846 if ( wpbc_setup_wizard__is_internal_step( $step_name ) ) {
847 return wpbc_setup_wizard__get_step_target_url( $step_name );
848 }
849
850 return add_query_arg(
851 array(
852 'wpbc_setup_wizard' => 'continue',
853 'wpbc_setup_step' => $step_name,
854 'wpbc_setup_from_page_step' => $step_name,
855 '_wpnonce' => wp_create_nonce( 'wpbc_settings_url_nonce' ),
856 ),
857 wpbc_get_setup_wizard_page_url()
858 );
859 }
860
861 /**
862 * Get setup step metadata for routing and UI.
863 *
864 * @param string $step_name Step name.
865 *
866 * @return array
867 */
868 function wpbc_setup_wizard__get_step_route_metadata( $step_name ) {
869
870 return array(
871 'is_external' => ! wpbc_setup_wizard__is_internal_step( $step_name ),
872 'target_url' => wpbc_setup_wizard__get_step_target_url( $step_name ),
873 'title' => wpbc_setup_wizard__get_step_title( $step_name ),
874 'heading' => wpbc_setup_wizard__get_step_heading( $step_name ),
875 'description' => wpbc_setup_wizard__get_step_description( $step_name ),
876 'save_behavior' => wpbc_setup_wizard__get_step_save_behavior( $step_name ),
877 'target_selector' => wpbc_setup_wizard__get_step_target_selector( $step_name ),
878 'scroll_selector' => wpbc_setup_wizard__get_step_scroll_selector( $step_name ),
879 'highlight_selector' => wpbc_setup_wizard__get_step_highlight_selector( $step_name ),
880 'form_selector' => wpbc_setup_wizard__get_step_form_selector( $step_name ),
881 'save_selector' => wpbc_setup_wizard__get_step_save_selector( $step_name ),
882 'save_events' => wpbc_setup_wizard__get_step_save_events( $step_name ),
883 'open_action' => wpbc_setup_wizard__get_step_open_action( $step_name ),
884 );
885 }
886
887 /**
888 * Get first step after "Booking Type" for current profile.
889 *
890 * @return string
891 */
892 function wpbc_setup_wizard__get_first_profile_step() {
893
894 $route = wpbc_setup_wizard__get_profile_route();
895
896 return ( empty( $route ) ) ? 'color_theme' : $route[0];
897 }
898