PluginProbe
Booking Calendar / 11.8.3
Booking Calendar v11.8.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
← All changes | includes/page-setup/setup_profiles.php +535 -258 11.411.8.3 View file →
@@ -8,30 +8,39 @@
8 8
9 9 /**
10 10 * Store the WPBC admin fullscreen preference for the current user.
11 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.
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 and its immediate browser cookie when it moves between internal and external
15 + * setup screens. Synchronizing both values prevents an older cookie from overriding the active wizard state.
16 + * This sends a response cookie when headers remain available and always updates the cookie value for the current
17 + * request.
15 18 *
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 ) {
19 + * @param bool $is_full_screen Whether WPBC admin pages should open in fullscreen mode.
20 + *
21 + * @return bool True when the saved user option changed; otherwise false.
22 + */
23 +function wpbc_setup_wizard__set_full_screen_mode_for_current_user( $is_full_screen ) {
24 +
25 + $user_id = wpbc_get_current_user_id();
21 26
22 - $user_id = wpbc_get_current_user_id();
23 -
24 27 if ( empty( $user_id ) ) {
25 28 return false;
26 29 }
27 30
28 - return update_user_option(
29 - $user_id,
30 - 'booking_custom_is_full_screen',
31 - array( 'value' => $is_full_screen ? 'On' : 'Off' )
32 - );
33 -}
31 + $full_screen_value = $is_full_screen ? 'On' : 'Off';
32 +
33 + if ( function_exists( 'wpbc_ui__set_full_screen_mode_cookie' ) ) {
34 + wpbc_ui__set_full_screen_mode_cookie( $full_screen_value );
35 + }
36 +
37 + return update_user_option(
38 + $user_id,
39 + 'booking_custom_is_full_screen',
40 + array( 'value' => $full_screen_value )
41 + );
42 +}
34 43
35 44 /**
36 45 * Get persisted wizard choices.
37 46 *
@@ -36,9 +45,9 @@
36 45 * Get persisted wizard choices.
37 46 *
38 47 * @return array
39 48 */
40 -function wpbc_setup_wizard__get_booking_wizard_data() {
49 +function wpbc_setup_wizard__get_booking_wizard_data() {
41 50
42 51 $wizard_data = get_bk_option( 'booking_wizard_data' );
43 52
44 53 return ( empty( $wizard_data ) || ( ! is_array( $wizard_data ) ) ) ? array() : $wizard_data;
@@ -81,29 +90,88 @@
81 90 * @param array|null $wizard_data Wizard data.
82 91 *
83 92 * @return string
84 93 */
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 (
94 +function wpbc_setup_wizard__get_selected_appointments_type( $wizard_data = null ) {
95 +
96 + if ( null === $wizard_data ) {
97 + $wizard_data = wpbc_setup_wizard__get_booking_wizard_data();
98 + }
99 +
100 + // Appointment mode always uses the Service duration and start-time flow.
101 + if ( 'appointment' === wpbc_setup_wizard__get_selected_mode_id( $wizard_data ) ) {
102 + return 'durationtime';
103 + }
104 +
105 + if (
92 106 isset( $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_appointments_type'] )
93 107 && ( ! empty( $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_appointments_type'] ) )
94 108 ) {
95 109 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 - *
110 + }
111 +
112 + return 'rangetime';
113 +}
114 +
115 +/**
116 + * Check whether Booking Modes can resolve the current owner safely.
117 + *
118 + * Setup progress can be inspected while active plugins are still loading.
119 + * Before `init`, WordPress has not guaranteed that current-user pluggable
120 + * functions or just-in-time translation loading are ready. Mode registries
121 + * must therefore remain untouched until this boundary is reached.
122 + *
123 + * @return bool True when current-user and translation-dependent mode APIs can
124 + * be used safely.
125 + */
126 +function wpbc_setup_wizard__is_booking_modes_runtime_ready() {
127 +
128 + return did_action( 'init' ) && function_exists( 'wp_get_current_user' );
129 +}
130 +
131 +/**
132 + * Get the presentation mode selected in wizard history or owner settings.
133 + *
134 + * Missing historical mode data is expected on upgrades. In that case the
135 + * owner-scoped Booking Modes setting remains authoritative, with Classic as a
136 + * compatibility fallback when the feature module is unavailable.
137 + *
138 + * @param array|null $wizard_data Wizard data.
139 + *
140 + * @return string Allowed Booking Modes identifier.
141 + */
142 +function wpbc_setup_wizard__get_selected_mode_id( $wizard_data = null ) {
143 +
144 + if ( null === $wizard_data ) {
145 + $wizard_data = wpbc_setup_wizard__get_booking_wizard_data();
146 + }
147 +
148 + $saved_mode_id = isset( $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_mode'] )
149 + ? sanitize_key( (string) $wizard_data['save_and_continue__bookings_types']['wpbc_swp_booking_mode'] )
150 + : '';
151 + $standard_mode_ids = array( 'classic', 'appointment', 'rental' );
152 +
153 + if ( ! wpbc_setup_wizard__is_booking_modes_runtime_ready() ) {
154 + return in_array( $saved_mode_id, $standard_mode_ids, true ) ? $saved_mode_id : 'classic';
155 + }
156 +
157 + if ( function_exists( 'wpbc_booking_modes_get_allowed_mode_ids' ) ) {
158 + $allowed_mode_ids = wpbc_booking_modes_get_allowed_mode_ids();
159 + if ( in_array( $saved_mode_id, $allowed_mode_ids, true ) ) {
160 + return $saved_mode_id;
161 + }
162 +
163 + return wpbc_booking_modes_get_selected_mode_id();
164 + }
165 +
166 + return 'classic';
167 +}
168 +
169 +/**
170 + * Convert selected booking type to a setup profile.
171 + *
172 + * @param array|null $wizard_data Wizard data.
173 + *
106 174 * @return string
107 175 */
108 176 function wpbc_setup_wizard__get_selected_profile( $wizard_data = null ) {
109 177
@@ -167,10 +235,11 @@
167 235
168 236 /**
169 237 * Get profile-specific setup route matrix after "Booking Type".
170 238 *
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.
239 + * Steps 1-4 stay inside the setup wizard. These compatibility routes remain
240 + * behavior-based; `wpbc_setup_wizard__get_profile_route()` can replace their
241 + * order for a presentation mode while reusing the same canonical controllers.
173 242 *
174 243 * @return array
175 244 */
176 245 function wpbc_setup_wizard__get_profile_route_map() {
@@ -203,10 +272,10 @@
203 272 'wizard_publish',
204 273 'get_started',
205 274 );
206 275
207 - return array(
208 - 'full_day' => $full_day_route,
276 + return array(
277 + 'full_day' => $full_day_route,
209 278 'changeover' => $changeover_route,
210 279 'time_slots' => $time_based_route,
211 280 'duration_appointments' => $time_based_route,
212 281 );
@@ -215,25 +284,65 @@
215 284 /**
216 285 * Get profile-specific setup route after "Booking Type".
217 286 *
218 287 * @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 ) {
288 + * @param bool|null $is_bfb_enabled Deprecated. Kept for backward-compatible calls.
289 + *
290 + * @return array
291 + */
292 +function wpbc_setup_wizard__get_profile_route( $profile = null, $is_bfb_enabled = null ) {
293 +
294 + $profile = ( null === $profile ) ? wpbc_setup_wizard__get_selected_profile() : $profile;
295 + $mode_id = wpbc_setup_wizard__get_selected_mode_id();
296 + $route_map = wpbc_setup_wizard__get_profile_route_map();
297 +
298 + /**
299 + * Filter whether Setup temporarily ends with a Form Builder handoff.
300 + *
301 + * The compact route keeps the four introductory screens and uses Form
302 + * Builder as the fifth and final destination. Returning false restores the
303 + * longer mode-aware route while it remains available for compatibility.
304 + *
305 + * @param bool $is_enabled Whether the compact Form Builder handoff is enabled.
306 + * @param string $mode_id Active administration mode.
307 + * @param string $profile Selected booking behavior profile.
308 + */
309 + $is_compact_form_builder_handoff = (bool) apply_filters(
310 + 'wpbc_setup_wizard_compact_form_builder_handoff_enabled',
311 + true,
312 + $mode_id,
313 + $profile
314 + );
315 +
316 + if ( $is_compact_form_builder_handoff ) {
317 + $route = array( 'form_structure' );
318 + } elseif ( 'appointment' === $mode_id ) {
319 + $route = array(
320 + 'service_provider',
321 + 'working_time',
322 + 'date_availability',
323 + 'time_slots_availability',
324 + 'form_structure',
325 + 'color_theme',
326 + 'wizard_publish',
327 + 'get_started',
328 + );
329 + } else {
330 + $route = isset( $route_map[ $profile ] ) ? $route_map[ $profile ] : $route_map['full_day'];
331 + }
332 +
333 + /**
334 + * Filter the mode-aware Setup Wizard route after Step 4.
335 + *
336 + * @param array $route Ordered external setup steps.
337 + * @param string $mode_id Active Booking Modes identifier.
338 + * @param string $profile Booking behavior profile.
339 + */
340 + $route = apply_filters( 'wpbc_setup_wizard_profile_route', $route, $mode_id, $profile );
341 +
342 + return is_array( $route ) ? array_values( $route ) : array();
343 +}
224 344
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 345 /**
237 346 * Get the next setup step from the current profile route.
238 347 *
239 348 * @param string $current_step Current step name.
@@ -269,9 +378,9 @@
269 378 * Detect the external setup step from the current WPBC admin page request.
270 379 *
271 380 * @return string
272 381 */
273 -function wpbc_setup_wizard__detect_step_from_admin_request() {
382 +function wpbc_setup_wizard__detect_step_from_admin_request() {
274 383
275 384 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
276 385 $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
277 386 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
@@ -276,19 +385,25 @@
276 385 $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
277 386 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
278 387 $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : '';
279 388 // 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'] ) ) : '';
389 + $scroll_to_section = isset( $_GET['scroll_to_section'] ) ? sanitize_key( wp_unslash( $_GET['scroll_to_section'] ) ) : '';
390 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
391 + $wpbc_ag_open = isset( $_GET['wpbc_ag_open'] ) ? sanitize_key( wp_unslash( $_GET['wpbc_ag_open'] ) ) : '';
392 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
393 + $wpbc_calendar_section = isset( $_GET['wpbc_calendar_section'] ) ? sanitize_key( wp_unslash( $_GET['wpbc_calendar_section'] ) ) : '';
394 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
395 + $wpbc_setup_step = isset( $_GET['wpbc_setup_step'] ) ? sanitize_key( wp_unslash( $_GET['wpbc_setup_step'] ) ) : '';
396 +
397 + if ( '' !== $wpbc_setup_step ) {
398 + return $wpbc_setup_step;
399 + }
400 +
401 + if ( 'wpbc-settings' === $page ) {
402 + if ( 'builder_booking_form' === $tab ) {
403 + return 'form_structure';
404 + }
285 405
286 - if ( 'wpbc-settings' === $page ) {
287 - if ( 'builder_booking_form' === $tab ) {
288 - return 'form_structure';
289 - }
290 -
291 406 if ( 'form' === $tab ) {
292 407 return 'form_structure';
293 408 }
294 409
@@ -303,31 +418,35 @@
303 418 return 'date_selection';
304 419 }
305 420
306 421 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 ) {
422 + return 'color_theme';
423 + }
424 + }
425 +
426 + if ( 'wpbc-availability' === $page ) {
427 + if ( 'time_slots_availability' === $tab ) {
428 + return 'time_slots_availability';
429 + }
430 +
431 + if ( 'working_time' === $wpbc_ag_open ) {
317 432 return 'working_time';
318 433 }
434 +
435 + return 'date_availability';
436 + }
437 +
438 + if ( 'wpbc-resources' === $page ) {
439 + return 'wizard_publish';
440 + }
441 +
442 + if ( 'wpbc-services' === $page && 'appointment_services' === $tab ) {
443 + return 'service_provider';
444 + }
445 +
446 + return '';
447 +}
319 448
320 - return 'date_availability';
321 - }
322 -
323 - if ( 'wpbc-resources' === $page ) {
324 - return 'wizard_publish';
325 - }
326 -
327 - return '';
328 -}
329 -
330 449 /**
331 450 * Detect an external setup step from an admin URL.
332 451 *
333 452 * @param string $url URL.
@@ -347,19 +466,24 @@
347 466
348 467 $query_args = array();
349 468 wp_parse_str( $url_parts['query'], $query_args );
350 469
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'] ) : '';
470 + $page = isset( $query_args['page'] ) ? sanitize_key( $query_args['page'] ) : '';
471 + $tab = isset( $query_args['tab'] ) ? sanitize_key( $query_args['tab'] ) : '';
472 + $scroll_to_section = isset( $query_args['scroll_to_section'] ) ? sanitize_key( $query_args['scroll_to_section'] ) : '';
473 + $wpbc_ag_open = isset( $query_args['wpbc_ag_open'] ) ? sanitize_key( $query_args['wpbc_ag_open'] ) : '';
474 + $wpbc_calendar_section = isset( $query_args['wpbc_calendar_section'] ) ? sanitize_key( $query_args['wpbc_calendar_section'] ) : '';
475 + $wpbc_setup_step = isset( $query_args['wpbc_setup_step'] ) ? sanitize_key( $query_args['wpbc_setup_step'] ) : '';
476 +
477 + if ( '' !== $wpbc_setup_step ) {
478 + return $wpbc_setup_step;
479 + }
480 +
481 + if ( 'wpbc-settings' === $page ) {
482 + if ( 'builder_booking_form' === $tab ) {
483 + return 'form_structure';
484 + }
356 485
357 - if ( 'wpbc-settings' === $page ) {
358 - if ( 'builder_booking_form' === $tab ) {
359 - return 'form_structure';
360 - }
361 -
362 486 if ( 'form' === $tab ) {
363 487 return 'form_structure';
364 488 }
365 489
@@ -374,31 +498,35 @@
374 498 return 'date_selection';
375 499 }
376 500
377 501 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 ) {
502 + return 'color_theme';
503 + }
504 + }
505 +
506 + if ( 'wpbc-availability' === $page ) {
507 + if ( 'time_slots_availability' === $tab ) {
508 + return 'time_slots_availability';
509 + }
510 +
511 + if ( 'working_time' === $wpbc_ag_open ) {
388 512 return 'working_time';
389 513 }
514 +
515 + return 'date_availability';
516 + }
517 +
518 + if ( 'wpbc-resources' === $page ) {
519 + return 'wizard_publish';
520 + }
521 +
522 + if ( 'wpbc-services' === $page && 'appointment_services' === $tab ) {
523 + return 'service_provider';
524 + }
525 +
526 + return '';
527 +}
390 528
391 - return 'date_availability';
392 - }
393 -
394 - if ( 'wpbc-resources' === $page ) {
395 - return 'wizard_publish';
396 - }
397 -
398 - return '';
399 -}
400 -
401 529 /**
402 530 * Get human-readable setup step title.
403 531 *
404 532 * @param string $step_name Step name.
@@ -404,29 +532,43 @@
404 532 * @param string $step_name Step name.
405 533 *
406 534 * @return string
407 535 */
408 -function wpbc_setup_wizard__get_step_title( $step_name ) {
536 +function wpbc_setup_wizard__get_step_title( $step_name ) {
537 + $mode_id = wpbc_setup_wizard__get_selected_mode_id();
538 +
539 + if ( 'wizard_publish' === $step_name && 'appointment' === $mode_id ) {
540 + return __( 'Appointment Page', 'booking' );
541 + }
542 +
543 + if ( 'wizard_publish' === $step_name && 'rental' === $mode_id ) {
544 + return __( 'Rental Page', 'booking' );
545 + }
546 +
547 + if ( 'date_availability' === $step_name && 'appointment' === $mode_id ) {
548 + return __( 'Days Off', 'booking' );
549 + }
409 550
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 - );
551 + $step_titles = array(
552 + 'welcome' => __( 'Welcome', 'booking' ),
553 + 'general_info' => __( 'General Info', 'booking' ),
554 + 'date_time_formats' => __( 'Dates and Times', 'booking' ),
555 + 'bookings_types' => __( 'Booking Type', 'booking' ),
556 + 'service_provider' => __( 'Service and Provider', 'booking' ),
557 + 'date_selection' => __( 'Date Selection', 'booking' ),
558 + 'changeover_days' => __( 'Changeover Days', 'booking' ),
559 + 'working_time' => __( 'Working Time', 'booking' ),
560 + 'time_slots_availability' => __( 'Time Slots', 'booking' ),
561 + 'date_availability' => __( 'Date Availability', 'booking' ),
562 + 'form_structure' => __( 'Booking Form', 'booking' ),
563 + 'color_theme' => __( 'Color Theme', 'booking' ),
564 + 'wizard_publish' => __( 'Publish', 'booking' ),
565 + 'get_started' => __( 'Get Started', 'booking' ),
566 + );
567 +
568 + return isset( $step_titles[ $step_name ] ) ? $step_titles[ $step_name ] : $step_name;
569 +}
425 570
426 - return isset( $step_titles[ $step_name ] ) ? $step_titles[ $step_name ] : $step_name;
427 -}
428 -
429 571 /**
430 572 * Get action-oriented setup step heading shown in the floating setup bar.
431 573 *
432 574 * @param string $step_name Step name.
@@ -432,29 +574,43 @@
432 574 * @param string $step_name Step name.
433 575 *
434 576 * @return string
435 577 */
436 -function wpbc_setup_wizard__get_step_heading( $step_name ) {
578 +function wpbc_setup_wizard__get_step_heading( $step_name ) {
579 + $mode_id = wpbc_setup_wizard__get_selected_mode_id();
580 +
581 + if ( 'wizard_publish' === $step_name && 'appointment' === $mode_id ) {
582 + return __( 'Review and test the Appointment page', 'booking' );
583 + }
584 +
585 + if ( 'wizard_publish' === $step_name && 'rental' === $mode_id ) {
586 + return __( 'Review and test the Rental page', 'booking' );
587 + }
588 +
589 + if ( 'date_availability' === $step_name && 'appointment' === $mode_id ) {
590 + return __( 'Block Provider days off and exceptions', 'booking' );
591 + }
437 592
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 - );
593 + $step_headings = array(
594 + 'welcome' => __( 'Start the initial setup', 'booking' ),
595 + 'general_info' => __( 'Confirm your business details', 'booking' ),
596 + 'date_time_formats' => __( 'Choose date and time formats', 'booking' ),
597 + 'bookings_types' => __( 'Choose the main booking workflow', 'booking' ),
598 + 'service_provider' => __( 'Review your first Service and Provider', 'booking' ),
599 + 'form_structure' => __( 'Select and save the booking form template', 'booking' ),
600 + 'date_selection' => __( 'Set how visitors select dates', 'booking' ),
601 + 'changeover_days' => __( 'Configure changeover days', 'booking' ),
602 + 'working_time' => __( 'Define when bookings can start and end', 'booking' ),
603 + 'time_slots_availability' => __( 'Review availability for appointment slots', 'booking' ),
604 + 'date_availability' => __( 'Set date availability rules', 'booking' ),
605 + 'color_theme' => __( 'Choose the calendar appearance', 'booking' ),
606 + 'wizard_publish' => __( 'Publish the booking form on your site', 'booking' ),
607 + 'get_started' => __( 'Complete setup and manage bookings', 'booking' ),
608 + );
609 +
610 + return isset( $step_headings[ $step_name ] ) ? $step_headings[ $step_name ] : wpbc_setup_wizard__get_step_title( $step_name );
611 +}
453 612
454 - return isset( $step_headings[ $step_name ] ) ? $step_headings[ $step_name ] : wpbc_setup_wizard__get_step_title( $step_name );
455 -}
456 -
457 613 /**
458 614 * Get setup step guidance shown in the floating setup bar.
459 615 *
460 616 * @param string $step_name Step name.
@@ -460,42 +616,103 @@
460 616 * @param string $step_name Step name.
461 617 *
462 618 * @return string
463 619 */
464 -function wpbc_setup_wizard__get_step_description( $step_name ) {
620 +function wpbc_setup_wizard__get_step_description( $step_name ) {
621 + $mode_id = wpbc_setup_wizard__get_selected_mode_id();
622 +
623 + if ( 'wizard_publish' === $step_name && 'appointment' === $mode_id ) {
624 + return __( 'Open a published Appointment page to test the Service, Provider, date, and time flow. If no page is listed, run Appointment QuickStart or publish the shortcode first.', 'booking' );
625 + }
626 +
627 + if ( 'wizard_publish' === $step_name && 'rental' === $mode_id ) {
628 + return __( 'Open a published Property booking page to test the Rental flow. If no page is listed, run Rental QuickStart or publish the booking form first.', 'booking' );
629 + }
630 +
631 + if ( 'date_availability' === $step_name && 'appointment' === $mode_id ) {
632 + return __( 'Use the Block Dates calendar to block holidays, leave, and other Provider-specific exceptions.', 'booking' );
633 + }
465 634
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 - *
635 + $step_descriptions = array(
636 + 'welcome' => __( 'Begin the guided setup. You can leave the wizard at any time and continue later from the setup bar.', 'booking' ),
637 + 'general_info' => __( 'Review the business name, contact details, and basic information used while preparing the booking configuration.', 'booking' ),
638 + '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' ),
639 + 'bookings_types' => __( 'Select whether bookings use full days, appointment time slots, or changeover-style date ranges. This choice controls the next configuration steps.', 'booking' ),
640 + 'service_provider' => __( 'QuickStart created a starter Service assigned to an existing booking resource. Review its duration, buffers, price, Booking Form, and Provider assignment.', 'booking' ),
641 + 'form_structure' => __( 'Open the form template chooser, select the template that matches your booking type, and save the Booking Form page before continuing.', 'booking' ),
642 + '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' ),
643 + 'changeover_days' => __( 'Enable and review check-in/check-out changeover days, including diagonal or vertical markings and related changeover options.', 'booking' ),
644 + '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' ),
645 + 'time_slots_availability' => __( 'Check the generated appointment slots and adjust any slot-specific availability rules before choosing the calendar appearance.', 'booking' ),
646 + 'date_availability' => __( 'Set which weekdays, dates, booking windows, and buffer rules should be available or unavailable for visitors.', 'booking' ),
647 + 'color_theme' => __( 'Choose the calendar skin and visual style so the booking form fits your site before you publish it.', 'booking' ),
648 + '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' ),
649 + 'get_started' => __( 'Finish the setup wizard. After this, the setup bar will disappear and you can start managing bookings normally.', 'booking' ),
650 + );
651 +
652 + return isset( $step_descriptions[ $step_name ] ) ? $step_descriptions[ $step_name ] : '';
653 +}
654 +
655 +/**
656 + * Get external setup step UI integration matrix.
657 + *
488 658 * Each entry describes how the floating setup bar should connect a wizard step
489 659 * to an existing WPBC admin page: what to open, what to scroll/highlight, which
490 660 * form/save control belongs to this step, and which JS events mean the external
491 661 * page has saved successfully.
492 662 *
493 - * @return array
494 - */
495 -function wpbc_setup_wizard__get_step_ui_matrix() {
496 -
497 - return array(
663 + * @return array
664 + */
665 +function wpbc_setup_wizard__get_step_ui_matrix() {
666 + $publish_step_ui = wpbc_setup_wizard__get_publish_step_ui();
667 + $time_slots_step_ui = array(
668 + 'save_behavior' => 'link_only',
669 + 'target_selector' => '.wpbc_admin_page__tab__time_slots_availability, .wpbc_ts_page',
670 + 'scroll_selector' => '.wpbc_admin_page__tab__time_slots_availability:visible, .wpbc_ts_page:visible',
671 + 'highlight_disabled' => '1',
672 + );
673 + $date_availability_step_ui = array(
674 + 'save_behavior' => 'link_only',
675 + 'target_selector' => '.wpbc_admin_page__tab__availability, .wpbc_ajx_availability_container',
676 + 'scroll_selector' => '.wpbc_ajx_availability_container:visible, .wpbc_admin_page__tab__availability:visible',
677 + 'highlight_disabled' => '1',
678 + );
679 +
680 + if ( 'rental' === wpbc_setup_wizard__get_selected_mode_id() ) {
681 + $date_availability_step_ui = array(
682 + 'save_behavior' => 'manual_save_required',
683 + 'target_selector' => '.wpbc_admin_page__tab__general_availability, [data-wpbc-ag-settings-form="1"]',
684 + 'scroll_selector' => '[data-wpbc-ag-settings-form="1"]:visible, .wpbc_admin_page__tab__general_availability:visible',
685 + 'highlight_disabled' => '1',
686 + 'form_selector' => '[data-wpbc-ag-settings-form="1"]',
687 + 'save_selector' => '[data-wpbc-ag-save="1"]',
688 + 'save_ajax_action' => 'WPBC_AJX_AVAILABILITY_GENERAL_SAVE',
689 + 'save_events' => 'wpbc:availability-general:settings-saved,wpbc:setup-wizard:step-saved',
690 + );
691 + }
692 +
693 + if ( 'appointment' === wpbc_setup_wizard__get_selected_mode_id() ) {
694 + $form_builder_url = wpbc_get_settings_url() . '&tab=builder_booking_form';
695 + $form_builder_url = add_query_arg(
696 + array(
697 + 'wpbc_bfb_panel' => 'add_fields',
698 + 'wpbc_bfb_group' => 'fields-times',
699 + 'wpbc_bfb_focus' => 'weekday_starttime',
700 + ),
701 + $form_builder_url
702 + );
703 +
704 + $time_slots_step_ui['secondary_action_url'] = wpbc_setup_wizard__add_setup_context_to_url( $form_builder_url, 'time_slots_availability' );
705 + $time_slots_step_ui['secondary_action_label'] = __( 'Adjust slot-specific availability rules', 'booking' );
706 + }
707 +
708 + return array(
709 + 'service_provider' => array(
710 + 'save_behavior' => 'link_only',
711 + 'target_selector' => '.wpbc_appointment_services_page',
712 + 'scroll_selector' => '.wpbc_appointment_services_page:visible',
713 + 'highlight_disabled' => '1',
714 + ),
498 715 'form_structure' => array(
499 716 'save_behavior' => 'manual_save_required',
500 717 'target_selector' => '.wpbc_admin_page__tab__builder_booking_form, #wpbc_form_field_free',
501 718 'scroll_selector' => '.wpbc_bfb_popup_modal__forms_loading_section:visible, #wpbc_form_field_free:visible, .wpbc_admin_page__tab__builder_booking_form:visible',
@@ -534,25 +751,10 @@
534 751 'save_ajax_action' => 'WPBC_AJX_AVAILABILITY_GENERAL_SAVE',
535 752 'save_events' => 'wpbc:availability-general:settings-saved,wpbc:setup-wizard:step-saved',
536 753 'open_action' => 'availability_section',
537 754 ),
538 - 'time_slots_availability' => array(
539 - 'save_behavior' => 'link_only',
540 - 'target_selector' => '.wpbc_admin_page__tab__time_slots_availability, .wpbc_ts_page',
541 - 'scroll_selector' => '.wpbc_admin_page__tab__time_slots_availability:visible, .wpbc_ts_page:visible',
542 - 'highlight_disabled' => '1',
543 - ),
544 - 'date_availability' => array(
545 - 'save_behavior' => 'manual_save_required',
546 - 'target_selector' => '[data-group="general-availability-weekdays"], .wpbc_admin_page__tab__general_availability, [data-wpbc-ag-settings-form="1"]',
547 - 'scroll_selector' => '[data-group="general-availability-weekdays"]:visible, [data-wpbc-ag-settings-form="1"]:visible',
548 - 'highlight_selector' => '[data-group="general-availability-weekdays"]:visible, [data-wpbc-ag-settings-form="1"]:visible',
549 - 'form_selector' => '[data-wpbc-ag-settings-form="1"]',
550 - 'save_selector' => '[data-wpbc-ag-save="1"]',
551 - 'save_ajax_action' => 'WPBC_AJX_AVAILABILITY_GENERAL_SAVE',
552 - 'save_events' => 'wpbc:availability-general:settings-saved,wpbc:setup-wizard:step-saved',
553 - 'open_action' => 'availability_section',
554 - ),
755 + 'time_slots_availability' => $time_slots_step_ui,
756 + 'date_availability' => $date_availability_step_ui,
555 757 'color_theme' => array(
556 758 'save_behavior' => 'manual_save_required',
557 759 'target_selector' => '.wpbc_admin_page__tab__themes, [data-wpbc-theme-page="1"]',
558 760 'scroll_selector' => '.wpbc_theme__inspector_settings:visible, [data-wpbc-theme-settings-form="1"]:visible, .wpbc_theme_rightbar_panels:visible',
@@ -561,15 +763,9 @@
561 763 'save_selector' => '[data-wpbc-theme-save="1"]',
562 764 'save_ajax_action' => 'WPBC_AJX_SETTINGS_THEMES_SAVE',
563 765 'save_events' => 'wpbc:setup-wizard:step-saved',
564 766 ),
565 - 'wizard_publish' => array(
566 - 'save_behavior' => 'link_only',
567 - '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',
568 - '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',
569 - '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',
570 - 'open_action' => 'publish_area',
571 - ),
767 + 'wizard_publish' => $publish_step_ui,
572 768 'get_started' => array(
573 769 'save_behavior' => 'complete',
574 770 'target_selector' => '.wpbc_admin_page',
575 771 'scroll_selector' => '.wpbc_admin_page:visible',
@@ -576,11 +772,61 @@
576 772 'highlight_disabled' => '1',
577 773 ),
578 774 );
579 775 }
580 -
581 -/**
582 - * Get one UI integration value from the external setup step matrix.
776 +
777 +/**
778 + * Determine whether Setup Wizard publishing should use the shared Resource catalog.
779 + *
780 + * The compatibility resolver remains authoritative so an older paid edition,
781 + * the temporary legacy preference, or the support rollback constant keeps the
782 + * wizard connected to the released legacy Resources renderer.
783 + *
784 + * @return bool True when the new Resource catalog is the effective renderer.
785 + */
786 +function wpbc_setup_wizard__uses_new_resources_catalog() {
787 + return function_exists( 'wpbc_booking_resources_catalog_should_use_new_renderer' )
788 + && wpbc_booking_resources_catalog_should_use_new_renderer();
789 +}
790 +
791 +/**
792 + * Get the renderer-aware Setup Wizard publishing integration.
793 + *
794 + * The new catalog is opened through its domain action event after the initial
795 + * AJAX response. The legacy selectors are intentionally retained unchanged
796 + * while the compatibility renderer remains available in Booking Calendar 11.6.
797 + *
798 + * @param bool|null $use_new_catalog Optional renderer override for deterministic tests. Null uses the effective compatibility resolver.
799 + *
800 + * @return array<string,string> Setup bar selector and action configuration.
801 + */
802 +function wpbc_setup_wizard__get_publish_step_ui( $use_new_catalog = null ) {
803 + if ( null === $use_new_catalog ) {
804 + $use_new_catalog = wpbc_setup_wizard__uses_new_resources_catalog();
805 + }
806 +
807 + if ( true === $use_new_catalog ) {
808 + return array(
809 + 'save_behavior' => 'link_only',
810 + 'target_selector' => '#wpbc_catalog_booking_resources',
811 + 'scroll_selector' => '#wpbc_catalog_booking_resources:visible',
812 + 'highlight_disabled' => '1',
813 + 'open_action' => 'catalog_publish',
814 + );
815 + }
816 +
817 + return array(
818 + 'save_behavior' => 'link_only',
819 + 'target_selector' => '.ui_group__publish_btn, .wpbc_resource_field__publish, .wpbc_resource_publish, .wpbc_publish_resources, [data-wpbc-resource-publish]',
820 + 'scroll_selector' => '.ui_group__publish_btn:visible, .wpbc_resource_field__publish:visible, .wpbc_resource_publish:visible, .wpbc_publish_resources:visible, [data-wpbc-resource-publish]:visible',
821 + 'highlight_selector' => '.ui_group__publish_btn:visible, .wpbc_resource_field__publish:visible, .wpbc_resource_publish:visible, .wpbc_publish_resources:visible, [data-wpbc-resource-publish]:visible',
822 + 'highlight_all' => '1',
823 + 'open_action' => 'publish_area',
824 + );
825 +}
826 +
827 +/**
828 + * Get one UI integration value from the external setup step matrix.
583 829 *
584 830 * @param string $step_name Step name.
585 831 * @param string $key Matrix key.
586 832 *
@@ -789,20 +1035,27 @@
789 1035 * @param string $step_name Step name.
790 1036 *
791 1037 * @return string
792 1038 */
793 -function wpbc_setup_wizard__get_step_target_url( $step_name ) {
1039 +function wpbc_setup_wizard__get_step_target_url( $step_name ) {
1040 + $target_fragment = '';
794 1041
795 - if ( wpbc_setup_wizard__is_internal_step( $step_name ) ) {
796 - return add_query_arg( 'current_step', $step_name, wpbc_get_setup_wizard_page_url() );
797 - }
798 -
799 - switch ( $step_name ) {
800 - case 'date_selection':
801 - $url = function_exists( 'wpbc_get_settings_calendar_url' )
802 - ? wpbc_get_settings_calendar_url()
803 - : wpbc_get_settings_url() . '&tab=calendar_settings';
804 - $url = add_query_arg( 'wpbc_calendar_section', 'days_selection', $url );
1042 + if ( wpbc_setup_wizard__is_internal_step( $step_name ) ) {
1043 + return add_query_arg( 'current_step', $step_name, wpbc_get_setup_wizard_page_url() );
1044 + }
1045 +
1046 + switch ( $step_name ) {
1047 + case 'service_provider':
1048 + $url = function_exists( 'wpbc_booking_modes_get_canonical_page_url' )
1049 + ? wpbc_booking_modes_get_canonical_page_url( 'wpbc-services__appointment_services' )
1050 + : admin_url( 'admin.php?page=wpbc-services&tab=appointment_services' );
1051 + break;
1052 +
1053 + case 'date_selection':
1054 + $url = function_exists( 'wpbc_get_settings_calendar_url' )
1055 + ? wpbc_get_settings_calendar_url()
1056 + : wpbc_get_settings_url() . '&tab=calendar_settings';
1057 + $url = add_query_arg( 'wpbc_calendar_section', 'days_selection', $url );
805 1058 break;
806 1059
807 1060 case 'changeover_days':
808 1061 $url = function_exists( 'wpbc_get_settings_calendar_url' )
@@ -810,28 +1063,35 @@
810 1063 : wpbc_get_settings_url() . '&tab=calendar_settings';
811 1064 $url = add_query_arg( 'wpbc_calendar_section', 'changeover_times', $url );
812 1065 break;
813 1066
814 - case 'working_time':
815 - $url = function_exists( 'wpbc_get_general_availability_url' )
816 - ? wpbc_get_general_availability_url()
817 - : admin_url( 'admin.php?page=wpbc-availability&tab=general_availability' );
818 - $url = add_query_arg( 'wpbc_ag_open', 'working_time', $url );
819 - break;
820 -
821 - case 'time_slots_availability':
822 - $url = function_exists( 'wpbc_get_time_slots_availability_url' )
823 - ? wpbc_get_time_slots_availability_url()
824 - : admin_url( 'admin.php?page=wpbc-availability&tab=time_slots_availability' );
825 - break;
826 -
827 - case 'date_availability':
828 - $url = function_exists( 'wpbc_get_general_availability_url' )
829 - ? wpbc_get_general_availability_url()
830 - : admin_url( 'admin.php?page=wpbc-availability&tab=general_availability' );
831 - $url = add_query_arg( 'wpbc_ag_open', 'weekdays', $url );
832 - break;
1067 + case 'working_time':
1068 + $url = function_exists( 'wpbc_get_general_availability_url' )
1069 + ? wpbc_get_general_availability_url()
1070 + : admin_url( 'admin.php?page=wpbc-availability&tab=general_availability' );
1071 + $url = add_query_arg( 'wpbc_ag_open', 'working_time', $url );
1072 + break;
833 1073
1074 + case 'time_slots_availability':
1075 + $url = function_exists( 'wpbc_get_time_slots_availability_url' )
1076 + ? wpbc_get_time_slots_availability_url()
1077 + : admin_url( 'admin.php?page=wpbc-availability&tab=time_slots_availability' );
1078 + break;
1079 +
1080 + case 'date_availability':
1081 + if ( 'rental' === wpbc_setup_wizard__get_selected_mode_id() ) {
1082 + $url = function_exists( 'wpbc_get_general_availability_url' )
1083 + ? wpbc_get_general_availability_url()
1084 + : admin_url( 'admin.php?page=wpbc-availability&tab=general_availability' );
1085 + break;
1086 + }
1087 +
1088 + $canonical_url = function_exists( 'wpbc_booking_modes_get_canonical_page_url' )
1089 + ? wpbc_booking_modes_get_canonical_page_url( 'wpbc-availability__availability' )
1090 + : '';
1091 + $url = ! empty( $canonical_url ) ? $canonical_url : admin_url( 'admin.php?page=wpbc-availability&tab=availability' );
1092 + break;
1093 +
834 1094 case 'form_structure':
835 1095 $url = wpbc_get_settings_url() . '&tab=builder_booking_form';
836 1096
837 1097 $template_search_key = wpbc_setup_wizard__get_bfb_template_search_key();
@@ -844,30 +1104,45 @@
844 1104 $url = function_exists( 'wpbc_get_settings_themes_url' )
845 1105 ? wpbc_get_settings_themes_url()
846 1106 : wpbc_get_settings_url() . '&tab=themes';
847 1107 break;
848 -
849 - case 'wizard_publish':
850 - $url = wpbc_get_resources_url() . '#wpbc_booking_resource_table';
851 - break;
852 -
853 - case 'get_started':
854 - $url = wpbc_get_bookings_url() . '&tab=vm_booking_listing';
855 - break;
856 -
857 - default:
1108 +
1109 + case 'wizard_publish':
1110 + $url = function_exists( 'wpbc_booking_modes_get_canonical_page_url' )
1111 + ? wpbc_booking_modes_get_canonical_page_url( 'wpbc-resources__resources' )
1112 + : '';
1113 + if ( empty( $url ) ) {
1114 + $url = wpbc_get_resources_url();
1115 + }
1116 + $url = add_query_arg( 'tab', 'resources', $url );
1117 + $target_fragment = wpbc_setup_wizard__uses_new_resources_catalog()
1118 + ? 'wpbc_catalog_booking_resources'
1119 + : 'wpbc_booking_resource_table';
1120 + break;
1121 +
1122 + case 'get_started':
1123 + $url = wpbc_get_bookings_url() . '&tab=vm_booking_listing';
1124 + break;
1125 +
1126 + default:
858 1127 $url = wpbc_get_setup_wizard_page_url();
859 1128 break;
860 - }
861 -
862 - return wpbc_setup_wizard__add_setup_context_to_url( $url, $step_name );
863 -}
864 -
865 -/**
866 - * Get URL that completes an external setup step and redirects to the next mapped step.
867 - *
868 - * @param string $step_name Step name.
869 - *
1129 + }
1130 +
1131 + $url = wpbc_setup_wizard__add_setup_context_to_url( $url, $step_name );
1132 +
1133 + if ( ! empty( $target_fragment ) ) {
1134 + $url .= '#' . $target_fragment;
1135 + }
1136 +
1137 + return $url;
1138 +}
1139 +
1140 +/**
1141 + * Get URL that completes an external setup step and redirects to the next mapped step.
1142 + *
1143 + * @param string $step_name Step name.
1144 + *
870 1145 * @return string
871 1146 */
872 1147 function wpbc_setup_wizard__get_step_continue_url( $step_name ) {
873 1148
@@ -910,8 +1185,10 @@
910 1185 'save_selector' => wpbc_setup_wizard__get_step_save_selector( $step_name ),
911 1186 'save_ajax_action' => wpbc_setup_wizard__get_step_save_ajax_action( $step_name ),
912 1187 'save_events' => wpbc_setup_wizard__get_step_save_events( $step_name ),
913 1188 'open_action' => wpbc_setup_wizard__get_step_open_action( $step_name ),
1189 + 'secondary_action_url' => wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'secondary_action_url' ),
1190 + 'secondary_action_label' => wpbc_setup_wizard__get_step_ui_matrix_value( $step_name, 'secondary_action_label' ),
914 1191 );
915 1192 }
916 1193
917 1194 /**