Linux hkvL61zh9Vexzf 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 Path : /www/wwwroot/fashion-kingdom.com/wp-content/plugins/kitify/inc/framework/customizer/ |
Current File : /www/wwwroot/fashion-kingdom.com/wp-content/plugins/kitify/inc/framework/customizer/customizer.php |
<?php /** * Module to work with standard WordPress customizer * * Version: 1.0.3 */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } if ( ! class_exists( 'CX_Customizer' ) ) { /** * Contains methods for customizing the theme customization screen. * * @since 1.0.0 */ class CX_Customizer { /** * Unique prefix. * This is a theme or plugin slug. * * @since 1.0.0 * @access protected * @var string */ protected $prefix; /** * Capability. * * @since 1.0.0 * @access protected * @var string */ protected $capability; /** * Setting type. * * @since 1.0.0 * @access protected * @var string */ protected $type; /** * Options. * * @since 1.0.0 * @access protected * @var array */ protected $options; /** * Path to module folder. * * @since 1.0.0 * @access protected * @var object */ protected $path; /** * WP_Customize_Manager instance. * * @since 1.0.0 * @access protected * @var object. */ protected $customize; /** * Module directory URI. * * @since 1.0.0 * @access protected * @var array. */ protected $fonts; /** * Fonts manager instance * * @var object */ protected $fonts_manager = null; /** * Fonts options list * * @var array */ protected $fonts_options = array(); /** * Module initialization. * * @since 1.0.0 * @param array $args Arguments. */ /* * $args = array( * 'just_fonts' => false, // set to TRUE if you want use customizer only as fonts manager. * 'prefix' => 'unique_prefix', // theme or plugin slug (*). * 'capability' => 'edit_theme_options', // (default: `edit_theme_options`). * 'type' => 'theme_mod', // `theme_mod` - for themes; `option` - for plugins (default: `theme_mod`) * 'options' => array( * 'unique_panel_ID' => array( * 'title' => esc_html__( 'Panel Title', 'text-domain' ), * 'description' => esc_html__( 'Panel Description', 'text-domain' ), * 'priority' => 140, * 'capability' => '', (optional) * 'theme_supports' => '', (optional) * 'active_callback' => '', // (optional: is_front_page, is_single) * 'type' => 'panel', // panel, section or control (*). * ), * 'unique_section_ID' => array( * 'title' => esc_html__( 'Section Title', 'text-domain' ), * 'description' => esc_html__( 'Section Description', 'text-domain' ), * 'priority' => 10, (10, 20, 30, ...) * 'panel' => 'unique_panel_ID', (*) * 'type' => 'section', (*) * ), * 'unique_control_ID' => array( * 'title' => esc_html__( 'Control Title', 'text-domain' ), * 'description' => esc_html__( 'Control Description', 'text-domain' ), * 'section' => 'unique_section_ID', (*) * 'default' => '', * 'field' => 'text', // text, textarea, checkbox, radio, select, * // iconpicker, fonts, hex_color, image, file. * 'choices' => array(), // for `select` and `radio` field. * 'type' => 'control', (*) * 'active_callback' => '', (optional: is_front_page, is_single) * 'transport' => 'refresh', // refresh or postMessage (default: refresh) * 'sanitize_callback' => '', (optional) Maybe need to use a custom function or sanitization. * 'sanitize_js_callback' => '', (optional) * ), * ) * ); */ /** * Cherry customizer class construct. */ public function __construct( array $args = array() ) { /** * Cherry Customizer only works in WordPress 4.0 or later. */ if ( version_compare( $GLOBALS['wp_version'], '4.0', '<' ) ) { return; } $this->path = isset( $args['path'] ) ? $args['path'] : false; $this->fonts_manager = isset( $args['fonts_manager'] ) ? $args['fonts_manager'] : false; $this->fonts = array(); $this->prefix = $this->prepare_prefix( $args['prefix'] ); $this->options = $args['options']; $this->capability = ! empty( $args['capability'] ) ? $args['capability'] : 'edit_theme_options'; $this->type = ! empty( $args['type'] ) && $this->sanitize_type( $args['type'] ) ? $args['type'] : 'theme_mod'; // Prepare options after theme activation. add_action( 'after_switch_theme', array( $this, 'add_options' ), 11 ); if ( ! empty( $this->fonts_manager ) ) { $this->init_fonts_manager(); } /** * Fonts are loaded, abort if $args['just_fonts'] set to TRUE */ if ( isset( $args['just_fonts'] ) && true === $args['just_fonts'] ) { return; } $this->type = ! empty( $args['type'] ) && $this->sanitize_type( $args['type'] ) ? $args['type'] : 'theme_mod'; if ( empty( $args['options'] ) || ( ( 'option' === $this->type ) && empty( $args['prefix'] ) ) ) { return; } add_action( 'customize_register', array( $this, 'register' ) ); add_filter( 'customize_previewable_devices', array( $this, 'custom_devices' ) ); add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); add_action( 'wp_head', array( $this, 'auto_enqueue_frontend_css' ), 999 ); } public function customize_preview_init(){ $theme_version = defined('WP_DEBUG') && WP_DEBUG ? time() : kitify()->get_version(); $dependency = array( 'jquery', 'customize-preview', ); wp_enqueue_script( 'kitify-customize-preview', kitify()->plugin_url('assets/js/nova-customizer-preview.js') , $dependency, $theme_version, true ); wp_localize_script('kitify-customize-preview', 'kitifyCustomizeConfigs', $this->get_controls_with_css()); } public function get_controls_with_css(){ $controls = []; if ( empty( $this->options ) ) { return $controls; } foreach ( (array) $this->options as $id => $option ) { if ( empty( $option['type'] ) ) { continue; } if ( 'control' === $option['type'] && !empty($option['css']) && empty($option['responsive']) ) { $controls[$id] = $option['css']; } } return $controls; } public function auto_enqueue_frontend_css(){ $cssRules = [ 'desktop' => '', 'laptop' => '', 'tablet' => '', 'mobile_extra' => '', 'mobile' => '' ]; if ( empty( $this->options ) ) { return; } $responsive_controls = []; foreach ( (array) $this->options as $id => $option ) { if ( empty( $option['type'] ) ) { continue; } if ( 'control' === $option['type'] && !empty($option['css']) ) { $value = $this->get_value($id); if($option['field'] == 'fonts'){ $value = $this->render_font_value($value); } if(!empty($value)){ foreach ( $option['css'] as $item ){ $cssRules['desktop'] .= sprintf('%1$s{%2$s:%3$s}', $item['selector'], $item['property'], $value ); } } if( $option['field'] === 'kitify_responsive' && $option['responsive'] ) { $responsive_controls[$id] = $option['css']; } } } $device_list = [ 'laptop', 'tablet', 'mobile_extra', 'mobile' ]; if(!empty($responsive_controls)){ foreach ($responsive_controls as $control => $css){ foreach ( $device_list as $device ) { $res_cval = $this->get_value($control . '_' . $device ); if(!empty($res_cval)){ foreach ($css as $item){ $cssRules[$device] .= sprintf('%1$s{%2$s:%3$s}', $item['selector'], $item['property'], $res_cval ); } } } } } $css_render = ''; foreach ($cssRules as $device => $val){ if(empty($val)){ continue; } if ( $device == 'laptop' ){ $css_render .= '@media(max-width: 1599px){'. $val .'}'; } elseif ( $device == 'tablet' ){ $css_render .= '@media(max-width: 1279px){'. $val .'}'; } elseif ( $device == 'mobile_extra' ){ $css_render .= '@media(max-width: 991px){'. $val .'}'; } elseif ( $device == 'mobile' ){ $css_render .= '@media(max-width: 767px){'. $val .'}'; } else{ $css_render .= $val; } } if(!empty($css_render)){ echo sprintf('<style id="kitifycustomizer-css-style">%1$s</style>', $css_render); } } public function render_font_value( $value ){ if(!empty($value)){ $tmp = explode(',', $value); if(strpos($tmp[0], ' ') !== false){ $tmp[0] = '"' . $tmp[0] . '"'; $value = join(',', $tmp); } } return $value; } /** * Initialize fonts manager if its instance was passed in arguments. * * @return void */ public function init_fonts_manager() { $this->fonts_manager->set_args( array( 'prefix' => $this->prefix, 'single' => false, 'type' => $this->type, 'get_fonts' => array( $this, 'get_fonts' ), 'options' => $this->get_fonts_options() ) ); } /** * Return fonts options list * * @return array */ public function get_fonts_options() { array_walk( $this->options, array( $this, '_get_fonts_options' ) ); return $this->fonts_options; } /** * Callback for fonts options grabber walker. * * @param array $item Option data. * @param string $key Option key. * @return [type] [description] */ public function _get_fonts_options( $item, $key ) { if ( ! isset( $item['field'] ) || 'fonts' !== $item['field'] ) { return; } $pairs = array( 'style' => '_font_style', 'weight' => '_font_weight', 'charset' => '_character_set', ); $opt_key = str_replace( '_font_family', '', $key ); $data = array( 'family' => $key ); foreach ( $pairs as $prop => $mod ) { $data[ $prop ] = $opt_key . $mod; } $this->fonts_options[ $opt_key ] = $data; } /** * Registeration for a new panel, sections, settings and controls. * * @since 1.0.0 * @param object $wp_customize WP_Customize_Manager instance. */ public function register( $wp_customize ) { // Failsafe is safe. if ( ! isset( $wp_customize ) ) { return; } $this->set_customize( $wp_customize ); foreach ( (array) $this->options as $id => $option ) { if ( empty( $option['type'] ) ) { continue; } if ( 'panel' === $option['type'] ) { $this->add_panel( $id, $option ); } if ( 'section' === $option['type'] ) { $this->add_section( $id, $option ); } if ( 'control' === $option['type'] ) { $this->add_control( $id, $option ); } } } /** * Add a customize panel. * * @since 1.0.0 * @param number $id Settings ID. * @param array $args Panel arguments. */ public function add_panel( $id, $args ) { $prefix = $this->prefix . '_'; $priority = isset( $args['priority'] ) ? $args['priority'] : 160; $theme_supports = isset( $args['theme_supports'] ) ? $args['theme_supports'] : ''; $title = isset( $args['title'] ) ? esc_attr( $args['title'] ) : ''; $description = isset( $args['description'] ) ? esc_attr( $args['description'] ) : ''; $active_callback = isset( $args['active_callback'] ) ? $this->active_callback( $args['active_callback'] ) : ''; $this->customize->add_panel( $prefix . esc_attr( $id ), array( 'priority' => $priority, 'capability' => $this->capability, 'theme_supports' => $theme_supports, 'title' => $title, 'description' => $description, 'active_callback' => $active_callback, ) ); } /** * Add a customize section. * * @since 1.0.0 * @param array $id Settings ID. * @param array $args Section arguments. */ /** * The priorities of the core sections are below: * * Title ID Priority (Order) * Site Title & Tagline title_tagline 20 * Colors colors 40 * Header Image header_image 60 * Background Image background_image 80 * Navigation nav 100 * Widgets (Panel) widgets 110 * Static Front Page static_front_page 120 */ public function add_section( $id, $args ) { $prefix = $this->prefix . '_'; $title = isset( $args['title'] ) ? esc_attr( $args['title'] ) : ''; $description = isset( $args['description'] ) ? esc_attr( $args['description'] ) : ''; $panel = isset( $args['panel'] ) ? $prefix . esc_attr( $args['panel'] ) : ''; $priority = isset( $args['priority'] ) ? $args['priority'] : 160; $theme_supports = isset( $args['theme_supports'] ) ? $args['theme_supports'] : ''; $active_callback = isset( $args['active_callback'] ) ? $this->active_callback( $args['active_callback'] ) : ''; $this->customize->add_section( $prefix . esc_attr( $id ), array( 'title' => $title, 'description' => $description, 'panel' => $panel, 'priority' => $priority, 'capability' => $this->capability, 'theme_supports' => $theme_supports, 'active_callback' => $active_callback, ) ); } /** * Add a customize control. * * @since 1.0.0 * @since 1.0.2 Added a `cropped_image` support. * @param number $id Settings ID. * @param array $args Control arguments. */ public function add_control( $id, $args ) { static $control_priority = 0; $prefix = $this->prefix . '_'; $section = $this->get_control_section( $args ); $id = ( 'option' === $this->type ) ? sprintf( '%1$s_options[%2$s]', $this->prefix, esc_attr( $id ) ) : esc_attr( $id ); $priority = isset( $args['priority'] ) ? $args['priority'] : ++$control_priority; $default = isset( $args['default'] ) ? $args['default'] : ''; $title = isset( $args['title'] ) ? esc_attr( $args['title'] ) : ''; $description = isset( $args['description'] ) ? esc_attr( $args['description'] ) : ''; $transport = isset( $args['transport'] ) ? esc_attr( $args['transport'] ) : 'refresh'; $field_type = isset( $args['field'] ) ? esc_attr( $args['field'] ) : 'text'; $sanitize_callback = isset( $args['sanitize_callback'] ) ? esc_attr( $args['sanitize_callback'] ) : array( $this, 'sanitize_' . $field_type ); $sanitize_callback = is_callable( $sanitize_callback ) ? $sanitize_callback : 'sanitize_text_field'; $sanitize_js_callback = isset( $args['sanitize_js_callback'] ) ? esc_attr( $args['sanitize_js_callback'] ) : ''; $active_callback = isset( $args['active_callback'] ) ? $this->active_callback( $args['active_callback'] ) : ''; $args_settings = array( 'type' => $this->type, 'capability' => $this->capability, 'default' => $default, 'transport' => $transport, 'sanitize_callback' => $sanitize_callback, 'sanitize_js_callback' => $sanitize_js_callback, ); // Add a customize setting. $this->customize->add_setting( $id, $args_settings ); // Prepare arguments for a customize control. $control_args = array( 'priority' => $priority, 'section' => $section, 'label' => $title, 'description' => $description, 'active_callback' => $active_callback, 'choices' => '', // select, radio ); $control_class = ''; if ( isset( $args['responsive'] ) && $args['responsive'] ) { $settings_laptop = $args_settings; $settings_laptop['default'] = isset( $settings_laptop['default_laptop'] ) ? $settings_laptop['default_laptop'] : $settings_laptop['default']; $this->customize->add_setting( $id . '_laptop', $settings_laptop ); $settings_tablet_ext = $args_settings; $settings_tablet_ext['default'] = isset( $settings_tablet_ext['default_tablet_extra'] ) ? $settings_tablet_ext['default_tablet_extra'] : $settings_tablet_ext['default']; $this->customize->add_setting( $id . '_tablet_extra', $settings_tablet_ext ); $settings_tablet = $args_settings; $settings_tablet['default'] = isset( $settings_tablet['default_tablet'] ) ? $settings_tablet['default_tablet'] : $settings_tablet['default']; $this->customize->add_setting( $id . '_tablet', $settings_tablet ); $settings_ml = $args_settings; $settings_ml['default'] = isset( $settings_ml['default_mobile_extra'] ) ? $settings_ml['default_mobile_extra'] : $settings_ml['default']; $this->customize->add_setting( $id . '_mobile_extra', $settings_ml ); $settings_mobile = $args_settings; $settings_mobile['default'] = isset( $settings_mobile['default_mobile'] ) ? $settings_mobile['default_mobile'] : $settings_mobile['default']; $this->customize->add_setting( $id . '_mobile', $settings_mobile ); $control_args['responsive'] = true; $control_args['settings'] = array( 'default' => $id, 'desktop' => $id, 'laptop' => $id . '_laptop', 'tablet' => $id . '_tablet_extra', 'tablet' => $id . '_tablet', 'mobile_extra' => $id . '_mobile_extra', 'mobile' => $id . '_mobile', ); } if( !empty($args['css']) ){ $control_args['css'] = $args['css']; } switch ( $field_type ) { case 'text': case 'textarea': case 'email': case 'url': case 'password': case 'checkbox': case 'dropdown-pages': $control_args = wp_parse_args( array( 'type' => $field_type, ), $control_args ); break; case 'range': case 'number': $input_attrs = ( isset( $args['input_attrs'] ) ) ? $args['input_attrs'] : array(); $control_args = wp_parse_args( array( 'type' => $field_type, 'input_attrs' => $input_attrs, ), $control_args ); break; case 'select': $choices = ( isset( $args['choices'] ) ) ? $args['choices'] : array(); $control_args = wp_parse_args( array( 'type' => 'select', 'choices' => $choices, ), $control_args ); break; case 'fonts': $choices = ( isset( $args['choices'] ) ) ? $args['choices'] : $this->get_fonts(); $control_args = wp_parse_args( array( 'type' => 'select', 'choices' => $choices, ), $control_args ); break; case 'radio': $choices = ( isset( $args['choices'] ) ) ? $args['choices'] : array(); $control_args = wp_parse_args( array( 'type' => 'radio', 'choices' => $choices, ), $control_args ); break; case 'hex_color': $control_class = 'WP_Customize_Color_Control'; break; case 'image': $control_class = 'WP_Customize_Image_Control'; if(isset($args['button_labels'])){ $control_args['button_labels'] = $args['button_labels']; } break; case 'file': $control_class = 'WP_Customize_Upload_Control'; if(isset($args['button_labels'])){ $control_args['button_labels'] = $args['button_labels']; } break; case 'cropped_image': $control_class = 'WP_Customize_Cropped_Image_Control'; $cropped_args = ( isset( $args['cropped_args'] ) ) ? $args['cropped_args'] : array(); $control_args = wp_parse_args( array( 'width' => ( isset( $cropped_args['width'] ) ) ? esc_attr( $cropped_args['width'] ) : 150, 'height' => ( isset( $cropped_args['height'] ) ) ? esc_attr( $cropped_args['height'] ) : 150, 'flex-width' => ( isset( $cropped_args['flex-width'] ) ) ? $cropped_args['flex-width'] : false, 'flex-height' => ( isset( $cropped_args['flex-height'] ) ) ? $cropped_args['flex-height'] : false, 'button_labels' => ( isset( $cropped_args['labels'] ) ) ? $cropped_args['labels'] : array(), ), $control_args ); if(isset($args['button_labels'])){ $control_args['button_labels'] = $args['button_labels']; } break; case 'kitify_responsive': $control_class = 'CX_Customizer_Responsive_control'; break; case 'checkbox-multiple': $control_class = 'CX_Customizer_Checkbox_Multiple_control'; $choices = ( isset( $args['choices'] ) ) ? $args['choices'] : array(); $control_args['choices'] = $choices; break; default: /** * Filter arguments for a `$field_type` customize control. * * @since 1.0.0 * @param array $control_args Control's arguments. * @param string $id Control's ID. * @param object $this Cherry_Customizer instance. */ $control_args = apply_filters( 'kitify/theme/customizer/control_args/{$field_type}', $control_args, $id, $this ); break; } /** * Filter arguments for a customize control. * * @since 1.0.0 * @param array $control_args Control's arguments. * @param string $id Control's ID. * @param object $this Cherry_Customizer instance. */ $control_args = apply_filters( 'kitify/theme/customizer/control_args', $control_args, $id, $this ); /** * Filter PHP-class name for a customize control (maybe custom). * * @since 1.0.0 * @param array $control_args Control's PHP-class name. * @param string $id Control's ID. * @param object $this Cherry_Customizer instance. */ $control_class = apply_filters( 'kitify/theme/customizer/control_class', $control_class, $id, $this ); if ( class_exists( $control_class ) ) { $this->customize->add_control( new $control_class( $this->customize, $id, $control_args ) ); } else { $this->customize->add_control( $id, $control_args ); } } /** * Get section name from arguments - prefixed, if is custom section, unprefixed - if is core section. * * @since 1.0.0 * @param array $args Control arguments. * @return string */ public function get_control_section( $args ) { if ( ! isset( $args['section'] ) ) { return ''; } $default_sections = apply_filters( 'kitify/theme/customizer/core_sections', array( 'title_tagline', 'colors', 'header_image', 'background_image', 'nav', 'widgets', 'static_front_page', ) ); if ( in_array( esc_attr( $args['section'] ), $default_sections ) ) { return esc_attr( $args['section'] ); } return $this->prefix . '_' . esc_attr( $args['section'] ); } /** * Retrieve a prefix. * * @since 1.0.0 * @return string */ public function prepare_prefix( $prefix ) { $prefix = preg_replace( '/\W/', '-', strtolower( $prefix ) ); $prefix = sanitize_key( $prefix ); return $prefix; } /** * Save WP_Customize_Manager instance to prorerty. * * @since 1.0.0 * @param object $customize WP_Customize_Manager instance. */ public function set_customize( $customize ) { $this->customize = $customize; } /** * Retrieve a option value by ID. * * @since 1.0.0 * @param mixed $id Settings ID. * @return bool|mixed */ public function get_value( $id, $default = null ) { if ( null === $default ) { $default = $this->get_default( $id ); } if ( 'theme_mod' === $this->type ) { return get_theme_mod( $id, $default ); } if ( 'option' === $this->type ) { $options = get_option( $this->prefix . '_options', array() ); return isset( $options[ $id ] ) ? $options[ $id ] : $default; } return $default; } /** * Retrieve a default option value. * * @since 1.0.0 * @param [string] $id Settings ID. * @return mixed */ public function get_default( $id ) { return isset( $this->options[ $id ]['default'] ) ? $this->options[ $id ]['default'] : null; } /** * Whitelist for setting type. * * @since 1.0.0 * @param [string] $type Settings type. * @return bool */ public function sanitize_type( $type ) { return in_array( $type, array( 'theme_mod', 'option' ) ); } /** * Text sanitization callback. * * - Sanitization: html * - Control: text, textarea * * Sanitization callback for 'html' type text inputs. This callback sanitizes `$html` * for HTML allowable in posts. * * NOTE: wp_filter_post_kses() can be passed directly as `$wp_customize->add_setting()` * 'sanitize_callback'. It is wrapped in a callback here merely for example purposes. * * @see wp_filter_post_kses() https://developer.wordpress.org/reference/functions/wp_filter_post_kses/ * @since 1.0.0 * @param [string] $html HTML to sanitize. * @return string Sanitized HTML. */ public function sanitize_text( $html ) { return wp_filter_post_kses( $html ); } /** * Email sanitization callback. * * - Sanitization: email * - Control: text * * Sanitization callback for 'email' type text controls. This callback sanitizes `$email` * as a valid email address. * * @see sanitize_email() https://developer.wordpress.org/reference/functions/sanitize_key/ * @link sanitize_email() https://codex.wordpress.org/Function_Reference/sanitize_email * @since 1.0.0 * @param [string] $email Email address to sanitize. * @param WP_Customize_Setting $setting Setting instance. * @return string The sanitized email if not null; otherwise, the setting default. */ public function sanitize_email( $email, $setting ) { // Sanitize $input as a hex value without the hash prefix. $email = sanitize_email( $email ); // If $email is a valid email, return it; otherwise, return the default. return ( '' === $email ) ? $setting->default : $email; } /** * Textarea sanitization callback. * * @since 1.0.0 * @param [string] $html HTML to sanitize. * @return string Sanitized HTML. */ public function sanitize_textarea( $html ) { return $this->sanitize_text( $html ); } /** * Select sanitization callback. * * - Sanitization: select * - Control: select, radio * * Sanitization callback for 'select' and 'radio' type controls. This callback sanitizes `$input` * as a slug, and then validates `$input` against the choices defined for the control. * * @see sanitize_key() https://developer.wordpress.org/reference/functions/sanitize_key/ * @see $wp_customize->get_control() https://developer.wordpress.org/reference/classes/wp_customize_manager/get_control/ * @since 1.0.0 * @param [string] $input Slug to sanitize. * @param WP_Customize_Setting $setting Setting instance. * @return string Sanitized slug if it is a valid choice; otherwise, the setting default. */ public function sanitize_select( $input, $setting ) { // Ensure input is a slug. $input = sanitize_key( $input ); // Get list of choices from the control associated with the setting. $choices = $setting->manager->get_control( $setting->id )->choices; // If the input is a valid key, return it; otherwise, return the default. return ( array_key_exists( $input, $choices ) ? $input : $setting->default ); } /** * Function sanitize_radio */ public function sanitize_radio( $input, $setting ) { return $this->sanitize_select( $input, $setting ); } /** * Checkbox sanitization callback. * * Sanitization callback for 'checkbox' type controls. This callback sanitizes `$checked` * as a boolean value, either TRUE or FALSE. * * @since 1.0.0 * @param bool $checked Whether the checkbox is checked. * @return bool Whether the checkbox is checked. */ public function sanitize_checkbox( $checked ) { return ( ( isset( $checked ) && true == $checked ) ? true : false ); } /** * HEX Color sanitization callback example. * * - Sanitization: hex_color * - Control: text, WP_Customize_Color_Control * * Note: sanitize_hex_color_no_hash() can also be used here, depending on whether * or not the hash prefix should be stored/retrieved with the hex color value. * * @see sanitize_hex_color() https://developer.wordpress.org/reference/functions/sanitize_hex_color/ * @link sanitize_hex_color_no_hash() https://developer.wordpress.org/reference/functions/sanitize_hex_color_no_hash/ * @since 1.0.0 * @param [string] $hex_color HEX color to sanitize. * @param WP_Customize_Setting $setting Setting instance. * @return string The sanitized hex color if not null; otherwise, the setting default. */ public function sanitize_hex_color( $hex_color, $setting ) { // Sanitize $input as a hex value without the hash prefix. $hex_color = sanitize_hex_color( $hex_color ); // If $input is a valid hex value, return it; otherwise, return the default. return ( '' === $hex_color ) ? $setting->default : $hex_color; } /** * Image sanitization callback. * * Checks the image's file extension and mime type against a whitelist. If they're allowed, * send back the filename, otherwise, return the setting default. * * - Sanitization: image file extension * - Control: text, WP_Customize_Image_Control * * @see wp_check_filetype() https://developer.wordpress.org/reference/functions/wp_check_filetype/ * @since 1.0.0 * @param [string] $image Image filename. * @param WP_Customize_Setting $setting Setting instance. * @return string The image filename if the extension is allowed; otherwise, the setting default. */ public function sanitize_image( $image, $setting ) { // Allow to correctly remove selected image if ( empty( $image ) ) { return $image; } $mimes = $this->get_image_types(); // Return an array with file extension and mime_type. $file = wp_check_filetype( $image, $mimes ); // If $image has a valid mime_type, return it; otherwise, return the default. return ( $file['ext'] ? $image : $setting->default ); } /** * URL sanitization callback. * * - Sanitization: url * - Control: text, url * * Sanitization callback for 'url' type text inputs. This callback sanitizes `$url` as a valid URL. * * NOTE: esc_url_raw() can be passed directly as `$wp_customize->add_setting()` 'sanitize_callback'. * It is wrapped in a callback here merely for example purposes. * * @see esc_url_raw() https://developer.wordpress.org/reference/functions/esc_url_raw/ * @since 1.0.0 * @param [string] $url URL to sanitize. * @return string Sanitized URL. */ public function sanitize_url( $url ) { return esc_url_raw( $url ); } /** * File URL sanitization callback. * * @since 1.0.0 * @param [string] $url File URL to sanitize. * @return string Sanitized URL. */ public function sanitize_file( $url ) { return $this->sanitize_url( $url ); } /** * Range sanitization callback. * * - Sanitization: number_range * - Control: number, tel * * Sanitization callback for 'number' or 'tel' type text inputs. This callback sanitizes * `$number` as an absolute integer within a defined min-max range. * * @see absint() https://developer.wordpress.org/reference/functions/absint/ * @since 1.0.0 * @param int $number Number to check within the numeric range defined by the setting. * @param WP_Customize_Setting $setting Setting instance. * @return int|string The number, if it is zero or greater and falls within the defined range; * otherwise, the setting default. */ public function sanitize_range( $number, $setting ) { // Get the input attributes associated with the setting. $atts = $setting->manager->get_control( $setting->id )->input_attrs; // Get step. $step = ( isset( $atts['step'] ) ? $atts['step'] : 1 ); $number = ( ! isset( $atts['min'] ) && 0 > $number ) ? $setting->default : $number ; if ( is_float( $step ) ) { // Ensure input is a float value. $number = floatval( $number ); $checker = is_float( $number / $step ); } else { // Ensure input is an absolute integer. $number = ( isset( $atts['min'] ) && 0 > $atts['min'] && 0 > $number ) ? intval( $number ) : absint( $number ); $checker = is_int( $number / $step ); } // Get minimum number in the range. $min = ( isset( $atts['min'] ) ? $atts['min'] : $number ); // Get maximum number in the range. $max = ( isset( $atts['max'] ) ? $atts['max'] : $number ); // If the number is within the valid range, return it; otherwise, return the default return ( $min <= $number && $number <= $max && $checker ? $number : $setting->default ); } /** * Number sanitization callback. * * @since 1.0.0 * @param int $number Number to check within the numeric range defined by the setting. * @param WP_Customize_Setting $setting Setting instance. * @return int|string The number, if it is zero or greater and falls within the defined range; * otherwise, the setting default. */ public function sanitize_number( $number, $setting ) { return $this->sanitize_range( $number, $setting ); } /** * Cropped image sanitization callback. * * @since 1.0.2 * @param int $number Number to check within the numeric range defined by the setting. * @param WP_Customize_Setting $setting Setting instance. * @return int|string The number, if it is zero or greater and falls within the defined range; * otherwise, the setting default. */ public function sanitize_cropped_image( $number, $setting ) { return $this->sanitize_range( $number, $setting ); } /** * Retrieve array of image file types. * * @since 1.0.0 * @return array */ public function get_image_types() { /** * Filter array of valid image file types. * * The array includes image mime types that are included in wp_get_mime_types() * * @since 1.0.0 * @param array $mimes Image mime types. * @param object $this CX_Customizer instance. */ return apply_filters( 'kitify/theme/customizer/image_types', array( 'jpg|jpeg|jpe' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', 'bmp' => 'image/bmp', 'tif|tiff' => 'image/tiff', 'ico' => 'image/x-icon', ), $this ); } /** * Prepare fonts. * * @since 1.0.0 */ public function prepare_fonts() { $fonts_data = $this->get_fonts_data(); foreach ( $fonts_data as $type => $file ) { $fonts = $this->read_font_file( $file ); if ( is_array( $fonts ) ) { $this->fonts = array_merge( $this->fonts, $this->satizite_font_family( $fonts ) ); } } /** * Filter array of prepared fonts. * You can add new fonts from here * * @var array $this->fonts * @param CX_Customizer $this */ $this->fonts = apply_filters( 'kitify/theme/customizer/fonts_list', $this->fonts, $this ); } /** * Retrieve array with fonts file path. * * @since 1.0.0 * @return array */ public function get_fonts_data() { /** * Filter array of fonts data. * * @since 1.0.0 * @param array $data Set of fonts data. * @param object $this CX_Customizer instance. */ return apply_filters( 'kitify/theme/customizer/fonts_data', array( 'standard' => $this->path . 'assets/fonts/standard.json', 'google' => $this->path . 'assets/fonts/google.json', ), $this ); } /** * Retrieve array with font-family (for select element). * * @since 1.0.0 * @param string $type Font type. * @return array */ public function get_fonts( $type = '' ) { if ( ! empty( $this->fonts[ $type ] ) ) { return $this->fonts[ $type ]; } if ( ! empty( $this->fonts ) ) { return $this->fonts; } $this->prepare_fonts( $type ); return ! empty( $type ) && isset( $this->fonts[ $type ] ) ? $this->fonts[ $type ] : $this->fonts; } /** * Retrieve a data from font's file. * * @since 1.0.0 * @param string $file File path. * @return array Fonts data. */ public function read_font_file( $file ) { if ( ! $this->file_exists( $file ) ) { return false; } // Read the file. $json = $this->get_file( $file ); if ( ! $json ) { return new WP_Error( 'reading_error', 'Error when reading file' ); } $content = json_decode( $json, true ); return $content['items']; } /** * Safely checks exists file or not. * * @since 1.1.4 * @global object $wp_filesystem * @param string $file File path. * @return bool */ public function file_exists( $file ) { return file_exists( $file ); } /** * Safely get file content. * * @since 1.1.4 * @global object $wp_filesystem * @param string $file File path. * @return bool */ public function get_file( $file ) { if ( ! file_exists( $file ) ) { return false; } ob_start(); include $file; return ob_get_clean(); } /** * Retrieve a set with `font-family` ( 'foo' => 'foo' ). * * @since 1.0.0 * @param array $data All fonts data. * @return array */ public function satizite_font_family( $data ) { $keys = array_map( array( $this, '_build_keys' ), $data ); $values = array_map( array( $this, '_build_values' ), $data ); array_filter( $keys ); array_filter( $values ); return array_combine( $keys, $values ); } /** * Function _build_keys. * * @since 1.0.0 */ public function _build_keys( $item ) { if ( empty( $item['family'] ) ) { return false; } return sprintf( '%1$s, %2$s', $item['family'], $item['category'] ); } /** * Function _build_values. * * @since 1.0.0 */ public function _build_values( $item ) { if ( empty( $item['family'] ) ) { return false; } return $item['family']; } /** * Function add_options * * @since 1.0.0 */ public function add_options() { if ( empty( $this->options ) ) { return; } $mods = get_theme_mods(); foreach ( $this->options as $id => $option ) { if ( 'control' != $option['type'] ) { continue; } if ( isset( $mods[ $id ] ) ) { continue; } $mods[ $id ] = $this->get_default( $id ); } $theme = get_option( 'stylesheet' ); update_option( "theme_mods_$theme", $mods ); } /** * Handler for custom `active_callback` feature. * * @since 1.0.0 * @param string $callback Callback-function. * @return mixed */ public function active_callback( $callback ) { $callback = esc_attr( $callback ); if ( is_callable( array( $this, $callback ) ) ) { return array( $this, $callback ); } return $callback; } /** * Is the customizer preview a single post? * * @since 1.0.0 * @return bool */ public function callback_single() { return is_single(); } /** * Custom Devices * * Add new devices to this array. * * @since 1.0.0 * @access public * * @param array $devices Default array of devices. * * @return array Filtered new devices array. */ public function custom_devices( $devices ) { $laptop = array( 'laptop' => array( 'label' => __( 'Enter laptop preview mode', 'kitify' ), ), ); $mobile_landscape = array( 'mobile_extra' => array( 'label' => __( 'Enter mobile landscape preview mode', 'kitify' ), ), ); $devices = array_slice( $devices, 0, 1, true ) + $laptop + array_slice( $devices, 1, 1, true ) + $mobile_landscape + array_slice( $devices, 1, null, true ); return $devices; } } }