PluginProbe
Booking Calendar / 11.5
Booking Calendar v11.5
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-setup / setup_steps.php

setup_steps.php in Booking Calendar 11.5, at includes/page-setup/setup_steps.php

2,197 lines 75.7 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 Steps Structure for Setup Wizard Page
4 * @category Setup Class
5 * @author wpdevelop
6 *
7 * @web-site http://oplugins.com/
8 * @email info@oplugins.com
9 *
10 * @modified 2024-09-06
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
15
16 class WPBC_SETUP_WIZARD_STEPS {
17
18 private $steps_arr = array();
19
20 /**
21 * Whether setup route data has been initialized for this instance.
22 *
23 * The class is used both as a renderer and as an early setup-state helper. Some callers can reach it before the
24 * WordPress init hook, so route data must be available before any DB normalization or status checks run.
25 *
26 * @var bool
27 */
28 private $is_steps_data_initialized = false;
29
30 /**
31 * Whether the setup bar render hook has already been registered.
32 *
33 * This class is also used as a setup-state helper in AJAX and routing code, so multiple instances can exist during
34 * one request. Only one of them should render the floating setup bar.
35 *
36 * @var bool
37 */
38 private static $is_top_bar_hook_registered = false;
39
40 /**
41 * Whether the setup bar has already been printed in the current request.
42 *
43 * @var bool
44 */
45 private static $is_top_bar_rendered = false;
46
47 public function __construct() {
48
49 if ( WPBC()->is_wp_inited() || did_action( 'init' ) ) {
50 $this->init_steps_data();
51 } else {
52 add_action( 'init', array( $this, 'init_steps_data' ) );
53 }
54
55 if ( ! self::$is_top_bar_hook_registered ) {
56 add_action( 'wpbc_after_wpbc_page_top__header_tabs', array( $this, 'show_top_right_wizard_button' ), 10, 3 );
57 self::$is_top_bar_hook_registered = true;
58 }
59
60 }
61
62 /**
63 * Check whether translated strings can be loaded without triggering WordPress just-in-time translation notices.
64 *
65 * @return bool
66 */
67 private function is_i18n_ready() {
68
69 return ( WPBC()->is_wp_inited() || did_action( 'init' ) );
70 }
71
72
73 /**
74 * Define Steps Data Structure - Init
75 *
76 * @return void
77 */
78 public function init_steps_data(){
79
80 $is_i18n_ready = $this->is_i18n_ready();
81
82 $step_default_params = array(
83 'show_section_left' => false,
84 'show_section_right' => false,
85 'is_done' => false,
86 'do_action' => 'none',
87 'prior' => '',
88 'next' => '',
89 'prior_title' => $is_i18n_ready ? __( 'Go Back', 'booking' ) : 'Go Back',
90 'next_title' => $is_i18n_ready ? __( 'Save and Continue', 'booking' ) : 'Save and Continue'
91 );
92 $steps_arr = array();
93
94 if ( function_exists( 'wpbc_setup_wizard__get_intro_route' ) ) {
95 $route = wpbc_setup_wizard__get_intro_route();
96 } else {
97 $route = array( 'welcome' );
98 if ( ! wpbc_is_this_demo() ) {
99 $route[] = 'general_info';
100 }
101 $route[] = 'date_time_formats';
102 $route[] = 'bookings_types';
103 }
104 $route = array_merge( $route, wpbc_setup_wizard__get_profile_route() );
105
106 foreach ( $route as $step_index => $step_name ) {
107 $steps_arr[ $step_name ] = $step_default_params;
108 $steps_arr[ $step_name ]['do_action'] = 'save_and_continue__' . $step_name;
109 $steps_arr[ $step_name ]['prior'] = ( 0 === $step_index ) ? '' : $route[ $step_index - 1 ];
110 $steps_arr[ $step_name ]['next'] = isset( $route[ $step_index + 1 ] ) ? $route[ $step_index + 1 ] : 'welcome';
111
112 if ( $is_i18n_ready && function_exists( 'wpbc_setup_wizard__get_step_route_metadata' ) ) {
113 $steps_arr[ $step_name ] = array_merge(
114 $steps_arr[ $step_name ],
115 wpbc_setup_wizard__get_step_route_metadata( $step_name )
116 );
117 }
118 }
119
120 foreach ( array( 'service_provider', 'date_selection', 'changeover_days', 'working_time', 'time_slots_availability', 'date_availability', 'form_structure', 'color_theme', 'wizard_publish' ) as $continue_step_name ) {
121 if ( isset( $steps_arr[ $continue_step_name ] ) ) {
122 $steps_arr[ $continue_step_name ]['next_title'] = $is_i18n_ready ? __( 'Continue', 'booking' ) : 'Continue';
123 }
124 }
125
126 $this->steps_arr = $steps_arr;
127 $this->is_steps_data_initialized = true;
128 }
129
130 /**
131 * Ensure setup route data is available before this instance reads or normalizes step state.
132 *
133 * @return void
134 */
135 private function ensure_steps_data_initialized() {
136
137 if ( ! $this->is_steps_data_initialized ) {
138 $this->init_steps_data();
139 }
140 }
141
142 /**
143 * Get Steps Data Structure
144 * @return array
145 */
146 public function get_steps_arr(){
147 $this->ensure_steps_data_initialized();
148
149 return $this->steps_arr;
150 }
151
152
153 // =================================================================================================================
154 // == Steps STRUCTURE ==
155 // =================================================================================================================
156
157 /**
158 * Actual Step Number -> 'general_info' or 'date_availability'
159 *
160 * @return int
161 */
162 public function get_active_step_name() {
163
164 $steps_arr = $this->db__get_steps_is_done();
165
166 $first_step_name = '';
167 foreach ( $steps_arr as $step_name => $step ) {
168
169 $first_step_name = (empty($first_step_name)) ? $step_name : $first_step_name;
170
171 if ( empty( $step ) ) {
172 return $step_name;
173 }
174 }
175 return $first_step_name;
176 }
177
178
179 /**
180 * Actual Step Number -> 2
181 *
182 * @return int
183 */
184 public function get_active_step_num( $current_step = '' ) {
185
186 if ( ! empty( $current_step ) ) {
187 return $this->get_step_num_by_name( $current_step );
188 }
189
190 $steps_arr = $this->db__get_steps_is_done();
191 $total_steps = count( $steps_arr );
192 $completed_steps = 0;
193
194 foreach ( $steps_arr as $step ) {
195 if ( ! empty( $step ) ) {
196 $completed_steps++;
197 }
198 }
199
200 if ( $completed_steps >= $total_steps ) {
201 return $total_steps;
202 }
203
204 return min( $completed_steps + 1, $total_steps );
205 }
206
207 /**
208 * Get Step Number by step name.
209 *
210 * @param string $current_step Step name.
211 *
212 * @return int
213 */
214 public function get_step_num_by_name( $current_step ) {
215
216 $step_num = 1;
217
218 foreach ( array_keys( $this->get_steps_arr() ) as $step_name ) {
219 if ( $step_name === $current_step ) {
220 return $step_num;
221 }
222 $step_num++;
223 }
224
225 return 1;
226 }
227
228 /**
229 * Get the last wizard step saved in the setup wizard request history.
230 *
231 * @return string
232 */
233 public function get_saved_current_step_name() {
234
235 $steps_arr = $this->get_steps_arr();
236 $current_step = $this->get_active_step_name();
237
238 if ( function_exists( 'wpbc_setup_wizard_page__get_cleaned_params__saved_request_default' ) ) {
239 $saved_request_params = wpbc_setup_wizard_page__get_cleaned_params__saved_request_default();
240
241 if (
242 is_array( $saved_request_params )
243 && ( ! empty( $saved_request_params['current_step'] ) )
244 && isset( $steps_arr[ $saved_request_params['current_step'] ] )
245 ) {
246 $current_step = $saved_request_params['current_step'];
247 }
248 }
249
250 return $current_step;
251 }
252
253 /**
254 * Get target URL for a setup step.
255 *
256 * @param string $step_name Step name.
257 *
258 * @return string
259 */
260 public function get_step_target_url( $step_name ) {
261
262 $steps_arr = $this->get_steps_arr();
263
264 if ( isset( $steps_arr[ $step_name ]['target_url'] ) && ( ! empty( $steps_arr[ $step_name ]['target_url'] ) ) ) {
265 return $steps_arr[ $step_name ]['target_url'];
266 }
267
268 return function_exists( 'wpbc_setup_wizard__get_step_target_url' )
269 ? wpbc_setup_wizard__get_step_target_url( $step_name )
270 : wpbc_get_setup_wizard_page_url();
271 }
272
273 /**
274 * Get Continue URL for the floating setup bar.
275 *
276 * @param string $step_name Step name.
277 *
278 * @return string
279 */
280 public function get_step_continue_url( $step_name ) {
281
282 return function_exists( 'wpbc_setup_wizard__get_step_continue_url' )
283 ? wpbc_setup_wizard__get_step_continue_url( $step_name )
284 : $this->get_step_target_url( $step_name );
285 }
286
287 /**
288 * Get step name from setup URL context or first incomplete setup step.
289 *
290 * @return string
291 */
292 public function get_context_step_name() {
293
294 $steps_arr = $this->get_steps_arr();
295 $current_step = $this->get_saved_current_step_name();
296
297 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
298 if ( isset( $_REQUEST['wpbc_setup_step'] ) ) {
299 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
300 $request_step = sanitize_key( wp_unslash( $_REQUEST['wpbc_setup_step'] ) );
301 if ( isset( $steps_arr[ $request_step ] ) ) {
302 $current_step = $request_step;
303 $this->db__save_current_step_name( $current_step );
304 return $current_step;
305 }
306 }
307
308 if ( $this->db__is_step_completed( 'bookings_types' ) && function_exists( 'wpbc_setup_wizard__detect_step_from_admin_request' ) ) {
309 $detected_step = wpbc_setup_wizard__detect_step_from_admin_request();
310 if ( ! empty( $detected_step ) && isset( $steps_arr[ $detected_step ] ) ) {
311 $current_step = $detected_step;
312 $this->db__save_current_step_name( $current_step );
313 return $current_step;
314 }
315 }
316
317 return $current_step;
318 }
319
320 /**
321 * Save the current setup step into the per-user wizard request state.
322 *
323 * @param string $step_name Step name.
324 *
325 * @return bool
326 */
327 public function db__save_current_step_name( $step_name ) {
328
329 $steps_arr = $this->get_steps_arr();
330 if ( empty( $step_name ) || ! isset( $steps_arr[ $step_name ] ) || ! function_exists( 'wpbc_setup_wizard_page__request_rules_structure' ) ) {
331 return false;
332 }
333
334 $request_params_to_save = function_exists( 'wpbc_setup_wizard_page__get_cleaned_params__saved_request_default' )
335 ? wpbc_setup_wizard_page__get_cleaned_params__saved_request_default()
336 : array();
337
338 if ( ! is_array( $request_params_to_save ) || empty( $request_params_to_save ) ) {
339 $request_params_to_save = function_exists( 'wpbc_setup_wizard_page__get__request_values__default' )
340 ? wpbc_setup_wizard_page__get__request_values__default()
341 : array();
342 }
343
344 $request_params_to_save['current_step'] = $step_name;
345
346 $user_request = new WPBC_AJX__REQUEST( array(
347 'db_option_name' => 'booking_setup_wizard_page_request_params',
348 'user_id' => wpbc_get_current_user_id(),
349 'request_rules_structure' => wpbc_setup_wizard_page__request_rules_structure()
350 )
351 );
352
353 return (bool) $user_request->user_request_params__db_save( $request_params_to_save );
354 }
355
356 /**
357 * Get target URL for prior setup step.
358 *
359 * @param string $step_name Step name.
360 *
361 * @return string
362 */
363 public function get_step_prior_url( $step_name ) {
364
365 $steps_arr = $this->get_steps_arr();
366 $prior = isset( $steps_arr[ $step_name ]['prior'] ) ? $steps_arr[ $step_name ]['prior'] : '';
367
368 return ( empty( $prior ) ) ? '' : $this->get_step_target_url( $prior );
369 }
370
371 /**
372 * Get step title for setup bar.
373 *
374 * @param string $step_name Step name.
375 *
376 * @return string
377 */
378 public function get_step_title( $step_name ) {
379
380 $steps_arr = $this->get_steps_arr();
381
382 if ( isset( $steps_arr[ $step_name ]['title'] ) ) {
383 return $steps_arr[ $step_name ]['title'];
384 }
385
386 return function_exists( 'wpbc_setup_wizard__get_step_title' )
387 ? wpbc_setup_wizard__get_step_title( $step_name )
388 : $step_name;
389 }
390
391 /**
392 * Get action-oriented setup step heading.
393 *
394 * @param string $step_name Step name.
395 *
396 * @return string
397 */
398 public function get_step_heading( $step_name ) {
399
400 $steps_arr = $this->get_steps_arr();
401
402 if ( isset( $steps_arr[ $step_name ]['heading'] ) ) {
403 return $steps_arr[ $step_name ]['heading'];
404 }
405
406 return function_exists( 'wpbc_setup_wizard__get_step_heading' )
407 ? wpbc_setup_wizard__get_step_heading( $step_name )
408 : $this->get_step_title( $step_name );
409 }
410
411 /**
412 * Get setup step description.
413 *
414 * @param string $step_name Step name.
415 *
416 * @return string
417 */
418 public function get_step_description( $step_name ) {
419
420 $steps_arr = $this->get_steps_arr();
421
422 if ( isset( $steps_arr[ $step_name ]['description'] ) ) {
423 return $steps_arr[ $step_name ]['description'];
424 }
425
426 return function_exists( 'wpbc_setup_wizard__get_step_description' )
427 ? wpbc_setup_wizard__get_step_description( $step_name )
428 : '';
429 }
430
431 /**
432 * Get setup step save behavior.
433 *
434 * @param string $step_name Step name.
435 *
436 * @return string
437 */
438 public function get_step_save_behavior( $step_name ) {
439
440 $steps_arr = $this->get_steps_arr();
441
442 if ( isset( $steps_arr[ $step_name ]['save_behavior'] ) ) {
443 return $steps_arr[ $step_name ]['save_behavior'];
444 }
445
446 return function_exists( 'wpbc_setup_wizard__get_step_save_behavior' )
447 ? wpbc_setup_wizard__get_step_save_behavior( $step_name )
448 : 'link_only';
449 }
450
451 /**
452 * Get route metadata value.
453 *
454 * @param string $step_name Step name.
455 * @param string $key Metadata key.
456 *
457 * @return string
458 */
459 public function get_step_meta_value( $step_name, $key ) {
460
461 $steps_arr = $this->get_steps_arr();
462
463 return ( isset( $steps_arr[ $step_name ][ $key ] ) ) ? (string) $steps_arr[ $step_name ][ $key ] : '';
464 }
465
466
467 /**
468 * Get Steps Count -> 9
469 *
470 * @return int
471 */
472 public function get_total_steps_count(){
473
474 $steps_arr = $this->db__get_steps_is_done();
475
476 return count($steps_arr);
477 }
478
479
480 /**
481 * Get % Progress for Setup Steps -> 30
482 * @return int
483 */
484 public function get_progess_value( $current_step = '' ) {
485
486 $total_steps = $this->get_total_steps_count();
487 if ( $total_steps <= 0 ) {
488 return 0;
489 }
490
491 $progess_value = ( $this->get_active_step_num( $current_step ) * 100 ) / $total_steps;
492 $progess_value = intval( $progess_value );
493
494 return $progess_value;
495 }
496
497
498 // =================================================================================================================
499 // == DB :: "Set Wizard Steps as Done" ==
500 // =================================================================================================================
501
502 /**
503 * Get all Steps from DB and from Structure,
504 *
505 * If not saved yet to DB, then get default structure
506 *
507 * And if later Wizard structure ->init_steps_data() was extended, then system get such steps as uncompleted.
508 *
509 * @return array|mixed
510 */
511 public function db__get_steps_is_done() {
512
513 $steps_is_done = get_bk_option( 'booking_setup_wizard_page_steps_is_done' );
514 $is_completed = ( 'On' === get_bk_option( 'booking_setup_wizard_page_is_completed' ) );
515
516 $active_steps_names = array_keys( $this->get_steps_arr() );
517 $normalized_steps = array();
518
519 if ( empty( $active_steps_names ) ) {
520 return is_array( $steps_is_done ) ? $steps_is_done : array();
521 }
522
523 foreach ( $active_steps_names as $step_name ) {
524 $normalized_steps[ $step_name ] = $is_completed ? true : ( ( is_array( $steps_is_done ) && isset( $steps_is_done[ $step_name ] ) ) ? (bool) $steps_is_done[ $step_name ] : false );
525 }
526
527 if ( $steps_is_done !== $normalized_steps ) {
528 $this->db__save_steps_is_done( $normalized_steps );
529 }
530
531 return $normalized_steps;
532 }
533
534
535 /**
536 * Save statuses to all steps
537 *
538 * @param $steps_arr
539 *
540 * @return void
541 */
542 public function db__save_steps_is_done( $steps_arr ) {
543 update_bk_option( 'booking_setup_wizard_page_steps_is_done', $steps_arr );
544 }
545
546 /**
547 * Set specific step as Completed
548 *
549 * @param $step_name
550 *
551 * @return void
552 */
553 public function db__set_step_as_completed( $step_name ) {
554
555 $steps_arr = $this->db__get_steps_is_done();
556
557 $steps_arr[ $step_name ] = true;
558
559 $this->db__save_steps_is_done( $steps_arr );
560 $this->db__set_step_as_saved( $step_name, true );
561
562 if ( ! in_array( false, $steps_arr, true ) ) {
563 update_bk_option( 'booking_setup_wizard_page_is_completed', 'On' );
564 }
565 }
566
567 /**
568 * Set specific step as Uncompleted
569 *
570 * @param $step_name
571 *
572 * @return void
573 */
574 public function db__set_step_as_uncompleted( $step_name ) {
575
576 $steps_arr = $this->db__get_steps_is_done();
577
578 $steps_arr[ $step_name ] = false;
579
580 delete_bk_option( 'booking_setup_wizard_page_is_completed' );
581
582 $this->db__save_steps_is_done( $steps_arr );
583 }
584
585 /**
586 * Reset a step and all following steps in the active route.
587 *
588 * Older wizard versions could leave later steps marked as completed, which made the continue handler think setup
589 * was finished too early after Step 5.
590 *
591 * @param string $first_step_name First step to reset.
592 *
593 * @return bool
594 */
595 public function db__reset_steps_from( $first_step_name ) {
596
597 $steps_is_done = $this->db__get_steps_is_done();
598 $steps_is_saved = $this->db__get_steps_is_saved();
599 $should_reset = false;
600
601 if ( ! array_key_exists( $first_step_name, $steps_is_done ) ) {
602 return false;
603 }
604
605 foreach ( array_keys( $steps_is_done ) as $step_name ) {
606 if ( $first_step_name === $step_name ) {
607 $should_reset = true;
608 }
609
610 if ( $should_reset ) {
611 $steps_is_done[ $step_name ] = false;
612 if ( array_key_exists( $step_name, $steps_is_saved ) ) {
613 $steps_is_saved[ $step_name ] = false;
614 }
615 }
616 }
617
618 delete_bk_option( 'booking_setup_wizard_page_is_completed' );
619 $this->db__save_steps_is_done( $steps_is_done );
620 $this->db__save_steps_is_saved( $steps_is_saved );
621
622 return true;
623 }
624
625 /**
626 * Check if specific step 'Is completed' ?
627 *
628 * @param string $step_name
629 *
630 * @return bool
631 */
632 public function db__is_step_completed( $step_name ) {
633
634 $steps_arr = $this->db__get_steps_is_done();
635
636 if ( empty( $steps_arr[ $step_name ] ) ) {
637 return false;
638 } else {
639 return true;
640 }
641 }
642
643
644 /**
645 * Mark All Steps as Completed or Uncompleted
646 *
647 * @param $is_completed bool (default true)
648 *
649 * @return void
650 */
651 public function db__set_all_steps_as( $is_completed = true ) {
652
653 if ( false === $is_completed ) {
654 delete_bk_option( 'booking_setup_wizard_page_steps_is_done' );
655 delete_bk_option( 'booking_setup_wizard_page_is_completed' );
656 } else {
657 update_bk_option( 'booking_setup_wizard_page_is_completed', 'On' );
658 }
659
660 $steps_names = $this->db__get_steps_is_done();
661
662 $steps_names = array_keys( $steps_names );
663 $steps_values = array_fill( 0, count( $steps_names ), $is_completed );
664 $steps_is_done = array_combine( $steps_names, $steps_values );
665
666 // Set all steps as not completed
667 $this->db__save_steps_is_done( $steps_is_done );
668 $this->db__save_steps_is_saved( $steps_is_done );
669 }
670
671 /**
672 * Get saved state for setup steps.
673 *
674 * @return array
675 */
676 public function db__get_steps_is_saved() {
677
678 $steps_is_saved = get_bk_option( 'booking_setup_wizard_page_steps_is_saved' );
679 $is_completed = ( 'On' === get_bk_option( 'booking_setup_wizard_page_is_completed' ) );
680 $normalized = array();
681
682 foreach ( array_keys( $this->get_steps_arr() ) as $step_name ) {
683 $normalized[ $step_name ] = $is_completed ? true : ( ( is_array( $steps_is_saved ) && isset( $steps_is_saved[ $step_name ] ) ) ? (bool) $steps_is_saved[ $step_name ] : false );
684 }
685
686 if ( $steps_is_saved !== $normalized ) {
687 $this->db__save_steps_is_saved( $normalized );
688 }
689
690 return $normalized;
691 }
692
693 /**
694 * Save setup step saved states.
695 *
696 * @param array $steps_arr Saved states.
697 *
698 * @return void
699 */
700 public function db__save_steps_is_saved( $steps_arr ) {
701 update_bk_option( 'booking_setup_wizard_page_steps_is_saved', $steps_arr );
702 }
703
704 /**
705 * Mark a setup step as saved or unsaved.
706 *
707 * @param string $step_name Step name.
708 * @param bool $is_saved Saved flag.
709 *
710 * @return bool
711 */
712 public function db__set_step_as_saved( $step_name, $is_saved = true ) {
713
714 $steps_arr = $this->db__get_steps_is_saved();
715 if ( ! array_key_exists( $step_name, $steps_arr ) ) {
716 return false;
717 }
718
719 $steps_arr[ $step_name ] = (bool) $is_saved;
720 $this->db__save_steps_is_saved( $steps_arr );
721
722 return true;
723 }
724
725 /**
726 * Check whether a setup step has been saved.
727 *
728 * @param string $step_name Step name.
729 *
730 * @return bool
731 */
732 public function db__is_step_saved( $step_name ) {
733
734 if ( 'manual_save_required' !== $this->get_step_save_behavior( $step_name ) ) {
735 return true;
736 }
737
738 $steps_arr = $this->db__get_steps_is_saved();
739
740 return ! empty( $steps_arr[ $step_name ] );
741 }
742
743 /**
744 * Check Is all steps Completed
745 * @return bool
746 */
747 public function db__is_all_steps_completed() {
748
749 if ( 'On' === get_bk_option( 'booking_setup_wizard_page_is_completed' ) ) {
750 return true;
751 }
752
753 $steps_arr = $this->db__get_steps_is_done();
754
755 if ( empty( $steps_arr ) ) {
756 return false;
757 }
758
759 foreach ( $steps_arr as $step_name => $steps_val ) {
760 if ( empty( $steps_val ) ) {
761 return false;
762 }
763 }
764
765 return true;
766 }
767
768
769
770 // =================================================================================================================
771 // == C O N T E N T ==
772 // =================================================================================================================
773
774 // ----------------------------------------------------------
775 // == Left Plugin Menu --> "Setup" with Progress Bar ==
776 // ----------------------------------------------------------
777
778 /**
779 * Main Left Menu Title - "Setup" with Progress Bar
780 *
781 * @return false|string
782 */
783 public function get_plugin_menu_title__setup_progress( $current_step = '' ){
784
785
786 $current_step_for_progress = ( ! empty( $current_step ) ) ? $current_step : $this->get_context_step_name();
787
788 ob_start();
789
790 ?><div class="setup_wizard_page_container" style="display: flex;flex-flow: row wrap;justify-content: flex-start;align-items: center;color: #fff;margin: 0 -5px 0 0;overflow: visible;">
791 <div class="name_item" style="margin-top: 0;white-space: nowrap;padding: 0 0 0 0;"><?php esc_html_e( 'Setup', 'booking' ); ?></div>
792 <div style="margin:3px 0px 0 0;margin-left: auto;font-size: 9px;background: var(--wpbc_admin-theme-color, #2271b1);height: 15px;" class="wpbc_badge_count name_item update-plugins">
793 <span class="update-count" style="white-space: nowrap;word-wrap: normal;"><?php
794 echo esc_html( $this->get_active_step_num( $current_step_for_progress ) . ' / ' . $this->get_total_steps_count() );
795 ?></span>
796 </div>
797 <div class="progress_line_container" style="width: 100%;border: 0px solid #757575;height: 3px;border-radius: 6px;margin: 7px 0 -3px -3px;overflow: hidden;background: #555;">
798 <div class="progress_line" style="font-size: 6px;font-weight: 600;word-wrap: normal;border-radius: 6px;white-space: nowrap;background: #8ECE01;width: <?php
799 echo esc_html( $this->get_progess_value( $current_step_for_progress ) ); ?>%;height: 3px;"></div>
800 </div>
801 </div><?php
802
803 return ob_get_clean();
804 }
805
806 // ----------------------------------------------------------
807 // == Content Top Wizard Button ==
808 // ----------------------------------------------------------
809
810 /**
811 * Black Button at Top Right Side in WPBC plugin menu ( except Wizard page )
812 *
813 * Show Continue Setup Wizard Button
814 * @return void
815 */
816 public function show_top_right_wizard_button() {
817
818 if ( ! wpbc_is_setup_wizard_page() ){
819
820 if (
821 ( ! wpbc_is_user_can_access_wizard_page() ) ||
822 ( $this->db__is_all_steps_completed() )
823 ){
824 return false;
825 }
826
827 if ( self::$is_top_bar_rendered ) {
828 return false;
829 }
830 self::$is_top_bar_rendered = true;
831
832 $current_step = $this->get_context_step_name();
833 $is_external_setup_flow_started = $this->db__is_step_completed( 'bookings_types' );
834 $detected_page_step = ( $is_external_setup_flow_started && function_exists( 'wpbc_setup_wizard__detect_step_from_admin_request' ) )
835 ? wpbc_setup_wizard__detect_step_from_admin_request()
836 : '';
837 $continue_url = $this->get_step_continue_url( $current_step );
838 if ( ! empty( $detected_page_step ) && isset( $this->steps_arr[ $detected_page_step ] ) ) {
839 $continue_url = add_query_arg( 'wpbc_setup_from_page_step', $detected_page_step, $continue_url );
840 }
841 $prior_url = $this->get_step_prior_url( $current_step );
842 $step_title = $this->get_step_title( $current_step );
843 $step_heading = $this->get_step_heading( $current_step );
844 $step_save_page_title = ( 'form_structure' === $current_step ) ? __( 'Form Builder', 'booking' ) : $step_title;
845 $description = $this->get_step_description( $current_step );
846 $save_behavior = $this->get_step_save_behavior( $current_step );
847 $target_selector = $this->get_step_meta_value( $current_step, 'target_selector' );
848 $scroll_selector = $this->get_step_meta_value( $current_step, 'scroll_selector' );
849 $highlight_selector = $this->get_step_meta_value( $current_step, 'highlight_selector' );
850 $highlight_disabled = $this->get_step_meta_value( $current_step, 'highlight_disabled' );
851 $highlight_all = $this->get_step_meta_value( $current_step, 'highlight_all' );
852 $form_selector = $this->get_step_meta_value( $current_step, 'form_selector' );
853 $save_selector = $this->get_step_meta_value( $current_step, 'save_selector' );
854 $save_ajax_action = $this->get_step_meta_value( $current_step, 'save_ajax_action' );
855 $save_events = $this->get_step_meta_value( $current_step, 'save_events' );
856 $open_action = $this->get_step_meta_value( $current_step, 'open_action' );
857 $secondary_action_url = $this->get_step_meta_value( $current_step, 'secondary_action_url' );
858 $secondary_action_label = $this->get_step_meta_value( $current_step, 'secondary_action_label' );
859 $can_save_from_bar = ( 'manual_save_required' === $save_behavior && ! empty( $save_selector ) );
860 $continue_title = ( 'complete' === $save_behavior ) ? __( 'Finish Setup', 'booking' ) : __( 'Continue', 'booking' );
861 if ( $can_save_from_bar ) {
862 $continue_title = __( 'Save and Continue', 'booking' );
863 }
864 $is_step_saved = $this->db__is_step_saved( $current_step );
865 $is_step_unsaved = ( 'manual_save_required' === $save_behavior && ! $is_step_saved );
866 $is_continue_disabled = ( $is_step_unsaved && ! $can_save_from_bar );
867 $continue_href = $is_step_unsaved ? '#wpbc_setup_save_required' : $continue_url;
868 $mark_saved_nonce = wp_create_nonce( 'wpbc_setup_wizard_mark_step_saved' );
869 $step_target_url = $this->get_step_target_url( $current_step );
870 $skip_wizard_url = add_query_arg( 'wpbc_setup_wizard', 'completed', wpbc_get_bookings_url() );
871 $reset_wizard_url = add_query_arg( 'wpbc_setup_wizard', 'reset', wpbc_get_setup_wizard_page_url() );
872 $save_required_note = sprintf(
873 /* translators: %s: setup target page title. */
874 __( 'Save changes on the %s page before continuing.', 'booking' ),
875 '<a href="' . esc_url( $step_target_url ) . '">' . esc_html( $step_save_page_title ) . '</a>'
876 );
877 $test_page_links = (
878 'wizard_publish' === $current_step
879 && function_exists( 'wpbc_booking_modes_get_setup_test_page_links' )
880 ) ? wpbc_booking_modes_get_setup_test_page_links() : array();
881
882 // FixIn: 10.12.1.1.
883 ?><style type="text/css">
884 @media screen and (max-width: 782px) {
885 .ui_element.wpbc_page_top__wizard_button {
886 /*top: 49px !important;*/
887 }
888 }
889 .wp-admin.wpbc_admin_full_screen .wpbc_header_news {
890 display: none !important;
891 }
892 .wpbc_page_top__wizard_button {
893 width: auto;
894 min-width: 330px;
895 max-width: min(420px, calc(100vw - 30px));
896 position: fixed;
897 z-index: 150000;
898 box-shadow: 0 0 10px #c1c1c1;
899 border-radius: 9px;
900 background: transparent;
901 right: 15px;
902 top: auto !important;
903 bottom: 15px !important;
904 }
905 .wpbc_page_top__wizard_button.wpbc_setup_wizard_bar_is_moved {
906 left: var(--wpbc-setup-bar-left, auto) !important;
907 top: auto !important;
908 right: auto !important;
909 bottom: var(--wpbc-setup-bar-bottom, auto) !important;
910 }
911 .wpbc_page_top__wizard_button.wpbc_setup_wizard_bar_auto_shifted {
912 left: auto !important;
913 top: auto !important;
914 right: var(--wpbc-setup-bar-auto-right, 15px) !important;
915 bottom: 15px !important;
916 }
917 .wpbc_page_top__wizard_button.wpbc_setup_wizard_bar_auto_top {
918 left: auto !important;
919 top: var(--wpbc-setup-bar-auto-top, 15px) !important;
920 right: var(--wpbc-setup-bar-auto-right, 15px) !important;
921 bottom: auto !important;
922 }
923 .wpbc_page_top__wizard_button.wpbc_setup_wizard_bar_is_dragging {
924 user-select: none;
925 }
926 .wpbc_page_top__wizard_button.wpbc_setup_wizard_bar_collapsed {
927 min-width: 260px;
928 }
929 .wpbc_page_top__wizard_button.wpbc_setup_wizard_bar_collapsed .wpbc_setup_wizard_bar_expandable {
930 display: none !important;
931 }
932 div .wpbc_admin_page__tab__builder_booking_form .wpbc_page_top__wizard_button {
933 top: calc(var(--wpbc_ui_top_nav__wp_top_menu_height) + var(--wpbc_ui_top_nav__height) + 10px) !important;
934 top: auto !important;
935 }
936 .ui_element.wpbc_page_top__wizard_button .wpbc_page_top__wizard_button_content,
937 .ui_element.wpbc_page_top__wizard_button .wpbc_page_top__wizard_button_content:hover {
938 border-radius: 5px;
939 border: none;
940 background: #535353; /* #6c9e00 #0b9300;*/
941 box-shadow: 0 0 10px #dbdbdb;
942 text-shadow: none;
943 color: #fff;
944 font-weight: 600;
945 padding: 8px 10px 8px 15px;
946 display: flex;
947 flex-flow: column nowrap;
948 justify-content: flex-start;
949 align-items: stretch;
950 gap: 8px;
951 }
952 .wpbc_setup_wizard_bar_title_row {
953 display: flex;
954 flex-flow: row nowrap;
955 justify-content: flex-start;
956 align-items: center;
957 gap: 8px;
958 width: 100%;
959 border-bottom: 2px solid #686868;
960 padding-bottom: 8px;
961 margin-bottom: 10px;
962 }
963 .wpbc_setup_wizard_bar_title {
964 flex: 1 1 auto;
965 min-width: 0;
966 white-space: nowrap;
967 overflow: hidden;
968 text-overflow: ellipsis;
969 margin-top: 0;
970 padding: 0;
971 }
972 .wpbc_setup_wizard_bar_header_actions {
973 display: flex;
974 flex: 0 0 auto;
975 flex-flow: row nowrap;
976 align-items: center;
977 gap: 2px;
978 margin-left: auto;
979 }
980 .wpbc_setup_wizard_bar_icon_button {
981 display: inline-flex;
982 align-items: center;
983 justify-content: center;
984 width: 24px;
985 height: 24px;
986 min-width: 24px;
987 min-height: 24px;
988 border: 0;
989 border-radius: 4px;
990 background: transparent;
991 color: #fff;
992 cursor: pointer;
993 padding: 0;
994 margin: 0;
995 }
996 .wpbc_setup_wizard_bar_icon_button:hover,
997 .wpbc_setup_wizard_bar_icon_button:focus {
998 background: rgba(255,255,255,0.16);
999 color: #fff;
1000 outline: none;
1001 box-shadow: none;
1002 }
1003 .wpbc_setup_wizard_bar_drag_handle {
1004 cursor: move;
1005 }
1006 .wpbc_page_top__wizard_button_actions {
1007 display: flex;
1008 flex-flow: row nowrap;
1009 justify-content: flex-end;
1010 align-items: center;
1011 gap: 8px;
1012 }
1013 .wpbc_page_top__wizard_button_actions .button {
1014 font-size: 11px;
1015 min-height: 10px;
1016 line-height: 1.8;
1017 margin: 0;
1018 }
1019 .wpbc_page_top__wizard_button_actions .button.button-secondary {
1020 background-color: #e4e4e4;
1021 }
1022 .wpbc_setup_wizard_test_page_actions {
1023 display: flex;
1024 flex-flow: row wrap;
1025 align-items: center;
1026 gap: 8px;
1027 font-size: 11px;
1028 font-weight: 400;
1029 line-height: 1.35;
1030 }
1031 .wpbc_page_top__wizard_button[data-wpbc-setup-step="wizard_publish"] .wpbc_page_top__wizard_button_actions {
1032 flex-flow: row wrap;
1033 }
1034 .wpbc_page_top__wizard_button_actions .button.wpbc_setup_wizard_test_page_button,
1035 .wpbc_page_top__wizard_button_actions .button.wpbc_setup_wizard_test_page_button:hover,
1036 .wpbc_page_top__wizard_button_actions .button.wpbc_setup_wizard_test_page_button:focus {
1037 margin: 20px 0;
1038 background: #71a501;
1039 border-color: #71a501;
1040 color: #f0ffce;
1041 }
1042 .wpbc_page_top__wizard_button_actions .button.wpbc_setup_wizard_test_page_button:first-child {
1043 margin-right: auto;
1044 margin-left: 0;
1045 }
1046 .wpbc_page_top__wizard_button[data-wpbc-setup-step="wizard_publish"] .wpbc_page_top__wizard_button_actions.wpbc_page_top__wizard_button_links {
1047 margin: 0;
1048 gap: 10px 15px;
1049 justify-content: flex-start;
1050 }
1051 .wpbc_page_top__wizard_button_actions.wpbc_page_top__wizard_button_links .button.wpbc_setup_wizard_test_page_button:first-child,
1052 .wpbc_page_top__wizard_button[data-wpbc-setup-step="wizard_publish"] .wpbc_page_top__wizard_button_actions.wpbc_page_top__wizard_button_links a {
1053 margin: 0;
1054 flex: 0 1 auto;
1055 }
1056 .wpbc_page_top__wizard_button_actions .button.disabled,
1057 .wpbc_page_top__wizard_button_actions .button[aria-disabled="true"] {
1058 cursor: not-allowed;
1059 opacity: 0.55;
1060 pointer-events: auto;
1061 }
1062 .wpbc_page_top__wizard_button_links {
1063 display: flex;
1064 flex-flow: row wrap;
1065 justify-content: flex-start;
1066 align-items: center;
1067 gap: 1.5em;
1068 font-size: 10px;
1069 font-weight: 400;
1070 line-height: 1.4;
1071 margin-top: -2px;
1072 }
1073 .wpbc_page_top__wizard_button_links a {
1074 color: #e6e6e6;
1075 text-decoration: underline;
1076 text-underline-offset: 2px;
1077 }
1078 .wpbc_page_top__wizard_button_links a:hover,
1079 .wpbc_page_top__wizard_button_links a:focus {
1080 color: #fff;
1081 }
1082 .wpbc_page_top__wizard_button_links a.wpbc_setup_wizard_bar_danger_link {
1083 /*color: #ff9b00;*/
1084 }
1085 .wpbc_page_top__wizard_button_links a.wpbc_setup_wizard_bar_danger_link:hover,
1086 .wpbc_page_top__wizard_button_links a.wpbc_setup_wizard_bar_danger_link:focus {
1087 color: #fff;
1088 }
1089 .wpbc_page_top__wizard_button_note {
1090 font-size: 12px;
1091 font-weight: 400;
1092 line-height: 1.35;
1093 color: #fff;
1094 background: rgb(160, 160, 95);
1095 background: rgb(160, 132, 95);
1096 background: rgb(160, 116, 95);
1097 border-radius: 4px;
1098 padding: 10px 14px;
1099 margin: 8px 0 5px;
1100 }
1101 .wpbc_page_top__wizard_button_note a {
1102 color: #fff;
1103 text-decoration: underline;
1104 text-underline-offset: 2px;
1105 }
1106 .wpbc_page_top__wizard_button_note.wpbc_setup_wizard_bar_note_saved {
1107 background: #4f8f16;
1108 }
1109 .wpbc_setup_wizard_attention_pulse {
1110 animation: wpbc_setup_wizard_attention_pulse 0.62s ease-in-out 3;
1111 }
1112 @keyframes wpbc_setup_wizard_attention_pulse {
1113 0% {
1114 box-shadow: 0 0 0 0 rgba(255, 196, 0, 0.82);
1115 transform: scale(1);
1116 }
1117 50% {
1118 box-shadow: 0 0 0 7px rgba(255, 196, 0, 0.2);
1119 transform: scale(1.025);
1120 }
1121 100% {
1122 box-shadow: 0 0 0 0 rgba(255, 196, 0, 0);
1123 transform: scale(1);
1124 }
1125 }
1126 .wpbc_setup_wizard__target_highlight {
1127 outline: 2px solid #8ECE01 !important;
1128 outline-offset: 3px !important;
1129 box-shadow: 0 0 0 5px rgba(142, 206, 1, 0.16) !important;
1130 transition: outline-color 0.2s ease, box-shadow 0.2s ease;
1131 }
1132 @media screen and (max-width: 782px) {
1133 .wpbc_page_top__wizard_button {
1134 left: 10px !important;
1135 right: 10px !important;
1136 bottom: 10px !important;
1137 top: auto !important;
1138 min-width: 0;
1139 max-width: none;
1140 }
1141 .wpbc_setup_wizard_bar_drag_handle,
1142 .wpbc_setup_wizard_bar_reset_button {
1143 display: none;
1144 }
1145 }
1146 </style>
1147 <div style="top: 35px;font-size: 15px;"
1148 class="ui_element wpbc_page_top__wizard_button"
1149 data-wpbc-setup-step="<?php echo esc_attr( $current_step ); ?>"
1150 data-wpbc-setup-save-behavior="<?php echo esc_attr( $save_behavior ); ?>"
1151 data-wpbc-setup-is-saved="<?php echo esc_attr( $is_step_saved ? '1' : '0' ); ?>"
1152 data-wpbc-setup-ajax-url="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>"
1153 data-wpbc-setup-mark-saved-nonce="<?php echo esc_attr( $mark_saved_nonce ); ?>"
1154 data-wpbc-setup-target-selector="<?php echo esc_attr( $target_selector ); ?>"
1155 data-wpbc-setup-scroll-selector="<?php echo esc_attr( $scroll_selector ); ?>"
1156 data-wpbc-setup-highlight-selector="<?php echo esc_attr( $highlight_selector ); ?>"
1157 data-wpbc-setup-highlight-disabled="<?php echo esc_attr( $highlight_disabled ); ?>"
1158 data-wpbc-setup-highlight-all="<?php echo esc_attr( $highlight_all ); ?>"
1159 data-wpbc-setup-form-selector="<?php echo esc_attr( $form_selector ); ?>"
1160 data-wpbc-setup-save-selector="<?php echo esc_attr( $save_selector ); ?>"
1161 data-wpbc-setup-save-ajax-action="<?php echo esc_attr( $save_ajax_action ); ?>"
1162 data-wpbc-setup-save-events="<?php echo esc_attr( $save_events ); ?>"
1163 data-wpbc-setup-open-action="<?php echo esc_attr( $open_action ); ?>">
1164 <div class="wpbc_ui_control wpbc_page_top__wizard_button_content">
1165 <div class="in-button-text"
1166 style="width: 100%;margin: 0;display: flex;flex-flow: column nowrap;justify-content: flex-start;align-items: stretch;gap:8px;">
1167 <div class="setup_wizard_page_container"
1168 style="display: flex;flex-flow: row wrap;justify-content: flex-start;align-items: center;color: #fff;overflow: visible;flex: 1 1 auto;">
1169 <div class="wpbc_setup_wizard_bar_title_row">
1170 <div class="wpbc_setup_wizard_bar_header_actions">
1171 <button type="button"
1172 style="margin: -1px 5px 0 -7px;"
1173 class="wpbc_setup_wizard_bar_icon_button wpbc_setup_wizard_bar_drag_handle"
1174 title="<?php esc_attr_e( 'Move setup bar', 'booking' ); ?>"
1175 aria-label="<?php esc_attr_e( 'Move setup bar', 'booking' ); ?>">
1176 <i class="menu_icon icon-1x wpbc_icn_drag_indicator"></i>
1177 </button>
1178 </div>
1179
1180 <div class="name_item wpbc_setup_wizard_bar_title">
1181 <i style="margin-right: 4px;" class="menu_icon icon-1x wpbc_icn_donut_large wpbc_icn_adjust0"></i> <?php echo esc_html( $step_title ); ?>
1182 </div>
1183 <div class="wpbc_setup_wizard_bar_header_actions">
1184 <button type="button"
1185 class="wpbc_setup_wizard_bar_icon_button wpbc_setup_wizard_bar_reset_button"
1186 title="<?php esc_attr_e( 'Reset setup bar position', 'booking' ); ?>"
1187 aria-label="<?php esc_attr_e( 'Reset setup bar position', 'booking' ); ?>">
1188 <i class="menu_icon icon-1x wpbc_icn_refresh"></i>
1189 </button>
1190 <button type="button"
1191 class="wpbc_setup_wizard_bar_icon_button wpbc_setup_wizard_bar_toggle_button"
1192 title="<?php esc_attr_e( 'Collapse setup bar', 'booking' ); ?>"
1193 aria-label="<?php esc_attr_e( 'Collapse setup bar', 'booking' ); ?>"
1194 aria-expanded="true">
1195 <i class="menu_icon icon-1x wpbc_icn_expand_less"></i>
1196 </button>
1197 </div>
1198 </div>
1199 <div class="name_item wpbc_setup_wizard_bar_expandable" style="flex:1 1 100%;font-size:13px;font-weight:600;line-height:1.35;margin:3px 0 0;color:#f1f1f1;">
1200 <?php echo esc_html( $step_heading ); ?>
1201 </div>
1202 <?php if ( ! empty( $description ) ) { ?>
1203 <div class="name_item wpbc_setup_wizard_bar_expandable" style="flex:1 1 100%;font-size:11px;font-weight:400;line-height:1.35;margin:2px 0 0;color:#e6e6e6;">
1204 <?php echo esc_html( $description ); ?>
1205 </div>
1206 <?php } ?>
1207 <div
1208 style="margin:2px 0px 0 9px;font-size: 9px;background: #3e3e3e;height: auto;border-radius: 5px;padding: 0px 7px 0px;margin-left: auto;"
1209 class="wpbc_badge_count name_item update-plugins">
1210 <span class="update-count"
1211 style="white-space: nowrap;word-wrap: normal;"><?php echo esc_html( $this->get_active_step_num( $current_step ) . ' / ' . $this->get_total_steps_count() ); ?></span>
1212 </div>
1213
1214 <div class="progress_line_container"
1215 style="width: 100%;border: 0px solid #757575;height: 3px;border-radius: 6px;margin: 7px 0 0 0;overflow: hidden;background: #202020;">
1216 <div class="progress_line"
1217 style="font-size: 6px;font-weight: 600;border-radius: 6px;word-wrap: normal;white-space: nowrap;background: #8ECE01;width: <?php echo esc_attr( $this->get_progess_value( $current_step ) ); ?>%;height: 3px;"></div>
1218 </div>
1219 </div>
1220 <?php if ( 'manual_save_required' === $save_behavior ) { ?>
1221 <div class="wpbc_page_top__wizard_button_note wpbc_setup_wizard_bar_expandable<?php echo $is_step_saved ? ' wpbc_setup_wizard_bar_note_saved' : ''; ?>">
1222 <?php
1223 if ( $is_step_saved ) {
1224 esc_html_e( 'Changes saved. You can continue.', 'booking' );
1225 } else {
1226 echo wp_kses_post( $save_required_note );
1227 }
1228 ?>
1229 </div>
1230 <?php } ?>
1231 <?php if ( 'wizard_publish' === $current_step && empty( $test_page_links ) ) { ?>
1232 <div class="wpbc_setup_wizard_test_page_actions wpbc_setup_wizard_bar_expandable">
1233 <span><?php esc_html_e( 'No published booking page was found yet. Use QuickStart or the page publishing controls, then return to this step.', 'booking' ); ?></span>
1234 </div>
1235 <?php } ?>
1236 <?php if ( 'wizard_publish' === $current_step && ! empty( $test_page_links ) ) { ?>
1237 <div class="wpbc_page_top__wizard_button_actions wpbc_setup_wizard_bar_expandable wpbc_page_top__wizard_button_links">
1238 <?php foreach ( $test_page_links as $test_page_link ) {
1239 if ( empty( $test_page_link['url'] ) || empty( $test_page_link['label'] ) ) {
1240 continue;
1241 }
1242 ?>
1243 <a class="button button-primary secondary wpbc_setup_wizard_test_page_button"
1244 href="<?php echo esc_url( $test_page_link['url'] ); ?>"
1245 target="_blank"
1246 rel="noopener noreferrer"><?php echo esc_html( $test_page_link['label'] ); ?></a>
1247 <?php } ?>
1248 </div>
1249 <?php } ?>
1250 <div class="wpbc_page_top__wizard_button_actions wpbc_setup_wizard_bar_expandable">
1251 <?php if ( ! empty( $secondary_action_url ) && ! empty( $secondary_action_label ) ) { ?>
1252 <a class="button button-secondary wpbc_setup_wizard_secondary_action"
1253 href="<?php echo esc_url( $secondary_action_url ); ?>"><?php echo esc_html( $secondary_action_label ); ?></a>
1254 <?php } ?>
1255 <?php if ( ! empty( $prior_url ) ) { ?>
1256 <a href="<?php echo esc_url( $prior_url ); ?>" class="button button-secondary"><?php esc_html_e( 'Back', 'booking' ); ?></a>
1257 <?php } ?>
1258 <a href="<?php echo esc_url( $continue_href ); ?>"
1259 class="button button-primary wpbc_setup_wizard_continue_button<?php echo $is_continue_disabled ? ' disabled' : ''; ?>"
1260 data-wpbc-setup-continue-url="<?php echo esc_url( $continue_url ); ?>"
1261 <?php echo $is_continue_disabled ? 'aria-disabled="true"' : ''; ?>><?php echo esc_html( $continue_title ); ?></a>
1262 </div>
1263 <div class="wpbc_page_top__wizard_button_links wpbc_setup_wizard_bar_expandable">
1264 <a href="<?php echo esc_url( $skip_wizard_url ); ?>"
1265 title="<?php esc_attr_e( 'Exit and skip the setup wizard', 'booking' ); ?>">
1266 <?php esc_html_e( 'Exit and skip the setup wizard', 'booking' ); ?>
1267 </a>
1268 <a href="<?php echo esc_url( $reset_wizard_url ); ?>"
1269 class="wpbc_setup_wizard_bar_danger_link"
1270 title="<?php esc_attr_e( 'Start Setup from Beginning', 'booking' ); ?>">
1271 <?php esc_html_e( 'Reset Wizard', 'booking' ); ?>
1272 </a>
1273 </div>
1274 </div>
1275 </div>
1276 </div>
1277 <script type="text/javascript">
1278 jQuery( document ).ready( function() {
1279 var $bar = jQuery( '.wpbc_page_top__wizard_button[data-wpbc-setup-step]' ).first();
1280 var step = $bar.attr( 'data-wpbc-setup-step' ) || '';
1281 var saveBehavior = $bar.attr( 'data-wpbc-setup-save-behavior' ) || '';
1282 var selector = $bar.attr( 'data-wpbc-setup-target-selector' ) || '';
1283 var scrollSelector = $bar.attr( 'data-wpbc-setup-scroll-selector' ) || selector;
1284 var highlightSelector = $bar.attr( 'data-wpbc-setup-highlight-selector' ) || selector;
1285 var highlightDisabled = ( '1' === ( $bar.attr( 'data-wpbc-setup-highlight-disabled' ) || '' ) );
1286 var highlightAll = ( '1' === ( $bar.attr( 'data-wpbc-setup-highlight-all' ) || '' ) );
1287 var formSelector = $bar.attr( 'data-wpbc-setup-form-selector' ) || '';
1288 var saveSelector = $bar.attr( 'data-wpbc-setup-save-selector' ) || '';
1289 var saveAjaxAction = $bar.attr( 'data-wpbc-setup-save-ajax-action' ) || '';
1290 var saveEvents = ( $bar.attr( 'data-wpbc-setup-save-events' ) || '' ).split( ',' );
1291 var openAction = $bar.attr( 'data-wpbc-setup-open-action' ) || '';
1292 var ajaxUrl = $bar.attr( 'data-wpbc-setup-ajax-url' ) || '';
1293 var nonce = $bar.attr( 'data-wpbc-setup-mark-saved-nonce' ) || '';
1294 var $continueButton = $bar.find( '.wpbc_setup_wizard_continue_button' ).first();
1295 var $note = $bar.find( '.wpbc_page_top__wizard_button_note' ).first();
1296 var savedNote = '<?php echo esc_js( __( 'Changes saved. You can continue.', 'booking' ) ); ?>';
1297 var saveRequiredNote = <?php echo wp_json_encode( wp_kses_post( $save_required_note ) ); ?>;
1298 var continueTitle = <?php echo wp_json_encode( ( 'complete' === $save_behavior ) ? __( 'Finish Setup', 'booking' ) : __( 'Continue', 'booking' ) ); ?>;
1299 var saveAndContinueTitle = <?php echo wp_json_encode( __( 'Save and Continue', 'booking' ) ); ?>;
1300 var savingTitle = <?php echo wp_json_encode( __( 'Saving', 'booking' ) . '...' ); ?>;
1301 var $toggleButton = $bar.find( '.wpbc_setup_wizard_bar_toggle_button' ).first();
1302 var $toggleIcon = $toggleButton.find( 'i' ).first();
1303 var $resetButton = $bar.find( '.wpbc_setup_wizard_bar_reset_button' ).first();
1304 var $dragHandle = $bar.find( '.wpbc_setup_wizard_bar_drag_handle' ).first();
1305 var positionStorageKey = 'wpbc_setup_wizard_bar_position';
1306 var collapsedStorageKey = 'wpbc_setup_wizard_bar_collapsed';
1307 var collapseLabel = <?php echo wp_json_encode( __( 'Collapse setup bar', 'booking' ) ); ?>;
1308 var expandLabel = <?php echo wp_json_encode( __( 'Expand setup bar', 'booking' ) ); ?>;
1309 var $target;
1310 var $highlightTargets = jQuery();
1311 var saveClicked = false;
1312 var saveAndContinueRequested = false;
1313 var saveAndContinueRedirecting = false;
1314
1315 function wpbcSetupWizardStorageGet( key ) {
1316 try {
1317 return window.localStorage.getItem( key );
1318 } catch ( _e ) {
1319 return null;
1320 }
1321 }
1322
1323 function wpbcSetupWizardStorageSet( key, value ) {
1324 try {
1325 window.localStorage.setItem( key, value );
1326 } catch ( _e ) {}
1327 }
1328
1329 function wpbcSetupWizardStorageRemove( key ) {
1330 try {
1331 window.localStorage.removeItem( key );
1332 } catch ( _e ) {}
1333 }
1334
1335 function wpbcSetupWizardIsSmallViewport() {
1336 return window.matchMedia && window.matchMedia( '(max-width: 782px)' ).matches;
1337 }
1338
1339 function wpbcSetupWizardClampPosition( left, bottom ) {
1340 var margin = 10;
1341 var barWidth = $bar.outerWidth() || 330;
1342 var barHeight = $bar.outerHeight() || 120;
1343 var maxLeft = Math.max( margin, jQuery( window ).width() - barWidth - margin );
1344 var maxBottom = Math.max( margin, jQuery( window ).height() - barHeight - margin );
1345
1346 return {
1347 left: Math.min( Math.max( margin, left ), maxLeft ),
1348 bottom: Math.min( Math.max( margin, bottom ), maxBottom )
1349 };
1350 }
1351
1352 function wpbcSetupWizardApplyPosition( position ) {
1353 var clampedPosition;
1354 var positionBottom;
1355
1356 if ( wpbcSetupWizardIsSmallViewport() || ! position ) {
1357 $bar
1358 .removeClass( 'wpbc_setup_wizard_bar_is_moved' )
1359 .removeClass( 'wpbc_setup_wizard_bar_auto_shifted' )
1360 .removeClass( 'wpbc_setup_wizard_bar_auto_top' )
1361 .css( {
1362 '--wpbc-setup-bar-left': '',
1363 '--wpbc-setup-bar-bottom': '',
1364 '--wpbc-setup-bar-auto-right': '',
1365 '--wpbc-setup-bar-auto-top': ''
1366 } );
1367 return;
1368 }
1369
1370 positionBottom = parseFloat( position.bottom );
1371 if ( isNaN( positionBottom ) && ! isNaN( parseFloat( position.top ) ) ) {
1372 positionBottom = jQuery( window ).height() - parseFloat( position.top ) - ( $bar.outerHeight() || 120 );
1373 }
1374
1375 clampedPosition = wpbcSetupWizardClampPosition( parseFloat( position.left ) || 15, isNaN( positionBottom ) ? 15 : positionBottom );
1376 $bar
1377 .addClass( 'wpbc_setup_wizard_bar_is_moved' )
1378 .removeClass( 'wpbc_setup_wizard_bar_auto_shifted' )
1379 .removeClass( 'wpbc_setup_wizard_bar_auto_top' )
1380 .css( {
1381 '--wpbc-setup-bar-left': clampedPosition.left + 'px',
1382 '--wpbc-setup-bar-bottom': clampedPosition.bottom + 'px',
1383 '--wpbc-setup-bar-auto-right': '',
1384 '--wpbc-setup-bar-auto-top': ''
1385 } );
1386 }
1387
1388 function wpbcSetupWizardShouldUseTopDefault() {
1389 return -1 !== jQuery.inArray( step, [
1390 'date_selection',
1391 'changeover_days',
1392 'working_time',
1393 'time_slots_availability',
1394 'date_availability'
1395 ] );
1396 }
1397
1398 function wpbcSetupWizardGetRightSidebarOffset() {
1399 var viewportWidth = jQuery( window ).width();
1400 var viewportHeight = jQuery( window ).height();
1401 var $sidebar = jQuery();
1402 var sidebarSelectors = [
1403 '.wpbc_ui_el__vert_right_bar__wrapper',
1404 '.wpbc_ui_el__vert_right_bar',
1405 '.wpbc_ui_el__vert_right_bar__content',
1406 '.wpbc_ui_el__vert_right_bar__content .simplebar-content-wrapper'
1407 ].join( ',' );
1408
1409 jQuery( sidebarSelectors ).filter( ':visible' ).each( function() {
1410 var rect = this.getBoundingClientRect();
1411
1412 if (
1413 rect.width >= 140
1414 && rect.left > ( viewportWidth * 0.45 )
1415 && rect.right > ( viewportWidth - 80 )
1416 && rect.top < ( viewportHeight - 90 )
1417 && rect.bottom > ( viewportHeight * 0.35 )
1418 ) {
1419 $sidebar = jQuery( this );
1420 return false;
1421 }
1422 } );
1423
1424 if ( ! $sidebar.length ) {
1425 return 0;
1426 }
1427
1428 return Math.max( 0, viewportWidth - $sidebar[0].getBoundingClientRect().left + 15 );
1429 }
1430
1431 function wpbcSetupWizardApplyDefaultPosition() {
1432 var rightOffset;
1433 var maxRight;
1434 var barWidth = $bar.outerWidth() || 330;
1435
1436 if ( wpbcSetupWizardIsSmallViewport() ) {
1437 wpbcSetupWizardApplyPosition( null );
1438 return;
1439 }
1440
1441 // Clear any visible inspector while retaining the minimum offset used by the Days Availability page.
1442 rightOffset = wpbcSetupWizardGetRightSidebarOffset();
1443 if ( 'date_availability' === step ) {
1444 rightOffset = Math.max( rightOffset, 60 );
1445 }
1446 maxRight = Math.max( 15, jQuery( window ).width() - barWidth - 10 );
1447
1448 if ( wpbcSetupWizardShouldUseTopDefault() ) {
1449 $bar
1450 .removeClass( 'wpbc_setup_wizard_bar_is_moved' )
1451 .addClass( 'wpbc_setup_wizard_bar_auto_shifted' )
1452 .addClass( 'wpbc_setup_wizard_bar_auto_top' )
1453 .css( {
1454 '--wpbc-setup-bar-left': '',
1455 '--wpbc-setup-bar-bottom': '',
1456 '--wpbc-setup-bar-auto-right': Math.min( Math.max( rightOffset, 15 ), maxRight ) + 'px',
1457 '--wpbc-setup-bar-auto-top': '15px'
1458 } );
1459 return;
1460 }
1461
1462 if ( rightOffset > 15 ) {
1463 $bar
1464 .removeClass( 'wpbc_setup_wizard_bar_is_moved' )
1465 .removeClass( 'wpbc_setup_wizard_bar_auto_top' )
1466 .addClass( 'wpbc_setup_wizard_bar_auto_shifted' )
1467 .css( {
1468 '--wpbc-setup-bar-left': '',
1469 '--wpbc-setup-bar-bottom': '',
1470 '--wpbc-setup-bar-auto-right': Math.min( rightOffset, maxRight ) + 'px',
1471 '--wpbc-setup-bar-auto-top': ''
1472 } );
1473 return;
1474 }
1475
1476 wpbcSetupWizardApplyPosition( null );
1477 }
1478
1479 function wpbcSetupWizardSavePosition( left, bottom ) {
1480 var clampedPosition = wpbcSetupWizardClampPosition( left, bottom );
1481
1482 wpbcSetupWizardStorageSet( positionStorageKey, JSON.stringify( clampedPosition ) );
1483 wpbcSetupWizardApplyPosition( clampedPosition );
1484 }
1485
1486 function wpbcSetupWizardApplySavedPosition() {
1487 var savedPosition = wpbcSetupWizardStorageGet( positionStorageKey );
1488 var rightSidebarOffset;
1489 var barRect;
1490 var sidebarLeft;
1491
1492 if ( ! savedPosition ) {
1493 wpbcSetupWizardApplyDefaultPosition();
1494 return;
1495 }
1496
1497 try {
1498 wpbcSetupWizardApplyPosition( JSON.parse( savedPosition ) );
1499 } catch ( _e ) {
1500 wpbcSetupWizardStorageRemove( positionStorageKey );
1501 wpbcSetupWizardApplyDefaultPosition();
1502 return;
1503 }
1504
1505 rightSidebarOffset = wpbcSetupWizardGetRightSidebarOffset();
1506 if ( 'service_provider' === step && rightSidebarOffset > 15 ) {
1507 barRect = $bar[0].getBoundingClientRect();
1508 sidebarLeft = jQuery( window ).width() - rightSidebarOffset + 15;
1509
1510 if ( barRect.right > ( sidebarLeft - 10 ) ) {
1511 wpbcSetupWizardApplyDefaultPosition();
1512 }
1513 }
1514 }
1515
1516 function wpbcSetupWizardResetPosition() {
1517 wpbcSetupWizardStorageRemove( positionStorageKey );
1518 wpbcSetupWizardApplyDefaultPosition();
1519 }
1520
1521 function wpbcSetupWizardSetCollapsed( isCollapsed ) {
1522 $bar.toggleClass( 'wpbc_setup_wizard_bar_collapsed', !! isCollapsed );
1523 $toggleButton
1524 .attr( 'aria-expanded', isCollapsed ? 'false' : 'true' )
1525 .attr( 'title', isCollapsed ? expandLabel : collapseLabel )
1526 .attr( 'aria-label', isCollapsed ? expandLabel : collapseLabel );
1527 $toggleIcon
1528 .toggleClass( 'wpbc_icn_expand_less', ! isCollapsed )
1529 .toggleClass( 'wpbc_icn_expand_more', !! isCollapsed );
1530 wpbcSetupWizardStorageSet( collapsedStorageKey, isCollapsed ? '1' : '0' );
1531 wpbcSetupWizardApplySavedPosition();
1532 }
1533
1534 $toggleButton.on( 'click', function() {
1535 wpbcSetupWizardSetCollapsed( ! $bar.hasClass( 'wpbc_setup_wizard_bar_collapsed' ) );
1536 } );
1537
1538 $resetButton.on( 'click', function() {
1539 wpbcSetupWizardResetPosition();
1540 } );
1541
1542 $dragHandle.on( 'mousedown', function( event ) {
1543 var startX;
1544 var startY;
1545 var startLeft;
1546 var startBottom;
1547 var rect;
1548 var barHeight;
1549
1550 if ( wpbcSetupWizardIsSmallViewport() || ( event.which && 1 !== event.which ) ) {
1551 return;
1552 }
1553
1554 event.preventDefault();
1555 rect = $bar[0].getBoundingClientRect();
1556 startX = event.clientX;
1557 startY = event.clientY;
1558 startLeft = rect.left;
1559 barHeight = $bar.outerHeight() || rect.height || 120;
1560 startBottom = jQuery( window ).height() - rect.top - barHeight;
1561 $bar.addClass( 'wpbc_setup_wizard_bar_is_dragging' );
1562
1563 jQuery( document )
1564 .off( '.wpbc_setup_wizard_bar_drag' )
1565 .on( 'mousemove.wpbc_setup_wizard_bar_drag', function( moveEvent ) {
1566 wpbcSetupWizardApplyPosition( {
1567 left: startLeft + moveEvent.clientX - startX,
1568 bottom: startBottom - moveEvent.clientY + startY
1569 } );
1570 } )
1571 .on( 'mouseup.wpbc_setup_wizard_bar_drag', function( upEvent ) {
1572 var movedRect = $bar[0].getBoundingClientRect();
1573 var movedBottom = jQuery( window ).height() - movedRect.top - ( $bar.outerHeight() || movedRect.height || 120 );
1574
1575 wpbcSetupWizardSavePosition( movedRect.left, movedBottom );
1576 $bar.removeClass( 'wpbc_setup_wizard_bar_is_dragging' );
1577 jQuery( document ).off( '.wpbc_setup_wizard_bar_drag' );
1578 } );
1579 } );
1580
1581 wpbcSetupWizardSetCollapsed( '1' === wpbcSetupWizardStorageGet( collapsedStorageKey ) );
1582 wpbcSetupWizardApplySavedPosition();
1583 setTimeout( wpbcSetupWizardApplySavedPosition, 400 );
1584 setTimeout( wpbcSetupWizardApplySavedPosition, 1000 );
1585 jQuery( window ).on( 'resize.wpbc_setup_wizard_bar', wpbcSetupWizardApplySavedPosition );
1586 jQuery( document ).on( 'wpbc_setup_wizard_layout_changed.wpbc_setup_wizard_bar', wpbcSetupWizardApplySavedPosition );
1587
1588 function wpbcSetupWizardOpenPublishArea() {
1589 var isResourcesPage = -1 !== window.location.href.indexOf( 'page=wpbc-resources' );
1590 var publishTabSelectors = [
1591 '.wpdvlp-sub-tabs .nav-tab',
1592 '.wpdvlp-top-tabs .nav-tab',
1593 '.wpbc_settings_navigation_item a',
1594 '.wpbc_ui_el__vert_nav_item a',
1595 '[role="tab"]',
1596 '[data-tab]',
1597 '[data-subtab]'
1598 ].join( ',' );
1599 var publishToggleSelectors = [
1600 '.wpbc_resource_field__switchable a',
1601 '.wpbc_resource_field__switchable button',
1602 '.wpbc_ajx_toolbar a',
1603 '.wpbc_ajx_toolbar button',
1604 'a.button',
1605 'button.button'
1606 ].join( ',' );
1607 var publishTargetSelector = [
1608 '.wpbc_resources_table .ui_group__publish_btn:visible',
1609 '#wpbc_booking_resource_table .ui_group__publish_btn:visible',
1610 '.wpbc_resource_field__switchable.wpbc_resource_field__publish:visible',
1611 '.wpbc_resource_field__publish:visible',
1612 '.wpbc_resource_publish:visible',
1613 '.wpbc_publish_resources:visible',
1614 '[data-wpbc-resource-publish]:visible'
1615 ].join( ',' );
1616 var $publishTab;
1617 var $publishToggle;
1618
1619 if ( ( 'wizard_publish' !== step && 'publish_area' !== openAction ) || ! isResourcesPage ) {
1620 return;
1621 }
1622
1623 $publishTab = jQuery( publishTabSelectors ).filter( ':visible' ).filter( function() {
1624 var $element = jQuery( this );
1625 var text = $element.text() || '';
1626 var href = $element.attr( 'href' ) || '';
1627 var dataTab = $element.attr( 'data-tab' ) || '';
1628 var dataSubtab = $element.attr( 'data-subtab' ) || '';
1629 var haystack = ( text + ' ' + href + ' ' + dataTab + ' ' + dataSubtab ).toLowerCase();
1630
1631 if ( $element.closest( '.wpbc_page_top__wizard_button' ).length ) {
1632 return false;
1633 }
1634
1635 return (
1636 -1 !== haystack.indexOf( 'publish' )
1637 || -1 !== haystack.indexOf( 'shortcode' )
1638 || -1 !== haystack.indexOf( 'embed' )
1639 );
1640 } ).first();
1641
1642 if ( $publishTab.length && ! $publishTab.hasClass( 'nav-tab-active' ) && ! $publishTab.parent().hasClass( 'active' ) ) {
1643 $publishTab.trigger( 'click' );
1644 }
1645
1646 if ( ! $publishTab.length ) {
1647 $publishToggle = jQuery( publishToggleSelectors ).filter( ':visible' ).filter( function() {
1648 var $element = jQuery( this );
1649 var text = $element.text() || '';
1650 var title = $element.attr( 'title' ) || $element.attr( 'data-original-title' ) || '';
1651 var onclick = $element.attr( 'onclick' ) || '';
1652 var className = $element.attr( 'class' ) || '';
1653 var haystack = ( text + ' ' + title + ' ' + className ).toLowerCase();
1654
1655 if ( $element.closest( '.wpbc_page_top__wizard_button' ).length ) {
1656 return false;
1657 }
1658
1659 if ( -1 !== onclick.indexOf( 'wpbc_modal_dialog__show__resource_publish' ) ) {
1660 return false;
1661 }
1662
1663 return (
1664 -1 !== haystack.indexOf( 'show publish' )
1665 || -1 !== haystack.indexOf( 'publish option' )
1666 || -1 !== haystack.indexOf( 'shortcode' )
1667 || -1 !== haystack.indexOf( 'resource_field__publish' )
1668 );
1669 } ).first();
1670
1671 if ( $publishToggle.length ) {
1672 $publishToggle.trigger( 'click' );
1673 }
1674 }
1675
1676 setTimeout( function() {
1677 var $publishTarget = jQuery( publishTargetSelector ).first();
1678
1679 if ( ! $publishTarget.length ) {
1680 $publishTarget = jQuery( selector ).filter( ':visible' ).first();
1681 }
1682
1683 if ( ! $publishTarget.length ) {
1684 return;
1685 }
1686
1687 if ( typeof wpbc_scroll_to === 'function' ) {
1688 wpbc_scroll_to( $publishTarget );
1689 } else if ( $publishTarget.offset() ) {
1690 jQuery( 'html, body' ).animate( { scrollTop: $publishTarget.offset().top - 80 }, 300 );
1691 }
1692
1693 if ( typeof wpbc_blink_element === 'function' ) {
1694 wpbc_blink_element( $publishTarget, 3, 300 );
1695 }
1696 }, 450 );
1697 }
1698
1699 wpbcSetupWizardOpenPublishArea();
1700
1701 function wpbcSetupWizardGetFirstElement( selectors ) {
1702 var $element = jQuery();
1703
1704 if ( ! selectors ) {
1705 return $element;
1706 }
1707
1708 try {
1709 $element = jQuery( selectors ).filter( ':visible' ).first();
1710 if ( $element.length ) {
1711 return $element;
1712 }
1713 return jQuery( selectors ).first();
1714 } catch ( _e ) {
1715 return jQuery();
1716 }
1717 }
1718
1719 function wpbcSetupWizardGetScrollableParent( $element ) {
1720 var $scrollParent;
1721
1722 if ( ! $element || ! $element.length ) {
1723 return jQuery();
1724 }
1725
1726 $scrollParent = $element.parents().filter( function() {
1727 var $parent = jQuery( this );
1728 var overflowY = $parent.css( 'overflow-y' );
1729
1730 return (
1731 /(auto|scroll)/.test( overflowY )
1732 && this.scrollHeight > Math.ceil( $parent.innerHeight() ) + 5
1733 );
1734 } ).first();
1735
1736 return $scrollParent;
1737 }
1738
1739 function wpbcSetupWizardScrollToElement( $element ) {
1740 var $scrollParent;
1741 var targetTop;
1742
1743 if ( ! $element || ! $element.length || ! $element.offset() ) {
1744 return;
1745 }
1746
1747 $scrollParent = wpbcSetupWizardGetScrollableParent( $element );
1748 if ( $scrollParent.length && ! $scrollParent.is( 'html, body' ) ) {
1749 targetTop = $element.offset().top - $scrollParent.offset().top + $scrollParent.scrollTop() - 40;
1750 $scrollParent.stop().animate( {
1751 scrollTop: Math.max( 0, targetTop )
1752 }, 350 );
1753 return;
1754 }
1755
1756 if ( typeof wpbc_scroll_to === 'function' ) {
1757 wpbc_scroll_to( $element );
1758 } else {
1759 jQuery( 'html, body' ).stop().animate( {
1760 scrollTop: Math.max( 0, $element.offset().top - 90 )
1761 }, 350 );
1762 }
1763 }
1764
1765 function wpbcSetupWizardHighlightElement( $element ) {
1766 if ( ! $element || ! $element.length ) {
1767 return;
1768 }
1769
1770 $element.addClass( 'wpbc_setup_wizard__target_highlight' );
1771 if ( typeof wpbc_blink_element === 'function' ) {
1772 wpbc_blink_element( $element, 3, 300 );
1773 }
1774 }
1775
1776 function wpbcSetupWizardPulseElement( $element ) {
1777 if ( ! $element || ! $element.length ) {
1778 return;
1779 }
1780
1781 $element
1782 .removeClass( 'wpbc_setup_wizard_attention_pulse' )
1783 .each( function() {
1784 // Restart the CSS animation when the user clicks Continue repeatedly.
1785 void this.offsetWidth;
1786 } )
1787 .addClass( 'wpbc_setup_wizard_attention_pulse' );
1788
1789 setTimeout( function() {
1790 $element.removeClass( 'wpbc_setup_wizard_attention_pulse' );
1791 }, 2100 );
1792 }
1793
1794 function wpbcSetupWizardPulseSaveRequiredMessage() {
1795 if ( $bar.hasClass( 'wpbc_setup_wizard_bar_collapsed' ) ) {
1796 wpbcSetupWizardSetCollapsed( false );
1797 }
1798
1799 if ( $note.length ) {
1800 wpbcSetupWizardPulseElement( $note );
1801 }
1802
1803 setTimeout( function() {
1804 wpbcSetupWizardPulseElement( jQuery( '#ajax_working .wpbc_inner_message.notice-warning' ).last() );
1805 }, 50 );
1806 }
1807
1808 function wpbcSetupWizardSetSaved() {
1809 $bar.attr( 'data-wpbc-setup-is-saved', '1' );
1810 $continueButton
1811 .removeClass( 'disabled' )
1812 .removeAttr( 'aria-disabled' )
1813 .attr( 'href', $continueButton.attr( 'data-wpbc-setup-continue-url' ) || '#' )
1814 .text( continueTitle );
1815 if ( $note.length ) {
1816 $note
1817 .addClass( 'wpbc_setup_wizard_bar_note_saved' )
1818 .text( savedNote );
1819 }
1820 }
1821
1822 function wpbcSetupWizardSetUnsaved() {
1823 $bar.attr( 'data-wpbc-setup-is-saved', '0' );
1824 $continueButton.attr( 'href', '#wpbc_setup_save_required' ).text( saveSelector ? saveAndContinueTitle : continueTitle );
1825 if ( saveSelector ) {
1826 $continueButton.removeClass( 'disabled' ).removeAttr( 'aria-disabled' );
1827 } else {
1828 $continueButton.addClass( 'disabled' ).attr( 'aria-disabled', 'true' );
1829 }
1830 if ( $note.length ) {
1831 $note
1832 .removeClass( 'wpbc_setup_wizard_bar_note_saved' )
1833 .html( saveRequiredNote );
1834 }
1835 }
1836
1837 function wpbcSetupWizardSetSaveAndContinueBusy( isBusy ) {
1838 if ( ! saveSelector ) {
1839 return;
1840 }
1841
1842 $continueButton.toggleClass( 'disabled', !! isBusy ).text( isBusy ? savingTitle : saveAndContinueTitle );
1843 if ( isBusy ) {
1844 $continueButton.attr( 'aria-disabled', 'true' );
1845 } else {
1846 $continueButton.removeAttr( 'aria-disabled' );
1847 }
1848 }
1849
1850 function wpbcSetupWizardGetContinueUrl() {
1851 return $continueButton.attr( 'data-wpbc-setup-continue-url' ) || $continueButton.attr( 'href' ) || '';
1852 }
1853
1854 function wpbcSetupWizardContinueAfterSave() {
1855 var continueUrl;
1856
1857 if ( saveAndContinueRedirecting ) {
1858 return;
1859 }
1860
1861 continueUrl = wpbcSetupWizardGetContinueUrl();
1862 if ( ! continueUrl || '#wpbc_setup_save_required' === continueUrl ) {
1863 wpbcSetupWizardSetSaveAndContinueBusy( false );
1864 return;
1865 }
1866
1867 saveAndContinueRedirecting = true;
1868 window.location.href = continueUrl;
1869 }
1870
1871 function wpbcSetupWizardMarkSaved( afterSavedCallback ) {
1872 if ( ! step || ! ajaxUrl || ! nonce ) {
1873 wpbcSetupWizardSetSaved();
1874 if ( 'function' === typeof afterSavedCallback ) {
1875 afterSavedCallback();
1876 }
1877 return;
1878 }
1879
1880 jQuery.post( ajaxUrl, {
1881 action: 'WPBC_AJX_SETUP_WIZARD_MARK_STEP_SAVED',
1882 nonce: nonce,
1883 wpbc_setup_step: step
1884 } ).done( function( response ) {
1885 if ( 'string' === typeof response ) {
1886 try {
1887 response = JSON.parse( response );
1888 } catch ( _e ) {}
1889 }
1890 if ( response && response.success ) {
1891 wpbcSetupWizardSetSaved();
1892 if ( 'function' === typeof afterSavedCallback ) {
1893 afterSavedCallback();
1894 }
1895 }
1896 } ).fail( function() {
1897 if ( saveAndContinueRequested ) {
1898 wpbcSetupWizardSetSaveAndContinueBusy( false );
1899 saveAndContinueRequested = false;
1900 }
1901 } );
1902 }
1903
1904 function wpbcSetupWizardSaveStarted() {
1905 saveClicked = true;
1906 }
1907
1908 function wpbcSetupWizardLooksSuccessfulResponse( response ) {
1909 if ( ! response ) {
1910 return false;
1911 }
1912
1913 return (
1914 !! response.success
1915 || 'success' === response.status
1916 || '1' === String( response.ajx_after_action_result || '' )
1917 || ( response.ajx_data && '1' === String( response.ajx_data.ajx_after_action_result || '' ) )
1918 || ( response.data && response.data.setup_step_saved )
1919 );
1920 }
1921
1922 function wpbcSetupWizardGetAjaxAction( ajaxSettings ) {
1923 var data = ajaxSettings && ajaxSettings.data ? ajaxSettings.data : '';
1924 var matches;
1925
1926 if ( ! data ) {
1927 return '';
1928 }
1929
1930 if ( 'string' === typeof data ) {
1931 matches = data.match( /(?:^|&)action=([^&]+)/ );
1932 return matches && matches[1] ? decodeURIComponent( matches[1].replace( /\+/g, ' ' ) ) : '';
1933 }
1934
1935 if ( window.FormData && data instanceof window.FormData && 'function' === typeof data.get ) {
1936 return data.get( 'action' ) || '';
1937 }
1938
1939 if ( 'object' === typeof data && data.action ) {
1940 return data.action;
1941 }
1942
1943 return '';
1944 }
1945
1946 function wpbcSetupWizardIsExpectedSaveAjax( ajaxSettings ) {
1947 var ajaxAction;
1948
1949 if ( ! saveAjaxAction ) {
1950 return true;
1951 }
1952
1953 ajaxAction = wpbcSetupWizardGetAjaxAction( ajaxSettings );
1954
1955 return saveAjaxAction === ajaxAction;
1956 }
1957
1958 function wpbcSetupWizardHandleSavedEvent() {
1959 saveClicked = false;
1960 wpbcSetupWizardSetSaved();
1961 if ( saveAndContinueRequested ) {
1962 wpbcSetupWizardMarkSaved( wpbcSetupWizardContinueAfterSave );
1963 return;
1964 }
1965 wpbcSetupWizardMarkSaved();
1966 }
1967
1968 function wpbcSetupWizardRegisterSavedEvent( eventName ) {
1969 eventName = ( eventName || '' ).replace( /^\s+|\s+$/g, '' );
1970 if ( ! eventName ) {
1971 return;
1972 }
1973
1974 document.addEventListener( eventName, wpbcSetupWizardHandleSavedEvent, true );
1975 jQuery( document ).on( eventName + '.wpbc_setup_wizard', wpbcSetupWizardHandleSavedEvent );
1976 }
1977
1978 function wpbcSetupWizardFindSaveControl() {
1979 var $saveControl = wpbcSetupWizardGetFirstElement( saveSelector );
1980
1981 if ( $saveControl.length ) {
1982 return $saveControl;
1983 }
1984
1985 if ( ! formSelector ) {
1986 return jQuery();
1987 }
1988
1989 return wpbcSetupWizardGetFirstElement(
1990 formSelector + ' button[type="submit"],' +
1991 formSelector + ' input[type="submit"],' +
1992 formSelector + ' .wpbc_submit_button_trigger,' +
1993 formSelector + ' .wpbc_submit_button'
1994 );
1995 }
1996
1997 function wpbcSetupWizardTriggerSaveAndContinue() {
1998 var $saveControl = wpbcSetupWizardFindSaveControl();
1999
2000 if ( saveAndContinueRequested ) {
2001 return;
2002 }
2003
2004 if ( ! $saveControl.length || $saveControl.hasClass( 'disabled' ) || 'true' === $saveControl.attr( 'aria-disabled' ) ) {
2005 if ( typeof wpbc_admin_show_message === 'function' ) {
2006 wpbc_admin_show_message( '<?php echo esc_js( __( 'Please save changes on this page before continuing setup.', 'booking' ) ); ?>', 'warning', 4000, false );
2007 }
2008 wpbcSetupWizardPulseSaveRequiredMessage();
2009 return;
2010 }
2011
2012 saveAndContinueRequested = true;
2013 wpbcSetupWizardSaveStarted();
2014 wpbcSetupWizardSetSaveAndContinueBusy( true );
2015 if ( formSelector ) {
2016 jQuery( formSelector ).find( 'input[name="wpbc_setup_continue_after_save"]' ).val( '1' );
2017 }
2018 $saveControl.trigger( 'click' );
2019 }
2020
2021 if ( 'manual_save_required' === saveBehavior ) {
2022 window.wpbc_setup_wizard_set_current_step_saved = wpbcSetupWizardSetSaved;
2023 window.wpbc_setup_wizard_mark_current_step_saved = wpbcSetupWizardMarkSaved;
2024
2025 document.addEventListener( 'wpbc:bfb:form:before_save_payload', function( event ) {
2026 if ( ! event || ! event.detail || ! event.detail.payload || ! step ) {
2027 return;
2028 }
2029 wpbcSetupWizardSaveStarted();
2030 event.detail.payload.wpbc_setup = '1';
2031 event.detail.payload.wpbc_setup_step = step;
2032 if ( saveAndContinueRequested ) {
2033 event.detail.payload.wpbc_setup_continue_after_save = '1';
2034 }
2035 }, true );
2036
2037 saveEvents.forEach( wpbcSetupWizardRegisterSavedEvent );
2038
2039 if ( formSelector ) {
2040 jQuery( formSelector ).each( function() {
2041 var $form = jQuery( this );
2042 if ( ! $form.is( 'form' ) ) {
2043 return;
2044 }
2045 if ( ! $form.find( 'input[name="wpbc_setup_saved_step"]' ).length ) {
2046 $form.append( '<input type="hidden" name="wpbc_setup_saved_step" value="" />' );
2047 }
2048 if ( ! $form.find( 'input[name="wpbc_setup_step"]' ).length ) {
2049 $form.append( '<input type="hidden" name="wpbc_setup_step" value="" />' );
2050 }
2051 if ( ! $form.find( 'input[name="wpbc_setup"]' ).length ) {
2052 $form.append( '<input type="hidden" name="wpbc_setup" value="" />' );
2053 }
2054 if ( ! $form.find( 'input[name="wpbc_setup_continue_after_save"]' ).length ) {
2055 $form.append( '<input type="hidden" name="wpbc_setup_continue_after_save" value="" />' );
2056 }
2057 $form.find( 'input[name="wpbc_setup_saved_step"]' ).val( step );
2058 $form.find( 'input[name="wpbc_setup_step"]' ).val( step );
2059 $form.find( 'input[name="wpbc_setup"]' ).val( '1' );
2060 $form.find( 'input[name="wpbc_setup_continue_after_save"]' ).val( '0' );
2061 $form
2062 .off( 'change.wpbc_setup_wizard input.wpbc_setup_wizard', ':input' )
2063 .on( 'change.wpbc_setup_wizard input.wpbc_setup_wizard', ':input', function() {
2064 if ( jQuery( this ).is( '[name="wpbc_setup_saved_step"],[name="wpbc_setup_step"],[name="wpbc_setup"],[name="wpbc_setup_continue_after_save"],[name="form_visible_section"]' ) ) {
2065 return;
2066 }
2067 wpbcSetupWizardSetUnsaved();
2068 } );
2069 $form
2070 .off( 'submit.wpbc_setup_wizard' )
2071 .on( 'submit.wpbc_setup_wizard', function() {
2072 wpbcSetupWizardSaveStarted();
2073 $form.find( 'input[name="wpbc_setup_saved_step"]' ).val( step );
2074 $form.find( 'input[name="wpbc_setup_step"]' ).val( step );
2075 $form.find( 'input[name="wpbc_setup"]' ).val( '1' );
2076 $form.find( 'input[name="wpbc_setup_continue_after_save"]' ).val( saveAndContinueRequested ? '1' : '0' );
2077 } );
2078 } );
2079 }
2080
2081 $continueButton.on( 'click', function( event ) {
2082 if ( '1' !== $bar.attr( 'data-wpbc-setup-is-saved' ) ) {
2083 event.preventDefault();
2084 if ( saveSelector ) {
2085 wpbcSetupWizardTriggerSaveAndContinue();
2086 return;
2087 }
2088 if ( typeof wpbc_admin_show_message === 'function' ) {
2089 wpbc_admin_show_message( '<?php echo esc_js( __( 'Please save changes on this page before continuing setup.', 'booking' ) ); ?>', 'warning', 4000, false );
2090 }
2091 wpbcSetupWizardPulseSaveRequiredMessage();
2092 }
2093 } );
2094
2095 if ( saveSelector ) {
2096 jQuery( document )
2097 .on( 'mousedown.wpbc_setup_wizard click.wpbc_setup_wizard', saveSelector, wpbcSetupWizardSaveStarted )
2098 .on( 'keydown.wpbc_setup_wizard', saveSelector, function( event ) {
2099 if ( 13 === event.which || 32 === event.which ) {
2100 wpbcSetupWizardSaveStarted();
2101 }
2102 } );
2103 }
2104
2105 jQuery( document ).ajaxComplete( function( _event, xhr, ajaxSettings ) {
2106 var response;
2107 if ( ! saveClicked ) {
2108 return;
2109 }
2110 if ( ! wpbcSetupWizardIsExpectedSaveAjax( ajaxSettings ) ) {
2111 return;
2112 }
2113 saveClicked = false;
2114
2115 response = xhr && xhr.responseJSON ? xhr.responseJSON : null;
2116 if ( ! response && xhr && xhr.responseText ) {
2117 try {
2118 response = JSON.parse( xhr.responseText );
2119 } catch ( _e ) {}
2120 }
2121 if ( response && response.data && response.data.setup_step_saved ) {
2122 wpbcSetupWizardSetSaved();
2123 if ( saveAndContinueRequested ) {
2124 wpbcSetupWizardContinueAfterSave();
2125 }
2126 } else if ( wpbcSetupWizardLooksSuccessfulResponse( response ) ) {
2127 if ( saveAndContinueRequested ) {
2128 wpbcSetupWizardMarkSaved( wpbcSetupWizardContinueAfterSave );
2129 } else {
2130 wpbcSetupWizardMarkSaved();
2131 }
2132 } else if ( saveAndContinueRequested ) {
2133 wpbcSetupWizardSetSaveAndContinueBusy( false );
2134 saveAndContinueRequested = false;
2135 }
2136 } );
2137 }
2138
2139 if ( highlightDisabled ) {
2140 highlightSelector = '';
2141 }
2142
2143 if ( ! selector && ! scrollSelector && ! highlightSelector ) {
2144 return;
2145 }
2146
2147 if ( ! highlightDisabled && highlightAll ) {
2148 try {
2149 $highlightTargets = jQuery( highlightSelector || selector ).filter( ':visible' );
2150 } catch ( _e ) {
2151 $highlightTargets = jQuery();
2152 }
2153
2154 $highlightTargets.each( function() {
2155 wpbcSetupWizardHighlightElement( jQuery( this ) );
2156 } );
2157 } else if ( ! highlightDisabled ) {
2158 $highlightTargets = wpbcSetupWizardGetFirstElement( highlightSelector || selector );
2159 wpbcSetupWizardHighlightElement( $highlightTargets );
2160 }
2161
2162 $target = $highlightTargets.first();
2163
2164 setTimeout( function() {
2165 var $scrollTarget = wpbcSetupWizardGetFirstElement( scrollSelector || ( highlightDisabled ? selector : highlightSelector ) || selector );
2166 if ( ! $scrollTarget.length ) {
2167 $scrollTarget = $target;
2168 }
2169 wpbcSetupWizardScrollToElement( $scrollTarget );
2170 }, 250 );
2171 } );
2172 </script><?php
2173 }
2174 }
2175
2176 }
2177 function wpbc_init_setup_wizard(){
2178 $setup_steps = new WPBC_SETUP_WIZARD_STEPS();
2179 }
2180 // $setup_steps = new WPBC_SETUP_WIZARD_STEPS();
2181 add_action( 'init', 'wpbc_init_setup_wizard' );
2182
2183
2184
2185 /**
2186 * On plugin activation set all steps as completed in Live Demos
2187 * @return void
2188 */
2189 function wpbc_booking_activate_plugin__wizard() {
2190 if ( wpbc_is_this_demo() ) {
2191 $setup_steps = new WPBC_SETUP_WIZARD_STEPS();
2192 $is_completed = true;
2193 $setup_steps->db__set_all_steps_as( $is_completed );
2194 }
2195 }
2196 add_bk_action( 'wpbc_other_versions_activation', 'wpbc_booking_activate_plugin__wizard' );
2197