* @copyright Copyright (c) 2012 - 2016, Cherry Team * @link http://www.cherryframework.com/ * @license http://www.gnu.org/licenses/gpl-3.0.html */ // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { die; } if ( ! class_exists( 'Cherry_Customizer' ) ) { /** * Contains methods for customizing the theme customization screen. * * @since 1.0.0 * @since 1.0.1 Removed `module_dir` and `module_uri` properties. */ class Cherry_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; /** * Core instance. * * @since 1.0.0 * @access protected * @var object */ protected $core; /** * 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; /** * Module directory path. * * @since 1.5.0 * @access protected * @var srting. */ protected $module_path; /** * Module initialization. * * @since 1.0.0 * @param object $core Cherry_Core instance. * @param array $args Aguments. */ /* * $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( $core, $args ) { /** * Cherry Customizer only works in WordPress 4.0 or later. */ if ( version_compare( $GLOBALS['wp_version'], '4.0', '<' ) ) { return; } $this->core = $core; $this->fonts = array(); $this->module_path = $args['module_path']; // Prepare fonts data. add_action( 'after_switch_theme', array( $this, 'init_fonts' ), 10 ); add_action( 'after_switch_theme', array( $this, 'add_options' ), 11 ); // Clear fonts data. add_action( 'switch_theme', array( $this, 'clear_fonts' ) ); add_action( 'upgrader_process_complete', array( $this, 'fire_clear_fonts' ), 10, 2 ); /** * 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; } $this->prefix = $this->prepare_prefix( $args['prefix'] ); $this->capability = ! empty( $args['capability'] ) ? $args['capability'] : 'edit_theme_options'; $this->type = ! empty( $args['type'] ) && $this->sanitize_type( $args['type'] ) ? $args['type'] : 'theme_mod'; $this->options = $args['options']; add_action( 'customize_register', array( $this, 'register' ) ); add_filter( 'cherry_customizer_get_core', array( $this, 'pass_core_into_control' ) ); $this->include_custom_controls(); } /** * Pass current core instance into custom controls * * @param mixed $core Default core instance (false) or core instance if its not first callback. * @return Cherry_Core */ public function pass_core_into_control( $core = false ) { return $this->core; } /** * Include advanced customizer controls classes * * @since 1.1.0 */ private function include_custom_controls() { if ( ! class_exists( 'Cherry_WP_Customize_Iconpicker' ) ) { require_once( $this->module_path . 'inc/class-cherry-wp-customize-iconpicker.php' ); } } /** * 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'] ) : esc_html__( 'Untitled Panel', 'cherry-framework' ); $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'] ) : esc_html__( 'Untitled Section', 'cherry-framework' ); $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.1.8 Added a `dropdown-pages` support. * @param numder $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'] ) : esc_html__( 'Untitled Control', 'cherry-framework' ); $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'] ) : ''; // Add a customize setting. $this->customize->add_setting( $id, array( 'type' => $this->type, 'capability' => $this->capability, 'default' => $default, 'transport' => $transport, 'sanitize_callback' => $sanitize_callback, 'sanitize_js_callback' => $sanitize_js_callback, ) ); // 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 = ''; 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'; break; case 'file': $control_class = 'WP_Customize_Upload_Control'; break; case 'iconpicker': $control_class = 'Cherry_WP_Customize_Iconpicker'; $icon_data = ( isset( $args['icon_data'] ) ) ? $args['icon_data'] : array(); $auto_parse = ( isset( $args['auto_parse'] ) ) ? $args['auto_parse'] : array(); $control_args = wp_parse_args( array( 'icon_data' => $icon_data, 'auto_parse' => $auto_parse, ), $control_args ); 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( 'cherry_customizer_control_args_for_{$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( 'cherry_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( 'cherry_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( 'cherry_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. * * @author WPTRT * @author Cherry Team * @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. * * @author WPTRT * @author Cherry Team * @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. * * @author WPTRT * @author Cherry Team * @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. * * @author WPTRT * @author Cherry Team * @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. * * @author WPTRT * @author Cherry Team * @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 * * @author WPTRT * @author Cherry Team * @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. * * @author WPTRT * @author Cherry Team * @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. * * @author WPTRT * @author Cherry Team * @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 ); } /** * Retrieve array of image file types. * * @author WPTRT * @author Cherry Team * @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 Cherry_Customiser instance. */ return apply_filters( 'cherry_customizer_get_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 ); } /** * Fonts initialization. * Once add records to the `wp_options` table. * * @since 1.0.0 */ public function init_fonts() { $inited = get_option( 'cherry_customiser_fonts_inited' ); if ( $inited ) { return; } $fonts_data = $this->get_fonts_data(); $fonts_data = (array) $fonts_data; foreach ( $fonts_data as $type => $file ) { $data = $this->read_font_file( $file ); add_option( 'cherry_customiser_fonts_' . $type, $data ); } add_option( 'cherry_customiser_fonts_inited', true ); } /** * Prepare fonts. * * @since 1.0.0 */ public function prepare_fonts() { $fonts_data = $this->get_fonts_data(); $fonts_data = (array) $fonts_data; foreach ( $fonts_data as $type => $file ) { $fonts = get_option( 'cherry_customiser_fonts_' . $type, false ); if ( false === $fonts ) { $fonts = $this->read_font_file( $file ); update_option( 'cherry_customiser_fonts_' . $type, $fonts ); } if ( is_array( $fonts ) ) { $this->fonts = array_merge( $this->fonts, $this->satizite_font_family( $fonts ) ); } } } /** * 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 Cherry_Customiser instance. */ return apply_filters( 'cherry_customizer_get_fonts_data', array( 'standard' => $this->module_path . 'assets/fonts/standard.json', 'google' => $this->module_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 ) { $result = Cherry_Toolkit::get_file( $file ); return $result; } /** * 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 ); } /** * Callback-function for `upgrader_process_complete` hook (for clear fonts data). * * @since 1.0.0 * @param WP_Upgrader $updater Upgrader instance. * @param array $data Array of bulk item update data. */ public function fire_clear_fonts( $updater, $data ) { $this->clear_fonts(); } /** * Clear customizer fonts. * * @since 1.0.0 */ public function clear_fonts() { $fonts_data = $this->get_fonts_data(); $fonts_data = (array) $fonts_data; foreach ( $fonts_data as $type => $file ) { delete_option( 'cherry_customiser_fonts_' . $type ); } delete_option( 'cherry_customiser_fonts_inited' ); $this->fonts = array(); } /** * 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(); } /** * Returns the instance. * * @since 1.0.0 * @return object */ public static function get_instance( $core, $args ) { return new self( $core, $args ); } } }