| 1 |
<?php |
| 2 |
/** |
| 3 |
* Scoped Booking Form Style integration for the Appointment selector. |
| 4 |
* |
| 5 |
* @package Booking Calendar |
| 6 |
*/ |
| 7 |
|
| 8 |
if ( ! defined( 'ABSPATH' ) ) { |
| 9 |
exit; |
| 10 |
} |
| 11 |
|
| 12 |
/** |
| 13 |
* Return Form Style variables consumed by the Appointment interface. |
| 14 |
* |
| 15 |
* Keeping a strict whitelist prevents unrelated Booking Form variables from |
| 16 |
* entering the Appointment scope. The native form keeps its existing complete |
| 17 |
* and independently injected Form Style configuration. |
| 18 |
* |
| 19 |
* @return array<int,string> CSS custom-property names. |
| 20 |
*/ |
| 21 |
function wpbc_booking_appointment_get_theme_css_var_names() { |
| 22 |
return array( |
| 23 |
'--wpbc-bfb-form-background', |
| 24 |
'--wpbc-bfb-form-border-color', |
| 25 |
'--wpbc-bfb-form-border-width', |
| 26 |
'--wpbc-bfb-form-border-radius', |
| 27 |
'--wpbc-bfb-form-padding', |
| 28 |
'--wpbc-bfb-form-box-shadow', |
| 29 |
'--wpbc_form-label-color', |
| 30 |
'--wpbc_form-label-sublabel-color', |
| 31 |
'--wpbc_form-label-error-color', |
| 32 |
'--wpbc_form-field-background-color', |
| 33 |
'--wpbc_form-field-text-color', |
| 34 |
'--wpbc_form-field-border-color', |
| 35 |
'--wpbc_form-field-focus-border-color', |
| 36 |
'--wpbc_form-field-focus-shadow-color', |
| 37 |
'--wpbc_form-choice-checked-border-color', |
| 38 |
'--wpbc_form-choice-focus-color', |
| 39 |
'--wpbc_form-button-border-radius', |
| 40 |
'--wpbc_form-button-border-style', |
| 41 |
'--wpbc_form-button-border-size', |
| 42 |
'--wpbc_form-button-background-color', |
| 43 |
'--wpbc_form-button-background-color-alt', |
| 44 |
'--wpbc_form-button-border-color', |
| 45 |
'--wpbc_form-button-primary-border-style', |
| 46 |
'--wpbc_form-button-text-color', |
| 47 |
'--wpbc_form-button-hover-background-color', |
| 48 |
'--wpbc_form-button-hover-border-color', |
| 49 |
'--wpbc_form-button-hover-text-color', |
| 50 |
'--wpbc_form-button-light-background-color', |
| 51 |
'--wpbc_form-button-light-border-color', |
| 52 |
'--wpbc_form-button-light-border-style', |
| 53 |
'--wpbc_form-button-light-border-size', |
| 54 |
'--wpbc_form-button-light-text-color', |
| 55 |
'--wpbc_form-button-light-box-shadow', |
| 56 |
'--wpbc_form-button-light-hover-background-color', |
| 57 |
'--wpbc_form-button-light-hover-border-color', |
| 58 |
'--wpbc_form-button-light-hover-text-color', |
| 59 |
'--wpbc_form-button-light-hover-box-shadow', |
| 60 |
'--wpbc_form-accent-contrast-color', |
| 61 |
'--wpbc-appointment-provider-avatar-background', |
| 62 |
'--wpbc-appointment-provider-avatar-border-color', |
| 63 |
'--wpbc-appointment-provider-avatar-text-color', |
| 64 |
'--wpbc_form-button-primary-hover-border-color', |
| 65 |
); |
| 66 |
} |
| 67 |
|
| 68 |
/** |
| 69 |
* Resolve the whitelisted Appointment theme variables from global Form Style. |
| 70 |
* |
| 71 |
* @return array<string,string> Values sanitized later during CSS serialization. |
| 72 |
*/ |
| 73 |
function wpbc_booking_appointment_get_theme_css_vars() { |
| 74 |
if ( |
| 75 |
! function_exists( 'wpbc_bfb_settings__get_current_form_style' ) |
| 76 |
|| ! function_exists( 'wpbc_bfb_settings__get_form_style_css_vars' ) |
| 77 |
) { |
| 78 |
return array(); |
| 79 |
} |
| 80 |
|
| 81 |
$style = wpbc_bfb_settings__get_current_form_style(); |
| 82 |
$form_vars = wpbc_bfb_settings__get_form_style_css_vars( $style ); |
| 83 |
$allowed = array_fill_keys( wpbc_booking_appointment_get_theme_css_var_names(), true ); |
| 84 |
$theme_vars = array_intersect_key( is_array( $form_vars ) ? $form_vars : array(), $allowed ); |
| 85 |
$theme_vars = apply_filters( 'wpbc_booking_appointment_theme_css_vars', $theme_vars, $style ); |
| 86 |
|
| 87 |
return array_intersect_key( is_array( $theme_vars ) ? $theme_vars : array(), $allowed ); |
| 88 |
} |
| 89 |
|
| 90 |
/** |
| 91 |
* Sanitize one CSS custom-property value for a generated declaration. |
| 92 |
* |
| 93 |
* @param mixed $value Candidate CSS value. |
| 94 |
* |
| 95 |
* @return string Safe value or an empty string. |
| 96 |
*/ |
| 97 |
function wpbc_booking_appointment_sanitize_theme_css_value( $value ) { |
| 98 |
$value = is_scalar( $value ) ? trim( (string) $value ) : ''; |
| 99 |
if ( '' === $value ) { |
| 100 |
return ''; |
| 101 |
} |
| 102 |
|
| 103 |
$value = str_replace( |
| 104 |
array( ';', '{', '}', '"', "'", '<', '>', "\n", "\r", "\0" ), |
| 105 |
'', |
| 106 |
$value |
| 107 |
); |
| 108 |
|
| 109 |
return trim( $value ); |
| 110 |
} |
| 111 |
|
| 112 |
/** |
| 113 |
* Build the single page-level CSS rule used by Appointment theme scopes. |
| 114 |
* |
| 115 |
* @return string Safe scoped CSS, or an empty string when styles are unavailable. |
| 116 |
*/ |
| 117 |
function wpbc_booking_appointment_build_theme_css() { |
| 118 |
$declarations = ''; |
| 119 |
foreach ( wpbc_booking_appointment_get_theme_css_vars() as $name => $value ) { |
| 120 |
$value = wpbc_booking_appointment_sanitize_theme_css_value( $value ); |
| 121 |
if ( '' !== $value ) { |
| 122 |
$declarations .= $name . ':' . $value . ';'; |
| 123 |
} |
| 124 |
} |
| 125 |
|
| 126 |
if ( '' === $declarations ) { |
| 127 |
return ''; |
| 128 |
} |
| 129 |
|
| 130 |
return '.wpbc_booking_ui_theme_scope,.wpbc_booking_appointment__loading{' . $declarations . '}'; |
| 131 |
} |
| 132 |
|