Permalink
executable file 1166 lines (1001 sloc) 34.1 KB
<?php
/**
* Module Name: Customizer
* Description: Customizer functionality.
* Version: 1.1.6
* Author: Cherry Team
* Author URI: http://www.cherryframework.com/
* License: GPLv3
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
*
* @package Cherry_Framework
* @subpackage Modules
* @version 1.1.6
* @author Cherry Team <cherryframework@gmail.com>
* @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 {
/**
* The version of this module.
*
* @since 1.0.0
* @access protected
* @var string
*/
protected $version;
/**
* 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 initialization.
*
* @since 1.0.0
* @param object $core Cherry_Core instance.
* @param array $args Aguments.
*/
/*
* $args = array(
* '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->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'];
$this->core = $core;
$this->fonts = array();
$this->version = '1.1.5';
add_action( 'customize_register', array( $this, 'register' ) );
// 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 );
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
* @since 1.1.4 Using dirname( __FILE__ ) instead of __DIR__.
*/
private function include_custom_controls() {
if ( ! class_exists( 'Cherry_WP_Customize_Iconpicker' ) ) {
require_once( trailingslashit( dirname( __FILE__ ) ) . '/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
* @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':
$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();
$control_args = wp_parse_args( array( 'icon_data' => $icon_data ), $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 the version number.
*
* @since 1.0.0
* @return string The version number of the module.
*/
public function get_version() {
return $this->version;
}
/**
* 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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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 <https://github.com/WPTRT>
* @author Cherry Team <cherryframework@gmail.com>
* @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() {
$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 );
}
}
/**
* 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' => dirname( __FILE__ ) . '/assets/fonts/standard.json',
'google' => dirname( __FILE__ ) . '/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 ) {
if ( ! function_exists( 'WP_Filesystem' ) ) {
include_once( ABSPATH . '/wp-admin/includes/file.php' );
}
WP_Filesystem();
global $wp_filesystem;
if ( $wp_filesystem->abspath() ) {
return $wp_filesystem->exists( $file );
} else {
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 ( ! function_exists( 'WP_Filesystem' ) ) {
include_once( ABSPATH . '/wp-admin/includes/file.php' );
}
WP_Filesystem();
global $wp_filesystem;
$result = '';
if ( $wp_filesystem->abspath() ) {
$result = $wp_filesystem->get_contents( $file );
} else {
$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 );
}
$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 );
}
}
}