PluginProbe
Customify / 2.2.0
Customify v2.2.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.2.0, at features/class-Font_Selector.php

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