PluginProbe
Autoptimize / trunk
Autoptimize vtrunk
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
← All changes | classes/autoptimizeUtils.php +262 -6 2.4.2 → trunk View file →
@@ -44,9 +44,9 @@
44 44 */
45 45 public static function strpos( $haystack, $needle, $offset = 0, $encoding = null )
46 46 {
47 47 if ( self::mbstring_available() ) {
48 - return ( null === $encoding ) ? \mb_strpos( $haystack, $needle, $offset ) : \mb_strlen( $haystack, $needle, $offset, $encoding );
48 + return ( null === $encoding ) ? \mb_strpos( $haystack, $needle, $offset ) : \mb_strpos( $haystack, $needle, $offset, $encoding );
49 49 } else {
50 50 return \strpos( $haystack, $needle, $offset );
51 51 }
52 52 }
@@ -58,9 +58,9 @@
58 58 *
59 59 * @param string $string String.
60 60 * @param string|null $encoding Encoding.
61 61 *
62 - * @return int Number of charcters or bytes in given $string
62 + * @return int Number of characters or bytes in given $string
63 63 * (characters if/when supported, bytes otherwise).
64 64 */
65 65 public static function strlen( $string, $encoding = null )
66 66 {
@@ -203,9 +203,9 @@
203 203 return $results[ $cdn_url ];
204 204 }
205 205
206 206 /**
207 - * When siteurl contans a path other than '/' and the CDN URL does not have
207 + * When siteurl contains a path other than '/' and the CDN URL does not have
208 208 * a path or it's path is '/', this will modify the CDN URL's path component
209 209 * to match that of the siteurl.
210 210 * This is to support "magic" CDN urls that worked that way before v2.4...
211 211 *
@@ -266,9 +266,9 @@
266 266 {
267 267 $result = false;
268 268
269 269 if ( ! empty( $url ) ) {
270 - $result = ( '/' === $url{1} ); // second char is `/`.
270 + $result = ( 0 === strpos( $url, '//' ) );
271 271 }
272 272
273 273 return $result;
274 274 }
@@ -300,11 +300,13 @@
300 300
301 301 /**
302 302 * Checks to see if 3rd party services are available and stores result in option
303 303 *
304 + * TODO This should be two separate methods.
305 + *
304 306 * @param string $return_result should we return resulting service status array (default no).
305 307 *
306 - * @return none if $return_result is false (default), array if $return_result is true.
308 + * @return null|array Service status or null.
307 309 */
308 310 public static function check_service_availability( $return_result = false )
309 311 {
310 312 $service_availability_resp = wp_remote_get( 'https://misc.optimizingmatters.com/api/autoptimize_service_availablity.json?from=aomain&ver=' . AUTOPTIMIZE_PLUGIN_VERSION );
@@ -311,9 +313,9 @@
311 313 if ( ! is_wp_error( $service_availability_resp ) ) {
312 314 if ( '200' == wp_remote_retrieve_response_code( $service_availability_resp ) ) {
313 315 $availabilities = json_decode( wp_remote_retrieve_body( $service_availability_resp ), true );
314 316 if ( is_array( $availabilities ) ) {
315 - update_option( 'autoptimize_service_availablity', $availabilities );
317 + autoptimizeOptionWrapper::update_option( 'autoptimize_service_availablity', $availabilities );
316 318 if ( $return_result ) {
317 319 return $availabilities;
318 320 }
319 321 }
@@ -318,8 +320,9 @@
318 320 }
319 321 }
320 322 }
321 323 }
324 + return null;
322 325 }
323 326
324 327 /**
325 328 * Returns true if the string is a valid regex.
@@ -334,6 +337,259 @@
334 337 $is_regex = ( false !== preg_match( $string, '' ) );
335 338 restore_error_handler();
336 339
337 340 return $is_regex;
341 + }
342 +
343 + /**
344 + * Returns true if a certain WP plugin is active/loaded.
345 + *
346 + * @param string $plugin_file Main plugin file.
347 + *
348 + * @return bool
349 + */
350 + public static function is_plugin_active( $plugin_file )
351 + {
352 + static $ipa_exists = null;
353 + if ( null === $ipa_exists ) {
354 + if ( ! function_exists( '\is_plugin_active' ) ) {
355 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
356 + }
357 + $ipa_exists = function_exists( '\is_plugin_active' );
358 + }
359 +
360 + return $ipa_exists && \is_plugin_active( $plugin_file );
361 + }
362 +
363 + /**
364 + * Returns a node without ID attrib for use in noscript tags
365 + *
366 + * @param string $node an html tag.
367 + *
368 + * @return string
369 + */
370 + public static function remove_id_from_node( $node ) {
371 + if ( strpos( $node, 'id=' ) === false || apply_filters( 'autoptimize_filter_utils_keep_ids', false ) ) {
372 + return $node;
373 + } else {
374 + return preg_replace( '#(.*) id=[\'|"].*[\'|"] (.*)#Um', '$1 $2', $node );
375 + }
376 + }
377 +
378 + /**
379 + * Returns true if given $str ends with given $test.
380 + *
381 + * @param string $str String to check.
382 + * @param string $test Ending to match.
383 + *
384 + * @return bool
385 + */
386 + public static function str_ends_in( $str, $test )
387 + {
388 + // @codingStandardsIgnoreStart
389 + // substr_compare() is bugged on 5.5.11: https://3v4l.org/qGYBH
390 + // return ( 0 === substr_compare( $str, $test, -strlen( $test ) ) );
391 + // @codingStandardsIgnoreEnd
392 +
393 + $length = strlen( $test );
394 +
395 + return ( substr( $str, -$length, $length ) === $test );
396 + }
397 +
398 + /**
399 + * Returns true if a pagecache is found, false if not.
400 + * Now used to show notice, might be used later on to (un)hide page caching in AO if no page cache found.
401 + *
402 + * @param bool $disregard_transient False by default, but can be used to ignore the transient and retest.
403 + *
404 + * @return bool
405 + */
406 + public static function find_pagecache( $disregard_transient = false ) {
407 + static $_found_pagecache = null;
408 +
409 + if ( null === $_found_pagecache ) {
410 + $_page_cache_constants = array(
411 + 'NgInx' => 'NGINX_HELPER_BASENAME',
412 + 'Kinsta' => 'KINSTAMU_VERSION',
413 + 'Presslabs' => 'PL_INSTANCE_REF',
414 + 'Cache Enabler' => 'CACHE_ENABLER_VERSION',
415 + 'Speed Booster Pack' => 'SBP_PLUGIN_NAME',
416 + 'Servebolt' => 'SERVEBOLT_PLUGIN_FILE',
417 + 'WP CloudFlare Super Page Cache' => 'SWCFPC_PLUGIN_PATH',
418 + 'Cachify' => 'CACHIFY_CACHE_DIR',
419 + 'WP Rocket' => 'WP_ROCKET_CACHE_PATH',
420 + 'WP Optimize' => 'WPO_VERSION',
421 + 'Autoptimize Pro' => 'AO_PRO_PAGECACHE_CACHE_DIR',
422 + );
423 + $_page_cache_classes = array(
424 + 'Pressidium' => 'Ninukis_Plugin',
425 + 'Swift Performance' => 'Swift_Performance_Cache',
426 + 'WP Fastest Cache' => 'WpFastestCache',
427 + 'Quick Cache' => 'c_ws_plugin__qcache_purging_routines',
428 + 'ZenCache' => 'zencache',
429 + 'Comet Cache' => 'comet_cache',
430 + 'WP Engine' => 'WpeCommon',
431 + 'Flywheel' => 'FlywheelNginxCompat',
432 + 'Pagely' => 'PagelyCachePurge',
433 + );
434 + $_page_cache_functions = array(
435 + 'WP Super Cache' => 'wp_cache_clear_cache',
436 + 'W3 Total Cache' => 'w3tc_pgcache_flush',
437 + 'WP Fast Cache' => 'wp_fast_cache_bulk_delete_all',
438 + 'Rapidcache' => 'rapidcache_clear_cache',
439 + 'Siteground' => 'sg_cachepress_purge_cache',
440 + 'WP Super Cache' => 'prune_super_cache',
441 + );
442 +
443 + $_found_pagecache = false;
444 + if ( true !== $disregard_transient ) {
445 + $_ao_pagecache_transient = 'autoptimize_pagecache_check';
446 + $_found_pagecache = get_transient( $_ao_pagecache_transient );
447 + }
448 +
449 + if ( current_user_can( 'manage_options' ) && false === $_found_pagecache ) {
450 + // loop through known pagecache constants.
451 + foreach ( $_page_cache_constants as $_name => $_constant ) {
452 + if ( defined( $_constant ) ) {
453 + $_found_pagecache = $_name;
454 + break;
455 + }
456 + }
457 + // and loop through known pagecache classes.
458 + if ( false === $_found_pagecache ) {
459 + foreach ( $_page_cache_classes as $_name => $_class ) {
460 + if ( class_exists( $_class ) ) {
461 + $_found_pagecache = $_name;
462 + break;
463 + }
464 + }
465 + }
466 + // and loop through known pagecache functions.
467 + if ( false === $_found_pagecache ) {
468 + foreach ( $_page_cache_functions as $_name => $_function ) {
469 + if ( function_exists( $_function ) ) {
470 + $_found_pagecache = $_name;
471 + break;
472 + }
473 + }
474 + }
475 +
476 + // store in transient for 1 week if pagecache found.
477 + if ( true === $_found_pagecache && true !== $disregard_transient ) {
478 + set_transient( $_ao_pagecache_transient, true, WEEK_IN_SECONDS );
479 + }
480 + }
481 + }
482 +
483 + return $_found_pagecache;
484 + }
485 +
486 + /**
487 + * Returns true if on one of the AO settings tabs, false if not.
488 + * Used to limit notifications to AO settings pages.
489 + *
490 + * @return bool
491 + */
492 + public static function is_ao_settings() {
493 + $_is_ao_settings = ( str_replace( array( 'autoptimize', 'autoptimize_imgopt', 'ao_critcss', 'autoptimize_extra', 'ao_partners', 'ao_pro_boosters', 'ao_pro_pagecache', 'ao_protab' ), '', $_SERVER['REQUEST_URI'] ) !== $_SERVER['REQUEST_URI'] ? true : false );
494 + return $_is_ao_settings;
495 + }
496 +
497 + /**
498 + * Returns false if no conflicting plugins are found, the name if the plugin if found.
499 + *
500 + * @return bool|string
501 + */
502 + public static function find_potential_conflicts() {
503 + if ( defined( 'WPFC_WP_CONTENT_BASENAME' ) ) {
504 + $_wpfc_options = json_decode( get_option( 'WpFastestCache' ) );
505 + foreach ( array( 'wpFastestCacheMinifyCss', 'wpFastestCacheCombineCss', 'wpFastestCacheCombineJs' ) as $_wpfc_conflicting ) {
506 + if ( isset( $_wpfc_options->$_wpfc_conflicting ) && 'on' === $_wpfc_options->$_wpfc_conflicting ) {
507 + return 'WP Fastest Cache';
508 + }
509 + }
510 + } elseif ( defined( 'W3TC_VERSION' ) ) {
511 + $w3tc_config = file_get_contents( WP_CONTENT_DIR . '/w3tc-config/master.php' );
512 + $w3tc_minify_on = strpos( $w3tc_config, '"minify.enabled": true' );
513 + if ( $w3tc_minify_on ) {
514 + return 'W3 Total Cache';
515 + }
516 + } elseif ( defined( 'SiteGround_Optimizer\VERSION' ) ) {
517 + if ( get_option( 'siteground_optimizer_optimize_css' ) == 1 || get_option( 'siteground_optimizer_optimize_javascript' ) == 1 || get_option( 'siteground_optimizer_combine_javascript' ) == 1 || get_option( 'siteground_optimizer_combine_css' ) == 1 ) {
518 + return 'Siteground Optimizer';
519 + }
520 + } elseif ( defined( 'WPO_VERSION' ) ) {
521 + $_wpo_options = get_site_option( 'wpo_minify_config' );
522 + if ( is_array( $_wpo_options ) && 1 == $_wpo_options['enabled'] && ( 1 == $_wpo_options['enable_css'] || 1 == $_wpo_options['enable_js'] ) ) {
523 + return 'WP Optimize';
524 + }
525 + } elseif ( defined( 'WPACU_PLUGIN_VERSION' ) || defined( 'WPACU_PRO_PLUGIN_VERSION' ) ) {
526 + $wpacu_settings_class = new \WpAssetCleanUp\Settings();
527 + $wpacu_settings = $wpacu_settings_class->getAll();
528 +
529 + if ( $wpacu_settings['minify_loaded_css'] || $wpacu_settings['minify_loaded_js'] || $wpacu_settings['combine_loaded_js'] || $wpacu_settings['combine_loaded_css'] ) {
530 + return 'Asset Cleanup';
531 + }
532 + } elseif ( defined( 'WP_ROCKET_VERSION' ) && function_exists( 'get_rocket_option' ) ) {
533 + if ( get_rocket_option( 'minify_js' ) || get_rocket_option( 'minify_concatenate_js' ) || get_rocket_option( 'minify_css' ) || get_rocket_option( 'minify_concatenate_css' ) || get_rocket_option( 'async_css' ) ) {
534 + return 'WP Rocket';
535 + }
536 + } elseif ( function_exists( 'fvm_get_settings' ) ) {
537 + return 'Fast Velocity Minify';
538 + }
539 +
540 + return false;
541 + }
542 +
543 + /**
544 + * Returns true if false if on a local dev environment, true if not.
545 + * Used to disallow image opt/ critcss for local dev environments.
546 + *
547 + * @return bool
548 + */
549 + public static function is_local_server( $_domain = AUTOPTIMIZE_SITE_DOMAIN ) {
550 + static $_is_local_server = null;
551 +
552 + if ( null === $_is_local_server ) {
553 + if ( false === strpos( $_domain, '.' ) && false === strpos( $_domain, ':' ) ) {
554 + // no dots in domain or colon (ipv6 address), so impossible to reach, this also matches 'localhost' or any other single-word domain.
555 + $_is_local_server = true;
556 + } elseif ( in_array( $_domain, array( '127.0.0.1', '0000:0000:0000:0000:0000:0000:0000:0001', '0:0:0:0:0:0:0:1', '::1' ) ) ) {
557 + // localhost IPv4/ IPv6.
558 + $_is_local_server = true;
559 + } elseif ( 0 === strpos( $_domain, '127.' ) || 0 === strpos( $_domain, '192.168.' ) || 0 === strpos( $_domain, '10.' ) || 0 === strpos( $_domain, 'fd' ) ) {
560 + // private ranges so unreachable for imgopt/ CCSS.
561 + // fixme; 172.16.0.0–172.31.255.255 also private.
562 + $_is_local_server = true;
563 + } elseif ( autoptimizeUtils::str_ends_in( $_domain, '.local') ) {
564 + // matches 'whatever.local'.
565 + $_is_local_server = true;
566 + } else {
567 + // likely OK.
568 + $_is_local_server = false;
569 + }
570 + }
571 +
572 + // filter to override result for testing purposes.
573 + return apply_filters( 'autoptimize_filter_utils_is_local_server', $_is_local_server );
574 + }
575 +
576 + public static function strip_tags_array( $array ) {
577 + // strip all tags in an array (use case: avoid XSS in CCSS rules both when importing and when outputting).
578 + // based on https://stackoverflow.com/a/44732196/237449 but heavily tweaked.
579 + if ( is_array( $array ) ) {
580 + $result = array();
581 + foreach ( $array as $key => $value ){
582 + if ( is_array( $value ) ) {
583 + $result[$key] = autoptimizeUtils::strip_tags_array( $value );
584 + } else if ( is_string( $value ) ) {
585 + $result[$key] = wp_strip_all_tags( $value );
586 + } else {
587 + $result[$key] = $value;
588 + }
589 + }
590 + } else {
591 + $result = wp_strip_all_tags( $array );
592 + }
593 + return $result;
338 594 }
339 595 }