Update to Kirki 4.0.22

This commit is contained in:
AlxMedia 2022-03-15 14:29:17 +01:00
parent 2b6ac38550
commit 78edeb1b25
492 changed files with 29668 additions and 39884 deletions

View file

@ -0,0 +1,184 @@
<?php
/**
* Adds class aliases for backwards compatibility.
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 0.1
*/
namespace Kirki\Compatibility;
/**
* Adds class aliases for backwards compatibility.
*
* @since 0.1
*/
class Aliases {
/**
* An array of class aliases.
*
* @access private
* @since 0.1
* @var array
*/
private $aliases = [
'generic' => [
[ 'Kirki\Compatibility\Kirki', 'Kirki' ],
[ 'Kirki\Compatibility\Config', 'Kirki_Config' ],
[ 'Kirki\Compatibility\Control', 'Kirki_Control' ],
[ 'Kirki\Compatibility\Field', 'Kirki_Field' ],
[ 'Kirki\Util\Helper', 'Kirki_Helper' ],
[ 'Kirki\Compatibility\Init', 'Kirki_Init' ],
[ 'Kirki\L10n', 'Kirki_L10n' ],
[ 'Kirki\Compatibility\Modules', 'Kirki_Modules' ],
[ 'Kirki\Compatibility\Sanitize_Values', 'Kirki_Sanitize_Values' ],
[ 'Kirki\Compatibility\Section', 'Kirki_Section' ],
[ 'Kirki\Compatibility\Values', 'Kirki_Values' ],
[ 'Kirki\Util\Util', 'Kirki_Util' ],
[ 'Kirki\Compatibility\Framework', 'Kirki_Toolkit' ],
[ 'Kirki\Module\CSS', 'Kirki_Modules_CSS' ],
[ 'Kirki\Module\CSS\Output', 'Kirki_Output' ],
[ 'Kirki\Module\CSS\Generator', 'Kirki_Modules_CSS_Generator' ],
[ 'Kirki\Module\CSS\Property', 'Kirki_Output_Property' ],
[ 'Kirki\Module\CSS\Property\Font_Family', 'Kirki_Output_Property_Font_Family' ],
[ 'Kirki\Module\Preset', 'Kirki_Modules_Preset' ],
[ 'Kirki\Module\Tooltips', 'Kirki_Modules_Tooltips' ],
[ 'Kirki\Module\Webfonts', 'Kirki_Modules_Webfonts' ],
[ 'Kirki\Module\Webfonts\Google', 'Kirki_Fonts_Google' ],
[ 'Kirki\Module\Webfonts\Fonts', 'Kirki_Fonts' ],
[ 'Kirki\Module\Webfonts\Embed', 'Kirki_Modules_Webfonts_Embed' ],
[ 'Kirki\Module\Webfonts\Async', 'Kirki_Modules_Webfonts_Async' ],
[ 'Kirki\Module\Field_Dependencies', 'Kirki_Modules_Field_Dependencies' ],
[ 'Kirki\Module\Editor_Styles', 'Kirki_Modules_Gutenberg' ],
[ 'Kirki\Module\Selective_Refresh', 'Kirki_Modules_Selective_Refresh' ],
[ 'Kirki\Module\Postmessage', 'Kirki_Modules_Postmessage' ],
[ 'Kirki\Field\Background', 'Kirki_Field_Background' ],
[ 'Kirki\Field\CSS\Background', 'Kirki_Output_Field_Background' ],
[ 'Kirki\Field\Checkbox', 'Kirki_Field_Checkbox' ],
[ 'Kirki\Field\Checkbox_Switch', 'Kirki_Field_Switch' ],
[ 'Kirki\Field\Checkbox_Switch', 'Kirki\Field\Switch' ], // Preventing typo.
[ 'Kirki\Field\Checkbox_Toggle', 'Kirki_Field_Toggle' ],
[ 'Kirki\Field\Checkbox_Toggle', 'Kirki\Field\Toggle' ], // Preventing typo.
[ 'Kirki\Field\Code', 'Kirki_Field_Code' ],
[ 'Kirki\Field\Color', 'Kirki_Field_Color' ],
[ 'Kirki\Field\Color', 'Kirki_Field_Color_Alpha' ],
[ 'Kirki\Field\Color_Palette', 'Kirki_Field_Color_Palette' ],
[ 'Kirki\Field\Custom', 'Kirki_Field_Custom' ],
[ 'Kirki\Field\Dashicons', 'Kirki_Field_Dashicons' ],
[ 'Kirki\Field\Date', 'Kirki_Field_Date' ],
[ 'Kirki\Field\Dimension', 'Kirki_Field_Dimension' ],
[ 'Kirki\Field\Dimensions', 'Kirki_Field_Dimensions' ],
[ 'Kirki\Field\CSS\Dimensions', 'Kirki_Output_Field_Dimensions' ],
[ 'Kirki\Field\Dimensions', 'Kirki_Field_Spacing' ],
[ 'Kirki\Field\Dimensions', 'Kirki\Field\Spacing' ],
[ 'Kirki\Field\Editor', 'Kirki_Field_Editor' ],
[ 'Kirki\Field\FontAwesome', 'Kirki_Field_FontAwesome' ],
[ 'Kirki\Field\Generic', 'Kirki_Field_Kirki_Generic' ],
[ 'Kirki\Field\Generic', 'Kirki_Field_Generic' ],
[ 'Kirki\Field\Text', 'Kirki_Field_Text' ],
[ 'Kirki\Field\Textarea', 'Kirki_Field_Textarea' ],
[ 'Kirki\Field\URL', 'Kirki_Field_URL' ],
[ 'Kirki\Field\URL', 'Kirki_Field_Link' ],
[ 'Kirki\Field\URL', 'Kirki\Field\Link' ],
[ 'Kirki\Field\Image', 'Kirki_Field_Image' ],
[ 'Kirki\Field\CSS\Image', 'Kirki_Output_Field_Image' ],
[ 'Kirki\Field\Multicheck', 'Kirki_Field_Multicheck' ],
[ 'Kirki\Field\Multicolor', 'Kirki_Field_Multicolor' ],
[ 'Kirki\Field\CSS\Multicolor', 'Kirki_Output_Field_Multicolor' ],
[ 'Kirki\Field\Number', 'Kirki_Field_Number' ],
[ 'Kirki\Field\Palette', 'Kirki_Field_Palette' ],
[ 'Kirki\Field\Repeater', 'Kirki_Field_Repeater' ],
[ 'Kirki\Field\Dropdown_Pages', 'Kirki_Field_Dropdown_Pages' ],
[ 'Kirki\Field\Preset', 'Kirki_Field_Preset' ],
[ 'Kirki\Field\Select', 'Kirki_Field_Select' ],
[ 'Kirki\Field\Slider', 'Kirki_Field_Slider' ],
[ 'Kirki\Field\Sortable', 'Kirki_Field_Sortable' ],
[ 'Kirki\Field\Typography', 'Kirki_Field_Typography' ],
[ 'Kirki\Field\CSS\Typography', 'Kirki_Output_Field_Typography' ],
[ 'Kirki\Field\Upload', 'Kirki_Field_Upload' ],
],
'customizer' => [
[ 'Kirki\Control\Base', 'Kirki_Control_Base' ],
[ 'Kirki\Control\Base', 'Kirki_Customize_Control' ],
[ 'Kirki\Control\Checkbox', 'Kirki_Control_Checkbox' ],
[ 'Kirki\Control\Checkbox_Switch', 'Kirki_Control_Switch' ],
[ 'Kirki\Control\Checkbox_Toggle', 'Kirki_Control_Toggle' ],
[ 'WP_Customize_Code_Editor_Control', 'Kirki_Control_Code' ],
[ 'Kirki\Control\Color', 'Kirki_Control_Color' ],
[ 'Kirki\Control\Color_Palette', 'Kirki_Control_Color_Palette' ],
[ 'WP_Customize_Cropped_Image_Control', 'Kirki_Control_Cropped_Image' ],
[ 'Kirki\Control\Custom', 'Kirki_Control_Custom' ],
[ 'Kirki\Control\Dashicons', 'Kirki_Control_Dashicons' ],
[ 'Kirki\Control\Date', 'Kirki_Control_Date' ],
[ 'Kirki\Control\Dimension', 'Kirki_Control_Dimension' ],
[ 'Kirki\Control\Editor', 'Kirki_Control_Editor' ],
[ 'Kirki\Control\Generic', 'Kirki_Control_Generic' ],
[ 'Kirki\Control\Image', 'Kirki_Control_Image' ],
[ 'Kirki\Control\Multicheck', 'Kirki_Control_Multicheck' ],
[ 'Kirki\Control\Generic', 'Kirki_Control_Number' ],
[ 'Kirki\Control\Palette', 'Kirki_Control_Palette' ],
[ 'Kirki\Control\Radio', 'Kirki_Control_Radio' ],
[ 'Kirki\Control\Radio_Buttonset', 'Kirki_Control_Radio_Buttonset' ],
[ 'Kirki\Control\Radio_Image', 'Kirki_Control_Radio_Image' ],
[ 'Kirki\Control\Radio_Image', 'Kirki_Controls_Radio_Image_Control' ],
[ 'Kirki\Control\Repeater', 'Kirki_Control_Repeater' ],
[ 'Kirki\Control\Select', 'Kirki_Control_Select' ],
[ 'Kirki\Control\Slider', 'Kirki_Control_Slider' ],
[ 'Kirki\Control\Sortable', 'Kirki_Control_Sortable' ],
[ 'Kirki\Control\Upload', 'Kirki_Control_Upload' ],
[ 'Kirki\Settings\Repeater', 'Kirki\Settings\Repeater_Setting' ],
[ 'Kirki\Settings\Repeater', 'Kirki_Settings_Repeater_Setting' ],
[ 'WP_Customize_Section', 'Kirki_Sections_Default_Section' ],
[ 'Kirki\Section_Types\Expanded', 'Kirki_Sections_Expanded_Section' ],
[ 'Kirki\Section_Types\Nested', 'Kirki_Sections_Nested_Section' ],
[ 'Kirki\Section_Types\Link', 'Kirki_Sections_Link_Section' ],
[ 'Kirki\Panel_Types\Nested', 'Kirki_Panels_Nested_Panel' ],
],
];
/**
* Constructor.
*
* @access public
* @since 0.1
*/
public function __construct() {
$this->add_aliases();
add_action( 'customize_register', [ $this, 'add_customizer_aliases' ] );
}
/**
* Adds object aliases.
*
* @access public
* @since 0.1
* @return void
*/
public function add_aliases() {
foreach ( $this->aliases['generic'] as $item ) {
if ( class_exists( $item[0] ) ) {
class_alias( $item[0], $item[1] );
}
}
}
/**
* Adds object aliases for classes that get instantiated on customize_register.
*
* @access public
* @since 0.1
* @return void
*/
public function add_customizer_aliases() {
foreach ( $this->aliases['customizer'] as $item ) {
if ( class_exists( $item[0] ) ) {
class_alias( $item[0], $item[1] );
}
}
}
}

