관리-도구
편집 파일: Init.php
<?php /** * Init the Kirki PRO's responsive package. * * @package kirki-pro-responsive * @since 1.0.0 */ namespace Kirki\Pro\Responsive; use Kirki\Pro\Field\Responsive; /** * Manage the responsive package. */ class Init { /** * Control types with horizontal layout. * * @var array */ private $horizontal_types = [ 'kirki-checkbox', 'kirki-toggle', 'kirki-react-colorful', ]; /** * The class constructor. */ public function __construct() { add_action( 'customize_register', [ $this, 'register_control_type' ] ); add_filter( 'kirki_control_types', [ $this, 'control_type' ] ); add_filter( 'kirki_field_exclude_init', array( $this, 'exclude_init' ), 99999, 4 ); add_action( 'kirki_field_custom_init', [ $this, 'field_init' ], 99999, 3 ); /** * We use 8 as the priority because we want this to run before "kirki_get_value" method * in wp-content/plugins/kirki-dev/packages/kirki-framework/data-option/src/Option.php file. */ add_filter( 'kirki_get_value', [ $this, 'kirki_get_value' ], 8, 4 ); } /** * Register control type. * * @param WP_Customize_Manager $wp_customize Instance of WP_Customize_Manager. */ public function register_control_type( $wp_customize ) { $wp_customize->register_control_type( '\Kirki\Pro\Control\Responsive' ); } /** * The control type. * * @param array $control_types The existing control types. */ public function control_type( $control_types ) { $control_types['kirki-responsive'] = 'Kirki\Pro\Control\Responsive'; return $control_types; } /** * Parse the "default" argument. * This method will format the "default" argument to contains the devices that wraps the default value. * * @since 1.0.0 * * @param array $args The field arguments. * @return array $args The modifiled field arguments. */ public function parse_default_arg( $args ) { $has_responsive_default = true; if ( isset( $args['default'] ) ) { if ( is_array( $args['default'] ) ) { if ( ! isset( $args['default']['desktop'] ) && ! isset( $args['default']['tablet'] ) && ! isset( $args['default']['mobile'] ) ) { $has_responsive_default = false; } } else { $has_responsive_default = false; } } if ( ! $has_responsive_default ) { if ( isset( $args['default'] ) ) { $args['default'] = array( 'desktop' => $args['default'], ); } else { $args['default'] = array( 'desktop' => '', ); } } return $args; } /** * Parse the output argument. * This method will format the "output" argument to modify the "media_query" based on the targetted device. * This method will be called inside of "default" argument loop when the control is using responsive mode. * * @since 1.0.0 * * @param array $args The field arguments. * @param string $device The targetted device. * * @return array $args The modified field arguments. */ public function parse_output_arg( $args, $device ) { if ( isset( $args['output'] ) && ! empty( $args['output'] ) ) { foreach ( $args['output'] as $index => $output ) { if ( isset( $output['media_query'] ) ) { if ( isset( $output['media_query'][ $device ] ) ) { $args['output'][ $index ]['media_query'] = $output['media_query'][ $device ]; } else { // If current device is not set in the "media_query", then the output won't work. unset( $args['output'][ $index ] ); } } else { // If "media_query" is not provided in the "output" arg, then the output won't work. unset( $args['output'][ $index ] ); } } } return $args; } /** * Exclude responsive field (field here means group of controls) from default field's init call. * * @see wp-content/plugins/kirki-dev/packages/kirki-framework/field/src/Field.php * @since 1.0.0 * * @param bool $condition The existing condition. * @param Object $field The field object. * @param array $args The field args. * * @return bool */ public function exclude_init( $condition, $field, $args ) { if ( isset( $args['responsive'] ) && $args['responsive'] ) { return true; } return $condition; } /** * Replace the default field init with custom init. * * @see wp-content/plugins/kirki-dev/packages/kirki-framework/field/src/Field.php * @since 1.0.0 * * @param Object $field The field object. * @param array $args The Kirki field args. * @param string $control_class The control class name if it exists. */ public function field_init( $field, $args, $control_class ) { // Stop if this field doesn't have the "responsive" argument. if ( ! isset( $args['responsive'] ) || ! $args['responsive'] ) { return; } $this->register_real_controls( $field, $args, $control_class ); } /** * Register the real controls. * * @since 1.0.0 * * @param Object $field The field object. * @param array $args The Kirki field args. * @param string $control_class The control class name if it exists. */ public function register_real_controls( $field, $args, $control_class = '' ) { $defaults = $this->parse_default_arg( $args ); $defaults = $defaults['default']; $defaults = array_reverse( $defaults ); $devices = []; $inside_horizontal_layout = property_exists( $field, 'type' ) && in_array( $field->type, $this->horizontal_types, true ) ? true : false; foreach ( $defaults as $device => $value ) { array_push( $devices, $device ); } $devices = array_reverse( $devices ); $devices_control_id = 'kirki_responsive__' . $args['settings']; $loop_count = 0; foreach ( $defaults as $device => $value ) { $loop_count++; if ( ! $inside_horizontal_layout && 1 === $loop_count ) { $this->add_devices_control( $devices_control_id, $args, $devices, $inside_horizontal_layout ); } $new_control_args = $args; $new_control_args['default'] = $value; $new_control_args['settings'] = $args['settings'] . '[' . $device . ']'; $new_control_args['device'] = $device; if ( ! isset( $new_control_args['wrapper_attrs'] ) ) { $new_control_args['wrapper_attrs'] = []; } $new_control_args['wrapper_attrs']['data-kirki-parent-responsive-id'] = $devices_control_id; $new_control_args['wrapper_attrs']['data-kirki-device-preview'] = $device; if ( isset( $new_control_args['label'] ) ) { unset( $new_control_args['label'] ); } if ( isset( $new_control_args['description'] ) ) { unset( $new_control_args['description'] ); } if ( isset( $new_control_args['responsive'] ) ) { unset( $new_control_args['responsive'] ); } $wrapper_class = ''; /** * If `$control_class` is empty, then we assume this is a "parent field" and not the "real controls". * A "parent field" here means: a parent of group of controls such as field-dimensions, field-typography, etc. */ if ( ! $control_class ) { $wrapper_class .= ' customize-control-kirki-hidden-field'; } if ( $inside_horizontal_layout ) { $wrapper_class .= ' customize-control-kirki-responsive-horizontal'; } if ( ! empty( $wrapper_class ) ) { if ( isset( $new_control_args['wrapper_attrs']['class'] ) ) { $new_control_args['wrapper_attrs']['class'] .= $wrapper_class; } else { $new_control_args['wrapper_attrs']['class'] = '{default_class}' . $wrapper_class; } } $new_control_args = $this->parse_output_arg( $new_control_args, $device ); $field_classname = get_class( $field ); new $field_classname( $new_control_args ); if ( $inside_horizontal_layout && count( $devices ) === $loop_count ) { $this->add_devices_control( $devices_control_id, $args, $devices, $inside_horizontal_layout ); } } } /** * Add devices control via $wp_customize. * * @param string $id The control's ID. * @param array $args The control arguments. * @param array $devices The specified devices. * @param bool $inside_horizontal_layout Whether or not this control is inside a horizontal layout. */ public function add_devices_control( $id, $args, $devices, $inside_horizontal_layout = false ) { unset( $args['responsive'] ); if ( isset( $args['default'] ) ) { unset( $args['default'] ); } if ( isset( $args['transport'] ) ) { unset( $args['transport'] ); } if ( isset( $args['output'] ) ) { unset( $args['output'] ); } if ( isset( $args['wrapper_attrs'] ) ) { if ( isset( $args['wrapper_attrs']['data-kirki-parent-responsive-id'] ) ) { unset( $args['wrapper_attrs']['data-kirki-parent-responsive-id'] ); } if ( isset( $args['wrapper_attrs']['data-kirki-device-preview'] ) ) { unset( $args['wrapper_attrs']['data-kirki-device-preview'] ); } } $args['settings'] = $id; $args['type'] = 'kirki-responsive'; if ( ! $inside_horizontal_layout ) { if ( ! isset( $args['wrapper_opts'] ) ) { $args['wrapper_opts'] = []; } $args['wrapper_opts']['gap'] = 'small'; } $args['choices'] = [ 'devices' => $devices, ]; new Responsive( $args ); } /** * Filter the value for responsive fields. * * @see wp-content/plugins/kirki-dev/packages/kirki-framework/data-option/src/Option.php * * @param mixed $value The field value. * @param string $field_name The field name. * @param mixed $default The default value. * @param string $type The option type (theme_mod or option). * * @return mixed The filtered value. */ public function kirki_get_value( $value = '', $field_name = '', $default = '', $type = 'theme_mod' ) { /** * The "option" will be handled by "kirki_get_value" method in * wp-content/plugins/kirki-dev/packages/kirki-framework/data-option/src/Option.php file. */ if ( 'option' === $type ) { return $value; } // If the field name doesn't contain a '[', then it's not a sub-item of another field. if ( false === strpos( $field_name, '[' ) ) { return $value; } // If this is not part of a responsive field, then return the value. if ( ! in_array( $field_name, Responsive::$sub_field_names, true ) ) { return $value; } /** * If we got here then this is part of an option array. * We need to get the 1st level, and then find the item inside that array. */ $parts = \explode( '[', $field_name ); $value = get_theme_mod( $parts[0], [] ); foreach ( $parts as $key => $part ) { /** * Skip the 1st item, it's already been dealt with * when we got the value initially right before this loop. */ if ( 0 === $key ) { continue; } $part = str_replace( ']', '', $part ); /** * If the item exists in the value, then change $value to the item. * This runs recursively for all parts until we get to the end. */ if ( is_array( $value ) && isset( $value[ $part ] ) ) { $value = $value[ $part ]; continue; } /** * If we got here, the item was not found in the value. * We need to change the value accordingly depending on whether * this is the last item in the loop or not. */ $value = ( isset( $parts[ $key + 1 ] ) ) ? [] : ''; } $value = empty( $value ) ? $default : $value; return $value; } }