PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
← All changes | minify/class-wp-optimize-minify-functions.php +161 -112 3.2.20 → 4.7.0 View file →
@@ -1,41 +1,22 @@
1 1 <?php
2 2
3 3 if (!defined('ABSPATH')) die('No direct access allowed');
4 4
5 -// handle better utf-8 and unicode encoding
5 +// handle better utf-8 and Unicode encoding
6 6 if (function_exists('mb_internal_encoding')) {
7 7 mb_internal_encoding('UTF-8');
8 8 }
9 9
10 10 // must have
11 +// phpcs:disable
12 +// Squiz.PHP.DiscouragedFunctions.Discouraged -- Not applicable here
11 13 ini_set('pcre.backtrack_limit', 5000000);
12 14 ini_set('pcre.recursion_limit', 5000000);
13 -
14 -// Include PHP Minify [1.3.60] - https://github.com/matthiasmullie/minify
15 -if (!class_exists('\MatthiasMullie\Minify\Minify')) {
16 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/minify/src/Minify.php';
17 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/minify/src/CSS.php';
18 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/minify/src/JS.php';
19 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/minify/src/Exception.php';
20 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/minify/src/Exceptions/BasicException.php';
21 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/minify/src//Exceptions/FileImportException.php';
22 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/minify/src/Exceptions/IOException.php';
23 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/path-converter/src/ConverterInterface.php';
24 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/matthiasmullie/path-converter/src/Converter.php';
25 -}
15 +// phpcs:enable
26 16
27 -use MatthiasMullie\Minify; // phpcs:ignore PHPCompatibility.Keywords.NewKeywords.t_useFound, PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
17 +use MatthiasMullie\Minify;
28 18
29 -// Use HTML minification
30 -if (!class_exists('Minify_HTML')) {
31 - require_once WPO_PLUGIN_MAIN_PATH.'vendor/mrclay/minify/lib/Minify/HTML.php';
32 -}
33 -
34 -if (!class_exists('WP_Optimize_Options')) {
35 - include_once WPO_PLUGIN_MAIN_PATH.'includes/class-wp-optimize-options.php';
36 -}
37 -
38 19 class WP_Optimize_Minify_Functions {
39 20
40 21 /**
41 22 * Applies `strip_tags` function for given array of messages
@@ -77,9 +58,9 @@
77 58 $ret = false;
78 59 foreach ($locations as $l) {
79 60 $l = preg_replace('/^https?:\/\//i', '', trim($l));
80 61 $l = trim(trim(preg_replace('/^www./', '', $l), '/'));
81 - if (stripos($src, $l) !== false && false === $ret) {
62 + if (false !== stripos($src, $l) && false === $ret) {
82 63 $ret = true;
83 64 }
84 65 }
85 66
@@ -115,15 +96,15 @@
115 96 // make sure wp_home doesn't have a forward slash
116 97 $wp_home = rtrim($wp_home, '/');
117 98
118 99 // apply some filters
119 - if (substr($hurl, 0, 2) === "//") {
100 + if ("//" === substr($hurl, 0, 2)) {
120 101 $hurl = $protocol.ltrim($hurl, "/");
121 102 }//end if
122 - if (substr($hurl, 0, 4) === "http" && stripos($hurl, $wp_domain) === false) {
103 + if ("http" === substr($hurl, 0, 4) && false === stripos($hurl, $wp_domain)) {
123 104 return $hurl;
124 105 }//end if
125 - if (substr($hurl, 0, 4) !== "http" && stripos($hurl, $wp_domain) !== false) {
106 + if ("http" !== substr($hurl, 0, 4) && false !== stripos($hurl, $wp_domain)) {
126 107 $hurl = $wp_home.'/'.ltrim($hurl, "/");
127 108 }//end if
128 109
129 110 // prevent double forward slashes in the middle
@@ -144,9 +125,9 @@
144 125 // protocol + home for relative paths
145 126 if ("/".WPINC === substr($hurl, 0, 12)
146 127 || "/wp-admin" === substr($hurl, 0, 9)
147 128 || "/$wp_content_folder" === substr($hurl, 0, 11)
148 - || 1 == $proceed
129 + || 1 === $proceed
149 130 ) {
150 131 $hurl = $wp_home.'/'.ltrim($hurl, "/");
151 132 }
152 133
@@ -153,12 +134,12 @@
153 134 // make sure there is a protocol prefix as required
154 135 $hurl = $protocol.preg_replace('/^https?:\/\//i', '', $hurl); // enforce protocol
155 136
156 137 // no query strings
157 - if (stripos($hurl, '.js?v') !== false) {
138 + if (false !== stripos($hurl, '.js?v')) {
158 139 $hurl = stristr($hurl, '.js?v', true).'.js';
159 140 }//end if
160 - if (stripos($hurl, '.css?v') !== false) {
141 + if (false !== stripos($hurl, '.css?v')) {
161 142 $hurl = stristr($hurl, '.css?v', true).'.css';
162 143 }//end if
163 144
164 145 return $hurl;
@@ -177,18 +158,18 @@
177 158
178 159 if (substr($hurl, 0, strlen($wp_home)) === $wp_home) {
179 160 return true;
180 161 }
181 - if (stripos($hurl, $wp_home) !== false) {
162 + if (false !== stripos($hurl, $wp_home)) {
182 163 return true;
183 164 }
184 - if (isset($_SERVER['HTTP_HOST']) && stripos($hurl, preg_replace('/:\d+$/', '', $_SERVER['HTTP_HOST'])) !== false) {
165 + if (isset($_SERVER['HTTP_HOST']) && false !== stripos($hurl, preg_replace('/:\d+$/', '', sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST']))))) {
185 166 return true;
186 167 }
187 - if (isset($_SERVER['SERVER_NAME']) && stripos($hurl, preg_replace('/:\d+$/', '', $_SERVER['SERVER_NAME'])) !== false) {
168 + if (isset($_SERVER['SERVER_NAME']) && false !== stripos($hurl, preg_replace('/:\d+$/', '', sanitize_text_field(wp_unslash($_SERVER['SERVER_NAME']))))) {
188 169 return true;
189 170 }
190 - if (isset($_SERVER['SERVER_ADDR']) && '::1' != $_SERVER['SERVER_ADDR'] && stripos($hurl, preg_replace('/:\d+$/', '', $_SERVER['SERVER_ADDR'])) !== false) {
171 + if (isset($_SERVER['SERVER_ADDR']) && '::1' !== sanitize_text_field(wp_unslash($_SERVER['SERVER_ADDR'])) && false !== stripos($hurl, preg_replace('/:\d+$/', '', sanitize_text_field(wp_unslash($_SERVER['SERVER_ADDR']))))) {
191 172 return true;
192 173 }
193 174
194 175 // allow specific external urls to be merged
@@ -195,9 +176,9 @@
195 176 if (null === $noxtra) {
196 177 $merge_allowed_urls = array_map('trim', explode("\n", $wpo_minify_options['merge_allowed_urls']));
197 178 if (is_array($merge_allowed_urls) && strlen(implode($merge_allowed_urls)) > 0) {
198 179 foreach ($merge_allowed_urls as $e) {
199 - if (stripos($hurl, $e) !== false && !empty($e)) {
180 + if (false !== stripos($hurl, $e) && !empty($e)) {
200 181 return true;
201 182 }
202 183 }
203 184 }
@@ -230,8 +211,20 @@
230 211 return false;
231 212 }
232 213
233 214 /**
215 + * Check if selected url is point to already minified css/js file
216 + *
217 + * @param string $url
218 + * @return bool
219 + */
220 + public static function is_minified_css_js_filename($url) {
221 + $parts = wp_parse_url($url);
222 + if (empty($parts['path']) || !is_string(basename($parts['path']))) return false;
223 + return 1 === preg_match('/\.min\.(js|css)$/i', basename($parts['path']));
224 + }
225 +
226 + /**
234 227 * Better compatibility urls + fix w3.org NamespaceAndDTDIdentifiers
235 228 *
236 229 * @param string $code
237 230 * @return string
@@ -238,11 +231,11 @@
238 231 * */
239 232 private static function compat_urls($code) {
240 233 $wpo_minify_options = wp_optimize_minify_config()->get();
241 234 $default_protocol = $wpo_minify_options['default_protocol'];
242 - if ('dynamic' == $default_protocol) {
243 - if ((isset($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'] || 1 == $_SERVER['HTTPS']))
244 - || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'])
235 + if ('dynamic' === $default_protocol) {
236 + if ((isset($_SERVER['HTTPS']) && ('on' === $_SERVER['HTTPS'] || 1 === (int) $_SERVER['HTTPS']))
237 + || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'])
245 238 ) {
246 239 $default_protocol = 'https://';
247 240 } else {
248 241 $default_protocol = 'http://';
@@ -285,9 +278,9 @@
285 278
286 279 // exclude minification on already minified files + jquery (because minification might break those)
287 280 $excl = array('jquery.js', '.min.js', '-min.js', '/uploads/fusion-scripts/', '/min/', '.packed.js', '/includes/builder/scripts/');
288 281 foreach ($excl as $e) {
289 - if (stripos(basename($url), $e) !== false) {
282 + if (false !== stripos(basename($url), $e)) {
290 283 $enable_js_minification = false;
291 284 break;
292 285 }
293 286 }
@@ -310,9 +303,9 @@
310 303 $js = preg_replace('/(\/\/\s*[#]\s*sourceMappingURL\s*[=]\s*)(.+)\s*/ui', '', $js);
311 304
312 305 // needed when merging js files
313 306 $js = trim($js);
314 - if (substr($js, -1) != ';') {
307 + if (';' !== substr($js, -1)) {
315 308 $js = $js.';';
316 309 }
317 310 if ($wpo_minify_options['debug']) {
318 311 $js = '/* info: ' . $url . ' */' . "\n" . $js;
@@ -324,9 +317,10 @@
324 317 * @param string $js - The imported JS
325 318 * @param string $url - The imported url
326 319 * @param boolean $enable_js_minification - Whether to minify or not
327 320 */
328 - return apply_filters('wpo_minify_get_js', $js . "\n", $url, $enable_js_minification);
321 + $filtered_js = apply_filters('wpo_minify_get_js', $js . "\n", $url, $enable_js_minification);
322 + return is_string($filtered_js) ? $filtered_js : $js;
329 323 }
330 324
331 325 /**
332 326 * Minify JS string with PHP Minify or YUI Compressors
@@ -338,9 +332,9 @@
338 332 $js = apply_filters('wpo_minify_js_string', $js);
339 333 // PHP Minify from https://github.com/matthiasmullie/minify
340 334 $minifier = new Minify\JS($js);
341 335 $min = $minifier->minify();
342 - if (false !== $min && (strlen(trim($js)) == strlen(trim($min)) || strlen(trim($min)) > 0)) {
336 + if (false !== $min && (strlen(trim($js)) === strlen(trim($min)) || strlen(trim($min)) > 0)) {
343 337 return self::compat_urls($min);
344 338 }
345 339
346 340 // if we are here, something went wrong and minification didn't work
@@ -361,8 +355,19 @@
361 355 return self::minify_js_string($js, true);
362 356 }
363 357
364 358 /**
359 + * Check if the JS code contains import statements
360 + *
361 + * @param string $js
362 + * @return boolean
363 + */
364 + public static function has_js_import_statements($js) {
365 + $js = preg_replace('/\/\/.*|\/\*[\s\S]*?\*\//', '', $js); // Remove comments to avoid false positives
366 + return 1 === preg_match('/\bimport\b/', $js);
367 + }
368 +
369 + /**
365 370 * Functions, minify html
366 371 *
367 372 * @param string $html
368 373 * @return string
@@ -395,9 +400,9 @@
395 400 *
396 401 * @return void
397 402 */
398 403 public static function html_compression_start() {
399 - if (self::exclude_contents() == true) {
404 + if (self::exclude_contents()) {
400 405 return;
401 406 }
402 407 ob_start(array(__CLASS__, 'html_compression_finish'));
403 408 }
@@ -474,9 +479,10 @@
474 479 * @param string $css - The imported CSS
475 480 * @param string $url - The imported url
476 481 * @param boolean $enable_css_minification - Whether to minify or not
477 482 */
478 - return apply_filters('wpo_minify_get_css', $css, $url, $enable_css_minification);
483 + $filtered_css = apply_filters('wpo_minify_get_css', $css, $url, $enable_css_minification);
484 + return is_string($filtered_css) ? $filtered_css : $css;
479 485 }
480 486
481 487 /**
482 488 * Adds full path to relative url() rules
@@ -489,13 +495,13 @@
489 495 $matches = array();
490 496 preg_match_all("/url\(\s*['\"]?(?!data:)(?!http)(?![\/'\"])(.+?)['\"]?\s*\)/ui", $css, $matches);
491 497 foreach ($matches[1] as $a) {
492 498 $b = trim($a);
493 - if ($b != $a) {
499 + if ($b !== $a) {
494 500 $css = str_replace($a, $b, $css);
495 501 }
496 502 }
497 - return preg_replace("/url\(\s*['\"]?(?!data:)(?!http)(?![\/'\"])(.+?)['\"]?\s*\)/ui", "url(".dirname($url)."/$1)", $css);
503 + return (string) preg_replace("/url\(\s*['\"]?(?!data:)(?!http)(?![\/'\"])(.+?)['\"]?\s*\)/ui", "url(".dirname($url)."/$1)", $css);
498 504 }
499 505
500 506 /**
501 507 * Include @import[ed] files - The @import statement can only be used at the top of a file, which breaks when merging everything.
@@ -520,9 +526,9 @@
520 526
521 527 // If $media_query contains print, and $remove_print_mediatypes is true, return empty string
522 528 if ($remove_print_mediatypes && false !== strpos($media_query, 'print') && apply_filters('wpo_minfy_remove_print_mediatypes_import', true, $url, $media_query, $matches[0], $file_url)) return ($debug ? '/*! Info: the import of "'.$url.'" was removed because the setting remove_print_mediatypes is enabled. */' : '');
523 529
524 - $purl = parse_url($url);
530 + $purl = wp_parse_url($url);
525 531 // If there's no host, the url is relative to $file_url, so prepend with the base url.
526 532 if (!isset($purl['host'])) {
527 533 $url = dirname($file_url).'/'.$url;
528 534 }
@@ -556,18 +562,20 @@
556 562
557 563 /**
558 564 * Download and cache css and js files
559 565 *
560 - * @param string $hurl
561 - * @param string $inline
566 + * @param ?string $hurl
567 + * @param ?string $inline
562 568 * @param boolean $enable_minification
563 569 * @param string $type
564 - * @param string $handle
570 + * @param ?string $handle
571 + * @param mixed $version
572 + *
565 573 * @return boolean|string
566 574 */
567 575 public static function download_and_minify($hurl, $inline, $enable_minification, $type, $handle, $version = '') {
568 576 // must have
569 - if (is_null($hurl) || empty($hurl)) {
577 + if (empty($hurl)) {
570 578 return false;
571 579 }
572 580 if (!in_array($type, array('js', 'css'))) {
573 581 return false;
@@ -582,16 +590,16 @@
582 590 'url' => $print_url,
583 591 );
584 592
585 593 // defaults
586 - if (false != $enable_minification) {
594 + if (false !== $enable_minification) {
587 595 $enable_minification = true;
588 596 }
589 - if (is_null($inline) || empty($inline)) {
597 + if (empty($inline)) {
590 598 $inline = '';
591 599 }
592 600 $print_handle = '';
593 - if (is_null($handle) || empty($handle)) {
601 + if (empty($handle)) {
594 602 $handle = '';
595 603 } else {
596 604 $print_handle = "[$handle]";
597 605 }
@@ -615,12 +623,12 @@
615 623 if ($wpo_minify_options['debug']) {
616 624 $log['debug'] = "$print_handle failed. Tried wp_remote_get and local file_get_contents.";
617 625 }
618 626 $return = array('request' => $dreq, 'log' => $log, 'code' => '', 'status' => false);
619 - return json_encode($return);
627 + return wp_json_encode($return);
620 628 }
621 629
622 - if ('js' == $type) {
630 + if ('js' === $type) {
623 631 $code = self::get_js($hurl, $code, $enable_minification);
624 632 } else {
625 633 $code = self::get_css($hurl, $code.$inline, $enable_minification);
626 634 }
@@ -626,18 +634,18 @@
626 634 }
627 635
628 636 // log, save and return
629 637 if ($wpo_minify_options['debug']) {
630 - $version_msg = ('' != $version) ? "[Version: $version]" : "";
638 + $version_msg = ('' !== $version) ? "[Version: $version]" : "";
631 639 $log['debug'] = $print_handle . $version_msg . ' was '.('local' === $asset_content['method'] ? 'opened' : 'fetched').' from '.$hurl;
632 640 }
633 641 $log['success'] = true;
634 642 $return = array('request' => $dreq, 'log' => $log, 'code' => $code, 'status' => true);
635 - return json_encode($return);
643 + return wp_json_encode($return);
636 644 }
637 645
638 646 /**
639 - * Get the content of an asset, wether local or remote
647 + * Get the content of an asset, whether local or remote
640 648 *
641 649 * @param string $url
642 650 * @return array
643 651 */
@@ -643,14 +651,14 @@
643 651 */
644 652 public static function get_asset_content($url) {
645 653
646 654 $wp_home = site_url();
647 - $wp_domain = parse_url($wp_home, PHP_URL_HOST);
655 + $wp_domain = wp_parse_url($wp_home, PHP_URL_HOST);
648 656 // If the file is local.
649 657 if (false !== stripos($url, $wp_domain)) {
650 658 // default
651 659 $f = str_ireplace(rtrim($wp_home, '/'), rtrim(ABSPATH, '/'), $url);
652 - // failover when home_url != site_url
660 + // fail over when home_url != site_url
653 661 if (!file_exists($f)) {
654 662 $nhurl = str_ireplace(site_url(), home_url(), $url);
655 663 $f = str_ireplace(rtrim($wp_home, '/'), rtrim(ABSPATH, '/'), $nhurl);
656 664 }
@@ -657,9 +665,9 @@
657 665 clearstatcache();
658 666 if (file_exists($f)) {
659 667 $content = file_get_contents($f);
660 668 // check for php code, skip if found
661 - if ("<?php" != strtolower(substr($content, 0, 5)) && false === stripos($content, "<?php")) {
669 + if ("<?php" !== strtolower(substr($content, 0, 5)) && false === stripos($content, "<?php")) {
662 670 return array('content' => $content, 'method' => 'local');
663 671 }
664 672 }
665 673 }
@@ -668,9 +676,9 @@
668 676 // else, fallback to remote urls (or windows)
669 677 $content = self::download_remote($url);
670 678 if (false !== $content
671 679 && !empty($content)
672 - && strtolower(substr($content, 0, 9)) != "<!doctype"
680 + && "<!doctype" !== strtolower(substr($content, 0, 9))
673 681 ) {
674 682 // check if we got HTML instead of js or css code
675 683 return array('content' => $content, 'method' => 'remote');
676 684 }
@@ -676,12 +684,12 @@
676 684 }
677 685
678 686
679 687 // fallback when home_url != site_url
680 - if (stripos($url, $wp_domain) !== false && home_url() != site_url()) {
688 + if (false !== stripos($url, $wp_domain) && home_url() !== site_url()) {
681 689 $nhurl = str_ireplace(site_url(), home_url(), $url);
682 690 $content = self::download_remote($nhurl);
683 - if (false !== $content && !empty($content) && '<!doctype' != strtolower(substr($content, 0, 9))) {
691 + if (false !== $content && !empty($content) && '<!doctype' !== strtolower(substr($content, 0, 9))) {
684 692 return array('content' => $content, 'method' => 'remote');
685 693 }
686 694 }
687 695
@@ -696,9 +704,11 @@
696 704 public static function disable_wp_emojicons() {
697 705 remove_action('wp_head', 'print_emoji_detection_script', 7);
698 706 remove_action('admin_print_scripts', 'print_emoji_detection_script');
699 707 remove_action('wp_print_styles', 'print_emoji_styles');
708 + remove_action('wp_enqueue_scripts', 'wp_enqueue_emoji_styles');
700 709 remove_action('admin_print_styles', 'print_emoji_styles');
710 + remove_action('admin_enqueue_scripts', 'wp_enqueue_emoji_styles');
701 711 remove_filter('the_content_feed', 'wp_staticize_emoji');
702 712 remove_filter('comment_text_rss', 'wp_staticize_emoji');
703 713 remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
704 714 }
@@ -734,9 +744,9 @@
734 744 * @param string $src
735 745 * @return string
736 746 */
737 747 public static function remove_cssjs_ver($src) {
738 - if (stripos($src, '?ver=')) {
748 + if (stripos($src, '?ver=') && self::is_already_minified($src)) {
739 749 $src = remove_query_arg('ver', $src);
740 750 }
741 751 return $src;
742 752 }
@@ -741,8 +751,18 @@
741 751 return $src;
742 752 }
743 753
744 754 /**
755 + * Determine if the source is already minified (served from minify cache)
756 + *
757 + * @param string $src
758 + * @return boolean
759 + */
760 + public static function is_already_minified($src) {
761 + return false !== strpos($src, 'cache/wpo-minify');
762 + }
763 +
764 + /**
745 765 * Rewrite cache files to http, https or dynamic
746 766 *
747 767 * @param string $url
748 768 * @return string
@@ -758,12 +778,12 @@
758 778 $cdn_url = $wpo_minify_options['cdn_url'];
759 779 $cdn_url = trim(trim(preg_replace('/^https?:\/\//i', '', trim($cdn_url, '/'))), '/');
760 780
761 781 // process cdn rewrite
762 - if (!empty($cdn_url) && self::is_local_domain($url) !== false) {
782 + if (!empty($cdn_url) && false !== self::is_local_domain($url)) {
763 783
764 784 // for js files, we need to consider thew defer for insights option
765 - if (substr($url, -3) == '.js') {
785 + if ('.js' === substr($url, -3)) {
766 786 $async_using_js = 'all' === $wpo_minify_options['enable_defer_js'] && 'async_using_js' === $wpo_minify_options['defer_js_type'];
767 787 if (!$async_using_js
768 788 || $wpo_minify_options['cdn_force']
769 789 ) {
@@ -774,11 +794,11 @@
774 794 }
775 795 }
776 796
777 797 // enforce protocol if needed
778 - if ('dynamic' == $default_protocol) {
779 - if ((isset($_SERVER['HTTPS']) && ('on' == $_SERVER['HTTPS'] || 1 == $_SERVER['HTTPS']))
780 - || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'])
798 + if ('dynamic' === $default_protocol) {
799 + if ((isset($_SERVER['HTTPS']) && ('on' === $_SERVER['HTTPS'] || 1 === (int) $_SERVER['HTTPS']))
800 + || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'])
781 801 ) {
782 802 $default_protocol = 'https://';
783 803 } else {
784 804 $default_protocol = 'http://';
@@ -800,9 +820,9 @@
800 820 // prevent execution for specific urls
801 821 if (isset($_SERVER['REQUEST_URI']) && !empty($_SERVER['REQUEST_URI'])) {
802 822 $disable_on_url = array_filter(array_map('trim', explode("\n", get_option('wpo_min_disable_on_url', ''))));
803 823 foreach ($disable_on_url as $url) {
804 - if (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == $url) {
824 + if (wp_parse_url(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])), PHP_URL_PATH) === $url) {
805 825 return true;
806 826 }
807 827 }
808 828 }
@@ -807,11 +827,16 @@
807 827 }
808 828 }
809 829
810 830 // for compatibility, let's always skip the checkout page
811 - if (function_exists('is_checkout') && is_checkout() === true) {
831 + if (function_exists('is_checkout') && true === is_checkout()) {
812 832 return true;
813 833 }
834 +
835 + if (isset($_SERVER['REQUEST_URI'])) {
836 + $is_txt_extension = '.txt' === strtolower(substr(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])), -4));
837 + $is_xml_extension = '.xml' === strtolower(substr(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])), -4));
838 + }
814 839
815 840 // exclude processing here
816 841 if (is_feed()
817 842 || is_admin()
@@ -828,14 +853,16 @@
828 853 || (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST)
829 854 || (defined('SHORTINIT') && SHORTINIT)
830 855 || (defined('REST_REQUEST') && REST_REQUEST)
831 856 || (isset($_SERVER['REQUEST_METHOD']) && 'POST' === $_SERVER['REQUEST_METHOD'])
832 - || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
833 - || (isset($_SERVER['REQUEST_URI']) && (strtolower(substr($_SERVER['REQUEST_URI'], -4)) == '.txt' || strtolower(substr($_SERVER['REQUEST_URI'], -4)) == '.xml'))
857 + || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 'xmlhttprequest' === strtolower(sanitize_text_field(wp_unslash($_SERVER['HTTP_X_REQUESTED_WITH']))))
858 + || (isset($_SERVER['REQUEST_URI']) && ($is_txt_extension || $is_xml_extension))
834 859 ) {
835 860 return true;
836 861 }
837 862
863 + // phpcs:disable
864 + // WordPress.Security.NonceVerification.Recommended -- Using $_GET element only to compare, returns boolean
838 865 // Thrive plugins and other post_types
839 866 $arr = array('tve_form_type', 'tve_lead_shortcode', 'tqb_splash');
840 867 foreach ($arr as $a) {
841 868 if (isset($_GET['post_type']) && $a === $_GET['post_type']) {
@@ -849,9 +876,9 @@
849 876
850 877 if (is_array($_GET)) {
851 878 foreach ($_GET as $k => $v) {
852 879 if (is_string($v) && is_string($k)) {
853 - if (stripos($k, 'elementor') !== false || stripos($v, 'elementor') !== false) {
880 + if (false !== stripos($k, 'elementor') || false !== stripos($v, 'elementor')) {
854 881 return true;
855 882 }
856 883 }
857 884 }
@@ -878,13 +905,14 @@
878 905 'trp-edit-translation',
879 906 );
880 907 return (bool) count(array_intersect($excluded_params, $get_params));
881 908 }
909 + // phpcs:enable
882 910
883 911 /**
884 - * Wether to exclude the content or not from the minifying process.
912 + * Whether to exclude the content or not from the minifying process.
885 913 */
886 - return apply_filters('wpo_minify_exclude_contents', false);
914 + return (bool) apply_filters('wpo_minify_exclude_contents', false);
887 915 }
888 916
889 917 /**
890 918 * Get the default files which are ignored / excluded from processing
@@ -891,15 +919,9 @@
891 919 *
892 920 * @return array
893 921 */
894 922 public static function get_default_ignore() {
895 - /**
896 - * Filters the default exclusions
897 - *
898 - * @param array The exclusions
899 - * @return array
900 - */
901 - return apply_filters('wp-optimize-minify-default-exclusions', array(
923 + $default_exclusions = array(
902 924 '/genericons.css',
903 925 '/Avada/assets/js/main.min.js',
904 926 '/woocommerce-product-search/js/product-search.js',
905 927 '/includes/builder/scripts/frontend-builder-scripts.js',
@@ -913,9 +935,17 @@
913 935 'elementor-admin-bar',
914 936 'pdfjs-dist',
915 937 'wordpress-popular-posts',
916 938 'uploads/bb-plugin/cache', // Beaver builder page specific pages
917 - ));
939 + );
940 + /**
941 + * Filters the default exclusions
942 + *
943 + * @param array The exclusions
944 + * @return array
945 + */
946 + $filtered_exclusions = apply_filters('wp-optimize-minify-default-exclusions', $default_exclusions);
947 + return is_array($filtered_exclusions) ? $filtered_exclusions : $default_exclusions;
918 948 }
919 949
920 950 /**
921 951 * Know files that should always be ignored
@@ -940,15 +970,9 @@
940 970 *
941 971 * @return array
942 972 */
943 973 public static function get_default_ie_blacklist() {
944 - /**
945 - * Filters the default IE specific / blacklisted items
946 - *
947 - * @param array The blacklist
948 - * @return array
949 - */
950 - return apply_filters('wp-optimize-minify-blacklist', array(
974 + $default_ie_blacklist = array(
951 975 '/html5shiv.js',
952 976 '/html5shiv-printshiv.min.js',
953 977 '/excanvas.js',
954 978 '/avada-ie9.js',
@@ -968,9 +992,17 @@
968 992 '/a.optnmstr.com/app/js/api.min.js',
969 993 '/pixelyoursite/js/public.js',
970 994 '/assets/js/wcdrip-drip.js',
971 995 '/instantpage.js',
972 - ));
996 + );
997 + /**
998 + * Filters the default IE specific / blacklisted items
999 + *
1000 + * @param array The blacklist
1001 + * @return array
1002 + */
1003 + $filtered_ie_blacklist = apply_filters('wp-optimize-minify-blacklist', $default_ie_blacklist);
1004 + return is_array($filtered_ie_blacklist) ? $filtered_ie_blacklist : $default_ie_blacklist;
973 1005 }
974 1006
975 1007 /**
976 1008 * Get the files excluded for IE compatibility
@@ -997,9 +1029,9 @@
997 1029 $blacklist[] = '/wpo_min/cache/';
998 1030
999 1031 // is the url on our list and return
1000 1032 $res = self::in_arrayi($url, $blacklist);
1001 - if (true == $res) {
1033 + if ($res) {
1002 1034 return true;
1003 1035 } else {
1004 1036 return false;
1005 1037 }
@@ -1008,19 +1040,19 @@
1008 1040 /**
1009 1041 * Download function with fallback
1010 1042 *
1011 1043 * @param string $url
1012 - * @return boolean
1044 + * @return boolean|string
1013 1045 */
1014 1046 public static function download_remote($url) {
1015 1047
1016 1048 $args = array(
1017 - // info (needed for google fonts woff files + hinted fonts) as well as to bypass some security filters
1018 - 'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
1049 + // info (needed for Google fonts woff files + hinted fonts) as well as to bypass some security filters
1050 + 'user-agent' => WP_Optimize_Utils::get_user_agent('gfont'),
1019 1051 'timeout' => 7
1020 1052 );
1021 1053
1022 - // fetch via wordpress functions
1054 + // fetch via WordPress functions
1023 1055 $response = wp_remote_get(
1024 1056 $url,
1025 1057 /**
1026 1058 * Filters the arguments passed to wp_remote_get when downloading the scripts.
@@ -1032,9 +1064,9 @@
1032 1064 apply_filters('wpo_minify_download_request_args', $args, $url)
1033 1065 );
1034 1066
1035 1067 $res_code = wp_remote_retrieve_response_code($response);
1036 - if (200 == $res_code) {
1068 + if (200 === $res_code) {
1037 1069 $data = wp_remote_retrieve_body($response);
1038 1070 if (strlen($data) > 1) {
1039 1071 return $data;
1040 1072 }
@@ -1058,25 +1090,25 @@
1058 1090 return $script;
1059 1091 }
1060 1092
1061 1093 /**
1062 - * Checks if an URL is a font-awesome resource (checks if it contains font-awesome or fontawesome)
1094 + * Checks if URL is a font-awesome resource (checks if it contains font-awesome or fontawesome)
1063 1095 *
1064 1096 * @param string $href
1065 1097 * @return boolean
1066 1098 */
1067 1099 public static function is_font_awesome($href) {
1068 - return (boolean) preg_match('/font[-_]?awesome/i', $href);
1100 + return (bool) preg_match('/font[-_]?awesome/i', $href);
1069 1101 }
1070 1102
1071 1103 /**
1072 - * Checks if an URL is a google font resource
1104 + * Checks if URL is a Google font resource
1073 1105 *
1074 1106 * @param string $href
1075 1107 * @return boolean
1076 1108 */
1077 1109 public static function is_google_font($href) {
1078 - return 'fonts.googleapis.com' === strtolower(parse_url($href, PHP_URL_HOST));
1110 + return 'fonts.googleapis.com' === strtolower(wp_parse_url($href, PHP_URL_HOST));
1079 1111 }
1080 1112
1081 1113 /**
1082 1114 * Get the content of an asset, whether local or remote
@@ -1131,14 +1163,14 @@
1131 1163 * @return int|false
1132 1164 */
1133 1165 public static function get_remote_file_size($url) {
1134 1166 $args = array(
1135 - // info (needed for google fonts woff files + hinted fonts) as well as to bypass some security filters
1136 - 'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
1167 + // info (needed for Google fonts woff files + hinted fonts) as well as to bypass some security filters
1168 + 'user-agent' => WP_Optimize_Utils::get_user_agent('gfont'),
1137 1169 'timeout' => 7
1138 1170 );
1139 1171
1140 - // fetch via wordpress functions
1172 + // fetch via WordPress functions
1141 1173 $response = wp_remote_get($url, $args);
1142 1174
1143 1175 if (is_wp_error($response)) return false;
1144 1176
@@ -1168,9 +1200,9 @@
1168 1200 * @return string Fixed google fonts url
1169 1201 */
1170 1202 public static function fix_flatsome_google_fonts_url($href) {
1171 1203 // Get query from $href
1172 - $query = parse_url($href, PHP_URL_QUERY);
1204 + $query = wp_parse_url($href, PHP_URL_QUERY);
1173 1205 $query_arr = explode('&', $query);
1174 1206
1175 1207 // Separate 'family and display' arguments in query
1176 1208 $family = str_replace('family=', '', $query_arr[0]);
@@ -1193,12 +1225,12 @@
1193 1225
1194 1226 // Remove beginning '+'
1195 1227 $font = str_replace(',+', ',', $font_variant[0]);
1196 1228
1197 - // Replace '-' with '+
1229 + // Replace '-' with '+'
1198 1230 $font = str_replace(array('-', ' '), '+', $font);
1199 1231
1200 - // Remove '"' or '%22'
1232 + // Remove `"` or '%22'
1201 1233 $font = str_replace(array('%22', '"'), '', $font);
1202 1234 $font_arr = explode(',', $font);
1203 1235 $font_arr = array_diff($font_arr, $system_fonts);
1204 1236 $variant = '';
@@ -1216,8 +1248,25 @@
1216 1248 return $protocol . '//fonts.googleapis.com/css?family=' . implode('|', $google_fonts) . '&' . $display_type;
1217 1249 }
1218 1250
1219 1251 /**
1252 + * Get the file modification time
1253 + *
1254 + * @param string $asset_src
1255 + * @return string
1256 + */
1257 + public static function get_modification_time($asset_src) {
1258 + $hurl = self::get_hurl($asset_src);
1259 + $abs_file_path = WP_Optimize_Utils::get_file_path($hurl);
1260 + if (empty($abs_file_path)) return '';
1261 +
1262 + $modification_time = strval(@filemtime($abs_file_path)); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Suppress E-Warning on failure
1263 + $filtered_modification_time = apply_filters('wpo_minify_file_modification_time', $modification_time, $abs_file_path);
1264 +
1265 + return is_string($filtered_modification_time) ? $filtered_modification_time : $modification_time;
1266 + }
1267 +
1268 + /**
1220 1269 * When BOM removed code is null (due to unrecognised character encoding), logs error message
1221 1270 *
1222 1271 * @param string $url URL of the script/stylesheet
1223 1272 * @param string|false $encoding Character encoding
@@ -1230,8 +1279,8 @@
1230 1279 $message = "Minify: Could not process {$url}, it contains invalid characters. ";
1231 1280 if (false === $encoding) {
1232 1281 $message .= "Could not determine its character encoding.";
1233 1282 }
1234 - error_log($message);
1283 + error_log($message); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Using for debugging purpose
1235 1284 }
1236 1285 }
1237 1286 }