| @@ -22,8 +22,15 @@ | ||
| 22 | 22 | * @var bool |
| 23 | 23 | */ |
| 24 | 24 | public $debug_log = false; |
| 25 | 25 | |
| 26 | + /** | |
| 27 | + * Initiated $cdn_url. | |
| 28 | + * | |
| 29 | + * @var string | |
| 30 | + */ | |
| 31 | + public $cdn_url = ''; | |
| 32 | + | |
| 26 | 33 | public function __construct( $content ) |
| 27 | 34 | { |
| 28 | 35 | $this->content = $content; |
| 29 | 36 | } |
| @@ -69,8 +76,12 @@ | ||
| 69 | 76 | public function getpath( $url ) |
| 70 | 77 | { |
| 71 | 78 | $url = apply_filters( 'autoptimize_filter_cssjs_alter_url', $url ); |
| 72 | 79 | |
| 80 | + if ( is_null( $url ) ) { | |
| 81 | + return false; | |
| 82 | + } | |
| 83 | + | |
| 73 | 84 | if ( false !== strpos( $url, '%' ) ) { |
| 74 | 85 | $url = urldecode( $url ); |
| 75 | 86 | } |
| 76 | 87 | |
| @@ -87,8 +98,10 @@ | ||
| 87 | 98 | } |
| 88 | 99 | } elseif ( ( false === $double_slash_position ) && ( false === strpos( $url, $site_host ) ) ) { |
| 89 | 100 | if ( AUTOPTIMIZE_WP_SITE_URL === $site_host ) { |
| 90 | 101 | $url = AUTOPTIMIZE_WP_SITE_URL . $url; |
| 102 | + } elseif ( 0 === strpos( $url, '/' ) ) { | |
| 103 | + $url = '//' . $site_host . autoptimizeUtils::path_canonicalize( $url ); | |
| 91 | 104 | } else { |
| 92 | 105 | $url = AUTOPTIMIZE_WP_SITE_URL . autoptimizeUtils::path_canonicalize( $url ); |
| 93 | 106 | } |
| 94 | 107 | } |
| @@ -137,8 +150,16 @@ | ||
| 137 | 150 | // As we replaced the content-domain with the site-domain, we should match against that. |
| 138 | 151 | $tmp_ao_root = preg_replace( '/https?:/', '', AUTOPTIMIZE_WP_SITE_URL ); |
| 139 | 152 | } |
| 140 | 153 | |
| 154 | + if ( is_multisite() && ! is_main_site() && ! empty( $this->cdn_url ) && apply_filters( 'autoptimize_filter_base_getpage_multisite_cdn_juggling', true ) ) { | |
| 155 | + // multisite child sites with CDN need the network_site_url as tmp_ao_root but only if directory-based multisite. | |
| 156 | + $_network_site_url = network_site_url(); | |
| 157 | + if ( strpos( AUTOPTIMIZE_WP_SITE_URL, $_network_site_url ) !== false ) { | |
| 158 | + $tmp_ao_root = preg_replace( '/https?:/', '', $_network_site_url ); | |
| 159 | + } | |
| 160 | + } | |
| 161 | + | |
| 141 | 162 | $tmp_url = preg_replace( '/https?:/', '', $url ); |
| 142 | 163 | $path = str_replace( $tmp_ao_root, '', $tmp_url ); |
| 143 | 164 | |
| 144 | 165 | // If path starts with :// or //, this is not a URL in the WP context and |
| @@ -148,10 +169,14 @@ | ||
| 148 | 169 | return false; |
| 149 | 170 | } |
| 150 | 171 | |
| 151 | 172 | // Prepend with WP_ROOT_DIR to have full path to file. |
| 152 | - $path = str_replace( '//', '/', WP_ROOT_DIR . $path ); | |
| 173 | + $path = str_replace( '//', '/', trailingslashit( WP_ROOT_DIR ) . $path ); | |
| 153 | 174 | |
| 175 | + // Allow path to be altered, e.g. in the case of bedrock-like setups where | |
| 176 | + // core, theme & plugins might be in different locations on the filesystem. | |
| 177 | + $path = apply_filters( 'autoptimize_filter_base_getpath_path', $path, $url ); | |
| 178 | + | |
| 154 | 179 | // Final check: does file exist and is it readable? |
| 155 | 180 | if ( file_exists( $path ) && is_file( $path ) && is_readable( $path ) ) { |
| 156 | 181 | return $path; |
| 157 | 182 | } else { |
| @@ -293,15 +318,14 @@ | ||
| 293 | 318 | $cdn_url = autoptimizeUtils::tweak_cdn_url_if_needed( $this->cdn_url ); |
| 294 | 319 | |
| 295 | 320 | // Allows API/filter to further tweak the cdn url... |
| 296 | 321 | $cdn_url = apply_filters( 'autoptimize_filter_base_cdnurl', $cdn_url ); |
| 297 | - if ( ! empty( $cdn_url ) ) { | |
| 298 | - $this->debug_log( 'before=' . $url ); | |
| 322 | + if ( ! empty( $cdn_url ) && false === strpos( $url, $cdn_url ) && false !== apply_filters( 'autoptimize_filter_base_apply_cdn', true, $url ) ) { | |
| 299 | 323 | |
| 300 | 324 | // Simple str_replace-based approach fails when $url is protocol-or-host-relative. |
| 301 | 325 | $is_protocol_relative = autoptimizeUtils::is_protocol_relative( $url ); |
| 302 | - $is_host_relative = ( ! $is_protocol_relative && ( '/' === $url{0} ) ); | |
| 303 | - $cdn_url = rtrim( $cdn_url, '/' ); | |
| 326 | + $is_host_relative = ( ! $is_protocol_relative && ( '/' === $url[0] ) ); | |
| 327 | + $cdn_url = esc_url( rtrim( $cdn_url, '/' ) ); | |
| 304 | 328 | |
| 305 | 329 | if ( $is_host_relative ) { |
| 306 | 330 | // Prepending host-relative urls with the cdn url. |
| 307 | 331 | $url = $cdn_url . $url; |
| @@ -313,13 +337,10 @@ | ||
| 313 | 337 | $site_url = str_replace( array( 'http:', 'https:' ), '', AUTOPTIMIZE_WP_SITE_URL ); |
| 314 | 338 | } else { |
| 315 | 339 | $site_url = AUTOPTIMIZE_WP_SITE_URL; |
| 316 | 340 | } |
| 317 | - $this->debug_log( '`' . $site_url . '` -> `' . $cdn_url . '` in `' . $url . '`' ); | |
| 318 | 341 | $url = str_replace( $site_url, $cdn_url, $url ); |
| 319 | 342 | } |
| 320 | - | |
| 321 | - $this->debug_log( 'after=' . $url ); | |
| 322 | 343 | } |
| 323 | 344 | |
| 324 | 345 | // Allow API filter to take further care of CDN replacement. |
| 325 | 346 | $url = apply_filters( 'autoptimize_filter_base_replace_cdn', $url ); |
| @@ -416,11 +437,11 @@ | ||
| 416 | 437 | $filepath = null; |
| 417 | 438 | $filehash = null; |
| 418 | 439 | |
| 419 | 440 | // Grab the parts we need. |
| 420 | - $parts = explode( $matches[1], '|' ); | |
| 441 | + $parts = explode( '|', $matches[1] ); | |
| 421 | 442 | if ( ! empty( $parts ) ) { |
| 422 | - $filepath = isset( $parts[0] ) ? $parts[0] : null; | |
| 443 | + $filepath = isset( $parts[0] ) ? base64_decode( $parts[0] ) : null; | |
| 423 | 444 | $filehash = isset( $parts[1] ) ? $parts[1] : null; |
| 424 | 445 | } |
| 425 | 446 | |
| 426 | 447 | // Bail early if something's not right... |
| @@ -484,9 +505,8 @@ | ||
| 484 | 505 | */ |
| 485 | 506 | protected function inject_minified( $in ) |
| 486 | 507 | { |
| 487 | 508 | $out = $in; |
| 488 | - | |
| 489 | 509 | if ( false !== strpos( $in, '%%INJECTLATER%%' ) ) { |
| 490 | 510 | $out = preg_replace_callback( |
| 491 | 511 | '#\/\*\!%%INJECTLATER' . AUTOPTIMIZE_HASH . '%%(.*?)%%INJECTLATER%%\*\/#is', |
| 492 | 512 | array( $this, 'inject_minified_callback' ), |
| @@ -559,9 +579,9 @@ | ||
| 559 | 579 | * @param string $content Content to work on. |
| 560 | 580 | * |
| 561 | 581 | * @return string |
| 562 | 582 | */ |
| 563 | - protected function replace_contents_with_marker_if_exists( $marker, $search, $re_replace_pattern, $content ) | |
| 583 | + public static function replace_contents_with_marker_if_exists( $marker, $search, $re_replace_pattern, $content ) | |
| 564 | 584 | { |
| 565 | 585 | $found = false; |
| 566 | 586 | |
| 567 | 587 | $is_regex = autoptimizeUtils::str_is_valid_regex( $search ); |
| @@ -578,8 +598,17 @@ | ||
| 578 | 598 | return autoptimizeBase::build_marker( $marker, $matches[0] ); |
| 579 | 599 | }, |
| 580 | 600 | $content |
| 581 | 601 | ); |
| 602 | + | |
| 603 | + // Check for error (for example, an error can occur if $content is very large). | |
| 604 | + if ( null === $content ) { | |
| 605 | + $error_message = 'Autoptimize: preg_replace_callback() failed'; | |
| 606 | + if ( function_exists( 'preg_last_error_msg' ) ) { | |
| 607 | + $error_message .= ': ' . preg_last_error_msg(); | |
| 608 | + } | |
| 609 | + error_log( $error_message ); | |
| 610 | + } | |
| 582 | 611 | } |
| 583 | 612 | |
| 584 | 613 | return $content; |
| 585 | 614 | } |
| @@ -591,9 +620,9 @@ | ||
| 591 | 620 | * @param string $content Markup. |
| 592 | 621 | * |
| 593 | 622 | * @return string |
| 594 | 623 | */ |
| 595 | - protected function restore_marked_content( $marker, $content ) | |
| 624 | + public static function restore_marked_content( $marker, $content ) | |
| 596 | 625 | { |
| 597 | 626 | if ( false !== strpos( $content, $marker ) ) { |
| 598 | 627 | $content = preg_replace_callback( |
| 599 | 628 | '#%%' . $marker . AUTOPTIMIZE_HASH . '%%(.*?)%%' . $marker . '%%#is', |
| @@ -636,25 +665,23 @@ | ||
| 636 | 665 | */ |
| 637 | 666 | protected function prepare_minify_single( $filepath ) |
| 638 | 667 | { |
| 639 | 668 | // Decide what we're dealing with, return false if we don't know. |
| 640 | - if ( $this->str_ends_in( $filepath, '.js' ) ) { | |
| 669 | + if ( autoptimizeUtils::str_ends_in( $filepath, '.js' ) ) { | |
| 641 | 670 | $type = 'js'; |
| 642 | - } elseif ( $this->str_ends_in( $filepath, '.css' ) ) { | |
| 671 | + } elseif ( autoptimizeUtils::str_ends_in( $filepath, '.css' ) ) { | |
| 643 | 672 | $type = 'css'; |
| 644 | 673 | } else { |
| 645 | 674 | return false; |
| 646 | 675 | } |
| 647 | 676 | |
| 648 | - // Bail if it looks like its already minifed (by having -min or .min | |
| 649 | - // in filename) or if it looks like WP jquery.js (which is minified). | |
| 677 | + // Bail if it looks like its already minifed (by having -min or .min in filename). | |
| 650 | 678 | $minified_variants = array( |
| 651 | 679 | '-min.' . $type, |
| 652 | 680 | '.min.' . $type, |
| 653 | - 'js/jquery/jquery.js', | |
| 654 | 681 | ); |
| 655 | 682 | foreach ( $minified_variants as $ending ) { |
| 656 | - if ( $this->str_ends_in( $filepath, $ending ) ) { | |
| 683 | + if ( autoptimizeUtils::str_ends_in( $filepath, $ending ) && true === apply_filters( 'autoptimize_filter_base_prepare_exclude_minified', true ) ) { | |
| 657 | 684 | return false; |
| 658 | 685 | } |
| 659 | 686 | } |
| 660 | 687 | |
| @@ -679,26 +706,6 @@ | ||
| 679 | 706 | // CDN-replace the resulting URL if needed... |
| 680 | 707 | $url = $this->url_replace_cdn( $url ); |
| 681 | 708 | |
| 682 | 709 | return $url; |
| 683 | - } | |
| 684 | - | |
| 685 | - /** | |
| 686 | - * Returns true if given $str ends with given $test. | |
| 687 | - * | |
| 688 | - * @param string $str String to check. | |
| 689 | - * @param string $test Ending to match. | |
| 690 | - * | |
| 691 | - * @return bool | |
| 692 | - */ | |
| 693 | - protected function str_ends_in( $str, $test ) | |
| 694 | - { | |
| 695 | - // @codingStandardsIgnoreStart | |
| 696 | - // substr_compare() is bugged on 5.5.11: https://3v4l.org/qGYBH | |
| 697 | - // return ( 0 === substr_compare( $str, $test, -strlen( $test ) ) ); | |
| 698 | - // @codingStandardsIgnoreEnd | |
| 699 | - | |
| 700 | - $length = strlen( $test ); | |
| 701 | - | |
| 702 | - return ( substr( $str, -$length, $length ) === $test ); | |
| 703 | 710 | } |
| 704 | 711 | } |