PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
11.9 11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 All 205 releases
← All changes | includes/page-settings-themes/settings_themes__page.php +400 -32 11.3 → 11.9 View file →
@@ -8,8 +8,10 @@
8 8 if ( ! defined( 'ABSPATH' ) ) {
9 9 exit;
10 10 }
11 11
12 +require_once WPBC_PLUGIN_DIR . '/includes/_front_end/form-style-presets.php';
13 +
12 14 /**
13 15 * Check whether the Appearance / Theme settings page is active.
14 16 *
15 17 * @return bool
@@ -96,8 +98,9 @@
96 98 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/settings_themes_page.css',
97 99 array( 'wpbc-calendar', 'wpbc-all-admin' ),
98 100 WP_BK_VERSION_NUM
99 101 );
102 + wp_enqueue_style( 'coloris', wpbc_plugin_url( '/vendors/coloris/dist/coloris.min.css' ), array(), WP_BK_VERSION_NUM );
100 103 }
101 104 add_action( 'wpbc_enqueue_css_files', 'wpbc_settings_themes_enqueue_css_files', 66 );
102 105
103 106 /**
@@ -117,11 +120,19 @@
117 120 return;
118 121 }
119 122
120 123 wp_enqueue_script(
124 + 'coloris',
125 + wpbc_plugin_url( '/vendors/coloris/dist/coloris.min.js' ),
126 + array(),
127 + WP_BK_VERSION_NUM,
128 + array( 'in_footer' => WPBC_JS_IN_FOOTER )
129 + );
130 +
131 + wp_enqueue_script(
121 132 'wpbc-settings-themes-page',
122 133 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/settings_themes_page.js',
123 - array( 'jquery', 'wpbc_all' ),
134 + array( 'jquery', 'wpbc_all', 'coloris' ),
124 135 WP_BK_VERSION_NUM,
125 136 array( 'in_footer' => WPBC_JS_IN_FOOTER )
126 137 );
127 138
@@ -134,8 +145,12 @@
134 145 'nonce' => wp_create_nonce( 'wpbc_settings_themes_ajax_nonce' ),
135 146 'action' => 'WPBC_AJX_SETTINGS_THEMES_SAVE',
136 147 'preview_action' => 'WPBC_AJX_SETTINGS_THEMES_PREVIEW',
137 148 'settings' => wpbc_settings_themes__get_settings_response(),
149 + 'form_style_presets' => wpbc_bfb_settings__get_form_style_presets(),
150 + 'form_style_css_var_names' => wpbc_bfb_settings__get_form_style_css_var_names(),
151 + 'custom_form_style_defaults' => wpbc_bfb_settings__get_default_custom_form_style_options(),
152 + 'form_accent_defaults' => wpbc_bfb_settings__get_default_form_accent_options(),
138 153 'days_selection' => wpbc_settings_themes__get_days_selection_response(),
139 154 'i18n' => array(
140 155 'saving' => __( 'Saving', 'booking' ),
141 156 'saved' => __( 'Appearance settings updated.', 'booking' ),
@@ -397,9 +412,9 @@
397 412 function wpbc_settings_themes__sanitize_preview_mode( $preview_mode ) {
398 413
399 414 $preview_mode = sanitize_key( (string) $preview_mode );
400 415
401 - return array_key_exists( $preview_mode, wpbc_settings_themes__get_preview_mode_options() ) ? $preview_mode : 'calendar';
416 + return array_key_exists( $preview_mode, wpbc_settings_themes__get_preview_mode_options() ) ? $preview_mode : 'form';
402 417 }
403 418
404 419 /**
405 420 * Get preview mode from request.
@@ -408,9 +423,9 @@
408 423 */
409 424 function wpbc_settings_themes__get_preview_mode() {
410 425
411 426 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
412 - $preview_mode = isset( $_REQUEST['preview_mode'] ) ? sanitize_key( wp_unslash( $_REQUEST['preview_mode'] ) ) : 'calendar';
427 + $preview_mode = isset( $_REQUEST['preview_mode'] ) ? sanitize_key( wp_unslash( $_REQUEST['preview_mode'] ) ) : 'form';
413 428
414 429 return wpbc_settings_themes__sanitize_preview_mode( $preview_mode );
415 430 }
416 431
@@ -491,8 +506,87 @@
491 506 );
492 507 }
493 508
494 509 /**
510 + * Get booking form container preset options.
511 + *
512 + * @return array
513 + */
514 +function wpbc_settings_themes__get_form_appearance_preset_options() {
515 +
516 + return array(
517 + 'bordered' => __( 'Bordered', 'booking' ),
518 + 'none' => __( 'No border', 'booking' ),
519 + 'soft' => __( 'Soft background', 'booking' ),
520 + 'custom' => __( 'Custom per form', 'booking' ),
521 + );
522 +}
523 +
524 +/**
525 + * Get combined booking form style choices for the visual selector.
526 + *
527 + * @return array
528 + */
529 +function wpbc_settings_themes__get_form_style_options() {
530 +
531 + return wpbc_bfb_settings__get_form_style_options();
532 +}
533 +
534 +/**
535 + * Resolve the combined visual form style value from saved settings.
536 + *
537 + * @param string $theme Form theme option.
538 + * @param string $preset Form appearance preset option.
539 + *
540 + * @return string
541 + */
542 +function wpbc_settings_themes__get_form_style_value( $theme, $preset ) {
543 +
544 + $theme = ( 'wpbc_theme_dark_1' === (string) $theme ) ? 'dark' : 'light';
545 + $preset = (string) $preset;
546 +
547 + if ( 'custom' === $preset ) {
548 + return 'custom';
549 + }
550 + if ( ! in_array( $preset, array( 'bordered', 'none', 'soft' ), true ) ) {
551 + $preset = 'bordered';
552 + }
553 +
554 + return $theme . '_' . $preset;
555 +}
556 +
557 +/**
558 + * Map the combined visual form style value to existing saved options.
559 + *
560 + * @param string $style Combined style value.
561 + * @param string $current_theme Current theme fallback.
562 + *
563 + * @return array
564 + */
565 +function wpbc_settings_themes__map_form_style_to_options( $style, $current_theme = '' ) {
566 +
567 + $style = sanitize_key( (string) $style );
568 + $current_theme = ( 'wpbc_theme_dark_1' === (string) $current_theme ) ? 'wpbc_theme_dark_1' : '';
569 +
570 + if ( 'custom' === $style ) {
571 + return array(
572 + 'booking_form_theme' => $current_theme,
573 + 'booking_form_appearance_preset' => 'custom',
574 + );
575 + }
576 +
577 + $parts = explode( '_', $style );
578 + $theme = ( isset( $parts[0] ) && 'dark' === $parts[0] ) ? 'wpbc_theme_dark_1' : '';
579 + $preset = isset( $parts[1] ) ? (string) $parts[1] : 'bordered';
580 + $preset = in_array( $preset, array( 'bordered', 'none', 'soft' ), true ) ? $preset : 'bordered';
581 +
582 + return array(
583 + 'booking_form_theme' => $theme,
584 + 'booking_form_appearance_preset' => $preset,
585 + );
586 +}
587 +
588 +/**
495 589 * Get time picker skin options.
496 590 *
497 591 * @return array
498 592 */
@@ -497,8 +591,9 @@
497 591 * @return array
498 592 */
499 593 function wpbc_settings_themes__get_time_picker_skin_options() {
500 594
595 + $automatic_skin = '/css/time_picker_skins/form_style.css';
501 596 $timeslot_picker_skins_options = array();
502 597 $upload_dir = wp_upload_dir();
503 598
504 599 if ( function_exists( 'wpbc_dir_list' ) ) {
@@ -514,11 +609,37 @@
514 609 $timeslot_picker_skins_options[ $skin_file[1] ] = $skin_file[2];
515 610 }
516 611 }
517 612
613 + // Keep the integrated option first and give bundled skins readable labels.
614 + if ( file_exists( WPBC_PLUGIN_DIR . $automatic_skin ) ) {
615 + unset( $timeslot_picker_skins_options[ $automatic_skin ] );
616 + $timeslot_picker_skins_options = array_merge(
617 + array(
618 + $automatic_skin => __( 'Automatic — Match Booking Form', 'booking' ),
619 + ),
620 + $timeslot_picker_skins_options
621 + );
622 + }
623 +
624 + $bundled_skin_titles = array(
625 + '/css/time_picker_skins/light__24_8.css' => __( 'Light', 'booking' ),
626 + '/css/time_picker_skins/grey.css' => __( 'Grey', 'booking' ),
627 + '/css/time_picker_skins/black.css' => __( 'Black', 'booking' ),
628 + '/css/time_picker_skins/blue.css' => __( 'Blue', 'booking' ),
629 + '/css/time_picker_skins/green.css' => __( 'Green', 'booking' ),
630 + '/css/time_picker_skins/orange.css' => __( 'Orange', 'booking' ),
631 + '/css/time_picker_skins/marine.css' => __( 'Marine', 'booking' ),
632 + );
633 + foreach ( $bundled_skin_titles as $skin_path => $skin_title ) {
634 + if ( isset( $timeslot_picker_skins_options[ $skin_path ] ) ) {
635 + $timeslot_picker_skins_options[ $skin_path ] = $skin_title;
636 + }
637 + }
638 +
518 639 if ( empty( $timeslot_picker_skins_options ) ) {
519 640 $default_options_values = wpbc_get_default_options();
520 - $default_skin = isset( $default_options_values['booking_timeslot_picker_skin'] ) ? $default_options_values['booking_timeslot_picker_skin'] : '/css/time_picker_skins/grey.css';
641 + $default_skin = isset( $default_options_values['booking_timeslot_picker_skin'] ) ? $default_options_values['booking_timeslot_picker_skin'] : $automatic_skin;
521 642 $timeslot_picker_skins_options[ $default_skin ] = __( 'Default', 'booking' );
522 643 }
523 644
524 645 return $timeslot_picker_skins_options;
@@ -611,13 +732,29 @@
611 732 * @return array
612 733 */
613 734 function wpbc_settings_themes__get_settings_response() {
614 735
615 - return array(
616 - 'booking_form_theme' => get_bk_option( 'booking_form_theme' ),
736 + $form_style = wpbc_bfb_settings__get_current_form_style();
737 + $transition_values = wpbc_settings_themes__map_form_style_to_options( $form_style, '' );
738 + $custom_values = wpbc_bfb_settings__get_custom_form_style_options();
739 + $accent_values = wpbc_bfb_settings__get_form_accent_options();
740 +
741 + return array_merge(
742 + array(
743 + 'booking_form_style' => $form_style,
744 + 'booking_form_theme' => $transition_values['booking_form_theme'],
745 + 'booking_form_appearance_preset' => $transition_values['booking_form_appearance_preset'],
746 + 'booking_form_appearance_background_color' => get_bk_option( 'booking_form_appearance_background_color' ) ? get_bk_option( 'booking_form_appearance_background_color' ) : '#ffffff',
747 + 'booking_form_appearance_border_color' => get_bk_option( 'booking_form_appearance_border_color' ) ? get_bk_option( 'booking_form_appearance_border_color' ) : '#cccccc',
748 + 'booking_form_appearance_border_width' => get_bk_option( 'booking_form_appearance_border_width' ) ? get_bk_option( 'booking_form_appearance_border_width' ) : '1px',
749 + 'booking_form_appearance_border_radius' => get_bk_option( 'booking_form_appearance_border_radius' ) ? get_bk_option( 'booking_form_appearance_border_radius' ) : '2px',
750 + 'booking_form_appearance_padding' => get_bk_option( 'booking_form_appearance_padding' ) ? get_bk_option( 'booking_form_appearance_padding' ) : '10px 30px',
617 751 'booking_skin' => wpbc_settings_themes__normalize_calendar_skin_value( get_bk_option( 'booking_skin' ) ),
618 752 'booking_timeslot_picker_skin' => get_bk_option( 'booking_timeslot_picker_skin' ),
619 753 'booking_timeslot_picker' => get_bk_option( 'booking_timeslot_picker' ),
754 + ),
755 + $custom_values,
756 + $accent_values
620 757 );
621 758 }
622 759
623 760 /**
@@ -653,9 +790,35 @@
653 790 */
654 791 function wpbc_settings_themes__get_preview_option_overrides( $current_settings ) {
655 792
656 793 $option_names = array(
657 - 'booking_form_theme',
794 + 'booking_form_style',
795 + 'booking_form_accent_enabled',
796 + 'booking_form_accent_color',
797 + 'booking_form_custom_background_color',
798 + 'booking_form_custom_border_color',
799 + 'booking_form_custom_border_width',
800 + 'booking_form_custom_border_radius',
801 + 'booking_form_custom_padding_vertical',
802 + 'booking_form_custom_padding_horizontal',
803 + 'booking_form_custom_text_color',
804 + 'booking_form_custom_field_background_color',
805 + 'booking_form_custom_field_text_color',
806 + 'booking_form_custom_field_border_color',
807 + 'booking_form_custom_button_background_color',
808 + 'booking_form_custom_button_text_color',
809 + 'booking_form_custom_button_border_color',
810 + 'booking_form_custom_button_hover_background_color',
811 + 'booking_form_custom_button_hover_text_color',
812 + 'booking_form_custom_button_hover_border_color',
813 + 'booking_form_custom_secondary_button_background_color',
814 + 'booking_form_custom_secondary_button_text_color',
815 + 'booking_form_custom_secondary_button_border_color',
816 + 'booking_form_custom_secondary_button_hover_background_color',
817 + 'booking_form_custom_secondary_button_hover_text_color',
818 + 'booking_form_custom_secondary_button_hover_border_color',
819 + 'booking_form_custom_button_border_width',
820 + 'booking_form_custom_button_border_radius',
658 821 'booking_skin',
659 822 'booking_timeslot_picker_skin',
660 823 'booking_timeslot_picker',
661 824 );
@@ -666,8 +829,19 @@
666 829 $overrides[ $option_name ] = $current_settings[ $option_name ];
667 830 }
668 831 }
669 832
833 + if ( isset( $overrides['booking_form_style'] ) ) {
834 + $style = wpbc_bfb_settings__sanitize_form_style( $overrides['booking_form_style'] );
835 + $preset = wpbc_bfb_settings__get_form_style_preset( $style );
836 + $legacy_theme = isset( $preset['theme_class'] ) ? sanitize_html_class( (string) $preset['theme_class'] ) : '';
837 + $legacy_container = isset( $preset['container_style'] ) ? sanitize_key( (string) $preset['container_style'] ) : 'bordered';
838 + $legacy_container = in_array( $legacy_container, array( 'bordered', 'none', 'soft', 'custom' ), true ) ? $legacy_container : 'bordered';
839 +
840 + $overrides['booking_form_theme'] = $legacy_theme;
841 + $overrides['booking_form_appearance_preset'] = $legacy_container;
842 + }
843 +
670 844 return $overrides;
671 845 }
672 846
673 847 /**
@@ -679,24 +853,137 @@
679 853 */
680 854 function wpbc_settings_themes__validate_data( $post_data ) {
681 855
682 856 $default_options_values = wpbc_get_default_options();
683 - $form_theme_options = wpbc_settings_themes__get_form_theme_options();
684 857 $calendar_skin_options = wpbc_settings_themes__get_calendar_skin_options_for_select();
685 858 $time_skin_options = wpbc_settings_themes__get_time_picker_skin_options();
859 + $custom_values = wpbc_bfb_settings__get_custom_form_style_options();
860 + $accent_values = wpbc_bfb_settings__get_form_accent_options();
686 861
687 - $cleaned = array(
688 - 'booking_form_theme' => isset( $default_options_values['booking_form_theme'] ) ? $default_options_values['booking_form_theme'] : '',
862 + $cleaned = array_merge(
863 + array(
864 + 'booking_form_style' => isset( $default_options_values['booking_form_style'] ) ? wpbc_bfb_settings__sanitize_form_style( $default_options_values['booking_form_style'] ) : wpbc_bfb_settings__get_default_form_style(),
689 865 'booking_skin' => isset( $default_options_values['booking_skin'] ) ? $default_options_values['booking_skin'] : '',
690 866 'booking_timeslot_picker_skin' => isset( $default_options_values['booking_timeslot_picker_skin'] ) ? $default_options_values['booking_timeslot_picker_skin'] : '',
691 867 'booking_timeslot_picker' => isset( $default_options_values['booking_timeslot_picker'] ) ? $default_options_values['booking_timeslot_picker'] : 'Off',
868 + ),
869 + $custom_values,
870 + $accent_values
692 871 );
693 872
694 - if ( isset( $post_data['booking_form_theme'] ) ) {
695 - $value = sanitize_text_field( wp_unslash( $post_data['booking_form_theme'] ) );
696 - if ( array_key_exists( $value, $form_theme_options ) ) {
697 - $cleaned['booking_form_theme'] = $value;
873 + if ( isset( $post_data['booking_form_style'] ) ) {
874 + $cleaned['booking_form_style'] = wpbc_bfb_settings__sanitize_form_style( wp_unslash( $post_data['booking_form_style'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
875 + }
876 +
877 + $cleaned['booking_form_accent_enabled'] = ( isset( $post_data['booking_form_accent_enabled'] ) && 'On' === sanitize_text_field( wp_unslash( $post_data['booking_form_accent_enabled'] ) ) ) ? 'On' : 'Off';
878 + if ( isset( $post_data['booking_form_accent_color'] ) ) {
879 + $cleaned['booking_form_accent_color'] = wpbc_bfb_settings__sanitize_form_accent_color( sanitize_text_field( wp_unslash( $post_data['booking_form_accent_color'] ) ), WPBC_DEFAULT_FORM_ACCENT_COLOR );
880 + }
881 +
882 + $sanitize_color = function ( $value, $fallback ) {
883 + $value = trim( sanitize_text_field( wp_unslash( $value ) ) );
884 + if ( preg_match( '/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i', $value ) || 'transparent' === $value ) {
885 + return $value;
698 886 }
887 + return $fallback;
888 + };
889 + $sanitize_length = function ( $value, $fallback ) {
890 + $value = trim( sanitize_text_field( wp_unslash( $value ) ) );
891 + if ( preg_match( '/^\d+(?:\.\d+)?(?:px|rem|em|%)$/i', $value ) ) {
892 + return $value;
893 + }
894 + return $fallback;
895 + };
896 + $sanitize_spacing = function ( $value, $fallback ) {
897 + $value = preg_replace( '/\s+/', ' ', trim( sanitize_text_field( wp_unslash( $value ) ) ) );
898 + if ( '' === $value ) {
899 + return $fallback;
900 + }
901 + $parts = explode( ' ', $value );
902 + if ( count( $parts ) < 1 || count( $parts ) > 4 ) {
903 + return $fallback;
904 + }
905 + foreach ( $parts as $part ) {
906 + if ( ! preg_match( '/^\d+(?:\.\d+)?(?:px|rem|em|%)$/i', $part ) ) {
907 + return $fallback;
908 + }
909 + }
910 + return implode( ' ', $parts );
911 + };
912 +
913 + if ( 'custom' === $cleaned['booking_form_style'] ) {
914 + if ( isset( $post_data['booking_form_custom_background_color'] ) ) {
915 + $cleaned['booking_form_custom_background_color'] = $sanitize_color( $post_data['booking_form_custom_background_color'], '#ffffff' );
916 + }
917 + if ( isset( $post_data['booking_form_custom_border_color'] ) ) {
918 + $cleaned['booking_form_custom_border_color'] = $sanitize_color( $post_data['booking_form_custom_border_color'], '#cccccc' );
919 + }
920 + if ( isset( $post_data['booking_form_custom_border_width'] ) ) {
921 + $cleaned['booking_form_custom_border_width'] = $sanitize_length( $post_data['booking_form_custom_border_width'], '1px' );
922 + }
923 + if ( isset( $post_data['booking_form_custom_border_radius'] ) ) {
924 + $cleaned['booking_form_custom_border_radius'] = $sanitize_length( $post_data['booking_form_custom_border_radius'], '2px' );
925 + }
926 + if ( isset( $post_data['booking_form_custom_padding_vertical'] ) ) {
927 + $cleaned['booking_form_custom_padding_vertical'] = $sanitize_length( $post_data['booking_form_custom_padding_vertical'], '10px' );
928 + }
929 + if ( isset( $post_data['booking_form_custom_padding_horizontal'] ) ) {
930 + $cleaned['booking_form_custom_padding_horizontal'] = $sanitize_length( $post_data['booking_form_custom_padding_horizontal'], '30px' );
931 + }
932 + if ( isset( $post_data['booking_form_custom_text_color'] ) ) {
933 + $cleaned['booking_form_custom_text_color'] = $sanitize_color( $post_data['booking_form_custom_text_color'], '#1d2327' );
934 + }
935 + if ( isset( $post_data['booking_form_custom_field_background_color'] ) ) {
936 + $cleaned['booking_form_custom_field_background_color'] = $sanitize_color( $post_data['booking_form_custom_field_background_color'], '#ffffff' );
937 + }
938 + if ( isset( $post_data['booking_form_custom_field_text_color'] ) ) {
939 + $cleaned['booking_form_custom_field_text_color'] = $sanitize_color( $post_data['booking_form_custom_field_text_color'], '#3c434a' );
940 + }
941 + if ( isset( $post_data['booking_form_custom_field_border_color'] ) ) {
942 + $cleaned['booking_form_custom_field_border_color'] = $sanitize_color( $post_data['booking_form_custom_field_border_color'], '#cccccc' );
943 + }
944 + if ( isset( $post_data['booking_form_custom_button_background_color'] ) ) {
945 + $cleaned['booking_form_custom_button_background_color'] = $sanitize_color( $post_data['booking_form_custom_button_background_color'], '#066aab' );
946 + }
947 + if ( isset( $post_data['booking_form_custom_button_text_color'] ) ) {
948 + $cleaned['booking_form_custom_button_text_color'] = $sanitize_color( $post_data['booking_form_custom_button_text_color'], '#ffffff' );
949 + }
950 + if ( isset( $post_data['booking_form_custom_button_border_color'] ) ) {
951 + $cleaned['booking_form_custom_button_border_color'] = $sanitize_color( $post_data['booking_form_custom_button_border_color'], '#066aab' );
952 + }
953 + if ( isset( $post_data['booking_form_custom_button_hover_background_color'] ) ) {
954 + $cleaned['booking_form_custom_button_hover_background_color'] = $sanitize_color( $post_data['booking_form_custom_button_hover_background_color'], '#055589' );
955 + }
956 + if ( isset( $post_data['booking_form_custom_button_hover_text_color'] ) ) {
957 + $cleaned['booking_form_custom_button_hover_text_color'] = $sanitize_color( $post_data['booking_form_custom_button_hover_text_color'], '#ffffff' );
958 + }
959 + if ( isset( $post_data['booking_form_custom_button_hover_border_color'] ) ) {
960 + $cleaned['booking_form_custom_button_hover_border_color'] = $sanitize_color( $post_data['booking_form_custom_button_hover_border_color'], '#055589' );
961 + }
962 + if ( isset( $post_data['booking_form_custom_secondary_button_background_color'] ) ) {
963 + $cleaned['booking_form_custom_secondary_button_background_color'] = $sanitize_color( $post_data['booking_form_custom_secondary_button_background_color'], '#fdfdfd' );
964 + }
965 + if ( isset( $post_data['booking_form_custom_secondary_button_text_color'] ) ) {
966 + $cleaned['booking_form_custom_secondary_button_text_color'] = $sanitize_color( $post_data['booking_form_custom_secondary_button_text_color'], '#444444' );
967 + }
968 + if ( isset( $post_data['booking_form_custom_secondary_button_border_color'] ) ) {
969 + $cleaned['booking_form_custom_secondary_button_border_color'] = $sanitize_color( $post_data['booking_form_custom_secondary_button_border_color'], '#eeeeee' );
970 + }
971 + if ( isset( $post_data['booking_form_custom_secondary_button_hover_background_color'] ) ) {
972 + $cleaned['booking_form_custom_secondary_button_hover_background_color'] = $sanitize_color( $post_data['booking_form_custom_secondary_button_hover_background_color'], '#fdfdfd' );
973 + }
974 + if ( isset( $post_data['booking_form_custom_secondary_button_hover_text_color'] ) ) {
975 + $cleaned['booking_form_custom_secondary_button_hover_text_color'] = $sanitize_color( $post_data['booking_form_custom_secondary_button_hover_text_color'], '#444444' );
976 + }
977 + if ( isset( $post_data['booking_form_custom_secondary_button_hover_border_color'] ) ) {
978 + $cleaned['booking_form_custom_secondary_button_hover_border_color'] = $sanitize_color( $post_data['booking_form_custom_secondary_button_hover_border_color'], '#4d91cd' );
979 + }
980 + if ( isset( $post_data['booking_form_custom_button_border_width'] ) ) {
981 + $cleaned['booking_form_custom_button_border_width'] = $sanitize_length( $post_data['booking_form_custom_button_border_width'], '1px' );
982 + }
983 + if ( isset( $post_data['booking_form_custom_button_border_radius'] ) ) {
984 + $cleaned['booking_form_custom_button_border_radius'] = $sanitize_length( $post_data['booking_form_custom_button_border_radius'], '3px' );
985 + }
699 986 }
700 987
701 988 if ( isset( $post_data['booking_skin'] ) ) {
702 989 $value = wpbc_settings_themes__normalize_calendar_skin_value( sanitize_text_field( wp_unslash( $post_data['booking_skin'] ) ) );
@@ -727,9 +1014,35 @@
727 1014 * @return void
728 1015 */
729 1016 function wpbc_settings_themes__update_settings( $cleaned_data ) {
730 1017
731 - update_bk_option( 'booking_form_theme', $cleaned_data['booking_form_theme'] );
1018 + update_bk_option( 'booking_form_style', $cleaned_data['booking_form_style'] );
1019 + update_bk_option( 'booking_form_accent_enabled', $cleaned_data['booking_form_accent_enabled'] );
1020 + update_bk_option( 'booking_form_accent_color', $cleaned_data['booking_form_accent_color'] );
1021 + update_bk_option( 'booking_form_custom_background_color', $cleaned_data['booking_form_custom_background_color'] );
1022 + update_bk_option( 'booking_form_custom_border_color', $cleaned_data['booking_form_custom_border_color'] );
1023 + update_bk_option( 'booking_form_custom_border_width', $cleaned_data['booking_form_custom_border_width'] );
1024 + update_bk_option( 'booking_form_custom_border_radius', $cleaned_data['booking_form_custom_border_radius'] );
1025 + update_bk_option( 'booking_form_custom_padding_vertical', $cleaned_data['booking_form_custom_padding_vertical'] );
1026 + update_bk_option( 'booking_form_custom_padding_horizontal', $cleaned_data['booking_form_custom_padding_horizontal'] );
1027 + update_bk_option( 'booking_form_custom_text_color', $cleaned_data['booking_form_custom_text_color'] );
1028 + update_bk_option( 'booking_form_custom_field_background_color', $cleaned_data['booking_form_custom_field_background_color'] );
1029 + update_bk_option( 'booking_form_custom_field_text_color', $cleaned_data['booking_form_custom_field_text_color'] );
1030 + update_bk_option( 'booking_form_custom_field_border_color', $cleaned_data['booking_form_custom_field_border_color'] );
1031 + update_bk_option( 'booking_form_custom_button_background_color', $cleaned_data['booking_form_custom_button_background_color'] );
1032 + update_bk_option( 'booking_form_custom_button_text_color', $cleaned_data['booking_form_custom_button_text_color'] );
1033 + update_bk_option( 'booking_form_custom_button_border_color', $cleaned_data['booking_form_custom_button_border_color'] );
1034 + update_bk_option( 'booking_form_custom_button_hover_background_color', $cleaned_data['booking_form_custom_button_hover_background_color'] );
1035 + update_bk_option( 'booking_form_custom_button_hover_text_color', $cleaned_data['booking_form_custom_button_hover_text_color'] );
1036 + update_bk_option( 'booking_form_custom_button_hover_border_color', $cleaned_data['booking_form_custom_button_hover_border_color'] );
1037 + update_bk_option( 'booking_form_custom_secondary_button_background_color', $cleaned_data['booking_form_custom_secondary_button_background_color'] );
1038 + update_bk_option( 'booking_form_custom_secondary_button_text_color', $cleaned_data['booking_form_custom_secondary_button_text_color'] );
1039 + update_bk_option( 'booking_form_custom_secondary_button_border_color', $cleaned_data['booking_form_custom_secondary_button_border_color'] );
1040 + update_bk_option( 'booking_form_custom_secondary_button_hover_background_color', $cleaned_data['booking_form_custom_secondary_button_hover_background_color'] );
1041 + update_bk_option( 'booking_form_custom_secondary_button_hover_text_color', $cleaned_data['booking_form_custom_secondary_button_hover_text_color'] );
1042 + update_bk_option( 'booking_form_custom_secondary_button_hover_border_color', $cleaned_data['booking_form_custom_secondary_button_hover_border_color'] );
1043 + update_bk_option( 'booking_form_custom_button_border_width', $cleaned_data['booking_form_custom_button_border_width'] );
1044 + update_bk_option( 'booking_form_custom_button_border_radius', $cleaned_data['booking_form_custom_button_border_radius'] );
732 1045 update_bk_option( 'booking_skin', $cleaned_data['booking_skin'] );
733 1046 update_bk_option( 'booking_timeslot_picker_skin', $cleaned_data['booking_timeslot_picker_skin'] );
734 1047 update_bk_option( 'booking_timeslot_picker', $cleaned_data['booking_timeslot_picker'] );
735 1048 }
@@ -825,9 +1138,9 @@
825 1138 * @param array $preview_settings Optional settings.
826 1139 *
827 1140 * @return void
828 1141 */
829 -function wpbc_settings_themes__render_calendar_preview( $resource_id, $months_count, $preview_settings = array(), $preview_mode = 'calendar', $custom_booking_form = 'standard' ) {
1142 +function wpbc_settings_themes__render_calendar_preview( $resource_id, $months_count, $preview_settings = array(), $preview_mode = 'form', $custom_booking_form = 'standard' ) {
830 1143
831 1144 global $wpbc_settings_themes__preview_options;
832 1145
833 1146 $resource_id = wpbc_settings_themes__sanitize_preview_resource_id( $resource_id );
@@ -832,9 +1145,11 @@
832 1145
833 1146 $resource_id = wpbc_settings_themes__sanitize_preview_resource_id( $resource_id );
834 1147 $months_count = wpbc_settings_themes__sanitize_preview_months_count( $months_count );
835 1148 $current_settings = wp_parse_args( $preview_settings, wpbc_settings_themes__get_settings_response() );
836 - $form_theme = sanitize_html_class( $current_settings['booking_form_theme'] );
1149 + $form_style = isset( $current_settings['booking_form_style'] ) ? wpbc_bfb_settings__sanitize_form_style( $current_settings['booking_form_style'] ) : wpbc_bfb_settings__get_default_form_style();
1150 + $form_style_preset = wpbc_bfb_settings__get_form_style_preset( $form_style );
1151 + $form_theme = isset( $form_style_preset['theme_class'] ) ? sanitize_html_class( (string) $form_style_preset['theme_class'] ) : '';
837 1152 $preview_mode = wpbc_settings_themes__sanitize_preview_mode( $preview_mode );
838 1153 $custom_booking_form = wpbc_settings_themes__sanitize_custom_booking_form( $custom_booking_form );
839 1154 $previous_preview_options = isset( $wpbc_settings_themes__preview_options ) ? $wpbc_settings_themes__preview_options : null;
840 1155 $wpbc_settings_themes__preview_options = wpbc_settings_themes__get_preview_option_overrides( $current_settings );
@@ -978,15 +1293,15 @@
978 1293 'is_show_top_path' => true,
979 1294 'right_vertical_sidebar__is_show' => true,
980 1295 'right_vertical_sidebar__default_view_mode' => '',
981 1296 'right_vertical_sidebar_compact__is_show' => true,
982 - 'left_navigation__default_view_mode' => 'compact',
1297 + 'left_navigation__default_view_mode' => '', // FixIn:11.7.1.1: 'compact',
983 1298 'top_path_title' => __( 'Appearance', 'booking' ) . ' / ' . __( 'Theme', 'booking' ),
984 - 'title' => __( 'Appearance', 'booking' ) . ' / ' . __( 'Theme', 'booking' ) .
985 - '<span class="wpbc_new_label" style="margin-left: auto;">' . esc_html__( 'New', 'booking' ) . '</span>',
1299 + 'title' => __( 'Appearance', 'booking' ) . ' / ' . __( 'Theme', 'booking' ),
1300 + // . '<span class="wpbc_new_label" style="margin-left: auto;">' . esc_html__( 'New', 'booking' ) . '</span>'
986 1301 'hint' => __( 'Preview and configure the booking form theme, calendar skin, and time slot appearance.', 'booking' ),
987 1302 'page_title' => __( 'Appearance', 'booking' ) . ' / ' . __( 'Theme', 'booking' ),
988 - 'link' => '',
1303 + 'link' => function_exists( 'wpbc_get_settings_themes_url' ) ? wpbc_get_settings_themes_url() : admin_url( 'admin.php?page=wpbc-settings&tab=themes' ),
989 1304 'position' => '',
990 1305 'css_classes' => 'wpbc_top_tab__themes',
991 1306 'icon' => '',
992 1307 'font_icon' => 'wpbc-bi-palette-fill',
@@ -1098,11 +1413,14 @@
1098 1413 public function right_panel_settings_content() {
1099 1414
1100 1415 $form_name = 'wpbc_settings_themes_form';
1101 1416 $current_settings = wpbc_settings_themes__get_settings_response();
1102 - $form_theme_options = wpbc_settings_themes__get_form_theme_options();
1417 + $form_style_options = wpbc_settings_themes__get_form_style_options();
1103 1418 $calendar_skin_options = wpbc_settings_themes__get_calendar_skin_options_for_select();
1104 1419 $time_skin_options = wpbc_settings_themes__get_time_picker_skin_options();
1420 + $current_form_style = wpbc_bfb_settings__sanitize_form_style( $current_settings['booking_form_style'] );
1421 + $current_form_accent = wpbc_bfb_settings__get_form_accent_options( $current_settings );
1422 + $transition_values = wpbc_settings_themes__map_form_style_to_options( $current_form_style, '' );
1105 1423
1106 1424 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Appearance', 'booking' ) . ' / ' . __( 'Theme', 'booking' ), __( 'Visual settings for the booking form and calendar preview.', 'booking' ) );
1107 1425 ?>
1108 1426 <form method="post" id="<?php echo esc_attr( $form_name ); ?>" class="wpbc_theme_settings_form" data-wpbc-theme-settings-form="1">
@@ -1113,23 +1431,72 @@
1113 1431 WPBC_UI_Sidebar_Panels::render_collapsible_group(
1114 1432 array(
1115 1433 'id' => 'wpbc_theme_form_group',
1116 1434 'group' => 'settings-theme-form',
1117 - 'title' => __( 'Form Theme', 'booking' ),
1435 + 'title' => __( 'Form Style', 'booking' ),
1118 1436 'open' => true,
1119 1437 ),
1120 - function () use ( $form_theme_options, $current_settings ) {
1438 + function () use ( $form_style_options, $current_form_style, $current_form_accent, $transition_values ) {
1439 + $is_custom = ( 'custom' === (string) $current_form_style );
1440 + $builder_url = add_query_arg(
1441 + array(
1442 + 'page' => 'wpbc-settings',
1443 + 'tab' => 'builder_booking_form',
1444 + 'wpbc_bfb_panel' => 'form_settings',
1445 + 'wpbc_bfb_group' => 'settings-appearance',
1446 + 'wpbc_bfb_focus' => 'booking_form_custom_background_color',
1447 + ),
1448 + admin_url( 'admin.php' )
1449 + );
1450 + $accent_builder_url = add_query_arg(
1451 + array(
1452 + 'page' => 'wpbc-settings',
1453 + 'tab' => 'builder_booking_form',
1454 + 'wpbc_bfb_panel' => 'form_settings',
1455 + 'wpbc_bfb_group' => 'settings-appearance',
1456 + 'wpbc_bfb_focus' => 'booking_form_accent_apply_to_components',
1457 + ),
1458 + admin_url( 'admin.php' )
1459 + );
1121 1460 ?>
1122 - <div class="wpbc_theme_choice_grid">
1123 - <?php foreach ( $form_theme_options as $theme_value => $theme_title ) : ?>
1124 - <label class="wpbc_theme_choice <?php echo ( (string) $current_settings['booking_form_theme'] === (string) $theme_value ) ? 'is-selected' : ''; ?>">
1125 - <input type="radio" name="booking_form_theme" value="<?php echo esc_attr( $theme_value ); ?>" <?php checked( (string) $current_settings['booking_form_theme'], (string) $theme_value ); ?> />
1126 - <span class="wpbc_theme_choice_swatch <?php echo esc_attr( sanitize_html_class( $theme_value ) ); ?>"></span>
1127 - <span class="wpbc_theme_choice_label"><?php echo esc_html( $theme_title ); ?></span>
1461 + <input type="hidden" id="booking_form_theme" value="<?php echo esc_attr( $transition_values['booking_form_theme'] ); ?>" />
1462 + <input type="hidden" id="booking_form_appearance_preset" value="<?php echo esc_attr( $transition_values['booking_form_appearance_preset'] ); ?>" data-wpbc-theme-appearance-control="1" />
1463 + <div class="wpbc_theme_field_row wpbc_theme_accent_toggle_row">
1464 + <label class="wpbc_theme_switch">
1465 + <input type="checkbox" id="booking_form_accent_enabled" name="booking_form_accent_enabled" value="On" <?php checked( 'On', $current_form_accent['booking_form_accent_enabled'] ); ?> data-wpbc-theme-accent-toggle="1" aria-describedby="booking_form_accent_enabled_description" />
1466 + <span class="wpbc_theme_switch_control" aria-hidden="true"><span class="wpbc_theme_switch_knob"></span></span>
1467 + <span class="wpbc_theme_switch_label"><?php esc_html_e( 'Custom accent color', 'booking' ); ?></span>
1468 + </label>
1469 + <p class="wpbc_theme_description" id="booking_form_accent_enabled_description"><?php esc_html_e( 'Use one accent for preset-style primary buttons, secondary-button hover borders, focus, selected choices, and navigation accents. Custom style keeps its explicitly configured button colors. Time slots use it only with the Automatic time-slot style.', 'booking' ); ?></p>
1470 + </div>
1471 + <div class="wpbc_theme_field_row wpbc_theme_accent_color_row" data-wpbc-theme-accent-color-row="1" data-wpbc-theme-accent-dependent="1" <?php echo ( 'On' === $current_form_accent['booking_form_accent_enabled'] ) ? '' : 'style="display:none;"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1472 + <label class="wpbc_theme_field_label" for="booking_form_accent_color"><?php esc_html_e( 'Accent color', 'booking' ); ?></label>
1473 + <input type="text" id="booking_form_accent_color" name="booking_form_accent_color" value="<?php echo esc_attr( $current_form_accent['booking_form_accent_color'] ); ?>" class="wpbc_theme_coloris" data-coloris autocomplete="off" pattern="^#[0-9A-Fa-f]{6}$" data-wpbc-theme-appearance-control="1" />
1474 + <p class="wpbc_theme_description"><?php esc_html_e( 'Preset styles calculate readable primary button text and hover colors automatically. Custom style uses its explicit button settings.', 'booking' ); ?></p>
1475 + </div>
1476 + <div class="wpbc_theme_field_row wpbc_theme_accent_components_row" data-wpbc-theme-accent-dependent="1" <?php echo ( 'On' === $current_form_accent['booking_form_accent_enabled'] ) ? '' : 'style="display:none;"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1477 + <a class="button button-secondary" href="<?php echo esc_url( $accent_builder_url ); ?>">
1478 + <?php esc_html_e( 'Apply accent to form elements…', 'booking' ); ?>
1479 + </a>
1480 + <p class="wpbc_theme_description"><?php esc_html_e( 'Open Forms Builder to copy the accent into editable component colors and switch time slots to Automatic — Match Booking Form.', 'booking' ); ?></p>
1481 + </div>
1482 + <div class="wpbc_theme_choice_grid wpbc_theme_style_choice_grid">
1483 + <?php foreach ( $form_style_options as $style_value => $style_title ) : ?>
1484 + <label class="wpbc_theme_choice <?php echo ( (string) $current_form_style === (string) $style_value ) ? 'is-selected' : ''; ?>">
1485 + <input type="radio" name="booking_form_style" value="<?php echo esc_attr( $style_value ); ?>" <?php checked( (string) $current_form_style, (string) $style_value ); ?> />
1486 + <span class="wpbc_theme_choice_swatch wpbc_theme_choice_swatch_<?php echo esc_attr( sanitize_html_class( $style_value ) ); ?>"></span>
1487 + <span class="wpbc_theme_choice_label"><?php echo esc_html( $style_title ); ?></span>
1128 1488 </label>
1129 1489 <?php endforeach; ?>
1130 1490 </div>
1131 - <p class="wpbc_theme_description"><?php esc_html_e( 'The form theme changes the booking form surface and can also guide matching calendar and time slot skins.', 'booking' ); ?></p>
1491 + <p class="wpbc_theme_description"><?php esc_html_e( 'Used globally by all booking forms. Dark styles can also guide matching calendar and time slot skins.', 'booking' ); ?></p>
1492 + <div class="wpbc_theme_notice" data-wpbc-theme-custom-appearance-notice="1" <?php echo $is_custom ? '' : 'style="display:none;"'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1493 + <p style="margin:0 0 10px 0;"><?php esc_html_e( 'Configure the global Custom style, including its container, fields, and buttons, in Forms Builder.', 'booking' ); ?></p>
1494 + <a class="button button-secondary" href="<?php echo esc_url( $builder_url ); ?>">
1495 + <i class="menu_icon icon-1x wpbc-bi-input-cursor-text"></i>
1496 + <span><?php esc_html_e( 'Edit in Forms Builder', 'booking' ); ?></span>
1497 + </a>
1498 + </div>
1132 1499 <?php
1133 1500 }
1134 1501 );
1135 1502
@@ -1199,9 +1566,9 @@
1199 1566 ),
1200 1567 function () use ( $time_skin_options, $current_settings ) {
1201 1568 ?>
1202 1569 <div class="wpbc_theme_field_row">
1203 - <label class="wpbc_theme_field_label" for="booking_timeslot_picker_skin"><?php esc_html_e( 'Time Picker Skin', 'booking' ); ?></label>
1570 + <label class="wpbc_theme_field_label" for="booking_timeslot_picker_skin"><?php esc_html_e( 'Time Slot Style', 'booking' ); ?></label>
1204 1571 <?php
1205 1572 wpbc_settings_themes__render_select(
1206 1573 'booking_timeslot_picker_skin',
1207 1574 $time_skin_options,
@@ -1214,8 +1581,9 @@
1214 1581 ),
1215 1582 )
1216 1583 );
1217 1584 ?>
1585 + <p class="description"><?php esc_html_e( 'Automatic matches time slots to the active Booking Form Style and accent color. Existing skins remain available for fixed color schemes.', 'booking' ); ?></p>
1218 1586 </div>
1219 1587 <label class="wpbc_theme_switch wpbc_theme_switch_card">
1220 1588 <input type="checkbox" name="booking_timeslot_picker" value="On" data-wpbc-theme-preview-notice="form" <?php checked( $current_settings['booking_timeslot_picker'], 'On' ); ?> />
1221 1589 <span class="wpbc_theme_switch_control" aria-hidden="true"><span class="wpbc_theme_switch_knob"></span></span>