PluginProbe
Autoptimize / 3.1.16
Autoptimize v3.1.16
3.1.16 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 All 108 releases
autoptimize / classes / autoptimizeExtra.php

autoptimizeExtra.php in Autoptimize 3.1.16, at classes/autoptimizeExtra.php

663 lines 34.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles autoptimizeExtra frontend features + admin options page
4 */
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 class autoptimizeExtra
11 {
12 /**
13 * Options
14 *
15 * @var array
16 */
17 protected $options = array();
18
19 /**
20 * Singleton instance.
21 *
22 * @var self|null
23 */
24 protected static $instance = null;
25
26 /**
27 * Creates an instance and calls run().
28 *
29 * @param array $options Optional. Allows overriding options without having to specify them via admin options page.
30 */
31 public function __construct( $options = array() )
32 {
33 if ( empty( $options ) ) {
34 $options = self::fetch_options();
35 }
36
37 $this->options = $options;
38 }
39
40 /**
41 * Helper for getting a singleton instance. While being an
42 * anti-pattern generally, it comes in handy for now from a
43 * readability/maintainability perspective, until we get some
44 * proper dependency injection going.
45 *
46 * @return self
47 */
48 public static function instance()
49 {
50 if ( null === self::$instance ) {
51 self::$instance = new self();
52 }
53
54 return self::$instance;
55 }
56
57 public function run()
58 {
59 if ( is_admin() ) {
60 if ( is_multisite() && is_network_admin() && autoptimizeOptionWrapper::is_ao_active_for_network() ) {
61 add_action( 'network_admin_menu', array( $this, 'admin_menu' ) );
62 } else {
63 add_action( 'admin_menu', array( $this, 'admin_menu' ) );
64 }
65 add_filter( 'autoptimize_filter_settingsscreen_tabs', array( $this, 'add_extra_tab' ) );
66 } else {
67 add_action( 'wp', array( $this, 'run_on_frontend' ) );
68 }
69 }
70
71 public function set_options( array $options )
72 {
73 $this->options = $options;
74
75 return $this;
76 }
77
78 public static function fetch_options()
79 {
80 $value = autoptimizeOptionWrapper::get_option( 'autoptimize_extra_settings' );
81 if ( empty( $value ) ) {
82 // Fallback to returning defaults when no stored option exists yet.
83 $value = autoptimizeConfig::get_ao_extra_default_options();
84 }
85
86 return $value;
87 }
88
89 public function disable_emojis()
90 {
91 // Removing all actions related to emojis!
92 remove_action( 'admin_print_styles', 'print_emoji_styles' );
93 remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
94 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
95 remove_action( 'wp_print_styles', 'print_emoji_styles' );
96 remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
97 remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
98 remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
99
100 // Removes TinyMCE emojis.
101 add_filter( 'tiny_mce_plugins', array( $this, 'filter_disable_emojis_tinymce' ) );
102
103 // Removes emoji dns-preftech.
104 add_filter( 'emoji_svg_url', '__return_false' );
105 }
106
107 public function filter_disable_emojis_tinymce( $plugins )
108 {
109 if ( is_array( $plugins ) ) {
110 return array_diff( $plugins, array( 'wpemoji' ) );
111 } else {
112 return array();
113 }
114 }
115
116 public function filter_remove_qs( $src )
117 {
118 if ( ! empty( $src ) ) {
119 if ( strpos( $src, '?ver=' ) ) {
120 $src = remove_query_arg( 'ver', $src );
121 } elseif ( strpos( $src, '?v=' ) ) {
122 $src = remove_query_arg( 'v', $src );
123 }
124 }
125
126 return $src;
127 }
128
129 public function extra_async_js( $in )
130 {
131 $exclusions = array();
132 if ( ! empty( $in ) ) {
133 $exclusions = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $in ) ) ), '' );
134 }
135
136 $settings = wp_strip_all_tags( $this->options['autoptimize_extra_text_field_3'] );
137 $async = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $settings ) ) ), '' );
138 $attr = apply_filters( 'autoptimize_filter_extra_async', 'async' );
139 foreach ( $async as $k => $v ) {
140 $async[ $k ] = $attr;
141 }
142
143 // Merge exclusions & asyncs in one array and return to AO API.
144 $merged = array_merge( $exclusions, $async );
145
146 return $merged;
147 }
148
149 public function run_on_frontend()
150 {
151 // only run the Extra optimizations on frontend if general conditions
152 // for optimizations are met, this to ensure e.g. removing querystrings
153 // is not done when optimizing for logged in users is off, breaking
154 // some pagebuilders (Divi & Elementor).
155 if ( false === autoptimizeMain::should_buffer() ) {
156 return;
157 }
158
159 $options = $this->options;
160
161 // Disable emojis if specified.
162 if ( ! empty( $options['autoptimize_extra_checkbox_field_1'] ) ) {
163 $this->disable_emojis();
164 }
165
166 // Remove version query parameters.
167 if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) ) {
168 add_filter( 'script_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 );
169 add_filter( 'style_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 );
170 }
171
172 // Avoiding conflicts of interest when async-javascript plugin is active!
173 $async_js_plugin_active = autoptimizeUtils::is_plugin_active( 'async-javascript/async-javascript.php' );
174 if ( ! empty( $options['autoptimize_extra_text_field_3'] ) && ! $async_js_plugin_active ) {
175 add_filter( 'autoptimize_filter_js_exclude', array( $this, 'extra_async_js' ), 10, 1 );
176 }
177
178 // Optimize google fonts!
179 if ( ! empty( $options['autoptimize_extra_radio_field_4'] ) && ( '1' !== $options['autoptimize_extra_radio_field_4'] ) ) {
180 add_filter( 'wp_resource_hints', array( $this, 'filter_remove_gfonts_dnsprefetch' ), 10, 2 );
181 add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_optimize_google_fonts' ), 10, 1 );
182 add_filter( 'autoptimize_extra_filter_tobepreconn', array( $this, 'filter_preconnect_google_fonts' ), 10, 1 );
183
184 if ( '2' === $options['autoptimize_extra_radio_field_4'] ) {
185 // remove Google Fonts, adding filters to also remove Google Fonts from 3rd party themes/ plugins.
186 // inspired by https://wordpress.org/plugins/disable-remove-google-fonts/.
187 remove_action( 'wp_footer', 'et_builder_print_font' ); // Divi.
188 remove_action( 'wp_footer', array( 'RevSliderFront', 'load_google_fonts' ) ); // Revslider.
189 add_filter( 'elementor/frontend/print_google_fonts', '__return_false' ); // Elementor.
190 add_filter( 'fl_builder_google_fonts_pre_enqueue', '__return_empty_array' ); // Beaver Builder.
191 }
192 }
193
194 // Preconnect!
195 if ( ! empty( $options['autoptimize_extra_text_field_2'] ) || has_filter( 'autoptimize_extra_filter_tobepreconn' ) ) {
196 add_filter( 'wp_resource_hints', array( $this, 'filter_preconnect' ), 10, 2 );
197 }
198
199 // Preload!
200 if ( ! empty( $options['autoptimize_extra_text_field_7'] ) || has_filter( 'autoptimize_filter_extra_tobepreloaded' ) || ! empty( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) {
201 add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_preload' ), 10, 2 );
202 }
203
204 // Remove global styles.
205 if ( ! empty( $options['autoptimize_extra_checkbox_field_8'] ) ) {
206 $this->disable_global_styles();
207 }
208 }
209
210 public function filter_remove_gfonts_dnsprefetch( $urls, $relation_type )
211 {
212 return $this->filter_remove_dns_prefetch( $urls, $relation_type, 'fonts.googleapis.com' );
213 }
214
215 public function filter_remove_dns_prefetch( $urls, $relation_type, $url_to_remove )
216 {
217 $url_to_remove = (string) $url_to_remove;
218
219 if ( ! empty( $url_to_remove ) && 'dns-prefetch' === $relation_type ) {
220 $cnt = 0;
221 foreach ( $urls as $url ) {
222 // $url can be an array, in which case we need to fetch the value of the href key.
223 if ( is_array( $url ) ) {
224 if ( isset( $url['href'] ) ) {
225 $url = $url['href'];
226 } else {
227 continue;
228 }
229 }
230
231 if ( is_string( $url ) && false !== strpos( $url, $url_to_remove ) ) {
232 unset( $urls[ $cnt ] );
233 }
234 $cnt++;
235 }
236 }
237
238 return $urls;
239 }
240
241 public function filter_optimize_google_fonts( $in )
242 {
243 // Extract fonts, partly based on wp rocket's extraction code.
244 $markup = preg_replace( '/<!--(.*)-->/Uis', '', $in );
245 preg_match_all( '#<link(?:\s+(?:(?!href\s*=\s*)[^>])+)?(?:\s+href\s*=\s*([\'"])((?:https?:)?\/\/fonts\.googleapis\.com\/css(?:(?!\1).)+)\1)(?:\s+[^>]*)?>#iU', $markup, $matches );
246
247 $fonts_collection = array();
248 if ( ! $matches[2] ) {
249 return $in;
250 }
251
252 // Store them in $fonts array.
253 $i = 0;
254 foreach ( $matches[2] as $font ) {
255 if ( ! preg_match( '/rel=["\']dns-prefetch["\']/', $matches[0][ $i ] ) ) {
256 // Get fonts name.
257 $font = str_replace( array( '%7C', '%7c' ), '|', $font );
258 if ( strpos( $font, 'fonts.googleapis.com/css2' ) !== false ) {
259 // (Somewhat) change Google Fonts APIv2 syntax back to v1.
260 // todo: support for 100..900
261 $font = rawurldecode( $font );
262 $font = str_replace( array( 'css2?', 'ital,wght@', 'wght@', 'ital@', '0,', '1,', ':1', ';', '&family=' ), array( 'css?', '', '', '', '', 'italic', ':italic', ',', '%7C' ), $font );
263 }
264 $font = explode( 'family=', $font );
265 $font = ( isset( $font[1] ) ) ? explode( '&', $font[1] ) : array();
266 // Add font to $fonts[$i] but make sure not to pollute with an empty family!
267 $_thisfont = array_values( array_filter( explode( '|', reset( $font ) ) ) );
268 if ( ! empty( $_thisfont ) ) {
269 $fonts_collection[ $i ]['fonts'] = $_thisfont;
270 // And add subset if any!
271 $subset = ( is_array( $font ) ) ? end( $font ) : '';
272 if ( false !== strpos( $subset, 'subset=' ) ) {
273 $subset = str_replace( array( '%2C', '%2c' ), ',', $subset );
274 $subset = explode( 'subset=', $subset );
275 $fonts_collection[ $i ]['subsets'] = explode( ',', $subset[1] );
276 }
277 }
278 // And remove Google Fonts.
279 $in = str_replace( $matches[0][ $i ], '', $in );
280 }
281 $i++;
282 }
283
284 $options = $this->options;
285 $fonts_markup = '';
286 if ( '2' === $options['autoptimize_extra_radio_field_4'] ) {
287 // Remove Google Fonts.
288 unset( $fonts_collection );
289 return $in;
290 } elseif ( '3' === $options['autoptimize_extra_radio_field_4'] || '5' === $options['autoptimize_extra_radio_field_4'] ) {
291 // Aggregate & link!
292 $fonts_string = '';
293 $subset_string = '';
294 foreach ( $fonts_collection as $font ) {
295 $fonts_string .= '|' . trim( implode( '|', $font['fonts'] ), '|' );
296 if ( ! empty( $font['subsets'] ) ) {
297 $subset_string .= ',' . trim( implode( ',', $font['subsets'] ), ',' );
298 }
299 }
300
301 if ( ! empty( $subset_string ) ) {
302 $subset_string = str_replace( ',', '%2C', ltrim( $subset_string, ',' ) );
303 $fonts_string = $fonts_string . '&#038;subset=' . $subset_string;
304 }
305
306 $fonts_string = apply_filters( 'autoptimize_filter_extra_gfont_fontstring', str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) ) );
307 // only add display parameter if there is none in $fonts_string (by virtue of the filter).
308 if ( strpos( $fonts_string, 'display=' ) === false ) {
309 $fonts_string .= apply_filters( 'autoptimize_filter_extra_gfont_display', '&amp;display=swap' );
310 }
311
312 if ( ! empty( $fonts_string ) ) {
313 if ( '5' === $options['autoptimize_extra_radio_field_4'] ) {
314 $rel_string = 'rel="stylesheet" media="print" onload="' . autoptimizeConfig::get_ao_css_preload_onload() . '"';
315 } else {
316 $rel_string = 'rel="stylesheet"';
317 }
318 $fonts_markup = '<link ' . $rel_string . ' id="ao_optimized_gfonts" href="https://fonts.googleapis.com/css?family=' . $fonts_string . '">';
319 }
320 } elseif ( '4' === $options['autoptimize_extra_radio_field_4'] ) {
321 // Aggregate & load async (webfont.js impl.)!
322 $fonts_array = array();
323 foreach ( $fonts_collection as $_fonts ) {
324 if ( ! empty( $_fonts['subsets'] ) ) {
325 $_subset = implode( ',', $_fonts['subsets'] );
326 foreach ( $_fonts['fonts'] as $key => $_one_font ) {
327 $_one_font = $_one_font . ':' . $_subset;
328 $_fonts['fonts'][ $key ] = $_one_font;
329 }
330 }
331 $fonts_array = array_merge( $fonts_array, $_fonts['fonts'] );
332 }
333
334 $fonts_array = array_map( 'urldecode', $fonts_array );
335 $fonts_array = array_map(
336 function( $_f ) {
337 return trim( $_f, ',' );
338 },
339 $fonts_array
340 );
341
342 // type attrib on <script not added by default.
343 $type_js = '';
344 if ( apply_filters( 'autoptimize_filter_cssjs_addtype', false ) ) {
345 $type_js = 'type="text/javascript" ';
346 }
347
348 $fonts_markup = '<script ' . $type_js . 'data-cfasync="false" id="ao_optimized_gfonts_config">WebFontConfig={google:{families:' . wp_json_encode( $fonts_array, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT ) . ' },classes:false, events:false, timeout:1500};</script>';
349 $fonts_library_markup = '<script ' . $type_js . 'data-cfasync="false" id="ao_optimized_gfonts_webfontloader">(function() {var wf = document.createElement(\'script\');wf.src=\'https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js\';wf.type=\'text/javascript\';wf.async=\'true\';var s=document.getElementsByTagName(\'script\')[0];s.parentNode.insertBefore(wf, s);})();</script>';
350 $in = substr_replace( $in, $fonts_library_markup . '</head>', strpos( $in, '</head>' ), strlen( '</head>' ) );
351 }
352
353 // Replace back in markup.
354 $inject_point = apply_filters( 'autoptimize_filter_extra_gfont_injectpoint', '<link' );
355 $out = substr_replace( $in, $fonts_markup . $inject_point, strpos( $in, $inject_point ), strlen( $inject_point ) );
356 unset( $fonts_collection );
357
358 return $out;
359 }
360
361 public function filter_preconnect( $hints, $relation_type )
362 {
363 $options = $this->options;
364 $preconns = array();
365
366 // Get settings and store in array.
367 if ( array_key_exists( 'autoptimize_extra_text_field_2', $options ) ) {
368 $preconns = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( $options['autoptimize_extra_text_field_2'] ) ) ) );
369 }
370 $preconns = apply_filters( 'autoptimize_extra_filter_tobepreconn', $preconns );
371
372 // Walk array, extract domain and add to new array with crossorigin attribute.
373 foreach ( $preconns as $preconn ) {
374 $domain = '';
375 $parsed = parse_url( $preconn );
376 if ( is_array( $parsed ) && ! empty( $parsed['host'] ) && empty( $parsed['scheme'] ) ) {
377 $domain = '//' . $parsed['host'];
378 } elseif ( is_array( $parsed ) && ! empty( $parsed['host'] ) ) {
379 $domain = $parsed['scheme'] . '://' . $parsed['host'];
380 }
381
382 if ( ! empty( $domain ) ) {
383 $hint = array( 'href' => $domain );
384 // Fonts don't get preconnected unless crossorigin flag is set, non-fonts don't get preconnected if origin flag is set
385 // so hardcode fonts.gstatic.com to come with crossorigin and have filter to add other domains if needed.
386 $crossorigins = apply_filters( 'autoptimize_extra_filter_preconn_crossorigin', array( 'https://fonts.gstatic.com' ) );
387 if ( in_array( $domain, $crossorigins ) ) {
388 $hint['crossorigin'] = 'anonymous';
389 }
390 $new_hints[] = $hint;
391 }
392 }
393
394 // Merge in WP's preconnect hints.
395 if ( 'preconnect' === $relation_type && ! empty( $new_hints ) ) {
396 $hints = array_merge( $hints, $new_hints );
397 }
398
399 return $hints;
400 }
401
402 public function filter_preconnect_google_fonts( $in )
403 {
404 if ( '2' !== $this->options['autoptimize_extra_radio_field_4'] ) {
405 // Preconnect to fonts.gstatic.com unless we remove gfonts.
406 $in[] = 'https://fonts.gstatic.com';
407 }
408
409 if ( '4' === $this->options['autoptimize_extra_radio_field_4'] ) {
410 // Preconnect even more hosts for webfont.js!
411 $in[] = 'https://ajax.googleapis.com';
412 $in[] = 'https://fonts.googleapis.com';
413 }
414
415 return $in;
416 }
417
418 public function filter_preload( $in ) {
419 // make array from comma separated list.
420 $options = $this->options;
421 $preloads = array();
422 if ( array_key_exists( 'autoptimize_extra_text_field_7', $options ) ) {
423 $preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( $options['autoptimize_extra_text_field_7'] ) ) ) );
424 }
425
426 if ( false === autoptimizeImages::imgopt_active() && false === autoptimizeImages::should_lazyload_wrapper() ) {
427 // only do this here if imgopt/ lazyload are not active?
428 $metabox_preloads = array_filter( array_map( 'trim', explode( ',', wp_strip_all_tags( autoptimizeConfig::get_post_meta_ao_settings( 'ao_post_preload' ) ) ) ) );
429 if ( ! empty( $metabox_preloads ) ) {
430 $preloads = array_merge( $preloads, $metabox_preloads );
431 }
432 }
433
434 $preloads = apply_filters( 'autoptimize_filter_extra_tobepreloaded', $preloads );
435
436 // immediately return if nothing to be preloaded.
437 if ( empty( $preloads ) ) {
438 return $in;
439 }
440
441 // iterate through array and add preload link to tmp string.
442 $preload_output = '';
443 foreach ( $preloads as $preload ) {
444 if ( filter_var( $preload, FILTER_VALIDATE_URL ) !== $preload ) {
445 continue;
446 }
447 $preload = esc_url_raw( $preload );
448 $crossorigin = '';
449 $preload_as = '';
450 $mime_type = '';
451 $_preload = strtok( $preload, '?' );
452
453 if ( autoptimizeUtils::str_ends_in( $_preload, '.css' ) ) {
454 $preload_as = 'style';
455 } elseif ( autoptimizeUtils::str_ends_in( $_preload, '.js' ) ) {
456 $preload_as = 'script';
457 } elseif ( autoptimizeUtils::str_ends_in( $_preload, '.woff' ) || autoptimizeUtils::str_ends_in( $_preload, '.woff2' ) || autoptimizeUtils::str_ends_in( $_preload, '.ttf' ) || autoptimizeUtils::str_ends_in( $_preload, '.eot' ) || autoptimizeUtils::str_ends_in( $_preload, '.otf' ) ) {
458 $preload_as = 'font';
459 $crossorigin = ' crossorigin';
460 $mime_type = ' type="font/' . pathinfo( $_preload, PATHINFO_EXTENSION ) . '"';
461 if ( ' type="font/eot"' === $mime_type ) {
462 $mime_type = 'application/vnd.ms-fontobject';
463 }
464 } elseif ( autoptimizeUtils::str_ends_in( $_preload, '.jpeg' ) || autoptimizeUtils::str_ends_in( $_preload, '.jpg' ) || autoptimizeUtils::str_ends_in( $_preload, '.webp' ) || autoptimizeUtils::str_ends_in( $_preload, '.png' ) || autoptimizeUtils::str_ends_in( $_preload, '.gif' ) || autoptimizeUtils::str_ends_in( $_preload, '.svg' ) ) {
465 $preload_as = 'image';
466 } else {
467 $preload_as = 'other';
468 }
469
470 $preload_output .= '<link rel="preload" fetchpriority="high" href="' . $preload . '" as="' . $preload_as . '"' . $mime_type . $crossorigin . '>';
471 }
472 $preload_output = apply_filters( 'autoptimize_filter_extra_preload_output', $preload_output );
473
474 return $this->inject_preloads( $preload_output, $in );
475 }
476
477 public static function inject_preloads( $preloads, $html ) {
478 // add string to head (before first link node by default).
479 $preload_inject = apply_filters( 'autoptimize_filter_extra_preload_inject', '<link' );
480 $position = autoptimizeUtils::strpos( $html, $preload_inject );
481
482 return autoptimizeUtils::substr_replace( $html, $preloads . $preload_inject, $position, strlen( $preload_inject ) );
483 }
484
485 public function disable_global_styles()
486 {
487 remove_action( 'wp_enqueue_scripts', 'wp_enqueue_global_styles' );
488 remove_action( 'wp_footer', 'wp_enqueue_global_styles', 1 );
489 remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
490
491 if ( true === apply_filters( 'autoptimize_filter_extra_global_styles_and_block_css', true ) ) {
492 add_action(
493 'wp_enqueue_scripts',
494 function() {
495 wp_dequeue_style( 'wp-block-library' );
496 wp_dequeue_style( 'wp-block-library-theme' );
497 }
498 );
499 }
500
501 if ( true === apply_filters( 'autoptimize_filter_extra_remove_woocommerce_block_css', true ) ) {
502 add_action(
503 'wp_enqueue_scripts',
504 function() {
505 wp_dequeue_style( 'wc-blocks-style' );
506 }
507 );
508 }
509 }
510
511 public function admin_menu()
512 {
513 // no acces if multisite and not network admin and no site config allowed.
514 if ( autoptimizeConfig::should_show_menu_tabs() ) {
515 add_submenu_page(
516 '',
517 'autoptimize_extra',
518 'autoptimize_extra',
519 'manage_options',
520 'autoptimize_extra',
521 array( $this, 'options_page' )
522 );
523 }
524 register_setting( 'autoptimize_extra_settings', 'autoptimize_extra_settings' );
525 }
526
527 public function add_extra_tab( $in )
528 {
529 if ( autoptimizeConfig::should_show_menu_tabs() ) {
530 $in = array_merge( $in, array( 'autoptimize_extra' => esc_html__( 'Extra', 'autoptimize' ) ) );
531 }
532
533 return $in;
534 }
535
536 public function options_page()
537 {
538 // phpcs:disable Squiz.ControlStructures.ControlSignature.NewlineAfterOpenBrace
539
540 // Working with actual option values from the database here.
541 // That way any saves are still processed as expected, but we can still
542 // override behavior by using `new autoptimizeExtra($custom_options)` and not have that custom
543 // behavior being persisted in the DB even if save is done here.
544 $options = $this->fetch_options();
545 $gfonts = $options['autoptimize_extra_radio_field_4'];
546 ?>
547 <style>
548 #ao_settings_form {background: white;border: 1px solid #ccc;padding: 1px 15px;margin: 15px 10px 10px 0;}
549 #ao_settings_form .form-table th {font-weight: normal;}
550 #autoptimize_extra_descr{font-size: 120%;}
551 </style>
552 <script>document.title = "Autoptimize: <?php esc_html_e( 'Extra', 'autoptimize' ); ?> " + document.title;</script>
553 <div class="wrap">
554 <h1><?php apply_filters( 'autoptimize_filter_settings_is_pro', false ) ? esc_html_e( 'Autoptimize Pro Settings', 'autoptimize' ) : esc_html_e( 'Autoptimize Settings', 'autoptimize' ); ?></h1>
555 <?php echo autoptimizeConfig::ao_admin_tabs(); ?>
556 <?php if ( 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_js' ) && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_css' ) && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_html' ) && ! autoptimizeImages::imgopt_active() ) { ?>
557 <div class="notice-warning notice"><p>
558 <?php esc_html_e( 'Most of below Extra optimizations require at least one of HTML, JS, CSS or Image autoptimizations being active.', 'autoptimize' ); ?>
559 </p></div>
560 <?php } ?>
561
562 <form id='ao_settings_form' action='<?php echo admin_url( 'options.php' ); ?>' method='post'>
563 <?php settings_fields( 'autoptimize_extra_settings' ); ?>
564 <h2><?php esc_html_e( 'Extra Auto-Optimizations', 'autoptimize' ); ?></h2>
565 <span id='autoptimize_extra_descr'><?php esc_html_e( 'The following settings can improve your site\'s performance even more.', 'autoptimize' ); ?></span>
566 <table class="form-table">
567 <tr>
568 <th scope="row"><?php esc_html_e( 'Google Fonts', 'autoptimize' ); ?></th>
569 <td>
570 <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="1" <?php if ( ! in_array( $gfonts, array( 2, 3, 4, 5 ) ) ) { echo 'checked'; } ?> ><?php esc_html_e( 'Leave as is', 'autoptimize' ); ?><br/>
571 <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="2" <?php checked( 2, $gfonts, true ); ?> ><?php esc_html_e( 'Remove Google Fonts', 'autoptimize' ); ?><br/>
572 <?php // translators: "display:swap" should remain untranslated, will be shown in code tags. ?>
573 <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="3" <?php checked( 3, $gfonts, true ); ?> ><?php echo esc_html__( 'Combine and link in head (fonts load fast but are render-blocking)', 'autoptimize' ) . ', ' . sprintf( esc_html__( 'includes %1$sdisplay:swap%2$s.', 'autoptimize' ), '<code>', '</code>' ); ?><br/>
574 <?php // translators: "display:swap" should remain untranslated, will be shown in code tags. ?>
575 <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="5" <?php checked( 5, $gfonts, true ); ?> ><?php echo esc_html__( 'Combine and link deferred in head (fonts load late, but are not render-blocking)', 'autoptimize' ) . ', ' . sprintf( esc_html__( 'includes %1$sdisplay:swap%2$s.', 'autoptimize' ), '<code>', '</code>' ); ?>
576 <span <?php if ( '4' !== $gfonts ){ echo "style='display:none;' "; } ?> ><br/><input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="4" <?php checked( 4, $gfonts, true ); ?> ><?php echo sprintf( esc_html__( 'Combine and load fonts asynchronously with %1$swebfont.js%2$s', 'autoptimize' ), '<a href="https://github.com/typekit/webfontloader#readme" target="_blank">', '</a>' ) . ' ' . esc_html__( '(deprecated)', 'autoptimize' ); ?></span><br/>
577 </td>
578 </tr>
579 <tr>
580 <th scope="row"><?php esc_html_e( 'Remove emojis', 'autoptimize' ); ?></th>
581 <td>
582 <label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_1]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_1'] ) && '1' === $options['autoptimize_extra_checkbox_field_1'] ) { echo 'checked="checked"'; } ?> value='1'><?php esc_html_e( 'Removes WordPress\' core emojis\' inline CSS, inline JavaScript, and an otherwise un-autoptimized JavaScript file.', 'autoptimize' ); ?></label>
583 </td>
584 </tr>
585 <tr>
586 <th scope="row"><?php esc_html_e( 'Remove query strings from static resources', 'autoptimize' ); ?></th>
587 <td>
588 <label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_0]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) && '1' === $options['autoptimize_extra_checkbox_field_0'] ) { echo 'checked="checked"'; } ?> value='1'>
589 <?php
590 // translators: just a code tag around "ver" which is the parameter added to CSS/ JS URL's by wordpress.
591 printf( esc_html__( 'Removing query strings (or more specifically the %1$sver%2$s parameter) will not improve load time, but might improve performance scores.', 'autoptimize' ), '<code>', '</code>' );
592 ?>
593 </label>
594 </td>
595 </tr>
596 <tr>
597 <th scope="row"><?php esc_html_e( 'Remove WordPress block CSS', 'autoptimize' ); ?></th>
598 <td>
599 <label><input type='checkbox' name='autoptimize_extra_settings[autoptimize_extra_checkbox_field_8]' <?php if ( ! empty( $options['autoptimize_extra_checkbox_field_8'] ) && '1' === $options['autoptimize_extra_checkbox_field_8'] ) { echo 'checked="checked"'; } ?> value='1'><?php esc_html_e( 'WordPress adds block CSS and global styles to improve easy styling of block-based sites, but which can add a significant amount of CSS and SVG. If you are sure your site can do without the block CSS and "global styles", you can disable them here.', 'autoptimize' ); ?></label>
600 </td>
601 </tr>
602 <tr>
603 <th scope="row"><?php esc_html_e( 'Preconnect to 3rd party domains (advanced users)', 'autoptimize' ); ?></th>
604 <td>
605 <label><input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_2]' value='<?php if ( array_key_exists( 'autoptimize_extra_text_field_2', $options ) ) { echo esc_attr( $options['autoptimize_extra_text_field_2'] ); } ?>'><br />
606 <?php
607 // Translators; link to a page on keycdn blog about preconnecting.
608 printf( esc_html__( 'Add 3rd party domains you want the browser to %1$spreconnect%2$s to, separated by comma\'s. Make sure to include the correct protocol (HTTP or HTTPS).', 'autoptimize' ), '<a href="https://www.keycdn.com/support/preconnect/#primary" target="_blank">', '</a>' );
609 ?>
610 </label>
611 </td>
612 </tr>
613 <tr>
614 <th scope="row"><?php esc_html_e( 'Preload specific requests (advanced users)', 'autoptimize' ); ?></th>
615 <td>
616 <label><input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_7]' value='<?php if ( array_key_exists( 'autoptimize_extra_text_field_7', $options ) ) { echo esc_attr( $options['autoptimize_extra_text_field_7'] ); } ?>'><br /><?php esc_html_e( 'Comma-separated list with full URL\'s of to to-be-preloaded resources. To be used sparingly!', 'autoptimize' ); ?></label>
617 </td>
618 </tr>
619 <tr>
620 <th scope="row"><?php esc_html_e( 'Async Javascript-files (advanced users)', 'autoptimize' ); ?></th>
621 <td>
622 <?php
623 if ( autoptimizeUtils::is_plugin_active( 'async-javascript/async-javascript.php' ) ) {
624 // translators: link points Async Javascript settings page.
625 printf( esc_html__( 'You have "Async JavaScript" installed, %1$sconfiguration of async javascript is best done there%2$s.', 'autoptimize' ), '<a href="' . 'options-general.php?page=async-javascript' . '">', '</a>' );
626 } else {
627 ?>
628 <input type='text' style='width:80%' name='autoptimize_extra_settings[autoptimize_extra_text_field_3]' value='<?php if ( array_key_exists( 'autoptimize_extra_text_field_3', $options ) ) { echo esc_attr( $options['autoptimize_extra_text_field_3'] ); } ?>'>
629 <br />
630 <?php
631 printf( esc_html__( 'Comma-separated list of local or 3rd party JS-files that should loaded with the %1$sasync%2$s flag. JS-files from your own site will be automatically excluded if added here. ', 'autoptimize' ), '<code>', '</code>' );
632 // translators: %s will be replaced by a link to the "async javascript" plugin.
633 echo sprintf( esc_html__( 'Configuration of async javascript is easier and more flexible using the %s plugin.', 'autoptimize' ), '"<a href="https://wordpress.org/plugins/async-javascript" target="_blank">Async Javascript</a>"' );
634 $asj_install_url = network_admin_url() . 'plugin-install.php?s=async+javascript&tab=search&type=term';
635 echo sprintf( ' <a href="' . $asj_install_url . '">%s</a>', esc_html__( 'Click here to install and activate it.', 'autoptimize' ) );
636 }
637 ?>
638 </td>
639 </tr>
640 <tr>
641 <th scope="row"><?php esc_html_e( 'Optimize YouTube videos', 'autoptimize' ); ?></th>
642 <td>
643 <?php
644 if ( autoptimizeUtils::is_plugin_active( 'wp-youtube-lyte/wp-youtube-lyte.php' ) ) {
645 esc_html_e( 'Great, you have WP YouTube Lyte installed.', 'autoptimize' );
646 $lyte_config_url = 'options-general.php?page=lyte_settings_page';
647 echo sprintf( ' <a href="' . $lyte_config_url . '">%s</a>', esc_html__( 'Click here to configure it.', 'autoptimize' ) );
648 } else {
649 // translators: %s will be replaced by a link to "wp youtube lyte" plugin.
650 echo sprintf( esc_html__( '%s allows you to “lazy load” your videos, by inserting responsive “Lite YouTube Embeds". ', 'autoptimize' ), '<a href="https://wordpress.org/plugins/wp-youtube-lyte" target="_blank">WP YouTube Lyte</a>' );
651 $lyte_install_url = network_admin_url() . 'plugin-install.php?s=lyte&tab=search&type=term';
652 echo sprintf( ' <a href="' . $lyte_install_url . '">%s</a>', esc_html__( 'Click here to install and activate it.', 'autoptimize' ) );
653 }
654 ?>
655 </td>
656 </tr>
657 </table>
658 <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_html_e( 'Save Changes', 'autoptimize' ); ?>" /></p>
659 </form>
660 <?php
661 }
662 }
663