PluginProbe
Booking Calendar / 11.3
Booking Calendar v11.3
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
booking / includes / page-settings-calendar / settings_calendar__page.php

settings_calendar__page.php in Booking Calendar 11.3, at includes/page-settings-calendar/settings_calendar__page.php

2,215 lines 102.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Calendar settings page.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Check whether the Calendar settings page is active.
14 *
15 * @return bool
16 */
17 function wpbc_settings_calendar__is_page() {
18
19 if ( ! is_admin() ) {
20 return false;
21 }
22
23 if ( function_exists( 'wpbc_is_settings_calendar_page' ) ) {
24 return wpbc_is_settings_calendar_page();
25 }
26
27 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
28 $page = isset( $_REQUEST['page'] ) ? sanitize_key( wp_unslash( $_REQUEST['page'] ) ) : '';
29 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
30 $tab = isset( $_REQUEST['tab'] ) ? sanitize_key( wp_unslash( $_REQUEST['tab'] ) ) : '';
31
32 return ( 'wpbc-settings' === $page && 'calendar_settings' === $tab );
33 }
34
35 /**
36 * Enqueue CSS for Calendar settings.
37 *
38 * @param string $where_to_load Where assets are loaded.
39 *
40 * @return void
41 */
42 function wpbc_settings_calendar_enqueue_css_files( $where_to_load ) {
43
44 if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) {
45 return;
46 }
47
48 if ( ! wpbc_settings_calendar__is_page() ) {
49 return;
50 }
51
52 wp_enqueue_style(
53 'wpbc-settings-calendar-page',
54 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/settings_calendar_page.css',
55 array( 'wpbc-calendar', 'wpbc-all-admin' ),
56 WP_BK_VERSION_NUM
57 );
58 }
59 add_action( 'wpbc_enqueue_css_files', 'wpbc_settings_calendar_enqueue_css_files', 66 );
60
61 /**
62 * Enqueue JS for Calendar settings.
63 *
64 * @param string $where_to_load Where assets are loaded.
65 *
66 * @return void
67 */
68 function wpbc_settings_calendar_enqueue_js_files( $where_to_load ) {
69
70 if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) {
71 return;
72 }
73
74 if ( ! wpbc_settings_calendar__is_page() ) {
75 return;
76 }
77
78 wp_enqueue_script(
79 'wpbc-settings-calendar-page',
80 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/settings_calendar_page.js',
81 array( 'jquery', 'wpbc_all' ),
82 WP_BK_VERSION_NUM,
83 array( 'in_footer' => WPBC_JS_IN_FOOTER )
84 );
85
86 wp_localize_script(
87 'wpbc-settings-calendar-page',
88 'wpbc_settings_calendar_page',
89 array(
90 'ajax_url' => admin_url( 'admin-ajax.php' ),
91 'nonce' => wp_create_nonce( 'wpbc_settings_calendar_ajax_nonce' ),
92 'action' => 'WPBC_AJX_SETTINGS_CALENDAR_SAVE',
93 'preview_action' => 'WPBC_AJX_SETTINGS_CALENDAR_PREVIEW',
94 'settings' => wpbc_settings_calendar__get_settings_response(),
95 'days_selection' => wpbc_settings_calendar__get_days_selection_response(),
96 'open_section' => wpbc_settings_calendar__get_open_section(),
97 'section_groups' => wpbc_settings_calendar__get_section_group_map(),
98 'section_menus' => wpbc_settings_calendar__get_section_menu_slug_map(),
99 'i18n' => array(
100 'saving' => __( 'Saving', 'booking' ),
101 'saved' => __( 'Calendar settings updated.', 'booking' ),
102 'save_failed' => __( 'Unable to save calendar settings.', 'booking' ),
103 'preview_failed' => __( 'Unable to refresh calendar preview.', 'booking' ),
104 'loading' => __( 'Loading', 'booking' ),
105 'premium_notice' => __( 'Range days selection is available in Booking Calendar Business Small or higher. Open the live demo to test the real behavior.', 'booking' ),
106 'premium_changeover_notice' => __( 'Changeover days are available in Booking Calendar Business Small or higher. Open the live demo to test the real behavior.', 'booking' ),
107 'premium_option_notice' => __( 'This option is available in Booking Calendar Business Small or higher.', 'booking' ),
108 ),
109 'is_range_supported' => wpbc_settings_calendar__is_range_supported() ? 1 : 0,
110 )
111 );
112 }
113 add_action( 'wpbc_enqueue_js_files', 'wpbc_settings_calendar_enqueue_js_files', 66 );
114
115 /**
116 * Print tooltip initializer for Calendar settings.
117 *
118 * @return void
119 */
120 function wpbc_settings_calendar_print_tooltip_js() {
121
122 if ( ! wpbc_settings_calendar__is_page() ) {
123 return;
124 }
125
126 if ( function_exists( 'wpbc_bs_javascript_tooltips' ) ) {
127 wpbc_bs_javascript_tooltips();
128 }
129 }
130 add_action( 'admin_footer', 'wpbc_settings_calendar_print_tooltip_js', 67 );
131
132 /**
133 * Check whether current edition supports range/change-over calendar settings.
134 *
135 * @return bool
136 */
137 function wpbc_settings_calendar__is_range_supported() {
138
139 return class_exists( 'wpdev_bk_biz_s' );
140 }
141
142 /**
143 * Calendar settings right-sidebar section navigation.
144 *
145 * @return array
146 */
147 function wpbc_settings_calendar__get_section_navigation_items() {
148
149 return array(
150 'days_selection' => array(
151 'menu_slug' => 'calendar_days_selection',
152 'group' => 'settings-calendar-days-selection',
153 'title' => __( 'Days Selection', 'booking' ),
154 'hint' => __( 'Choose how users can select days: single day, multiple days, or date range.', 'booking' ),
155 'font_icon' => 'wpbc-bi-calendar3-week',
156 ),
157 'changeover_times' => array(
158 'menu_slug' => 'calendar_changeover_times',
159 'group' => 'settings-calendar-time',
160 'title' => __( 'Changeover and Times', 'booking' ),
161 'hint' => __( 'Configure changeover days, recurrent time, and changeover exceptions.', 'booking' ),
162 'font_icon' => 'wpbc_icn_flip',
163 ),
164 'legend' => array(
165 'menu_slug' => 'calendar_legend',
166 'group' => 'settings-calendar-legend',
167 'title' => __( 'Calendar Legend', 'booking' ),
168 'hint' => __( 'Show or hide the calendar legend and configure each legend item.', 'booking' ),
169 'font_icon' => 'wpbc-bi-list-check',
170 ),
171 'tooltips' => array(
172 'menu_slug' => 'calendar_tooltips',
173 'group' => 'settings-calendar-tooltips',
174 'title' => __( 'Calendar Dates Tooltips', 'booking' ),
175 'hint' => __( 'Configure mouse-over tooltips for booked times, availability, cost, and booking details.', 'booking' ),
176 'font_icon' => 'wpbc-bi-chat-square-dots',
177 ),
178 'general' => array(
179 'menu_slug' => 'calendar_general',
180 'group' => 'settings-calendar-general',
181 'title' => __( 'Calendar General', 'booking' ),
182 'hint' => __( 'Configure month scrolling, week start day, and mobile month display.', 'booking' ),
183 'font_icon' => 'wpbc-bi-calendar2-range',
184 ),
185 );
186 }
187
188 /**
189 * Get section key to left-menu slug map for scripts.
190 *
191 * @return array
192 */
193 function wpbc_settings_calendar__get_section_menu_slug_map() {
194
195 $section_menus = array();
196
197 foreach ( wpbc_settings_calendar__get_section_navigation_items() as $section_key => $section ) {
198 $section_menus[ $section_key ] = $section['menu_slug'];
199 }
200
201 return $section_menus;
202 }
203
204 /**
205 * Get section key to collapsible group map for scripts.
206 *
207 * @return array
208 */
209 function wpbc_settings_calendar__get_section_group_map() {
210
211 $section_groups = array();
212
213 foreach ( wpbc_settings_calendar__get_section_navigation_items() as $section_key => $section ) {
214 $section_groups[ $section_key ] = $section['group'];
215 }
216
217 return $section_groups;
218 }
219
220 /**
221 * Get URL to the Calendar settings page with a right-sidebar section selected.
222 *
223 * @param string $section Section key.
224 * @return string
225 */
226 function wpbc_settings_calendar__get_section_url( $section ) {
227
228 $sections = wpbc_settings_calendar__get_section_navigation_items();
229 $base_url = function_exists( 'wpbc_get_settings_calendar_url' )
230 ? wpbc_get_settings_calendar_url()
231 : admin_url( 'admin.php?page=wpbc-settings&tab=calendar_settings' );
232
233 if ( empty( $sections[ $section ] ) ) {
234 return $base_url;
235 }
236
237 return add_query_arg(
238 array(
239 'wpbc_calendar_section' => $section,
240 ),
241 $base_url
242 );
243 }
244
245 /**
246 * Get the Calendar settings section that should be opened on page load.
247 *
248 * @return string
249 */
250 function wpbc_settings_calendar__get_open_section() {
251
252 $sections = wpbc_settings_calendar__get_section_navigation_items();
253
254 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
255 $open_section = isset( $_REQUEST['wpbc_calendar_section'] ) ? sanitize_key( wp_unslash( $_REQUEST['wpbc_calendar_section'] ) ) : '';
256
257 if ( isset( $sections[ $open_section ] ) ) {
258 return $open_section;
259 }
260
261 return '';
262 }
263
264 /**
265 * Adjust the universal top path for Calendar section URLs.
266 *
267 * Calendar sections use wpbc_calendar_section instead of the reserved subtab
268 * parameter, so we map the active section into the shared top path here.
269 *
270 * @param array $items Top path items.
271 * @param WPBC_Page_Structure $page_structure_obj Page structure object.
272 * @param array $top_path_config Top path config.
273 *
274 * @return array
275 */
276 function wpbc_settings_calendar__top_path_items( $items, $page_structure_obj, $top_path_config ) {
277
278 if ( ! is_object( $page_structure_obj ) || ! method_exists( $page_structure_obj, 'get_current_page_params' ) ) {
279 return $items;
280 }
281
282 $current_page_params = $page_structure_obj->get_current_page_params();
283 if ( empty( $current_page_params['tab']['tag'] ) || 'calendar_settings' !== $current_page_params['tab']['tag'] ) {
284 return $items;
285 }
286
287 $sections = wpbc_settings_calendar__get_section_navigation_items();
288 $section_key = wpbc_settings_calendar__get_open_section();
289 if ( empty( $section_key ) ) {
290 $section_key = 'days_selection';
291 }
292
293 if ( empty( $sections[ $section_key ]['title'] ) ) {
294 return $items;
295 }
296
297 foreach ( $items as $item_index => $item ) {
298 $items[ $item_index ]['active'] = false;
299 }
300
301 if ( ! empty( $items ) ) {
302 $last_item_index = count( $items ) - 1;
303 $section_titles = array_map( 'wp_strip_all_tags', wp_list_pluck( $sections, 'title' ) );
304 $last_title = isset( $items[ $last_item_index ]['title'] ) ? wp_strip_all_tags( $items[ $last_item_index ]['title'] ) : '';
305
306 if ( in_array( $last_title, $section_titles, true ) ) {
307 array_pop( $items );
308 }
309 }
310
311 $items[] = array(
312 'title' => $sections[ $section_key ]['title'],
313 'url' => wpbc_settings_calendar__get_section_url( $section_key ),
314 'onclick' => '',
315 'active' => true,
316 );
317
318 return $items;
319 }
320 add_filter( 'wpbc_ui_settings_top_path_items', 'wpbc_settings_calendar__top_path_items', 10, 3 );
321
322 /**
323 * Manage capability.
324 *
325 * @return string
326 */
327 function wpbc_settings_calendar__get_manage_cap() {
328
329 $min_user_role = get_bk_option( 'booking_user_role_settings' );
330 $capability = array(
331 'administrator' => 'activate_plugins',
332 'editor' => 'publish_pages',
333 'author' => 'publish_posts',
334 'contributor' => 'edit_posts',
335 'subscriber' => 'read',
336 );
337
338 return isset( $capability[ $min_user_role ] ) ? $capability[ $min_user_role ] : 'manage_options';
339 }
340
341 /**
342 * Get booking resources for preview toolbar.
343 *
344 * @return array
345 */
346 function wpbc_settings_calendar__get_resources() {
347
348 if ( function_exists( 'wpbc_settings_themes__get_resources' ) ) {
349 return wpbc_settings_themes__get_resources();
350 }
351
352 return array(
353 array(
354 'id' => 1,
355 'title' => __( 'Default booking resource', 'booking' ),
356 ),
357 );
358 }
359
360 /**
361 * Sanitize preview resource ID.
362 *
363 * @param int|string $resource_id Resource ID.
364 *
365 * @return int
366 */
367 function wpbc_settings_calendar__sanitize_preview_resource_id( $resource_id ) {
368
369 if ( function_exists( 'wpbc_settings_themes__sanitize_preview_resource_id' ) ) {
370 return wpbc_settings_themes__sanitize_preview_resource_id( $resource_id );
371 }
372
373 return max( 1, absint( $resource_id ) );
374 }
375
376 /**
377 * Sanitize preview months count.
378 *
379 * @param int|string $months_count Months count.
380 *
381 * @return int
382 */
383 function wpbc_settings_calendar__sanitize_preview_months_count( $months_count ) {
384
385 $months_count = absint( $months_count );
386 $allowed = array( 1, 2, 3, 4, 6, 12 );
387
388 return in_array( $months_count, $allowed, true ) ? $months_count : 3;
389 }
390
391 /**
392 * Get preview resource ID.
393 *
394 * @return int
395 */
396 function wpbc_settings_calendar__get_preview_resource_id() {
397
398 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
399 $resource_id = isset( $_GET['resource_id'] ) ? absint( wp_unslash( $_GET['resource_id'] ) ) : 1;
400
401 return wpbc_settings_calendar__sanitize_preview_resource_id( $resource_id );
402 }
403
404 /**
405 * Get preview months count.
406 *
407 * @return int
408 */
409 function wpbc_settings_calendar__get_preview_months_count() {
410
411 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
412 $months_count = isset( $_GET['months_count'] ) ? absint( wp_unslash( $_GET['months_count'] ) ) : 2;
413
414 return wpbc_settings_calendar__sanitize_preview_months_count( $months_count );
415 }
416
417 /**
418 * Get week day labels.
419 *
420 * @return array
421 */
422 function wpbc_settings_calendar__get_weekday_options() {
423
424 return array(
425 '0' => __( 'Sunday', 'booking' ),
426 '1' => __( 'Monday', 'booking' ),
427 '2' => __( 'Tuesday', 'booking' ),
428 '3' => __( 'Wednesday', 'booking' ),
429 '4' => __( 'Thursday', 'booking' ),
430 '5' => __( 'Friday', 'booking' ),
431 '6' => __( 'Saturday', 'booking' ),
432 );
433 }
434
435 /**
436 * Get maximum scroll options.
437 *
438 * @return array
439 */
440 function wpbc_settings_calendar__get_max_month_options() {
441
442 $options = array();
443
444 for ( $mm = 1; $mm < 12; $mm++ ) {
445 $options[ $mm . 'm' ] = $mm . ' ' . __( 'month(s)', 'booking' );
446 }
447 $options['18m'] = '18 ' . __( 'month(s)', 'booking' );
448 for ( $yy = 1; $yy < 11; $yy++ ) {
449 $options[ $yy . 'y' ] = $yy . ' ' . __( 'year(s)', 'booking' );
450 }
451
452 return $options;
453 }
454
455 /**
456 * Get time options in 15 minute steps while preserving saved values.
457 *
458 * @param string $current Current time.
459 *
460 * @return array
461 */
462 function wpbc_settings_calendar__get_time_options( $current = '' ) {
463
464 $options = array();
465
466 for ( $hh = 0; $hh < 24; $hh++ ) {
467 foreach ( array( 0, 15, 30, 45 ) as $mm ) {
468 $time = sprintf( '%02d:%02d', $hh, $mm );
469 $options[ $time ] = function_exists( 'wpbc_time_localized' ) ? wpbc_time_localized( $time ) : $time;
470 }
471 }
472
473 if ( '' !== $current && ! isset( $options[ $current ] ) && preg_match( '/^\d{2}:\d{2}$/', $current ) ) {
474 $options[ $current ] = function_exists( 'wpbc_time_localized' ) ? wpbc_time_localized( $current ) : $current;
475 ksort( $options );
476 }
477
478 return $options;
479 }
480
481 /**
482 * Get configurable legend item options.
483 *
484 * @return array
485 */
486 function wpbc_settings_calendar__get_legend_items_config() {
487
488 return array(
489 'available' => array(
490 'label' => __( 'Available item', 'booking' ),
491 'description' => sprintf( __( 'Activate and type your %1$stitle of available%2$s item in legend', 'booking' ), '<b>', '</b>' ),
492 'placeholder' => __( 'Available', 'booking' ),
493 ),
494 'pending' => array(
495 'label' => __( 'Pending item', 'booking' ),
496 'description' => sprintf( __( 'Activate and type your %1$stitle of pending%2$s item in legend', 'booking' ), '<b>', '</b>' ),
497 'placeholder' => __( 'Pending', 'booking' ),
498 ),
499 'approved' => array(
500 'label' => __( 'Approved item', 'booking' ),
501 'description' => sprintf( __( 'Activate and type your %1$stitle of approved%2$s item in legend', 'booking' ), '<b>', '</b>' ),
502 'placeholder' => __( 'Booked', 'booking' ),
503 ),
504 'partially' => array(
505 'label' => __( 'Partially booked item', 'booking' ),
506 'description' => sprintf( __( 'Activate and type your %1$stitle of partially booked%2$s item in legend', 'booking' ), '<b>', '</b>' ),
507 'placeholder' => __( 'Partially booked', 'booking' ),
508 'note' => __( 'Partially booked item - day, which is booked for the specific time-slot(s).', 'booking' ),
509 ),
510 'unavailable' => array(
511 'label' => __( 'Unavailable item', 'booking' ),
512 'description' => sprintf( __( 'Activate and type your %1$stitle of unavailable%2$s item in legend', 'booking' ), '<b>', '</b>' ),
513 'placeholder' => __( 'Unavailable', 'booking' ),
514 ),
515 );
516 }
517
518 /**
519 * Normalize week-day CSV.
520 *
521 * @param string|array $value Week days.
522 *
523 * @return string
524 */
525 function wpbc_settings_calendar__normalize_week_days( $value ) {
526
527 if ( is_array( $value ) ) {
528 $items = $value;
529 } else {
530 $value = (string) $value;
531 if ( '-1' === $value || '' === $value ) {
532 return '-1';
533 }
534 $items = explode( ',', $value );
535 }
536
537 $cleaned = array();
538 foreach ( $items as $item ) {
539 $day = (string) absint( $item );
540 if ( in_array( $day, array( '0', '1', '2', '3', '4', '5', '6' ), true ) ) {
541 $cleaned[] = $day;
542 }
543 }
544
545 $cleaned = array_values( array_unique( $cleaned ) );
546
547 return empty( $cleaned ) ? '-1' : implode( ',', $cleaned );
548 }
549
550 /**
551 * Get settings response.
552 *
553 * @return array
554 */
555 function wpbc_settings_calendar__get_settings_response() {
556
557 $settings = array(
558 'booking_max_monthes_in_calendar' => (string) get_bk_option( 'booking_max_monthes_in_calendar' ),
559 'booking_start_day_weeek' => (string) get_bk_option( 'booking_start_day_weeek' ),
560 'booking_calendar_allow_several_months_on_mobile' => (string) get_bk_option( 'booking_calendar_allow_several_months_on_mobile' ),
561 'booking_type_of_day_selections' => (string) get_bk_option( 'booking_type_of_day_selections' ),
562 'booking_range_selection_type' => (string) get_bk_option( 'booking_range_selection_type' ),
563 'booking_range_selection_days_count' => (string) get_bk_option( 'booking_range_selection_days_count' ),
564 'booking_range_start_day' => wpbc_settings_calendar__normalize_week_days( get_bk_option( 'booking_range_start_day' ) ),
565 'booking_range_selection_days_count_dynamic' => (string) get_bk_option( 'booking_range_selection_days_count_dynamic' ),
566 'booking_range_selection_days_max_count_dynamic' => (string) get_bk_option( 'booking_range_selection_days_max_count_dynamic' ),
567 'booking_range_selection_days_specific_num_dynamic' => (string) get_bk_option( 'booking_range_selection_days_specific_num_dynamic' ),
568 'booking_range_start_day_dynamic' => wpbc_settings_calendar__normalize_week_days( get_bk_option( 'booking_range_start_day_dynamic' ) ),
569 'booking_recurrent_time' => (string) get_bk_option( 'booking_recurrent_time' ),
570 'booking_last_checkout_day_available' => (string) get_bk_option( 'booking_last_checkout_day_available' ),
571 'booking_range_selection_time_is_active' => (string) get_bk_option( 'booking_range_selection_time_is_active' ),
572 'booking_range_selection_start_time' => (string) get_bk_option( 'booking_range_selection_start_time' ),
573 'booking_range_selection_end_time' => (string) get_bk_option( 'booking_range_selection_end_time' ),
574 'booking_change_over_days_triangles' => (string) get_bk_option( 'booking_change_over_days_triangles' ),
575 'booking_change_over__is_excerpt_on_pages' => (string) get_bk_option( 'booking_change_over__is_excerpt_on_pages' ),
576 'booking_change_over__excerpt_on_pages' => (string) get_bk_option( 'booking_change_over__excerpt_on_pages' ),
577 'booking_change_over__excerpt_bk_resources' => (string) get_bk_option( 'booking_change_over__excerpt_bk_resources' ),
578 'booking_is_show_legend' => (string) get_bk_option( 'booking_is_show_legend' ),
579 'booking_legend_is_show_numbers' => (string) get_bk_option( 'booking_legend_is_show_numbers' ),
580 'booking_legend_is_vertical' => (string) get_bk_option( 'booking_legend_is_vertical' ),
581 'booking_disable_timeslots_in_tooltip' => (string) get_bk_option( 'booking_disable_timeslots_in_tooltip' ),
582 'booking_highlight_timeslot_word' => (string) get_bk_option( 'booking_highlight_timeslot_word' ),
583 );
584
585 foreach ( wpbc_settings_calendar__get_legend_items_config() as $legend_item => $legend_config ) {
586 $settings[ 'booking_legend_is_show_item_' . $legend_item ] = (string) get_bk_option( 'booking_legend_is_show_item_' . $legend_item );
587 $settings[ 'booking_legend_text_for_item_' . $legend_item ] = (string) get_bk_option( 'booking_legend_text_for_item_' . $legend_item );
588 }
589
590 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
591 $settings['booking_is_show_availability_in_tooltips'] = (string) get_bk_option( 'booking_is_show_availability_in_tooltips' );
592 $settings['booking_highlight_availability_word'] = (string) get_bk_option( 'booking_highlight_availability_word' );
593 $settings['booking_is_show_availability_in_date_cell'] = (string) get_bk_option( 'booking_is_show_availability_in_date_cell' );
594 $settings['booking_highlight_availability_word_in_date_cell'] = (string) get_bk_option( 'booking_highlight_availability_word_in_date_cell' );
595 }
596
597 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
598 $settings['booking_is_show_cost_in_tooltips'] = (string) get_bk_option( 'booking_is_show_cost_in_tooltips' );
599 $settings['booking_highlight_cost_word'] = (string) get_bk_option( 'booking_highlight_cost_word' );
600 $settings['booking_is_show_cost_in_date_cell'] = (string) get_bk_option( 'booking_is_show_cost_in_date_cell' );
601 $settings['booking_cost_in_date_cell_currency'] = (string) get_bk_option( 'booking_cost_in_date_cell_currency' );
602 $settings['booking_is_show_booked_data_in_tooltips'] = (string) get_bk_option( 'booking_is_show_booked_data_in_tooltips' );
603 $settings['booking_booked_data_in_tooltips'] = (string) get_bk_option( 'booking_booked_data_in_tooltips' );
604 }
605
606 return $settings;
607 }
608
609 /**
610 * Get normalized day-selection settings for the calendar JS.
611 *
612 * @param array $settings Optional settings.
613 *
614 * @return array
615 */
616 function wpbc_settings_calendar__get_days_selection_response( $settings = array() ) {
617
618 $current = wp_parse_args( $settings, wpbc_settings_calendar__get_settings_response() );
619
620 $specific_days = ( function_exists( 'wpbc_get_specific_range_dates__as_comma_list' ) )
621 ? wpbc_get_specific_range_dates__as_comma_list( $current['booking_range_selection_days_specific_num_dynamic'] )
622 : $current['booking_range_selection_days_specific_num_dynamic'];
623
624 return array(
625 'days_select_mode' => ( 'range' === $current['booking_type_of_day_selections'] ) ? $current['booking_range_selection_type'] : $current['booking_type_of_day_selections'],
626 'fixed__days_num' => max( 1, absint( $current['booking_range_selection_days_count'] ) ),
627 'fixed__week_days__start' => wpbc_settings_calendar__normalize_week_days( $current['booking_range_start_day'] ),
628 'dynamic__days_min' => max( 1, absint( $current['booking_range_selection_days_count_dynamic'] ) ),
629 'dynamic__days_max' => max( 1, absint( $current['booking_range_selection_days_max_count_dynamic'] ) ),
630 'dynamic__days_specific' => (string) $specific_days,
631 'dynamic__week_days__start' => wpbc_settings_calendar__normalize_week_days( $current['booking_range_start_day_dynamic'] ),
632 );
633 }
634
635 /**
636 * Check whether booked time slots should be shown in calendar tooltips.
637 *
638 * @param array $settings Calendar settings.
639 *
640 * @return bool
641 */
642 function wpbc_settings_calendar__is_timeslots_tooltip_enabled( $settings ) {
643
644 return ( 'On' !== (string) $settings['booking_disable_timeslots_in_tooltip'] );
645 }
646
647 /**
648 * Override get_bk_option during preview rendering.
649 *
650 * @param mixed $value Current value.
651 * @param string $option Option name.
652 * @param mixed $default Default.
653 *
654 * @return mixed
655 */
656 function wpbc_settings_calendar__preview_get_bk_option( $value, $option, $default ) {
657
658 global $wpbc_settings_calendar__preview_options;
659
660 if (
661 is_array( $wpbc_settings_calendar__preview_options )
662 && array_key_exists( $option, $wpbc_settings_calendar__preview_options )
663 ) {
664 return $wpbc_settings_calendar__preview_options[ $option ];
665 }
666
667 return $value;
668 }
669 add_bk_filter( 'wpdev_bk_get_option', 'wpbc_settings_calendar__preview_get_bk_option' );
670
671 /**
672 * Override native WordPress options while Calendar Settings preview is active.
673 *
674 * This backs up the internal WPBC option filter for render paths that fall through
675 * to get_option(), without saving preview values into the database.
676 *
677 * @param mixed $pre_option Pre-option value.
678 * @param string $option Option name.
679 * @param mixed $default Default option value.
680 *
681 * @return mixed
682 */
683 function wpbc_settings_calendar__preview_get_wp_option( $pre_option, $option, $default ) {
684
685 global $wpbc_settings_calendar__preview_options;
686
687 if (
688 is_array( $wpbc_settings_calendar__preview_options )
689 && array_key_exists( $option, $wpbc_settings_calendar__preview_options )
690 ) {
691 return $wpbc_settings_calendar__preview_options[ $option ];
692 }
693
694 return $pre_option;
695 }
696
697 /**
698 * Register native option preview filters for the current option set.
699 *
700 * @param array $preview_options Preview option overrides.
701 *
702 * @return void
703 */
704 function wpbc_settings_calendar__preview_register_wp_option_filters( $preview_options ) {
705
706 global $wpbc_settings_calendar__preview_wp_option_filters;
707
708 if ( ! is_array( $preview_options ) ) {
709 return;
710 }
711
712 if ( ! is_array( $wpbc_settings_calendar__preview_wp_option_filters ) ) {
713 $wpbc_settings_calendar__preview_wp_option_filters = array();
714 }
715
716 foreach ( array_keys( $preview_options ) as $option_name ) {
717 $option_name = (string) $option_name;
718 if ( isset( $wpbc_settings_calendar__preview_wp_option_filters[ $option_name ] ) ) {
719 continue;
720 }
721 add_filter( 'pre_option_' . $option_name, 'wpbc_settings_calendar__preview_get_wp_option', 10, 3 );
722 $wpbc_settings_calendar__preview_wp_option_filters[ $option_name ] = true;
723 }
724 }
725
726 /**
727 * Activate Calendar Settings preview option overrides.
728 *
729 * @param array $preview_options Preview option overrides.
730 *
731 * @return array Previous preview context.
732 */
733 function wpbc_settings_calendar__preview_options_push( $preview_options ) {
734
735 global $wpbc_settings_calendar__preview_options;
736
737 $previous_context = array(
738 'is_set' => isset( $wpbc_settings_calendar__preview_options ),
739 'value' => isset( $wpbc_settings_calendar__preview_options ) ? $wpbc_settings_calendar__preview_options : null,
740 );
741
742 $wpbc_settings_calendar__preview_options = is_array( $preview_options ) ? $preview_options : array();
743
744 // Re-append while preview is active so this override runs after edition/MU option filters.
745 add_bk_filter( 'wpdev_bk_get_option', 'wpbc_settings_calendar__preview_get_bk_option' );
746
747 wpbc_settings_calendar__preview_register_wp_option_filters( $wpbc_settings_calendar__preview_options );
748
749 return $previous_context;
750 }
751
752 /**
753 * Restore Calendar Settings preview option overrides.
754 *
755 * @param array $previous_context Previous preview context from wpbc_settings_calendar__preview_options_push().
756 *
757 * @return void
758 */
759 function wpbc_settings_calendar__preview_options_pop( $previous_context ) {
760
761 global $wpbc_settings_calendar__preview_options;
762
763 if ( ! empty( $previous_context['is_set'] ) ) {
764 $wpbc_settings_calendar__preview_options = $previous_context['value'];
765 } else {
766 unset( $wpbc_settings_calendar__preview_options );
767 }
768 }
769
770 /**
771 * Check whether a calendar-load AJAX request may use Calendar Settings preview overrides.
772 *
773 * @param array $request_params Calendar-load request params.
774 *
775 * @return bool
776 */
777 function wpbc_settings_calendar__is_calendar_load_preview_request_allowed( $request_params ) {
778
779 return (
780 ! empty( $request_params['wpbc_settings_calendar_preview'] )
781 && function_exists( 'wpbc_is_mu_user_can_be_here' )
782 && wpbc_is_mu_user_can_be_here( 'only_super_admin' )
783 && current_user_can( wpbc_settings_calendar__get_manage_cap() )
784 );
785 }
786
787 /**
788 * Get option overrides from Calendar Settings calendar-load AJAX request.
789 *
790 * @param array $request_params Calendar-load request params.
791 *
792 * @return array
793 */
794 function wpbc_settings_calendar__get_calendar_load_preview_options( $request_params ) {
795
796 $preview_options = array(
797 'booking_range_selection_time_is_active' => isset( $request_params['wpbc_settings_calendar_preview_changeover'] ) ? $request_params['wpbc_settings_calendar_preview_changeover'] : 'Off',
798 'booking_change_over_days_triangles' => isset( $request_params['wpbc_settings_calendar_preview_triangles'] ) ? $request_params['wpbc_settings_calendar_preview_triangles'] : 'On',
799 'booking_recurrent_time' => isset( $request_params['wpbc_settings_calendar_preview_recurrent_time'] ) ? $request_params['wpbc_settings_calendar_preview_recurrent_time'] : 'Off',
800 'booking_last_checkout_day_available' => isset( $request_params['wpbc_settings_calendar_preview_last_checkout'] ) ? $request_params['wpbc_settings_calendar_preview_last_checkout'] : 'Off',
801 'booking_change_over__is_excerpt_on_pages' => isset( $request_params['wpbc_settings_calendar_preview_excerpt_on_pages'] ) ? $request_params['wpbc_settings_calendar_preview_excerpt_on_pages'] : 'Off',
802 'booking_change_over__excerpt_on_pages' => isset( $request_params['wpbc_settings_calendar_preview_excerpt_pages'] ) ? $request_params['wpbc_settings_calendar_preview_excerpt_pages'] : '',
803 'booking_change_over__excerpt_bk_resources' => isset( $request_params['wpbc_settings_calendar_preview_excerpt_resources'] ) ? $request_params['wpbc_settings_calendar_preview_excerpt_resources'] : '',
804 'booking_is_show_legend' => isset( $request_params['wpbc_settings_calendar_preview_show_legend'] ) ? $request_params['wpbc_settings_calendar_preview_show_legend'] : 'Off',
805 'booking_legend_is_show_numbers' => isset( $request_params['wpbc_settings_calendar_preview_legend_show_numbers'] ) ? $request_params['wpbc_settings_calendar_preview_legend_show_numbers'] : 'Off',
806 'booking_legend_is_vertical' => isset( $request_params['wpbc_settings_calendar_preview_legend_vertical'] ) ? $request_params['wpbc_settings_calendar_preview_legend_vertical'] : 'Off',
807 'booking_disable_timeslots_in_tooltip' => isset( $request_params['wpbc_settings_calendar_preview_disable_timeslots_tooltip'] ) ? $request_params['wpbc_settings_calendar_preview_disable_timeslots_tooltip'] : 'Off',
808 'booking_highlight_timeslot_word' => isset( $request_params['wpbc_settings_calendar_preview_timeslot_word'] ) ? $request_params['wpbc_settings_calendar_preview_timeslot_word'] : '',
809 );
810
811 foreach ( wpbc_settings_calendar__get_legend_items_config() as $legend_item => $legend_config ) {
812 $preview_options[ 'booking_legend_is_show_item_' . $legend_item ] = isset( $request_params[ 'wpbc_settings_calendar_preview_legend_show_' . $legend_item ] ) ? $request_params[ 'wpbc_settings_calendar_preview_legend_show_' . $legend_item ] : 'Off';
813 $preview_options[ 'booking_legend_text_for_item_' . $legend_item ] = isset( $request_params[ 'wpbc_settings_calendar_preview_legend_text_' . $legend_item ] ) ? $request_params[ 'wpbc_settings_calendar_preview_legend_text_' . $legend_item ] : '';
814 }
815
816 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
817 $preview_options['booking_is_show_availability_in_tooltips'] = isset( $request_params['wpbc_settings_calendar_preview_show_availability_tooltip'] ) ? $request_params['wpbc_settings_calendar_preview_show_availability_tooltip'] : 'Off';
818 $preview_options['booking_highlight_availability_word'] = isset( $request_params['wpbc_settings_calendar_preview_availability_word'] ) ? $request_params['wpbc_settings_calendar_preview_availability_word'] : '';
819 $preview_options['booking_is_show_availability_in_date_cell'] = isset( $request_params['wpbc_settings_calendar_preview_show_availability_cell'] ) ? $request_params['wpbc_settings_calendar_preview_show_availability_cell'] : 'Off';
820 $preview_options['booking_highlight_availability_word_in_date_cell'] = isset( $request_params['wpbc_settings_calendar_preview_availability_cell_word'] ) ? $request_params['wpbc_settings_calendar_preview_availability_cell_word'] : '';
821 }
822
823 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
824 $preview_options['booking_is_show_cost_in_tooltips'] = isset( $request_params['wpbc_settings_calendar_preview_show_cost_tooltip'] ) ? $request_params['wpbc_settings_calendar_preview_show_cost_tooltip'] : 'Off';
825 $preview_options['booking_highlight_cost_word'] = isset( $request_params['wpbc_settings_calendar_preview_cost_word'] ) ? $request_params['wpbc_settings_calendar_preview_cost_word'] : '';
826 $preview_options['booking_is_show_cost_in_date_cell'] = isset( $request_params['wpbc_settings_calendar_preview_show_cost_cell'] ) ? $request_params['wpbc_settings_calendar_preview_show_cost_cell'] : 'Off';
827 $preview_options['booking_cost_in_date_cell_currency'] = isset( $request_params['wpbc_settings_calendar_preview_cost_currency'] ) ? $request_params['wpbc_settings_calendar_preview_cost_currency'] : '';
828 $preview_options['booking_is_show_booked_data_in_tooltips'] = isset( $request_params['wpbc_settings_calendar_preview_show_booked_details'] ) ? $request_params['wpbc_settings_calendar_preview_show_booked_details'] : 'Off';
829 $preview_options['booking_booked_data_in_tooltips'] = isset( $request_params['wpbc_settings_calendar_preview_booked_details'] ) ? $request_params['wpbc_settings_calendar_preview_booked_details'] : '';
830 }
831
832 return $preview_options;
833 }
834
835 /**
836 * Get request overrides for the calendar-load AJAX generated inside Calendar Settings preview.
837 *
838 * @param array $current_settings Current preview settings.
839 *
840 * @return array
841 */
842 function wpbc_settings_calendar__get_calendar_load_preview_request_overrides( $current_settings ) {
843
844 $request_overrides = array(
845 'wpbc_settings_calendar_preview' => 1,
846 'wpbc_settings_calendar_preview_changeover' => ( 'On' === (string) $current_settings['booking_range_selection_time_is_active'] ) ? 'On' : 'Off',
847 'wpbc_settings_calendar_preview_triangles' => ( 'Off' === (string) $current_settings['booking_change_over_days_triangles'] ) ? 'Off' : 'On',
848 'wpbc_settings_calendar_preview_recurrent_time' => ( 'On' === (string) $current_settings['booking_recurrent_time'] ) ? 'On' : 'Off',
849 'wpbc_settings_calendar_preview_last_checkout' => ( 'On' === (string) $current_settings['booking_last_checkout_day_available'] ) ? 'On' : 'Off',
850 'wpbc_settings_calendar_preview_excerpt_on_pages' => ( 'On' === (string) $current_settings['booking_change_over__is_excerpt_on_pages'] ) ? 'On' : 'Off',
851 'wpbc_settings_calendar_preview_excerpt_pages' => (string) $current_settings['booking_change_over__excerpt_on_pages'],
852 'wpbc_settings_calendar_preview_excerpt_resources' => (string) $current_settings['booking_change_over__excerpt_bk_resources'],
853 'wpbc_settings_calendar_preview_show_legend' => ( 'On' === (string) $current_settings['booking_is_show_legend'] ) ? 'On' : 'Off',
854 'wpbc_settings_calendar_preview_legend_show_numbers' => ( 'On' === (string) $current_settings['booking_legend_is_show_numbers'] ) ? 'On' : 'Off',
855 'wpbc_settings_calendar_preview_legend_vertical' => ( 'On' === (string) $current_settings['booking_legend_is_vertical'] ) ? 'On' : 'Off',
856 'wpbc_settings_calendar_preview_disable_timeslots_tooltip' => ( 'On' === (string) $current_settings['booking_disable_timeslots_in_tooltip'] ) ? 'On' : 'Off',
857 'wpbc_settings_calendar_preview_timeslot_word' => (string) $current_settings['booking_highlight_timeslot_word'],
858 );
859
860 foreach ( wpbc_settings_calendar__get_legend_items_config() as $legend_item => $legend_config ) {
861 $is_show_key = 'booking_legend_is_show_item_' . $legend_item;
862 $text_key = 'booking_legend_text_for_item_' . $legend_item;
863 if ( isset( $current_settings[ $is_show_key ] ) ) {
864 $request_overrides[ 'wpbc_settings_calendar_preview_legend_show_' . $legend_item ] = ( 'On' === (string) $current_settings[ $is_show_key ] ) ? 'On' : 'Off';
865 }
866 if ( isset( $current_settings[ $text_key ] ) ) {
867 $request_overrides[ 'wpbc_settings_calendar_preview_legend_text_' . $legend_item ] = (string) $current_settings[ $text_key ];
868 }
869 }
870
871 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
872 $request_overrides['wpbc_settings_calendar_preview_show_availability_tooltip'] = ( 'On' === (string) $current_settings['booking_is_show_availability_in_tooltips'] ) ? 'On' : 'Off';
873 $request_overrides['wpbc_settings_calendar_preview_availability_word'] = (string) $current_settings['booking_highlight_availability_word'];
874 $request_overrides['wpbc_settings_calendar_preview_show_availability_cell'] = ( 'On' === (string) $current_settings['booking_is_show_availability_in_date_cell'] ) ? 'On' : 'Off';
875 $request_overrides['wpbc_settings_calendar_preview_availability_cell_word'] = (string) $current_settings['booking_highlight_availability_word_in_date_cell'];
876 }
877
878 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
879 $request_overrides['wpbc_settings_calendar_preview_show_cost_tooltip'] = ( 'On' === (string) $current_settings['booking_is_show_cost_in_tooltips'] ) ? 'On' : 'Off';
880 $request_overrides['wpbc_settings_calendar_preview_cost_word'] = (string) $current_settings['booking_highlight_cost_word'];
881 $request_overrides['wpbc_settings_calendar_preview_show_cost_cell'] = ( 'On' === (string) $current_settings['booking_is_show_cost_in_date_cell'] ) ? 'On' : 'Off';
882 $request_overrides['wpbc_settings_calendar_preview_cost_currency'] = (string) $current_settings['booking_cost_in_date_cell_currency'];
883 $request_overrides['wpbc_settings_calendar_preview_show_booked_details'] = ( 'On' === (string) $current_settings['booking_is_show_booked_data_in_tooltips'] ) ? 'On' : 'Off';
884 $request_overrides['wpbc_settings_calendar_preview_booked_details'] = (string) $current_settings['booking_booked_data_in_tooltips'];
885 }
886
887 return $request_overrides;
888 }
889
890 /**
891 * Check change-over state while Calendar Settings preview option overrides are active.
892 *
893 * @param int|string $resource_id Booking resource ID.
894 * @param string|false $request_uri Request URI or false for current URI.
895 *
896 * @return bool|null Boolean when preview context is active, null otherwise.
897 */
898 function wpbc_settings_calendar__preview_is_changeover_enabled( $resource_id = 0, $request_uri = false ) {
899
900 global $wpbc_settings_calendar__preview_options;
901
902 if ( ! is_array( $wpbc_settings_calendar__preview_options ) ) {
903 return null;
904 }
905
906 if (
907 ! isset( $wpbc_settings_calendar__preview_options['booking_range_selection_time_is_active'] )
908 || 'On' !== (string) $wpbc_settings_calendar__preview_options['booking_range_selection_time_is_active']
909 ) {
910 return false;
911 }
912
913 if ( function_exists( 'wpbc_is_booking_used_check_in_out_time' ) ) {
914 return wpbc_is_booking_used_check_in_out_time( $request_uri, $resource_id );
915 }
916
917 return true;
918 }
919
920 /**
921 * Validate page data.
922 *
923 * @param array $post_data Raw post data.
924 *
925 * @return array
926 */
927 function wpbc_settings_calendar__validate_data( $post_data, $is_preview = false ) {
928
929 $current = wpbc_settings_calendar__get_settings_response();
930 $max_months = wpbc_settings_calendar__get_max_month_options();
931 $weekdays = wpbc_settings_calendar__get_weekday_options();
932 $range_supported = wpbc_settings_calendar__is_range_supported();
933 $cleaned = array();
934
935 $max_monthes = isset( $post_data['booking_max_monthes_in_calendar'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_max_monthes_in_calendar'] ) ) : $current['booking_max_monthes_in_calendar'];
936 $cleaned['booking_max_monthes_in_calendar'] = isset( $max_months[ $max_monthes ] ) ? $max_monthes : '1y';
937
938 $start_day = isset( $post_data['booking_start_day_weeek'] ) ? sanitize_key( wp_unslash( $post_data['booking_start_day_weeek'] ) ) : $current['booking_start_day_weeek'];
939 $cleaned['booking_start_day_weeek'] = array_key_exists( $start_day, $weekdays ) ? $start_day : '0';
940
941 $cleaned['booking_calendar_allow_several_months_on_mobile'] = ( isset( $post_data['booking_calendar_allow_several_months_on_mobile'] ) && 'On' === wp_unslash( $post_data['booking_calendar_allow_several_months_on_mobile'] ) ) ? 'On' : 'Off';
942
943 $day_mode = isset( $post_data['booking_type_of_day_selections'] ) ? sanitize_key( wp_unslash( $post_data['booking_type_of_day_selections'] ) ) : $current['booking_type_of_day_selections'];
944 if ( ! in_array( $day_mode, array( 'single', 'multiple', 'range' ), true ) ) {
945 $day_mode = 'multiple';
946 }
947 $cleaned['booking_type_of_day_selections'] = $day_mode;
948
949 $range_type = isset( $post_data['booking_range_selection_type'] ) ? sanitize_key( wp_unslash( $post_data['booking_range_selection_type'] ) ) : $current['booking_range_selection_type'];
950 $cleaned['booking_range_selection_type'] = in_array( $range_type, array( 'fixed', 'dynamic' ), true ) ? $range_type : 'dynamic';
951
952 $cleaned['booking_range_selection_days_count'] = (string) min( 180, max( 1, absint( isset( $post_data['booking_range_selection_days_count'] ) ? wp_unslash( $post_data['booking_range_selection_days_count'] ) : $current['booking_range_selection_days_count'] ) ) );
953 $cleaned['booking_range_selection_days_count_dynamic'] = (string) min( 1095, max( 1, absint( isset( $post_data['booking_range_selection_days_count_dynamic'] ) ? wp_unslash( $post_data['booking_range_selection_days_count_dynamic'] ) : $current['booking_range_selection_days_count_dynamic'] ) ) );
954 $cleaned['booking_range_selection_days_max_count_dynamic'] = (string) min( 1095, max( 1, absint( isset( $post_data['booking_range_selection_days_max_count_dynamic'] ) ? wp_unslash( $post_data['booking_range_selection_days_max_count_dynamic'] ) : $current['booking_range_selection_days_max_count_dynamic'] ) ) );
955 if ( (int) $cleaned['booking_range_selection_days_max_count_dynamic'] < (int) $cleaned['booking_range_selection_days_count_dynamic'] ) {
956 $cleaned['booking_range_selection_days_max_count_dynamic'] = $cleaned['booking_range_selection_days_count_dynamic'];
957 }
958
959 $cleaned['booking_range_selection_days_specific_num_dynamic'] = isset( $post_data['booking_range_selection_days_specific_num_dynamic'] )
960 ? preg_replace( '/[^0-9,\-\s]/', '', sanitize_text_field( wp_unslash( $post_data['booking_range_selection_days_specific_num_dynamic'] ) ) )
961 : $current['booking_range_selection_days_specific_num_dynamic'];
962
963 $fixed_start_mode = isset( $post_data['booking_range_start_day_mode'] ) ? sanitize_key( wp_unslash( $post_data['booking_range_start_day_mode'] ) ) : ( '-1' === $current['booking_range_start_day'] ? '-1' : 'specific' );
964 $dynamic_start_mode = isset( $post_data['booking_range_start_day_dynamic_mode'] ) ? sanitize_key( wp_unslash( $post_data['booking_range_start_day_dynamic_mode'] ) ) : ( '-1' === $current['booking_range_start_day_dynamic'] ? '-1' : 'specific' );
965 $cleaned['booking_range_start_day'] = ( '-1' === $fixed_start_mode )
966 ? '-1'
967 : wpbc_settings_calendar__normalize_week_days( isset( $post_data['booking_range_start_day_weekdays'] ) ? wp_unslash( $post_data['booking_range_start_day_weekdays'] ) : $current['booking_range_start_day'] );
968 $cleaned['booking_range_start_day_dynamic'] = ( '-1' === $dynamic_start_mode )
969 ? '-1'
970 : wpbc_settings_calendar__normalize_week_days( isset( $post_data['booking_range_start_day_dynamic_weekdays'] ) ? wp_unslash( $post_data['booking_range_start_day_dynamic_weekdays'] ) : $current['booking_range_start_day_dynamic'] );
971
972 $cleaned['booking_recurrent_time'] = ( isset( $post_data['booking_recurrent_time'] ) && 'On' === wp_unslash( $post_data['booking_recurrent_time'] ) ) ? 'On' : 'Off';
973 $cleaned['booking_last_checkout_day_available'] = ( isset( $post_data['booking_last_checkout_day_available'] ) && 'On' === wp_unslash( $post_data['booking_last_checkout_day_available'] ) ) ? 'On' : 'Off';
974 $cleaned['booking_range_selection_time_is_active'] = ( isset( $post_data['booking_range_selection_time_is_active'] ) && 'On' === wp_unslash( $post_data['booking_range_selection_time_is_active'] ) ) ? 'On' : 'Off';
975 $cleaned['booking_change_over_days_triangles'] = ( isset( $post_data['booking_change_over_days_triangles'] ) && 'On' === wp_unslash( $post_data['booking_change_over_days_triangles'] ) ) ? 'On' : 'Off';
976 $cleaned['booking_change_over__is_excerpt_on_pages'] = ( isset( $post_data['booking_change_over__is_excerpt_on_pages'] ) && 'On' === wp_unslash( $post_data['booking_change_over__is_excerpt_on_pages'] ) ) ? 'On' : 'Off';
977
978 foreach ( array( 'booking_range_selection_start_time', 'booking_range_selection_end_time' ) as $time_key ) {
979 $time_value = isset( $post_data[ $time_key ] ) ? sanitize_text_field( wp_unslash( $post_data[ $time_key ] ) ) : $current[ $time_key ];
980 $cleaned[ $time_key ] = preg_match( '/^\d{2}:\d{2}$/', $time_value ) ? $time_value : $current[ $time_key ];
981 }
982
983 $cleaned['booking_change_over__excerpt_on_pages'] = isset( $post_data['booking_change_over__excerpt_on_pages'] ) ? sanitize_textarea_field( wp_unslash( $post_data['booking_change_over__excerpt_on_pages'] ) ) : $current['booking_change_over__excerpt_on_pages'];
984 $cleaned['booking_change_over__excerpt_bk_resources'] = isset( $post_data['booking_change_over__excerpt_bk_resources'] ) ? sanitize_textarea_field( wp_unslash( $post_data['booking_change_over__excerpt_bk_resources'] ) ) : $current['booking_change_over__excerpt_bk_resources'];
985
986 $cleaned['booking_is_show_legend'] = ( isset( $post_data['booking_is_show_legend'] ) && 'On' === wp_unslash( $post_data['booking_is_show_legend'] ) ) ? 'On' : 'Off';
987 $cleaned['booking_legend_is_show_numbers'] = ( isset( $post_data['booking_legend_is_show_numbers'] ) && 'On' === wp_unslash( $post_data['booking_legend_is_show_numbers'] ) ) ? 'On' : 'Off';
988 $cleaned['booking_legend_is_vertical'] = ( isset( $post_data['booking_legend_is_vertical'] ) && 'On' === wp_unslash( $post_data['booking_legend_is_vertical'] ) ) ? 'On' : 'Off';
989 if ( isset( $post_data['booking_show_timeslots_in_tooltip'] ) ) {
990 $cleaned['booking_disable_timeslots_in_tooltip'] = ( 'On' === wp_unslash( $post_data['booking_show_timeslots_in_tooltip'] ) ) ? 'Off' : 'On';
991 } else {
992 $cleaned['booking_disable_timeslots_in_tooltip'] = ( isset( $post_data['booking_disable_timeslots_in_tooltip'] ) && 'On' === wp_unslash( $post_data['booking_disable_timeslots_in_tooltip'] ) ) ? 'On' : 'Off';
993 }
994 $cleaned['booking_highlight_timeslot_word'] = isset( $post_data['booking_highlight_timeslot_word'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_highlight_timeslot_word'] ) ) : $current['booking_highlight_timeslot_word'];
995
996 foreach ( wpbc_settings_calendar__get_legend_items_config() as $legend_item => $legend_config ) {
997 $is_show_key = 'booking_legend_is_show_item_' . $legend_item;
998 $text_key = 'booking_legend_text_for_item_' . $legend_item;
999 $cleaned[ $is_show_key ] = ( isset( $post_data[ $is_show_key ] ) && 'On' === wp_unslash( $post_data[ $is_show_key ] ) ) ? 'On' : 'Off';
1000 $cleaned[ $text_key ] = isset( $post_data[ $text_key ] ) ? sanitize_text_field( wp_unslash( $post_data[ $text_key ] ) ) : $current[ $text_key ];
1001 }
1002
1003 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1004 $cleaned['booking_is_show_availability_in_tooltips'] = ( isset( $post_data['booking_is_show_availability_in_tooltips'] ) && 'On' === wp_unslash( $post_data['booking_is_show_availability_in_tooltips'] ) ) ? 'On' : 'Off';
1005 $cleaned['booking_highlight_availability_word'] = isset( $post_data['booking_highlight_availability_word'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_highlight_availability_word'] ) ) : $current['booking_highlight_availability_word'];
1006 $cleaned['booking_is_show_availability_in_date_cell'] = ( isset( $post_data['booking_is_show_availability_in_date_cell'] ) && 'On' === wp_unslash( $post_data['booking_is_show_availability_in_date_cell'] ) ) ? 'On' : 'Off';
1007 $cleaned['booking_highlight_availability_word_in_date_cell'] = isset( $post_data['booking_highlight_availability_word_in_date_cell'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_highlight_availability_word_in_date_cell'] ) ) : $current['booking_highlight_availability_word_in_date_cell'];
1008 }
1009
1010 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
1011 $cleaned['booking_is_show_cost_in_tooltips'] = ( isset( $post_data['booking_is_show_cost_in_tooltips'] ) && 'On' === wp_unslash( $post_data['booking_is_show_cost_in_tooltips'] ) ) ? 'On' : 'Off';
1012 $cleaned['booking_highlight_cost_word'] = isset( $post_data['booking_highlight_cost_word'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_highlight_cost_word'] ) ) : $current['booking_highlight_cost_word'];
1013 $cleaned['booking_is_show_cost_in_date_cell'] = ( isset( $post_data['booking_is_show_cost_in_date_cell'] ) && 'On' === wp_unslash( $post_data['booking_is_show_cost_in_date_cell'] ) ) ? 'On' : 'Off';
1014 $cleaned['booking_cost_in_date_cell_currency'] = isset( $post_data['booking_cost_in_date_cell_currency'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_cost_in_date_cell_currency'] ) ) : $current['booking_cost_in_date_cell_currency'];
1015 $cleaned['booking_is_show_booked_data_in_tooltips'] = ( isset( $post_data['booking_is_show_booked_data_in_tooltips'] ) && 'On' === wp_unslash( $post_data['booking_is_show_booked_data_in_tooltips'] ) ) ? 'On' : 'Off';
1016 $cleaned['booking_booked_data_in_tooltips'] = isset( $post_data['booking_booked_data_in_tooltips'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_booked_data_in_tooltips'] ) ) : $current['booking_booked_data_in_tooltips'];
1017 }
1018
1019 if ( ! $is_preview && ! $range_supported ) {
1020 foreach ( array( 'booking_range_selection_time_is_active', 'booking_last_checkout_day_available', 'booking_change_over_days_triangles', 'booking_change_over__is_excerpt_on_pages' ) as $premium_key ) {
1021 $cleaned[ $premium_key ] = $current[ $premium_key ];
1022 }
1023 }
1024
1025 return $cleaned;
1026 }
1027
1028 /**
1029 * Update settings.
1030 *
1031 * @param array $cleaned_data Cleaned data.
1032 *
1033 * @return void
1034 */
1035 function wpbc_settings_calendar__update_settings( $cleaned_data ) {
1036
1037 $range_supported = wpbc_settings_calendar__is_range_supported();
1038 $free_keys = array(
1039 'booking_max_monthes_in_calendar',
1040 'booking_start_day_weeek',
1041 'booking_calendar_allow_several_months_on_mobile',
1042 'booking_type_of_day_selections',
1043 'booking_recurrent_time',
1044 'booking_is_show_legend',
1045 'booking_legend_is_show_numbers',
1046 'booking_legend_is_vertical',
1047 'booking_disable_timeslots_in_tooltip',
1048 'booking_highlight_timeslot_word',
1049 );
1050 $premium_keys = array(
1051 'booking_range_selection_type',
1052 'booking_range_selection_days_count',
1053 'booking_range_start_day',
1054 'booking_range_selection_days_count_dynamic',
1055 'booking_range_selection_days_max_count_dynamic',
1056 'booking_range_selection_days_specific_num_dynamic',
1057 'booking_range_start_day_dynamic',
1058 'booking_last_checkout_day_available',
1059 'booking_range_selection_time_is_active',
1060 'booking_range_selection_start_time',
1061 'booking_range_selection_end_time',
1062 'booking_change_over_days_triangles',
1063 'booking_change_over__is_excerpt_on_pages',
1064 'booking_change_over__excerpt_on_pages',
1065 'booking_change_over__excerpt_bk_resources',
1066 );
1067 $availability_tooltip_keys = array(
1068 'booking_is_show_availability_in_tooltips',
1069 'booking_highlight_availability_word',
1070 'booking_is_show_availability_in_date_cell',
1071 'booking_highlight_availability_word_in_date_cell',
1072 );
1073 $cost_tooltip_keys = array(
1074 'booking_is_show_cost_in_tooltips',
1075 'booking_highlight_cost_word',
1076 'booking_is_show_cost_in_date_cell',
1077 'booking_cost_in_date_cell_currency',
1078 'booking_is_show_booked_data_in_tooltips',
1079 'booking_booked_data_in_tooltips',
1080 );
1081 foreach ( wpbc_settings_calendar__get_legend_items_config() as $legend_item => $legend_config ) {
1082 $free_keys[] = 'booking_legend_is_show_item_' . $legend_item;
1083 $free_keys[] = 'booking_legend_text_for_item_' . $legend_item;
1084 }
1085
1086 foreach ( $free_keys as $key ) {
1087 if ( 'booking_type_of_day_selections' === $key && ! $range_supported && 'range' === $cleaned_data[ $key ] ) {
1088 continue;
1089 }
1090 update_bk_option( $key, $cleaned_data[ $key ] );
1091 }
1092
1093 if ( $range_supported ) {
1094 foreach ( $premium_keys as $key ) {
1095 update_bk_option( $key, $cleaned_data[ $key ] );
1096 }
1097 }
1098
1099 if ( class_exists( 'wpdev_bk_biz_l' ) ) {
1100 foreach ( $availability_tooltip_keys as $key ) {
1101 update_bk_option( $key, $cleaned_data[ $key ] );
1102 }
1103 }
1104
1105 if ( class_exists( 'wpdev_bk_biz_m' ) ) {
1106 foreach ( $cost_tooltip_keys as $key ) {
1107 update_bk_option( $key, $cleaned_data[ $key ] );
1108 }
1109 }
1110 }
1111
1112 /**
1113 * Render select element.
1114 *
1115 * @param string $name Name.
1116 * @param array $options Options.
1117 * @param string $selected Selected value.
1118 * @param array $args Arguments.
1119 *
1120 * @return void
1121 */
1122 function wpbc_settings_calendar__render_select( $name, $options, $selected, $args = array() ) {
1123
1124 $id = isset( $args['id'] ) ? $args['id'] : $name;
1125 $class = isset( $args['class'] ) ? $args['class'] : '';
1126 ?>
1127 <select id="<?php echo esc_attr( $id ); ?>" name="<?php echo esc_attr( $name ); ?>" class="<?php echo esc_attr( $class ); ?>">
1128 <?php foreach ( $options as $value => $label ) : ?>
1129 <option value="<?php echo esc_attr( $value ); ?>" <?php selected( (string) $selected, (string) $value ); ?>><?php echo esc_html( $label ); ?></option>
1130 <?php endforeach; ?>
1131 </select>
1132 <?php
1133 }
1134
1135 /**
1136 * Get premium feature URL by required version label.
1137 *
1138 * @param string $label Premium label.
1139 * @param string $url Optional explicit URL.
1140 *
1141 * @return string
1142 */
1143 function wpbc_settings_calendar__get_premium_url( $label = 'Pro', $url = '' ) {
1144
1145 $generic_features_url = 'https://wpbookingcalendar.com/features/';
1146 $url = trim( (string) $url );
1147
1148 if ( ( '' !== $url ) && ( $generic_features_url !== $url ) ) {
1149 return $url;
1150 }
1151
1152 $label = strtolower( (string) $label );
1153
1154 if ( false !== strpos( $label, 'multiuser' ) ) {
1155 return 'https://wpbookingcalendar.com/features/#multiuser';
1156 }
1157 if ( false !== strpos( $label, 'business large' ) || false !== strpos( $label, 'bl+' ) ) {
1158 return 'https://wpbookingcalendar.com/features/#bl';
1159 }
1160 if ( false !== strpos( $label, 'business medium' ) || false !== strpos( $label, 'bm+' ) ) {
1161 return 'https://wpbookingcalendar.com/features/#bm';
1162 }
1163 if ( false !== strpos( $label, 'business small' ) || false !== strpos( $label, 'bs+' ) ) {
1164 return 'https://wpbookingcalendar.com/features/#bs';
1165 }
1166
1167 return $generic_features_url;
1168 }
1169
1170 /**
1171 * Render premium label.
1172 *
1173 * @return void
1174 */
1175 function wpbc_settings_calendar__render_premium_label( $label = 'Business Small+', $url = 'https://wpbookingcalendar.com/features/', $dismiss_id = '' ) {
1176
1177 $url = wpbc_settings_calendar__get_premium_url( $label, $url );
1178 ?>
1179 <a class="wpbc_pro_label wpbc_calendar_pro_label" href="<?php echo esc_url( $url ); ?>" target="_blank"><?php echo esc_html( $label ); ?></a>
1180 <?php if ( '' !== $dismiss_id ) : ?>
1181 <?php wpbc_settings_calendar__render_dismiss_button( $dismiss_id ); ?>
1182 <?php endif; ?>
1183 <?php
1184 }
1185
1186 /**
1187 * Check if a Calendar Settings upsell row is visible for current user.
1188 *
1189 * @param string $dismiss_id Dismiss ID.
1190 *
1191 * @return bool
1192 */
1193 function wpbc_settings_calendar__is_dismissed_visible( $dismiss_id ) {
1194
1195 if ( wpbc_is_this_demo() ) {
1196 return true;
1197 }
1198
1199 return ! function_exists( 'wpbc_is_dismissed_panel_visible' ) || wpbc_is_dismissed_panel_visible( $dismiss_id );
1200 }
1201
1202 /**
1203 * Get dismiss ID for a Calendar Settings premium option.
1204 *
1205 * @param string $option_name Option name.
1206 *
1207 * @return string
1208 */
1209 function wpbc_settings_calendar__get_premium_option_dismiss_id( $option_name ) {
1210
1211 return 'wpbc_is_dismissed__calendar_settings__' . sanitize_key( $option_name );
1212 }
1213
1214 /**
1215 * Render small dismiss button for Calendar Settings premium hints.
1216 *
1217 * @param string $dismiss_id Dismiss ID.
1218 *
1219 * @return void
1220 */
1221 function wpbc_settings_calendar__render_dismiss_button( $dismiss_id ) {
1222
1223 if ( wpbc_is_this_demo() || ! function_exists( 'wpbc_is_dismissed' ) ) {
1224 return;
1225 }
1226
1227 ?>
1228 <span class="wpbc_calendar_premium_dismiss">
1229 <?php
1230 wpbc_is_dismissed(
1231 $dismiss_id,
1232 array(
1233 'title' => '&times;',
1234 'hint' => __( 'Hide this option', 'booking' ),
1235 'css' => 'float:none;margin-left:4px;',
1236 )
1237 );
1238 ?>
1239 </span>
1240 <?php
1241 }
1242
1243 /**
1244 * Render shared Business Small+ explanation for range/changeover locked controls.
1245 *
1246 * @return void
1247 */
1248 function wpbc_settings_calendar__render_range_upgrade_note() {
1249
1250 ?>
1251 <div class="wpbc_calendar_premium_note" data-wpbc-calendar-range-upgrade-note="1">
1252 <div>
1253 <strong><?php esc_html_e( 'Range days selection', 'booking' ); ?></strong>
1254 <p><?php esc_html_e( 'Visitors select a start and end date, with optional minimum and maximum range length and allowed start weekdays. This feature is available in Booking Calendar Business Small or higher.', 'booking' ); ?></p>
1255 </div>
1256 <div class="wpbc_calendar_premium_note_actions">
1257 <a class="button button-secondary" href="<?php echo esc_url( 'https://bm.wpbookingcalendar.com/' ); ?>" target="_blank"><?php esc_html_e( 'View live demo', 'booking' ); ?></a>
1258 <a class="button button-primary" href="<?php echo esc_url( wpbc_settings_calendar__get_premium_url( 'Business Small+' ) ); ?>" target="_blank"><?php esc_html_e( 'Upgrade', 'booking' ); ?></a>
1259 </div>
1260 </div>
1261 <?php
1262 }
1263
1264 /**
1265 * Render Business Small+ explanation for locked changeover controls.
1266 *
1267 * @return void
1268 */
1269 function wpbc_settings_calendar__render_changeover_upgrade_note() {
1270
1271 ?>
1272 <div class="wpbc_calendar_premium_note" data-wpbc-calendar-changeover-upgrade-note="1">
1273 <div>
1274 <strong><?php esc_html_e( 'Changeover days', 'booking' ); ?></strong>
1275 <p><?php esc_html_e( 'Check-in and check-out days can be shown as half-day changeover dates with diagonal or vertical markings. This feature is available in Booking Calendar Business Small or higher.', 'booking' ); ?></p>
1276 </div>
1277 <div class="wpbc_calendar_premium_note_actions">
1278 <a class="button button-secondary" href="<?php echo esc_url( 'https://bm.wpbookingcalendar.com/' ); ?>" target="_blank"><?php esc_html_e( 'View live demo', 'booking' ); ?></a>
1279 <a class="button button-primary" href="<?php echo esc_url( wpbc_settings_calendar__get_premium_url( 'Business Small+' ) ); ?>" target="_blank"><?php esc_html_e( 'Upgrade', 'booking' ); ?></a>
1280 </div>
1281 </div>
1282 <?php
1283 }
1284
1285 /**
1286 * Render disabled premium-only toggle row.
1287 *
1288 * @param string $name Option name.
1289 * @param string $label Label.
1290 * @param string $description Description.
1291 * @param string $premium_label Premium label.
1292 *
1293 * @return void
1294 */
1295 function wpbc_settings_calendar__render_locked_premium_checkbox( $name, $label, $description, $premium_label ) {
1296
1297 $dismiss_id = wpbc_settings_calendar__get_premium_option_dismiss_id( $name );
1298 if ( ! wpbc_settings_calendar__is_dismissed_visible( $dismiss_id ) ) {
1299 return;
1300 }
1301 ?>
1302 <div id="<?php echo esc_attr( $dismiss_id ); ?>" class="wpbc_calendar_field_row wpbc_calendar_locked_premium_field">
1303 <label class="wpbc_calendar_switch wpbc_calendar_switch_card is-premium" aria-disabled="true">
1304 <input type="checkbox" name="<?php echo esc_attr( $name ); ?>" value="On" disabled="disabled" data-wpbc-calendar-premium="1" />
1305 <span class="wpbc_calendar_switch_control" aria-hidden="true"><span class="wpbc_calendar_switch_knob"></span></span>
1306 <span class="wpbc_calendar_switch_label"><?php echo esc_html( $label ); ?></span>
1307 <?php wpbc_settings_calendar__render_premium_label( $premium_label, '', $dismiss_id ); ?>
1308 </label>
1309 <?php if ( '' !== $description ) : ?>
1310 <p class="wpbc_calendar_description"><?php echo wp_kses_post( $description ); ?></p>
1311 <?php endif; ?>
1312 </div>
1313 <?php
1314 }
1315
1316 /**
1317 * Render checkbox field.
1318 *
1319 * @param string $name Option name.
1320 * @param string $label Label.
1321 * @param string $description Description.
1322 * @param array $settings Settings.
1323 * @param bool $is_premium Whether field is premium.
1324 *
1325 * @return bool
1326 */
1327 function wpbc_settings_calendar__render_checkbox( $name, $label, $description, $settings, $is_premium = false ) {
1328
1329 $premium_attr = $is_premium ? 'data-wpbc-calendar-premium="1"' : '';
1330 $dismiss_id = $is_premium ? wpbc_settings_calendar__get_premium_option_dismiss_id( $name ) : '';
1331 if ( $is_premium && ! wpbc_settings_calendar__is_dismissed_visible( $dismiss_id ) ) {
1332 return false;
1333 }
1334 if ( $is_premium && 'booking_range_selection_time_is_active' === $name ) {
1335 $premium_attr .= ' data-wpbc-calendar-premium-changeover-info="1"';
1336 }
1337 ?>
1338 <label class="wpbc_calendar_switch wpbc_calendar_switch_card <?php echo $is_premium ? 'is-premium' : ''; ?>">
1339 <input type="checkbox" name="<?php echo esc_attr( $name ); ?>" value="On" <?php checked( 'On', $settings[ $name ] ); ?> <?php echo $premium_attr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> />
1340 <span class="wpbc_calendar_switch_control" aria-hidden="true"><span class="wpbc_calendar_switch_knob"></span></span>
1341 <span class="wpbc_calendar_switch_label"><?php echo esc_html( $label ); ?></span>
1342 <?php if ( $is_premium ) : ?>
1343 <?php wpbc_settings_calendar__render_premium_label( 'Business Small+', '', $dismiss_id ); ?>
1344 <?php endif; ?>
1345 </label>
1346 <?php if ( '' !== $description ) : ?>
1347 <p class="wpbc_calendar_description"><?php echo wp_kses_post( $description ); ?></p>
1348 <?php endif; ?>
1349 <?php
1350 return true;
1351 }
1352
1353 /**
1354 * Render legend item toggle with title field.
1355 *
1356 * @param string $legend_item Legend item key.
1357 * @param array $config Legend item config.
1358 * @param array $settings Settings.
1359 *
1360 * @return void
1361 */
1362 function wpbc_settings_calendar__render_legend_item_control( $legend_item, $config, $settings ) {
1363
1364 $is_show_key = 'booking_legend_is_show_item_' . $legend_item;
1365 $text_key = 'booking_legend_text_for_item_' . $legend_item;
1366 ?>
1367 <div class="wpbc_calendar_legend_item_tile" data-wpbc-calendar-legend-item="<?php echo esc_attr( $legend_item ); ?>">
1368 <div class="wpbc_calendar_legend_item_header">
1369 <label class="wpbc_calendar_switch">
1370 <input type="checkbox" name="<?php echo esc_attr( $is_show_key ); ?>" value="On" <?php checked( 'On', $settings[ $is_show_key ] ); ?> />
1371 <span class="wpbc_calendar_switch_control" aria-hidden="true"><span class="wpbc_calendar_switch_knob"></span></span>
1372 <span class="wpbc_calendar_switch_label"><?php echo esc_html( $config['label'] ); ?></span>
1373 </label>
1374 </div>
1375 <div class="wpbc_calendar_legend_item_title">
1376 <label for="<?php echo esc_attr( $text_key ); ?>"><?php esc_html_e( 'Title', 'booking' ); ?></label>
1377 <input type="text" id="<?php echo esc_attr( $text_key ); ?>" name="<?php echo esc_attr( $text_key ); ?>" value="<?php echo esc_attr( $settings[ $text_key ] ); ?>" placeholder="<?php echo esc_attr( $config['placeholder'] ); ?>" />
1378 </div>
1379 <p class="wpbc_calendar_description"><?php echo wp_kses_post( $config['description'] ); ?></p>
1380 <?php if ( ! empty( $config['note'] ) ) : ?>
1381 <p class="wpbc_calendar_description"><strong><?php esc_html_e( 'Note', 'booking' ); ?>:</strong> <?php echo esc_html( $config['note'] ); ?></p>
1382 <?php endif; ?>
1383 </div>
1384 <?php
1385 }
1386
1387 /**
1388 * Render week-day checkbox row.
1389 *
1390 * @param string $name Field name.
1391 * @param string $value Current CSV value.
1392 *
1393 * @return void
1394 */
1395 function wpbc_settings_calendar__render_weekday_checks( $name, $value ) {
1396
1397 $selected = ( '-1' === $value || '' === $value ) ? array() : explode( ',', $value );
1398 ?>
1399 <div class="wpbc_calendar_weekday_checks" data-wpbc-calendar-weekday-checks="<?php echo esc_attr( $name ); ?>">
1400 <?php foreach ( wpbc_settings_calendar__get_weekday_options() as $day_value => $day_label ) : ?>
1401 <label>
1402 <input type="checkbox" name="<?php echo esc_attr( $name ); ?>[]" value="<?php echo esc_attr( $day_value ); ?>" <?php checked( in_array( (string) $day_value, $selected, true ) ); ?> />
1403 <span><?php echo esc_html( $day_label ); ?></span>
1404 </label>
1405 <?php endforeach; ?>
1406 </div>
1407 <?php
1408 }
1409
1410 /**
1411 * Render calendar preview.
1412 *
1413 * @param int $resource_id Resource ID.
1414 * @param int $months_count Number of months.
1415 * @param array $preview_settings Optional settings.
1416 *
1417 * @return void
1418 */
1419 function wpbc_settings_calendar__render_calendar_preview( $resource_id, $months_count, $preview_settings = array() ) {
1420
1421 $resource_id = wpbc_settings_calendar__sanitize_preview_resource_id( $resource_id );
1422 $months_count = wpbc_settings_calendar__sanitize_preview_months_count( $months_count );
1423 $current_settings = wp_parse_args( $preview_settings, wpbc_settings_calendar__get_settings_response() );
1424 $is_change_over_preview = ( 'On' === (string) $current_settings['booking_range_selection_time_is_active'] );
1425 $is_triangle_preview = ( 'Off' !== (string) $current_settings['booking_change_over_days_triangles'] );
1426 $preview_css_classes = 'wpbc_calendar_settings_preview';
1427 if ( $is_change_over_preview && $is_triangle_preview ) {
1428 $preview_css_classes .= ' wpbc_change_over_triangle';
1429 }
1430 $previous_preview_options = wpbc_settings_calendar__preview_options_push( $current_settings );
1431 ?>
1432 <div class="<?php echo esc_attr( $preview_css_classes ); ?>" data-wpbc-admin-calendar-preview="1" data-wpbc-calendar-preview="1" data-resource-id="<?php echo esc_attr( $resource_id ); ?>" data-months-count="<?php echo esc_attr( $months_count ); ?>">
1433 <div class="wpbc_calendar_settings_real_preview" data-wpbc-calendar-panel="1">
1434 <?php
1435 if ( class_exists( 'WPBC_FE_Render' ) ) {
1436 WPBC_FE_Render::render_calendar_only(
1437 array(
1438 'resource_id' => $resource_id,
1439 'cal_count' => $months_count,
1440 'is_echo' => 1,
1441 'calendar_request_overrides' => wpbc_settings_calendar__get_calendar_load_preview_request_overrides( $current_settings ),
1442 )
1443 );
1444 } elseif ( function_exists( 'wpbc__calendar__load' ) ) {
1445 $start_script_code = wpbc__calendar__load(
1446 array(
1447 'resource_id' => $resource_id,
1448 'aggregate_resource_id_arr' => array(),
1449 'selected_dates_without_calendar' => '',
1450 'calendar_number_of_months' => $months_count,
1451 'start_month_calendar' => false,
1452 'shortcode_options' => '',
1453 'custom_form' => 'standard',
1454 'skip_general_availability' => 1,
1455 'calendar_request_overrides' => wpbc_settings_calendar__get_calendar_load_preview_request_overrides( $current_settings ),
1456 )
1457 );
1458 if ( function_exists( 'wpbc_pre_get_calendar_html' ) ) {
1459 echo '<div style="clear:both;height:10px;"></div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1460 echo wpbc_pre_get_calendar_html( $resource_id, $months_count, '' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1461 echo ' ' . $start_script_code; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1462 } else {
1463 echo $start_script_code; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1464 }
1465 }
1466 ?>
1467 </div>
1468 </div>
1469 <?php
1470
1471 wpbc_settings_calendar__preview_options_pop( $previous_preview_options );
1472 }
1473
1474 /**
1475 * Show Calendar save button in top toolbar.
1476 *
1477 * @param string $page_tag Current page tag.
1478 * @param string $active_page_tab Current tab.
1479 * @param string $active_page_subtab Current subtab.
1480 *
1481 * @return void
1482 */
1483 function wpbc_settings_calendar__top_toolbar__show_save_button( $page_tag, $active_page_tab, $active_page_subtab ) {
1484
1485 if ( ( 'wpbc-settings' !== $page_tag ) || ( 'calendar_settings' !== $active_page_tab ) ) {
1486 return;
1487 }
1488
1489 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_settings_calendar__get_manage_cap() ) ) {
1490 return;
1491 }
1492 ?>
1493 <div class="wpbc_ui_el__buttons_group wpbc_calendar__top_toolbar_group">
1494 <a href="javascript:void(0);"
1495 class="button button-primary wpbc_calendar__top_btn_save"
1496 data-wpbc-calendar-save="1"
1497 data-wpbc-u-busy-text="<?php esc_attr_e( 'Saving', 'booking' ); ?>...">
1498 <i class="menu_icon icon-1x wpbc-bi-check2-circle"></i>
1499 <span class="in-button-text">&nbsp;&nbsp;<?php esc_html_e( 'Save Changes', 'booking' ); ?></span>
1500 </a>
1501 </div>
1502 <?php
1503 }
1504 add_action( 'wpbc_ui_el__top_nav__content_end', 'wpbc_settings_calendar__top_toolbar__show_save_button', 20, 3 );
1505
1506 /**
1507 * Block direct access for regular users in MultiUser context.
1508 *
1509 * @param bool $is_show_this_page Whether to show page.
1510 * @param string $page_tag Current page.
1511 * @param string $active_page_tab Active tab.
1512 * @param string $active_page_subtab Active subtab.
1513 *
1514 * @return bool
1515 */
1516 function wpbc_settings_calendar__check_showing_page( $is_show_this_page, $page_tag, $active_page_tab, $active_page_subtab ) {
1517
1518 if ( ( 'wpbc-settings' === $page_tag ) && ( 'calendar_settings' === $active_page_tab ) && ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_settings_calendar__get_manage_cap() ) ) ) {
1519 return false;
1520 }
1521
1522 return $is_show_this_page;
1523 }
1524 add_filter( 'wpbc_before_showing_settings_page_is_show_page', 'wpbc_settings_calendar__check_showing_page', 20, 4 );
1525
1526 /**
1527 * Calendar settings tab.
1528 */
1529 class WPBC_Page_Settings_Calendar extends WPBC_Page_Structure {
1530
1531 /**
1532 * Whether settings were saved during this request.
1533 *
1534 * @var bool
1535 */
1536 private $is_updated = false;
1537
1538 /**
1539 * Menu slug.
1540 *
1541 * @return string
1542 */
1543 public function in_page() {
1544
1545 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_settings_calendar__get_manage_cap() ) ) {
1546 return (string) wp_rand( 100000, 1000000 );
1547 }
1548
1549 return 'wpbc-settings';
1550 }
1551
1552 /**
1553 * Register tab.
1554 *
1555 * @return array
1556 */
1557 public function tabs() {
1558
1559 $subtabs = array();
1560 $subtab_default = array(
1561 'type' => 'subtab',
1562 'title' => '',
1563 'page_title' => __( 'Calendar Settings', 'booking' ),
1564 'hint' => '',
1565 'link' => '',
1566 'css_classes' => '',
1567 'font_icon' => 'wpbc-bi-calendar2-range',
1568 'font_icon_right' => 'wpbc-bi-question-circle',
1569 'default' => false,
1570 'content' => 'content',
1571 );
1572
1573 foreach ( wpbc_settings_calendar__get_section_navigation_items() as $section_key => $section ) {
1574 $subtabs[ $section['menu_slug'] ] = array_merge(
1575 $subtab_default,
1576 array(
1577 'title' => $section['title'],
1578 'hint' => $section['hint'],
1579 'font_icon' => $section['font_icon'],
1580 'link' => wpbc_settings_calendar__get_section_url( $section_key ),
1581 'default' => ( 'days_selection' === $section_key ),
1582 )
1583 );
1584 }
1585
1586 return array(
1587 'calendar_settings' => array(
1588 'is_show_top_path' => true,
1589 'right_vertical_sidebar__is_show' => true,
1590 'right_vertical_sidebar__default_view_mode' => '',
1591 'right_vertical_sidebar_compact__is_show' => true,
1592 'left_navigation__default_view_mode' => 'compact',
1593 'top_path_title' => __( 'Calendar', 'booking' ),
1594 'title' => __( 'Calendar', 'booking' ) . '<span class="wpbc_new_label" style="margin-left: auto;">' . esc_html__( 'New', 'booking' ) . '</span>&nbsp;&nbsp;',
1595 'hint' => __( 'Preview and configure date selection, range selection, and change-over behavior.', 'booking' ),
1596 'page_title' => __( 'Calendar Settings', 'booking' ),
1597 'link' => '',
1598 'position' => '',
1599 'css_classes' => 'wpbc_top_tab__calendar_settings',
1600 'icon' => '',
1601 'font_icon' => 'wpbc-bi-calendar2-range',
1602 'font_icon_right' => '',
1603 'default' => false,
1604 'disabled' => false,
1605 'hided' => false,
1606 'subtabs' => $subtabs,
1607 'folder_style' => 'order:18;',
1608 ),
1609 );
1610 }
1611
1612 /**
1613 * Save settings.
1614 *
1615 * @return void
1616 */
1617 public function maybe_update() {
1618
1619 $form_name = 'wpbc_settings_calendar_form';
1620
1621 // phpcs:ignore WordPress.Security.NonceVerification.Missing
1622 if ( ! isset( $_POST[ 'is_form_submitted_' . $form_name ] ) ) {
1623 return;
1624 }
1625
1626 check_admin_referer( 'wpbc_settings_page_' . $form_name );
1627
1628 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_settings_calendar__get_manage_cap() ) ) {
1629 return;
1630 }
1631
1632 $cleaned_data = wpbc_settings_calendar__validate_data( $_POST ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1633 wpbc_settings_calendar__update_settings( $cleaned_data );
1634
1635 $this->is_updated = true;
1636 }
1637
1638 /**
1639 * Right compact sidebar tabs.
1640 *
1641 * @return void
1642 */
1643 public function right_sidebar_compact_content() {
1644
1645 WPBC_UI_Sidebar_Panels::render_rightbar_tabs(
1646 array(
1647 array(
1648 'id' => 'wpbc_tab_calendar_settings',
1649 'panel_id' => 'wpbc_calendar__inspector_settings',
1650 'title' => __( 'Settings', 'booking' ),
1651 'icon' => 'wpbc_icn_tune',
1652 'selected' => true,
1653 ),
1654 array(
1655 'id' => 'wpbc_tab_calendar_notes',
1656 'panel_id' => 'wpbc_calendar__inspector_notes',
1657 'title' => __( 'Notes', 'booking' ),
1658 'icon' => 'wpbc-bi-info-circle',
1659 ),
1660 ),
1661 array(
1662 'aria_label' => __( 'Calendar Panels', 'booking' ),
1663 'context' => 'settings_calendar',
1664 'class' => 'wpbc_calendar_rightbar_tabs',
1665 )
1666 );
1667 }
1668
1669 /**
1670 * Right sidebar panels.
1671 *
1672 * @return void
1673 */
1674 public function right_sidebar_content() {
1675 ?>
1676 <div class="wpbc_bfb__panel--library wpbc_rightbar_palette wpbc_calendar_rightbar_panels">
1677 <?php
1678 WPBC_UI_Sidebar_Panels::render_panel(
1679 array(
1680 'id' => 'wpbc_calendar__inspector_settings',
1681 'labelledby' => 'wpbc_tab_calendar_settings',
1682 'class' => 'wpbc_calendar__inspector_settings',
1683 ),
1684 array( $this, 'right_panel_settings_content' )
1685 );
1686
1687 WPBC_UI_Sidebar_Panels::render_panel(
1688 array(
1689 'id' => 'wpbc_calendar__inspector_notes',
1690 'labelledby' => 'wpbc_tab_calendar_notes',
1691 'class' => 'wpbc_calendar__inspector_notes',
1692 'hidden' => true,
1693 ),
1694 array( $this, 'right_panel_notes_content' )
1695 );
1696 ?>
1697 </div>
1698 <?php
1699 }
1700
1701 /**
1702 * Settings panel content.
1703 *
1704 * @return void
1705 */
1706 public function right_panel_settings_content() {
1707
1708 $form_name = 'wpbc_settings_calendar_form';
1709 $settings = wpbc_settings_calendar__get_settings_response();
1710 $is_premium_lock = ! wpbc_settings_calendar__is_range_supported();
1711 $open_section = wpbc_settings_calendar__get_open_section();
1712
1713 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Calendar Settings', 'booking' ), __( 'Date selection and change-over behavior with live calendar preview.', 'booking' ) );
1714 ?>
1715 <form method="post" id="<?php echo esc_attr( $form_name ); ?>" class="wpbc_calendar_settings_form" data-wpbc-calendar-settings-form="1">
1716 <?php wp_nonce_field( 'wpbc_settings_page_' . $form_name ); ?>
1717 <input type="hidden" name="is_form_submitted_<?php echo esc_attr( $form_name ); ?>" value="1" />
1718 <div class="wpbc_bfb__inspector__body wpbc_calendar_inspector_body">
1719 <?php
1720 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1721 array(
1722 'id' => 'wpbc_calendar_days_selection_group',
1723 'group' => 'settings-calendar-days-selection',
1724 'title' => __( 'Days Selection', 'booking' ),
1725 'open' => ( '' === $open_section || 'days_selection' === $open_section ),
1726 ),
1727 function () use ( $settings, $is_premium_lock ) {
1728 $selected_day_mode = ( $is_premium_lock && 'range' === $settings['booking_type_of_day_selections'] ) ? 'multiple' : $settings['booking_type_of_day_selections'];
1729 $range_dismiss_id = wpbc_settings_calendar__get_premium_option_dismiss_id( 'booking_type_of_day_selections_range' );
1730 ?>
1731 <div class="wpbc_calendar_radio_stack" data-wpbc-calendar-days-mode="1">
1732 <label><input type="radio" name="booking_type_of_day_selections" value="single" <?php checked( 'single', $selected_day_mode ); ?> /> <span><?php esc_html_e( 'Single day', 'booking' ); ?></span></label>
1733 <label><input type="radio" name="booking_type_of_day_selections" value="multiple" <?php checked( 'multiple', $selected_day_mode ); ?> /> <span><?php esc_html_e( 'Multiple days', 'booking' ); ?></span></label>
1734 <?php if ( ! $is_premium_lock || wpbc_settings_calendar__is_dismissed_visible( $range_dismiss_id ) ) : ?>
1735 <label id="<?php echo esc_attr( $is_premium_lock ? $range_dismiss_id : '' ); ?>" class="<?php echo $is_premium_lock ? 'is-premium' : ''; ?>"><input type="radio" name="booking_type_of_day_selections" value="range" <?php checked( 'range', $selected_day_mode ); ?> <?php echo $is_premium_lock ? 'data-wpbc-calendar-premium="1" data-wpbc-calendar-premium-range-info="1"' : ''; ?> /> <span><?php esc_html_e( 'Range days', 'booking' ); ?></span> <?php $is_premium_lock && wpbc_settings_calendar__render_premium_label( 'Business Small+', '', $range_dismiss_id ); ?></label>
1736 <?php endif; ?>
1737 </div>
1738 <?php if ( $is_premium_lock ) : ?>
1739 <?php wpbc_settings_calendar__render_range_upgrade_note(); ?>
1740 <?php endif; ?>
1741 <div class="wpbc_calendar_subsettings" data-wpbc-calendar-range-settings="1">
1742 <div class="wpbc_calendar_radio_stack">
1743 <label><input type="radio" name="booking_range_selection_type" value="fixed" <?php checked( 'fixed', $settings['booking_range_selection_type'] ); ?> /> <span><?php esc_html_e( 'Select a fixed number of days with 1 mouse click', 'booking' ); ?></span></label>
1744 <label><input type="radio" name="booking_range_selection_type" value="dynamic" <?php checked( 'dynamic', $settings['booking_range_selection_type'] ); ?> /> <span><?php esc_html_e( 'Select a dynamic range of days with 2 mouse clicks', 'booking' ); ?></span></label>
1745 </div>
1746 <div class="wpbc_calendar_range_block" data-wpbc-calendar-range-type="fixed">
1747 <div class="wpbc_calendar_field_row">
1748 <label for="booking_range_selection_days_count"><?php esc_html_e( 'Days selection number', 'booking' ); ?></label>
1749 <input type="number" id="booking_range_selection_days_count" name="booking_range_selection_days_count" min="1" max="180" value="<?php echo esc_attr( $settings['booking_range_selection_days_count'] ); ?>" />
1750 </div>
1751 <div class="wpbc_calendar_field_row">
1752 <label><?php esc_html_e( 'Start day of range', 'booking' ); ?></label>
1753 <label><input type="radio" name="booking_range_start_day_mode" value="-1" <?php checked( '-1', $settings['booking_range_start_day'] ); ?> /> <?php esc_html_e( 'Any day of week', 'booking' ); ?></label>
1754 <label><input type="radio" name="booking_range_start_day_mode" value="specific" <?php checked( '-1' !== $settings['booking_range_start_day'] ); ?> /> <?php esc_html_e( 'Specific day(s) of week', 'booking' ); ?></label>
1755 <?php wpbc_settings_calendar__render_weekday_checks( 'booking_range_start_day_weekdays', $settings['booking_range_start_day'] ); ?>
1756 </div>
1757 </div>
1758 <div class="wpbc_calendar_range_block" data-wpbc-calendar-range-type="dynamic">
1759 <div class="wpbc_calendar_inline_fields">
1760 <div class="wpbc_calendar_field_row">
1761 <label for="booking_range_selection_days_count_dynamic"><?php esc_html_e( 'Min', 'booking' ); ?></label>
1762 <input type="number" id="booking_range_selection_days_count_dynamic" name="booking_range_selection_days_count_dynamic" min="1" max="1095" value="<?php echo esc_attr( $settings['booking_range_selection_days_count_dynamic'] ); ?>" />
1763 </div>
1764 <div class="wpbc_calendar_field_row">
1765 <label for="booking_range_selection_days_max_count_dynamic"><?php esc_html_e( 'Max', 'booking' ); ?></label>
1766 <input type="number" id="booking_range_selection_days_max_count_dynamic" name="booking_range_selection_days_max_count_dynamic" min="1" max="1095" value="<?php echo esc_attr( $settings['booking_range_selection_days_max_count_dynamic'] ); ?>" />
1767 </div>
1768 </div>
1769 <div class="wpbc_calendar_field_row">
1770 <label for="booking_range_selection_days_specific_num_dynamic"><?php esc_html_e( 'Specific days selections', 'booking' ); ?></label>
1771 <input type="text" id="booking_range_selection_days_specific_num_dynamic" name="booking_range_selection_days_specific_num_dynamic" value="<?php echo esc_attr( $settings['booking_range_selection_days_specific_num_dynamic'] ); ?>" placeholder="<?php esc_attr_e( 'Example: 7,14,21,28', 'booking' ); ?>" />
1772 </div>
1773 <div class="wpbc_calendar_field_row">
1774 <label><?php esc_html_e( 'Start day of range', 'booking' ); ?></label>
1775 <label><input type="radio" name="booking_range_start_day_dynamic_mode" value="-1" <?php checked( '-1', $settings['booking_range_start_day_dynamic'] ); ?> /> <?php esc_html_e( 'Any day of week', 'booking' ); ?></label>
1776 <label><input type="radio" name="booking_range_start_day_dynamic_mode" value="specific" <?php checked( '-1' !== $settings['booking_range_start_day_dynamic'] ); ?> /> <?php esc_html_e( 'Specific day(s) of week', 'booking' ); ?></label>
1777 <?php wpbc_settings_calendar__render_weekday_checks( 'booking_range_start_day_dynamic_weekdays', $settings['booking_range_start_day_dynamic'] ); ?>
1778 </div>
1779 </div>
1780 </div>
1781 <?php
1782 }
1783 );
1784
1785 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1786 array(
1787 'id' => 'wpbc_calendar_time_group',
1788 'group' => 'settings-calendar-time',
1789 'title' => __( 'Changeover and Times', 'booking' ),
1790 'open' => ( 'changeover_times' === $open_section ),
1791 ),
1792 function () use ( $settings, $is_premium_lock ) {
1793 $time_options = wpbc_settings_calendar__get_time_options( $settings['booking_range_selection_start_time'] );
1794 $time_options = array_merge( $time_options, wpbc_settings_calendar__get_time_options( $settings['booking_range_selection_end_time'] ) );
1795 ksort( $time_options );
1796 ?>
1797 <div class="wpbc_calendar_field_row">
1798 <?php
1799 wpbc_settings_calendar__render_checkbox(
1800 'booking_recurrent_time',
1801 __( 'Use selected times for each booking date', 'booking' ),
1802 __( 'Use selected times as booked time slots on each selected date.', 'booking' ),
1803 $settings
1804 );
1805 ?>
1806 </div>
1807 <?php if ( ! $is_premium_lock || wpbc_settings_calendar__is_dismissed_visible( wpbc_settings_calendar__get_premium_option_dismiss_id( 'booking_last_checkout_day_available' ) ) ) : ?>
1808 <div class="wpbc_calendar_field_row">
1809 <?php
1810 wpbc_settings_calendar__render_checkbox(
1811 'booking_last_checkout_day_available',
1812 __( 'Set check out date as available', 'booking' ),
1813 __( 'Remove the last selected day from saving to the booking.', 'booking' ),
1814 $settings,
1815 $is_premium_lock
1816 );
1817 ?>
1818 </div>
1819 <?php endif; ?>
1820 <?php if ( ! $is_premium_lock || wpbc_settings_calendar__is_dismissed_visible( wpbc_settings_calendar__get_premium_option_dismiss_id( 'booking_range_selection_time_is_active' ) ) ) : ?>
1821 <div class="wpbc_calendar_field_row">
1822 <?php
1823 wpbc_settings_calendar__render_checkbox(
1824 'booking_range_selection_time_is_active',
1825 __( 'Use changeover days', 'booking' ),
1826 __( 'Check-in/out days will be marked with vertical or diagonal lines.', 'booking' ),
1827 $settings,
1828 $is_premium_lock
1829 );
1830 ?>
1831 <?php if ( $is_premium_lock ) : ?>
1832 <?php wpbc_settings_calendar__render_changeover_upgrade_note(); ?>
1833 <?php endif; ?>
1834 </div>
1835 <?php endif; ?>
1836 <div class="wpbc_calendar_subsettings" data-wpbc-calendar-changeover-settings="1">
1837 <div class="wpbc_calendar_inline_fields">
1838 <div class="wpbc_calendar_field_row">
1839 <label for="booking_range_selection_start_time"><?php esc_html_e( 'Check-in time', 'booking' ); ?></label>
1840 <?php wpbc_settings_calendar__render_select( 'booking_range_selection_start_time', $time_options, $settings['booking_range_selection_start_time'] ); ?>
1841 </div>
1842 <div class="wpbc_calendar_field_row">
1843 <label for="booking_range_selection_end_time"><?php esc_html_e( 'Check-Out time', 'booking' ); ?></label>
1844 <?php wpbc_settings_calendar__render_select( 'booking_range_selection_end_time', $time_options, $settings['booking_range_selection_end_time'] ); ?>
1845 </div>
1846 </div>
1847 <?php if ( ! $is_premium_lock || wpbc_settings_calendar__is_dismissed_visible( wpbc_settings_calendar__get_premium_option_dismiss_id( 'booking_change_over_days_triangles' ) ) ) : ?>
1848 <div class="wpbc_calendar_field_row">
1849 <?php
1850 wpbc_settings_calendar__render_checkbox(
1851 'booking_change_over_days_triangles',
1852 __( 'Change over days as triangles', 'booking' ),
1853 '',
1854 $settings,
1855 $is_premium_lock
1856 );
1857 ?>
1858 </div>
1859 <?php endif; ?>
1860 <?php if ( ! $is_premium_lock || wpbc_settings_calendar__is_dismissed_visible( wpbc_settings_calendar__get_premium_option_dismiss_id( 'booking_change_over__is_excerpt_on_pages' ) ) ) : ?>
1861 <div class="wpbc_calendar_field_row">
1862 <?php
1863 wpbc_settings_calendar__render_checkbox(
1864 'booking_change_over__is_excerpt_on_pages',
1865 __( 'Do not use change over days on certain pages', 'booking' ),
1866 __( 'Activate exceptions for pages that should not use change over days.', 'booking' ),
1867 $settings,
1868 $is_premium_lock
1869 );
1870 ?>
1871 </div>
1872 <?php endif; ?>
1873 <div class="wpbc_calendar_field_row">
1874 <label for="booking_change_over__excerpt_on_pages"><?php esc_html_e( 'Relative URLs of pages', 'booking' ); ?></label>
1875 <textarea id="booking_change_over__excerpt_on_pages" name="booking_change_over__excerpt_on_pages" rows="4" placeholder="/page-no-change-over/"><?php echo esc_textarea( $settings['booking_change_over__excerpt_on_pages'] ); ?></textarea>
1876 </div>
1877 <div class="wpbc_calendar_field_row">
1878 <label for="booking_change_over__excerpt_bk_resources"><?php esc_html_e( 'Booking resource IDs', 'booking' ); ?></label>
1879 <textarea id="booking_change_over__excerpt_bk_resources" name="booking_change_over__excerpt_bk_resources" rows="3" placeholder="17, 21, 34"><?php echo esc_textarea( $settings['booking_change_over__excerpt_bk_resources'] ); ?></textarea>
1880 </div>
1881 </div>
1882 <?php
1883 }
1884 );
1885
1886 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1887 array(
1888 'id' => 'wpbc_calendar_legend_group',
1889 'group' => 'settings-calendar-legend',
1890 'title' => __( 'Calendar Legend', 'booking' ),
1891 'open' => ( 'legend' === $open_section ),
1892 ),
1893 function () use ( $settings ) {
1894 ?>
1895 <div class="wpbc_calendar_field_row">
1896 <?php
1897 wpbc_settings_calendar__render_checkbox(
1898 'booking_is_show_legend',
1899 __( 'Show legend below calendar', 'booking' ),
1900 __( 'Check this box to display a legend of dates below the booking calendar.', 'booking' ),
1901 $settings
1902 );
1903 ?>
1904 </div>
1905 <div class="wpbc_calendar_subsettings" data-wpbc-calendar-legend-settings="1">
1906 <div class="wpbc_calendar_legend_items_grid">
1907 <?php
1908 foreach ( wpbc_settings_calendar__get_legend_items_config() as $legend_item => $legend_config ) {
1909 wpbc_settings_calendar__render_legend_item_control( $legend_item, $legend_config, $settings );
1910 }
1911 ?>
1912 </div>
1913 <div class="wpbc_calendar_field_row">
1914 <?php
1915 wpbc_settings_calendar__render_checkbox(
1916 'booking_legend_is_show_numbers',
1917 __( 'Show date number in legend', 'booking' ),
1918 __( 'Check this box to display today date number in legend cells.', 'booking' ),
1919 $settings
1920 );
1921 ?>
1922 </div>
1923 <div class="wpbc_calendar_field_row">
1924 <?php
1925 wpbc_settings_calendar__render_checkbox(
1926 'booking_legend_is_vertical',
1927 __( 'Show legend items in a column', 'booking' ),
1928 __( 'Check this box to display legend items vertically in a column.', 'booking' ),
1929 $settings
1930 );
1931 ?>
1932 </div>
1933 </div>
1934 <?php
1935 }
1936 );
1937
1938 $settings['booking_show_timeslots_in_tooltip'] = wpbc_settings_calendar__is_timeslots_tooltip_enabled( $settings ) ? 'On' : 'Off';
1939
1940 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1941 array(
1942 'id' => 'wpbc_calendar_tooltips_group',
1943 'group' => 'settings-calendar-tooltips',
1944 'title' => __( 'Calendar Dates Tooltips', 'booking' ),
1945 'open' => ( 'tooltips' === $open_section ),
1946 ),
1947 function () use ( $settings ) {
1948 ?>
1949 <div class="wpbc_calendar_field_row">
1950 <?php
1951 wpbc_settings_calendar__render_checkbox(
1952 'booking_show_timeslots_in_tooltip',
1953 __( 'Show time slots in tooltips', 'booking' ),
1954 __( 'Show booked time slots in the tooltip when the mouse hovers over a booked day in the calendar.', 'booking' ),
1955 $settings
1956 );
1957 ?>
1958 </div>
1959 <div class="wpbc_calendar_field_row" data-wpbc-calendar-timeslot-tooltip-settings="1">
1960 <label for="booking_highlight_timeslot_word"><?php esc_html_e( 'Title of booked timeslot(s)', 'booking' ); ?></label>
1961 <input type="text" id="booking_highlight_timeslot_word" name="booking_highlight_timeslot_word" value="<?php echo esc_attr( $settings['booking_highlight_timeslot_word'] ); ?>" placeholder="<?php esc_attr_e( 'Booked Times:', 'booking' ); ?>" />
1962 <p class="wpbc_calendar_description"><?php echo wp_kses_post( sprintf( __( 'Type your %1$stitle%2$s, what will show in mouseover tooltip near booked timeslot(s)', 'booking' ), '<b>', '</b>' ) ); ?></p>
1963 </div>
1964 <?php if ( class_exists( 'wpdev_bk_biz_l' ) ) : ?>
1965 <div class="wpbc_calendar_field_row">
1966 <?php
1967 wpbc_settings_calendar__render_checkbox(
1968 'booking_is_show_availability_in_tooltips',
1969 __( 'Show availability in tooltip', 'booking' ),
1970 __( 'Check this box to display the available number of booking resources with a tooltip, when mouse hovers over each day on the calendar(s).', 'booking' ),
1971 $settings
1972 );
1973 ?>
1974 </div>
1975 <div class="wpbc_calendar_field_row" data-wpbc-calendar-availability-tooltip-settings="1">
1976 <label for="booking_highlight_availability_word"><?php esc_html_e( 'Availability Title', 'booking' ); ?></label>
1977 <input type="text" id="booking_highlight_availability_word" name="booking_highlight_availability_word" value="<?php echo esc_attr( $settings['booking_highlight_availability_word'] ); ?>" placeholder="<?php esc_attr_e( 'Available: ', 'booking' ); ?>" />
1978 <p class="wpbc_calendar_description"><?php echo wp_kses_post( sprintf( __( 'Type your %1$savailability%2$s description', 'booking' ), '<b>', '</b>' ) ); ?></p>
1979 </div>
1980 <div class="wpbc_calendar_field_row">
1981 <?php
1982 wpbc_settings_calendar__render_checkbox(
1983 'booking_is_show_availability_in_date_cell',
1984 __( 'Show availability in date cell', 'booking' ),
1985 __( 'Check this box to display the available number of booking resources at the date cells in the calendar(s).', 'booking' ),
1986 $settings
1987 );
1988 ?>
1989 </div>
1990 <div class="wpbc_calendar_field_row" data-wpbc-calendar-availability-cell-settings="1">
1991 <label for="booking_highlight_availability_word_in_date_cell"><?php esc_html_e( 'Availability Title', 'booking' ); ?></label>
1992 <input type="text" id="booking_highlight_availability_word_in_date_cell" name="booking_highlight_availability_word_in_date_cell" value="<?php echo esc_attr( $settings['booking_highlight_availability_word_in_date_cell'] ); ?>" placeholder="<?php echo esc_attr( __( 'available', 'booking' ) . ' / ' . __( 'slots', 'booking' ) . ' / ' . __( 'rooms', 'booking' ) ); ?>" />
1993 <p class="wpbc_calendar_description"><?php echo wp_kses_post( sprintf( __( 'Type your %1$savailability%2$s description', 'booking' ), '<b>', '</b>' ) ); ?></p>
1994 </div>
1995 <?php else : ?>
1996 <?php
1997 wpbc_settings_calendar__render_locked_premium_checkbox(
1998 'booking_is_show_availability_in_tooltips',
1999 __( 'Show availability in tooltip', 'booking' ),
2000 __( 'Display the available number of booking resources in the day tooltip.', 'booking' ),
2001 'Business Large+'
2002 );
2003 wpbc_settings_calendar__render_locked_premium_checkbox(
2004 'booking_is_show_availability_in_date_cell',
2005 __( 'Show availability in date cell', 'booking' ),
2006 __( 'Display the available number of booking resources directly inside calendar date cells.', 'booking' ),
2007 'Business Large+'
2008 );
2009 ?>
2010 <?php endif; ?>
2011 <?php if ( class_exists( 'wpdev_bk_biz_m' ) ) : ?>
2012 <div class="wpbc_calendar_field_row">
2013 <?php
2014 wpbc_settings_calendar__render_checkbox(
2015 'booking_is_show_cost_in_tooltips',
2016 __( 'Showing cost in tooltip', 'booking' ),
2017 __( 'Check this box to display the daily cost with a tooltip when mouse hovers over each day on the calendar(s).', 'booking' ),
2018 $settings
2019 );
2020 ?>
2021 </div>
2022 <div class="wpbc_calendar_field_row" data-wpbc-calendar-cost-tooltip-settings="1">
2023 <label for="booking_highlight_cost_word"><?php esc_html_e( 'Cost Title', 'booking' ); ?></label>
2024 <input type="text" id="booking_highlight_cost_word" name="booking_highlight_cost_word" value="<?php echo esc_attr( $settings['booking_highlight_cost_word'] ); ?>" placeholder="<?php esc_attr_e( 'Cost: ', 'booking' ); ?>" />
2025 <p class="wpbc_calendar_description"><?php echo wp_kses_post( sprintf( __( 'Type your %1$scost%2$s description', 'booking' ), '<b>', '</b>' ) ); ?></p>
2026 </div>
2027 <div class="wpbc_calendar_field_row">
2028 <?php
2029 wpbc_settings_calendar__render_checkbox(
2030 'booking_is_show_cost_in_date_cell',
2031 __( 'Showing cost in date cell', 'booking' ),
2032 sprintf( __( 'Check this box to display the %1$sdaily cost at the date cells%2$s in the calendar(s).', 'booking' ), '<b>', '</b>' ),
2033 $settings
2034 );
2035 ?>
2036 </div>
2037 <div class="wpbc_calendar_field_row" data-wpbc-calendar-cost-cell-settings="1">
2038 <label for="booking_cost_in_date_cell_currency"><?php esc_html_e( 'Currency symbol', 'booking' ); ?></label>
2039 <input type="text" id="booking_cost_in_date_cell_currency" name="booking_cost_in_date_cell_currency" value="<?php echo esc_attr( $settings['booking_cost_in_date_cell_currency'] ); ?>" placeholder="&#36;" />
2040 <p class="wpbc_calendar_description"><?php echo wp_kses_post( sprintf( __( 'Type your %1$scurrency symbol%2$s to display near daily cost in date cells.', 'booking' ), '<b>', '</b>' ) ); ?></p>
2041 </div>
2042 <div class="wpbc_calendar_field_row">
2043 <?php
2044 wpbc_settings_calendar__render_checkbox(
2045 'booking_is_show_booked_data_in_tooltips',
2046 __( 'Show booking details in tooltip', 'booking' ),
2047 __( 'Check this box to display booking details with a tooltip, when mouse hovers over each day on the usual month calendar(s).', 'booking' ),
2048 $settings
2049 );
2050 ?>
2051 </div>
2052 <div class="wpbc_calendar_field_row" data-wpbc-calendar-booked-tooltip-settings="1">
2053 <label for="booking_booked_data_in_tooltips"><?php esc_html_e( 'Booking details', 'booking' ); ?></label>
2054 <input type="text" id="booking_booked_data_in_tooltips" name="booking_booked_data_in_tooltips" value="<?php echo esc_attr( $settings['booking_booked_data_in_tooltips'] ); ?>" placeholder="[name] [secondname]" />
2055 <p class="wpbc_calendar_description"><?php esc_html_e( 'You can use the shortcodes from the bottom form of Settings Fields page.', 'booking' ); ?></p>
2056 </div>
2057 <?php else : ?>
2058 <?php
2059 wpbc_settings_calendar__render_locked_premium_checkbox(
2060 'booking_is_show_cost_in_tooltips',
2061 __( 'Showing cost in tooltip', 'booking' ),
2062 __( 'Display the daily cost in the tooltip when the mouse hovers over a calendar day.', 'booking' ),
2063 'Business Medium+'
2064 );
2065 wpbc_settings_calendar__render_locked_premium_checkbox(
2066 'booking_is_show_cost_in_date_cell',
2067 __( 'Showing cost in date cell', 'booking' ),
2068 __( 'Display the daily cost directly inside calendar date cells.', 'booking' ),
2069 'Business Medium+'
2070 );
2071 wpbc_settings_calendar__render_locked_premium_checkbox(
2072 'booking_is_show_booked_data_in_tooltips',
2073 __( 'Show booking details in tooltip', 'booking' ),
2074 __( 'Display selected booking details in the tooltip when the mouse hovers over booked days.', 'booking' ),
2075 'Business Medium+'
2076 );
2077 ?>
2078 <?php endif; ?>
2079 <?php
2080 }
2081 );
2082
2083 WPBC_UI_Sidebar_Panels::render_collapsible_group(
2084 array(
2085 'id' => 'wpbc_calendar_general_group',
2086 'group' => 'settings-calendar-general',
2087 'title' => __( 'Calendar General', 'booking' ),
2088 'open' => ( 'general' === $open_section ),
2089 ),
2090 function () use ( $settings ) {
2091 ?>
2092 <div class="wpbc_calendar_field_row">
2093 <label for="booking_max_monthes_in_calendar"><?php esc_html_e( 'Number of months to scroll', 'booking' ); ?></label>
2094 <?php wpbc_settings_calendar__render_select( 'booking_max_monthes_in_calendar', wpbc_settings_calendar__get_max_month_options(), $settings['booking_max_monthes_in_calendar'] ); ?>
2095 </div>
2096 <div class="wpbc_calendar_field_row">
2097 <label for="booking_start_day_weeek"><?php esc_html_e( 'Start Day of the week', 'booking' ); ?></label>
2098 <?php wpbc_settings_calendar__render_select( 'booking_start_day_weeek', wpbc_settings_calendar__get_weekday_options(), $settings['booking_start_day_weeek'] ); ?>
2099 </div>
2100 <div class="wpbc_calendar_field_row">
2101 <?php
2102 wpbc_settings_calendar__render_checkbox(
2103 'booking_calendar_allow_several_months_on_mobile',
2104 __( 'Allow multiple months to be shown on mobile', 'booking' ),
2105 __( 'Enable this option to allow multiple months to be shown in the calendar on mobile devices.', 'booking' ),
2106 $settings
2107 );
2108 ?>
2109 </div>
2110 <?php
2111 }
2112 );
2113 ?>
2114 </div>
2115 </form>
2116 <?php
2117 }
2118
2119 /**
2120 * Notes panel content.
2121 *
2122 * @return void
2123 */
2124 public function right_panel_notes_content() {
2125
2126 ?>
2127 <div class="wpbc_calendar_notes_panel">
2128 <?php WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Notes', 'booking' ), __( 'The preview uses the real booking calendar and applies the selected settings before saving.', 'booking' ) ); ?>
2129 <div class="wpbc_ts_hint wpbc_calendar_hint_bar">
2130 <span class="wpbc_icn_info_outline"></span>
2131 <?php esc_html_e( 'Premium options can be tested in the preview, but they are saved only when the installed edition supports them.', 'booking' ); ?>
2132 </div>
2133 </div>
2134 <?php
2135 }
2136
2137 /**
2138 * Page content.
2139 *
2140 * @return void
2141 */
2142 public function content() {
2143
2144 do_action( 'wpbc_hook_settings_page_header', 'page_settings_calendar' );
2145
2146 if ( ! wpbc_is_mu_user_can_be_here( 'only_super_admin' ) || ! current_user_can( wpbc_settings_calendar__get_manage_cap() ) ) {
2147 return false;
2148 }
2149
2150 if ( function_exists( 'wpbc_js_for_bookings_page' ) ) {
2151 wpbc_js_for_bookings_page();
2152 }
2153
2154 if ( $this->is_updated ) {
2155 wpbc_show_changes_saved_message();
2156 }
2157
2158 $resource_id = wpbc_settings_calendar__get_preview_resource_id();
2159 $months_count = wpbc_settings_calendar__get_preview_months_count();
2160 $resources = wpbc_settings_calendar__get_resources();
2161 $is_free_version = ! class_exists( 'wpdev_bk_personal' );
2162 ?>
2163 <div class="wpbc_calendar_settings_page wpdevelop" data-wpbc-calendar-page="1" data-wpbc-calendar-resource-id="<?php echo esc_attr( $resource_id ); ?>">
2164 <form method="get" class="wpbc_calendar_toolbar wpbc_ts_toolbar wpbc_calendar_preview_controls" data-wpbc-calendar-preview-toolbar="1">
2165 <input type="hidden" name="page" value="wpbc-settings" />
2166 <input type="hidden" name="tab" value="calendar_settings" />
2167 <div class="wpbc_ts_control wpbc_calendar_control_resource">
2168 <label for="wpbc_calendar_resource_id"><?php esc_html_e( 'Booking resource', 'booking' ); ?></label>
2169 <?php if ( $is_free_version ) : ?>
2170 <input type="hidden" id="wpbc_calendar_resource_id" name="resource_id" value="<?php echo esc_attr( $resource_id ); ?>" />
2171 <div class="wpbc_calendar_toolbar_value">
2172 <i class="menu_icon icon-1x wpbc-bi-calendar2-day"></i>
2173 <span><?php echo esc_html( ! empty( $resources[0]['title'] ) ? $resources[0]['title'] : __( 'Default booking resource', 'booking' ) ); ?></span>
2174 </div>
2175 <?php
2176 $resource_dismiss_id = wpbc_settings_calendar__get_premium_option_dismiss_id( 'booking_resources' );
2177 if ( wpbc_settings_calendar__is_dismissed_visible( $resource_dismiss_id ) ) :
2178 ?>
2179 <div id="<?php echo esc_attr( $resource_dismiss_id ); ?>" class="wpbc_calendar_upgrade_hint">
2180 <?php wpbc_settings_calendar__render_premium_label( 'Pro', '', $resource_dismiss_id ); ?>
2181 <span><?php esc_html_e( 'The Free version has one default booking resource. To have multiple resources, please upgrade to a premium version.', 'booking' ); ?></span>
2182 </div>
2183 <?php endif; ?>
2184 <?php else : ?>
2185 <select id="wpbc_calendar_resource_id" name="resource_id">
2186 <?php foreach ( $resources as $resource ) : ?>
2187 <option value="<?php echo esc_attr( $resource['id'] ); ?>" <?php selected( $resource_id, (int) $resource['id'] ); ?>><?php echo esc_html( $resource['title'] ); ?></option>
2188 <?php endforeach; ?>
2189 </select>
2190 <?php endif; ?>
2191 </div>
2192 <div class="wpbc_ts_control wpbc_calendar_control_months">
2193 <label for="wpbc_calendar_months_count"><?php esc_html_e( 'Months', 'booking' ); ?></label>
2194 <select id="wpbc_calendar_months_count" name="months_count">
2195 <?php foreach ( array( 1, 2, 3, 4, 6, 12 ) as $month_option ) : ?>
2196 <option value="<?php echo esc_attr( $month_option ); ?>" <?php selected( $months_count, $month_option ); ?>><?php echo esc_html( $month_option ); ?></option>
2197 <?php endforeach; ?>
2198 </select>
2199 </div>
2200 </form>
2201 <?php wpbc_settings_calendar__render_calendar_preview( $resource_id, $months_count ); ?>
2202 <div class="wpbc_calendar_settings_notes" data-wpbc-calendar-notes="1">
2203 <div class="wpbc_ts_hint wpbc_calendar_hint_bar">
2204 <span class="wpbc_icn_info_outline"></span>
2205 <?php esc_html_e( 'Preview how date selection behaves before saving the calendar settings.', 'booking' ); ?>
2206 </div>
2207 </div>
2208 </div>
2209 <?php
2210
2211 do_action( 'wpbc_hook_settings_page_footer', 'page_settings_calendar' );
2212 }
2213 }
2214 add_action( 'wpbc_menu_created', array( new WPBC_Page_Settings_Calendar(), '__construct' ) );
2215