$value ) { $key = sanitize_key( $key ); if ( in_array( $key, array( 'page', 'tab' ), true ) || is_array( $value ) ) { continue; } $args[ $key ] = sanitize_text_field( $value ); } $url = function_exists( 'wpbc_get_settings_themes_url' ) ? wpbc_get_settings_themes_url() : admin_url( 'admin.php?page=wpbc-settings&tab=themes' ); wp_safe_redirect( add_query_arg( $args, $url ) ); exit; } add_action( 'admin_init', 'wpbc_settings_themes__redirect_legacy_color_themes_url', 1 ); /** * Enqueue CSS for Appearance / Theme. * * @param string $where_to_load Where assets are loaded. * * @return void */ function wpbc_settings_themes_enqueue_css_files( $where_to_load ) { if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) { return; } if ( ! wpbc_settings_themes__is_page() ) { return; } wp_enqueue_style( 'wpbc-settings-themes-page', trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/settings_themes_page.css', array( 'wpbc-calendar', 'wpbc-all-admin' ), WP_BK_VERSION_NUM ); } add_action( 'wpbc_enqueue_css_files', 'wpbc_settings_themes_enqueue_css_files', 66 ); /** * Enqueue JS for Appearance / Theme. * * @param string $where_to_load Where assets are loaded. * * @return void */ function wpbc_settings_themes_enqueue_js_files( $where_to_load ) { if ( ( ! is_admin() ) || ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) ) ) { return; } if ( ! wpbc_settings_themes__is_page() ) { return; } wp_enqueue_script( 'wpbc-settings-themes-page', trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/settings_themes_page.js', array( 'jquery', 'wpbc_all' ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) ); wp_localize_script( 'wpbc-settings-themes-page', 'wpbc_settings_themes_page', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'plugin_url' => trailingslashit( WPBC_PLUGIN_URL ), 'nonce' => wp_create_nonce( 'wpbc_settings_themes_ajax_nonce' ), 'action' => 'WPBC_AJX_SETTINGS_THEMES_SAVE', 'preview_action' => 'WPBC_AJX_SETTINGS_THEMES_PREVIEW', 'settings' => wpbc_settings_themes__get_settings_response(), 'days_selection' => wpbc_settings_themes__get_days_selection_response(), 'i18n' => array( 'saving' => __( 'Saving', 'booking' ), 'saved' => __( 'Appearance settings updated.', 'booking' ), 'save_failed' => __( 'Unable to save appearance settings.', 'booking' ), 'preview_failed' => __( 'Unable to refresh calendar preview.', 'booking' ), 'security_error' => __( 'Security check failed.', 'booking' ), 'loading' => __( 'Loading', 'booking' ), 'calendar_only_theme_notice' => __( 'Preview is set to Calendar only. A matching calendar skin was selected automatically; switch Preview to Booking form to inspect the form theme.', 'booking' ), 'form_preview_option_notice' => __( 'This option is visible in the Booking form preview. Switch Preview to Booking form to inspect it.', 'booking' ), ), ) ); } add_action( 'wpbc_enqueue_js_files', 'wpbc_settings_themes_enqueue_js_files', 66 ); /** * Print tooltip initializer for Appearance / Theme. * * @return void */ function wpbc_settings_themes_print_tooltip_js() { if ( ! wpbc_settings_themes__is_page() ) { return; } if ( function_exists( 'wpbc_bs_javascript_tooltips' ) ) { wpbc_bs_javascript_tooltips(); } } add_action( 'admin_footer', 'wpbc_settings_themes_print_tooltip_js', 67 ); /** * Get day-selection settings in the same normalized shape used by calendar boot code. * * @return array */ function wpbc_settings_themes__get_days_selection_response() { $days_selection = array( 'days_select_mode' => 'multiple', 'fixed__days_num' => 0, 'fixed__week_days__start' => '-1', 'dynamic__days_min' => 0, 'dynamic__days_max' => 0, 'dynamic__days_specific' => '', 'dynamic__week_days__start' => '-1', ); if ( function_exists( 'wpbc__calendar__js_params__get_days_selection_arr' ) ) { $days_selection = wp_parse_args( wpbc__calendar__js_params__get_days_selection_arr(), $days_selection ); } return array( 'days_select_mode' => (string) $days_selection['days_select_mode'], 'fixed__days_num' => (int) $days_selection['fixed__days_num'], 'fixed__week_days__start' => (string) $days_selection['fixed__week_days__start'], 'dynamic__days_min' => (int) $days_selection['dynamic__days_min'], 'dynamic__days_max' => (int) $days_selection['dynamic__days_max'], 'dynamic__days_specific' => (string) $days_selection['dynamic__days_specific'], 'dynamic__week_days__start' => (string) $days_selection['dynamic__week_days__start'], ); } /** * Get resource options. * * @return array */ function wpbc_settings_themes__get_resources() { if ( function_exists( 'wpbc_availability_general__get_resources' ) ) { return wpbc_availability_general__get_resources(); } $resources = array(); if ( function_exists( 'wpbc_ajx_get_sorted_booking_resources_arr' ) && function_exists( 'wpbc_ajx_get_all_booking_resources_arr' ) ) { $resource_rows = wpbc_ajx_get_sorted_booking_resources_arr( wpbc_ajx_get_all_booking_resources_arr() ); foreach ( $resource_rows as $resource ) { $resources[] = array( 'id' => isset( $resource['booking_type_id'] ) ? (int) $resource['booking_type_id'] : 1, 'title' => isset( $resource['title'] ) ? $resource['title'] : __( 'Booking resource', 'booking' ), ); } } if ( empty( $resources ) ) { $resources[] = array( 'id' => function_exists( 'wpbc_get_default_resource' ) ? (int) wpbc_get_default_resource() : 1, 'title' => __( 'Booking resource', 'booking' ), ); } return $resources; } /** * Get capability required to manage Appearance / Theme. * * @return string */ function wpbc_settings_themes__get_manage_cap() { $min_user_role = get_bk_option( 'booking_user_role_settings' ); $capability = array( 'administrator' => 'activate_plugins', 'editor' => 'publish_pages', 'author' => 'publish_posts', 'contributor' => 'edit_posts', 'subscriber' => 'read', ); return isset( $capability[ $min_user_role ] ) ? $capability[ $min_user_role ] : 'manage_options'; } /** * Check if a Theme Settings upsell row is visible for current user. * * @param string $dismiss_id Dismiss ID. * * @return bool */ function wpbc_settings_themes__is_dismissed_visible( $dismiss_id ) { if ( wpbc_is_this_demo() ) { return true; } return ! function_exists( 'wpbc_is_dismissed_panel_visible' ) || wpbc_is_dismissed_panel_visible( $dismiss_id ); } /** * Get dismiss ID for Theme Settings premium option. * * @param string $option_name Option name. * * @return string */ function wpbc_settings_themes__get_premium_option_dismiss_id( $option_name ) { return 'wpbc_is_dismissed__theme_settings__' . sanitize_key( $option_name ); } /** * Render compact dismiss button for Theme Settings premium hints. * * @param string $dismiss_id Dismiss ID. * * @return void */ function wpbc_settings_themes__render_dismiss_button( $dismiss_id ) { if ( wpbc_is_this_demo() || ! function_exists( 'wpbc_is_dismissed' ) ) { return; } ?> '×', 'hint' => __( 'Hide this option', 'booking' ), 'css' => 'float:none;margin-left:4px;', ) ); ?> __( 'Calendar only', 'booking' ), 'form' => __( 'Booking form', 'booking' ), ); } /** * Sanitize preview mode. * * @param string $preview_mode Preview mode. * * @return string */ function wpbc_settings_themes__sanitize_preview_mode( $preview_mode ) { $preview_mode = sanitize_key( (string) $preview_mode ); return array_key_exists( $preview_mode, wpbc_settings_themes__get_preview_mode_options() ) ? $preview_mode : 'calendar'; } /** * Get preview mode from request. * * @return string */ function wpbc_settings_themes__get_preview_mode() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $preview_mode = isset( $_REQUEST['preview_mode'] ) ? sanitize_key( wp_unslash( $_REQUEST['preview_mode'] ) ) : 'calendar'; return wpbc_settings_themes__sanitize_preview_mode( $preview_mode ); } /** * Get booking form options for preview. * * @return array */ function wpbc_settings_themes__get_booking_form_options() { $form_options = array( 'standard' => __( 'Standard booking form', 'booking' ), ); if ( class_exists( 'WPBC_FE_Custom_Form_Helper' ) ) { $owner_user_id = method_exists( 'WPBC_FE_Custom_Form_Helper', 'wpbc_mu__get_current__owner_user_id' ) ? WPBC_FE_Custom_Form_Helper::wpbc_mu__get_current__owner_user_id() : 0; $forms_list = WPBC_FE_Custom_Form_Helper::get_custom_booking_forms_list( array( 'include_standard' => true, 'owner_user_id' => $owner_user_id, 'statuses' => array( 'published' ), 'list_mode' => 'auto', ) ); if ( is_array( $forms_list ) ) { foreach ( $forms_list as $form_slug => $form_data ) { $form_slug = sanitize_text_field( (string) $form_slug ); if ( '' === $form_slug ) { continue; } $form_options[ $form_slug ] = isset( $form_data['title'] ) ? sanitize_text_field( (string) $form_data['title'] ) : $form_slug; } } } return $form_options; } /** * Sanitize custom booking form. * * @param string $custom_booking_form Custom booking form slug. * * @return string */ function wpbc_settings_themes__sanitize_custom_booking_form( $custom_booking_form ) { $custom_booking_form = sanitize_text_field( (string) $custom_booking_form ); $form_options = wpbc_settings_themes__get_booking_form_options(); return array_key_exists( $custom_booking_form, $form_options ) ? $custom_booking_form : 'standard'; } /** * Get custom booking form from request. * * @return string */ function wpbc_settings_themes__get_custom_booking_form() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $custom_booking_form = isset( $_REQUEST['custom_booking_form'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['custom_booking_form'] ) ) : 'standard'; return wpbc_settings_themes__sanitize_custom_booking_form( $custom_booking_form ); } /** * Get form theme options. * * @return array */ function wpbc_settings_themes__get_form_theme_options() { return array( '' => __( 'Light', 'booking' ), 'wpbc_theme_dark_1' => __( 'Dark', 'booking' ), ); } /** * Get time picker skin options. * * @return array */ function wpbc_settings_themes__get_time_picker_skin_options() { $timeslot_picker_skins_options = array(); $upload_dir = wp_upload_dir(); if ( function_exists( 'wpbc_dir_list' ) ) { $files_in_folder = wpbc_dir_list( array( WPBC_PLUGIN_DIR . '/css/time_picker_skins/', $upload_dir['basedir'] . '/wpbc_time_picker_skins/', ) ); foreach ( $files_in_folder as $skin_file ) { $skin_file[1] = str_replace( array( WPBC_PLUGIN_DIR, WPBC_PLUGIN_URL, $upload_dir['basedir'] ), '', $skin_file[1] ); $timeslot_picker_skins_options[ $skin_file[1] ] = $skin_file[2]; } } if ( empty( $timeslot_picker_skins_options ) ) { $default_options_values = wpbc_get_default_options(); $default_skin = isset( $default_options_values['booking_timeslot_picker_skin'] ) ? $default_options_values['booking_timeslot_picker_skin'] : '/css/time_picker_skins/grey.css'; $timeslot_picker_skins_options[ $default_skin ] = __( 'Default', 'booking' ); } return $timeslot_picker_skins_options; } /** * Normalize calendar skin option value to a relative path. * * @param string $skin_value Calendar skin value. * * @return string */ function wpbc_settings_themes__normalize_calendar_skin_value( $skin_value ) { $skin_value = (string) $skin_value; $upload_dir = wp_upload_dir(); $upload_url = ( ! empty( $upload_dir['baseurl'] ) ) ? $upload_dir['baseurl'] : ''; return str_replace( array( WPBC_PLUGIN_URL, $upload_url, ), '', $skin_value ); } /** * Get URL for a relative calendar skin path. * * @param string $relative_skin Relative skin path. * * @return string */ function wpbc_settings_themes__get_calendar_skin_url( $relative_skin ) { $relative_skin = wpbc_settings_themes__normalize_calendar_skin_value( $relative_skin ); $upload_dir = wp_upload_dir(); $upload_url = ( ! empty( $upload_dir['baseurl'] ) ) ? $upload_dir['baseurl'] : ''; if ( 0 === strpos( $relative_skin, '/wpbc_skins/' ) && ! empty( $upload_url ) ) { return $upload_url . $relative_skin; } return WPBC_PLUGIN_URL . $relative_skin; } /** * Build calendar skin options for selectbox with live-preview URL metadata. * * @return array */ function wpbc_settings_themes__get_calendar_skin_options_for_select() { $options = function_exists( 'wpbc_get_calendar_skin_options' ) ? wpbc_get_calendar_skin_options() : array(); foreach ( $options as $option_value => $option_label ) { if ( is_array( $option_label ) && ! empty( $option_label['optgroup'] ) ) { continue; } $relative_skin = wpbc_settings_themes__normalize_calendar_skin_value( $option_value ); $skin_url = wpbc_settings_themes__get_calendar_skin_url( $relative_skin ); if ( is_array( $option_label ) ) { $option_label['attr'] = ( isset( $option_label['attr'] ) && is_array( $option_label['attr'] ) ) ? $option_label['attr'] : array(); $option_label['attr']['data-wpbc-calendar-skin-url'] = $skin_url; $options[ $relative_skin ] = $option_label; } else { $options[ $relative_skin ] = array( 'title' => $option_label, 'attr' => array( 'data-wpbc-calendar-skin-url' => $skin_url, ), ); } if ( $relative_skin !== $option_value ) { unset( $options[ $option_value ] ); } } return $options; } /** * Get current settings prepared for JavaScript and AJAX responses. * * @return array */ function wpbc_settings_themes__get_settings_response() { return array( 'booking_form_theme' => get_bk_option( 'booking_form_theme' ), 'booking_skin' => wpbc_settings_themes__normalize_calendar_skin_value( get_bk_option( 'booking_skin' ) ), 'booking_timeslot_picker_skin' => get_bk_option( 'booking_timeslot_picker_skin' ), 'booking_timeslot_picker' => get_bk_option( 'booking_timeslot_picker' ), ); } /** * Override option values while rendering the live Appearance / Theme preview. * * @param mixed $value Current filter value. * @param string $option Option name. * @param mixed $default Default option value. * * @return mixed */ function wpbc_settings_themes__preview_get_bk_option( $value, $option, $default ) { global $wpbc_settings_themes__preview_options; if ( is_array( $wpbc_settings_themes__preview_options ) && array_key_exists( $option, $wpbc_settings_themes__preview_options ) ) { return $wpbc_settings_themes__preview_options[ $option ]; } return $value; } add_bk_filter( 'wpdev_bk_get_option', 'wpbc_settings_themes__preview_get_bk_option' ); /** * Prepare option overrides for the live preview renderer. * * @param array $current_settings Current preview settings. * * @return array */ function wpbc_settings_themes__get_preview_option_overrides( $current_settings ) { $option_names = array( 'booking_form_theme', 'booking_skin', 'booking_timeslot_picker_skin', 'booking_timeslot_picker', ); $overrides = array(); foreach ( $option_names as $option_name ) { if ( array_key_exists( $option_name, $current_settings ) ) { $overrides[ $option_name ] = $current_settings[ $option_name ]; } } return $overrides; } /** * Validate posted Appearance / Theme settings. * * @param array $post_data Raw post data. * * @return array */ function wpbc_settings_themes__validate_data( $post_data ) { $default_options_values = wpbc_get_default_options(); $form_theme_options = wpbc_settings_themes__get_form_theme_options(); $calendar_skin_options = wpbc_settings_themes__get_calendar_skin_options_for_select(); $time_skin_options = wpbc_settings_themes__get_time_picker_skin_options(); $cleaned = array( 'booking_form_theme' => isset( $default_options_values['booking_form_theme'] ) ? $default_options_values['booking_form_theme'] : '', 'booking_skin' => isset( $default_options_values['booking_skin'] ) ? $default_options_values['booking_skin'] : '', 'booking_timeslot_picker_skin' => isset( $default_options_values['booking_timeslot_picker_skin'] ) ? $default_options_values['booking_timeslot_picker_skin'] : '', 'booking_timeslot_picker' => isset( $default_options_values['booking_timeslot_picker'] ) ? $default_options_values['booking_timeslot_picker'] : 'Off', ); if ( isset( $post_data['booking_form_theme'] ) ) { $value = sanitize_text_field( wp_unslash( $post_data['booking_form_theme'] ) ); if ( array_key_exists( $value, $form_theme_options ) ) { $cleaned['booking_form_theme'] = $value; } } if ( isset( $post_data['booking_skin'] ) ) { $value = wpbc_settings_themes__normalize_calendar_skin_value( sanitize_text_field( wp_unslash( $post_data['booking_skin'] ) ) ); if ( array_key_exists( $value, $calendar_skin_options ) ) { $cleaned['booking_skin'] = $value; } } if ( isset( $post_data['booking_timeslot_picker_skin'] ) ) { $value = sanitize_text_field( wp_unslash( $post_data['booking_timeslot_picker_skin'] ) ); if ( array_key_exists( $value, $time_skin_options ) ) { $cleaned['booking_timeslot_picker_skin'] = $value; } } $timeslot_picker_value = isset( $post_data['booking_timeslot_picker'] ) ? sanitize_text_field( wp_unslash( $post_data['booking_timeslot_picker'] ) ) : ''; $cleaned['booking_timeslot_picker'] = ( 'On' === $timeslot_picker_value ) ? 'On' : 'Off'; return $cleaned; } /** * Update Appearance / Theme settings. * * @param array $cleaned_data Cleaned settings. * * @return void */ function wpbc_settings_themes__update_settings( $cleaned_data ) { update_bk_option( 'booking_form_theme', $cleaned_data['booking_form_theme'] ); update_bk_option( 'booking_skin', $cleaned_data['booking_skin'] ); update_bk_option( 'booking_timeslot_picker_skin', $cleaned_data['booking_timeslot_picker_skin'] ); update_bk_option( 'booking_timeslot_picker', $cleaned_data['booking_timeslot_picker'] ); } /** * Render select field. * * @param string $name Field name. * @param array $options Options. * @param string $selected Selected value. * @param array $args Extra args. * * @return void */ function wpbc_settings_themes__render_select( $name, $options, $selected, $args = array() ) { $args = wp_parse_args( $args, array( 'id' => $name, 'class' => '', 'data_attrs' => array(), ) ); $data_attrs = ''; foreach ( $args['data_attrs'] as $attr_name => $attr_value ) { $data_attrs .= ' ' . esc_attr( $attr_name ) . '="' . esc_attr( $attr_value ) . '"'; } ?>