Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
subversal
/
video
/
wp-content
/
plugins
/
atlas-core
/
framework
/
redux-core
/
inc
/
fields
/
typography
:
class-redux-typography.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * Typography Field * * @package ReduxFramework/Fields * @author Kevin Provance (kprovance) & Dovy Paukstys * @version 4.0.0 */ // Exit if accessed directly. defined( 'ABSPATH' ) || exit; if ( ! class_exists( 'Redux_Typography', false ) ) { /** * Class Redux_Typography */ class Redux_Typography extends Redux_Field { /** * Array of data for typography preview. * * @var array */ private $typography_preview = array(); /** * Standard font array. * * @var array $std_fonts */ private $std_fonts = array( 'Arial, Helvetica, sans-serif' => 'Arial, Helvetica, sans-serif', '\'Arial Black\', Gadget, sans-serif' => '\'Arial Black\', Gadget, sans-serif', '\'Bookman Old Style\', serif' => '\'Bookman Old Style\', serif', '\'Comic Sans MS\', cursive' => '\'Comic Sans MS\', cursive', 'Courier, monospace' => 'Courier, monospace', 'Garamond, serif' => 'Garamond, serif', 'Georgia, serif' => 'Georgia, serif', 'Impact, Charcoal, sans-serif' => 'Impact, Charcoal, sans-serif', '\'Lucida Console\', Monaco, monospace' => '\'Lucida Console\', Monaco, monospace', '\'Lucida Sans Unicode\', \'Lucida Grande\', sans-serif' => '\'Lucida Sans Unicode\', \'Lucida Grande\', sans-serif', '\'MS Sans Serif\', Geneva, sans-serif' => '\'MS Sans Serif\', Geneva, sans-serif', '\'MS Serif\', \'New York\', sans-serif' => '\'MS Serif\', \'New York\', sans-serif', '\'Palatino Linotype\', \'Book Antiqua\', Palatino, serif' => '\'Palatino Linotype\', \'Book Antiqua\', Palatino, serif', 'Tahoma,Geneva, sans-serif' => 'Tahoma, Geneva, sans-serif', '\'Times New Roman\', Times,serif' => '\'Times New Roman\', Times, serif', '\'Trebuchet MS\', Helvetica, sans-serif' => '\'Trebuchet MS\', Helvetica, sans-serif', 'Verdana, Geneva, sans-serif' => 'Verdana, Geneva, sans-serif', ); /** * Default font weights. * * @var string[] */ private $default_font_weights = array( '400' => 'Normal 400', '700' => 'Bold 700', '400italic' => 'Normal 400 Italic', '700italic' => 'Bold 700 Italic', ); /** * User font array. * * @var bool $user_fonts */ private $user_fonts = true; /** * Redux_Field constructor. * * @param array $field Field array. * @param string $value Field values. * @param null $redux ReduxFramework object pointer. * * @throws ReflectionException Exception. */ public function __construct( $field = array(), $value = null, $redux = null ) { // phpcs:ignore Generic.CodeAnalysis.UselessOverridingMethod parent::__construct( $field, $value, $redux ); $this->parent = $redux; $this->field = $field; $this->value = $value; $this->set_defaults(); $path_info = Redux_Helpers::path_info( __FILE__ ); $this->dir = trailingslashit( dirname( $path_info['real_path'] ) ); $this->url = trailingslashit( dirname( $path_info['url'] ) ); $this->timestamp = Redux_Core::$version; if ( $redux->args['dev_mode'] ) { $this->timestamp .= '.' . time(); } } /** * Sets default values for field. */ public function set_defaults() { // Shim out old arg to new. if ( isset( $this->field['all_styles'] ) && ! empty( $this->field['all_styles'] ) ) { $this->field['all-styles'] = $this->field['all_styles']; unset( $this->field['all_styles'] ); } $defaults = array( 'font-family' => true, 'font-size' => true, 'font-weight' => true, 'font-style' => true, 'font-backup' => false, 'subsets' => true, 'custom_fonts' => true, 'text-align' => true, 'text-transform' => false, 'font-variant' => false, 'text-decoration' => false, 'color' => true, 'preview' => true, 'line-height' => true, 'multi' => array( 'subsets' => false, 'weight' => false, ), 'word-spacing' => false, 'letter-spacing' => false, 'google' => true, 'font_family_clear' => true, 'allow_empty_line_height' => false, 'margin-top' => false, 'margin-bottom' => false, 'text-shadow' => false, 'word-spacing-unit' => '', 'letter-spacing-unit' => '', 'font-size-unit' => '', 'margin-top-unit' => '', 'margin-bottom-unit' => '', ); $this->field = wp_parse_args( $this->field, $defaults ); if ( isset( $this->field['color_alpha'] ) ) { if ( is_array( $this->field['color_alpha'] ) ) { $this->field['color_alpha']['color'] = $this->field['color_alpha']['color'] ?? false; $this->field['color_alpha']['shadow-color'] = $this->field['color_alpha']['shadow-color'] ?? false; } else { $mode = $this->field['color_alpha']; $this->field['color_alpha'] = array(); $this->field['color_alpha']['color'] = $mode; $this->field['color_alpha']['shadow-color'] = $mode; } } else { $this->field['color_alpha']['color'] = false; $this->field['color_alpha']['shadow-color'] = false; } // Set value defaults. $defaults = array( 'font-family' => '', 'font-options' => '', 'font-backup' => '', 'text-align' => '', 'text-transform' => '', 'font-variant' => '', 'text-decoration' => '', 'line-height' => '', 'word-spacing' => '', 'letter-spacing' => '', 'subsets' => '', 'google' => false, 'font-script' => '', 'font-weight' => '', 'font-style' => '', 'color' => '', 'font-size' => '', 'margin-top' => '', 'margin-bottom' => '', 'shadow-color' => '#000000', 'shadow-horizontal' => '1', 'shadow-vertical' => '1', 'shadow-blur' => '4', ); $this->value = wp_parse_args( $this->value, $defaults ); if ( empty( $this->field['units'] ) || ! in_array( $this->field['units'], Redux_Helpers::$array_units, true ) ) { $this->field['units'] = 'px'; } // Get the Google array. $this->get_google_array(); if ( empty( $this->field['fonts'] ) ) { $this->user_fonts = false; $this->field['fonts'] = $this->std_fonts; } $this->field['weights'] = $this->field['weights'] ?? $this->default_font_weights; // Localize std fonts. $this->localize_std_fonts(); } /** * Localize font array * * @param array $field Field array. * @param string $value Value. * * @return array */ public function localize( array $field, string $value = '' ): array { $params = array(); if ( true === $this->user_fonts && ! empty( $this->field['fonts'] ) ) { $params['std_font'] = $this->field['fonts']; } return $params; } /** * Field Render Function. * Takes the vars and outputs the HTML for the field in the settings * * @since ReduxFramework 1.0.0 */ public function render() { // Since fonts declared is CSS (@font-face) are not rendered in the preview, // they can be declared in a CSS file and passed here, so they DO display in // font preview. Do NOT pass style.css in your theme, as that will mess up // admin page styling. It's recommended to pass a CSS file with ONLY font // declarations. // If field is set and not blank, then enqueue field. if ( isset( $this->field['ext-font-css'] ) && '' !== $this->field['ext-font-css'] ) { wp_enqueue_style( 'redux-external-fonts', $this->field['ext-font-css'], array(), $this->timestamp ); } if ( empty( $this->field['units'] ) && ! empty( $this->field['default']['units'] ) ) { $this->field['units'] = $this->field['default']['units']; } $unit = $this->field['units']; echo '<div id="' . esc_attr( $this->field['id'] ) . '" class="redux-typography-container" data-id="' . esc_attr( $this->field['id'] ) . '" data-units="' . esc_attr( $unit ) . '">'; $this->select2_config['allowClear'] = true; if ( isset( $this->field['select2'] ) ) { $this->field['select2'] = wp_parse_args( $this->field['select2'], $this->select2_config ); } else { $this->field['select2'] = $this->select2_config; } $this->field['select2'] = Redux_Functions::sanitize_camel_case_array_keys( $this->field['select2'] ); $select2_data = Redux_Functions::create_data_string( $this->field['select2'] ); $google_set = false; $is_google_font = '0'; // If no fontFamily array exists, create one and set array 0 // with font value. if ( ! isset( $font_family ) ) { $font_family = array(); $font_family[0] = $this->value['font-family']; $font_family[1] = ''; } /* Font Family */ if ( true === $this->field['font-family'] ) { if ( filter_var( $this->value['google'], FILTER_VALIDATE_BOOLEAN ) ) { // Divide and conquer. $font_family = explode( ', ', $this->value['font-family'], 2 ); // If array 0 is empty and array 1 is not. if ( empty( $font_family[0] ) && ! empty( $font_family[1] ) ) { // Make array 0 = array 1. $font_family[0] = $font_family[1]; } } // Is selected font a Google font. if ( isset( $this->parent->fonts['google'][ $font_family[0] ] ) ) { $is_google_font = '1'; } // If not a Google font, show all font families. if ( '1' !== $is_google_font ) { $font_family[0] = $this->value['font-family']; } $user_fonts = '0'; if ( true === $this->user_fonts ) { $user_fonts = '1'; } echo '<input type="hidden" class="redux-typography-font-family ' . esc_attr( $this->field['class'] ) . '" data-user-fonts="' . esc_attr( $user_fonts ) . '" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-family]" value="' . esc_attr( $this->value['font-family'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '<input type="hidden" class="redux-typography-font-options ' . esc_attr( $this->field['class'] ) . '" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-options]" value="' . esc_attr( $this->value['font-options'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '<input type="hidden" class="redux-typography-google-font" value="' . esc_attr( $is_google_font ) . '" id="' . esc_attr( $this->field['id'] ) . '-google-font">'; echo '<div class="select_wrapper typography-family" style="width: 220px; margin-right: 5px;">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-family">' . esc_html__( 'Font Family', 'redux-framework' ) . '</label>'; $placeholder = esc_html__( 'Font family', 'redux-framework' ); $new_arr = $this->field['select2']; $new_arr['allow-clear'] = $this->field['font_family_clear']; $new_data = Redux_Functions::create_data_string( $new_arr ); echo '<select class=" redux-typography redux-typography-family select2-container ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '-family" data-placeholder="' . esc_attr( $placeholder ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" data-value="' . esc_attr( $font_family[0] ) . '"' . esc_html( $new_data ) . '>'; echo '</select>'; echo '</div>'; if ( true === $this->field['google'] ) { // Set a flag, so we know to set a header style or not. echo '<input type="hidden" class="redux-typography-google ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '-google" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[google]" type="text" value="' . esc_attr( $this->field['google'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; $google_set = true; } } /* Backup Font */ if ( true === $this->field['font-family'] && true === $this->field['google'] ) { if ( false === $google_set ) { // Set a flag, so we know to set a header style or not. echo '<input type="hidden" class="redux-typography-google ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '-google" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[google]" type="text" value="' . esc_attr( $this->field['google'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; } if ( true === $this->field['font-backup'] ) { echo '<div class="select_wrapper typography-family-backup" style="width: 220px; margin-right: 5px;">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-family-backup">' . esc_html__( 'Backup Font Family', 'redux-framework' ) . '</label>'; echo '<select data-placeholder="' . esc_html__( 'Backup Font Family', 'redux-framework' ) . '" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-backup]" class="redux-typography redux-typography-family-backup ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '-family-backup" data-id="' . esc_attr( $this->field['id'] ) . '" data-value="' . esc_attr( $this->value['font-backup'] ) . '"' . esc_attr( $select2_data ) . '>'; echo '<option data-google="false" data-details="" value=""></option>'; foreach ( $this->field['fonts'] as $i => $family ) { echo '<option data-google="true" value="' . esc_attr( $i ) . '" ' . selected( $this->value['font-backup'], $i, false ) . '>' . esc_html( $family ) . '</option>'; } echo '</select></div>'; } } /* Font Style/Weight */ if ( true === $this->field['font-style'] || true === $this->field['font-weight'] ) { echo '<div data-weights="' . rawurlencode( wp_json_encode( $this->field['weights'] ) ) . '" class="select_wrapper typography-style" original-title="' . esc_html__( 'Font style', 'redux-framework' ) . '">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '_style">' . esc_html__( 'Font Weight & Style', 'redux-framework' ) . '</label>'; $style = $this->value['font-weight'] . $this->value['font-style']; echo '<input type="hidden" class="typography-font-weight" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-weight]" value="' . esc_attr( $this->value['font-weight'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" /> '; echo '<input type="hidden" class="typography-font-style" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-style]" value="' . esc_attr( $this->value['font-style'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" /> '; $multi = ( isset( $this->field['multi']['weight'] ) && $this->field['multi']['weight'] ) ? ' multiple="multiple"' : ''; echo '<select' . esc_html( $multi ) . ' data-placeholder="' . esc_html__( 'Style', 'redux-framework' ) . '" class="redux-typography redux-typography-style select ' . esc_attr( $this->field['class'] ) . '" original-title="' . esc_html__( 'Font style', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '_style" data-id="' . esc_attr( $this->field['id'] ) . '" data-value="' . esc_attr( $style ) . '"' . esc_attr( $select2_data ) . '>'; if ( empty( $this->value['subsets'] ) || empty( $this->value['font-weight'] ) ) { echo '<option value=""></option>'; } echo '</select></div>'; } /* Font Script */ if ( true === $this->field['font-family'] && true === $this->field['subsets'] && true === $this->field['google'] ) { echo '<div class="select_wrapper typography-script tooltip" original-title="' . esc_html__( 'Font subsets', 'redux-framework' ) . '">'; echo '<input type="hidden" class="typography-subsets" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[subsets]" value="' . esc_attr( $this->value['subsets'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" /> '; echo '<label for="' . esc_attr( $this->field['id'] ) . '-subsets">' . esc_html__( 'Font Subsets', 'redux-framework' ) . '</label>'; $multi = ( isset( $this->field['multi']['subsets'] ) && $this->field['multi']['subsets'] ) ? ' multiple="multiple"' : ''; echo '<select' . esc_html( $multi ) . ' data-placeholder="' . esc_html__( 'Subsets', 'redux-framework' ) . '" class="redux-typography redux-typography-subsets ' . esc_attr( $this->field['class'] ) . '" original-title="' . esc_html__( 'Font script', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-subsets" data-value="' . esc_attr( $this->value['subsets'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>'; if ( empty( $this->value['subsets'] ) ) { echo '<option value=""></option>'; } echo '</select></div>'; } /* Font Align */ if ( true === $this->field['text-align'] ) { echo '<div class="select_wrapper typography-align tooltip" original-title="' . esc_html__( 'Text Align', 'redux-framework' ) . '">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-align">' . esc_html__( 'Text Align', 'redux-framework' ) . '</label>'; echo '<select data-placeholder="' . esc_html__( 'Text Align', 'redux-framework' ) . '" class="redux-typography redux-typography-align ' . esc_attr( $this->field['class'] ) . '" original-title="' . esc_html__( 'Text Align', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-align" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[text-align]" data-value="' . esc_attr( $this->value['text-align'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>'; echo '<option value=""></option>'; $align = array( esc_html__( 'inherit', 'redux-framework' ), esc_html__( 'left', 'redux-framework' ), esc_html__( 'right', 'redux-framework' ), esc_html__( 'center', 'redux-framework' ), esc_html__( 'justify', 'redux-framework' ), esc_html__( 'initial', 'redux-framework' ), ); foreach ( $align as $v ) { echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-align'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>'; } echo '</select></div>'; } /* Text Transform */ if ( true === $this->field['text-transform'] ) { echo '<div class="select_wrapper typography-transform tooltip" original-title="' . esc_html__( 'Text Transform', 'redux-framework' ) . '">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-transform">' . esc_html__( 'Text Transform', 'redux-framework' ) . '</label>'; echo '<select data-placeholder="' . esc_html__( 'Text Transform', 'redux-framework' ) . '" class="redux-typography redux-typography-transform ' . esc_attr( $this->field['class'] ) . '" original-title="' . esc_html__( 'Text Transform', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-transform" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[text-transform]" data-value="' . esc_attr( $this->value['text-transform'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>'; echo '<option value=""></option>'; $values = array( esc_html__( 'none', 'redux-framework' ), esc_html__( 'capitalize', 'redux-framework' ), esc_html__( 'uppercase', 'redux-framework' ), esc_html__( 'lowercase', 'redux-framework' ), esc_html__( 'initial', 'redux-framework' ), esc_html__( 'inherit', 'redux-framework' ), ); foreach ( $values as $v ) { echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-transform'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>'; } echo '</select></div>'; } /* Font Variant */ if ( true === $this->field['font-variant'] ) { echo '<div class="select_wrapper typography-font-variant tooltip" original-title="' . esc_html__( 'Font Variant', 'redux-framework' ) . '">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-font-variant">' . esc_html__( 'Font Variant', 'redux-framework' ) . '</label>'; echo '<select data-placeholder="' . esc_html__( 'Font Variant', 'redux-framework' ) . '" class="redux-typography redux-typography-font-variant ' . esc_attr( $this->field['class'] ) . '" original-title="' . esc_html__( 'Font Variant', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-font-variant" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-variant]" data-value="' . esc_attr( $this->value['font-variant'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>'; echo '<option value=""></option>'; $values = array( esc_html__( 'inherit', 'redux-framework' ), esc_html__( 'normal', 'redux-framework' ), esc_html__( 'small-caps', 'redux-framework' ), ); foreach ( $values as $v ) { echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['font-variant'], $v, false ) . '>' . esc_attr( ucfirst( $v ) ) . '</option>'; } echo '</select></div>'; } /* Text Decoration */ if ( true === $this->field['text-decoration'] ) { echo '<div class="select_wrapper typography-decoration tooltip" original-title="' . esc_html__( 'Text Decoration', 'redux-framework' ) . '">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-decoration">' . esc_html__( 'Text Decoration', 'redux-framework' ) . '</label>'; echo '<select data-placeholder="' . esc_html__( 'Text Decoration', 'redux-framework' ) . '" class="redux-typography redux-typography-decoration ' . esc_attr( $this->field['class'] ) . '" original-title="' . esc_html__( 'Text Decoration', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-decoration" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[text-decoration]" data-value="' . esc_attr( $this->value['text-decoration'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"' . esc_attr( $select2_data ) . '>'; echo '<option value=""></option>'; $values = array( esc_html__( 'none', 'redux-framework' ), esc_html__( 'inherit', 'redux-framework' ), esc_html__( 'underline', 'redux-framework' ), esc_html__( 'overline', 'redux-framework' ), esc_html__( 'line-through', 'redux-framework' ), esc_html__( 'blink', 'redux-framework' ), ); foreach ( $values as $v ) { echo '<option value="' . esc_attr( $v ) . '" ' . selected( $this->value['text-decoration'], $v, false ) . '>' . esc_html( ucfirst( $v ) ) . '</option>'; } echo '</select></div>'; } /* Font Size */ if ( true === $this->field['font-size'] ) { $the_unit = '' !== $this->field['font-size-unit'] ? $this->field['font-size-unit'] : $unit; echo '<div class="input_wrapper font-size redux-container-typography">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-size">' . esc_html__( 'Font Size', 'redux-framework' ) . '</label>'; echo '<div class="input-append">'; echo '<input type="text" class="span2 redux-typography redux-typography-size mini typography-input ' . esc_attr( $this->field['class'] ) . '" title="' . esc_html__( 'Font Size', 'redux-framework' ) . '" placeholder="' . esc_html__( 'Size', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-size" value="' . esc_attr( str_replace( Redux_Helpers::$array_units, '', $this->value['font-size'] ) ) . '" data-unit="' . esc_attr( $the_unit ) . '" data-value="' . esc_attr( str_replace( Redux_Helpers::$array_units, '', $this->value['font-size'] ) ) . '">'; echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>'; echo '</div>'; echo '<input type="hidden" class="typography-font-size" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[font-size]" value="' . esc_attr( $this->value['font-size'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"/>'; echo '</div>'; } /* Line Height */ if ( true === $this->field['line-height'] ) { $the_unit = $this->field['line-height-unit'] ?? $unit; echo '<div class="input_wrapper line-height redux-container-typography">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-height">' . esc_html__( 'Line Height', 'redux-framework' ) . '</label>'; echo '<div class="input-append">'; echo '<input type="text" class="span2 redux-typography redux-typography-height mini typography-input ' . esc_attr( $this->field['class'] ) . '" title="' . esc_html__( 'Line Height', 'redux-framework' ) . '" placeholder="' . esc_html__( 'Height', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-height" value="' . esc_attr( str_replace( Redux_Helpers::$array_units, '', $this->value['line-height'] ) ) . '" data-allow-empty="' . esc_attr( $this->field['allow_empty_line_height'] ) . '" data-unit="' . esc_attr( $the_unit ) . '" data-value="' . esc_attr( str_replace( Redux_Helpers::$array_units, '', $this->value['line-height'] ) ) . '">'; echo '<span class="add-on">' . esc_html( '' === $the_unit ? ' ' : $the_unit ) . '</span>'; echo '</div>'; echo '<input type="hidden" class="typography-line-height" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[line-height]" value="' . esc_attr( $this->value['line-height'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"/>'; echo '</div>'; } /* Word Spacing */ if ( true === $this->field['word-spacing'] ) { $the_unit = '' !== $this->field['word-spacing-unit'] ? $this->field['word-spacing-unit'] : $unit; echo '<div class="input_wrapper word-spacing redux-container-typography">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-word">' . esc_html__( 'Word Spacing', 'redux-framework' ) . '</label>'; echo '<div class="input-append">'; echo '<input type="text" class="span2 redux-typography redux-typography-word mini typography-input ' . esc_attr( $this->field['class'] ) . '" title="' . esc_html__( 'Word Spacing', 'redux-framework' ) . '" placeholder="' . esc_html__( 'Word Spacing', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-word" data-unit="' . esc_attr( $the_unit ) . '" value="' . esc_attr( str_replace( $the_unit, '', $this->value['word-spacing'] ) ) . '" data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['word-spacing'] ) ) . '">'; echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>'; echo '</div>'; echo '<input type="hidden" class="typography-word-spacing" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[word-spacing] " value="' . esc_attr( $this->value['word-spacing'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '"/>'; echo '</div>'; } /* Letter Spacing */ if ( true === $this->field['letter-spacing'] ) { $the_unit = '' !== $this->field['letter-spacing-unit'] ? $this->field['letter-spacing-unit'] : $unit; echo '<div class="input_wrapper letter-spacing redux-container-typography">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-letter">' . esc_html__( 'Letter Spacing', 'redux-framework' ) . '</label>'; echo '<div class="input-append">'; echo '<input type="text" class="span2 redux-typography redux-typography-letter mini typography-input ' . esc_attr( $this->field['class'] ) . '" title="' . esc_html__( 'Letter Spacing', 'redux-framework' ) . '" placeholder="' . esc_html__( 'Letter Spacing', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-letter" data-unit="' . esc_attr( $the_unit ) . '" value="' . esc_attr( str_replace( $the_unit, '', $this->value['letter-spacing'] ) ) . '" data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['letter-spacing'] ) ) . '">'; echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>'; echo '</div>'; echo '<input type="hidden" class="typography-letter-spacing" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[letter-spacing]" value="' . esc_attr( $this->value['letter-spacing'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '</div>'; } echo '<div class="clearfix"></div>'; // Margins. if ( $this->field['margin-top'] ) { $the_unit = '' !== $this->field['margin-top-unit'] ? $this->field['margin-top-unit'] : $unit; echo '<div class="input_wrapper margin-top redux-container-typography">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-margin-top">' . esc_html__( 'Margin Top', 'redux-framework' ) . '</label>'; echo '<div class="input-append">'; echo '<input type="text" class="span2 redux-typography redux-typography-margin-top mini typography-input ' . esc_attr( $this->field['class'] ) . '" title="' . esc_html__( 'Margin Top', 'redux-framework' ) . '" placeholder="' . esc_html__( 'Top', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-margin-top" data-unit="' . esc_attr( $the_unit ) . '" value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-top'] ) ) . '" data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-top'] ) ) . '">'; echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>'; echo '</div>'; echo '<input type="hidden" class="typography-margin-top" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[margin-top]" value="' . esc_attr( $this->value['margin-top'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '</div>'; } /* Bottom Margin */ if ( $this->field['margin-bottom'] ) { $the_unit = '' !== $this->field['margin-bottom-unit'] ? $this->field['margin-bottom-unit'] : $unit; echo '<div class="input_wrapper margin-bottom redux-container-typography">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-margin-bottom">' . esc_html__( 'Margin Bottom', 'redux-framework' ) . '</label>'; echo '<div class="input-append">'; echo '<input type="text" class="span2 redux-typography redux-typography-margin-bottom mini typography-input ' . esc_attr( $this->field['class'] ) . '" title="' . esc_html__( 'Margin Bottom', 'redux-framework' ) . '" placeholder="' . esc_html__( 'Bottom', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-margin-bottom" data-unit="' . esc_attr( $the_unit ) . '" value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-bottom'] ) ) . '" data-value="' . esc_attr( str_replace( $the_unit, '', $this->value['margin-bottom'] ) ) . '">'; echo '<span class="add-on">' . esc_html( $the_unit ) . '</span>'; echo '</div>'; echo '<input type="hidden" class="typography-margin-bottom" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[margin-bottom]" value="' . esc_attr( $this->value['margin-bottom'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '</div>'; } if ( $this->field['margin-top'] || $this->field['margin-bottom'] ) { echo '<div class="clearfix"></div>'; } /* Font Color */ if ( true === $this->field['color'] ) { $default = ''; if ( empty( $this->field['default']['color'] ) && ! empty( $this->field['color'] ) ) { $default = $this->value['color']; } elseif ( ! empty( $this->field['default']['color'] ) ) { $default = $this->field['default']['color']; } echo '<div class="picker-wrapper">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-color">' . esc_html__( 'Font Color', 'redux-framework' ) . '</label>'; echo '<div id="' . esc_attr( $this->field['id'] ) . '_color_picker" class="colorSelector typography-color">'; echo '<div style="background-color: ' . esc_attr( $this->value['color'] ) . '"></div>'; echo '</div>'; echo '<input '; echo 'data-default-color="' . esc_attr( $default ) . '"'; echo 'class="color-picker redux-color redux-typography-color ' . esc_attr( $this->field['class'] ) . '"'; echo 'original-title="' . esc_html__( 'Font color', 'redux-framework' ) . '"'; echo 'id="' . esc_attr( $this->field['id'] ) . '-color"'; echo 'name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[color]"'; echo 'type="text"'; echo 'value="' . esc_attr( $this->value['color'] ) . '"'; echo 'data-id="' . esc_attr( $this->field['id'] ) . '"'; $data = array( 'field' => $this->field, 'index' => 'color', ); echo Redux_Functions_Ex::output_alpha_data( $data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo '>'; echo '</div>'; } echo '<div class="clearfix"></div>'; /* Font Preview */ if ( ! isset( $this->field['preview'] ) || false !== $this->field['preview'] ) { $g_text = $this->field['preview']['text'] ?? '1 2 3 4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z'; $style = ''; if ( isset( $this->field['preview']['always_display'] ) ) { if ( true === filter_var( $this->field['preview']['always_display'], FILTER_VALIDATE_BOOLEAN ) ) { if ( true === (bool) $is_google_font ) { $this->typography_preview[ $font_family[0] ] = array( 'font-style' => array( $this->value['font-weight'] . $this->value['font-style'] ), 'subset' => array( $this->value['subsets'] ), ); wp_deregister_style( 'redux-typography-preview' ); wp_dequeue_style( 'redux-typography-preview' ); wp_enqueue_style( 'redux-typography-preview', $this->make_google_web_font_link( $this->typography_preview ), array(), $this->timestamp ); } $style = 'display: block; font-family: ' . esc_attr( $this->value['font-family'] ) . '; font-weight: ' . esc_attr( $this->value['font-weight'] ) . ';'; } } if ( isset( $this->field['preview']['font-size'] ) ) { $style .= 'font-size: ' . $this->field['preview']['font-size'] . ';'; $in_use = '1'; } else { $in_use = '0'; } // Filter to disable Google font updates. if ( apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/google_font_update", true ) ) { // phpcs:ignored WordPress.NamingConventions.ValidHookName if ( Redux_Helpers::google_fonts_update_needed() && ! get_option( 'auto_update_redux_google_fonts', false ) && $this->field['font-family'] && $this->field['google'] ) { $nonce = wp_create_nonce( 'redux_update_google_fonts' ); echo '<div data-nonce="' . esc_attr( $nonce ) . '" class="redux-update-google-fonts update-message notice inline notice-warning notice-alt">'; echo '<p>' . esc_html__( 'Your Google Fonts are out of date. To update them, please click one of the following:', 'redux-framework' ); echo ' <a href="#" class="update-google-fonts" data-action="automatic" aria-label="' . esc_attr__( 'Automated updates', 'redux-framework' ) . '">' . esc_html__( 'Automated updates', 'redux-framework' ) . '</a> ' . esc_html__( 'or', 'redux-framework' ) . ' <a href="#" class="update-google-fonts" data-action="manual" aria-label="' . esc_attr__( 'one-time update', 'redux-framework' ) . '">' . esc_html__( 'one-time update', 'redux-framework' ) . '</a>.'; echo '</p>'; echo '</div>'; } } echo '<p data-preview-size="' . esc_attr( $in_use ) . '" class="clear ' . esc_attr( $this->field['id'] ) . '_previewer typography-preview" style="' . esc_attr( $style ) . '">' . esc_html( $g_text ) . '</p>'; if ( $this->field['text-shadow'] ) { /* Shadow Colour */ echo '<div class="picker-wrapper">'; echo '<label for="' . esc_attr( $this->field['id'] ) . '-shadow-color">' . esc_html__( 'Shadow Color', 'redux-framework' ) . '</label>'; echo '<div id="' . esc_attr( $this->field['id'] ) . '_color_picker" class="colorSelector typography-shadow-color"><div style="background-color: ' . esc_attr( $this->value['color'] ) . '"></div></div>'; echo '<input data-default-color="' . esc_attr( $this->value['shadow-color'] ) . '" class="color-picker redux-color redux-typography-shadow-color ' . esc_attr( $this->field['class'] ) . '" original-title="' . esc_html__( 'Shadow color', 'redux-framework' ) . '" id="' . esc_attr( $this->field['id'] ) . '-shadow-color" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-color]" type="text" value="' . esc_attr( $this->value['shadow-color'] ) . '" data-alpha="' . esc_attr( $this->field['color_alpha']['shadow-color'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '</div>'; /* Shadow Horizontal Length */ echo '<div class="input_wrapper shadow-horizontal redux-container-typography" style="top:-60px;margin-left:20px;width:20%">'; echo '<div class="label">' . esc_html__( 'Horizontal', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-horizontal'] ) . 'px</strong></div>'; echo '<div class="redux-typography-slider span2 redux-typography redux-typography-shadow-horizontal mini typography-input ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '-h" data-min="-20" data-max="20" data-step="1" data-rtl="' . esc_attr( is_rtl() ) . '" data-label="' . esc_attr__( 'Horizontal', 'redux-framework' ) . '" data-default = "' . esc_attr( $this->value['shadow-horizontal'] ) . '"> </div>'; echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-h" class="typography-shadow-horizontal" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-horizontal]" value="' . esc_attr( $this->value['shadow-horizontal'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '</div>'; /* Shadow Vertical Length */ echo '<div class="input_wrapper shadow-vertical redux-container-typography" style="top:-60px;margin-left:20px;width:20%">'; echo '<div>' . esc_html__( 'Vertical', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-vertical'] ) . 'px</strong></div>'; echo '<div class="redux-typography-slider span2 redux-typography redux-typography-shadow-vertical mini typography-input ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '-v" data-min="-20" data-max="20" data-step="1" data-rtl="' . esc_attr( is_rtl() ) . '" data-label="' . esc_attr__( 'Vertical', 'redux-framework' ) . '" data-default = "' . esc_attr( $this->value['shadow-vertical'] ) . '"> </div>'; echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-v" class="typography-shadow-vertical" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-vertical]" value="' . esc_attr( $this->value['shadow-vertical'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '</div>'; /* Shadow Blur */ echo '<div class="input_wrapper shadow-blur redux-container-typography" style="top:-60px;margin-left:20px;width:20%">'; echo '<div>' . esc_html__( 'Blur', 'redux-framework' ) . ': <strong>' . esc_attr( $this->value['shadow-blur'] ) . 'px</strong></div>'; echo '<div class="redux-typography-slider span2 redux-typography redux-typography-shadow-blur mini typography-input ' . esc_attr( $this->field['class'] ) . '" id="' . esc_attr( $this->field['id'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '-b" data-min="0" data-max="25" data-step="1" data-rtl="' . esc_attr( is_rtl() ) . '" data-label="' . esc_attr__( 'Blur', 'redux-framework' ) . '" data-default = "' . esc_attr( $this->value['shadow-blur'] ) . '"> </div>'; echo '<input type="hidden" id="redux-slider-value-' . esc_attr( $this->field['id'] ) . '-b" class="typography-shadow-blur" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '[shadow-blur]" value="' . esc_attr( $this->value['shadow-blur'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" />'; echo '</div>'; } echo '</div>'; // end typography container. } } /** * Enqueue for every field instance. */ public function always_enqueue() { $min = Redux_Functions::is_min(); if ( isset( $this->field['color_alpha'] ) && is_array( $this->field['color_alpha'] ) ) { if ( $this->field['color_alpha']['color'] || $this->field['color_alpha']['shadow-color'] ) { wp_enqueue_script( 'redux-wp-color-picker-alpha' ); } } if ( ! wp_style_is( 'redux-nouislider' ) && isset( $this->field['text-shadow'] ) && $this->field['text-shadow'] ) { wp_enqueue_style( 'redux-nouislider', Redux_Core::$url . "assets/css/vendor/nouislider$min.css", array(), '5.0.0' ); wp_enqueue_script( 'redux-nouislider', Redux_Core::$url . "assets/js/vendor/nouislider/redux.jquery.nouislider$min.js", array( 'jquery' ), '5.0.0', true ); } } /** * Enqueue Function. * If this field requires any scripts, or CSS define this function and register/enqueue the scripts/css * * @since ReduxFramework 1.0.0 */ public function enqueue() { $min = Redux_Functions::is_min(); if ( ! wp_style_is( 'select2-css' ) ) { wp_enqueue_style( 'select2-css' ); } if ( ! wp_style_is( 'wp-color-picker' ) ) { wp_enqueue_style( 'wp-color-picker' ); } wp_enqueue_script( 'redux-webfont', '//' . 'ajax' . '.googleapis' . '.com/ajax/libs/webfont/1.6.26/webfont.js', // phpcs:ignore Generic.Strings.UnnecessaryStringConcat array(), '1.6.26', true ); $dep_array = array( 'jquery', 'wp-color-picker', 'select2-js', 'redux-js', 'redux-webfont' ); wp_enqueue_script( 'redux-field-typography', Redux_Core::$url . "inc/fields/typography/redux-typography$min.js", $dep_array, $this->timestamp, true ); wp_localize_script( 'redux-field-typography', 'redux_typography_ajax', array( 'ajaxurl' => esc_url( admin_url( 'admin-ajax.php' ) ), 'update_google_fonts' => array( 'updating' => esc_html__( 'Downloading Google Fonts...', 'redux-framework' ), // translators: Aria title, link title. 'error' => sprintf( esc_html__( 'Update Failed|msg. %1$s', 'redux-framework' ), sprintf( '<a href="#" class="update-google-fonts" data-action="manual" aria-label="%s">%s</a>', esc_html__( 'Retry?', 'redux-framework' ), esc_html__( 'Retry?', 'redux-framework' ) ) ), // translators: Javascript reload command, link title. 'success' => sprintf( esc_html__( 'Updated! %1$s to start using your updated fonts.', 'redux-framework' ), sprintf( '<a href="%1$s">%2$s</a>', 'javascript:location.reload();', esc_html__( 'Reload the page', 'redux-framework' ) ) ), ), ) ); if ( $this->parent->args['dev_mode'] ) { wp_enqueue_style( 'redux-color-picker' ); wp_enqueue_style( 'redux-field-typography', Redux_Core::$url . 'inc/fields/typography/redux-typography.css', array(), $this->timestamp ); } } /** * Make_google_web_font_link Function. * Creates the Google fonts link. * * @param array $fonts Array of google fonts. * * @return string * * @since ReduxFramework 3.0.0 */ public function make_google_web_font_link( array $fonts ): string { $link = ''; $subsets = array(); foreach ( $fonts as $family => $font ) { if ( ! empty( $link ) ) { $link .= '|'; // Append a new font to the string. } $link .= $family; if ( ! empty( $font['font-style'] ) || ! empty( $font['all-styles'] ) ) { $link .= ':'; if ( ! empty( $font['all-styles'] ) ) { $link .= implode( ',', $font['all-styles'] ); } elseif ( ! empty( $font['font-style'] ) ) { $link .= implode( ',', $font['font-style'] ); } } if ( ! empty( $font['subset'] ) || ! empty( $font['all-subsets'] ) ) { if ( ! empty( $font['all-subsets'] ) ) { foreach ( $font['all-subsets'] as $subset ) { if ( ! in_array( $subset, $subsets, true ) ) { $subsets[] = $subset; } } } elseif ( ! empty( $font['subset'] ) ) { foreach ( $font['subset'] as $subset ) { if ( ! in_array( $subset, $subsets, true ) ) { $subsets[] = $subset; } } } } } if ( ! empty( $subsets ) ) { $link .= '&subset=' . implode( ',', $subsets ); } $link .= '&display=' . $this->parent->args['font_display']; // return 'https://fonts.bunny.net/css?family=' . $link; return 'https://fonts.googleapis.com/css?family=' . $link; } /** * Make_google_web_font_string Function. * Creates the Google fonts link. * * @param array $fonts Array of Google fonts. * * @return string * * @since ReduxFramework 3.1.8 */ public function make_google_web_font_string( array $fonts ): string { $link = ''; $subsets = array(); foreach ( $fonts as $family => $font ) { if ( ! empty( $link ) ) { $link .= "', '"; // Append a new font to the string. } $link .= $family; if ( ! empty( $font['font-style'] ) || ! empty( $font['all-styles'] ) ) { $link .= ':'; if ( ! empty( $font['all-styles'] ) ) { $link .= implode( ',', $font['all-styles'] ); } elseif ( ! empty( $font['font-style'] ) ) { $link .= implode( ',', $font['font-style'] ); } } if ( ! empty( $font['subset'] ) || ! empty( $font['all-subsets'] ) ) { if ( ! empty( $font['all-subsets'] ) ) { foreach ( $font['all-subsets'] as $subset ) { if ( ! in_array( $subset, $subsets, true ) && ! is_numeric( $subset ) ) { $subsets[] = $subset; } } } elseif ( ! empty( $font['subset'] ) ) { foreach ( $font['subset'] as $subset ) { if ( ! in_array( $subset, $subsets, true ) && ! is_numeric( $subset ) ) { $subsets[] = $subset; } } } } } if ( ! empty( $subsets ) ) { $link .= '&subset=' . implode( ',', $subsets ); } return "'" . $link . "'"; } /** * Compiles field CSS for output. * * @param array $data Array of data to process. * * @return string */ public function css_style( $data ): string { $style = ''; $font = $data; // Shim out old arg to new. if ( isset( $this->field['all_styles'] ) && ! empty( $this->field['all_styles'] ) ) { $this->field['all-styles'] = $this->field['all_styles']; unset( $this->field['all_styles'] ); } // Check for font-backup. If it's set, stick it on a variable for // later use. if ( ! empty( $font['font-family'] ) && ! empty( $font['font-backup'] ) ) { $font['font-family'] = str_replace( ', ' . $font['font-backup'], '', $font['font-family'] ); $font_backup = ',' . $font['font-backup']; } $font_value_set = false; if ( ! empty( $font ) ) { foreach ( $font as $key => $value ) { if ( ! empty( $value ) && in_array( $key, array( 'font-family', 'font-weight' ), true ) ) { $font_value_set = true; } } } if ( ! empty( $font ) ) { foreach ( $font as $key => $value ) { if ( 'font-options' === $key ) { continue; } // Check for font-family key. if ( 'font-family' === $key ) { // Enclose font family in quotes if spaces are in the // name. This is necessary because if there are numerics // in the font name, they will not render properly. // Google should know better. if ( strpos( $value, ' ' ) && ! strpos( $value, ',' ) ) { $value = '"' . $value . '"'; } // Ensure fontBackup isn't empty. We already option // checked this earlier. No need to do it again. if ( ! empty( $font_backup ) ) { // Apply the backup font to the font-family element // via the saved variable. We do this here, so it // doesn't get appended to the Google stuff below. $value .= $font_backup; } } if ( empty( $value ) && in_array( $key, array( 'font-weight', 'font-style', ), true ) && true === $font_value_set ) { $value = 'normal'; } if ( 'font-weight' === $key && false === $this->field['font-weight'] ) { continue; } if ( 'font-style' === $key && false === $this->field['font-style'] ) { continue; } if ( 'google' === $key || 'subsets' === $key || 'font-backup' === $key || empty( $value ) ) { continue; } if ( isset( $data['key'] ) ) { return $data; } $continue = false; if ( 'shadow-horizontal' === $key || 'shadow-vertical' === $key || 'shadow-blur' === $key ) { $continue = true; } if ( 'shadow-color' === $key ) { if ( $this->field['text-shadow'] ) { $key = 'text-shadow'; $value = $data['shadow-horizontal'] . 'px ' . $data['shadow-vertical'] . 'px ' . $data['shadow-blur'] . 'px ' . $data['shadow-color']; } else { $continue = true; } } if ( $continue ) { continue; } $style .= $key . ':' . $value . ';'; } } return $style; } /** * CSS Output to send to the page. * * @param string|null|array $style CSS styles. */ public function output( $style = '' ) { $font = $this->value; if ( '' !== $style ) { if ( ! empty( $this->field['output'] ) && ! is_array( $this->field['output'] ) ) { $this->field['output'] = array( $this->field['output'] ); } if ( ! empty( $this->field['output'] ) && is_array( $this->field['output'] ) ) { $keys = implode( ',', $this->field['output'] ); $this->parent->outputCSS .= $keys . '{' . $style . '}'; } if ( ! empty( $this->field['compiler'] ) && ! is_array( $this->field['compiler'] ) ) { $this->field['compiler'] = array( $this->field['compiler'] ); } if ( ! empty( $this->field['compiler'] ) && is_array( $this->field['compiler'] ) ) { $keys = implode( ',', $this->field['compiler'] ); $this->parent->compilerCSS .= $keys . '{' . $style . '}'; } } $this->set_google_fonts( (array) $font ); } /** * Set global Google font data for global pointer. * * @param array $font Array of font data. */ private function set_google_fonts( array $font ) { // Google only stuff! if ( ! empty( $font['font-family'] ) && ! empty( $this->field['google'] ) && filter_var( $this->field['google'], FILTER_VALIDATE_BOOLEAN ) ) { // Added standard font matching check to avoid output to Google fonts call - kp // If no custom font array was supplied, then load it with default // standard fonts. if ( empty( $this->field['fonts'] ) ) { $this->field['fonts'] = $this->std_fonts; } // Ensure the fonts array is NOT empty. if ( ! empty( $this->field['fonts'] ) ) { // Make the font keys in the array lowercase, for case-insensitive matching. $lc_fonts = array_change_key_case( $this->field['fonts'] ); // Rebuild font array with all keys stripped of spaces. $arr = array(); foreach ( $lc_fonts as $key => $value ) { $key = str_replace( ', ', ',', $key ); $arr[ $key ] = $value; } if ( is_array( $this->field['custom_fonts'] ) ) { $lc_fonts = array_change_key_case( $this->field['custom_fonts'] ); foreach ( $lc_fonts as $font_arr ) { foreach ( $font_arr as $key => $value ) { $arr[ Redux_Core::strtolower( $key ) ] = $key; } } } $lc_fonts = $arr; unset( $arr ); // lowercase chosen font for matching purposes. $lc_font = Redux_Core::strtolower( $font['font-family'] ); // Remove spaces after commas in chosen font for matching purposes. $lc_font = str_replace( ', ', ',', $lc_font ); // If the lower cased passed font-family is NOT found in the standard font array // Then it's a Google font, so process it for output. if ( ! array_key_exists( $lc_font, $lc_fonts ) ) { $family = $font['font-family']; // TODO: This method doesn't respect spaces after commas, hence the reason // Strip out spaces in font names and replace with with plus signs // for the std_font array keys having no spaces after commas. This could be // fixed with RegEx in the future. $font['font-family'] = str_replace( ' ', '+', $font['font-family'] ); // Push data to parent typography variable. if ( empty( $this->parent->typography[ $font['font-family'] ] ) ) { $this->parent->typography[ $font['font-family'] ] = array(); } if ( isset( $this->field['all-styles'] ) || isset( $this->field['all-subsets'] ) ) { if ( empty( $font['font-options'] ) ) { $this->get_google_array(); if ( isset( $this->parent->google_array ) && ! empty( $this->parent->google_array ) && isset( $this->parent->google_array[ $family ] ) ) { $font['font-options'] = $this->parent->google_array[ $family ]; } } else { $font['font-options'] = json_decode( $font['font-options'], true ); } } if ( isset( $font['font-options'] ) && ! empty( $font['font-options'] ) && isset( $this->field['all-styles'] ) && filter_var( $this->field['all-styles'], FILTER_VALIDATE_BOOLEAN ) ) { if ( ! empty( $font['font-options']['variants'] ) ) { if ( ! isset( $this->parent->typography[ $font['font-family'] ]['all-styles'] ) || empty( $this->parent->typography[ $font['font-family'] ]['all-styles'] ) ) { $this->parent->typography[ $font['font-family'] ]['all-styles'] = array(); foreach ( $font['font-options']['variants'] as $variant ) { $this->parent->typography[ $font['font-family'] ]['all-styles'][] = $variant['id']; } } } } if ( isset( $font['font-options'] ) && ! empty( $font['font-options'] ) && isset( $this->field['all-subsets'] ) && $this->field['all-styles'] ) { if ( ! empty( $font['font-options']['subsets'] ) ) { if ( ! isset( $this->parent->typography[ $font['font-family'] ]['all-subsets'] ) || empty( $this->parent->typography[ $font['font-family'] ]['all-subsets'] ) ) { $this->parent->typography[ $font['font-family'] ]['all-subsets'] = array(); foreach ( $font['font-options']['subsets'] as $variant ) { $this->parent->typography[ $font['font-family'] ]['all-subsets'][] = $variant['id']; } } } } $style = ''; if ( ! empty( $font['font-weight'] ) ) { if ( empty( $this->parent->typography[ $font['font-family'] ]['font-weight'] ) || ! in_array( $font['font-weight'], $this->parent->typography[ $font['font-family'] ]['font-weight'], true ) ) { $style = $font['font-weight']; } if ( ! empty( $font['font-style'] ) ) { $style .= $font['font-style']; } if ( empty( $this->parent->typography[ $font['font-family'] ]['font-style'] ) || ! in_array( $style, $this->parent->typography[ $font['font-family'] ]['font-style'], true ) ) { $this->parent->typography[ $font['font-family'] ]['font-style'][] = $style; } } if ( ! empty( $font['subsets'] ) ) { if ( empty( $this->parent->typography[ $font['font-family'] ]['subset'] ) || ! in_array( $font['subsets'], $this->parent->typography[ $font['font-family'] ]['subset'], true ) ) { $this->parent->typography[ $font['font-family'] ]['subset'][] = $font['subsets']; } } } } } } /** * Localize standard, custom and typekit fonts. */ private function localize_std_fonts() { if ( false === $this->user_fonts ) { if ( isset( $this->parent->fonts['std'] ) && ! empty( $this->parent->fonts['std'] ) ) { return; } $this->parent->font_groups['std'] = array( 'text' => esc_html__( 'Standard Fonts', 'redux-framework' ), 'children' => array(), ); foreach ( $this->field['fonts'] as $font => $extra ) { $this->parent->font_groups['std']['children'][] = array( 'id' => $font, 'text' => $font, 'data-google' => 'false', ); } } if ( false !== $this->field['custom_fonts'] ) { // phpcs:ignored WordPress.NamingConventions.ValidHookName $this->field['custom_fonts'] = apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/custom_fonts", array() ); if ( ! empty( $this->field['custom_fonts'] ) ) { foreach ( $this->field['custom_fonts'] as $group => $fonts ) { $this->parent->font_groups['customfonts'] = array( 'text' => $group, 'children' => array(), ); foreach ( $fonts as $family => $v ) { $this->parent->font_groups['customfonts']['children'][] = array( 'id' => $family, 'text' => $family, 'data-google' => 'false', ); } } } } // Typekit. // phpcs:ignored WordPress.NamingConventions.ValidHookName $typekit_fonts = apply_filters( "redux/{$this->parent->args['opt_name']}/field/typography/typekit_fonts", array() ); if ( ! empty( $typekit_fonts ) ) { foreach ( $typekit_fonts as $group => $fonts ) { $this->parent->font_groups['typekitfonts'] = array( 'text' => $group, 'children' => array(), ); foreach ( $fonts as $family => $v ) { $this->parent->font_groups['typekitfonts']['children'][] = array( 'text' => $family, 'id' => $family, 'data-google' => 'false', ); } } } } /** * Construct the Google array from the stored JSON/HTML */ private function get_google_array() { if ( ( isset( $this->parent->fonts['google'] ) && ! empty( $this->parent->fonts['google'] ) ) || isset( $this->parent->fonts['google'] ) && false === $this->parent->fonts['google'] ) { return; } $fonts = Redux_Helpers::google_fonts_array( get_option( 'auto_update_redux_google_fonts', false ) ); if ( empty( $fonts ) ) { $google_font = __DIR__ . '/googlefonts.php'; $fonts = include $google_font; } if ( true === $fonts ) { $this->parent->fonts['google'] = false; return; } if ( isset( $fonts ) && ! empty( $fonts ) && is_array( $fonts ) ) { $this->parent->fonts['google'] = $fonts; $this->parent->google_array = $fonts; // optgroup. $this->parent->font_groups['google'] = array( 'text' => esc_html__( 'Google Webfonts', 'redux-framework' ), 'children' => array(), ); // options. foreach ( $this->parent->fonts['google'] as $font => $extra ) { $this->parent->font_groups['google']['children'][] = array( 'id' => $font, 'text' => $font, 'data-google' => 'true', ); } } } /** * Clean up the Google Webfonts subsets to be human-readable * * @param array $var Font subset array. * * @return array * * @since ReduxFramework 0.2.0 */ private function get_subsets( array $var ): array { $result = array(); foreach ( $var as $v ) { if ( strpos( $v, '-ext' ) ) { $name = ucfirst( str_replace( '-ext', ' Extended', $v ) ); } else { $name = ucfirst( $v ); } $result[] = array( 'id' => $v, 'name' => $name, ); } return array_filter( $result ); } /** * Clean up the Google Webfonts variants to be human-readable * * @param array $var Font variant array. * * @return array * * @since ReduxFramework 0.2.0 */ private function get_variants( array $var ): array { $result = array(); $italic = array(); foreach ( $var as $v ) { $name = ''; if ( 1 === $v[0] ) { $name = 'Ultra-Light 100'; } elseif ( 2 === $v[0] ) { $name = 'Light 200'; } elseif ( 3 === $v[0] ) { $name = 'Book 300'; } elseif ( 4 === $v[0] || 'r' === $v[0] || 'i' === $v[0] ) { $name = 'Normal 400'; } elseif ( 5 === $v[0] ) { $name = 'Medium 500'; } elseif ( 6 === $v[0] ) { $name = 'Semi-Bold 600'; } elseif ( 7 === $v[0] ) { $name = 'Bold 700'; } elseif ( 8 === $v[0] ) { $name = 'Extra-Bold 800'; } elseif ( 9 === $v[0] ) { $name = 'Ultra-Bold 900'; } if ( 'regular' === $v ) { $v = '400'; } if ( strpos( $v, 'italic' ) || 'italic' === $v ) { $name .= ' Italic'; $name = trim( $name ); if ( 'italic' === $v ) { $v = '400italic'; } $italic[] = array( 'id' => $v, 'name' => $name, ); } else { $result[] = array( 'id' => $v, 'name' => $name, ); } } foreach ( $italic as $item ) { $result[] = $item; } return array_filter( $result ); } /** * Update google font array via AJAX call. */ public function google_fonts_update_ajax() { if ( ! isset( $_POST['nonce'] ) || ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'redux_update_google_fonts' ) ) ) { die( 'Security check' ); } if ( isset( $_POST['data'] ) && 'automatic' === $_POST['data'] ) { update_option( 'auto_update_redux_google_fonts', true ); } $fonts = Redux_Helpers::google_fonts_array( true ); if ( ! empty( $fonts ) && ! is_wp_error( $fonts ) ) { echo wp_json_encode( array( 'status' => 'success', 'fonts' => $fonts, ) ); } else { $err_msg = ''; if ( is_wp_error( $fonts ) ) { $err_msg = $fonts->get_error_code(); } echo wp_json_encode( array( 'status' => 'error', 'error' => $err_msg, ) ); } die(); } /** * Enable output_variables to be generated. * * @since 4.0.3 * @return void */ public function output_variables() { // No code needed, just defining the method is enough. } } } if ( ! class_exists( 'ReduxFramework_Typography' ) ) { class_alias( 'Redux_Typography', 'ReduxFramework_Typography' ); }