PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
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 / ui_settings / parts / ui__nav_top.php

ui__nav_top.php in Booking Calendar 11.8.4, at includes/ui_settings/parts/ui__nav_top.php

536 lines 17.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Panel UI - Parts
4 *
5 * @version 1.2
6 * @package Any
7 * @category Page Structure in Admin Panel
8 * @author wpdevelop
9 *
10 * @web-site https://wpbookingcalendar.com/
11 * @email info@wpbookingcalendar.com
12 *
13 * @modified 2025-02-15
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit; // Exit, if accessed directly.
18 }
19
20 /**
21 * Show Top Nav bar
22 *
23 * @param array $args - parameters.
24 *
25 * @return void
26 */
27 function wpbc_ui__top_nav( $args = array() ) {
28
29 $defaults = array(
30 'attr' => array(),
31 'is_full_screen_user_mode_enabled' => true,
32 );
33 $params = wp_parse_args( $args, $defaults );
34
35 echo '<div class="wpbc_ui_el wpbc_ui_el__top_nav">';
36
37 wpbc_ui__vert_left_bar__do_toggle();
38 wpbc_ui_el__divider_vertical( array( 'class' => 'wpbc_ui_el__vertical_line wpbc_ui__top_nav__btn_show_left_vertical_nav_divider' ) );
39
40 wpbc_ui__top_nav__dropdown__wpbc();
41
42 do_action( 'wpbc_ui_el__top_nav__content_start', $params['page_tag'], $params['active_page_tab'], $params['active_page_subtab'] );
43
44
45 ?><div class="wpbc_ui_el__make_space"></div><?php // Spacer.
46
47 do_action( 'wpbc_ui_el__top_nav__content_center', $params['page_tag'], $params['active_page_tab'], $params['active_page_subtab'] );
48
49 // Load Top News Message and "Search by ID" fields.
50 echo '<style type="text/css"> .wpbc_message_wrapper { margin-left: 0px !important; } </style>';
51 make_bk_action( 'wpbc_h1_header_content_end', $params['page_tag'], $params['active_page_tab'], $params['active_page_subtab'] );
52
53 ?><div class="wpbc_ui_el__make_space"></div><?php // Spacer.
54
55 do_action( 'wpbc_ui_el__top_nav__content_end', $params['page_tag'], $params['active_page_tab'], $params['active_page_subtab'] );
56
57 wpbc_ui_el__divider_vertical();
58
59 // Right sidebar toggle button.
60 wpbc_ui__vert_right_bar__do_toggle();
61 wpbc_ui_el__divider_vertical( array( 'class' => 'wpbc_ui_el__vertical_line wpbc_ui__top_nav__btn_show_right_vertical_nav_divider' ) );
62
63
64 // Full Screen Buttons.
65 wpbc_ui__top_nav__btn_full_screen( $params );
66 wpbc_ui__top_nav__btn_normal_screen( $params );
67
68 echo '</div>';
69 }
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 ) {
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
115 /**
116 * Show element - "WPBC - Main Dropdown"
117 *
118 * @return void
119 */
120 function wpbc_ui__top_nav__dropdown__wpbc() {
121
122 $svg_size = '22px';
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 . ';'; //.
124 $svg_icon = wpbc_get_svg_logo_for_background( '#555', '#e5e5e5', '1.0' );
125
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 );
128 $wp_post_booking_absolute = false;
129
130 $el_arr = array(
131 // 'title' => 'Booking Calendar',
132 // 'font_icon' => 'wpbc-bi-calendar2-range',
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>',
134 'svg_icon' => $svg_icon,
135 'svg_icon_style' => $svg_icon_style,
136 'style' => 'display: flex;flex-flow:row nowrap;align-items: center;justify-content: flex-start; ',
137 'container_style' => 'padding: 0 15px 0 10px;',
138 'position' => 'left',
139 'has_down_arrow' => true,
140 'items' => array(),
141 );
142
143 if ( ! empty( $wpbc_starter_pages ) && is_array( $wpbc_starter_pages ) ) {
144 $el_arr['items'][] = array(
145 'type' => 'header',
146 'title' => __( 'Visit Booking Pages', 'booking' ),
147 );
148
149 foreach ( $wpbc_starter_pages as $wpbc_starter_page ) {
150 if ( empty( $wpbc_starter_page['url'] ) ) {
151 continue;
152 }
153
154 $wpbc_starter_page_title = __( 'Go to page with booking form', 'booking' );
155 if ( ! empty( $wpbc_starter_page['button_title'] ) ) {
156 $wpbc_starter_page_title = $wpbc_starter_page['button_title'];
157 } elseif ( ! empty( $wpbc_starter_page['page_title'] ) ) {
158 $wpbc_starter_page_title = $wpbc_starter_page['page_title'];
159 }
160
161 $el_arr['items'][] = array(
162 'type' => 'link',
163 'title' => $wpbc_starter_page_title,
164 'url' => esc_url( $wpbc_starter_page['url'] ),
165 );
166 }
167
168 $el_arr['items'][] = array(
169 'type' => 'link',
170 'title' => __( 'Visit Home Page', 'booking' ),
171 'url' => esc_url( home_url( '/' ) ),
172 );
173 } elseif ( ! empty( $wp_post_booking_absolute ) ) {
174 $el_arr['items'][] = array(
175 'type' => 'header',
176 'title' => __( 'Visit Booking Page', 'booking' ),
177 );
178 $el_arr['items'][] = array(
179 'type' => 'link',
180 'title' => __( 'Go to page with booking form', 'booking' ),
181 'url' => esc_url( $wp_post_booking_absolute ),
182 );
183 $el_arr['items'][] = array(
184 'type' => 'link',
185 'title' => __( 'Visit Home Page', 'booking' ),
186 'url' => esc_url( home_url( '/' ) ),
187 );
188 }
189 $el_arr['items'][] = array(
190 'type' => 'header',
191 'title' => __( 'Help', 'booking' ),
192 );
193 $el_arr['items'][] = array(
194 'type' => 'link',
195 'title' => __( 'FAQ', 'booking' ),
196 'url' => 'https://wpbookingcalendar.com/faq/',
197 );
198 $el_arr['items'][] = array(
199 'type' => 'header',
200 'title' => __( 'Support', 'booking' ),
201 );
202 $el_arr['items'][] = array(
203 'type' => 'link',
204 'title' => __( 'Support Forum', 'booking' ),
205 'url' => 'https://wpbookingcalendar.com/support/',
206 );
207 $el_arr['items'][] = array(
208 'type' => 'link',
209 'title' => __( 'Contact Support', 'booking' ),
210 'url' => 'mailto:support@wpbookingcalendar.com',
211 'attr' => array( 'style' => 'font-weight: 600;' ),
212 );
213 $el_arr['items'][] = array( 'type' => 'divider' );
214 $el_arr['items'][] = array(
215 'type' => 'link',
216 'title' => __( 'Release History', 'booking' ),
217 'url' => 'https://wpbookingcalendar.com/wn/',
218 );
219 $el_arr['items'][] = array(
220 'type' => 'link',
221 'title' => __( 'What\'s New', 'booking' ) . ' <span style="float:right">' . esc_attr( WP_BK_VERSION_NUM ) . '</span>',
222 'url' => esc_url( admin_url( add_query_arg( array( 'page' => 'wpbc-about' ), 'index.php' ) ) ),
223 );
224 // $el_arr['items'][] = array(
225 // 'type' => 'link',
226 // 'title' => __( 'About', 'booking' ),
227 // 'url' => 'https://wpbookingcalendar.com/',
228 // );
229
230
231 $is_show_up = wpbc_is_show_up();
232
233 if ( $is_show_up ) {
234 $el_arr['items'][] = array( 'type' => 'divider' );
235 $el_arr['items'][] = array(
236 'type' => 'link',
237 'title' => ( class_exists( 'wpdev_bk_personal' ) )
238 ? __( 'View Upgrade Options', 'booking' )
239 : __( 'Upgrade to Pro', 'booking' ),
240 'url' => wpbc_up_link(),
241 'attr' => array(
242 'class' => 'wpbc_ui_el_upgrade_button wpbc_button_light wpbc_button_green',
243 'style' => 'color:#fff;font-weight: 600;',
244 ),
245 );
246 }
247
248 wpbc_ui_el__dropdown_menu( $el_arr );
249 }
250
251
252 /**
253 * Show element - "Full Screen"
254 *
255 * @return void
256 */
257 function wpbc_ui__top_nav__btn_full_screen( $args = array() ) {
258
259 $defaults = array(
260 'is_full_screen_user_mode_enabled' => true,
261 );
262 $params = wp_parse_args( $args, $defaults );
263
264 $el_arr = array();
265
266 $el_arr['onclick'] = 'wpbc_admin_ui__full_screen__do_on( this, ' . ( $params['is_full_screen_user_mode_enabled'] ? 'true' : 'false' ) . ' );';
267
268 $el_arr['font_icon'] = 'wpbc-bi-arrows-fullscreen';
269 $el_arr['hint'] = array(
270 'title' => __( 'Full Screen', 'booking' ),
271 'position' => 'top',
272 );
273
274 $el_arr['container_class'] = 'wpbc_ui__top_nav__btn_full_screen';
275
276 if ( ( ! wpbc_is_setup_wizard_page() ) && ( $params['is_full_screen_user_mode_enabled'] ) ) {
277
278 // Params for saving user option.
279 $user_cust_option = 'is_full_screen';
280 $nonce_action = $user_cust_option . '_nonce_act';
281
282 $el_arr['attr'] = array(
283 'data-wpbc-u-save-name' => $user_cust_option,
284 'data-wpbc-u-save-value' => 'On',
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.
286 'data-wpbc-u-save-user-id' => wpbc_get_current_user_id(),
287 'data-wpbc-u-save-action' => $nonce_action,
288 );
289 ?><script type="text/javascript"><?php
290
291 $is_full_screen = WPBC_User_Custom_Data_Saver::get_user_data_value( wpbc_get_current_user_id(), $user_cust_option );
292 $is_full_screen = ( 'On' === wpbc_ui__get_full_screen_mode_from_cookie( $is_full_screen ) );
293
294 echo wpbc_jq_ready_start(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
295
296 if ( $is_full_screen ) {
297 echo " jQuery( '.wpbc_ui__top_nav__btn_full_screen,.wpbc_ui__top_nav__btn_normal_screen' ).toggleClass( 'wpbc_ui__hide' ); ";
298 }
299 echo ' wpbc_check_full_screen_mode(); ';
300 echo wpbc_jq_ready_end(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
301
302 ?></script><?php
303 }
304 wpbc_ui_el__a( $el_arr );
305 }
306
307
308 /**
309 * Show element - "Normal Screen"
310 *
311 * @return void
312 */
313 function wpbc_ui__top_nav__btn_normal_screen( $args = array() ) {
314
315 $defaults = array(
316 'is_full_screen_user_mode_enabled' => true,
317 );
318 $params = wp_parse_args( $args, $defaults );
319
320 $el_arr = array();
321
322 $el_arr['onclick'] = 'wpbc_admin_ui__full_screen__do_off( this, ' . ( $params['is_full_screen_user_mode_enabled'] ? 'true' : 'false' ) . ' );';
323
324 $el_arr['title'] = '';
325 $el_arr['font_icon'] = 'wpbc-bi-arrows-angle-contract';
326 $el_arr['hint'] = array(
327 'title' => __( 'Exit Full Screen', 'booking' ),
328 'position' => 'top',
329 );
330 $el_arr['container_class'] = 'wpbc_ui__top_nav__btn_normal_screen wpbc_ui__hide';
331
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 }
344
345 wpbc_ui_el__a( $el_arr );
346 }
347
348
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 /**
517 * Set the admin full screen class
518 *
519 * @param bool $classes Body classes.
520 *
521 * @return array
522 */
523 function wpbc_check_full_screen_mode_on_loading( $classes ) {
524
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 );
527 $is_full_screen = ( 'On' === $is_full_screen );
528
529 if ( ( wpbc_is_this_plugin_page() ) && ( $is_full_screen ) && ( ! wpbc_is_setup_wizard_page() ) ) {
530 $classes .= ' wpbc_admin_full_screen';
531 }
532
533 return $classes;
534 }
535 add_filter( 'admin_body_class', 'wpbc_check_full_screen_mode_on_loading' );
536