| 1 |
<?php /** |
| 2 |
* @version 1.0 |
| 3 |
* @description Support functions for the 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 |
/** |
| 17 |
* Do we need to start 'Setup Wizard' ? |
| 18 |
* |
| 19 |
* @return bool |
| 20 |
*/ |
| 21 |
function wpbc_setup_wizard_page__is_need_start(){ |
| 22 |
|
| 23 |
if ( wpbc_setup_wizard_page__is_all_steps_completed() ) { |
| 24 |
return false; // Wizard Completed! |
| 25 |
} |
| 26 |
|
| 27 |
// Some steps were not completed or wizard was not started at all |
| 28 |
|
| 29 |
$days_num_ago = wpbc_how_old_in_days(); |
| 30 |
|
| 31 |
// No bookings, so maybe need to start |
| 32 |
if ( - 1 === $days_num_ago ) { |
| 33 |
return true; |
| 34 |
} |
| 35 |
|
| 36 |
// If older than 3 days ago, then no need to start ! |
| 37 |
if ( $days_num_ago < 3 ){ |
| 38 |
return true; |
| 39 |
} |
| 40 |
|
| 41 |
// No need to start, because this installation already OLD |
| 42 |
return false; |
| 43 |
} |
| 44 |
|
| 45 |
/** |
| 46 |
* Do we need to Continue 'Setup Wizard' or all steps already completed ? |
| 47 |
* |
| 48 |
* @return bool |
| 49 |
*/ |
| 50 |
function wpbc_setup_wizard_page__is_all_steps_completed() { |
| 51 |
|
| 52 |
$setup_steps = new WPBC_SETUP_WIZARD_STEPS(); |
| 53 |
|
| 54 |
$is_all_steps_completed = $setup_steps->db__is_all_steps_completed(); |
| 55 |
|
| 56 |
return $is_all_steps_completed; |
| 57 |
} |
| 58 |
|
| 59 |
|
| 60 |
/** |
| 61 |
* Check whether the Setup Wizard has started and is not yet complete. |
| 62 |
* |
| 63 |
* Explicit Setup Wizard requests count as active before the first step has |
| 64 |
* been saved. Persisted completed steps keep the wizard active while the user |
| 65 |
* visits another Booking Calendar administration page. A completed or skipped |
| 66 |
* wizard is not considered in progress. |
| 67 |
* |
| 68 |
* @return bool True while an unfinished Setup Wizard is in progress. |
| 69 |
*/ |
| 70 |
function wpbc_setup_wizard_page__is_in_progress() { |
| 71 |
|
| 72 |
if ( wpbc_setup_wizard_page__is_all_steps_completed() ) { |
| 73 |
return false; |
| 74 |
} |
| 75 |
|
| 76 |
if ( function_exists( 'wpbc_is_setup_wizard_page' ) && wpbc_is_setup_wizard_page() ) { |
| 77 |
return true; |
| 78 |
} |
| 79 |
|
| 80 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only UI context. |
| 81 |
$setup_context = isset( $_GET['wpbc_setup'] ) && is_scalar( $_GET['wpbc_setup'] ) |
| 82 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only UI context. |
| 83 |
? sanitize_text_field( wp_unslash( $_GET['wpbc_setup'] ) ) |
| 84 |
: ''; |
| 85 |
|
| 86 |
if ( '1' === $setup_context ) { |
| 87 |
return true; |
| 88 |
} |
| 89 |
|
| 90 |
$steps_is_done = get_bk_option( 'booking_setup_wizard_page_steps_is_done' ); |
| 91 |
|
| 92 |
if ( ! is_array( $steps_is_done ) ) { |
| 93 |
return false; |
| 94 |
} |
| 95 |
|
| 96 |
foreach ( $steps_is_done as $is_step_done ) { |
| 97 |
if ( ! empty( $is_step_done ) ) { |
| 98 |
return true; |
| 99 |
} |
| 100 |
} |
| 101 |
|
| 102 |
return false; |
| 103 |
} |
| 104 |
|
| 105 |
|
| 106 |
/** |
| 107 |
* Check whether the current request explicitly targets one Setup Wizard step. |
| 108 |
* |
| 109 |
* This read-only request check is intentionally independent from saved wizard |
| 110 |
* completion state. It lets an authorized user follow an explicit external |
| 111 |
* setup URL without causing ordinary administration-page visits to reopen the |
| 112 |
* completed wizard. |
| 113 |
* |
| 114 |
* @param string $step_name Expected Setup Wizard step identifier. |
| 115 |
* |
| 116 |
* @return bool True when the current URL explicitly requests the step. |
| 117 |
*/ |
| 118 |
function wpbc_setup_wizard_page__has_explicit_step_context( $step_name ) { |
| 119 |
|
| 120 |
$step_name = sanitize_key( (string) $step_name ); |
| 121 |
|
| 122 |
if ( '' === $step_name ) { |
| 123 |
return false; |
| 124 |
} |
| 125 |
|
| 126 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only UI context. |
| 127 |
$setup_context = isset( $_GET['wpbc_setup'] ) && is_scalar( $_GET['wpbc_setup'] ) |
| 128 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only UI context. |
| 129 |
? sanitize_text_field( wp_unslash( $_GET['wpbc_setup'] ) ) |
| 130 |
: ''; |
| 131 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only UI context. |
| 132 |
$request_step = isset( $_GET['wpbc_setup_step'] ) && is_scalar( $_GET['wpbc_setup_step'] ) |
| 133 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only UI context. |
| 134 |
? sanitize_key( wp_unslash( $_GET['wpbc_setup_step'] ) ) |
| 135 |
: ''; |
| 136 |
|
| 137 |
return '1' === $setup_context && $step_name === $request_step; |
| 138 |
} |
| 139 |
|
| 140 |
|
| 141 |
/** |
| 142 |
* Check whether the current request is one explicit external Setup Wizard step. |
| 143 |
* |
| 144 |
* The setup context flag prevents ordinary visits to the same administration |
| 145 |
* page from receiving wizard-only defaults. |
| 146 |
* |
| 147 |
* @param string $step_name Expected Setup Wizard step identifier. |
| 148 |
* |
| 149 |
* @return bool True when the unfinished wizard explicitly requested the step. |
| 150 |
*/ |
| 151 |
function wpbc_setup_wizard_page__is_active_step( $step_name ) { |
| 152 |
|
| 153 |
$step_name = sanitize_key( (string) $step_name ); |
| 154 |
|
| 155 |
if ( '' === $step_name || ! wpbc_setup_wizard_page__is_in_progress() ) { |
| 156 |
return false; |
| 157 |
} |
| 158 |
|
| 159 |
return wpbc_setup_wizard_page__has_explicit_step_context( $step_name ); |
| 160 |
} |
| 161 |
|
| 162 |
/** |
| 163 |
* Is user can access Wizard Setup page ? |
| 164 |
* @return bool |
| 165 |
*/ |
| 166 |
function wpbc_is_user_can_access_wizard_page() { |
| 167 |
$is_user_can_access_wizard_page = true; |
| 168 |
if ( class_exists( 'wpdev_bk_multiuser' ) ) { |
| 169 |
|
| 170 |
$real_current_user_id = get_current_user_id(); // Is current user suer booking admin and if this user was simulated log in |
| 171 |
$is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $real_current_user_id ); |
| 172 |
if ( ! $is_user_super_admin ) { |
| 173 |
$is_user_can_access_wizard_page = false; |
| 174 |
} |
| 175 |
} |
| 176 |
|
| 177 |
return $is_user_can_access_wizard_page; |
| 178 |
} |
| 179 |
|
| 180 |
|
| 181 |
// ===================================================================================================================== |
| 182 |
// == Shortcodes Content == |
| 183 |
// ===================================================================================================================== |
| 184 |
|
| 185 |
/** |
| 186 |
* Get "Booking Form" Shortcode Content |
| 187 |
* |
| 188 |
* @param $resource_id |
| 189 |
* |
| 190 |
* @return false|string |
| 191 |
*/ |
| 192 |
function wpbc_setup_wizard_page__get_shortcode_html( $resource_id = 1 , $is_show_only_calendar = false ) { |
| 193 |
|
| 194 |
ob_start(); |
| 195 |
|
| 196 |
$localized_js_vars_script = wpbc_get_localized_js_vars(); |
| 197 |
|
| 198 |
if ( $is_show_only_calendar ) { |
| 199 |
// Center calendar. |
| 200 |
?><style type="text/css"> |
| 201 |
.wpbc_calendar_wraper { |
| 202 |
display: flex; |
| 203 |
flex-flow: column nowrap; |
| 204 |
align-items: center; |
| 205 |
justify-content: flex-start; |
| 206 |
} |
| 207 |
.wpbc_calendar_wraper div { |
| 208 |
margin-bottom: 10px; |
| 209 |
} |
| 210 |
</style> |
| 211 |
<div class="wpbc_shortcode_container"><?php |
| 212 |
echo do_shortcode( '[bookingcalendar resource_id=' . $resource_id . ']' ); |
| 213 |
?></div><?php |
| 214 |
|
| 215 |
// If we use the [bookingcalendar] shortcode, then we remove this tag, for ability to select dates in calendar. |
| 216 |
?><script tye="text/javascript"> |
| 217 |
jQuery(document).ready(function(){ |
| 218 |
<?php |
| 219 |
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 220 |
echo $localized_js_vars_script; |
| 221 |
?> |
| 222 |
jQuery( 'body' ).on( 'wpbc_calendar_ajx__loaded_data', function( event, resource_id ) { |
| 223 |
jQuery( '#calendar_booking_unselectable' + resource_id ).remove(); |
| 224 |
} ); |
| 225 |
}); |
| 226 |
</script><?php |
| 227 |
|
| 228 |
} else { |
| 229 |
|
| 230 |
// Help message |
| 231 |
?><div class="wpbc-settings-notice notice-warning notice-helpful-info" style="padding: 8px 20px;font-size: 14px;margin: 0 auto;max-width: Min(54em,100%);"> |
| 232 |
<strong><?php esc_html_e('Note','booking'); ?>: </strong> |
| 233 |
<?php |
| 234 |
esc_html_e( 'This is a preview of your booking form.', 'booking' ); echo ' '; |
| 235 |
esc_html_e( 'You can adjust settings in the widgets on the right side of the page.', 'booking' ); |
| 236 |
//echo '<a href="' . esc_attr( function_exists( 'wpbc_get_general_availability_url' ) ? wpbc_get_general_availability_url() : admin_url( 'admin.php?page=wpbc-availability&tab=general_availability' ) ) . '">Availability > General Availability</a>'; |
| 237 |
?> |
| 238 |
</div><?php |
| 239 |
|
| 240 |
// If we use the [bookingcalendar] shortcode, then we remove this tag, for ability to select dates in calendar. |
| 241 |
?><script type="text/javascript"> |
| 242 |
jQuery( document ).ready( function () { |
| 243 |
<?php |
| 244 |
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 245 |
echo $localized_js_vars_script; |
| 246 |
?> |
| 247 |
_wpbc.set_other_param( 'calendars__on_this_page', [] ); |
| 248 |
<?php if ( 'On' === get_bk_option( 'booking_timeslot_picker') ) { ?> |
| 249 |
wpbc_hook__init_timeselector(); |
| 250 |
<?php } ?> |
| 251 |
wpbc_hook__init_booking_form_wizard_buttons(); |
| 252 |
// wpbc__calendar__change_skin( '<?php echo esc_url( WPBC_PLUGIN_URL . get_bk_option( 'booking_skin' ) ); ?>' ); |
| 253 |
// wpbc__css__change_skin( '<?php echo esc_url( WPBC_PLUGIN_URL . get_bk_option( 'booking_timeslot_picker_skin' ) ); ?>' ); |
| 254 |
<?php if ('wpbc_theme_dark_1' === get_bk_option( 'booking_form_theme' ) ){ ?> |
| 255 |
jQuery( '.wpbc_widget_preview_booking_form .wpbc_center_preview,.wpbc_widget_preview_booking_form .wpbc_container.wpbc_container_booking_form,.wpbc_widget_preview_booking_form .wpbc_widget_content' ).addClass( 'wpbc_theme_dark_1' ); |
| 256 |
<?php } ?> |
| 257 |
if ( 'function' === typeof( wpbc_update_capacity_hint ) ) { |
| 258 |
jQuery( '.booking_form_div' ).on( 'wpbc_booking_date_or_option_selected', function ( event, resource_id ) { |
| 259 |
wpbc_update_capacity_hint( resource_id ); |
| 260 |
} ); |
| 261 |
} |
| 262 |
//jQuery( 'body' ).on( 'wpbc_datepick_inline_calendar_loaded', function ( event, resource_id, jCalContainer, inst ) { }); |
| 263 |
// jQuery( 'body' ).off( 'wpbc_calendar_ajx__loaded_data' ); |
| 264 |
// jQuery( 'body' ).on( 'wpbc_calendar_ajx__loaded_data', function ( event, loaded_resource_id ){ |
| 265 |
// // wpbc_blink_element( '.wpbc_widget_change_form_structure', 3, 220 ); |
| 266 |
// wpbc_blink_element( '#ui_btn_cstm__set_booking_form_template_pro', 2, 220 ); |
| 267 |
// wpbc_blink_element( '#ui_btn_cstm__set_booking_form_template_apply', 4, 220 ); |
| 268 |
// }); |
| 269 |
|
| 270 |
// jQuery( 'body' ).on( 'wpbc_calendar_ajx__before_loaded_data', function( event, resource_id ) { |
| 271 |
// wpbc_calendar__loading__stop( resource_id ); |
| 272 |
// } ); |
| 273 |
}); |
| 274 |
//if ( 'undefined' !== typeof _wpbc ) { |
| 275 |
// <?php |
| 276 |
// echo "_wpbc.set_other_param( 'availability__week_days_unavailable', [" |
| 277 |
// . ( ( get_bk_option( 'booking_unavailable_day0') == 'On' ) ? '0,' : '' ) |
| 278 |
// . ( ( get_bk_option( 'booking_unavailable_day1') == 'On' ) ? '1,' : '' ) |
| 279 |
// . ( ( get_bk_option( 'booking_unavailable_day2') == 'On' ) ? '2,' : '' ) |
| 280 |
// . ( ( get_bk_option( 'booking_unavailable_day3') == 'On' ) ? '3,' : '' ) |
| 281 |
// . ( ( get_bk_option( 'booking_unavailable_day4') == 'On' ) ? '4,' : '' ) |
| 282 |
// . ( ( get_bk_option( 'booking_unavailable_day5') == 'On' ) ? '5,' : '' ) |
| 283 |
// . ( ( get_bk_option( 'booking_unavailable_day6') == 'On' ) ? '6,' : '' ) |
| 284 |
// . "999] ); "; |
| 285 |
// ?> |
| 286 |
//} |
| 287 |
</script><?php |
| 288 |
|
| 289 |
?><div class="wpbc_shortcode_container"><?php |
| 290 |
echo do_shortcode( '[booking resource_id=' . $resource_id . ']' ); |
| 291 |
?></div><?php |
| 292 |
|
| 293 |
|
| 294 |
} |
| 295 |
|
| 296 |
return ob_get_clean(); |
| 297 |
} |
| 298 |
|
| 299 |
|
| 300 |
|
| 301 |
function wpbc_setup_wizard_page__get_left_navigation_menu_arr(){ |
| 302 |
|
| 303 |
$navigation_menu_arr = array(); |
| 304 |
$setup_steps = new WPBC_SETUP_WIZARD_STEPS(); |
| 305 |
|
| 306 |
foreach ( array_keys( $setup_steps->get_steps_arr() ) as $step_name ) { |
| 307 |
$navigation_menu_arr[ $step_name ] = array( |
| 308 |
'title' => function_exists( 'wpbc_setup_wizard__get_step_title' ) ? wpbc_setup_wizard__get_step_title( $step_name ) : $step_name, |
| 309 |
'icon' => 'wpbc_icn_circle_outline', |
| 310 |
'class' => '', |
| 311 |
'action' => "wpbc_ajx__setup_wizard_page__send_request_with_params( { 'current_step':'" . esc_js( $step_name ) . "' } );", |
| 312 |
); |
| 313 |
} |
| 314 |
|
| 315 |
return $navigation_menu_arr; |
| 316 |
} |
| 317 |
|
| 318 |
|
| 319 |
/** |
| 320 |
* Show Warning Conflict with "Wordfence" plugin |
| 321 |
* |
| 322 |
* @return void |
| 323 |
*/ |
| 324 |
function wpbc_maybe_show_warning_conflict__wordfence( $style = '' ) { |
| 325 |
if ( class_exists( 'wordfence' ) ) { |
| 326 |
|
| 327 |
$is_panel_visible = wpbc_is_dismissed_panel_visible( 'wpbc_show_warning_wordfence' ); // FixIn: 9.9.0.8. |
| 328 |
if ( $is_panel_visible ) { |
| 329 |
?><div id="wpbc_show_warning_wordfence" class="wpbc-settings-notice notice-error notice-helpful-info0" |
| 330 |
style="max-width: Min(450px, 100%);margin: auto;padding: 4px 15px 7px 20px;font-size: 14px;line-height: 28px;margin-bottom: 25px; display: flex;flex-flow:row nowrap;justify-content: space-between;align-items: flex-start;border-left-color: #e2892b;<?php echo esc_attr( $style ); ?>" |
| 331 |
> |
| 332 |
<div> |
| 333 |
<span style="margin: 0 5px 0 0;color: #e2892b;" ><i class="menu_icon icon-1x wpbc_icn_warning_amber"></i></span> |
| 334 |
<?php |
| 335 |
echo '<strong>' . esc_html__('Important!' ,'booking') . '</strong> ' ; |
| 336 |
// FixIn: 10.9.1.1. |
| 337 |
/* translators: 1: ... */ |
| 338 |
echo wp_kses_post( sprintf( __( 'We detect that you use %s plugin.', 'booking' ), '<strong>Wordfence</strong>' ) ); |
| 339 |
|
| 340 |
echo '<br>'; |
| 341 |
|
| 342 |
/* translators: 1: ... */ |
| 343 |
echo wp_kses_post( sprintf( __( 'If you encounter any issues, follow this %1$stroubleshooting instruction%2$s.', 'booking' ), |
| 344 |
'<a href="https://wpbookingcalendar.com/faq/setup-wizard-on-step-4-keeps-going-to-blank-page/" target="_blank" style="font-weight:600;text-underline-offset: 3px;text-decoration-thickness: 0px;text-decoration-style: dashed;">', '</a>' ) ); |
| 345 |
?> |
| 346 |
</div> |
| 347 |
<div><?php |
| 348 |
ob_start(); |
| 349 |
$is_panel_visible = wpbc_is_dismissed( 'wpbc_show_warning_wordfence', array( |
| 350 |
'title' => '<i class="menu_icon icon-1x wpbc_icn_close"></i> ', |
| 351 |
'hint' => __( 'Dismiss', 'booking' ), |
| 352 |
'class' => 'wpbc_panel_get_started_dismiss', |
| 353 |
'css' => 'background: #fff;border-radius: 7px;' |
| 354 |
)); |
| 355 |
|
| 356 |
$dismiss_x_button = ob_get_clean(); |
| 357 |
|
| 358 |
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped |
| 359 |
echo wpbc_replace__js_scripts__to__tpl_scripts( $dismiss_x_button ); |
| 360 |
|
| 361 |
?></div> |
| 362 |
</div><?php |
| 363 |
} |
| 364 |
|
| 365 |
|
| 366 |
|
| 367 |
} |
| 368 |
} |
| 369 |
|
| 370 |
|
| 371 |
/** |
| 372 |
* Escape scripts from the Booking Calendar shortcode content for showing in Wizard templates. |
| 373 |
* |
| 374 |
* @param string $calendar_html_content - usualy it is the content of [booking ...] shortcode. |
| 375 |
* |
| 376 |
* @return mixed |
| 377 |
*/ |
| 378 |
function wpbc_clean_calendar_loading_scripts( $calendar_html_content ) { |
| 379 |
|
| 380 |
// Prevent of any intention usage od this tag. |
| 381 |
$calendar_html_content = str_replace( 'ajax_scrpt', '', $calendar_html_content ); |
| 382 |
|
| 383 |
$pattern = '/<script\s*(type=[\'"]+text\/javascript[\'"]+)?\s*>/i'; |
| 384 |
$calendar_html_content = preg_replace( $pattern, '<ajax_scrpt>', $calendar_html_content ); |
| 385 |
|
| 386 |
$pattern = '/<\/script>/i'; |
| 387 |
$calendar_html_content = preg_replace( $pattern, '</ajax_scrpt>', $calendar_html_content ); |
| 388 |
|
| 389 |
return $calendar_html_content; |
| 390 |
} |
| 391 |
|