PluginProbe
Customify / 2.5.2
Customify v2.5.2
2.10.9 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.7.1 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.6.0 1.6.0.1 1.6.5 1.7.0 1.7.1 All 77 releases
customify / features / class-Font_Selector.php

class-Font_Selector.php in Customify 2.5.2, at features/class-Font_Selector.php

664 lines 19.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Customify_Font_Selector {
4
5 /**
6 * Instance of this class.
7 * @since 1.0.0
8 * @var object
9 */
10 protected static $_instance = null;
11
12 protected static $typo_settings = null;
13 protected static $options_list = null;
14 protected $theme_fonts = null;
15 protected $customify_CSS_output = array();
16
17
18 function __construct() {
19 $this->theme_fonts = apply_filters( 'customify_theme_fonts', array() );
20
21 $load_location = PixCustomifyPlugin()->settings->get_plugin_setting( 'style_resources_location', 'wp_head' );
22 add_action( $load_location, array( $this, 'output_webfont_script' ), 99 );
23 add_action( $load_location, array( $this, 'output_fonts_dynamic_style' ), 100 );
24 add_action( 'customify_font_family_before_options', array( $this, 'add_customify_theme_fonts' ), 11, 1 );
25
26 if ( PixCustomifyPlugin()->settings->get_plugin_setting( 'enable_editor_style', true ) ) {
27 add_action( 'admin_head', array( $this, 'script_to_add_customizer_settings_into_wp_editor' ) );
28 }
29
30 }
31
32 function script_to_add_customizer_settings_into_wp_editor() {
33
34 ob_start();
35 $this->output_fonts_dynamic_style();
36
37 $custom_css = ob_get_clean();
38
39 ob_start(); ?>
40 (function ($) {
41 $(window).load(function () {
42 /**
43 * @param iframe_id the id of the frame you want to append the style
44 * @param style_element the style element you want to append
45 */
46 var append_script_to_iframe = function (ifrm_id, scriptEl) {
47 var myIframe = document.getElementById(ifrm_id);
48
49 var script = myIframe.contentWindow.document.createElement("script");
50 script.type = "text/javascript";
51 script.innerHTML = scriptEl.innerHTML;
52
53 myIframe.contentWindow.document.head.appendChild(script);
54 };
55
56 var append_style_to_iframe = function (ifrm_id, styleElment) {
57 var ifrm = window.frames[ifrm_id];
58 if ( typeof ifrm === "undefined" ) {
59 return;
60 }
61 ifrm = ( ifrm.contentDocument || ifrm.document );
62 var head = ifrm.getElementsByTagName('head')[0];
63
64 if (typeof styleElment !== "undefined") {
65 head.appendChild(styleElment);
66 }
67 };
68
69 var xmlString = <?php echo json_encode( str_replace( "\n", "", $custom_css ) ); ?>,
70 parser = new DOMParser(),
71 doc = parser.parseFromString(xmlString, "text/html");
72
73 if (typeof window.frames['content_ifr'] !== 'undefined') {
74
75 $.each(doc.head.childNodes, function (key, el) {
76 if (typeof el !== "undefined" && typeof el.tagName !== "undefined") {
77
78 switch (el.tagName) {
79 case 'STYLE' :
80 append_style_to_iframe('content_ifr', el);
81 break;
82 case 'SCRIPT' :
83 append_script_to_iframe('content_ifr', el);
84 break;
85 default:
86 break;
87 }
88 }
89 });
90 }
91 });
92 })(jQuery);
93 <?php
94 $script = ob_get_clean();
95 wp_add_inline_script( 'editor', $script );
96 }
97
98 public function get_theme_fonts() {
99 return $this->theme_fonts;
100 }
101
102 function add_customify_theme_fonts( $active_font_family ) {
103 //first get all the published custom fonts
104 if ( empty( $this->theme_fonts ) ) {
105 return;
106 }
107
108 echo '<optgroup label="' . esc_html__( 'Theme Fonts', 'customify' ) . '">';
109 foreach ( $this->theme_fonts as $font ) {
110 if ( ! empty( $font ) ) {
111 //display the select option's HTML
112 Pix_Customize_Font_Control::output_font_option( $font, $active_font_family, 'theme_font' );
113 }
114 }
115 echo "</optgroup>";
116 }
117
118 function maybe_decode_value( $value ) {
119
120 $to_return = PixCustomifyPlugin::decodeURIComponent( $value );
121 if ( is_string( $value ) ) {
122 $to_return = json_decode( wp_unslash( $to_return ), true );
123 }
124
125 return $to_return;
126 }
127
128 protected function get_fonts_args() {
129
130 $args = array(
131 'google_families' => array(),
132 'local_families' => array(),
133 'local_srcs' => array(),
134 );
135
136 /** @var PixCustomifyPlugin $local_plugin */
137 $local_plugin = PixCustomifyPlugin();
138
139 self::$options_list = $local_plugin->get_options_details();
140
141 $local_plugin->customizer->get_typography_fields( self::$options_list, 'type', 'font', self::$typo_settings );
142
143 if ( empty( self::$typo_settings ) ) {
144 return $args;
145 }
146
147 foreach ( self::$typo_settings as $id => $font ) {
148 if ( isset ( $font['value'] ) ) {
149
150 $load_all_weights = false;
151 if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
152 $load_all_weights = true;
153 }
154
155 $value = $this->maybe_decode_value( $font['value'] );
156
157 $value = $this->validate_font_values( $value );
158
159 // in case the value is still null, try default value (mostly for google fonts)
160 if ( ! is_array( $value ) || $value === null ) {
161 $value = $local_plugin->customizer->get_font_defaults_value( str_replace( '"', '', $font['value'] ) );
162 }
163
164 //bail if by this time we don't have a value of some sort
165 if ( empty( $value ) ) {
166 continue;
167 }
168
169 // Handle special logic for when the $value array is not an associative array
170 if ( ! $local_plugin->is_assoc( $value ) ) {
171 $value = $local_plugin->customizer->standardize_non_associative_font_default( $value );
172 }
173
174 // If we have reached this far and we don't have a type, we will assume it's a google font.
175 if ( ! isset( $value['type'] ) ) {
176 $value['type'] = 'google';
177 }
178
179 if ( ! isset( $value['font_family'] ) ) {
180 continue;
181 }
182
183 if ( isset( $this->theme_fonts[ $value['font_family'] ] ) ) {
184
185 // $value['type'] = 'theme_font';
186 // $args['local_srcs'] .= $this->theme_fonts[ $value['font_family'] ]['src'] . ',';
187 // $value['variants'] = $this->theme_fonts[ $value['font_family'] ]['variants'];
188
189 if ( false === array_search( $value['font_family'], $args['local_families'] ) ) {
190 $args['local_families'][] = "'" . $value['font_family'] . "'";
191 }
192
193 if ( false === array_search( $this->theme_fonts[ $value['font_family'] ]['src'], $args['local_srcs'] ) ) {
194 $args['local_srcs'][] = "'" . $this->theme_fonts[ $value['font_family'] ]['src'] . "'";
195 }
196 } elseif ( isset( $value['font_family'] ) && isset( $value['type'] ) && $value['type'] === 'google' ) {
197 $family = "'" . $value['font_family'];
198
199 if ( $load_all_weights && ! empty( $value['variants'] ) && is_array( $value['variants'] ) ) {
200 $family .= ":" . implode( ',', $value['variants'] );
201 } elseif ( ! empty( $value['selected_variants'] ) ) {
202 if ( is_array( $value['selected_variants'] ) ) {
203 $family .= ":" . implode( ',', $value['selected_variants'] );
204 } elseif ( is_string( $value['selected_variants'] ) || is_numeric( $value['selected_variants'] ) ) {
205 $family .= ":" . $value['selected_variants'];
206 }
207 } elseif ( ! empty( $value['variants'] ) ) {
208 if ( is_array( $value['variants'] ) ) {
209 $family .= ":" . implode( ',', $value['variants'] );
210 } else {
211 $family .= ":" . $value['variants'];
212 }
213 }
214
215 if ( ! empty( $value['selected_subsets'] ) ) {
216 if ( is_array( $value['selected_subsets'] ) ) {
217 $family .= ":" . implode( ',', $value['selected_subsets'] );
218 } else {
219 $family .= ":" . $value['selected_subsets'];
220 }
221 } elseif ( ! empty( $value['subsets'] ) ) {
222 if ( is_array( $value['subsets'] ) ) {
223 $family .= ":" . implode( ',', $value['subsets'] );
224 } else {
225 $family .= ":" . $value['subsets'];
226 }
227 }
228
229 $family .= "'";
230
231 $args['google_families'][] = $family;
232 }
233 }
234 }
235
236 $args = array(
237 'google_families' => array_unique( $args['google_families'] ),
238 'local_families' => array_unique( $args['local_families'] ),
239 'local_srcs' => array_unique( $args['local_srcs'] ),
240 );
241
242 return $args;
243 }
244
245 function output_fonts_dynamic_style() {
246
247 /** @var PixCustomifyPlugin $local_plugin */
248 $local_plugin = PixCustomifyPlugin();
249
250 self::$options_list = $local_plugin->get_options_details();
251 $local_plugin->customizer->get_typography_fields( self::$options_list, 'type', 'font', self::$typo_settings );
252
253 if ( empty( self::$typo_settings ) ) {
254 return;
255 }
256
257 $output = '';
258
259 foreach ( self::$typo_settings as $key => $font ) {
260 $font_output = $this->get_font_style( $font );
261 if ( empty( $font_output ) ) {
262 continue;
263 }
264
265 $output .= $font_output . "\n";
266
267 // If we are in a Customizer context we will output CSS rules grouped so we can target them.
268 // In the frontend we want a whole bulk.
269 if ( isset( $GLOBALS['wp_customize'] ) ) { ?>
270 <style id="customify_font_output_for_<?php echo sanitize_html_class( $key ); ?>">
271 <?php echo $font_output; ?>
272 </style><?php
273 }
274 }
275
276 // in customizer the CSS is printed per option, in front-end we need to print them in bulk
277 if ( ! isset( $GLOBALS['wp_customize'] ) ) { ?>
278 <style id="customify_fonts_output">
279 <?php echo $output; ?>
280 </style><?php
281 }
282 }
283
284 function get_fonts_dynamic_style() {
285
286 $output = '';
287
288 /** @var PixCustomifyPlugin $local_plugin */
289 $local_plugin = PixCustomifyPlugin();
290
291 self::$options_list = $local_plugin->get_options_details();
292 $local_plugin->customizer->get_typography_fields( self::$options_list, 'type', 'font', self::$typo_settings );
293
294 if ( empty( self::$typo_settings ) ) {
295 return $output;
296 }
297
298 foreach ( self::$typo_settings as $key => $font ) {
299
300 $font_output = $this->get_font_style( $font );
301 if ( empty( $font_output ) ) {
302 continue;
303 }
304
305 $output .= $font_output . "\n";
306 }
307
308 return $output;
309 }
310
311 function get_font_style( $font ) {
312
313 if ( ! isset( $font['selector'] ) ) {
314 return '';
315 }
316
317 $font['selector'] = apply_filters( 'customify_font_css_selector', $font['selector'], $font );
318
319 if ( empty( $font['selector'] ) || empty( $font['value'] ) ) {
320 return '';
321 }
322
323 /** @var PixCustomifyPlugin $local_plugin */
324 $local_plugin = PixCustomifyPlugin();
325
326 $value = $this->maybe_decode_value( $font['value'] );
327
328 if ( $value === null ) {
329 $value = $local_plugin->customizer->get_font_defaults_value( $font['value'] );
330 }
331
332 // shim the old case when the default was only the font name
333 if ( is_string( $value ) && ! empty( $value ) ) {
334 $value = array( 'font_family' => $value );
335 }
336
337 // Handle special logic for when the $value array is not an associative array
338 if ( ! $local_plugin->is_assoc( $value ) ) {
339 $value = $local_plugin->customizer->standardize_non_associative_font_default( $value );
340 }
341
342 $value = $this->validate_font_values( $value );
343 // some sanitizing
344 $load_all_weights = false;
345 if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
346 $load_all_weights = true;
347 }
348 $selected_variant = '';
349 if ( ! empty( $value['selected_variants'] ) ) {
350 if ( is_array( $value['selected_variants'] ) ) {
351 $selected_variant = $value['selected_variants'][0];
352 } else {
353 $selected_variant = $value['selected_variants'];
354 }
355 }
356
357 ob_start();
358
359 if ( isset( $font['callback'] ) && function_exists( $font['callback'] ) ) {
360 $output = call_user_func( $font['callback'], $value, $font );
361 echo $output;
362 } elseif ( isset( $font['selector'] ) ) {
363 echo $font['selector'] . " {" . "\n";
364
365 // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
366 if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
367 //the variant's font-family
368 $this->display_property( 'font-family', $selected_variant['font-family'] );
369
370 if ( ! $load_all_weights ) {
371 // if this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
372 // we need to "force" the font-weight and font-style
373 if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
374 $selected_variant['font-weight'] = '400 !important';
375 $selected_variant['font-style'] = 'normal !important';
376 }
377
378 $italic_font = false;
379
380 // output the font weight, if available
381 if ( ! empty( $selected_variant['font-weight'] ) ) {
382 echo ": " . $selected_variant['font-weight'] . ";\n";
383 $italic_font = $this->display_weight_property( $selected_variant['font-weight'] );
384 }
385
386 // output the font style, if available and if it wasn't displayed already
387 if ( ! $italic_font && ! empty( $selected_variant['font-style'] ) ) {
388 $this->display_property( 'font-style', $selected_variant['font-style'] );
389 }
390 }
391
392 } elseif ( isset( $value['font_family'] ) ) {
393 // the selected font family
394 $this->display_property( 'font-family', $value['font_family'] );
395
396 if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
397 $weight_and_style = strtolower( $selected_variant );
398 $italic_font = false;
399
400 //determine if this is an italic font (the $weight_and_style is usually like '400' or '400italic' )
401 if ( ! empty( $weight_and_style ) ) {
402 //a little bit of sanity check - in case it's not a number
403 if( $weight_and_style === 'regular' ) {
404 $weight_and_style = 'normal';
405 }
406 $italic_font = $this->display_weight_property( $weight_and_style );
407 }
408
409 // output the font style, if available
410 if ( ! $italic_font && ! empty( $selected_variant['font-style'] ) ) {
411 $this->display_property( 'font-style', $selected_variant['font-style'] );
412 }
413 }
414 } else if ( isset( $value['font-family'] ) ) {
415 $this->display_property( 'font-family', $value['font-family'] );
416 }
417
418 if ( ! empty( $value['font_weight'] ) ) {
419 $this->display_weight_property( $value['font_weight'] );
420 }
421
422 if ( ! empty( $value['font_size'] ) ) {
423 // If the value already contains a unit, go with that.
424 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
425 $font_size = $value['font_size'];
426 $unit = '';
427 if ( is_numeric( $value['font_size'] ) ) {
428 $unit = $this->get_field_unit( $font, 'font-size' );
429 } elseif ( is_array( $value['font_size'] ) ) {
430 if ( isset( $value['font_size']['unit'] ) ) {
431 $unit = $value['font_size']['unit'];
432 }
433
434 if ( isset( $value['font_size']['value'] ) ) {
435 $font_size = $value['font_size']['value'];
436 }
437 }
438
439 if ( isset( $value['font_size']['unit'] ) && $value['font_size']['unit'] == 'em' && $value['font_size']['value'] >= 9 ) {
440 $value['font_size']['unit'] = 'px';
441 }
442
443 $this->display_property( 'font-size', $font_size, $unit );
444 }
445
446 if ( isset( $value['line_height'] ) ) {
447 // If the value already contains a unit, go with that.
448 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
449 $line_height = $value['line_height'];
450 $unit = '';
451 if ( is_numeric( $value['line_height'] ) ) {
452 $unit = $this->get_field_unit( $font, 'line-height' );
453 } elseif ( is_array( $value['line_height'] ) ) {
454 if ( isset( $value['line_height']['unit'] ) ) {
455 $unit = $value['line_height']['unit'];
456 }
457
458 if ( isset( $value['line_height']['value'] ) ) {
459 $line_height = $value['line_height']['value'];
460 }
461 }
462
463 $this->display_property( 'line-height', $line_height, $unit );
464 }
465
466 if ( isset( $value['letter_spacing'] ) ) {
467 // If the value already contains a unit, go with that.
468 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
469 $letter_spacing = $value['letter_spacing'];
470 $unit = '';
471 if ( is_numeric( $value['letter_spacing'] ) ) {
472 $unit = $this->get_field_unit( $font, 'letter-spacing' );
473 } elseif ( is_array( $value['letter_spacing'] ) ) {
474 if ( isset( $value['letter_spacing']['unit'] ) ) {
475 $unit = $value['letter_spacing']['unit'];
476 }
477
478 if ( isset( $value['letter_spacing']['value'] ) ) {
479 $letter_spacing = $value['letter_spacing']['value'];
480 }
481 }
482
483 $this->display_property( 'letter-spacing', $letter_spacing, $unit );
484 }
485
486 if ( ! empty( $value['text_align'] ) ) {
487 $this->display_property( 'text-align', $value['text_align'] );
488 }
489
490 if ( ! empty( $value['text_transform'] ) ) {
491 $this->display_property( 'text-transform', $value['text_transform'] );
492 }
493
494 if ( ! empty( $value['text_decoration'] ) ) {
495 $this->display_property( 'text-decoration', $value['text_decoration'] );
496 }
497 echo "}\n";
498 }
499
500 $CSS = ob_get_clean();
501
502 return $CSS;
503 }
504
505 function output_webfont_script() {
506 $script = $this->get_fonts_dynamic_script();
507 if ( ! empty( $script ) ) { ?>
508 <script type="text/javascript">
509 <?php echo $script; ?>
510 </script>
511 <?php }
512 }
513
514 function get_fonts_dynamic_script() {
515 $args = $this->get_fonts_args();
516
517 if ( ( empty ( $args['local_families'] ) && empty ( $args['google_families'] ) )
518 || ! PixCustomifyPlugin()->settings->get_plugin_setting( 'typography', '1' )
519 || ! PixCustomifyPlugin()->settings->get_plugin_setting( 'typography_google_fonts', 1 ) ) {
520 return '';
521 }
522
523 ob_start(); ?>
524 function customify_font_loader() {
525 var webfontargs = {
526 classes: false,
527 events: false
528 };
529 <?php if ( ! empty( $args['google_families'] ) ) { ?>
530 webfontargs.google = {
531 families: [<?php echo join( ',', $args['google_families'] ); ?>]
532 };
533 <?php }
534 if ( ! empty( $args['local_families'] ) && ! empty( $args['local_srcs'] ) ) { ?>
535 webfontargs.custom = {
536 families: [<?php echo join( ',', $args['local_families'] ); ?>],
537 urls: [<?php echo join( ',', $args['local_srcs'] ) ?>]
538 };
539 <?php } ?>
540 WebFont.load(webfontargs);
541 };
542
543 if (typeof WebFont !== 'undefined') {
544 customify_font_loader();
545 } else {
546 var tk = document.createElement('script');
547 tk.src = '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
548 tk.type = 'text/javascript';
549
550 tk.onload = tk.onreadystatechange = function () {
551 customify_font_loader();
552 };
553
554 var s = document.getElementsByTagName('script')[0];
555 s.parentNode.insertBefore(tk, s);
556 }
557 <?php
558 $output = ob_get_clean();
559
560 return apply_filters( 'customify_fonts_webfont_script', $output );
561 }
562
563 function get_field_unit( $font, $field ) {
564
565 if ( empty( $font ) || empty( $font['fields'] ) || empty( $font['fields'][ $field ] ) ) {
566 return 'px';
567 }
568
569 if ( isset( $font['fields'][ $field ]['unit'] ) ) {
570 return $font['fields'][ $field ]['unit'];
571 }
572
573 if ( isset( $font['fields'][ $field ][3] ) ) {
574 return $font['fields'][ $field ][3];
575 }
576
577 return 'px';
578 }
579
580 function validate_font_values( $values ) {
581
582 if ( empty( $values ) ) {
583 return array();
584 }
585
586 foreach ( $values as $key => $value ) {
587
588 if ( strpos( $key, '-' ) !== false ) {
589 $new_key = str_replace( '-', '_', $key );
590
591 $values[ $new_key ] = $value;
592
593 unset( $values[ $key ] );
594 }
595 }
596
597 return $values;
598 }
599
600 function display_selector( $selector ) {
601
602 }
603
604 function display_property( $property, $value, $unit = '' ) {
605 echo $property . ": " . $value . $unit . ";\n";
606 }
607
608 // well weight sometimes comes from google as 600italic which in CSS syntax should come in two separate properties
609 function display_weight_property( $value ) {
610 $has_style = false;
611
612 if ( strpos( $value, 'italic' ) !== false ) {
613
614 $value = str_replace( 'italic', '', $value );
615 echo 'font-weight' . ": " . $value . ";\n";
616 echo 'font-style' . ": italic;\n";
617 $has_style = true;
618 } else {
619 echo 'font-weight' . ": " . $value . ";\n";
620 }
621
622
623 return $has_style;
624 }
625
626 /**
627 * Main Customify_Font_Selector Instance
628 *
629 * Ensures only one instance of Customify_Font_Selector is loaded or can be loaded.
630 *
631 * @since 1.0.0
632 * @static
633 *
634 * @return Customify_Font_Selector Main Customify_Font_Selector instance
635 */
636 public static function instance() {
637
638 if ( is_null( self::$_instance ) ) {
639 self::$_instance = new self();
640 }
641 return self::$_instance;
642 } // End instance ()
643
644 /**
645 * Cloning is forbidden.
646 *
647 * @since 1.0.0
648 */
649 public function __clone() {
650
651 _doing_it_wrong( __FUNCTION__,esc_html__( 'You should not do that!', 'customify' ), '' );
652 }
653
654 /**
655 * Unserializing instances of this class is forbidden.
656 *
657 * @since 1.0.0
658 */
659 public function __wakeup() {
660
661 _doing_it_wrong( __FUNCTION__, esc_html__( 'You should not do that!', 'customify' ), '' );
662 }
663 }
664