View file

@ -0,0 +1,179 @@
<?php
/**
* Processes configurations.
*
* @package Kirki
* @category Compatibility
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
*/
namespace Kirki\Compatibility;
/**
* The Config object
*/
final class Config {
/**
* Each instance is stored separately in this array.
*
* @static
* @access private
* @var array
*/
private static $instances = [];
/**
* The finalized configuration array.
*
* @access protected
* @var array
*/
protected $config_final = [];
/**
* The configuration ID.
*
* @access public
* @var string
*/
public $id = 'global';
/**
* Capability (fields will inherit this).
*
* @access protected
* @var string
*/
protected $capability = 'edit_theme_options';
/**
* The data-type we'll be using.
*
* @access protected
* @var string
*/
protected $option_type = 'theme_mod';
/**
* If we're using serialized options, then this is the global option name.
*
* @access protected
* @var string
*/
protected $option_name = '';
/**
* The compiler.
*
* @access protected
* @var array
*/
protected $compiler = [];
/**
* Set to true if you want to completely disable any Kirki-generated CSS.
*
* @access protected
* @var bool
*/
protected $disable_output = false;
/**
* The class constructor.
* Use the get_instance() static method to get the instance you need.
*
* @access private
* @param string $config_id @see Kirki\Compatibility\Config::get_instance().
* @param array $args @see Kirki\Compatibility\Config::get_instance().
*/
private function __construct( $config_id = 'global', $args = [] ) {
// Get defaults from the class.
$defaults = get_class_vars( __CLASS__ );
// Skip what we don't need in this context.
unset( $defaults['config_final'] );
unset( $defaults['instances'] );
// Apply any kirki_config global filters.
$defaults = apply_filters( 'kirki_config', $defaults );
// Merge our args with the defaults.
$args = wp_parse_args( $args, $defaults );
// Modify default values with the defined ones.
foreach ( $args as $key => $value ) {
// Is this property whitelisted?
if ( property_exists( $this, $key ) ) {
$args[ $key ] = $value;
}
}
$this->id = $config_id;
$this->config_final = wp_parse_args(
[
'id' => $config_id,
],
$args
);
}
/**
* Use this method to get an instance of your config.
* Each config has its own instance of this object.
*
* @static
* @access public
* @param string $id Config ID.
* @param array $args {
* Optional. Arguments to override config defaults.
*
* @type string $capability @see https://codex.wordpress.org/Roles_and_Capabilities
* @type string $option_type theme_mod or option.
* @type string $option_name If we want to used serialized options,
* this is where we'll be adding the option name.
* All fields using this config will be items in that array.
* @type array $compiler Not yet fully implemented
* @type bool $disable_output If set to true, no CSS will be generated
* from fields using this configuration.
* }
*
* @return Kirki\Compatibility\Config
*/
public static function get_instance( $id = 'global', $args = [] ) {
if ( empty( $id ) ) {
$id = 'global';
}
$id_md5 = md5( $id );
if ( ! isset( self::$instances[ $id_md5 ] ) ) {
self::$instances[ $id_md5 ] = new self( $id, $args );
}
return self::$instances[ $id_md5 ];
}
/**
* Get the IDs of all current configs.
*
* @static
* @access public
* @since 3.0.22
* @return array
*/
public static function get_config_ids() {
$configs = [];
foreach ( self::$instances as $instance ) {
$configs[] = $instance->id;
}
return array_unique( $configs );
}
/**
* Returns the $config_final property
*
* @access public
* @return array
*/
public function get_config() {
return $this->config_final;
}
}

View file

@ -0,0 +1,129 @@
<?php
/**
* Controls handler
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
*/
namespace Kirki\Compatibility;
/**
* Our main Kirki\Control object
*/
class Control {
/**
* The $wp_customize WordPress global.
*
* @access protected
* @var WP_Customize_Manager
*/
protected $wp_customize;
/**
* An array of all available control types.
*
* @access protected
* @var array
*/
protected static $control_types = [];
/**
* The class constructor.
* Creates the actual controls in the customizer.
*
* @access public
* @param array $args The field definition as sanitized in Kirki\Field.
*/
public function __construct( $args ) {
// Set the $wp_customize property.
global $wp_customize;
if ( ! $wp_customize ) {
return;
}
$this->wp_customize = $wp_customize;
// Set the control types.
$this->set_control_types();
// Add the control.
$this->add_control( $args );
}
/**
* Get the class name of the class needed to create tis control.
*
* @access private
* @param array $args The field definition as sanitized in Kirki\Field.
*
* @return string the name of the class that will be used to create this control.
*/
final function get_control_class_name( $args ) {
// Set a default class name.
$class_name = 'WP_Customize_Control';
// Get the classname from the array of control classnames.
if ( array_key_exists( $args['type'], self::$control_types ) ) {
$class_name = self::$control_types[ $args['type'] ];
}
return $class_name;
}
/**
* Adds the control.
*
* @access protected
* @param array $args The field definition as sanitized in Kirki\Field.
*/
final protected function add_control( $args ) {
// Get the name of the class we're going to use.
$class_name = $this->get_control_class_name( $args );
/**
* Allow filtering the arguments.
*
* @since 0.1
* @param array $args The arguments.
* @param WP_Customize_Manager $wp_customize The customizer instance.
* @return array Return the arguments.
*/
$args = apply_filters( 'kirki_field_add_control_args', $args, $this->wp_customize );
// Add the control.
$this->wp_customize->add_control( new $class_name( $this->wp_customize, $args['settings'], $args ) );
}
/**
* Sets the $control_types property.
* Makes sure the kirki_control_types filter is applied
* and that the defined classes actually exist.
* If a defined class does not exist, it is removed.
*
* @access private
*/
final function set_control_types() {
// Early exit if this has already run.
if ( ! empty( self::$control_types ) ) {
return;
}
self::$control_types = apply_filters( 'kirki_control_types', [] );
// Make sure the defined classes actually exist.
foreach ( self::$control_types as $key => $classname ) {
if ( ! class_exists( $classname ) ) {
unset( self::$control_types[ $key ] );
}
}
}
}

View file

@ -0,0 +1,32 @@
<?php
/**
* Backwards-compatibility for Kirki filters.
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Please do not use this class directly.
* You should instead extend it per-field-type.
*/
class Deprecated {
/**
* Constructor.
*
* @access public
* @since 1.0
*/
public function __construct() {
require_once __DIR__ . '/deprecated/classes.php'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude
require_once __DIR__ . '/deprecated/functions.php'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude
require_once __DIR__ . '/deprecated/filters.php'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude
}
}

View file

