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

565 lines 17.8 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() {
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 ( empty( $font['selector'] ) || empty( $font['value'] ) ) {
231 continue;
232 }
233 $value = $this->maybe_decode_value( $font['value'] );
234
235 if ( $value === null ) {
236 $value = $local_plugin->get_font_defaults_value( $font['value'] );
237 }
238
239 // shim the old case when the default was only the font name
240 if ( is_string( $value ) && ! empty( $value ) ) {
241 $value = array( 'font_family' => $value );
242 }
243
244 // Handle special logic for when the $value array is not an associative array
245 if ( ! $local_plugin->is_assoc( $value ) ) {
246 $value = $local_plugin->standardize_non_associative_font_default( $value );
247 }
248
249 $this->output_font_style( $key, $font, $value );
250 }
251
252 // in customizer the CSS is printed per option, in front-end we need to print them in bulk
253 if ( ! isset( $GLOBALS['wp_customize'] ) ) { ?>
254 <style id="customify_fonts_output">
255 <?php echo join( "\n", $this->customify_CSS_output ); ?>
256 </style><?php
257 return;
258 }
259 }
260
261 function display_webfont_script( $args ) { ?>
262 <script type="text/javascript">
263 var customify_font_loader = function () {
264 var webfontargs = {
265 classes: false,
266 events: false
267 };
268 <?php if ( ! empty( $args['google_families'] ) ) { ?>
269 webfontargs.google = {families: [<?php echo( rtrim( $args['google_families'], ',' ) ); ?>]};
270 <?php }
271 if ( ! empty( $args['local_families'] ) && ! empty( $args['local_srcs'] ) ) { ?>
272 webfontargs.custom = {
273 families: [<?php echo( rtrim( $args['local_families'], ',' ) ); ?>],
274 urls: [<?php echo rtrim( $args['local_srcs'], ',' ) ?>]
275 };
276 <?php } ?>
277 WebFont.load(webfontargs);
278 };
279
280 if (typeof WebFont !== 'undefined') { <?php // if there is a WebFont object, use it ?>
281 customify_font_loader();
282 } else { <?php // basically when we don't have the WebFont object we create the google script dynamically ?>
283 var tk = document.createElement('script');
284 tk.src = '//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
285 tk.type = 'text/javascript';
286
287 tk.onload = tk.onreadystatechange = function () {
288 customify_font_loader();
289 };
290 var s = document.getElementsByTagName('script')[0];
291 s.parentNode.insertBefore(tk, s);
292 }
293 </script>
294 <?php
295 }
296
297 function output_font_style( $field, $font, $value ) {
298 $value = $this->validate_font_values( $value );
299 // some sanitizing
300 $load_all_weights = false;
301 if ( isset( $font['load_all_weights'] ) && $font['load_all_weights'] == 'true' ) {
302 $load_all_weights = true;
303 }
304 $selected_variant = '';
305 if ( ! empty( $value['selected_variants'] ) ) {
306 if ( is_array( $value['selected_variants'] ) ) {
307 $selected_variant = $value['selected_variants'][0];
308 } else {
309 $selected_variant = $value['selected_variants'];
310 }
311 }
312
313 ob_start();
314
315 if ( isset( $font['callback'] ) && function_exists( $font['callback'] ) ) {
316 $output = call_user_func( $font['callback'], $value, $font );
317 echo $output;
318 } else {
319 echo $font['selector'] . " {" . PHP_EOL;
320
321 // First handle the case where we have the font-family in the selected variant (usually this means a custom font from our Fonto plugin)
322 if ( ! empty( $selected_variant ) && is_array( $selected_variant ) && ! empty( $selected_variant['font-family'] ) ) {
323 //the variant's font-family
324 $this->display_property( 'font-family', $selected_variant['font-family'] );
325
326 if ( ! $load_all_weights ) {
327 // if this is a custom font (like from our plugin Fonto) with individual styles & weights - i.e. the font-family says it all
328 // we need to "force" the font-weight and font-style
329 if ( ! empty( $value['type'] ) && 'custom_individual' == $value['type'] ) {
330 $selected_variant['font-weight'] = '400 !important';
331 $selected_variant['font-style'] = 'normal !important';
332 }
333
334 $italic_font = false;
335
336 // output the font weight, if available
337 if ( ! empty( $selected_variant['font-weight'] ) ) {
338 echo ": " . $selected_variant['font-weight'] . ";\n";
339 $italic_font = $this->display_weight_property( $selected_variant['font-weight'] );
340 }
341
342 // output the font style, if available and if it wasn't displayed already
343 if ( ! $italic_font && ! empty( $selected_variant['font-style'] ) ) {
344 $this->display_property( 'font-style', $selected_variant['font-style'] );
345 }
346 }
347
348 } elseif ( isset( $value['font_family'] ) ) {
349 // the selected font family
350 $this->display_property( 'font-family', $value['font_family'] );
351
352 if ( ! empty( $selected_variant ) && ! $load_all_weights ) {
353 $weight_and_style = strtolower( $selected_variant );
354 $italic_font = false;
355
356 //determine if this is an italic font (the $weight_and_style is usually like '400' or '400italic' )
357 if ( ! empty( $weight_and_style ) ) {
358 //a little bit of sanity check - in case it's not a number
359 if( $weight_and_style === 'regular' ) {
360 $weight_and_style = 'normal';
361 }
362 $italic_font = $this->display_weight_property( $weight_and_style );
363 }
364
365 // output the font style, if available
366 if ( ! $italic_font && ! empty( $selected_variant['font-style'] ) ) {
367 $this->display_property( 'font-style', $selected_variant['font-style'] );
368 }
369 }
370 } else if ( isset( $value['font-family'] ) ) {
371 $this->display_property( 'font-family', $value['font-family'] );
372 }
373
374 if ( ! empty( $value['font_weight'] ) ) {
375 $italic_font = $this->display_weight_property( $value['font_weight'] );
376 }
377
378 if ( ! empty( $value['font_size'] ) ) {
379 // If the value already contains a unit, go with that.
380 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
381 $font_size = $value['font_size'];
382 $unit = '';
383 if ( is_numeric( $value['font_size'] ) ) {
384 $unit = $this->get_field_unit( $font, 'font-size' );
385 } elseif ( is_array( $value['font_size'] ) ) {
386 if ( isset( $value['font_size']['unit'] ) ) {
387 $unit = $value['font_size']['unit'];
388 }
389
390 if ( isset( $value['font_size']['value'] ) ) {
391 $font_size = $value['font_size']['value'];
392 }
393 }
394
395 $this->display_property( 'font-size', $font_size, $unit );
396 }
397
398 if ( isset( $value['line_height'] ) ) {
399 // If the value already contains a unit, go with that.
400 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
401 $line_height = $value['line_height'];
402 $unit = '';
403 if ( is_numeric( $value['line_height'] ) ) {
404 $unit = $this->get_field_unit( $font, 'line-height' );
405 } elseif ( is_array( $value['line_height'] ) ) {
406 if ( isset( $value['line_height']['unit'] ) ) {
407 $unit = $value['line_height']['unit'];
408 }
409
410 if ( isset( $value['line_height']['value'] ) ) {
411 $line_height = $value['line_height']['value'];
412 }
413 }
414
415 $this->display_property( 'line-height', $line_height, $unit );
416 }
417
418 if ( isset( $value['letter_spacing'] ) ) {
419 // If the value already contains a unit, go with that.
420 // We also handle receiving the value in a standardized format ( array with 'value' and 'unit').
421 $letter_spacing = $value['letter_spacing'];
422 $unit = '';
423 if ( is_numeric( $value['letter_spacing'] ) ) {
424 $unit = $this->get_field_unit( $font, 'letter-spacing' );
425 } elseif ( is_array( $value['letter_spacing'] ) ) {
426 if ( isset( $value['letter_spacing']['unit'] ) ) {
427 $unit = $value['letter_spacing']['unit'];
428 }
429
430 if ( isset( $value['letter_spacing']['value'] ) ) {
431 $letter_spacing = $value['letter_spacing']['value'];
432 }
433 }
434
435 $this->display_property( 'letter-spacing', $letter_spacing, $unit );
436 }
437
438 if ( ! empty( $value['text_align'] ) ) {
439 $this->display_property( 'text-align', $value['text_align'] );
440 }
441
442 if ( ! empty( $value['text_transform'] ) ) {
443 $this->display_property( 'text-transform', $value['text_transform'] );
444 }
445
446 if ( ! empty( $value['text_decoration'] ) ) {
447 $this->display_property( 'text-decoration', $value['text_decoration'] );
448 }
449 echo "}\n";
450 }
451
452 $CSS = ob_get_clean();
453
454 if ( isset( $GLOBALS['wp_customize'] ) ) { ?>
455 <style id="customify_font_output_for_<?php echo sanitize_html_class( $field ); ?>">
456 <?php echo $CSS ?>
457 </style><?php
458 return;
459 } else {
460 $this->customify_CSS_output[] = $CSS;
461 }
462 }
463
464 function get_field_unit( $font, $field ) {
465
466 if ( empty( $font ) || empty( $font['fields'] ) || empty( $font['fields'][ $field ] ) ) {
467 return 'px';
468 }
469
470 if ( isset( $font['fields'][ $field ]['unit'] ) ) {
471 return $font['fields'][ $field ]['unit'];
472 }
473
474 if ( isset( $font['fields'][ $field ][3] ) ) {
475 return $font['fields'][ $field ][3];
476 }
477
478 return 'px';
479 }
480
481 function validate_font_values( $values ) {
482
483 if ( empty( $values ) ) {
484 return array();
485 }
486
487 foreach ( $values as $key => $value ) {
488
489 if ( strpos( $key, '-' ) !== false ) {
490 $new_key = str_replace( '-', '_', $key );
491
492 $values[ $new_key ] = $value;
493
494 unset( $values[ $key ] );
495 }
496 }
497
498 return $values;
499 }
500
501 function display_selector( $selector ) {
502
503 }
504
505 function display_property( $property, $value, $unit = '' ) {
506 echo $property . ": " . $value . $unit . ";\n";
507 }
508
509 // well weight sometimes comes from google as 600italic which in CSS syntax should come in two separate properties
510 function display_weight_property( $value ) {
511 $has_style = false;
512
513 if ( strpos( $value, 'italic' ) !== false ) {
514
515 $value = str_replace( 'italic', '', $value );
516 echo 'font-weight' . ": " . $value . ";\n";
517 echo 'font-style' . ": italic;\n";
518 $has_style = true;
519 } else {
520 echo 'font-weight' . ": " . $value . ";\n";
521 }
522
523
524 return $has_style;
525 }
526
527 /**
528 * Main Customify_Font_Selector Instance
529 *
530 * Ensures only one instance of Customify_Font_Selector is loaded or can be loaded.
531 *
532 * @since 1.0.0
533 * @static
534 *
535 * @return Customify_Font_Selector Main Customify_Font_Selector instance
536 */
537 public static function instance() {
538
539 if ( is_null( self::$_instance ) ) {
540 self::$_instance = new self();
541 }
542 return self::$_instance;
543 } // End instance ()
544
545 /**
546 * Cloning is forbidden.
547 *
548 * @since 1.0.0
549 */
550 public function __clone() {
551
552 _doing_it_wrong( __FUNCTION__,esc_html( __( 'Cheatin&#8217; huh?' ) ), '' );
553 } // End __clone ()
554
555 /**
556 * Unserializing instances of this class is forbidden.
557 *
558 * @since 1.0.0
559 */
560 public function __wakeup() {
561
562 _doing_it_wrong( __FUNCTION__, esc_html( __( 'Cheatin&#8217; huh?' ) ), '' );
563 } // End __wakeup ()
564 }
565