This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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; |
||
0 ignored issues
–
show
|
|||
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 | View Code Duplication | public function run() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
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( 'wp_resource_hints', array( $this, 'filter_remove_emoji_dns_prefetch' ), 10, 2 ); |
||
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 ( strpos( $src, '?ver=' ) ) { |
||
119 | $src = remove_query_arg( 'ver', $src ); |
||
120 | } |
||
121 | |||
122 | return $src; |
||
123 | } |
||
124 | |||
125 | public function extra_async_js( $in ) |
||
126 | { |
||
127 | $exclusions = array(); |
||
128 | View Code Duplication | if ( ! empty( $in ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
129 | $exclusions = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $in ) ) ), '' ); |
||
130 | } |
||
131 | |||
132 | $settings = $this->options['autoptimize_extra_text_field_3']; |
||
133 | $async = array_fill_keys( array_filter( array_map( 'trim', explode( ',', $settings ) ) ), '' ); |
||
134 | $attr = apply_filters( 'autoptimize_filter_extra_async', 'async' ); |
||
135 | foreach ( $async as $k => $v ) { |
||
136 | $async[ $k ] = $attr; |
||
137 | } |
||
138 | |||
139 | // Merge exclusions & asyncs in one array and return to AO API. |
||
140 | $merged = array_merge( $exclusions, $async ); |
||
141 | |||
142 | return $merged; |
||
143 | } |
||
144 | |||
145 | public function run_on_frontend() |
||
146 | { |
||
147 | // only run the Extra optimizations on frontend if general conditions |
||
148 | // for optimizations are met, this to ensure e.g. removing querystrings |
||
149 | // is not done when optimizing for logged in users is off, breaking |
||
150 | // some pagebuilders (Divi & Elementor). |
||
151 | if ( false === autoptimizeMain::should_buffer() ) { |
||
152 | return; |
||
153 | } |
||
154 | |||
155 | $options = $this->options; |
||
156 | |||
157 | // Disable emojis if specified. |
||
158 | if ( ! empty( $options['autoptimize_extra_checkbox_field_1'] ) ) { |
||
159 | $this->disable_emojis(); |
||
160 | } |
||
161 | |||
162 | // Remove version query parameters. |
||
163 | if ( ! empty( $options['autoptimize_extra_checkbox_field_0'] ) ) { |
||
164 | add_filter( 'script_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 ); |
||
165 | add_filter( 'style_loader_src', array( $this, 'filter_remove_qs' ), 15, 1 ); |
||
166 | } |
||
167 | |||
168 | // Avoiding conflicts of interest when async-javascript plugin is active! |
||
169 | $async_js_plugin_active = autoptimizeUtils::is_plugin_active( 'async-javascript/async-javascript.php' ); |
||
170 | if ( ! empty( $options['autoptimize_extra_text_field_3'] ) && ! $async_js_plugin_active ) { |
||
171 | add_filter( 'autoptimize_filter_js_exclude', array( $this, 'extra_async_js' ), 10, 1 ); |
||
172 | } |
||
173 | |||
174 | // Optimize google fonts! |
||
175 | if ( ! empty( $options['autoptimize_extra_radio_field_4'] ) && ( '1' !== $options['autoptimize_extra_radio_field_4'] ) ) { |
||
176 | add_filter( 'wp_resource_hints', array( $this, 'filter_remove_gfonts_dnsprefetch' ), 10, 2 ); |
||
177 | add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_optimize_google_fonts' ), 10, 1 ); |
||
178 | add_filter( 'autoptimize_extra_filter_tobepreconn', array( $this, 'filter_preconnect_google_fonts' ), 10, 1 ); |
||
179 | } |
||
180 | |||
181 | // Preconnect! |
||
182 | if ( ! empty( $options['autoptimize_extra_text_field_2'] ) || has_filter( 'autoptimize_extra_filter_tobepreconn' ) ) { |
||
183 | add_filter( 'wp_resource_hints', array( $this, 'filter_preconnect' ), 10, 2 ); |
||
184 | } |
||
185 | |||
186 | // Preload! |
||
187 | if ( ! empty( $options['autoptimize_extra_text_field_7'] ) || has_filter( 'autoptimize_filter_extra_tobepreloaded' ) ) { |
||
188 | add_filter( 'autoptimize_html_after_minify', array( $this, 'filter_preload' ), 10, 2 ); |
||
189 | } |
||
190 | } |
||
191 | |||
192 | public function filter_remove_emoji_dns_prefetch( $urls, $relation_type ) |
||
193 | { |
||
194 | $emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/' ); |
||
195 | |||
196 | return $this->filter_remove_dns_prefetch( $urls, $relation_type, $emoji_svg_url ); |
||
197 | } |
||
198 | |||
199 | public function filter_remove_gfonts_dnsprefetch( $urls, $relation_type ) |
||
200 | { |
||
201 | return $this->filter_remove_dns_prefetch( $urls, $relation_type, 'fonts.googleapis.com' ); |
||
202 | } |
||
203 | |||
204 | public function filter_remove_dns_prefetch( $urls, $relation_type, $url_to_remove ) |
||
205 | { |
||
206 | $url_to_remove = (string) $url_to_remove; |
||
207 | |||
208 | if ( ! empty( $url_to_remove ) && 'dns-prefetch' === $relation_type ) { |
||
209 | $cnt = 0; |
||
210 | foreach ( $urls as $url ) { |
||
211 | if ( false !== strpos( $url, $url_to_remove ) ) { |
||
212 | unset( $urls[ $cnt ] ); |
||
213 | } |
||
214 | $cnt++; |
||
215 | } |
||
216 | } |
||
217 | |||
218 | return $urls; |
||
219 | } |
||
220 | |||
221 | public function filter_optimize_google_fonts( $in ) |
||
222 | { |
||
223 | // Extract fonts, partly based on wp rocket's extraction code. |
||
224 | $markup = preg_replace( '/<!--(.*)-->/Uis', '', $in ); |
||
225 | preg_match_all( '#<link(?:\s+(?:(?!href\s*=\s*)[^>])+)?(?:\s+href\s*=\s*([\'"])((?:https?:)?\/\/fonts\.googleapis\.com\/css(?:(?!\1).)+)\1)(?:\s+[^>]*)?>#iU', $markup, $matches ); |
||
226 | |||
227 | $fonts_collection = array(); |
||
228 | if ( ! $matches[2] ) { |
||
229 | return $in; |
||
230 | } |
||
231 | |||
232 | // Store them in $fonts array. |
||
233 | $i = 0; |
||
234 | foreach ( $matches[2] as $font ) { |
||
235 | if ( ! preg_match( '/rel=["\']dns-prefetch["\']/', $matches[0][ $i ] ) ) { |
||
236 | // Get fonts name. |
||
237 | $font = str_replace( array( '%7C', '%7c' ), '|', $font ); |
||
238 | if ( strpos( $font, 'fonts.googleapis.com/css2' ) !== false ) { |
||
239 | // (Somewhat) change Google Fonts APIv2 syntax back to v1. |
||
240 | // todo: support for 100..900 |
||
241 | $font = rawurldecode( $font ); |
||
242 | $font = str_replace( array( 'css2?', 'ital,wght@', 'wght@', 'ital@', '0,', '1,', ':1', ';', '&family=' ), array( 'css?', '', '', '', '', 'italic', ':italic', ',', '%7C' ), $font ); |
||
243 | } |
||
244 | $font = explode( 'family=', $font ); |
||
245 | $font = ( isset( $font[1] ) ) ? explode( '&', $font[1] ) : array(); |
||
246 | // Add font to $fonts[$i] but make sure not to pollute with an empty family! |
||
247 | $_thisfont = array_values( array_filter( explode( '|', reset( $font ) ) ) ); |
||
248 | if ( ! empty( $_thisfont ) ) { |
||
249 | $fonts_collection[ $i ]['fonts'] = $_thisfont; |
||
250 | // And add subset if any! |
||
251 | $subset = ( is_array( $font ) ) ? end( $font ) : ''; |
||
252 | if ( false !== strpos( $subset, 'subset=' ) ) { |
||
253 | $subset = str_replace( array( '%2C', '%2c' ), ',', $subset ); |
||
254 | $subset = explode( 'subset=', $subset ); |
||
255 | $fonts_collection[ $i ]['subsets'] = explode( ',', $subset[1] ); |
||
256 | } |
||
257 | } |
||
258 | // And remove Google Fonts. |
||
259 | $in = str_replace( $matches[0][ $i ], '', $in ); |
||
260 | } |
||
261 | $i++; |
||
262 | } |
||
263 | |||
264 | $options = $this->options; |
||
265 | $fonts_markup = ''; |
||
266 | if ( '2' === $options['autoptimize_extra_radio_field_4'] ) { |
||
267 | // Remove Google Fonts. |
||
268 | unset( $fonts_collection ); |
||
269 | return $in; |
||
270 | } elseif ( '3' === $options['autoptimize_extra_radio_field_4'] || '5' === $options['autoptimize_extra_radio_field_4'] ) { |
||
271 | // Aggregate & link! |
||
272 | $fonts_string = ''; |
||
273 | $subset_string = ''; |
||
274 | foreach ( $fonts_collection as $font ) { |
||
275 | $fonts_string .= '|' . trim( implode( '|', $font['fonts'] ), '|' ); |
||
276 | if ( ! empty( $font['subsets'] ) ) { |
||
277 | $subset_string .= ',' . trim( implode( ',', $font['subsets'] ), ',' ); |
||
278 | } |
||
279 | } |
||
280 | |||
281 | if ( ! empty( $subset_string ) ) { |
||
282 | $subset_string = str_replace( ',', '%2C', ltrim( $subset_string, ',' ) ); |
||
283 | $fonts_string = $fonts_string . '&subset=' . $subset_string; |
||
284 | } |
||
285 | |||
286 | $fonts_string = apply_filters( 'autoptimize_filter_extra_gfont_fontstring', str_replace( '|', '%7C', ltrim( $fonts_string, '|' ) ) ); |
||
287 | // only add display parameter if there is none in $fonts_string (by virtue of the filter). |
||
288 | if ( strpos( $fonts_string, 'display=' ) === false ) { |
||
289 | $fonts_string .= apply_filters( 'autoptimize_filter_extra_gfont_display', '&display=swap' ); |
||
290 | } |
||
291 | |||
292 | if ( ! empty( $fonts_string ) ) { |
||
293 | if ( '5' === $options['autoptimize_extra_radio_field_4'] ) { |
||
294 | $rel_string = 'rel="stylesheet" media="print" onload="' . autoptimizeConfig::get_ao_css_preload_onload() . '"'; |
||
295 | } else { |
||
296 | $rel_string = 'rel="stylesheet"'; |
||
297 | } |
||
298 | $fonts_markup = '<link ' . $rel_string . ' id="ao_optimized_gfonts" href="https://fonts.googleapis.com/css?family=' . $fonts_string . '" />'; |
||
299 | } |
||
300 | } elseif ( '4' === $options['autoptimize_extra_radio_field_4'] ) { |
||
301 | // Aggregate & load async (webfont.js impl.)! |
||
302 | $fonts_array = array(); |
||
303 | foreach ( $fonts_collection as $_fonts ) { |
||
304 | if ( ! empty( $_fonts['subsets'] ) ) { |
||
305 | $_subset = implode( ',', $_fonts['subsets'] ); |
||
306 | foreach ( $_fonts['fonts'] as $key => $_one_font ) { |
||
307 | $_one_font = $_one_font . ':' . $_subset; |
||
308 | $_fonts['fonts'][ $key ] = $_one_font; |
||
309 | } |
||
310 | } |
||
311 | $fonts_array = array_merge( $fonts_array, $_fonts['fonts'] ); |
||
312 | } |
||
313 | |||
314 | $fonts_array = array_map( 'urldecode', $fonts_array ); |
||
315 | $fonts_array = array_map( |
||
316 | function( $_f ) { |
||
317 | return trim( $_f, ',' ); |
||
318 | }, |
||
319 | $fonts_array |
||
320 | ); |
||
321 | |||
322 | // type attrib on <script not added by default. |
||
323 | $type_js = ''; |
||
324 | if ( apply_filters( 'autoptimize_filter_cssjs_addtype', false ) ) { |
||
325 | $type_js = 'type="text/javascript" '; |
||
326 | } |
||
327 | |||
328 | $fonts_markup = '<script ' . $type_js . 'data-cfasync="false" id="ao_optimized_gfonts_config">WebFontConfig={google:{families:' . wp_json_encode( $fonts_array ) . ' },classes:false, events:false, timeout:1500};</script>'; |
||
329 | $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>'; |
||
330 | $in = substr_replace( $in, $fonts_library_markup . '</head>', strpos( $in, '</head>' ), strlen( '</head>' ) ); |
||
331 | } |
||
332 | |||
333 | // Replace back in markup. |
||
334 | $inject_point = apply_filters( 'autoptimize_filter_extra_gfont_injectpoint', '<link' ); |
||
335 | $out = substr_replace( $in, $fonts_markup . $inject_point, strpos( $in, $inject_point ), strlen( $inject_point ) ); |
||
336 | unset( $fonts_collection ); |
||
337 | |||
338 | return $out; |
||
339 | } |
||
340 | |||
341 | public function filter_preconnect( $hints, $relation_type ) |
||
342 | { |
||
343 | $options = $this->options; |
||
344 | $preconns = array(); |
||
345 | |||
346 | // Get settings and store in array. |
||
347 | View Code Duplication | if ( array_key_exists( 'autoptimize_extra_text_field_2', $options ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
348 | $preconns = array_filter( array_map( 'trim', explode( ',', $options['autoptimize_extra_text_field_2'] ) ) ); |
||
349 | } |
||
350 | $preconns = apply_filters( 'autoptimize_extra_filter_tobepreconn', $preconns ); |
||
351 | |||
352 | // Walk array, extract domain and add to new array with crossorigin attribute. |
||
353 | foreach ( $preconns as $preconn ) { |
||
354 | $domain = ''; |
||
355 | $parsed = parse_url( $preconn ); |
||
356 | if ( is_array( $parsed ) && ! empty( $parsed['host'] ) && empty( $parsed['scheme'] ) ) { |
||
357 | $domain = '//' . $parsed['host']; |
||
358 | } elseif ( is_array( $parsed ) && ! empty( $parsed['host'] ) ) { |
||
359 | $domain = $parsed['scheme'] . '://' . $parsed['host']; |
||
360 | } |
||
361 | |||
362 | if ( ! empty( $domain ) ) { |
||
363 | $hint = array( 'href' => $domain ); |
||
364 | // Fonts don't get preconnected unless crossorigin flag is set, non-fonts don't get preconnected if origin flag is set |
||
365 | // so hardcode fonts.gstatic.com to come with crossorigin and have filter to add other domains if needed. |
||
366 | $crossorigins = apply_filters( 'autoptimize_extra_filter_preconn_crossorigin', array( 'https://fonts.gstatic.com' ) ); |
||
367 | if ( in_array( $domain, $crossorigins ) ) { |
||
368 | $hint['crossorigin'] = 'anonymous'; |
||
369 | } |
||
370 | $new_hints[] = $hint; |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
$new_hints was never initialized. Although not strictly required by PHP, it is generally a good practice to add $new_hints = array(); before regardless.
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code. Let’s take a look at an example: foreach ($collection as $item) {
$myArray['foo'] = $item->getFoo();
if ($item->hasBar()) {
$myArray['bar'] = $item->getBar();
}
// do something with $myArray
}
As you can see in this example, the array This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop. ![]() |
|||
371 | } |
||
372 | } |
||
373 | |||
374 | // Merge in WP's preconnect hints. |
||
375 | if ( 'preconnect' === $relation_type && ! empty( $new_hints ) ) { |
||
376 | $hints = array_merge( $hints, $new_hints ); |
||
377 | } |
||
378 | |||
379 | return $hints; |
||
380 | } |
||
381 | |||
382 | public function filter_preconnect_google_fonts( $in ) |
||
383 | { |
||
384 | if ( '2' !== $this->options['autoptimize_extra_radio_field_4'] ) { |
||
385 | // Preconnect to fonts.gstatic.com unless we remove gfonts. |
||
386 | $in[] = 'https://fonts.gstatic.com'; |
||
387 | } |
||
388 | |||
389 | if ( '4' === $this->options['autoptimize_extra_radio_field_4'] ) { |
||
390 | // Preconnect even more hosts for webfont.js! |
||
391 | $in[] = 'https://ajax.googleapis.com'; |
||
392 | $in[] = 'https://fonts.googleapis.com'; |
||
393 | } |
||
394 | |||
395 | return $in; |
||
396 | } |
||
397 | |||
398 | public function filter_preload( $in ) { |
||
399 | // make array from comma separated list. |
||
400 | $options = $this->options; |
||
401 | $preloads = array(); |
||
402 | View Code Duplication | if ( array_key_exists( 'autoptimize_extra_text_field_7', $options ) ) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
403 | $preloads = array_filter( array_map( 'trim', explode( ',', $options['autoptimize_extra_text_field_7'] ) ) ); |
||
404 | } |
||
405 | $preloads = apply_filters( 'autoptimize_filter_extra_tobepreloaded', $preloads ); |
||
406 | |||
407 | // immediately return if nothing to be preloaded. |
||
408 | if ( empty( $preloads ) ) { |
||
409 | return $in; |
||
410 | } |
||
411 | |||
412 | // iterate through array and add preload link to tmp string. |
||
413 | $preload_output = ''; |
||
414 | foreach ( $preloads as $preload ) { |
||
415 | $crossorigin = ''; |
||
416 | $preload_as = ''; |
||
0 ignored issues
–
show
$preload_as is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
417 | $mime_type = ''; |
||
418 | $_preload = strtok( $preload, '?' ); |
||
419 | |||
420 | if ( autoptimizeUtils::str_ends_in( $_preload, '.css' ) ) { |
||
421 | $preload_as = 'style'; |
||
422 | } elseif ( autoptimizeUtils::str_ends_in( $_preload, '.js' ) ) { |
||
423 | $preload_as = 'script'; |
||
424 | } 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' ) ) { |
||
425 | $preload_as = 'font'; |
||
426 | $crossorigin = ' crossorigin'; |
||
427 | $mime_type = ' type="font/' . pathinfo( $_preload, PATHINFO_EXTENSION ) . '"'; |
||
428 | if ( ' type="font/eot"' === $mime_type ) { |
||
429 | $mime_type = 'application/vnd.ms-fontobject'; |
||
430 | } |
||
431 | } 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' ) ) { |
||
432 | $preload_as = 'image'; |
||
433 | } else { |
||
434 | $preload_as = 'other'; |
||
435 | } |
||
436 | |||
437 | $preload_output .= '<link rel="preload" href="' . $preload . '" as="' . $preload_as . '"' . $mime_type . $crossorigin . '>'; |
||
438 | } |
||
439 | $preload_output = apply_filters( 'autoptimize_filter_extra_preload_output', $preload_output ); |
||
440 | |||
441 | // add string to head (before first link node by default). |
||
442 | $preload_inject = apply_filters( 'autoptimize_filter_extra_preload_inject', '<link' ); |
||
443 | $position = autoptimizeUtils::strpos( $in, $preload_inject ); |
||
444 | |||
445 | return autoptimizeUtils::substr_replace( $in, $preload_output . $preload_inject, $position, strlen( $preload_inject ) ); |
||
0 ignored issues
–
show
It seems like
$position defined by \autoptimizeUtils::strpos($in, $preload_inject) on line 443 can also be of type false ; however, autoptimizeUtils::substr_replace() does only seem to accept integer , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
|||
446 | } |
||
447 | |||
448 | public function admin_menu() |
||
449 | { |
||
450 | // no acces if multisite and not network admin and no site config allowed. |
||
451 | if ( autoptimizeConfig::should_show_menu_tabs() ) { |
||
452 | add_submenu_page( |
||
453 | null, |
||
454 | 'autoptimize_extra', |
||
455 | 'autoptimize_extra', |
||
456 | 'manage_options', |
||
457 | 'autoptimize_extra', |
||
458 | array( $this, 'options_page' ) |
||
459 | ); |
||
460 | } |
||
461 | register_setting( 'autoptimize_extra_settings', 'autoptimize_extra_settings' ); |
||
462 | } |
||
463 | |||
464 | public function add_extra_tab( $in ) |
||
465 | { |
||
466 | if ( autoptimizeConfig::should_show_menu_tabs() ) { |
||
467 | $in = array_merge( $in, array( 'autoptimize_extra' => __( 'Extra', 'autoptimize' ) ) ); |
||
468 | } |
||
469 | |||
470 | return $in; |
||
471 | } |
||
472 | |||
473 | public function options_page() |
||
474 | { |
||
475 | // Working with actual option values from the database here. |
||
476 | // That way any saves are still processed as expected, but we can still |
||
477 | // override behavior by using `new autoptimizeExtra($custom_options)` and not have that custom |
||
478 | // behavior being persisted in the DB even if save is done here. |
||
479 | $options = $this->fetch_options(); |
||
480 | $gfonts = $options['autoptimize_extra_radio_field_4']; |
||
481 | ?> |
||
482 | <style> |
||
483 | #ao_settings_form {background: white;border: 1px solid #ccc;padding: 1px 15px;margin: 15px 10px 10px 0;} |
||
484 | #ao_settings_form .form-table th {font-weight: normal;} |
||
485 | #autoptimize_extra_descr{font-size: 120%;} |
||
486 | </style> |
||
487 | <script>document.title = "Autoptimize: <?php _e( 'Extra', 'autoptimize' ); ?> " + document.title;</script> |
||
488 | <div class="wrap"> |
||
489 | <h1><?php _e( 'Autoptimize Settings', 'autoptimize' ); ?></h1> |
||
490 | <?php echo autoptimizeConfig::ao_admin_tabs(); ?> |
||
491 | <?php if ( 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_js' ) && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_css' ) && 'on' !== autoptimizeOptionWrapper::get_option( 'autoptimize_html' ) && ! autoptimizeImages::imgopt_active() ) { ?> |
||
0 ignored issues
–
show
The expression
\autoptimizeImages::imgopt_active() of type null|boolean is loosely compared to false ; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.
If an expression can have both $a = canBeFalseAndNull();
// Instead of
if ( ! $a) { }
// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
![]() |
|||
492 | <div class="notice-warning notice"><p> |
||
493 | <?php _e( 'Most of below Extra optimizations require at least one of HTML, JS, CSS or Image autoptimizations being active.', 'autoptimize' ); ?> |
||
494 | </p></div> |
||
495 | <?php } ?> |
||
496 | |||
497 | <form id='ao_settings_form' action='<?php echo admin_url( 'options.php' ); ?>' method='post'> |
||
498 | <?php settings_fields( 'autoptimize_extra_settings' ); ?> |
||
499 | <h2><?php _e( 'Extra Auto-Optimizations', 'autoptimize' ); ?></h2> |
||
500 | <span id='autoptimize_extra_descr'><?php _e( 'The following settings can improve your site\'s performance even more.', 'autoptimize' ); ?></span> |
||
501 | <table class="form-table"> |
||
502 | <tr> |
||
503 | <th scope="row"><?php _e( 'Google Fonts', 'autoptimize' ); ?></th> |
||
504 | <td> |
||
505 | <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 _e( 'Leave as is', 'autoptimize' ); ?><br/> |
||
506 | <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="2" <?php checked( 2, $gfonts, true ); ?> ><?php _e( 'Remove Google Fonts', 'autoptimize' ); ?><br/> |
||
507 | <?php // translators: "display:swap" should remain untranslated, will be shown in code tags. ?> |
||
508 | <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="3" <?php checked( 3, $gfonts, true ); ?> ><?php echo __( 'Combine and link in head (fonts load fast but are render-blocking)', 'autoptimize' ) . ', ' . sprintf( __( 'includes %1$sdisplay:swap%2$s.', 'autoptimize' ), '<code>', '</code>' ); ?><br/> |
||
509 | <?php // translators: "display:swap" should remain untranslated, will be shown in code tags. ?> |
||
510 | <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="5" <?php checked( 5, $gfonts, true ); ?> ><?php echo __( 'Combine and link deferred in head (fonts load late, but are not render-blocking)', 'autoptimize' ) . ', ' . sprintf( __( 'includes %1$sdisplay:swap%2$s.', 'autoptimize' ), '<code>', '</code>' ); ?><br/> |
||
511 | <input type="radio" name="autoptimize_extra_settings[autoptimize_extra_radio_field_4]" value="4" <?php checked( 4, $gfonts, true ); ?> ><?php echo __( 'Combine and load fonts asynchronously with <a href="https://github.com/typekit/webfontloader#readme" target="_blank">webfont.js</a>', 'autoptimize' ) . ' ' . __( '(deprecated)', 'autoptimize' ); ?><br/> |
||
512 | </td> |
||
513 | </tr> |
||
514 | <tr> |
||
515 | <th scope="row"><?php _e( 'Remove emojis', 'autoptimize' ); ?></th> |
||
516 | <td> |
||
517 | <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 _e( 'Removes WordPress\' core emojis\' inline CSS, inline JavaScript, and an otherwise un-autoptimized JavaScript file.', 'autoptimize' ); ?></label> |
||
518 | </td> |
||
519 | </tr> |
||
520 | <tr> |
||
521 | <th scope="row"><?php _e( 'Remove query strings from static resources', 'autoptimize' ); ?></th> |
||
522 | <td> |
||
523 | <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'><?php _e( 'Removing query strings (or more specifically the <code>ver</code> parameter) will not improve load time, but might improve performance scores.', 'autoptimize' ); ?></label> |
||
524 | </td> |
||
525 | </tr> |
||
526 | <tr> |
||
527 | <th scope="row"><?php _e( 'Preconnect to 3rd party domains <em>(advanced users)</em>', 'autoptimize' ); ?></th> |
||
528 | <td> |
||
529 | <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 /><?php _e( 'Add 3rd party domains you want the browser to <a href="https://www.keycdn.com/support/preconnect/#primary" target="_blank">preconnect</a> to, separated by comma\'s. Make sure to include the correct protocol (HTTP or HTTPS).', 'autoptimize' ); ?></label> |
||
530 | </td> |
||
531 | </tr> |
||
532 | <tr> |
||
533 | <th scope="row"><?php _e( 'Preload specific requests <em>(advanced users)</em>', 'autoptimize' ); ?></th> |
||
534 | <td> |
||
535 | <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 _e( 'Comma-separated list with full URL\'s of to to-be-preloaded resources. To be used sparingly!', 'autoptimize' ); ?></label> |
||
536 | </td> |
||
537 | </tr> |
||
538 | <tr> |
||
539 | <th scope="row"><?php _e( 'Async Javascript-files <em>(advanced users)</em>', 'autoptimize' ); ?></th> |
||
540 | <td> |
||
541 | <?php |
||
542 | if ( autoptimizeUtils::is_plugin_active( 'async-javascript/async-javascript.php' ) ) { |
||
543 | // translators: link points Async Javascript settings page. |
||
544 | printf( __( '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>' ); |
||
545 | } else { |
||
546 | ?> |
||
547 | <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'] ); } ?>'> |
||
548 | <br /> |
||
549 | <?php |
||
550 | _e( 'Comma-separated list of local or 3rd party JS-files that should loaded with the <code>async</code> flag. JS-files from your own site will be automatically excluded if added here. ', 'autoptimize' ); |
||
551 | // translators: %s will be replaced by a link to the "async javascript" plugin. |
||
552 | echo sprintf( __( '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>"' ); |
||
553 | $asj_install_url = network_admin_url() . 'plugin-install.php?s=async+javascript&tab=search&type=term'; |
||
554 | echo sprintf( ' <a href="' . $asj_install_url . '">%s</a>', __( 'Click here to install and activate it.', 'autoptimize' ) ); |
||
555 | } |
||
556 | ?> |
||
557 | </td> |
||
558 | </tr> |
||
559 | <tr> |
||
560 | <th scope="row"><?php _e( 'Optimize YouTube videos', 'autoptimize' ); ?></th> |
||
561 | <td> |
||
562 | <?php |
||
563 | if ( autoptimizeUtils::is_plugin_active( 'wp-youtube-lyte/wp-youtube-lyte.php' ) ) { |
||
564 | _e( 'Great, you have WP YouTube Lyte installed.', 'autoptimize' ); |
||
565 | $lyte_config_url = 'options-general.php?page=lyte_settings_page'; |
||
566 | echo sprintf( ' <a href="' . $lyte_config_url . '">%s</a>', __( 'Click here to configure it.', 'autoptimize' ) ); |
||
567 | } else { |
||
568 | // translators: %s will be replaced by a link to "wp youtube lyte" plugin. |
||
569 | echo sprintf( __( '%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>' ); |
||
570 | $lyte_install_url = network_admin_url() . 'plugin-install.php?s=lyte&tab=search&type=term'; |
||
571 | echo sprintf( ' <a href="' . $lyte_install_url . '">%s</a>', __( 'Click here to install and activate it.', 'autoptimize' ) ); |
||
572 | } |
||
573 | ?> |
||
574 | </td> |
||
575 | </tr> |
||
576 | </table> |
||
577 | <p class="submit"><input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'autoptimize' ); ?>" /></p> |
||
578 | </form> |
||
579 | <?php |
||
580 | } |
||
581 | } |
||
582 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..