@ -0,0 +1,677 @@
<?php
/**
* Creates and validates field parameters.
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
use Kirki\Compatibility\Kirki;
/**
* Please do not use this class directly.
* You should instead extend it per-field-type.
*/
class Field {
/**
* An array of the field arguments.
*
* @access protected
* @var array
*/
protected $args = [];
/**
* The ID of the kirki_config we're using.
*
* @see Kirki\Compatibility\Config
* @access protected
* @var string
*/
protected $kirki_config = 'global';
/**
* The capability required so that users can edit this field.
*
* @access protected
* @var string
*/
protected $capability = 'edit_theme_options';
/**
* If we're using options instead of theme_mods
* and we want them serialized, this is the option that
* will saved in the db.
*
* @access protected
* @var string
*/
protected $option_name = '';
/**
* Custom input attributes (defined as an array).
*
* @access protected
* @var array
*/
protected $input_attrs = [];
/**
* Preset choices.
*
* @access protected
* @var array
*/
protected $preset = [];
/**
* CSS Variables.
*
* @access protected
* @var array
*/
protected $css_vars = [];
/**
* Use "theme_mod" or "option".
*
* @access protected
* @var string
*/
protected $option_type = 'theme_mod';
/**
* The name of this setting (id for the db).
*
* @access protected
* @var string|array
*/
protected $settings = '';
/**
* Set to true if you want to disable all CSS output for this field.
*
* @access protected
* @var bool
*/
protected $disable_output = false;
/**
* The field type.
*
* @access protected
* @var string
*/
protected $type = 'kirki-generic';
/**
* Some fields require options to be set.
* We're whitelisting the property here
* and suggest you validate this in a child class.
*
* @access protected
* @var array
*/
protected $choices = [];
/**
* Assign this field to a section.
* Fields not assigned to a section will not be displayed in the customizer.
*
* @access protected
* @var string
*/
protected $section = '';
/**
* The default value for this field.
*
* @access protected
* @var string|array|bool
*/
protected $default = '';
/**
* Priority determines the position of a control inside a section.
* Lower priority numbers move the control to the top.
*
* @access protected
* @var int
*/
protected $priority = 10;
/**
* Unique ID for this field.
* This is auto-calculated from the $settings argument.
*
* @access protected
* @var string
*/
protected $id = '';
/**
* Use if you want to automatically generate CSS from this field's value.
*
* @see https://kirki.org/docs/arguments/output
* @access protected
* @var array
*/
protected $output = [];
/**
* Use to automatically generate postMessage scripts.
* Not necessary to use if you use 'transport' => 'auto'
* and have already set an array for the 'output' argument.
*
* @see https://kirki.org/docs/arguments/js_vars
* @access protected
* @var array
*/
protected $js_vars = [];
/**
* If you want to use a CSS compiler, then use this to set the variable names.
*
* @see https://kirki.org/docs/arguments/variables
* @access protected
* @var array
*/
protected $variables = [];
/**
* Text that will be used in a tooltip to provide extra info for this field.
*
* @access protected
* @var string
*/
protected $tooltip = '';
/**
* A custom callback to determine if the field should be visible or not.
*
* @access protected
* @var string|array
*/
protected $active_callback = '__return_true';
/**
* A custom sanitize callback that will be used to properly save the values.
*
* @access protected
* @var string|array
*/
protected $sanitize_callback = '';
/**
* Use 'refresh', 'postMessage' or 'auto'.
* 'auto' will automatically geberate any 'js_vars' from the 'output' argument.
*
* @access protected
* @var string
*/
protected $transport = 'refresh';
/**
* Define dependencies to show/hide this field based on the values of other fields.
*
* @access protected
* @var array
*/
protected $required = [];
/**
* Partial Refreshes array.
*
* @access protected
* @var array
*/
protected $partial_refresh = [];
/**
* The class constructor.
* Parses and sanitizes all field arguments.
* Then it adds the field to Kirki::$fields.
*
* @access public
* @param string $config_id The ID of the config we want to use.
* Defaults to "global".
* Configs are handled by the Kirki\Compatibility\Config class.
* @param array $args The arguments of the field.
*/
public function __construct( $config_id = 'global', $args = [] ) {
/**
* In case the user only provides 1 argument,
* assume that the provided argument is $args and set $config_id = 'global'.
*/
if ( is_array( $config_id ) && empty( $args ) ) {
$args = $config_id;
$config_id = isset( $args['kirki_config'] ) ? $args['kirki_config'] : 'global';
}
if ( isset( $args['setting'] ) && ! empty( $args['setting'] ) && ( ! isset( $args['settings'] ) || empty( $args['settings'] ) ) ) {
/* translators: %s represents the field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( 'Typo found in field %s - setting instead of settings.', 'kirki' ), esc_html( $args['settings'] ) ), '3.0.10' );
$args['settings'] = $args['setting'];
unset( $args['setting'] );
}
$args['kirki_config'] = $config_id;
$this->kirki_config = $config_id;
if ( '' === $config_id ) {
/* translators: %1$s represents the field ID where the error occurs. %2$s is the URL in the documentation site. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( 'Config not defined for field %1$s - See %2$s for details on how to properly add fields.', 'kirki' ), esc_html( $args['settings'] ), 'https://aristath.github.io/kirki/docs/getting-started/fields.html' ), '3.0.10' );
$this->kirki_config = 'global';
}
// Get defaults from the class.
$defaults = get_class_vars( __CLASS__ );
// Get the config arguments, and merge them with the defaults.
$config_defaults = ( isset( Kirki::$config['global'] ) ) ? Kirki::$config['global'] : [];
if ( 'global' !== $this->kirki_config && isset( Kirki::$config[ $this->kirki_config ] ) ) {
$config_defaults = Kirki::$config[ $this->kirki_config ];
}
$config_defaults = ( is_array( $config_defaults ) ) ? $config_defaults : [];
foreach ( $config_defaults as $key => $value ) {
if ( isset( $defaults[ $key ] ) && ! empty( $value ) && $value !== $defaults[ $key ] ) {
$defaults[ $key ] = $value;
}
}
// Merge our args with the defaults.
$args = wp_parse_args( $args, $defaults );
// Set the class properties using the parsed args.
foreach ( $args as $key => $value ) {
$this->$key = $value;
}
$this->args = $args;
$this->set_field();
// Instantiate the \Kirki\Field to apply hooks.
new \Kirki\Field\None( $this->args );
}
/**
* Processes the field arguments
*
* @access protected
*/
protected function set_field() {
$properties = get_class_vars( __CLASS__ );
// Some things must run before the others.
$this->set_option_type();
$this->set_settings();
// Sanitize the properties, skipping the ones that have already run above.
foreach ( array_keys( $properties ) as $property ) {
if ( in_array( $property, [ 'option_name', 'option_type', 'settings' ], true ) ) {
continue;
}
if ( method_exists( $this, 'set_' . $property ) ) {
$method_name = 'set_' . $property;
$this->$method_name();
}
}
// Get all arguments with their values.
$args = get_object_vars( $this );
foreach ( array_keys( $args ) as $key ) {
$args[ $key ] = $this->$key;
}
// Add the field to the static $fields variable properly indexed.
Kirki::$fields[ $this->settings ] = $args;
}
/**
* Escape the $section.
*
* @access protected
*/
protected function set_input_attrs() {
$this->input_attrs = (array) $this->input_attrs;
}
/**
* Make sure we're using the correct option_type
*
* @access protected
*/
protected function set_option_type() {
// Take care of common typos.
if ( 'options' === $this->option_type ) {
$this->option_type = 'option';
}
// Take care of common typos.
if ( 'theme_mods' === $this->option_type ) {
/* translators: %1$s represents the field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html( 'Typo found in field %s - "theme_mods" vs "theme_mod"', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
$this->option_type = 'theme_mod';
}
}
/**
* Modifications for partial refreshes.
*
* @access protected
*/
protected function set_partial_refresh() {
if ( ! is_array( $this->partial_refresh ) ) {
$this->partial_refresh = [];
}
foreach ( $this->partial_refresh as $id => $args ) {
if ( ! is_array( $args ) || ! isset( $args['selector'] ) || ! isset( $args['render_callback'] ) || ! is_callable( $args['render_callback'] ) ) {
/* translators: %1$s represents the field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( '"partial_refresh" invalid entry in field %s', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
unset( $this->partial_refresh[ $id ] );
continue;
}
}
if ( ! empty( $this->partial_refresh ) ) {
$this->transport = 'postMessage';
}
}
/**
* Sets the settings.
* If we're using serialized options it makes sure that settings are properly formatted.
* We'll also be escaping all setting names here for consistency.
*
* @access protected
*/
protected function set_settings() {
// If settings is not an array, temporarily convert it to an array.
// This is just to allow us to process everything the same way and avoid code duplication.
// if settings is not an array then it will not be set as an array in the end.
if ( ! is_array( $this->settings ) ) {
$this->settings = [
'kirki_placeholder_setting' => $this->settings,
];
}
$settings = [];
foreach ( $this->settings as $setting_key => $setting_value ) {
$settings[ $setting_key ] = $setting_value;
// If we're using serialized options then we need to spice this up.
if ( 'option' === $this->option_type && '' !== $this->option_name && ( false === strpos( $setting_key, '[' ) ) ) {
$settings[ $setting_key ] = "{$this->option_name}[{$setting_value}]";
}
}
$this->settings = $settings;
if ( isset( $this->settings['kirki_placeholder_setting'] ) ) {
$this->settings = $this->settings['kirki_placeholder_setting'];
}
}
/**
* Sets the active_callback
* If we're using the $required argument,
* Then this is where the switch is made to our evaluation method.
*
* @access protected
*/
protected function set_active_callback() {
if ( is_array( $this->active_callback ) ) {
if ( ! is_callable( $this->active_callback ) ) {
// Bugfix for https://github.com/aristath/kirki/issues/1961.
foreach ( $this->active_callback as $key => $val ) {
if ( is_callable( $val ) ) {
unset( $this->active_callback[ $key ] );
}
}
if ( isset( $this->active_callback[0] ) ) {
$this->required = $this->active_callback;
}
}
}
if ( ! empty( $this->required ) ) {
$this->active_callback = '__return_true';
return;
}
// No need to proceed any further if we're using the default value.
if ( '__return_true' === $this->active_callback ) {
return;
}
// Make sure the function is callable, otherwise fallback to __return_true.
if ( ! is_callable( $this->active_callback ) ) {
$this->active_callback = '__return_true';
}
}
/**
* Sets the $id.
* Setting the ID should happen after the 'settings' sanitization.
* This way we can also properly handle cases where the option_type is set to 'option'
* and we're using an array instead of individual options.
*
* @access protected
*/
protected function set_id() {
$this->id = sanitize_key( str_replace( '[', '-', str_replace( ']', '', $this->settings ) ) );
}
/**
* Sets the $choices.
*
* @access protected
*/
protected function set_choices() {
if ( ! is_array( $this->choices ) ) {
$this->choices = [];
}
}
/**
* Escapes the $disable_output.
*
* @access protected
*/
protected function set_disable_output() {
$this->disable_output = (bool) $this->disable_output;
}
/**
* Sets the $sanitize_callback
*
* @access protected
*/
protected function set_output() {
if ( empty( $this->output ) ) {
return;
}
if ( ! is_array( $this->output ) ) {
/* translators: The field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( '"output" invalid format in field %s. The "output" argument should be defined as an array of arrays.', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
$this->output = [
[
'element' => $this->output,
],
];
}
// Convert to array of arrays if needed.
if ( isset( $this->output['element'] ) ) {
/* translators: The field ID where the error occurs. */
_doing_it_wrong( __METHOD__, sprintf( esc_html__( '"output" invalid format in field %s. The "output" argument should be defined as an array of arrays.', 'kirki' ), esc_html( $this->settings ) ), '3.0.10' );
$this->output = [ $this->output ];
}
foreach ( $this->output as $key => $output ) {
if ( empty( $output ) || ! isset( $output['element'] ) ) {
unset( $this->output[ $key ] );
continue;
}
if ( ! isset( $output['sanitize_callback'] ) && isset( $output['callback'] ) ) {
$this->output[ $key ]['sanitize_callback'] = $output['callback'];
}
// Convert element arrays to strings.
if ( isset( $output['element'] ) && is_array( $output['element'] ) ) {
$this->output[ $key ]['element'] = array_unique( $this->output[ $key ]['element'] );
sort( $this->output[ $key ]['element'] );
// Trim each element in the array.
foreach ( $this->output[ $key ]['element'] as $index => $element ) {
$this->output[ $key ]['element'][ $index ] = trim( $element );
}
$this->output[ $key ]['element'] = implode( ',', $this->output[ $key ]['element'] );
}
// Fix for https://github.com/aristath/kirki/issues/1659#issuecomment-346229751.
$this->output[ $key ]['element'] = str_replace( [ "\t", "\n", "\r", "\0", "\x0B" ], ' ', $this->output[ $key ]['element'] );
$this->output[ $key ]['element'] = trim( preg_replace( '/\s+/', ' ', $this->output[ $key ]['element'] ) );
}
}
/**
* Sets the $js_vars
*
* @access protected
*/
protected function set_js_vars() {
if ( ! is_array( $this->js_vars ) ) {
$this->js_vars = [];
}
// Check if transport is set to auto.
// If not, then skip the auto-calculations and exit early.
if ( 'auto' !== $this->transport ) {
return;
}
// Set transport to refresh initially.
// Serves as a fallback in case we failt to auto-calculate js_vars.
$this->transport = 'refresh';
$js_vars = [];
// Try to auto-generate js_vars.
// First we need to check if js_vars are empty, and that output is not empty.
if ( empty( $this->js_vars ) && ! empty( $this->output ) ) {
// Start going through each item in the $output array.
foreach ( $this->output as $output ) {
$output['function'] = ( isset( $output['function'] ) ) ? $output['function'] : 'style';
// If 'element' is not defined, skip this.
if ( ! isset( $output['element'] ) ) {
continue;
}
if ( is_array( $output['element'] ) ) {
$output['element'] = implode( ',', $output['element'] );
}
// If there's a sanitize_callback defined skip this, unless we also have a js_callback defined.
if ( isset( $output['sanitize_callback'] ) && ! empty( $output['sanitize_callback'] ) && ! isset( $output['js_callback'] ) ) {
continue;
}
// If we got this far, it's safe to add this.
$js_vars[] = $output;
}
// Did we manage to get all the items from 'output'?
// If not, then we're missing something so don't add this.
if ( count( $js_vars ) !== count( $this->output ) ) {
return;
}
$this->js_vars = $js_vars;
$this->transport = 'postMessage';
}
}
/**
* Sets the $variables
*
* @access protected
*/
protected function set_variables() {
if ( ! is_array( $this->variables ) ) {
$variable = ( is_string( $this->variables ) && ! empty( $this->variables ) ) ? $this->variables : false;
$this->variables = [];
if ( $variable && empty( $this->variables ) ) {
$this->variables[0]['name'] = $variable;
}
}
}
/**
* Sets the $transport
*
* @access protected
*/
protected function set_transport() {
if ( 'postmessage' === trim( strtolower( $this->transport ) ) ) {
$this->transport = 'postMessage';
}
}
/**
* Sets the $required
*
* @access protected
*/
protected function set_required() {
if ( ! is_array( $this->required ) ) {
$this->required = [];
}
}
/**
* Sets the $priority
*
* @access protected
*/
protected function set_priority() {
$this->priority = absint( $this->priority );
}
/**
* Sets the $css_vars
*
* @access protected
*/
protected function set_css_vars() {
if ( is_string( $this->css_vars ) ) {
$this->css_vars = [ $this->css_vars ];
}
if ( isset( $this->css_vars[0] ) && is_string( $this->css_vars[0] ) ) {
$this->css_vars = [ $this->css_vars ];
}
foreach ( $this->css_vars as $key => $val ) {
if ( ! isset( $val[1] ) ) {
$this->css_vars[ $key ][1] = '$';
}
}
}
}

View file

@ -0,0 +1,47 @@
<?php
/**
* The main Kirki object
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Singleton class
*/
final class Framework {
/**
* Holds the one, true instance of this object.
*
* @static
* @access protected
* @var object
*/
protected static $instance = null;
/**
* Access the single instance of this class.
*
* @static
* @access public
* @return Kirki\Compatibility\Framework
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
}

View file

@ -0,0 +1,310 @@
<?php
/**
* Initializes Kirki
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Initialize Kirki
*/
class Init {
/**
* Control types.
*
* @access private
* @since 3.0.0
* @var array
*/
private $control_types = [];
/**
* Should we show a nag for the deprecated fontawesome field?
*
* @static
* @access private
* @since 3.0.42
* @var bool
*/
private static $show_fa_nag = false;
/**
* The class constructor.
*/
public function __construct() {
add_action( 'wp_loaded', [ $this, 'add_to_customizer' ], 1 );
add_filter( 'kirki_control_types', [ $this, 'default_control_types' ] );
add_action( 'customize_register', [ $this, 'remove_controls' ], 99999 );
add_action( 'admin_notices', [ $this, 'admin_notices' ] );
add_action( 'admin_init', [ $this, 'dismiss_nag' ] );
// ? Bagus: is this necessary? The Values class doesn't have constructor, so this does nothing.
new Values();
}
/**
* Add the default Kirki control types.
*
* @access public
* @since 3.0.0
* @param array $control_types The control types array.
* @return array
*/
public function default_control_types( $control_types = [] ) {
$this->control_types = [
'kirki-composite' => '\Kirki\Control\Composite',
'checkbox' => '\Kirki\Control\Checkbox',
'kirki-color' => '\Kirki\Control\ReactColorful',
'kirki-color-palette' => '\Kirki\Control\Color_Palette',
'kirki-custom' => '\Kirki\Control\Custom',
'kirki-date' => '\Kirki\Control\Date',
'kirki-dashicons' => '\Kirki\Control\Dashicons',
'kirki-dimension' => '\Kirki\Control\Dimension',
'kirki-dimensions' => '\Kirki\Control\Dimensions',
'kirki-editor' => '\Kirki\Control\Editor',
'kirki-image' => '\Kirki\Control\Image',
'kirki-multicolor' => '\Kirki\Control\Multicolor',
'kirki-multicheck' => '\Kirki\Control\Multicheck',
'kirki-number' => '\Kirki\Control\Number',
'kirki-radio' => '\Kirki\Control\Radio',
'kirki-radio-buttonset' => '\Kirki\Control\Radio_Buttonset',
'kirki-radio-image' => '\Kirki\Control\Radio_Image',
'repeater' => '\Kirki\Control\Repeater',
'kirki-select' => '\Kirki\Control\Select',
'kirki-slider' => '\Kirki\Control\Slider',
'kirki-sortable' => '\Kirki\Control\Sortable',
'kirki-spacing' => '\Kirki\Control\Dimensions',
'kirki-switch' => '\Kirki\Control\Checkbox_Switch',
'kirki-generic' => '\Kirki\Control\Generic',
'kirki-toggle' => '\Kirki\Control\Checkbox_Toggle',
'image' => '\Kirki\Control\Image',
'cropped_image' => '\Kirki\Control\Cropped_Image',
'upload' => '\Kirki\Control\Upload',
];
return array_merge( $this->control_types, $control_types );
}
/**
* Helper function that adds the fields to the customizer.
*/
public function add_to_customizer() {
$this->fields_from_filters();
add_action( 'customize_register', [ $this, 'register_control_types' ] );
add_action( 'customize_register', [ $this, 'add_fields' ], 99 );
}
/**
* Register control types
*/
public function register_control_types() {
global $wp_customize;
$this->control_types = $this->default_control_types();
if ( ! class_exists( 'WP_Customize_Code_Editor_Control' ) ) {
unset( $this->control_types['code_editor'] );
}
foreach ( $this->control_types as $key => $classname ) {
if ( ! class_exists( $classname ) ) {
unset( $this->control_types[ $key ] );
}
}
$skip_control_types = apply_filters(
'kirki_control_types_exclude',
[
'\Kirki\Control\Repeater',
'\WP_Customize_Control',
]
);
foreach ( $this->control_types as $control_type ) {
if ( ! in_array( $control_type, $skip_control_types, true ) && class_exists( $control_type ) ) {
$wp_customize->register_control_type( $control_type );
}
}
}
/**
* Create the settings and controls from the $fields array and register them.
*
* @var object The WordPress Customizer object.
*/
public function add_fields() {
global $wp_customize;
foreach ( Kirki::$fields as $args ) {
// Create the settings.
new \Kirki\Compatibility\Settings( $args );
// Check if we're on the customizer.
// If we are, then we will create the controls, add the scripts needed for the customizer
// and any other tweaks that this field may require.
if ( $wp_customize ) {
// Create the control.
new Control( $args );
}
}
}
/**
* Process fields added using the 'kirki_fields' and 'kirki_controls' filter.
* These filters are no longer used, this is simply for backwards-compatibility.
*
* @access private
* @since 2.0.0
*/
private function fields_from_filters() {
$fields = apply_filters( 'kirki_controls', [] );
$fields = apply_filters( 'kirki_fields', $fields );
if ( ! empty( $fields ) ) {
foreach ( $fields as $field ) {
$field['kirki_config'] = 'global';
Kirki::add_field( 'global', $field );
}
}
}
/**
* Alias for the is_plugin static method in the Kirki\Util\Util class.
* This is here for backwards-compatibility purposes.
*
* @static
* @access public
* @since 3.0.0
* @return bool
*/
public static function is_plugin() {
return Util::is_plugin();
}
/**
* Alias for the get_variables static method in the Kirki\Util\Util class.
* This is here for backwards-compatibility purposes.
*
* @static
* @access public
* @since 2.0.0
* @return array Formatted as array( 'variable-name' => value ).
*/
public static function get_variables() {
// Log error for developers.
_doing_it_wrong( __METHOD__, esc_html__( 'We detected you\'re using Kirki\Compatibility\Init::get_variables(). Please use \Kirki\Util\Util::get_variables() instead.', 'kirki' ), '3.0.10' );
// ! This will be failed, because Util class is under Kirki\Util namespace.
return Util::get_variables();
}
/**
* Remove controls.
*
* @since 3.0.17
* @param object $wp_customize The customizer object.
* @return void
*/
public function remove_controls( $wp_customize ) {
foreach ( Kirki::$controls_to_remove as $control ) {
$wp_customize->remove_control( $control );
}
}
/**
* Shows an admin notice.
*
* @access public
* @since 3.0.42
* @return void
*/
public function admin_notices() {
// No need for a nag if we don't need to recommend installing the FA plugin.
if ( ! self::$show_fa_nag ) {
return;
}
// No need for a nag if FA plugin is already installed.
if ( defined( 'FONTAWESOME_DIR_PATH' ) ) {
return;
}
// No need for a nag if current user can't install plugins.
if ( ! current_user_can( 'install_plugins' ) ) {
return;
}
// No need for a nag if user has dismissed it.
$dismissed = get_user_meta( get_current_user_id(), 'kirki_fa_nag_dismissed', true );
if ( true === $dismissed || 1 === $dismissed || '1' === $dismissed ) {
return;
}
?>
<div class="notice notice-info is-dismissible">
<p>
<?php esc_html_e( 'Your theme uses a Font Awesome field for icons. To avoid issues with missing icons on your frontend we recommend you install the official Font Awesome plugin.', 'kirki' ); ?>
</p>
<p>
<a class="button button-primary" href="<?php echo esc_url( admin_url( 'plugin-install.php?tab=plugin-information&plugin=font-awesome&TB_iframe=true&width=600&height=550' ) ); ?>"><?php esc_html_e( 'Install Plugin', 'kirki' ); ?></a>
<a class="button button-secondary" href="<?php echo esc_url( wp_nonce_url( admin_url( '?dismiss-nag=font-awesome-kirki' ), 'kirki-dismiss-nag', 'nonce' ) ); ?>"><?php esc_html_e( 'Don\'t show this again', 'kirki' ); ?></a>
</p>
</div>
<?php
}
/**
* Dismisses the nag.
*
* @access public
* @since 3.0.42
* @return void
*/
public function dismiss_nag() {
if ( isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'], 'kirki-dismiss-nag' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
if ( get_current_user_id() && isset( $_GET['dismiss-nag'] ) && 'font-awesome-kirki' === $_GET['dismiss-nag'] ) {
update_user_meta( get_current_user_id(), 'kirki_fa_nag_dismissed', true );
}
}
}
/**
* Handles showing a nag if the theme is using the deprecated fontawesome field
*
* @static
* @access protected
* @since 3.0.42
* @param array $args The field arguments.
* @return void
*/
protected static function maybe_show_fontawesome_nag( $args ) {
// If we already know we want it, skip check.
if ( self::$show_fa_nag ) {
return;
}
// Check if the field is fontawesome.
if ( isset( $args['type'] ) && in_array( $args['type'], [ 'fontawesome', 'kirki-fontawesome' ], true ) ) {
// Skip check if theme has disabled FA enqueueing via a filter.
if ( ! apply_filters( 'kirki_load_fontawesome', true ) ) {
return;
}
// If we got this far, we need to show the nag.
self::$show_fa_nag = true;
}
}
}

View file

@ -0,0 +1,304 @@
<?php
/**
* The Kirki API class.
* Takes care of adding panels, sections & fields to the customizer.
* For documentation please see https://github.com/aristath/kirki/wiki
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
// ? Bagus: do we really need these? They are already under the same namespace as Kirki class (this file).
use Kirki\Compatibility\Config;
use Kirki\Compatibility\Field;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* This class acts as an interface.
* Developers may use this object to add configurations, fields, panels and sections.
* You can also access all available configurations, fields, panels and sections
* by accessing the object's static properties.
*/
class Kirki extends Init {
/**
* URL to the Kirki folder.
*
* @deprecated This is no longer used. Only kept here for backwards compatibility to avoid fatal errors.
* @static
* @access public
* @var string
*/
public static $url;
/**
* An array containing all configurations.
*
* @static
* @access public
* @var array
*/
public static $config = [];
/**
* An array containing all fields for compatibility purpose.
*
* @static
* @access public
* @var array
*/
public static $fields = [];
/**
* An array containing all fields.
*
* @static
* @access public
* @var array
*/
public static $all_fields = [];
/**
* An array containing all controls to be removed.
*
* @static
* @access public
* @since 3.0.17
* @var array
*/
public static $controls_to_remove = [];
/**
* Modules object.
*
* @access public
* @since 3.0.0
* @var object
*/
public $modules;
/**
* Get the value of an option from the db.
*
* @static
* @access public
* @param string $config_id The ID of the configuration corresponding to this field.
* @param string $field_id The field_id (defined as 'settings' in the field arguments).
* @return mixed The saved value of the field.
*/
public static function get_option( $config_id = '', $field_id = '' ) {
return Values::get_value( $config_id, $field_id );
}
/**
* Sets the configuration options.
*
* @static
* @access public
* @param string $config_id The configuration ID.
* @param array $args The configuration options.
*/
public static function add_config( $config_id, $args = [] ) {
$config = Config::get_instance( $config_id, $args );
$config_args = $config->get_config();
self::$config[ $config_args['id'] ] = $config_args;
}
/**
* Create a new panel.
*
* @static
* @access public
* @param string $id The ID for this panel.
* @param array $args The panel arguments.
*/
public static function add_panel( $id = '', $args = [] ) {
new \Kirki\Panel( $id, $args );
}
/**
* Remove a panel.
*
* @static
* @access public
* @since 3.0.17
* @param string $id The ID for this panel.
*/
public static function remove_panel( $id = '' ) {
$panel = new \Kirki\Panel( $id );
$panel->remove();
}
/**
* Create a new section.
*
* @static
* @access public
* @param string $id The ID for this section.
* @param array $args The section arguments.
*/
public static function add_section( $id, $args ) {
new \Kirki\Section( $id, $args );
}
/**
* Remove a section.
*
* @static
* @access public
* @since 3.0.17
* @param string $id The ID for this section.
*/
public static function remove_section( $id = '' ) {
$section = new \Kirki\Section( $id, $args );
$section->remove();
}
/**
* Create a new field.
*
* @static
* @access public
* @param string $config_id The configuration ID for this field.
* @param array $args The field arguments.
*/
public static function add_field( $config_id, $args = [] ) {
if ( doing_action( 'customize_register' ) ) {
_doing_it_wrong( __METHOD__, esc_html__( 'Kirki fields should not be added on customize_register. Please add them directly, or on init.', 'kirki' ), '3.0.10' );
}
parent::maybe_show_fontawesome_nag( $args );
// Early exit if 'type' is not defined.
if ( ! isset( $args['type'] ) ) {
return;
}
$args = self::migrate_css_vars( $args );
$str = str_replace( [ '-', '_' ], ' ', $args['type'] );
$classname = '\Kirki\Field\\' . str_replace( ' ', '_', ucwords( $str ) );
$config = Config::get_instance( $config_id )->get_config();
$args['kirki_config'] = isset( $args['kirki_config'] ) ? $args['kirki_config'] : $config_id;
unset( $config['id'] );
$args = wp_parse_args( $args, $config );
if ( class_exists( $classname ) ) {
unset( $args['type'] );
new $classname( $args );
return;
}
new Field( $config_id, $args );
}
/**
* Remove a control.
*
* @static
* @access public
* @since 3.0.17
* @param string $id The field ID.
*/
public static function remove_control( $id ) {
if ( ! in_array( $id, self::$controls_to_remove, true ) ) {
self::$controls_to_remove[] = $id;
}
}
/**
* Gets a parameter for a config-id.
*
* @static
* @access public
* @since 3.0.10
* @param string $id The config-ID.
* @param string $param The parameter we want.
* @return string
*/
public static function get_config_param( $id, $param ) {
if ( ! isset( self::$config[ $id ] ) || ! isset( self::$config[ $id ][ $param ] ) ) {
return '';
}
return self::$config[ $id ][ $param ];
}
/**
* Migrate css-variables to output argument.
*
* This only exists for backwards-compatibility with the deprecated css-vars argument.
*
* @static
* @since 4.0
* @param array $args The field arguments.
* @return array
*/
private static function migrate_css_vars( $args ) {
// Convert css_vars to output args.
if ( isset( $args['css_vars'] ) ) {
if ( 'postMessage' === $args['transport'] ) {
$args['transport'] = 'auto';
}
// Convert to properly-formatted arrays.
$args['css_vars'] = (array) $args['css_vars'];
if ( isset( $args['css_vars'][0] ) && is_string( $args['css_vars'][0] ) ) {
$args['css_vars'] = [ $args['css_vars'] ];
}
foreach ( $args['css_vars'] as $css_var ) {
$output = [
'element' => ':root',
'property' => $css_var[0],
];
if ( isset( $css_var[1] ) ) {
$output['value_pattern'] = $css_var[1];
}
if ( isset( $css_var[2] ) ) {
$output['choice'] = $css_var[2];
}
$args['output'][] = $output;
}
}
return $args;
}
}

View file

@ -0,0 +1,160 @@
<?php
/**
* Handles modules loading.
*
* @package Kirki
* @category Modules
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 3.0.0
*/
namespace Kirki\Compatibility;
/**
* The Modules class.
*/
class Modules {
/**
* An array of available modules.
*
* @static
* @access private
* @since 3.0.0
* @var array
*/
private static $modules = [];
/**
* An array of active modules (objects).
*
* @static
* @access private
* @since 3.0.0
* @var array
*/
private static $active_modules = [];
/**
* Constructor.
*
* @access public
* @since 3.0.0
*/
public function __construct() {
add_action( 'after_setup_theme', [ $this, 'setup_default_modules' ], 10 );
add_action( 'after_setup_theme', [ $this, 'init' ], 11 );
}
/**
* Set the default modules and apply the 'kirki_modules' filter.
* In v3.0.35 this method was renamed from default_modules to setup_default_modules,
* and its visibility changed from private to public to fix https://github.com/aristath/kirki/issues/2023
*
* @access public
* @since 3.0.0
*/
public function setup_default_modules() {
self::$modules = apply_filters(
'kirki_modules',
[
'css' => '\Kirki\Module\CSS',
'tooltips' => '\Kirki\Module\Tooltips',
'postMessage' => '\Kirki\Module\Postmessage',
'selective-refresh' => '\Kirki\Module\Selective_Refresh',
'field-dependencies' => '\Kirki\Module\Field_Dependencies',
'webfonts' => '\Kirki\Module\Webfonts',
'preset' => '\Kirki\Module\Preset',
'gutenberg' => '\Kirki\Module\Editor_Styles',
'section-icons' => '\Kirki\Module\Section_Icons',
]
);
}
/**
* Instantiates the modules.
* In v3.0.35 the visibility for this method was changed
* from private to public to fix https://github.com/aristath/kirki/issues/2023
*
* @access public
* @since 3.0.0
*/
public function init() {
foreach ( self::$modules as $module_class ) {
if ( class_exists( $module_class ) ) {
new $module_class();
}
}
}
/**
* Add a module.
*
* @static
* @access public
* @param string $module The classname of the module to add.
* @since 3.0.0
*/
public static function add_module( $module ) {
if ( ! in_array( $module, self::$modules, true ) ) {
self::$modules[] = $module;
}
}
/**
* Remove a module.
*
* @static
* @access public
* @param string $module The classname of the module to add.
* @since 3.0.0
*/
public static function remove_module( $module ) {
$key = array_search( $module, self::$modules, true );
if ( false !== $key ) {
unset( self::$modules[ $key ] );
}
}
/**
* Get the modules array.
*
* @static
* @access public
* @since 3.0.0
* @return array
*/
public static function get_modules() {
return self::$modules;
}
/**
* Get the array of active modules (objects).
*
* @static
* @access public
* @since 3.0.0
* @return array
*/
public static function get_active_modules() {
return self::$active_modules;
}
}

View file

@ -0,0 +1,209 @@
<?php
/**
* Additional sanitization methods for controls.
* These are used in the field's 'sanitize_callback' argument.
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
use Kirki\Field\Checkbox;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* A simple wrapper class for static methods.
*/
class Sanitize_Values {
/**
* Checkbox sanitization callback.
*
* Sanitization callback for 'checkbox' type controls.
* This callback sanitizes `$value` as a boolean value, either TRUE or FALSE.
*
* Deprecated. Use \Kirki\Field\Checkbox::sanitize() instead.
*
* @static
* @access public
* @see \Kirki\Field\Checkbox::sanitize()
* @param bool|string $value Whether the checkbox is checked.
* @return bool Whether the checkbox is checked.
*/
public static function checkbox( $value ) {
$obj = new Checkbox();
// ! This sanitize function doesn't exist. A method exists check should be used before actually calling it.
return (bool) $obj->sanitize( $value );
}
/**
* Sanitize number options.
*
* @static
* @access public
* @since 0.5
* @param int|float|double|string $value The value to be sanitized.
* @return integer|double|string
*/
public static function number( $value ) {
return ( is_numeric( $value ) ) ? $value : intval( $value );
}
/**
* Drop-down Pages sanitization callback.
*
* - Sanitization: dropdown-pages
* - Control: dropdown-pages
*
* Sanitization callback for 'dropdown-pages' type controls. This callback sanitizes `$page_id`
* as an absolute integer, and then validates that $input is the ID of a published page.
*
* @see absint() https://developer.wordpress.org/reference/functions/absint/
* @see get_post_status() https://developer.wordpress.org/reference/functions/get_post_status/
*
* @param int $page_id Page ID.
* @param WP_Customize_Setting $setting Setting instance.
* @return int|string Page ID if the page is published; otherwise, the setting default.
*/
public static function dropdown_pages( $page_id, $setting ) {
// Ensure $input is an absolute integer.
$page_id = absint( $page_id );
// If $page_id is an ID of a published page, return it; otherwise, return the default.
return ( 'publish' === get_post_status( $page_id ) ? $page_id : $setting->default );
}
/**
* Sanitizes css dimensions.
*
* @static
* @access public
* @since 2.2.0
* @param string $value The value to be sanitized.
* @return string
*/
public static function css_dimension( $value ) {
// Trim it.
$value = trim( $value );
// If the value is round, then return 50%.
if ( 'round' === $value ) {
$value = '50%';
}
// If the value is empty, return empty.
if ( '' === $value ) {
return '';
}
// If auto, inherit or initial, return the value.
if ( 'auto' === $value || 'initial' === $value || 'inherit' === $value || 'normal' === $value ) {
return $value;
}
// Return empty if there are no numbers in the value.
if ( ! preg_match( '#[0-9]#', $value ) ) {
return '';
}
// If we're using calc() then return the value.
if ( false !== strpos( $value, 'calc(' ) ) {
return $value;
}
// The raw value without the units.
$raw_value = self::filter_number( $value );
$unit_used = '';
// An array of all valid CSS units. Their order was carefully chosen for this evaluation, don't mix it up!!!
$units = [ 'fr', 'rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax' ];
foreach ( $units as $unit ) {
if ( false !== strpos( $value, $unit ) ) {
$unit_used = $unit;
}
}
// Hack for rem values.
if ( 'em' === $unit_used && false !== strpos( $value, 'rem' ) ) {
$unit_used = 'rem';
}
return $raw_value . $unit_used;
}
/**
* Filters numeric values.
*
* @static
* @access public
* @param string $value The value to be sanitized.
* @return int|float
*/
public static function filter_number( $value ) {
return filter_var( $value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION );
}
/**
* Sanitize RGBA colors
*
* @static
* @since 0.8.5
* @param string $value The value to be sanitized.
* @return string
*/
public static function rgba( $value ) {
$color = \ariColor::newColor( $value );
return $color->toCSS( 'rgba' );
}
/**
* Sanitize colors.
*
* @static
* @since 0.8.5
* @param string $value The value to be sanitized.
* @return string
*/
public static function color( $value ) {
// If the value is empty, then return empty.
if ( '' === $value ) {
return '';
}
// If transparent, then return 'transparent'.
if ( is_string( $value ) && 'transparent' === trim( $value ) ) {
return 'transparent';
}
// Instantiate the object.
$color = \ariColor::newColor( $value );
// Return a CSS value, using the auto-detected mode.
return $color->toCSS( $color->mode );
}
/**
* DOES NOT SANITIZE ANYTHING.
*
* @static
* @since 0.5
* @param int|string|array $value The value to be sanitized.
* @return int|string|array
*/
public static function unfiltered( $value ) {
return $value;
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
* Registers scripts for WordPress Compatibility with versions prior to WP5.0
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 0.1
*/
namespace Kirki\Compatibility;
/**
* Adds scripts for backwards-compatibility
*
* @since 0.1
*/
class Scripts {
/**
* Constructor.
*
* @access public
* @since 0.1
*/
public function __construct() {
global $wp_version;
/**
* Check if the WordPress version is lower than 5.0
* If lower then we need to enqueue the backported scripts.
*/
if ( version_compare( $GLOBALS['wp_version'], '5.0', '<' ) ) {
add_action( 'wp_enqueue_scripts', [ $this, 'register_scripts' ] );
add_action( 'admin_register_scripts', [ $this, 'register_scripts' ] );
add_action( 'customize_controls_enqueue_scripts', [ $this, 'register_scripts' ] );
}
}
/**
* Enqueue missing WP scripts.
*
* @access public
* @since 0.1
* @return void
*/
public function register_scripts() {
$folder_url = trailingslashit( URL::get_from_path( __DIR__ ) );
wp_register_script( 'wp-polyfill', $folder_url . 'scripts/wp-polyfill.js', [], '7.0.0', false );
wp_register_script( 'wp-hooks', $folder_url . 'scripts/hooks.js', [ 'wp-polyfill' ], '2.2.0', false );
wp_register_script( 'wp-i18n', $folder_url . 'scripts/i18n.js', [ 'wp-polyfill' ], '3.3.0', false );
}
}

View file

@ -0,0 +1,157 @@
<?php
/**
* Handles sections created via the Kirki API.
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Each setting is a separate instance
*/
class Settings {
/**
* The global $wp_customize object.
*
* @access protected
* @var WP_Customize_Manager
*/
protected $wp_customize;
/**
* The setting-stypes we're using.
*
* @access protected
* @var array
*/
protected $setting_types = [];
/**
* Creates a new Settings object.
* Class constructor.
*
* @access public
* @param array $args The field definition as sanitized in Kirki\Compatibility\Field.
*/
public function __construct( $args = [] ) {
// Set the $wp_customize property.
global $wp_customize;
if ( ! $wp_customize ) {
return;
}
$this->wp_customize = $wp_customize;
// Set the setting_types.
$this->set_setting_types();
// Add the settings.
$this->add_settings( $args );
}
/**
* Adds the settings for this field.
* If settings are defined as an array, then it goes through them
* and calls the add_setting method.
* If not an array, then it just calls add_setting
*
* @access private
* @param array $args The field definition as sanitized in Kirki\Compatibility\Field.
*/
final function add_settings( $args = [] ) {
// Get the classname we'll be using to create our setting(s).
$classname = false;
if ( isset( $args['option_type'] ) && array_key_exists( $args['option_type'], $this->setting_types ) ) {
$classname = $this->setting_types[ $args['option_type'] ];
}
if ( ! isset( $args['type'] ) || ! array_key_exists( $args['type'], $this->setting_types ) ) {
$args['type'] = 'default';
}
$classname = ! $classname ? $this->setting_types[ $args['type'] ] : $classname;
// If settings are defined as an array, then we need to go through them
// and call add_setting for each one of them separately.
if ( isset( $args['settings'] ) && is_array( $args['settings'] ) ) {
// Make sure defaults have been defined.
if ( ! isset( $args['default'] ) || ! is_array( $args['default'] ) ) {
$args['default'] = [];
}
foreach ( $args['settings'] as $key => $value ) {
// ? Bagus: this $defaults var is not defined anywhere inside this function, so is this a mistake?
$default = ( isset( $defaults[ $key ] ) ) ? $defaults[ $key ] : '';
$this->add_setting( $classname, $value, $default, $args['option_type'], $args['capability'], $args['transport'], $args['sanitize_callback'] );
}
}
$this->add_setting( $classname, $args['settings'], $args['default'], $args['option_type'], $args['capability'], $args['transport'], $args['sanitize_callback'] );
}
/**
* This is where we're finally adding the setting to the Customizer.
*
* @access private
* @param string $classname The name of the class that will be used to create this setting.
* We're getting this from $this->setting_types.
* @param string $setting The setting-name.
* If settings is an array, then this method is called per-setting.
* @param string|array $default Default value for this setting.
* @param string $type The data type we're using. Valid options: theme_mod|option.
* @param string $capability @see https://codex.wordpress.org/Roles_and_Capabilities.
* @param string $transport Use refresh|postMessage.
* @param string|array $sanitize_callback A callable sanitization function or method.
*/
final function add_setting( $classname, $setting, $default, $type, $capability, $transport, $sanitize_callback ) {
$this->wp_customize->add_setting(
new $classname(
$this->wp_customize,
$setting,
[
'default' => $default,
'type' => $type,
'capability' => $capability,
'transport' => $transport,
'sanitize_callback' => $sanitize_callback,
]
)
);
}
/**
* Sets the $this->setting_types property.
* Makes sure the kirki_setting_types filter is applied
* and that the defined classes actually exist.
* If a defined class does not exist, it is removed.
*/
final function set_setting_types() {
// Apply the kirki_setting_types filter.
$this->setting_types = apply_filters(
'kirki_setting_types',
[
'default' => 'WP_Customize_Setting',
'repeater' => '\Kirki_Settings_Repeater_Setting',
'user_meta' => '\Kirki\Util\Setting\User_Meta',
'site_option' => '\Kirki\Util\Setting\Site_Option',
]
);
// Make sure the defined classes actually exist.
foreach ( $this->setting_types as $key => $classname ) {
if ( ! class_exists( $classname ) ) {
unset( $this->setting_types[ $key ] );
}
}
}
}

View file

@ -0,0 +1,124 @@
<?php
/**
* Helpers to get the values of a field.
*
* ! WARNING: PLEASE DO NOT USE THESE.
* we only have these for backwards-compatibility purposes.
* please use get_option() & get_theme_mod() instead.
*
* @package Kirki
* @category Core
* @author Ari Stathopoulos (@aristath)
* @copyright Copyright (c) 2020, David Vongries
* @license https://opensource.org/licenses/MIT
* @since 1.0
*/
namespace Kirki\Compatibility;
/**
* Wrapper class for static methods.
*/
class Values {
/**
* Get the value of a field.
*
* @static
* @access public
* @param string $config_id The configuration ID. @see Kirki\Compatibility\Config.
* @param string $field_id The field ID.
* @return string|array
*/
public static function get_value( $config_id = '', $field_id = '' ) {
// Make sure value is defined.
$value = '';
// This allows us to skip the $config_id argument.
// If we skip adding a $config_id, use the 'global' configuration.
if ( ( '' === $field_id ) && '' !== $config_id ) {
$field_id = $config_id;
$config_id = 'global';
}
// If $config_id is empty, set it to 'global'.
$config_id = ( '' === $config_id ) ? 'global' : $config_id;
// Fallback to 'global' if $config_id is not found.
if ( ! isset( Kirki::$config[ $config_id ] ) ) {
$config_id = 'global';
}
if ( 'theme_mod' === Kirki::$config[ $config_id ]['option_type'] ) {
// We're using theme_mods so just get the value using get_theme_mod.
$default_value = null;
if ( isset( Kirki::$all_fields[ $field_id ] ) && isset( Kirki::$all_fields[ $field_id ]['default'] ) ) {
$default_value = Kirki::$all_fields[ $field_id ]['default'];
}
$value = get_theme_mod( $field_id, $default_value );
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
if ( 'option' === Kirki::$config[ $config_id ]['option_type'] ) {
// We're using options.
if ( '' !== Kirki::$config[ $config_id ]['option_name'] ) {
// Options are serialized as a single option in the db.
// We'll have to get the option and then get the item from the array.
$options = get_option( Kirki::$config[ $config_id ]['option_name'] );
if ( ! isset( Kirki::$all_fields[ $field_id ] ) && isset( Kirki::$all_fields[ Kirki::$config[ $config_id ]['option_name'] . '[' . $field_id . ']' ] ) ) {
$field_id = Kirki::$config[ $config_id ]['option_name'] . '[' . $field_id . ']';
}
$setting_modified = str_replace( ']', '', str_replace( Kirki::$config[ $config_id ]['option_name'] . '[', '', $field_id ) );
$default_value = ( isset( Kirki::$all_fields[ $field_id ] ) && isset( Kirki::$all_fields[ $field_id ]['default'] ) ) ? Kirki::$all_fields[ $field_id ]['default'] : '';
$value = ( isset( $options[ $setting_modified ] ) ) ? $options[ $setting_modified ] : $default_value;
$value = maybe_unserialize( $value );
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
// Each option separately saved in the db.
$value = get_option( $field_id, Kirki::$all_fields[ $field_id ]['default'] );
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
return apply_filters( 'kirki_values_get_value', $value, $field_id );
}
/**
* Gets the value or fallsback to default.
*
* @static
* @access public
* @param array $field The field aruments.
* @return string|array
*/
public static function get_sanitized_field_value( $field ) {
$value = $field['default'];
if ( ! isset( $field['option_type'] ) || 'theme_mod' === $field['option_type'] ) {
$value = get_theme_mod( $field['settings'], $field['default'] );
} elseif ( isset( $field['option_type'] ) && 'option' === $field['option_type'] ) {
if ( isset( $field['option_name'] ) && '' !== $field['option_name'] ) {
$all_values = get_option( $field['option_name'], [] );
$sub_setting_id = str_replace( [ ']', $field['option_name'] . '[' ], '', $field['settings'] );
if ( isset( $all_values[ $sub_setting_id ] ) ) {
$value = $all_values[ $sub_setting_id ];
}
} else {
$value = get_option( $field['settings'], $field['default'] );
}
}
return $value;
}
}

View file

@ -0,0 +1,35 @@
<?php
// phpcs:ignoreFile
if ( ! class_exists( 'Kirki_Active_Callback' ) ) {
// Removed in https://github.com/aristath/kirki/pull/1682/files
class Kirki_Active_Callback {
public static function evaluate() {
_deprecated_function( __METHOD__, '3.0.17', null );
return true;
}
private static function evaluate_requirement() {
_deprecated_function( __METHOD__, '3.0.17', null );
return true;
}
public static function compare( $value1, $value2, $operator ) {
_deprecated_function( __METHOD__, '3.0.17', 'Kirki_Helper::compare_values' );
return Kirki_Helper::compare_values( $value1, $value2, $operator );
}
}
}
/**
* Deprecated in v3.0.36
*
* Keeping it here in case a theme or plugin was using one of its public methods.
* This is just to avoid fatal errors, it does not do anything.
*/
if ( ! class_exists( 'Kirki_CSS_To_File' ) ) {
class Kirki_CSS_To_File {
public function __construct() {}
public function get_url() {}
public function get_timestamp() {}
public function write_file() {}
}
}

View file

@ -0,0 +1,112 @@
<?php
// phpcs:ignoreFile
add_filter( 'kirki_config', function( $args ) {
return apply_filters( 'kirki/config', $args );
}, 99 );
add_filter( 'kirki_control_types', function( $args ) {
return apply_filters( 'kirki/control_types', $args );
}, 99 );
add_filter( 'kirki_section_types', function( $args ) {
return apply_filters( 'kirki/section_types', $args );
}, 99 );
add_filter( 'kirki_section_types_exclude', function( $args ) {
return apply_filters( 'kirki/section_types/exclude', $args );
}, 99 );
add_filter( 'kirki_control_types_exclude', function( $args ) {
return apply_filters( 'kirki/control_types/exclude', $args );
}, 99 );
add_filter( 'kirki_controls', function( $args ) {
return apply_filters( 'kirki/controls', $args );
}, 99 );
add_filter( 'kirki_fields', function( $args ) {
return apply_filters( 'kirki/fields', $args );
}, 99 );
add_filter( 'kirki_modules', function( $args ) {
return apply_filters( 'kirki/modules', $args );
}, 99 );
add_filter( 'kirki_panel_types', function( $args ) {
return apply_filters( 'kirki/panel_types', $args );
}, 99 );
add_filter( 'kirki_setting_types', function( $args ) {
return apply_filters( 'kirki/setting_types', $args );
}, 99 );
add_filter( 'kirki_variable', function( $args ) {
return apply_filters( 'kirki/variable', $args );
}, 99 );
add_filter( 'kirki_values_get_value', function( $arg1, $arg2 ) {
return apply_filters( 'kirki/values/get_value', $arg1, $arg2 );
}, 99, 2 );
add_action( 'init', function() {
$config_ids = \Kirki\Compatibility\Config::get_config_ids();
global $kirki_deprecated_filters_iteration;
foreach ( $config_ids as $config_id ) {
foreach( array(
'/dynamic_css',
'/output/control-classnames',
'/css/skip_hidden',
'/styles',
'/output/property-classnames',
'/webfonts/skip_hidden',
) as $filter_suffix ) {
$kirki_deprecated_filters_iteration = array( $config_id, $filter_suffix );
add_filter( "kirki_{$config_id}_{$filter_suffix}", function( $args ) {
global $kirki_deprecated_filters_iteration;
$kirki_deprecated_filters_iteration[1] = str_replace( '-', '_', $kirki_deprecated_filters_iteration[1] );
return apply_filters( "kirki/{$kirki_deprecated_filters_iteration[0]}/{$kirki_deprecated_filters_iteration[1]}", $args );
}, 99 );
if ( false !== strpos( $kirki_deprecated_filters_iteration[1], '-' ) ) {
$kirki_deprecated_filters_iteration[1] = str_replace( '-', '_', $kirki_deprecated_filters_iteration[1] );
add_filter( "kirki_{$config_id}_{$filter_suffix}", function( $args ) {
global $kirki_deprecated_filters_iteration;
$kirki_deprecated_filters_iteration[1] = str_replace( '-', '_', $kirki_deprecated_filters_iteration[1] );
return apply_filters( "kirki/{$kirki_deprecated_filters_iteration[0]}/{$kirki_deprecated_filters_iteration[1]}", $args );
}, 99 );
}
}
}
}, 99 );
add_filter( 'kirki_enqueue_google_fonts', function( $args ) {
return apply_filters( 'kirki/enqueue_google_fonts', $args );
}, 99 );
add_filter( 'kirki_styles_array', function( $args ) {
return apply_filters( 'kirki/styles_array', $args );
}, 99 );
add_filter( 'kirki_dynamic_css_method', function( $args ) {
return apply_filters( 'kirki/dynamic_css/method', $args );
}, 99 );
add_filter( 'kirki_postmessage_script', function( $args ) {
return apply_filters( 'kirki/postmessage/script', $args );
}, 99 );
add_filter( 'kirki_fonts_all', function( $args ) {
return apply_filters( 'kirki/fonts/all', $args );
}, 99 );
add_filter( 'kirki_fonts_standard_fonts', function( $args ) {
return apply_filters( 'kirki/fonts/standard_fonts', $args );
}, 99 );
add_filter( 'kirki_fonts_google_fonts', function( $args ) {
return apply_filters( 'kirki/fonts/google_fonts', $args );
}, 99 );
add_filter( 'kirki_googlefonts_load_method', function( $args ) {
return apply_filters( 'kirki/googlefonts_load_method', $args );
}, 99 );

View file

@ -0,0 +1,57 @@
<?php
// phpcs:ignoreFile
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! function_exists( 'kirki_get_option' ) ) {
/**
* Get the value of a field.
* This is a deprecated function that we used when there was no API.
* Please use get_theme_mod() or get_option() instead.
* @see https://developer.wordpress.org/reference/functions/get_theme_mod/
* @see https://developer.wordpress.org/reference/functions/get_option/
*
* @return mixed
*/
function kirki_get_option( $option = '' ) {
_deprecated_function( __FUNCTION__, '1.0.0', sprintf( esc_html__( '%1$s or %2$s', 'kirki' ), 'get_theme_mod', 'get_option' ) );
return Kirki::get_option( '', $option );
}
}
if ( ! function_exists( 'kirki_sanitize_hex' ) ) {
function kirki_sanitize_hex( $color ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->toCSS( \'hex\' )' );
return Kirki_Color::sanitize_hex( $color );
}
}
if ( ! function_exists( 'kirki_get_rgb' ) ) {
function kirki_get_rgb( $hex, $implode = false ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->toCSS( \'rgb\' )' );
return Kirki_Color::get_rgb( $hex, $implode );
}
}
if ( ! function_exists( 'kirki_get_rgba' ) ) {
function kirki_get_rgba( $hex = '#fff', $opacity = 100 ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->toCSS( \'rgba\' )' );
return Kirki_Color::get_rgba( $hex, $opacity );
}
}
if ( ! function_exists( 'kirki_get_brightness' ) ) {
function kirki_get_brightness( $hex ) {
_deprecated_function( __FUNCTION__, '1.0.0', 'ariColor::newColor( $color )->lightness' );
return Kirki_Color::get_brightness( $hex );
}
}
if ( ! function_exists( 'Kirki' ) ) {
function Kirki() {
return \Kirki\Compatibility\Framework::get_instance();
}
}

View file

@ -0,0 +1,623 @@
this["wp"] = this["wp"] || {}; this["wp"]["hooks"] =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 366);
/******/ })
/************************************************************************/
/******/ ({
/***/ 366:
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/validateNamespace.js
/**
* Validate a namespace string.
*
* @param {string} namespace The namespace to validate - should take the form
* `vendor/plugin/function`.
*
* @return {boolean} Whether the namespace is valid.
*/
function validateNamespace(namespace) {
if ('string' !== typeof namespace || '' === namespace) {
// eslint-disable-next-line no-console
console.error('The namespace must be a non-empty string.');
return false;
}
if (!/^[a-zA-Z][a-zA-Z0-9_.\-\/]*$/.test(namespace)) {
// eslint-disable-next-line no-console
console.error('The namespace can only contain numbers, letters, dashes, periods, underscores and slashes.');
return false;
}
return true;
}
/* harmony default export */ var build_module_validateNamespace = (validateNamespace);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/validateHookName.js
/**
* Validate a hookName string.
*
* @param {string} hookName The hook name to validate. Should be a non empty string containing
* only numbers, letters, dashes, periods and underscores. Also,
* the hook name cannot begin with `__`.
*
* @return {boolean} Whether the hook name is valid.
*/
function validateHookName(hookName) {
if ('string' !== typeof hookName || '' === hookName) {
// eslint-disable-next-line no-console
console.error('The hook name must be a non-empty string.');
return false;
}
if (/^__/.test(hookName)) {
// eslint-disable-next-line no-console
console.error('The hook name cannot begin with `__`.');
return false;
}
if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(hookName)) {
// eslint-disable-next-line no-console
console.error('The hook name can only contain numbers, letters, dashes, periods and underscores.');
return false;
}
return true;
}
/* harmony default export */ var build_module_validateHookName = (validateHookName);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createAddHook.js
/**
* Internal dependencies
*/
/**
* Returns a function which, when invoked, will add a hook.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that adds a new hook.
*/
function createAddHook(hooks) {
/**
* Adds the hook to the appropriate hooks container.
*
* @param {string} hookName Name of hook to add
* @param {string} namespace The unique namespace identifying the callback in the form `vendor/plugin/function`.
* @param {Function} callback Function to call when the hook is run
* @param {?number} priority Priority of this hook (default=10)
*/
return function addHook(hookName, namespace, callback) {
var priority = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 10;
if (!build_module_validateHookName(hookName)) {
return;
}
if (!build_module_validateNamespace(namespace)) {
return;
}
if ('function' !== typeof callback) {
// eslint-disable-next-line no-console
console.error('The hook callback must be a function.');
return;
} // Validate numeric priority
if ('number' !== typeof priority) {
// eslint-disable-next-line no-console
console.error('If specified, the hook priority must be a number.');
return;
}
var handler = {
callback: callback,
priority: priority,
namespace: namespace
};
if (hooks[hookName]) {
// Find the correct insert index of the new hook.
var handlers = hooks[hookName].handlers;
var i;
for (i = handlers.length; i > 0; i--) {
if (priority >= handlers[i - 1].priority) {
break;
}
}
if (i === handlers.length) {
// If append, operate via direct assignment.
handlers[i] = handler;
} else {
// Otherwise, insert before index via splice.
handlers.splice(i, 0, handler);
} // We may also be currently executing this hook. If the callback
// we're adding would come after the current callback, there's no
// problem; otherwise we need to increase the execution index of
// any other runs by 1 to account for the added element.
(hooks.__current || []).forEach(function (hookInfo) {
if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
hookInfo.currentIndex++;
}
});
} else {
// This is the first hook of its type.
hooks[hookName] = {
handlers: [handler],
runs: 0
};
}
if (hookName !== 'hookAdded') {
doAction('hookAdded', hookName, namespace, callback, priority);
}
};
}
/* harmony default export */ var build_module_createAddHook = (createAddHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createRemoveHook.js
/**
* Internal dependencies
*/
/**
* Returns a function which, when invoked, will remove a specified hook or all
* hooks by the given name.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
* @param {boolean} removeAll Whether to remove all callbacks for a hookName, without regard to namespace. Used to create `removeAll*` functions.
*
* @return {Function} Function that removes hooks.
*/
function createRemoveHook(hooks, removeAll) {
/**
* Removes the specified callback (or all callbacks) from the hook with a
* given hookName and namespace.
*
* @param {string} hookName The name of the hook to modify.
* @param {string} namespace The unique namespace identifying the callback in the form `vendor/plugin/function`.
*
* @return {number} The number of callbacks removed.
*/
return function removeHook(hookName, namespace) {
if (!build_module_validateHookName(hookName)) {
return;
}
if (!removeAll && !build_module_validateNamespace(namespace)) {
return;
} // Bail if no hooks exist by this name
if (!hooks[hookName]) {
return 0;
}
var handlersRemoved = 0;
if (removeAll) {
handlersRemoved = hooks[hookName].handlers.length;
hooks[hookName] = {
runs: hooks[hookName].runs,
handlers: []
};
} else {
// Try to find the specified callback to remove.
var handlers = hooks[hookName].handlers;
var _loop = function _loop(i) {
if (handlers[i].namespace === namespace) {
handlers.splice(i, 1);
handlersRemoved++; // This callback may also be part of a hook that is
// currently executing. If the callback we're removing
// comes after the current callback, there's no problem;
// otherwise we need to decrease the execution index of any
// other runs by 1 to account for the removed element.
(hooks.__current || []).forEach(function (hookInfo) {
if (hookInfo.name === hookName && hookInfo.currentIndex >= i) {
hookInfo.currentIndex--;
}
});
}
};
for (var i = handlers.length - 1; i >= 0; i--) {
_loop(i);
}
}
if (hookName !== 'hookRemoved') {
doAction('hookRemoved', hookName, namespace);
}
return handlersRemoved;
};
}
/* harmony default export */ var build_module_createRemoveHook = (createRemoveHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createHasHook.js
/**
* Returns a function which, when invoked, will return whether any handlers are
* attached to a particular hook.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns whether any handlers are
* attached to a particular hook.
*/
function createHasHook(hooks) {
/**
* Returns how many handlers are attached for the given hook.
*
* @param {string} hookName The name of the hook to check for.
*
* @return {boolean} Whether there are handlers that are attached to the given hook.
*/
return function hasHook(hookName) {
return hookName in hooks;
};
}
/* harmony default export */ var build_module_createHasHook = (createHasHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createRunHook.js
/**
* Returns a function which, when invoked, will execute all callbacks
* registered to a hook of the specified type, optionally returning the final
* value of the call chain.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
* @param {?boolean} returnFirstArg Whether each hook callback is expected to
* return its first argument.
*
* @return {Function} Function that runs hook callbacks.
*/
function createRunHook(hooks, returnFirstArg) {
/**
* Runs all callbacks for the specified hook.
*
* @param {string} hookName The name of the hook to run.
* @param {...*} args Arguments to pass to the hook callbacks.
*
* @return {*} Return value of runner, if applicable.
*/
return function runHooks(hookName) {
if (!hooks[hookName]) {
hooks[hookName] = {
handlers: [],
runs: 0
};
}
hooks[hookName].runs++;
var handlers = hooks[hookName].handlers;
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
if (!handlers || !handlers.length) {
return returnFirstArg ? args[0] : undefined;
}
var hookInfo = {
name: hookName,
currentIndex: 0
};
hooks.__current.push(hookInfo);
while (hookInfo.currentIndex < handlers.length) {
var handler = handlers[hookInfo.currentIndex];
var result = handler.callback.apply(null, args);
if (returnFirstArg) {
args[0] = result;
}
hookInfo.currentIndex++;
}
hooks.__current.pop();
if (returnFirstArg) {
return args[0];
}
};
}
/* harmony default export */ var build_module_createRunHook = (createRunHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createCurrentHook.js
/**
* Returns a function which, when invoked, will return the name of the
* currently running hook, or `null` if no hook of the given type is currently
* running.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns the current hook.
*/
function createCurrentHook(hooks) {
/**
* Returns the name of the currently running hook, or `null` if no hook of
* the given type is currently running.
*
* @return {?string} The name of the currently running hook, or
* `null` if no hook is currently running.
*/
return function currentHook() {
if (!hooks.__current || !hooks.__current.length) {
return null;
}
return hooks.__current[hooks.__current.length - 1].name;
};
}
/* harmony default export */ var build_module_createCurrentHook = (createCurrentHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createDoingHook.js
/**
* Returns a function which, when invoked, will return whether a hook is
* currently being executed.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns whether a hook is currently
* being executed.
*/
function createDoingHook(hooks) {
/**
* Returns whether a hook is currently being executed.
*
* @param {?string} hookName The name of the hook to check for. If
* omitted, will check for any hook being executed.
*
* @return {boolean} Whether the hook is being executed.
*/
return function doingHook(hookName) {
// If the hookName was not passed, check for any current hook.
if ('undefined' === typeof hookName) {
return 'undefined' !== typeof hooks.__current[0];
} // Return the __current hook.
return hooks.__current[0] ? hookName === hooks.__current[0].name : false;
};
}
/* harmony default export */ var build_module_createDoingHook = (createDoingHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createDidHook.js
/**
* Internal dependencies
*/
/**
* Returns a function which, when invoked, will return the number of times a
* hook has been called.
*
* @param {Object} hooks Stored hooks, keyed by hook name.
*
* @return {Function} Function that returns a hook's call count.
*/
function createDidHook(hooks) {
/**
* Returns the number of times an action has been fired.
*
* @param {string} hookName The hook name to check.
*
* @return {number} The number of times the hook has run.
*/
return function didHook(hookName) {
if (!build_module_validateHookName(hookName)) {
return;
}
return hooks[hookName] && hooks[hookName].runs ? hooks[hookName].runs : 0;
};
}
/* harmony default export */ var build_module_createDidHook = (createDidHook);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/createHooks.js
/**
* Internal dependencies
*/
/**
* Returns an instance of the hooks object.
*
* @return {Object} Object that contains all hooks.
*/
function createHooks() {
var actions = Object.create(null);
var filters = Object.create(null);
actions.__current = [];
filters.__current = [];
return {
addAction: build_module_createAddHook(actions),
addFilter: build_module_createAddHook(filters),
removeAction: build_module_createRemoveHook(actions),
removeFilter: build_module_createRemoveHook(filters),
hasAction: build_module_createHasHook(actions),
hasFilter: build_module_createHasHook(filters),
removeAllActions: build_module_createRemoveHook(actions, true),
removeAllFilters: build_module_createRemoveHook(filters, true),
doAction: build_module_createRunHook(actions),
applyFilters: build_module_createRunHook(filters, true),
currentAction: build_module_createCurrentHook(actions),
currentFilter: build_module_createCurrentHook(filters),
doingAction: build_module_createDoingHook(actions),
doingFilter: build_module_createDoingHook(filters),
didAction: build_module_createDidHook(actions),
didFilter: build_module_createDidHook(filters),
actions: actions,
filters: filters
};
}
/* harmony default export */ var build_module_createHooks = (createHooks);
// CONCATENATED MODULE: ./node_modules/@wordpress/hooks/build-module/index.js
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addAction", function() { return addAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "addFilter", function() { return addFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAction", function() { return removeAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeFilter", function() { return removeFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasAction", function() { return hasAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasFilter", function() { return hasFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAllActions", function() { return removeAllActions; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAllFilters", function() { return removeAllFilters; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "doAction", function() { return doAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "applyFilters", function() { return applyFilters; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "currentAction", function() { return currentAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "currentFilter", function() { return currentFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "doingAction", function() { return doingAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "doingFilter", function() { return doingFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "didAction", function() { return didAction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "didFilter", function() { return didFilter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "actions", function() { return build_module_actions; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filters", function() { return build_module_filters; });
/* concated harmony reexport createHooks */__webpack_require__.d(__webpack_exports__, "createHooks", function() { return build_module_createHooks; });
/**
* Internal dependencies
*/
var _createHooks = build_module_createHooks(),
addAction = _createHooks.addAction,
addFilter = _createHooks.addFilter,
removeAction = _createHooks.removeAction,
removeFilter = _createHooks.removeFilter,
hasAction = _createHooks.hasAction,
hasFilter = _createHooks.hasFilter,
removeAllActions = _createHooks.removeAllActions,
removeAllFilters = _createHooks.removeAllFilters,
doAction = _createHooks.doAction,
applyFilters = _createHooks.applyFilters,
currentAction = _createHooks.currentAction,
currentFilter = _createHooks.currentFilter,
doingAction = _createHooks.doingAction,
doingFilter = _createHooks.doingFilter,
didAction = _createHooks.didAction,
didFilter = _createHooks.didFilter,
build_module_actions = _createHooks.actions,
build_module_filters = _createHooks.filters;
/***/ })
/******/ });

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff