PluginProbe
Customify / 1.7.4
Customify v1.7.4
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 1.7.4, at features/class-Font_Selector.php

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