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 +253 -40 11.2.1 → 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>',
@@ -107,13 +144,8 @@
107 144 $el_arr['items'][] = array(
108 145 'type' => 'header',
109 146 'title' => __( 'Visit Booking Pages', 'booking' ),
110 147 );
111 - $el_arr['items'][] = array(
112 - 'type' => 'link',
113 - 'title' => __( 'Visit Home Page', 'booking' ),
114 - 'url' => esc_url( home_url( '/' ) ),
115 - );
116 148
117 149 foreach ( $wpbc_starter_pages as $wpbc_starter_page ) {
118 150 if ( empty( $wpbc_starter_page['url'] ) ) {
119 151 continue;
@@ -131,8 +163,14 @@
131 163 'title' => $wpbc_starter_page_title,
132 164 'url' => esc_url( $wpbc_starter_page['url'] ),
133 165 );
134 166 }
167 +
168 + $el_arr['items'][] = array(
169 + 'type' => 'link',
170 + 'title' => __( 'Visit Home Page', 'booking' ),
171 + 'url' => esc_url( home_url( '/' ) ),
172 + );
135 173 } elseif ( ! empty( $wp_post_booking_absolute ) ) {
136 174 $el_arr['items'][] = array(
137 175 'type' => 'header',
138 176 'title' => __( 'Visit Booking Page', 'booking' ),
@@ -138,15 +176,15 @@
138 176 'title' => __( 'Visit Booking Page', 'booking' ),
139 177 );
140 178 $el_arr['items'][] = array(
141 179 'type' => 'link',
142 - 'title' => __( 'Visit Home Page', 'booking' ),
143 - 'url' => esc_url( home_url( '/' ) ),
180 + 'title' => __( 'Go to page with booking form', 'booking' ),
181 + 'url' => esc_url( $wp_post_booking_absolute ),
144 182 );
145 183 $el_arr['items'][] = array(
146 184 'type' => 'link',
147 - 'title' => __( 'Go to page with booking form', 'booking' ),
148 - 'url' => esc_url( $wp_post_booking_absolute ),
185 + 'title' => __( 'Visit Home Page', 'booking' ),
186 + 'url' => esc_url( home_url( '/' ) ),
149 187 );
150 188 }
151 189 $el_arr['items'][] = array(
152 190 'type' => 'header',
@@ -215,14 +253,18 @@
215 253 * Show element - "Full Screen"
216 254 *
217 255 * @return void
218 256 */
219 -function wpbc_ui__top_nav__btn_full_screen() {
257 +function wpbc_ui__top_nav__btn_full_screen( $args = array() ) {
220 258
259 + $defaults = array(
260 + 'is_full_screen_user_mode_enabled' => true,
261 + );
262 + $params = wp_parse_args( $args, $defaults );
263 +
221 264 $el_arr = array();
222 265
223 - $el_arr['onclick'] = "jQuery( '.wpbc_ui__top_nav__btn_full_screen,.wpbc_ui__top_nav__btn_normal_screen' ).toggleClass( 'wpbc_ui__hide' );";
224 - $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' ) . ' );';
225 267
226 268 $el_arr['font_icon'] = 'wpbc-bi-arrows-fullscreen';
227 269 $el_arr['hint'] = array(
228 270 'title' => __( 'Full Screen', 'booking' ),
@@ -230,9 +272,9 @@
230 272 );
231 273
232 274 $el_arr['container_class'] = 'wpbc_ui__top_nav__btn_full_screen';
233 275
234 - if ( ! wpbc_is_setup_wizard_page() ) {
276 + if ( ( ! wpbc_is_setup_wizard_page() ) && ( $params['is_full_screen_user_mode_enabled'] ) ) {
235 277
236 278 // Params for saving user option.
237 279 $user_cust_option = 'is_full_screen';
238 280 $nonce_action = $user_cust_option . '_nonce_act';
@@ -243,14 +285,12 @@
243 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.
244 286 'data-wpbc-u-save-user-id' => wpbc_get_current_user_id(),
245 287 'data-wpbc-u-save-action' => $nonce_action,
246 288 );
247 - $el_arr['onclick'] .= 'wpbc_save_custom_user_data_from_element(this);';
248 -
249 289 ?><script type="text/javascript"><?php
250 290
251 291 $is_full_screen = WPBC_User_Custom_Data_Saver::get_user_data_value( wpbc_get_current_user_id(), $user_cust_option );
252 - $is_full_screen = ( 'On' === $is_full_screen );
292 + $is_full_screen = ( 'On' === wpbc_ui__get_full_screen_mode_from_cookie( $is_full_screen ) );
253 293
254 294 echo wpbc_jq_ready_start(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
255 295
256 296 if ( $is_full_screen ) {
@@ -269,14 +309,18 @@
269 309 * Show element - "Normal Screen"
270 310 *
271 311 * @return void
272 312 */
273 -function wpbc_ui__top_nav__btn_normal_screen() {
313 +function wpbc_ui__top_nav__btn_normal_screen( $args = array() ) {
274 314
315 + $defaults = array(
316 + 'is_full_screen_user_mode_enabled' => true,
317 + );
318 + $params = wp_parse_args( $args, $defaults );
319 +
275 320 $el_arr = array();
276 321
277 - $el_arr['onclick'] = "jQuery( '.wpbc_ui__top_nav__btn_full_screen,.wpbc_ui__top_nav__btn_normal_screen' ).toggleClass( 'wpbc_ui__hide' );";
278 - $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' ) . ' );';
279 323
280 324 $el_arr['title'] = '';
281 325 $el_arr['font_icon'] = 'wpbc-bi-arrows-angle-contract';
282 326 $el_arr['hint'] = array(
@@ -284,19 +328,20 @@
284 328 'position' => 'top',
285 329 );
286 330 $el_arr['container_class'] = 'wpbc_ui__top_nav__btn_normal_screen wpbc_ui__hide';
287 331
288 - // Params for saving user option.
289 - $user_cust_option = 'is_full_screen';
290 - $nonce_action = $user_cust_option . '_nonce_act';
291 - $el_arr['attr'] = array(
292 - 'data-wpbc-u-save-name' => $user_cust_option,
293 - 'data-wpbc-u-save-value' => 'Off',
294 - '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.
295 - 'data-wpbc-u-save-user-id' => wpbc_get_current_user_id(),
296 - 'data-wpbc-u-save-action' => $nonce_action,
297 - );
298 - $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 + }
299 344
300 345 wpbc_ui_el__a( $el_arr );
301 346 }
302 347
@@ -301,8 +346,175 @@
301 346 }
302 347
303 348
304 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 +/**
305 517 * Set the admin full screen class
306 518 *
307 519 * @param bool $classes Body classes.
308 520 *
@@ -310,8 +522,9 @@
310 522 */
311 523 function wpbc_check_full_screen_mode_on_loading( $classes ) {
312 524
313 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 );
314 527 $is_full_screen = ( 'On' === $is_full_screen );
315 528
316 529 if ( ( wpbc_is_this_plugin_page() ) && ( $is_full_screen ) && ( ! wpbc_is_setup_wizard_page() ) ) {
317 530 $classes .= ' wpbc_admin_full_screen';