PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
11.9 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 All 205 releases
← All changes | includes/ui_settings/parts/ui__nav_top.php +255 -32 10.15.7 → 11.9 View file →
@@ -1,4 +1,4 @@
1 1 <?php
2 2 /**
3 3 * Admin Panel UI - Parts
4 4 *
@@ -26,9 +26,10 @@
26 26 */
27 27 function wpbc_ui__top_nav( $args = array() ) {
28 28
29 29 $defaults = array(
30 - 'attr' => array(),
30 + 'attr' => array(),
31 + 'is_full_screen_user_mode_enabled' => true,
31 32 );
32 33 $params = wp_parse_args( $args, $defaults );
33 34
34 35 echo '<div class="wpbc_ui_el wpbc_ui_el__top_nav">';
@@ -60,16 +61,58 @@
60 61 wpbc_ui_el__divider_vertical( array( 'class' => 'wpbc_ui_el__vertical_line wpbc_ui__top_nav__btn_show_right_vertical_nav_divider' ) );
61 62
62 63
63 64 // Full Screen Buttons.
64 - wpbc_ui__top_nav__btn_full_screen();
65 - wpbc_ui__top_nav__btn_normal_screen();
65 + wpbc_ui__top_nav__btn_full_screen( $params );
66 + wpbc_ui__top_nav__btn_normal_screen( $params );
66 67
67 68 echo '</div>';
68 69 }
69 70
70 71
72 +/**
73 + * Order validated starter pages for the Booking Calendar top dropdown.
74 + *
75 + * The publishing module remains responsible for discovering valid pages. This
76 + * helper controls presentation only and appends unknown future page purposes in
77 + * their original order so new integrations are not hidden.
78 + *
79 + * @param array $wpbc_starter_pages Validated starter pages keyed by purpose.
80 + *
81 + * @return array Starter pages in top-dropdown display order.
82 + */
83 +function wpbc_ui__top_nav__order_starter_pages( $wpbc_starter_pages ) {
71 84
85 + if ( empty( $wpbc_starter_pages ) || ! is_array( $wpbc_starter_pages ) ) {
86 + return array();
87 + }
88 +
89 + $preferred_page_order = array(
90 + 'full_day_booking',
91 + 'appointment_booking',
92 + 'time_slots_booking',
93 + 'resource_selector_booking',
94 + 'contact_form',
95 + );
96 + $ordered_starter_pages = array();
97 +
98 + foreach ( $preferred_page_order as $page_key ) {
99 + if ( array_key_exists( $page_key, $wpbc_starter_pages ) ) {
100 + $ordered_starter_pages[ $page_key ] = $wpbc_starter_pages[ $page_key ];
101 + }
102 + }
103 +
104 + foreach ( $wpbc_starter_pages as $page_key => $wpbc_starter_page ) {
105 + if ( ! array_key_exists( $page_key, $ordered_starter_pages ) ) {
106 + $ordered_starter_pages[ $page_key ] = $wpbc_starter_page;
107 + }
108 + }
109 +
110 + return $ordered_starter_pages;
111 +}
112 +
113 +
114 +
72 115 /**
73 116 * Show element - "WPBC - Main Dropdown"
74 117 *
75 118 * @return void
@@ -80,17 +123,11 @@
80 123 $svg_icon_style = 'margin:5px 5px 0 0;'; // 'background-position: 0 0;background-size: ' . $svg_size . ' ' . $svg_size . ';width: ' . $svg_size . ';height: ' . $svg_size . ';'; //.
81 124 $svg_icon = wpbc_get_svg_logo_for_background( '#555', '#e5e5e5', '1.0' );
82 125
83 126 $wpbc_starter_pages = function_exists( 'wpbc_get_published_activation_booking_pages' ) ? wpbc_get_published_activation_booking_pages() : array();
127 + $wpbc_starter_pages = wpbc_ui__top_nav__order_starter_pages( $wpbc_starter_pages );
84 128 $wp_post_booking_absolute = false;
85 129
86 - if (
87 - empty( $wpbc_starter_pages ) &&
88 - function_exists( 'wpbc_stp_wiz__is_exist_published_page_with_booking_form' )
89 - ) {
90 - $wp_post_booking_absolute = wpbc_stp_wiz__is_exist_published_page_with_booking_form();
91 - }
92 -
93 130 $el_arr = array(
94 131 // 'title' => 'Booking Calendar',
95 132 // 'font_icon' => 'wpbc-bi-calendar2-range',
96 133 'title_html' => '<span class="nav-tab-text" style="margin: -3px 0 0 5px;font-size: 16px;padding: 0;"><span style="position: absolute;font-size: 7px;margin-top: 13px;margin-left: 1px;">WP</span>Booking Calendar</span>',
@@ -126,8 +163,14 @@
126 163 'title' => $wpbc_starter_page_title,
127 164 'url' => esc_url( $wpbc_starter_page['url'] ),
128 165 );
129 166 }
167 +
168 + $el_arr['items'][] = array(
169 + 'type' => 'link',
170 + 'title' => __( 'Visit Home Page', 'booking' ),
171 + 'url' => esc_url( home_url( '/' ) ),
172 + );
130 173 } elseif ( ! empty( $wp_post_booking_absolute ) ) {
131 174 $el_arr['items'][] = array(
132 175 'type' => 'header',
133 176 'title' => __( 'Visit Booking Page', 'booking' ),
@@ -136,8 +179,13 @@
136 179 'type' => 'link',
137 180 'title' => __( 'Go to page with booking form', 'booking' ),
138 181 'url' => esc_url( $wp_post_booking_absolute ),
139 182 );
183 + $el_arr['items'][] = array(
184 + 'type' => 'link',
185 + 'title' => __( 'Visit Home Page', 'booking' ),
186 + 'url' => esc_url( home_url( '/' ) ),
187 + );
140 188 }
141 189 $el_arr['items'][] = array(
142 190 'type' => 'header',
143 191 'title' => __( 'Help', 'booking' ),
@@ -169,9 +217,9 @@
169 217 'url' => 'https://wpbookingcalendar.com/wn/',
170 218 );
171 219 $el_arr['items'][] = array(
172 220 'type' => 'link',
173 - 'title' => __( 'What\'s New', 'booking' ) . ' <span style="float:right">' . wpbc_dashboard_info_get_version_number() . '</span>',
221 + 'title' => __( 'What\'s New', 'booking' ) . ' <span style="float:right">' . esc_attr( WP_BK_VERSION_NUM ) . '</span>',
174 222 'url' => esc_url( admin_url( add_query_arg( array( 'page' => 'wpbc-about' ), 'index.php' ) ) ),
175 223 );
176 224 // $el_arr['items'][] = array(
177 225 // 'type' => 'link',
@@ -205,14 +253,18 @@
205 253 * Show element - "Full Screen"
206 254 *
207 255 * @return void
208 256 */
209 -function wpbc_ui__top_nav__btn_full_screen() {
257 +function wpbc_ui__top_nav__btn_full_screen( $args = array() ) {
210 258
259 + $defaults = array(
260 + 'is_full_screen_user_mode_enabled' => true,
261 + );
262 + $params = wp_parse_args( $args, $defaults );
263 +
211 264 $el_arr = array();
212 265
213 - $el_arr['onclick'] = "jQuery( '.wpbc_ui__top_nav__btn_full_screen,.wpbc_ui__top_nav__btn_normal_screen' ).toggleClass( 'wpbc_ui__hide' );";
214 - $el_arr['onclick'] .= "jQuery('body').toggleClass('wpbc_admin_full_screen');wpbc_check_full_screen_mode();";
266 + $el_arr['onclick'] = 'wpbc_admin_ui__full_screen__do_on( this, ' . ( $params['is_full_screen_user_mode_enabled'] ? 'true' : 'false' ) . ' );';
215 267
216 268 $el_arr['font_icon'] = 'wpbc-bi-arrows-fullscreen';
217 269 $el_arr['hint'] = array(
218 270 'title' => __( 'Full Screen', 'booking' ),
@@ -220,9 +272,9 @@
220 272 );
221 273
222 274 $el_arr['container_class'] = 'wpbc_ui__top_nav__btn_full_screen';
223 275
224 - if ( ! wpbc_is_setup_wizard_page() ) {
276 + if ( ( ! wpbc_is_setup_wizard_page() ) && ( $params['is_full_screen_user_mode_enabled'] ) ) {
225 277
226 278 // Params for saving user option.
227 279 $user_cust_option = 'is_full_screen';
228 280 $nonce_action = $user_cust_option . '_nonce_act';
@@ -233,14 +285,12 @@
233 285 'data-wpbc-u-save-nonce' => wp_create_nonce( $nonce_action ), // do not need to make escaping the values because: wpbc_get_custom_attr() should handle escaping.
234 286 'data-wpbc-u-save-user-id' => wpbc_get_current_user_id(),
235 287 'data-wpbc-u-save-action' => $nonce_action,
236 288 );
237 - $el_arr['onclick'] .= 'wpbc_save_custom_user_data_from_element(this);';
238 -
239 289 ?><script type="text/javascript"><?php
240 290
241 291 $is_full_screen = WPBC_User_Custom_Data_Saver::get_user_data_value( wpbc_get_current_user_id(), $user_cust_option );
242 - $is_full_screen = ( 'On' === $is_full_screen );
292 + $is_full_screen = ( 'On' === wpbc_ui__get_full_screen_mode_from_cookie( $is_full_screen ) );
243 293
244 294 echo wpbc_jq_ready_start(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
245 295
246 296 if ( $is_full_screen ) {
@@ -259,14 +309,18 @@
259 309 * Show element - "Normal Screen"
260 310 *
261 311 * @return void
262 312 */
263 -function wpbc_ui__top_nav__btn_normal_screen() {
313 +function wpbc_ui__top_nav__btn_normal_screen( $args = array() ) {
264 314
315 + $defaults = array(
316 + 'is_full_screen_user_mode_enabled' => true,
317 + );
318 + $params = wp_parse_args( $args, $defaults );
319 +
265 320 $el_arr = array();
266 321
267 - $el_arr['onclick'] = "jQuery( '.wpbc_ui__top_nav__btn_full_screen,.wpbc_ui__top_nav__btn_normal_screen' ).toggleClass( 'wpbc_ui__hide' );";
268 - $el_arr['onclick'] .= "jQuery('body').toggleClass('wpbc_admin_full_screen');wpbc_check_full_screen_mode();";
322 + $el_arr['onclick'] = 'wpbc_admin_ui__full_screen__do_off( this, ' . ( $params['is_full_screen_user_mode_enabled'] ? 'true' : 'false' ) . ' );';
269 323
270 324 $el_arr['title'] = '';
271 325 $el_arr['font_icon'] = 'wpbc-bi-arrows-angle-contract';
272 326 $el_arr['hint'] = array(
@@ -274,19 +328,20 @@
274 328 'position' => 'top',
275 329 );
276 330 $el_arr['container_class'] = 'wpbc_ui__top_nav__btn_normal_screen wpbc_ui__hide';
277 331
278 - // Params for saving user option.
279 - $user_cust_option = 'is_full_screen';
280 - $nonce_action = $user_cust_option . '_nonce_act';
281 - $el_arr['attr'] = array(
282 - 'data-wpbc-u-save-name' => $user_cust_option,
283 - 'data-wpbc-u-save-value' => 'Off',
284 - 'data-wpbc-u-save-nonce' => wp_create_nonce( $nonce_action ), // do not need to make escaping the values because: wpbc_get_custom_attr() should handle escaping.
285 - 'data-wpbc-u-save-user-id' => wpbc_get_current_user_id(),
286 - 'data-wpbc-u-save-action' => $nonce_action,
287 - );
288 - $el_arr['onclick'] .= 'wpbc_save_custom_user_data_from_element(this);';
332 + if ( $params['is_full_screen_user_mode_enabled'] ) {
333 + // Params for saving user option.
334 + $user_cust_option = 'is_full_screen';
335 + $nonce_action = $user_cust_option . '_nonce_act';
336 + $el_arr['attr'] = array(
337 + 'data-wpbc-u-save-name' => $user_cust_option,
338 + 'data-wpbc-u-save-value' => 'Off',
339 + 'data-wpbc-u-save-nonce' => wp_create_nonce( $nonce_action ), // do not need to make escaping the values because: wpbc_get_custom_attr() should handle escaping.
340 + 'data-wpbc-u-save-user-id' => wpbc_get_current_user_id(),
341 + 'data-wpbc-u-save-action' => $nonce_action,
342 + );
343 + }
289 344
290 345 wpbc_ui_el__a( $el_arr );
291 346 }
292 347
@@ -291,8 +346,175 @@
291 346 }
292 347
293 348
294 349 /**
350 + * Build a short-lived browser value for an immediately changed fullscreen preference.
351 + *
352 + * The timestamp distinguishes a pending navigation safeguard from legacy
353 + * year-long cookies, which must not override a successfully stored user value.
354 + *
355 + * @param string $mode Fullscreen mode, either `On` or `Off`.
356 + * @param int|null $issued_timestamp Optional Unix timestamp for deterministic tests.
357 + *
358 + * @return string Pending cookie value, or an empty string for an invalid mode.
359 + */
360 +function wpbc_ui__create_full_screen_mode_cookie_value( $mode, $issued_timestamp = null ) {
361 +
362 + if ( ! in_array( $mode, array( 'On', 'Off' ), true ) ) {
363 + return '';
364 + }
365 +
366 + $issued_timestamp = null === $issued_timestamp ? time() : absint( $issued_timestamp );
367 +
368 + return $mode . '|' . $issued_timestamp;
369 +}
370 +
371 +/**
372 + * Return every server-side cookie path used by Booking Calendar administration.
373 + *
374 + * Multiple paths are updated together to replace legacy cookies created by
375 + * root, subdirectory, or WordPress administration requests.
376 + *
377 + * @return string[] Unique absolute cookie paths.
378 + */
379 +function wpbc_ui__get_full_screen_mode_cookie_paths() {
380 +
381 + $cookie_paths = array( '/' );
382 +
383 + if ( defined( 'COOKIEPATH' ) && COOKIEPATH ) {
384 + $cookie_paths[] = COOKIEPATH;
385 + }
386 +
387 + if ( defined( 'ADMIN_COOKIE_PATH' ) && ADMIN_COOKIE_PATH ) {
388 + $cookie_paths[] = ADMIN_COOKIE_PATH;
389 + }
390 +
391 + return array_values( array_unique( array_filter( $cookie_paths ) ) );
392 +}
393 +
394 +/**
395 + * Set the pending fullscreen cookie on every applicable administration path.
396 + *
397 + * User metadata remains authoritative. This short-lived cookie only bridges
398 + * immediate navigation and replaces stale same-name cookies on narrower paths.
399 + *
400 + * @param string $mode Fullscreen mode, either `On` or `Off`.
401 + *
402 + * @return bool True when the mode was valid; otherwise false.
403 + */
404 +function wpbc_ui__set_full_screen_mode_cookie( $mode ) {
405 +
406 + $cookie_value = wpbc_ui__create_full_screen_mode_cookie_value( $mode );
407 + if ( '' === $cookie_value ) {
408 + return false;
409 + }
410 +
411 + if ( ! headers_sent() ) {
412 + $cookie_domain = defined( 'COOKIE_DOMAIN' ) ? COOKIE_DOMAIN : '';
413 +
414 + foreach ( wpbc_ui__get_full_screen_mode_cookie_paths() as $cookie_path ) {
415 + setcookie(
416 + 'wpbc_admin_full_screen',
417 + $cookie_value,
418 + time() + ( 5 * 60 ),
419 + $cookie_path,
420 + $cookie_domain,
421 + is_ssl(),
422 + false
423 + );
424 + }
425 + }
426 +
427 + $_COOKIE['wpbc_admin_full_screen'] = $cookie_value;
428 +
429 + return true;
430 +}
431 +
432 +/**
433 + * Resolve fullscreen mode from saved user data and an optional pending cookie.
434 + *
435 + * A fresh timestamped cookie temporarily wins so immediate navigation remains
436 + * deterministic if the asynchronous AJAX request is interrupted. A legacy
437 + * plain `On` or `Off` cookie is accepted only when no valid user preference
438 + * exists, preventing stale or duplicate-path cookies from overriding storage.
439 + *
440 + * @param string $saved_value Saved user-meta value.
441 + * @param string $cookie_value Browser cookie value.
442 + * @param int|null $current_timestamp Optional Unix timestamp for deterministic tests.
443 + *
444 + * @return string `On`, `Off`, or an empty string.
445 + */
446 +function wpbc_ui__resolve_full_screen_mode( $saved_value = '', $cookie_value = '', $current_timestamp = null ) {
447 +
448 + $saved_value = in_array( $saved_value, array( 'On', 'Off' ), true ) ? $saved_value : '';
449 + $cookie_value = is_scalar( $cookie_value ) ? (string) $cookie_value : '';
450 +
451 + if ( in_array( $cookie_value, array( 'On', 'Off' ), true ) ) {
452 + return '' === $saved_value ? $cookie_value : $saved_value;
453 + }
454 +
455 + if ( ! preg_match( '/^(On|Off)\|([0-9]{10,})$/', $cookie_value, $cookie_parts ) ) {
456 + return $saved_value;
457 + }
458 +
459 + $current_timestamp = null === $current_timestamp ? time() : absint( $current_timestamp );
460 + $issued_timestamp = absint( $cookie_parts[2] );
461 + $pending_cookie_lifetime = 5 * 60;
462 + $allowed_clock_skew = 60;
463 +
464 + if (
465 + $issued_timestamp > ( $current_timestamp + $allowed_clock_skew )
466 + || $issued_timestamp < ( $current_timestamp - $pending_cookie_lifetime )
467 + ) {
468 + return $saved_value;
469 + }
470 +
471 + return $cookie_parts[1];
472 +}
473 +
474 +/**
475 + * Get fullscreen mode from the immediate browser cookie and saved user metadata.
476 + *
477 + * @param string $saved_value Saved user-meta value.
478 + *
479 + * @return string `On`, `Off`, or an empty string.
480 + */
481 +function wpbc_ui__get_full_screen_mode_from_cookie( $saved_value = '' ) {
482 +
483 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- Optional same-origin UI preference.
484 + $cookie_value = isset( $_COOKIE['wpbc_admin_full_screen'] ) && is_scalar( $_COOKIE['wpbc_admin_full_screen'] )
485 + ? sanitize_text_field( wp_unslash( $_COOKIE['wpbc_admin_full_screen'] ) )
486 + : '';
487 +
488 + return wpbc_ui__resolve_full_screen_mode( $saved_value, $cookie_value );
489 +}
490 +
491 +/**
492 + * Synchronize the fullscreen navigation cookie after verified user-meta storage.
493 + *
494 + * @param int $user_id User whose preference was saved.
495 + * @param string $data_name Saved Booking Calendar preference name.
496 + * @param array $sanitized_data Sanitized value stored in user metadata.
497 + *
498 + * @return void
499 + */
500 +function wpbc_ui__sync_full_screen_cookie_after_user_data_save( $user_id, $data_name, $sanitized_data ) {
501 +
502 + if (
503 + 'is_full_screen' !== $data_name
504 + || wpbc_get_current_user_id() !== absint( $user_id )
505 + || ! isset( $sanitized_data['value'] )
506 + || ! is_scalar( $sanitized_data['value'] )
507 + ) {
508 + return;
509 + }
510 +
511 + wpbc_ui__set_full_screen_mode_cookie( (string) $sanitized_data['value'] );
512 +}
513 +add_action( 'wpbc_user_custom_data_saved', 'wpbc_ui__sync_full_screen_cookie_after_user_data_save', 10, 3 );
514 +
515 +
516 +/**
295 517 * Set the admin full screen class
296 518 *
297 519 * @param bool $classes Body classes.
298 520 *
@@ -300,8 +522,9 @@
300 522 */
301 523 function wpbc_check_full_screen_mode_on_loading( $classes ) {
302 524
303 525 $is_full_screen = WPBC_User_Custom_Data_Saver::get_user_data_value( wpbc_get_current_user_id(), 'is_full_screen' );
526 + $is_full_screen = wpbc_ui__get_full_screen_mode_from_cookie( $is_full_screen );
304 527 $is_full_screen = ( 'On' === $is_full_screen );
305 528
306 529 if ( ( wpbc_is_this_plugin_page() ) && ( $is_full_screen ) && ( ! wpbc_is_setup_wizard_page() ) ) {
307 530 $classes .= ' wpbc_admin_full_screen';