ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-kirki-fonts-google.php (9528B)


      1 <?php
      2 /**
      3  * Processes typography-related fields
      4  * and generates the google-font link.
      5  *
      6  * @package     Kirki
      7  * @category    Core
      8  * @author      Aristeides Stathopoulos
      9  * @copyright   Copyright (c) 2016, Aristeides Stathopoulos
     10  * @license     http://opensource.org/licenses/https://opensource.org/licenses/MIT
     11  * @since       1.0
     12  */
     13 
     14 if ( ! class_exists( 'Kirki_Fonts_Google' ) ) {
     15 
     16 	/**
     17 	 * Manages the way Google Fonts are enqueued.
     18 	 */
     19 	final class Kirki_Fonts_Google {
     20 
     21 		/**
     22 		 * The Kirki_Fonts_Google instance.
     23 		 * We use the singleton pattern here to avoid loading the google-font array multiple times.
     24 		 * This is mostly a performance tweak.
     25 		 *
     26 		 * @access private
     27 		 * @var null|object
     28 		 */
     29 		private static $instance = null;
     30 
     31 		/**
     32 		 * If set to true, forces loading ALL variants.
     33 		 *
     34 		 * @static
     35 		 * @access public
     36 		 * @var bool
     37 		 */
     38 		public static $force_load_all_variants = false;
     39 
     40 		/**
     41 		 * If set to true, forces loading ALL subsets.
     42 		 *
     43 		 * @static
     44 		 * @access public
     45 		 * @var bool
     46 		 */
     47 		public static $force_load_all_subsets = false;
     48 
     49 		/**
     50 		 * The array of fonts
     51 		 *
     52 		 * @access private
     53 		 * @var array
     54 		 */
     55 		private $fonts = array();
     56 
     57 		/**
     58 		 * An array of all google fonts.
     59 		 *
     60 		 * @access private
     61 		 * @var array
     62 		 */
     63 		private $google_fonts = array();
     64 
     65 		/**
     66 		 * The array of subsets
     67 		 *
     68 		 * @access private
     69 		 * @var array
     70 		 */
     71 		private $subsets = array();
     72 
     73 		/**
     74 		 * The google link
     75 		 *
     76 		 * @access private
     77 		 * @var string
     78 		 */
     79 		private $link = '';
     80 
     81 		/**
     82 		 * The class constructor.
     83 		 */
     84 		private function __construct() {
     85 
     86 			$config = apply_filters( 'kirki/config', array() );
     87 
     88 			// If we have set $config['disable_google_fonts'] to true then do not proceed any further.
     89 			if ( isset( $config['disable_google_fonts'] ) && true === $config['disable_google_fonts'] ) {
     90 				return;
     91 			}
     92 
     93 			// Populate the array of google fonts.
     94 			$this->google_fonts = Kirki_Fonts::get_google_fonts();
     95 
     96 			// Enqueue link.
     97 			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ), 105 );
     98 
     99 		}
    100 
    101 		/**
    102 		 * Get the one, true instance of this class.
    103 		 * Prevents performance issues since this is only loaded once.
    104 		 *
    105 		 * @return object Kirki_Fonts_Google
    106 		 */
    107 		public static function get_instance() {
    108 			if ( null === self::$instance ) {
    109 				self::$instance = new Kirki_Fonts_Google();
    110 			}
    111 			return self::$instance;
    112 		}
    113 
    114 		/**
    115 		 * Calls all the other necessary methods to populate and create the link.
    116 		 */
    117 		public function enqueue() {
    118             if (apply_filters('kirki_skip_fonts_enqueue', false)) {
    119                 return;
    120             }
    121 
    122 			// Go through our fields and populate $this->fonts.
    123 			$this->loop_fields();
    124 
    125 			$this->fonts = apply_filters( 'kirki/enqueue_google_fonts', $this->fonts );
    126 
    127 			// Goes through $this->fonts and adds or removes things as needed.
    128 			$this->process_fonts();
    129 
    130 			// Go through $this->fonts and populate $this->link.
    131 			$this->create_link();
    132 
    133 			// If $this->link is not empty then enqueue it.
    134 			if ( '' !== $this->link ) {
    135 				wp_enqueue_style( 'kirki_google_fonts', $this->link, array(), null );
    136 			}
    137 		}
    138 
    139 		/**
    140 		 * Goes through all our fields and then populates the $this->fonts property.
    141 		 */
    142 		private function loop_fields() {
    143 			foreach ( Kirki::$fields as $field_id => $args ) {
    144 				$this->generate_google_font( $args );
    145 			}
    146 		}
    147 
    148 		/**
    149 		 * Processes the arguments of a field
    150 		 * determines if it's a typography field
    151 		 * and if it is, then takes appropriate actions.
    152 		 *
    153 		 * @param array $args The field arguments.
    154 		 */
    155 		private function generate_google_font( $args ) {
    156 
    157 			// Process typography fields.
    158 			if ( isset( $args['type'] ) && 'kirki-typography' === $args['type'] ) {
    159 
    160 				// Get the value.
    161 				$value = Kirki_Values::get_sanitized_field_value( $args );
    162 
    163 				// If we don't have a font-family then we can skip this.
    164 				if ( ! isset( $value['font-family'] ) ) {
    165 					return;
    166 				}
    167 
    168 				// Add support for older formats of the typography control.
    169 				// We used to have font-weight instead of variant.
    170 				if ( isset( $value['font-weight'] ) && ( ! isset( $value['variant'] ) || empty( $value['variant'] ) ) ) {
    171 					$value['variant'] = $value['font-weight'];
    172 				}
    173 
    174 				// Set a default value for variants.
    175 				if ( ! isset( $value['variant'] ) ) {
    176 					$value['variant'] = 'regular';
    177 				}
    178 				if ( isset( $value['subsets'] ) ) {
    179 
    180 					// Add the subset directly to the array of subsets in the Kirki_GoogleFonts_Manager object.
    181 					// Subsets must be applied to ALL fonts if possible.
    182 					if ( ! is_array( $value['subsets'] ) ) {
    183 						$this->subsets[] = $value['subsets'];
    184 					} else {
    185 						foreach ( $value['subsets'] as $subset ) {
    186 							$this->subsets[] = $subset;
    187 						}
    188 					}
    189 				}
    190 
    191 				// Add the requested google-font.
    192 				if ( ! isset( $this->fonts[ $value['font-family'] ] ) ) {
    193 					$this->fonts[ $value['font-family'] ] = array();
    194 				}
    195 				if ( ! in_array( $value['variant'], $this->fonts[ $value['font-family'] ], true ) ) {
    196 					$this->fonts[ $value['font-family'] ][] = $value['variant'];
    197 				}
    198 			} else {
    199 
    200 				// Process non-typography fields.
    201 				if ( isset( $args['output'] ) && is_array( $args['output'] ) ) {
    202 					foreach ( $args['output'] as $output ) {
    203 
    204 						// If we don't have a typography-related output argument we can skip this.
    205 						if ( ! isset( $output['property'] ) || ! in_array( $output['property'], array( 'font-family', 'font-weight', 'font-subset', 'subset', 'subsets' ), true ) ) {
    206 							continue;
    207 						}
    208 
    209 						// Get the value.
    210 						$value = Kirki_Values::get_sanitized_field_value( $args );
    211 
    212 						if ( 'font-family' === $output['property'] ) {
    213 							if ( ! array_key_exists( $value, $this->fonts ) ) {
    214 								$this->fonts[ $value ] = array();
    215 							}
    216 						} elseif ( 'font-weight' === $output['property'] ) {
    217 							foreach ( $this->fonts as $font => $variants ) {
    218 								if ( ! in_array( $value, $variants, true ) ) {
    219 									$this->fonts[ $font ][] = $value;
    220 								}
    221 							}
    222 						} elseif ( 'font-subset' === $output['property'] || 'subset' === $output['property'] || 'subsets' === $output['property'] ) {
    223 							if ( ! is_array( $value ) ) {
    224 								if ( ! in_array( $value, $this->subsets, true ) ) {
    225 									$this->subsets[] = $value;
    226 								}
    227 							} else {
    228 								foreach ( $value as $subset ) {
    229 									if ( ! in_array( $subset, $this->subsets, true ) ) {
    230 										$this->subsets[] = $subset;
    231 									}
    232 								}
    233 							}
    234 						}
    235 					}
    236 				}
    237 			}
    238 		}
    239 
    240 		/**
    241 		 * Determines the vbalidity of the selected font as well as its properties.
    242 		 * This is vital to make sure that the google-font script that we'll generate later
    243 		 * does not contain any invalid options.
    244 		 */
    245 		private function process_fonts() {
    246 
    247 			// Early exit if font-family is empty.
    248 			if ( empty( $this->fonts ) ) {
    249 				return;
    250 			}
    251 
    252 			$valid_subsets = array();
    253 			foreach ( $this->fonts as $font => $variants ) {
    254 
    255 				// Determine if this is indeed a google font or not.
    256 				// If it's not, then just remove it from the array.
    257 				if ( ! array_key_exists( $font, $this->google_fonts ) ) {
    258 					unset( $this->fonts[ $font ] );
    259 					continue;
    260 				}
    261 
    262 				// Get all valid font variants for this font.
    263 				$font_variants = array();
    264 				if ( isset( $this->google_fonts[ $font ]['variants'] ) ) {
    265 					$font_variants = $this->google_fonts[ $font ]['variants'];
    266 				}
    267 				foreach ( $variants as $variant ) {
    268 
    269 					// If this is not a valid variant for this font-family
    270 					// then unset it and move on to the next one.
    271 					if ( ! in_array( $variant, $font_variants, true ) ) {
    272 						$variant_key = array_search( $variant, $this->fonts[ $font ] );
    273 						unset( $this->fonts[ $font ][ $variant_key ] );
    274 						continue;
    275 					}
    276 				}
    277 
    278 				// Check if the selected subsets exist, even in one of the selected fonts.
    279 				// If they don't, then they have to be removed otherwise the link will fail.
    280 				if ( isset( $this->google_fonts[ $font ]['subsets'] ) ) {
    281 					foreach ( $this->subsets as $subset ) {
    282 						if ( in_array( $subset, $this->google_fonts[ $font ]['subsets'], true ) ) {
    283 							$valid_subsets[] = $subset;
    284 						}
    285 					}
    286 				}
    287 			}
    288 			$this->subsets = $valid_subsets;
    289 		}
    290 
    291 		/**
    292 		 * Creates the google-fonts link.
    293 		 */
    294 		private function create_link() {
    295 
    296 			// If we don't have any fonts then we can exit.
    297 			if ( empty( $this->fonts ) ) {
    298 				return;
    299 			}
    300 
    301 			// Get font-family + subsets.
    302 			$link_fonts = array();
    303 			foreach ( $this->fonts as $font => $variants ) {
    304 
    305 				// Are we force-loading all variants?
    306 				if ( true === self::$force_load_all_variants ) {
    307 					if ( isset( $this->google_fonts[ $font ]['variants'] ) ) {
    308 						$variants = $this->google_fonts[ $font ]['variants'];
    309 					}
    310 				}
    311 				$variants = implode( ',', $variants );
    312 
    313 				$link_font = str_replace( ' ', '+', $font );
    314 				if ( ! empty( $variants ) ) {
    315 					$link_font .= ':' . $variants;
    316 				}
    317 				$link_fonts[] = $link_font;
    318 			}
    319 
    320 			// Are we force-loading all subsets?
    321 			if ( true === self::$force_load_all_subsets ) {
    322 
    323 				if ( isset( $this->google_fonts[ $font ]['subsets'] ) ) {
    324 					foreach ( $this->google_fonts[ $font ]['subsets'] as $subset ) {
    325 						$this->subsets[] = $subset;
    326 					}
    327 				}
    328 			}
    329 
    330 			if ( ! empty( $this->subsets ) ) {
    331 				$this->subsets = array_unique( $this->subsets );
    332 			}
    333 
    334 			$this->link = add_query_arg( array(
    335 				'family' => str_replace( '%2B', '+', urlencode( implode( '|', $link_fonts ) ) ),
    336 				'subset' => urlencode( implode( ',', $this->subsets ) ),
    337 			), 'https://fonts.googleapis.com/css' );
    338 
    339 		}
    340 	}
    341 }