| 1 |
<?php |
| 2 |
/** |
| 3 |
* First-install onboarding prompts on the Booking Listing page. |
| 4 |
* |
| 5 |
* @package Booking Calendar |
| 6 |
* @since 11.8.1 |
| 7 |
*/ |
| 8 |
|
| 9 |
if ( ! defined( 'ABSPATH' ) ) { |
| 10 |
exit; |
| 11 |
} |
| 12 |
|
| 13 |
/** |
| 14 |
* Coordinate first-run prompt eligibility, assets, templates, and dismissal. |
| 15 |
* |
| 16 |
* The Setup domain owns the persisted state and markup. The Booking Listing is |
| 17 |
* only the route where this non-mutating entry prompt is presented. |
| 18 |
* |
| 19 |
* @since 11.8.1 |
| 20 |
*/ |
| 21 |
final class WPBC_Setup_Wizard_First_Run_Popup { |
| 22 |
|
| 23 |
/** |
| 24 |
* Logged-in WordPress AJAX action used to consume the Setup prompt. |
| 25 |
* |
| 26 |
* @var string |
| 27 |
*/ |
| 28 |
const AJAX_ACTION = 'WPBC_AJX_SETUP_WIZARD_FIRST_RUN_PROMPT'; |
| 29 |
|
| 30 |
/** |
| 31 |
* Logged-in WordPress AJAX action used to consume the booking-pages prompt. |
| 32 |
* |
| 33 |
* @var string |
| 34 |
*/ |
| 35 |
const BOOKING_PAGES_AJAX_ACTION = 'WPBC_AJX_SETUP_WIZARD_BOOKING_PAGES_PROMPT'; |
| 36 |
|
| 37 |
/** |
| 38 |
* Nonce action protecting prompt state changes. |
| 39 |
* |
| 40 |
* @var string |
| 41 |
*/ |
| 42 |
const NONCE_ACTION = 'wpbc_setup_wizard_first_run_prompt_wpbcnonce'; |
| 43 |
|
| 44 |
/** |
| 45 |
* Nonce action protecting booking-pages prompt state changes. |
| 46 |
* |
| 47 |
* @var string |
| 48 |
*/ |
| 49 |
const BOOKING_PAGES_NONCE_ACTION = 'wpbc_setup_wizard_booking_pages_prompt_wpbcnonce'; |
| 50 |
|
| 51 |
/** |
| 52 |
* WordPress script handle for the route-scoped browser adapter. |
| 53 |
* |
| 54 |
* @var string |
| 55 |
*/ |
| 56 |
const SCRIPT_HANDLE = 'wpbc-setup-wizard-first-run-popup'; |
| 57 |
|
| 58 |
/** |
| 59 |
* WordPress style handle for the route-scoped popup presentation. |
| 60 |
* |
| 61 |
* @var string |
| 62 |
*/ |
| 63 |
const STYLE_HANDLE = 'wpbc-setup-wizard-first-run-popup'; |
| 64 |
|
| 65 |
/** |
| 66 |
* Whether route-scoped assets were configured during this request. |
| 67 |
* |
| 68 |
* @var bool |
| 69 |
*/ |
| 70 |
private static $assets_configured = false; |
| 71 |
|
| 72 |
/** |
| 73 |
* Register prompt assets, allow-listed templates, and AJAX endpoints. |
| 74 |
* |
| 75 |
* @return void |
| 76 |
*/ |
| 77 |
public static function init() { |
| 78 |
|
| 79 |
add_action( 'wpbc_enqueue_js_files', array( __CLASS__, 'enqueue_js_files' ), 60 ); |
| 80 |
add_action( 'wpbc_enqueue_css_files', array( __CLASS__, 'enqueue_css_files' ), 60 ); |
| 81 |
add_action( 'wpbc_hook_settings_page_footer', array( __CLASS__, 'render_template' ) ); |
| 82 |
add_action( 'wp_ajax_' . self::AJAX_ACTION, array( __CLASS__, 'ajax_dismiss' ) ); |
| 83 |
add_action( 'wp_ajax_' . self::BOOKING_PAGES_AJAX_ACTION, array( __CLASS__, 'ajax_dismiss_booking_pages_prompt' ) ); |
| 84 |
} |
| 85 |
|
| 86 |
/** |
| 87 |
* Check whether the current administrator can use Initial Setup. |
| 88 |
* |
| 89 |
* This mirrors the Setup menu's role and MultiUser ownership boundaries. The |
| 90 |
* AJAX endpoint repeats the same check because browser visibility is never an |
| 91 |
* authorization boundary. |
| 92 |
* |
| 93 |
* @return bool True when the current user may access Setup. |
| 94 |
*/ |
| 95 |
private static function current_user_can_access() { |
| 96 |
|
| 97 |
if ( ! wpbc_is_user_can_access_wizard_page() ) { |
| 98 |
return false; |
| 99 |
} |
| 100 |
|
| 101 |
$minimum_role = get_bk_option( 'booking_user_role_settings' ); |
| 102 |
|
| 103 |
return wpbc_is_current_user_have_this_role( $minimum_role ); |
| 104 |
} |
| 105 |
|
| 106 |
/** |
| 107 |
* Check whether the first-run prompt remains pending for this site. |
| 108 |
* |
| 109 |
* @return bool True when the prompt belongs to an unfinished first install. |
| 110 |
*/ |
| 111 |
private static function is_setup_prompt_pending() { |
| 112 |
|
| 113 |
return wpbc_setup_wizard_is_initial_install_site() |
| 114 |
&& 'On' === get_bk_option( 'booking_setup_wizard_first_run_prompt' ) |
| 115 |
&& 'On' !== get_bk_option( 'booking_setup_wizard_page_is_completed' ); |
| 116 |
} |
| 117 |
|
| 118 |
/** |
| 119 |
* Check whether the booking-pages prompt is enabled for this first install. |
| 120 |
* |
| 121 |
* This deliberately does not inspect the Setup prompt flag. The browser needs |
| 122 |
* the cards preloaded so it can open the second dialog immediately after a |
| 123 |
* successful first-dialog dismissal. |
| 124 |
* |
| 125 |
* @return bool True when this installation owns an unconsumed pages prompt. |
| 126 |
*/ |
| 127 |
private static function is_booking_pages_prompt_enabled() { |
| 128 |
|
| 129 |
return wpbc_setup_wizard_is_initial_install_site() |
| 130 |
&& 'On' === get_bk_option( 'booking_setup_wizard_booking_pages_prompt' ); |
| 131 |
} |
| 132 |
|
| 133 |
/** |
| 134 |
* Check whether the booking-pages prompt is next in the first-run sequence. |
| 135 |
* |
| 136 |
* @return bool True after the Setup prompt has been consumed. |
| 137 |
*/ |
| 138 |
private static function is_booking_pages_prompt_pending() { |
| 139 |
|
| 140 |
return self::is_booking_pages_prompt_enabled() |
| 141 |
&& 'Off' === get_bk_option( 'booking_setup_wizard_first_run_prompt' ) |
| 142 |
&& ! empty( self::get_booking_page_cards() ); |
| 143 |
} |
| 144 |
|
| 145 |
/** |
| 146 |
* Get presentation metadata for valid public starter booking pages. |
| 147 |
* |
| 148 |
* Page existence and shortcode validation remain owned by the publishing |
| 149 |
* module. This Setup-owned mapper adds only translated onboarding copy and |
| 150 |
* resolved local previews for the allow-listed starter page purposes. |
| 151 |
* |
| 152 |
* @return array<int,array<string,string>> JSON-safe card records. |
| 153 |
*/ |
| 154 |
private static function get_booking_page_cards() { |
| 155 |
|
| 156 |
static $booking_page_cards_by_site = array(); |
| 157 |
|
| 158 |
$site_id = get_current_blog_id(); |
| 159 |
|
| 160 |
if ( array_key_exists( $site_id, $booking_page_cards_by_site ) ) { |
| 161 |
return $booking_page_cards_by_site[ $site_id ]; |
| 162 |
} |
| 163 |
|
| 164 |
$booking_page_cards_by_site[ $site_id ] = array(); |
| 165 |
|
| 166 |
if ( ! function_exists( 'wpbc_get_published_activation_booking_pages' ) ) { |
| 167 |
return $booking_page_cards_by_site[ $site_id ]; |
| 168 |
} |
| 169 |
|
| 170 |
$published_pages = wpbc_get_published_activation_booking_pages(); |
| 171 |
if ( empty( $published_pages ) || ! is_array( $published_pages ) ) { |
| 172 |
return $booking_page_cards_by_site[ $site_id ]; |
| 173 |
} |
| 174 |
|
| 175 |
$page_presentations = array( |
| 176 |
'full_day_booking' => array( |
| 177 |
'template_key' => 'dates_2_columns_hints_full_days', |
| 178 |
'description' => __( 'Try a date-based booking for stays, rentals, events, or other full-day reservations.', 'booking' ), |
| 179 |
), |
| 180 |
'appointment_booking' => array( |
| 181 |
'template_key' => 'appointments_services_flow', |
| 182 |
'description' => __( 'Try the guided service and appointment booking experience.', 'booking' ), |
| 183 |
), |
| 184 |
'time_slots_booking' => array( |
| 185 |
'template_key' => 'time_slots_2_columns_hints', |
| 186 |
'description' => __( 'Try a two-step time-slot booking with date and time selection followed by customer details.', 'booking' ), |
| 187 |
), |
| 188 |
'resource_selector_booking' => array( |
| 189 |
'image_url' => 'https://wpbookingcalendar.com/assets/template-img/wp_booking_calendar__resource_selection_card.png', |
| 190 |
'description' => __( 'Choose a Booking Resource first, then continue through its booking form.', 'booking' ), |
| 191 |
), |
| 192 |
'contact_form' => array( |
| 193 |
'template_key' => 'contact_form_simple', |
| 194 |
'description' => __( 'Preview the simple inquiry form included with your starter pages.', 'booking' ), |
| 195 |
), |
| 196 |
); |
| 197 |
|
| 198 |
foreach ( $page_presentations as $page_key => $page_presentation ) { |
| 199 |
if ( empty( $published_pages[ $page_key ] ) || ! is_array( $published_pages[ $page_key ] ) ) { |
| 200 |
continue; |
| 201 |
} |
| 202 |
|
| 203 |
$published_page = $published_pages[ $page_key ]; |
| 204 |
$image_url = isset( $page_presentation['image_url'] ) |
| 205 |
? esc_url_raw( (string) $page_presentation['image_url'] ) |
| 206 |
: ''; |
| 207 |
$template_key = isset( $page_presentation['template_key'] ) |
| 208 |
? sanitize_key( (string) $page_presentation['template_key'] ) |
| 209 |
: ''; |
| 210 |
$template_record = '' !== $template_key && function_exists( 'wpbc_get_bfb_template_record_by_key' ) |
| 211 |
? wpbc_get_bfb_template_record_by_key( $template_key ) |
| 212 |
: array(); |
| 213 |
|
| 214 |
if ( |
| 215 |
'' === $image_url |
| 216 |
&& ! empty( $template_record['picture_url'] ) |
| 217 |
&& function_exists( 'wpbc_bfb_resolve_picture_url' ) |
| 218 |
) { |
| 219 |
$image_url = esc_url_raw( wpbc_bfb_resolve_picture_url( $template_record['picture_url'] ) ); |
| 220 |
} |
| 221 |
|
| 222 |
$page_title = isset( $published_page['page_title'] ) ? (string) $published_page['page_title'] : ''; |
| 223 |
/* translators: %s: starter booking page title. */ |
| 224 |
$image_alt = sprintf( __( 'Preview of %s', 'booking' ), $page_title ); |
| 225 |
/* translators: %s: starter booking page title. */ |
| 226 |
$button_title = sprintf( __( 'Open %s', 'booking' ), $page_title ); |
| 227 |
|
| 228 |
$booking_page_cards_by_site[ $site_id ][] = array( |
| 229 |
'key' => $page_key, |
| 230 |
'url' => esc_url_raw( (string) $published_page['url'] ), |
| 231 |
'page_title' => $page_title, |
| 232 |
'button_title' => $button_title, |
| 233 |
'description' => $page_presentation['description'], |
| 234 |
'image_url' => $image_url, |
| 235 |
'image_alt' => $image_alt, |
| 236 |
); |
| 237 |
} |
| 238 |
|
| 239 |
return $booking_page_cards_by_site[ $site_id ]; |
| 240 |
} |
| 241 |
|
| 242 |
/** |
| 243 |
* Check whether the current authorized user can manually reopen starter pages. |
| 244 |
* |
| 245 |
* Automatic display remains controlled by the one-time prompt option. This |
| 246 |
* separate read-only capability keeps the approved starter-page window |
| 247 |
* available from the first-install welcome panel after that option is Off. |
| 248 |
* Updates remain excluded by the persisted initial-install marker. Live demo |
| 249 |
* sites are the only presentation-only exception: they may open existing demo |
| 250 |
* pages manually, but never enable either automatic prompt. No missing page is |
| 251 |
* created or repaired while evaluating this method. The Booking Listing route |
| 252 |
* is part of this decision so the launcher is never emitted on Timeline where |
| 253 |
* its route-scoped assets are intentionally absent. |
| 254 |
* |
| 255 |
* @return bool True when at least one validated starter page can be shown. |
| 256 |
*/ |
| 257 |
public static function can_manually_open_booking_pages_dialog() { |
| 258 |
|
| 259 |
$is_initial_install_or_demo = wpbc_setup_wizard_is_initial_install_site() |
| 260 |
|| ( function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo() ); |
| 261 |
|
| 262 |
return self::is_booking_listing_route() |
| 263 |
&& $is_initial_install_or_demo |
| 264 |
&& ! empty( self::get_booking_page_cards() ); |
| 265 |
} |
| 266 |
|
| 267 |
/** |
| 268 |
* Check whether the current request is the Booking Listing route. |
| 269 |
* |
| 270 |
* The Booking Listing controller normalizes an omitted tab into `$_REQUEST` |
| 271 |
* before administration assets are enqueued. Reading that normalized value |
| 272 |
* avoids loading the interface over a saved Timeline default. |
| 273 |
* |
| 274 |
* @return bool True when the current authorized request is Booking Listing. |
| 275 |
*/ |
| 276 |
private static function is_booking_listing_route() { |
| 277 |
|
| 278 |
if ( ! is_admin() || ! wpbc_is_bookings_page() || ! self::current_user_can_access() ) { |
| 279 |
return false; |
| 280 |
} |
| 281 |
|
| 282 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only route selection. |
| 283 |
$requested_tab = isset( $_REQUEST['tab'] ) && is_scalar( $_REQUEST['tab'] ) |
| 284 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only route selection. |
| 285 |
? sanitize_key( wp_unslash( $_REQUEST['tab'] ) ) |
| 286 |
: ''; |
| 287 |
|
| 288 |
return in_array( $requested_tab, array( '', 'vm_booking_listing' ), true ); |
| 289 |
} |
| 290 |
|
| 291 |
/** |
| 292 |
* Check whether the current request needs the popup interface. |
| 293 |
* |
| 294 |
* A pending first-run prompt can open automatically. After the starter-pages |
| 295 |
* prompt is consumed, the same interface remains available only through the |
| 296 |
* explicit welcome-panel button. Both paths retain the exact route, user, and |
| 297 |
* first-install boundaries. |
| 298 |
* |
| 299 |
* @return bool True when assets and allow-listed templates are required. |
| 300 |
*/ |
| 301 |
private static function should_render() { |
| 302 |
|
| 303 |
if ( ! self::is_booking_listing_route() ) { |
| 304 |
return false; |
| 305 |
} |
| 306 |
|
| 307 |
return self::is_setup_prompt_pending() |
| 308 |
|| self::can_manually_open_booking_pages_dialog(); |
| 309 |
} |
| 310 |
|
| 311 |
/** |
| 312 |
* Enqueue the thin browser adapter on an eligible Booking Listing request. |
| 313 |
* |
| 314 |
* @param string $where_to_load Booking Calendar asset context. |
| 315 |
* |
| 316 |
* @return void |
| 317 |
*/ |
| 318 |
public static function enqueue_js_files( $where_to_load ) { |
| 319 |
|
| 320 |
if ( self::$assets_configured || ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! self::should_render() ) { |
| 321 |
return; |
| 322 |
} |
| 323 |
|
| 324 |
$script_path = WPBC_PLUGIN_DIR . '/includes/page-setup/_out/setup_first_run_popup.js'; |
| 325 |
$version = file_exists( $script_path ) ? (string) filemtime( $script_path ) : WP_BK_VERSION_NUM; |
| 326 |
|
| 327 |
wp_enqueue_script( |
| 328 |
self::SCRIPT_HANDLE, |
| 329 |
wpbc_plugin_url( '/includes/page-setup/_out/setup_first_run_popup.js' ), |
| 330 |
array( 'jquery', 'wp-util', 'wpbc-modal' ), |
| 331 |
$version, |
| 332 |
true |
| 333 |
); |
| 334 |
|
| 335 |
$can_open_booking_pages = self::can_manually_open_booking_pages_dialog(); |
| 336 |
$booking_page_cards = $can_open_booking_pages ? self::get_booking_page_cards() : array(); |
| 337 |
|
| 338 |
wp_localize_script( |
| 339 |
self::SCRIPT_HANDLE, |
| 340 |
'wpbc_setup_wizard_first_run_popup_vars', |
| 341 |
array( |
| 342 |
'ajax_url' => admin_url( 'admin-ajax.php', 'relative' ), |
| 343 |
'setup_prompt' => array( |
| 344 |
'action' => self::AJAX_ACTION, |
| 345 |
'nonce' => wp_create_nonce( self::NONCE_ACTION ), |
| 346 |
'setup_url' => wpbc_get_setup_wizard_page_url(), |
| 347 |
'show' => self::is_setup_prompt_pending(), |
| 348 |
), |
| 349 |
'booking_pages_prompt' => array( |
| 350 |
'action' => self::BOOKING_PAGES_AJAX_ACTION, |
| 351 |
'nonce' => wp_create_nonce( self::BOOKING_PAGES_NONCE_ACTION ), |
| 352 |
'available' => $can_open_booking_pages, |
| 353 |
'show' => self::is_booking_pages_prompt_pending(), |
| 354 |
'booking_pages' => $booking_page_cards, |
| 355 |
), |
| 356 |
) |
| 357 |
); |
| 358 |
|
| 359 |
self::$assets_configured = true; |
| 360 |
} |
| 361 |
|
| 362 |
/** |
| 363 |
* Enqueue route-scoped popup presentation styles. |
| 364 |
* |
| 365 |
* @param string $where_to_load Booking Calendar asset context. |
| 366 |
* |
| 367 |
* @return void |
| 368 |
*/ |
| 369 |
public static function enqueue_css_files( $where_to_load ) { |
| 370 |
|
| 371 |
if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! self::should_render() ) { |
| 372 |
return; |
| 373 |
} |
| 374 |
|
| 375 |
$style_path = WPBC_PLUGIN_DIR . '/includes/page-setup/_out/setup_first_run_popup.css'; |
| 376 |
$version = file_exists( $style_path ) ? (string) filemtime( $style_path ) : WP_BK_VERSION_NUM; |
| 377 |
|
| 378 |
wp_enqueue_style( |
| 379 |
self::STYLE_HANDLE, |
| 380 |
wpbc_plugin_url( '/includes/page-setup/_out/setup_first_run_popup.css' ), |
| 381 |
array(), |
| 382 |
$version |
| 383 |
); |
| 384 |
} |
| 385 |
|
| 386 |
/** |
| 387 |
* Render the Setup-owned, allow-listed WordPress template. |
| 388 |
* |
| 389 |
* @param string $page Booking Calendar footer template context. |
| 390 |
* |
| 391 |
* @return void |
| 392 |
*/ |
| 393 |
public static function render_template( $page ) { |
| 394 |
|
| 395 |
if ( 'wpbc-ajx_booking' !== $page || ! self::should_render() ) { |
| 396 |
return; |
| 397 |
} |
| 398 |
|
| 399 |
$template_paths = array( |
| 400 |
WPBC_PLUGIN_DIR . '/includes/page-setup/templates/first-run-popup-wptpl.php', |
| 401 |
WPBC_PLUGIN_DIR . '/includes/page-setup/templates/booking-pages-popup-wptpl.php', |
| 402 |
); |
| 403 |
|
| 404 |
foreach ( $template_paths as $template_path ) { |
| 405 |
if ( is_readable( $template_path ) ) { |
| 406 |
require $template_path; |
| 407 |
} |
| 408 |
} |
| 409 |
} |
| 410 |
|
| 411 |
/** |
| 412 |
* Persist that the first-run prompt must not be shown again. |
| 413 |
* |
| 414 |
* Both the start and dismiss choices consume the one-time prompt. Starting the |
| 415 |
* wizard does not mark Setup complete; completion remains owned by its existing |
| 416 |
* step workflow. |
| 417 |
* |
| 418 |
* @return void |
| 419 |
*/ |
| 420 |
public static function ajax_dismiss() { |
| 421 |
|
| 422 |
if ( ! check_ajax_referer( self::NONCE_ACTION, 'nonce', false ) ) { |
| 423 |
wp_send_json_error( array( 'message' => __( 'Security check failed.', 'booking' ) ), 403 ); |
| 424 |
} |
| 425 |
|
| 426 |
if ( ! self::current_user_can_access() ) { |
| 427 |
wp_send_json_error( array( 'message' => __( 'You do not have access to Initial Setup.', 'booking' ) ), 403 ); |
| 428 |
} |
| 429 |
|
| 430 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above with check_ajax_referer(). |
| 431 |
$choice = isset( $_POST['choice'] ) && is_scalar( $_POST['choice'] ) |
| 432 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above with check_ajax_referer(). |
| 433 |
? sanitize_key( wp_unslash( $_POST['choice'] ) ) |
| 434 |
: ''; |
| 435 |
|
| 436 |
if ( ! in_array( $choice, array( 'dismiss', 'start' ), true ) ) { |
| 437 |
wp_send_json_error( array( 'message' => __( 'The Initial Setup choice is not valid.', 'booking' ) ), 400 ); |
| 438 |
} |
| 439 |
|
| 440 |
if ( ! wpbc_setup_wizard_is_initial_install_site() ) { |
| 441 |
wp_send_json_error( array( 'message' => __( 'The Initial Setup prompt is not available for this installation.', 'booking' ) ), 409 ); |
| 442 |
} |
| 443 |
|
| 444 |
update_bk_option( 'booking_setup_wizard_first_run_prompt', 'Off' ); |
| 445 |
if ( 'Off' !== get_bk_option( 'booking_setup_wizard_first_run_prompt' ) ) { |
| 446 |
wp_send_json_error( array( 'message' => __( 'The Initial Setup choice could not be saved.', 'booking' ) ), 500 ); |
| 447 |
} |
| 448 |
|
| 449 |
wp_send_json_success( array( 'choice' => $choice ) ); |
| 450 |
} |
| 451 |
|
| 452 |
/** |
| 453 |
* Permanently dismiss the first-install booking-pages prompt. |
| 454 |
* |
| 455 |
* The endpoint is intentionally idempotent. Closing the dialog twice because |
| 456 |
* of overlapping browser events still leaves the one-time option safely Off. |
| 457 |
* |
| 458 |
* @return void |
| 459 |
*/ |
| 460 |
public static function ajax_dismiss_booking_pages_prompt() { |
| 461 |
|
| 462 |
if ( ! check_ajax_referer( self::BOOKING_PAGES_NONCE_ACTION, 'nonce', false ) ) { |
| 463 |
wp_send_json_error( array( 'message' => __( 'Security check failed.', 'booking' ) ), 403 ); |
| 464 |
} |
| 465 |
|
| 466 |
if ( ! self::current_user_can_access() ) { |
| 467 |
wp_send_json_error( array( 'message' => __( 'You do not have access to Initial Setup.', 'booking' ) ), 403 ); |
| 468 |
} |
| 469 |
|
| 470 |
if ( ! wpbc_setup_wizard_is_initial_install_site() ) { |
| 471 |
wp_send_json_error( array( 'message' => __( 'The starter-pages prompt is not available for this installation.', 'booking' ) ), 409 ); |
| 472 |
} |
| 473 |
|
| 474 |
if ( 'Off' === get_bk_option( 'booking_setup_wizard_booking_pages_prompt' ) ) { |
| 475 |
wp_send_json_success( array( 'dismissed' => true ) ); |
| 476 |
} |
| 477 |
|
| 478 |
if ( 'Off' !== get_bk_option( 'booking_setup_wizard_first_run_prompt' ) ) { |
| 479 |
wp_send_json_error( array( 'message' => __( 'Finish the Initial Setup choice before dismissing starter pages.', 'booking' ) ), 409 ); |
| 480 |
} |
| 481 |
|
| 482 |
update_bk_option( 'booking_setup_wizard_booking_pages_prompt', 'Off' ); |
| 483 |
if ( 'Off' !== get_bk_option( 'booking_setup_wizard_booking_pages_prompt' ) ) { |
| 484 |
wp_send_json_error( array( 'message' => __( 'The starter-pages choice could not be saved.', 'booking' ) ), 500 ); |
| 485 |
} |
| 486 |
|
| 487 |
wp_send_json_success( array( 'dismissed' => true ) ); |
| 488 |
} |
| 489 |
} |
| 490 |
|
| 491 |
WPBC_Setup_Wizard_First_Run_Popup::init(); |
| 492 |
|