PluginProbe
Customify / 2.6.0
Customify v2.6.0
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.6.0, at features/class-Font_Selector.php

682 lines 20.5 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 if ( empty( $font['selector'] ) || empty( $font['value'] ) ) {
319 return '';
320 }
321
322 $properties_prefix = '';
323 if ( ! empty ( $font['properties_prefix'] ) ) {
324 $properties_prefix = $font['properties_prefix'];
325 }
326
327 /** @var PixCustomifyPlugin $local_plugin */
328 $local_plugin = PixCustomifyPlugin();
329
330 $value = $this->maybe_decode_value( $font['value'] );
331
332 if ( $value === null ) {
333 $value = $local_plugin->customizer->get_font_defaults_value( $font['value'] );
334 }
335
336 // shim the old case when the default was only the font name
337 if ( is_string( $value ) && ! empty( $value ) ) {
338 $value = array( 'font_family' => $value );
339 }
340
341 // Handle special logic for when the $value array is not an associative array
342 if ( ! $local_plugin->is_assoc( $value ) ) {
343 $value = $local_plugin->customizer->standardize_non_associative_font_default( $value );
344 }
345
346 $value = $this->validate_font_values( $value );
347 // some sanitizing
348 $load_all_weights = false;
349 if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
350 $load_all_weights = true;
351 }
352 $selected_variant = '';
353 if ( ! empty( $value['selected_variants'] ) ) {
354 if ( is_array( $value['selected_variants'] ) ) {
355 $selected_variant = $value['selected_variants'][0];
356 } else {
357 $selected_variant = $value['selected_variants'];
358 }
359 }
360
361 ob_start();
362
363 if ( isset( $font['callback'] ) && function_exists( $font['callback'] ) ) {
364 $output = call_user_func( $font['callback'], $value, $font );
365 echo $output;
366 } elseif ( isset( $font['selector'] ) ) {
367 echo $font['selector'] . " {" . "\n";
368
369 // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
370 if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
371 //the variant's font-family
372 $this->display_property( 'font-family', $selected_variant['font-family'], '', $properties_prefix );
373
374 if ( ! $load_all_weights ) {
375 // if this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
376 // we need to "force" the font-weight and font-style
377 if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
378 $selected_variant['font-weight'] = '400 !important';
379 $selected_variant['font-style'] = 'normal !important';
380 }
381
382 $italic_font = false;
383
384 // output the font weight, if available
385 if ( ! empty( $selected_variant['font-weight'] ) ) {
386 echo ": " . $selected_variant['font-weight'] . ";\n";
387 $italic_font = $this->display_weight_property( $selected_variant['font-weight'], $properties_prefix );
388 }
389
390 // output the font style, if available and if it wasn't displayed already
391 if ( ! $italic_font && ! empty( $selected_variant['font-style'] ) ) {
392 $this->display_property( 'font-style', $selected_variant['font-style'], '', $properties_prefix );
393 }
394 }
395
396 } elseif ( isset( $value['font_family'] ) ) {
397 // the selected font family
398 $this->display_property( 'font-family', $value['font_family'], '', $properties_prefix );
399
400 if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
401 $weight_and_style = strtolower( $selected_variant );
402 $italic_font = false;
403
404 //determine if this is an italic font (the $weight_and_style is usually like '400' or '400italic' )
405 if ( ! empty( $weight_and_style ) ) {
406 //a little bit of sanity check - in case it's not a number
407 if( $weight_and_style === 'regular' ) {
408 $weight_and_style = 'normal';
409 }
410 $italic_font = $this->display_weight_property( $weight_and_style, $properties_prefix );
411 }
412
413 // output the font style, if available
414 if ( ! $italic_font && ! empty( $selected_variant['font-style'] ) ) {
415 $this->display_property( 'font-style', $selected_variant['font-style'], '', $properties_prefix );
416 }
417 }
418 } else if ( isset( $value['font-family'] ) ) {
419 $this->display_property( 'font-family', $value['font-family'], '', $properties_prefix );
420 }
421
422 if ( ! empty( $value['font_weight'] ) ) {
423 $this->display_weight_property( $value['font_weight'], $properties_prefix );
424 }
425
426 if ( ! empty( $value['font_size'] ) ) {
427 // If the value already contains a unit, go with that.
428 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
429 $font_size = $value['font_size'];
430 $unit = '';
431 if ( is_numeric( $value['font_size'] ) ) {
432 $unit = $this->get_field_unit( $font, 'font-size' );
433 } elseif ( is_array( $value['font_size'] ) ) {
434 if ( isset( $value['font_size']['unit'] ) ) {
435 $unit = $value['font_size']['unit'];
436 }
437
438 if ( isset( $value['font_size']['value'] ) ) {
439 $font_size = $value['font_size']['value'];
440 }
441 }
442
443 if ( isset( $value['font_size']['unit'] ) && $value['font_size']['unit'] == 'em' && $value['font_size']['value'] >= 9 ) {
444 $value['font_size']['unit'] = 'px';
445 }
446
447 $this->display_property( 'font-size', $font_size, $unit, $properties_prefix );
448 }
449
450 if ( isset( $value['line_height'] ) ) {
451 // If the value already contains a unit, go with that.
452 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
453 $line_height = $value['line_height'];
454 $unit = '';
455 if ( is_numeric( $value['line_height'] ) ) {
456 $unit = $this->get_field_unit( $font, 'line-height' );
457 } elseif ( is_array( $value['line_height'] ) ) {
458 if ( isset( $value['line_height']['unit'] ) ) {
459 $unit = $value['line_height']['unit'];
460 }
461
462 if ( isset( $value['line_height']['value'] ) ) {
463 $line_height = $value['line_height']['value'];
464 }
465 }
466
467 $this->display_property( 'line-height', $line_height, $unit, $properties_prefix );
468 }
469
470 if ( isset( $value['letter_spacing'] ) ) {
471 // If the value already contains a unit, go with that.
472 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
473 $letter_spacing = $value['letter_spacing'];
474 $unit = '';
475 if ( is_numeric( $value['letter_spacing'] ) ) {
476 $unit = $this->get_field_unit( $font, 'letter-spacing' );
477 } elseif ( is_array( $value['letter_spacing'] ) ) {
478 if ( isset( $value['letter_spacing']['unit'] ) ) {
479 $unit = $value['letter_spacing']['unit'];
480 }
481
482 if ( isset( $value['letter_spacing']['value'] ) ) {
483 $letter_spacing = $value['letter_spacing']['value'];
484 }
485 }
486
487 $this->display_property( 'letter-spacing', $letter_spacing, $unit, $properties_prefix );
488 }
489
490 if ( ! empty( $value['text_align'] ) ) {
491 $this->display_property( 'text-align', $value['text_align'], '', $properties_prefix );
492 }
493
494 if ( ! empty( $value['text_transform'] ) ) {
495 $this->display_property( 'text-transform', $value['text_transform'], '', $properties_prefix );
496 }
497
498 if ( ! empty( $value['text_decoration'] ) ) {
499 $this->display_property( 'text-decoration', $value['text_decoration'], '', $properties_prefix );
500 }
501 echo "}\n";
502 }
503
504 $CSS = ob_get_clean();
505
506 return $CSS;
507 }
508
509 function output_webfont_script() {
510 $script = $this->get_fonts_dynamic_script();
511 if ( ! empty( $script ) ) { ?>
512 <script type="text/javascript">
513 <?php echo $script; ?>
514 </script>
515 <?php }
516 }
517
518 function get_fonts_dynamic_script() {
519 $args = $this->get_fonts_args();
520
521 if ( ( empty ( $args['local_families'] ) && empty ( $args['google_families'] ) )
522 || ! PixCustomifyPlugin()->settings->get_plugin_setting( 'typography', '1' )
523 || ! PixCustomifyPlugin()->settings->get_plugin_setting( 'typography_google_fonts', 1 ) ) {
524 return '';
525 }
526
527 ob_start(); ?>
528 function customify_font_loader() {
529 var webfontargs = {
530 classes: true,
531 events: true,
532 loading: function() {
533 jQuery( window ).trigger( 'wf-loading' );
534 },
535 active: function() {
536 jQuery( window ).trigger( 'wf-active' );
537 },
538 inactive: function() {
539 jQuery( window ).trigger( 'wf-inactive' );
540 },
541 };
542 <?php if ( ! empty( $args['google_families'] ) ) { ?>
543 webfontargs.google = {
544 families: [<?php echo join( ',', $args['google_families'] ); ?>]
545 };
546 <?php }
547 if ( ! empty( $args['local_families'] ) && ! empty( $args['local_srcs'] ) ) { ?>
548 webfontargs.custom = {
549 families: [<?php echo join( ',', $args['local_families'] ); ?>],
550 urls: [<?php echo join( ',', $args['local_srcs'] ) ?>]
551 };
552 <?php } ?>
553 WebFont.load(webfontargs);
554 };
555
556 if (typeof WebFont !== 'undefined') {
557 customify_font_loader();
558 } else {
559 var tk = document.createElement('script');
560 tk.src = '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
561 tk.type = 'text/javascript';
562
563 tk.onload = tk.onreadystatechange = function () {
564 customify_font_loader();
565 };
566
567 var s = document.getElementsByTagName('script')[0];
568 s.parentNode.insertBefore(tk, s);
569 }
570 <?php
571 $output = ob_get_clean();
572
573 return apply_filters( 'customify_fonts_webfont_script', $output );
574 }
575
576 function get_field_unit( $font, $field ) {
577
578 if ( empty( $font ) || empty( $font['fields'] ) || empty( $font['fields'][ $field ] ) ) {
579
580 if ( 'line-height' == $field ){
581 return '';
582 }
583
584 return 'px';
585 }
586
587 if ( isset( $font['fields'][ $field ]['unit'] ) ) {
588 return $font['fields'][ $field ]['unit'];
589 }
590
591 if ( isset( $font['fields'][ $field ][3] ) ) {
592 return $font['fields'][ $field ][3];
593 }
594
595 return 'px';
596 }
597
598 function validate_font_values( $values ) {
599
600 if ( empty( $values ) ) {
601 return array();
602 }
603
604 foreach ( $values as $key => $value ) {
605
606 if ( strpos( $key, '-' ) !== false ) {
607 $new_key = str_replace( '-', '_', $key );
608
609 $values[ $new_key ] = $value;
610
611 unset( $values[ $key ] );
612 }
613 }
614
615 return $values;
616 }
617
618 function display_selector( $selector ) {
619
620 }
621
622 function display_property( $property, $value, $unit = '', $prefix = '' ) {
623 echo $prefix . $property . ": " . $value . $unit . ";\n";
624 }
625
626 // well weight sometimes comes from google as 600italic which in CSS syntax should come in two separate properties
627 function display_weight_property( $value, $prefix = '' ) {
628 $has_style = false;
629
630 if ( strpos( $value, 'italic' ) !== false ) {
631
632 $value = str_replace( 'italic', '', $value );
633 echo $prefix . 'font-weight' . ": " . $value . ";\n";
634 echo $prefix . 'font-style' . ": italic;\n";
635 $has_style = true;
636 } else {
637 echo $prefix . 'font-weight' . ": " . $value . ";\n";
638 }
639
640
641 return $has_style;
642 }
643
644 /**
645 * Main Customify_Font_Selector Instance
646 *
647 * Ensures only one instance of Customify_Font_Selector is loaded or can be loaded.
648 *
649 * @since 1.0.0
650 * @static
651 *
652 * @return Customify_Font_Selector Main Customify_Font_Selector instance
653 */
654 public static function instance() {
655
656 if ( is_null( self::$_instance ) ) {
657 self::$_instance = new self();
658 }
659 return self::$_instance;
660 } // End instance ()
661
662 /**
663 * Cloning is forbidden.
664 *
665 * @since 1.0.0
666 */
667 public function __clone() {
668
669 _doing_it_wrong( __FUNCTION__,esc_html__( 'You should not do that!', 'customify' ), '' );
670 }
671
672 /**
673 * Unserializing instances of this class is forbidden.
674 *
675 * @since 1.0.0
676 */
677 public function __wakeup() {
678
679 _doing_it_wrong( __FUNCTION__, esc_html__( 'You should not do that!', 'customify' ), '' );
680 }
681 }
682