W3 Total Cache - Version 0.12.0

Version Description

  • Added querystring based URL structures for AMP pages
  • Added filter of minify options
  • Added lazyload picture tag support
  • Removed footer link "Support Us" option
  • Improved wp_die handling
  • Improved lazyload handling of content in script tags
  • Improved lazyload handling of feeds
  • Improved printing tags coming from feeds
  • Improved handling of modified posts before wp_rewrite initialized
  • Nginx rules changed a lot to avoid "location" block conflicts. That change may cause problems on some systems using non-default WordPress rules - keep a backup of your original rules
  • Improved handling of .htaccess files in regard to EOF
  • Fixed Varnish purging
  • Fixed html minification of data tags equaling 0
Download this release

Release Info

Developer boldgrid
Plugin Icon 128x128 W3 Total Cache
Version 0.12.0
Comparing to
See all releases

Code changes from version 0.11.0 to 0.12.0

BrowserCache_Environment.php CHANGED
@@ -68,15 +68,6 @@ class BrowserCache_Environment {
68
  return null;
69
 
70
  $rewrite_rules = array();
71
- if ( Dispatcher::should_browsercache_generate_rules_for_cdn( $config ) ) {
72
- $domain = Dispatcher::get_cdn_domain();
73
- $cdn_rules_path = sprintf( 'ftp://%s/%s', $domain,
74
- Util_Rule::get_cdn_rules_path() );
75
- $rewrite_rules[] = array(
76
- 'filename' => $cdn_rules_path,
77
- 'content' => $this->rules_cache_generate( $config, true )
78
- );
79
- }
80
 
81
  $browsercache_rules_cache_path = Util_Rule::get_browsercache_rules_cache_path();
82
  $rewrite_rules[] = array(
@@ -192,7 +183,9 @@ class BrowserCache_Environment {
192
  return $this->rules_cache_generate_apache( $config );
193
 
194
  case Util_Environment::is_nginx():
195
- return $this->rules_cache_generate_nginx( $config, $cdnftp );
 
 
196
  }
197
  return '';
198
  }
@@ -492,12 +485,14 @@ class BrowserCache_Environment {
492
  $set_last_modified = $config->get_boolean( 'browsercache.' . $section . '.last_modified' );
493
  $compatibility = $config->get_boolean( 'pgcache.compatibility' );
494
 
495
- $extensions = array_keys( $mime_types );
 
 
496
 
497
  // Remove ext from filesmatch if its the same as permalink extension
498
  $pext = strtolower( pathinfo( get_option( 'permalink_structure' ), PATHINFO_EXTENSION ) );
499
  if ( $pext ) {
500
- $extensions = $this->_remove_extension_from_list( $extensions, $pext );
501
  }
502
 
503
  $extensions_lowercase = array_map( 'strtolower', $extensions );
@@ -593,326 +588,6 @@ class BrowserCache_Environment {
593
  return $rules;
594
  }
595
 
596
- /**
597
- * Returns cache rules
598
- *
599
- * @param Config $config
600
- * @param bool $cdnftp
601
- * @return string
602
- */
603
- private function rules_cache_generate_nginx( $config, $cdnftp = false ) {
604
- $mime_types = $this->get_mime_types();
605
- $cssjs_types = $mime_types['cssjs'];
606
- $cssjs_types = array_unique( $cssjs_types );
607
- $html_types = $mime_types['html'];
608
- $other_types = $mime_types['other'];
609
- $other_compression_types = $mime_types['other_compression'];
610
-
611
- $rules = '';
612
- $rules .= W3TC_MARKER_BEGIN_BROWSERCACHE_CACHE . "\n";
613
-
614
- if ( $config->get_boolean( 'browsercache.rewrite' ) ) {
615
- $core = Dispatcher::component( 'BrowserCache_Core' );
616
- $extensions = $core->get_replace_extensions( $config );
617
-
618
- $rules .= 'location ~ "^(?<w3tcbc_base>.+)\.(x[0-9]{5})' .
619
- '(?<w3tcbc_ext>\.(' . implode( '|', $extensions ) . '))$" {' . "\n";
620
- $rules .= ' if (-f $document_root$w3tcbc_base$w3tcbc_ext) {' . "\n";
621
- $rules .= ' rewrite .* $w3tcbc_base$w3tcbc_ext;' . "\n";
622
- $rules .= " }\n";
623
- $rules .= "}\n";
624
-
625
- }
626
-
627
- $cssjs_brotli = $config->get_boolean( 'browsercache.cssjs.brotli' );
628
- $html_brotli = $config->get_boolean( 'browsercache.html.brotli' );
629
- $other_brotli = $config->get_boolean( 'browsercache.other.brotli' );
630
-
631
- if ( $cssjs_brotli || $html_brotli || $other_brotli ) {
632
- $brotli_types = array();
633
-
634
- if ( $cssjs_brotli ) {
635
- $brotli_types = array_merge( $brotli_types, $cssjs_types );
636
- }
637
-
638
- if ( $html_brotli ) {
639
- $brotli_types = array_merge( $brotli_types, $html_types );
640
- }
641
-
642
- if ( $other_brotli ) {
643
- $brotli_types = array_merge( $brotli_types,
644
- $other_compression_types );
645
- }
646
-
647
- unset( $brotli_types['html|htm'] );
648
-
649
- // some nginx cant handle values longer than 47 chars
650
- unset( $brotli_types['odp'] );
651
-
652
- $rules .= "brotli on;\n";
653
- $rules .= 'brotli_types ' .
654
- implode( ' ', array_unique( $brotli_types ) ) . ";\n";
655
- }
656
-
657
- $cssjs_compression = $config->get_boolean( 'browsercache.cssjs.compression' );
658
- $html_compression = $config->get_boolean( 'browsercache.html.compression' );
659
- $other_compression = $config->get_boolean( 'browsercache.other.compression' );
660
-
661
- if ( $cssjs_compression || $html_compression || $other_compression ) {
662
- $compression_types = array();
663
-
664
- if ( $cssjs_compression ) {
665
- $compression_types = array_merge( $compression_types, $cssjs_types );
666
- }
667
-
668
- if ( $html_compression ) {
669
- $compression_types = array_merge( $compression_types, $html_types );
670
- }
671
-
672
- if ( $other_compression ) {
673
- $compression_types = array_merge( $compression_types,
674
- $other_compression_types );
675
- }
676
-
677
- unset( $compression_types['html|htm'] );
678
-
679
- // some nginx cant handle values longer than 47 chars
680
- unset( $compression_types['odp'] );
681
-
682
- $rules .= "gzip on;\n";
683
- $rules .= "gzip_types " .
684
- implode( ' ', array_unique( $compression_types ) ) . ";\n";
685
- }
686
-
687
- if ( $config->get_boolean( 'browsercache.no404wp' ) ) {
688
- $exceptions = $config->get_array( 'browsercache.no404wp.exceptions' );
689
-
690
- $impoloded = implode( '|', $exceptions );
691
- if ( !empty( $impoloded ) ) {
692
- $wp_uri = network_home_url( '', 'relative' );
693
- $wp_uri = rtrim( $wp_uri, '/' );
694
-
695
- $rules .= "location ~ (" . $impoloded . ") {\n";
696
- $rules .= ' try_files $uri $uri/ $uri.html ' . $wp_uri .
697
- '/index.php?$args;' . "\n";
698
- $rules .= "}\n";
699
- }
700
- }
701
-
702
- foreach ( $mime_types as $type => $extensions ) {
703
- if ( $type != 'other_compression' ) {
704
- $this->_rules_cache_generate_nginx_for_type( $config, $rules,
705
- $extensions, $type );
706
- }
707
- }
708
-
709
- if ( $config->get_boolean( 'browsercache.hsts' ) ||
710
- $config->get_boolean( 'browsercache.security.xfo' ) ||
711
- $config->get_boolean( 'browsercache.security.xss' ) ||
712
- $config->get_boolean( 'browsercache.security.xcto' ) ||
713
- $config->get_boolean( 'browsercache.security.pkp' ) ||
714
- $config->get_boolean( 'browsercache.security.referrer.policy' ) ||
715
- $config->get_boolean( 'browsercache.security.csp' )
716
- ) {
717
- $lifetime = $config->get_integer( 'browsercache.other.lifetime' );
718
-
719
- if ( $config->get_boolean( 'browsercache.hsts' ) ) {
720
- $dir = $config->get_string( 'browsercache.security.hsts.directive' );
721
- $rules .= "add_header Strict-Transport-Security \"max-age=$lifetime" . ( strpos( $dir,"inc" ) ? "; includeSubDomains" : "" ) . ( strpos( $dir, "pre" ) ? "; preload" : "" ) . "\";\n";
722
- }
723
-
724
- if ( $config->get_boolean( 'browsercache.security.xfo' ) ) {
725
- $dir = $config->get_string( 'browsercache.security.xfo.directive' );
726
- $url = trim( $config->get_string( 'browsercache.security.xfo.allow' ) );
727
- if ( empty( $url ) ) {
728
- $url = Util_Environment::home_url_maybe_https();
729
- }
730
- $rules .= "add_header X-Frame-Options \"" . ( $dir == "same" ? "SAMEORIGIN" : ( $dir == "deny" ? "DENY" : "ALLOW-FROM $url" ) ) . "\";\n";
731
- }
732
-
733
- if ( $config->get_boolean( 'browsercache.security.xss' ) ) {
734
- $dir = $config->get_string( 'browsercache.security.xss.directive' );
735
- $rules .= "add_header X-XSS-Protection \"" . ( $dir == "block" ? "1; mode=block" : $dir ) . "\";\n";
736
-
737
- }
738
-
739
- if ( $config->get_boolean( 'browsercache.security.xcto' ) ) {
740
- $rules .= "add_header X-Content-Type-Options \"nosniff\";\n";
741
- }
742
-
743
- if ( $config->get_boolean( 'browsercache.security.pkp' ) ) {
744
- $pin = trim( $config->get_string( 'browsercache.security.pkp.pin' ) );
745
- $pinbak = trim( $config->get_string( 'browsercache.security.pkp.pin.backup' ) );
746
- $extra = $config->get_string( 'browsercache.security.pkp.extra' );
747
- $url = trim( $config->get_string( 'browsercache.security.pkp.report.url' ) );
748
- $rep_only = $config->get_string( 'browsercache.security.pkp.report.only' ) == '1' ? true : false;
749
- $rules .= "add_header " . ( $rep_only ? "Public-Key-Pins-Report-Only" : "Public-Key-Pins" ) . " 'pin-sha256=\"$pin\"; pin-sha256=\"$pinbak\"; max-age=$lifetime" . ( strpos( $extra,"inc" ) ? "; includeSubDomains" : "" ) . ( !empty( $url ) ? "; report-uri=\"$url\"" : "" ) . "';\n";
750
- }
751
-
752
- if ( $config->get_boolean( 'browsercache.security.referrer.policy' ) ) {
753
- $dir = $config->get_string( 'browsercache.security.referrer.policy.directive' );
754
- $rules .= "add_header Referrer-Policy \"" . ( $dir == "0" ? "" : $dir ) . "\";\n";
755
- }
756
-
757
- if ( $config->get_boolean( 'browsercache.security.csp' ) ) {
758
- $base = trim( $config->get_string( 'browsercache.security.csp.base' ) );
759
- $frame = trim( $config->get_string( 'browsercache.security.csp.frame' ) );
760
- $connect = trim( $config->get_string( 'browsercache.security.csp.connect' ) );
761
- $font = trim( $config->get_string( 'browsercache.security.csp.font' ) );
762
- $script = trim( $config->get_string( 'browsercache.security.csp.script' ) );
763
- $style = trim( $config->get_string( 'browsercache.security.csp.style' ) );
764
- $img = trim( $config->get_string( 'browsercache.security.csp.img' ) );
765
- $media = trim( $config->get_string( 'browsercache.security.csp.media' ) );
766
- $object = trim( $config->get_string( 'browsercache.security.csp.object' ) );
767
- $plugin = trim( $config->get_string( 'browsercache.security.csp.plugin' ) );
768
- $form = trim( $config->get_string( 'browsercache.security.csp.form' ) );
769
- $frame_ancestors = trim( $config->get_string( 'browsercache.security.csp.frame.ancestors' ) );
770
- $sandbox = $config->get_string( 'browsercache.security.csp.sandbox' );
771
- $default = trim( $config->get_string( 'browsercache.security.csp.default' ) );
772
-
773
- $dir = rtrim( ( !empty( $base ) ? "base-uri $base; " : "" ).
774
- ( !empty( $frame ) ? "frame-src $frame; " : "" ).
775
- ( !empty( $connect ) ? "connect-src $connect; " : "" ).
776
- ( !empty( $font ) ? "font-src $font; " : "" ).
777
- ( !empty( $script ) ? "script-src $script; " : "" ).
778
- ( !empty( $style ) ? "style-src $style; " : "" ).
779
- ( !empty( $img ) ? "img-src $img; " : "" ).
780
- ( !empty( $media ) ? "media-src $media; " : "" ).
781
- ( !empty( $object ) ? "object-src $object; " : "" ).
782
- ( !empty( $plugin ) ? "plugin-types $plugin; " : "" ).
783
- ( !empty( $form ) ? "form-action $form; " : "" ).
784
- ( !empty( $frame_ancestors ) ? "frame-ancestors $frame_ancestors; " : "" ).
785
- ( !empty( $sandbox ) ? "sandbox " . trim( $sandbox ) . "; " : "" ).
786
- ( !empty( $default ) ? "default-src $default;" : "" ), "; " );
787
-
788
- if ( !empty( $dir ) ) {
789
- $rules .= "add_header Content-Security-Policy \"$dir\";\n";
790
- }
791
- }
792
- }
793
-
794
- $rules .= W3TC_MARKER_END_BROWSERCACHE_CACHE . "\n";
795
-
796
- return $rules;
797
- }
798
-
799
- /**
800
- * Adds cache rules for type to &$rules
801
- *
802
- * @param Config $config
803
- * @param string $rules
804
- * @param array $mime_types
805
- * @param string $section
806
- * @return void
807
- */
808
- private function _rules_cache_generate_nginx_for_type( $config, &$rules,
809
- $mime_types, $section ) {
810
-
811
- $expires = $config->get_boolean( 'browsercache.' . $section . '.expires' );
812
- $etag = $config->get_boolean( 'browsercache.' . $section . '.etag' );
813
- $cache_control = $config->get_boolean( 'browsercache.' . $section . '.cache.control' );
814
- $w3tc = $config->get_boolean( 'browsercache.' . $section . '.w3tc' );
815
- $last_modified = $config->get_boolean( 'browsercache.' . $section . '.last_modified' );
816
-
817
- if ( $etag || $expires || $cache_control || $w3tc || !$last_modified ) {
818
- $lifetime = $config->get_integer( 'browsercache.' . $section . '.lifetime' );
819
-
820
- $extensions = array_keys( $mime_types );
821
-
822
- // Remove ext from filesmatch if its the same as permalink extension
823
- $pext = strtolower( pathinfo( get_option( 'permalink_structure' ), PATHINFO_EXTENSION ) );
824
- if ( $pext ) {
825
- $extensions = $this->_remove_extension_from_list( $extensions, $pext );
826
- }
827
-
828
- $rules .= "location ~ \\.(" . implode( '|', $extensions ) . ")$ {\n";
829
-
830
- if ( $expires ) {
831
- $rules .= " expires " . $lifetime . "s;\n";
832
- }
833
- if ( version_compare( Util_Environment::get_server_version(), '1.3.3', '>=' ) ) {
834
- if ( $etag ) {
835
- $rules .= " etag on;\n";
836
- } else {
837
- $rules .= " etag off;\n";
838
- }
839
- }
840
- if ( $last_modified ) {
841
- $rules .= " if_modified_since exact;\n";
842
- } else {
843
- $rules .= " if_modified_since off;\n";
844
- }
845
-
846
- $add_header_rules = '';
847
-
848
- if ( $cache_control ) {
849
- $cache_policy = $config->get_string( 'browsercache.' . $section . '.cache.policy' );
850
-
851
- switch ( $cache_policy ) {
852
- case 'cache':
853
- $add_header_rules .= " add_header Pragma \"public\";\n";
854
- $add_header_rules .= " add_header Cache-Control \"public\";\n";
855
- break;
856
-
857
- case 'cache_public_maxage':
858
- $add_header_rules .= " add_header Pragma \"public\";\n";
859
-
860
- if ( $expires ) {
861
- $add_header_rules .= " add_header Cache-Control \"public\";\n";
862
- } else {
863
- $add_header_rules .= " add_header Cache-Control \"max-age=" . $lifetime . ", public\";\n";
864
- }
865
- break;
866
-
867
- case 'cache_validation':
868
- $add_header_rules .= " add_header Pragma \"public\";\n";
869
- $add_header_rules .= " add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n";
870
- break;
871
-
872
- case 'cache_noproxy':
873
- $add_header_rules .= " add_header Pragma \"public\";\n";
874
- $add_header_rules .= " add_header Cache-Control \"private, must-revalidate\";\n";
875
- break;
876
-
877
- case 'cache_maxage':
878
- $add_header_rules .= " add_header Pragma \"public\";\n";
879
-
880
- if ( $expires ) {
881
- $add_header_rules .= " add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n";
882
- } else {
883
- $add_header_rules .= " add_header Cache-Control \"max-age=" . $lifetime . ", public, must-revalidate, proxy-revalidate\";\n";
884
- }
885
- break;
886
-
887
- case 'no_cache':
888
- $add_header_rules .= " add_header Pragma \"no-cache\";\n";
889
- $add_header_rules .= " add_header Cache-Control \"max-age=0, private, no-store, no-cache, must-revalidate\";\n";
890
- break;
891
- }
892
- }
893
-
894
- if ( $w3tc ) {
895
- $add_header_rules .= " add_header X-Powered-By \"" .
896
- Util_Environment::w3tc_header() . "\";\n";
897
- }
898
-
899
- $rules .= $add_header_rules;
900
- $rules .= Dispatcher::on_browsercache_rules_generation_for_section(
901
- $config, false, $section, $add_header_rules );
902
-
903
- if ( !$config->get_boolean( 'browsercache.no404wp' ) ) {
904
- $wp_uri = network_home_url( '', 'relative' );
905
- $wp_uri = rtrim( $wp_uri, '/' );
906
-
907
- $rules .= ' try_files $uri $uri/ $uri.html ' . $wp_uri .
908
- '/index.php?$args;' . "\n";
909
- }
910
- $rules .= "}\n";
911
- }
912
- }
913
-
914
-
915
-
916
  /*
917
  * rules_no404wp
918
  */
@@ -1041,40 +716,4 @@ class BrowserCache_Environment {
1041
 
1042
  return $rules;
1043
  }
1044
-
1045
- /**
1046
- * Returns the apache, nginx version
1047
- *
1048
- * @return string
1049
- */
1050
- private function _get_server_version() {
1051
- $sig= explode( '/', $_SERVER['SERVER_SOFTWARE'] );
1052
- $temp = isset( $sig[1] ) ? explode( ' ', $sig[1] ) : array( '0' );
1053
- $version = $temp[0];
1054
- return $version;
1055
- }
1056
-
1057
- /**
1058
- * Takes an array of extensions single per row and/or extensions delimited by |
1059
- *
1060
- * @param unknown $extensions
1061
- * @param unknown $ext
1062
- * @return array
1063
- */
1064
- private function _remove_extension_from_list( $extensions, $ext ) {
1065
- for ( $i = 0; $i < sizeof( $extensions ); $i++ ) {
1066
- if ( $extensions[$i] == $ext ) {
1067
- unset( $extensions[$i] );
1068
- return $extensions;
1069
- } elseif ( strpos( $extensions[$i], $ext ) !== false &&
1070
- strpos( $extensions[$i], '|' ) !== false ) {
1071
- $exts = explode( '|', $extensions[$i] );
1072
- $key = array_search( $ext, $exts );
1073
- unset( $exts[$key] );
1074
- $extensions[$i] = implode( '|', $exts );
1075
- return $extensions;
1076
- }
1077
- }
1078
- return $extensions;
1079
- }
1080
  }
68
  return null;
69
 
70
  $rewrite_rules = array();
 
 
 
 
 
 
 
 
 
71
 
72
  $browsercache_rules_cache_path = Util_Rule::get_browsercache_rules_cache_path();
73
  $rewrite_rules[] = array(
183
  return $this->rules_cache_generate_apache( $config );
184
 
185
  case Util_Environment::is_nginx():
186
+ $generator_nginx = new BrowserCache_Environment_Nginx( $config );
187
+ $mime_types = $this->get_mime_types();
188
+ return $generator_nginx->generate( $mime_types, $cdnftp );
189
  }
190
  return '';
191
  }
485
  $set_last_modified = $config->get_boolean( 'browsercache.' . $section . '.last_modified' );
486
  $compatibility = $config->get_boolean( 'pgcache.compatibility' );
487
 
488
+ $mime_types2 = apply_filters( 'w3tc_browsercache_rules_section_extensions',
489
+ $mime_types, $config, $section );
490
+ $extensions = array_keys( $mime_types2 );
491
 
492
  // Remove ext from filesmatch if its the same as permalink extension
493
  $pext = strtolower( pathinfo( get_option( 'permalink_structure' ), PATHINFO_EXTENSION ) );
494
  if ( $pext ) {
495
+ $extensions = Util_Rule::remove_extension_from_list( $extensions, $pext );
496
  }
497
 
498
  $extensions_lowercase = array_map( 'strtolower', $extensions );
588
  return $rules;
589
  }
590
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
  /*
592
  * rules_no404wp
593
  */
716
 
717
  return $rules;
718
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  }
BrowserCache_Environment_Nginx.php ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * Rules generation for Nginx
6
+ */
7
+ class BrowserCache_Environment_Nginx {
8
+ private $c;
9
+
10
+
11
+
12
+ public function __construct( $config ) {
13
+ $this->c = $config;
14
+ }
15
+
16
+
17
+
18
+ /**
19
+ * Returns cache rules
20
+ */
21
+ public function generate( $mime_types, $cdnftp = false ) {
22
+ $cssjs_types = $mime_types['cssjs'];
23
+ $cssjs_types = array_unique( $cssjs_types );
24
+ $html_types = $mime_types['html'];
25
+ $other_types = $mime_types['other'];
26
+ $other_compression_types = $mime_types['other_compression'];
27
+
28
+ $rules = '';
29
+ $rules .= W3TC_MARKER_BEGIN_BROWSERCACHE_CACHE . "\n";
30
+
31
+ if ( $this->c->get_boolean( 'browsercache.rewrite' ) ) {
32
+ $core = Dispatcher::component( 'BrowserCache_Core' );
33
+ $extensions = $core->get_replace_extensions( $this->c );
34
+
35
+ $exts = implode( '|', $extensions );
36
+
37
+ $rules .= "set \$w3tcbc_rewrite_filename '';\n";
38
+ $rules .= "set \$w3tcbc_rewrite_uri '';\n";
39
+ $rules .= "if (\$uri ~ '^(?<w3tcbc_base>.+)\.(x[0-9]{5})" .
40
+ "(?<w3tcbc_ext>\.($exts))$') {\n";
41
+ $rules .= " set \$w3tcbc_rewrite_filename \$document_root\$w3tcbc_base\$w3tcbc_ext;\n";
42
+ $rules .= " set \$w3tcbc_rewrite_uri \$w3tcbc_base\$w3tcbc_ext;\n";
43
+ $rules .= "}\n";
44
+
45
+ if ( Util_Environment::is_wpmu() &&
46
+ !Util_Environment::is_wpmu_subdomain() ) {
47
+ // WPMU subdir extra rewrite
48
+
49
+ if ( defined( 'W3TC_HOME_URI' ) ) {
50
+ $home_uri = W3TC_HOME_URI;
51
+ } else {
52
+ $primary_blog_id = get_network()->site_id;
53
+ $home_uri = parse_url( get_home_url( $primary_blog_id ),
54
+ PHP_URL_PATH );
55
+ $home_uri = rtrim( $home_uri, '/' );
56
+ }
57
+
58
+ $rules .= "if (\$uri ~ '^$home_uri/[_0-9a-zA-Z-]+(?<w3tcbc_base>/wp-.+)\.(x[0-9]{5})(?<w3tcbc_ext>\.($exts))$') {\n";
59
+ $rules .= " set \$w3tcbc_rewrite_filename \$document_root$home_uri\$w3tcbc_base\$w3tcbc_ext;\n";
60
+ $rules .= " set \$w3tcbc_rewrite_uri $home_uri\$w3tcbc_base\$w3tcbc_ext;\n";
61
+ $rules .= "}\n";
62
+ }
63
+
64
+ $rules .= "if (-f \$w3tcbc_rewrite_filename) {\n";
65
+ $rules .= " rewrite .* \$w3tcbc_rewrite_uri;\n";
66
+ $rules .= "}\n";
67
+ }
68
+
69
+ $cssjs_brotli = $this->c->get_boolean( 'browsercache.cssjs.brotli' );
70
+ $html_brotli = $this->c->get_boolean( 'browsercache.html.brotli' );
71
+ $other_brotli = $this->c->get_boolean( 'browsercache.other.brotli' );
72
+
73
+ if ( $cssjs_brotli || $html_brotli || $other_brotli ) {
74
+ $brotli_types = array();
75
+
76
+ if ( $cssjs_brotli ) {
77
+ $brotli_types = array_merge( $brotli_types, $cssjs_types );
78
+ }
79
+
80
+ if ( $html_brotli ) {
81
+ $brotli_types = array_merge( $brotli_types, $html_types );
82
+ }
83
+
84
+ if ( $other_brotli ) {
85
+ $brotli_types = array_merge( $brotli_types,
86
+ $other_compression_types );
87
+ }
88
+
89
+ unset( $brotli_types['html|htm'] );
90
+
91
+ // some nginx cant handle values longer than 47 chars
92
+ unset( $brotli_types['odp'] );
93
+
94
+ $rules .= "brotli on;\n";
95
+ $rules .= 'brotli_types ' .
96
+ implode( ' ', array_unique( $brotli_types ) ) . ";\n";
97
+ }
98
+
99
+ $cssjs_compression = $this->c->get_boolean( 'browsercache.cssjs.compression' );
100
+ $html_compression = $this->c->get_boolean( 'browsercache.html.compression' );
101
+ $other_compression = $this->c->get_boolean( 'browsercache.other.compression' );
102
+
103
+ if ( $cssjs_compression || $html_compression || $other_compression ) {
104
+ $compression_types = array();
105
+
106
+ if ( $cssjs_compression ) {
107
+ $compression_types = array_merge( $compression_types, $cssjs_types );
108
+ }
109
+
110
+ if ( $html_compression ) {
111
+ $compression_types = array_merge( $compression_types, $html_types );
112
+ }
113
+
114
+ if ( $other_compression ) {
115
+ $compression_types = array_merge( $compression_types,
116
+ $other_compression_types );
117
+ }
118
+
119
+ unset( $compression_types['html|htm'] );
120
+
121
+ // some nginx cant handle values longer than 47 chars
122
+ unset( $compression_types['odp'] );
123
+
124
+ $rules .= "gzip on;\n";
125
+ $rules .= "gzip_types " .
126
+ implode( ' ', array_unique( $compression_types ) ) . ";\n";
127
+ }
128
+
129
+ if ( $this->c->get_boolean( 'browsercache.no404wp' ) ) {
130
+ $exceptions = $this->c->get_array( 'browsercache.no404wp.exceptions' );
131
+
132
+ $impoloded = implode( '|', $exceptions );
133
+ if ( !empty( $impoloded ) ) {
134
+ $wp_uri = network_home_url( '', 'relative' );
135
+ $wp_uri = rtrim( $wp_uri, '/' );
136
+
137
+ $rules .= "location ~ (" . $impoloded . ") {\n";
138
+ $rules .= ' try_files $uri $uri/ ' . $wp_uri .
139
+ '/index.php?$args;' . "\n";
140
+ $rules .= "}\n";
141
+ }
142
+ }
143
+
144
+ foreach ( $mime_types as $type => $extensions ) {
145
+ if ( $type != 'other_compression' ) {
146
+ $this->generate_section( $rules, $extensions, $type );
147
+ }
148
+ }
149
+
150
+ $rules .= implode( "\n", $this->security_rules() ) . "\n";
151
+ $rules .= W3TC_MARKER_END_BROWSERCACHE_CACHE . "\n";
152
+
153
+ return $rules;
154
+ }
155
+
156
+
157
+
158
+ /**
159
+ * Returns security header directives
160
+ */
161
+ private function security_rules() {
162
+ $rules = [];
163
+
164
+ if ( $this->c->get_boolean( 'browsercache.hsts' ) ||
165
+ $this->c->get_boolean( 'browsercache.security.xfo' ) ||
166
+ $this->c->get_boolean( 'browsercache.security.xss' ) ||
167
+ $this->c->get_boolean( 'browsercache.security.xcto' ) ||
168
+ $this->c->get_boolean( 'browsercache.security.pkp' ) ||
169
+ $this->c->get_boolean( 'browsercache.security.referrer.policy' ) ||
170
+ $this->c->get_boolean( 'browsercache.security.csp' )
171
+ ) {
172
+ $lifetime = $this->c->get_integer( 'browsercache.other.lifetime' );
173
+
174
+ if ( $this->c->get_boolean( 'browsercache.hsts' ) ) {
175
+ $dir = $this->c->get_string( 'browsercache.security.hsts.directive' );
176
+ $rules[] = "add_header Strict-Transport-Security \"max-age=$lifetime" . ( strpos( $dir,"inc" ) ? "; includeSubDomains" : "" ) . ( strpos( $dir, "pre" ) ? "; preload" : "" ) . "\";";
177
+ }
178
+
179
+ if ( $this->c->get_boolean( 'browsercache.security.xfo' ) ) {
180
+ $dir = $this->c->get_string( 'browsercache.security.xfo.directive' );
181
+ $url = trim( $this->c->get_string( 'browsercache.security.xfo.allow' ) );
182
+ if ( empty( $url ) ) {
183
+ $url = Util_Environment::home_url_maybe_https();
184
+ }
185
+ $rules[] = "add_header X-Frame-Options \"" . ( $dir == "same" ? "SAMEORIGIN" : ( $dir == "deny" ? "DENY" : "ALLOW-FROM $url" ) ) . "\";";
186
+ }
187
+
188
+ if ( $this->c->get_boolean( 'browsercache.security.xss' ) ) {
189
+ $dir = $this->c->get_string( 'browsercache.security.xss.directive' );
190
+ $rules[] = "add_header X-XSS-Protection \"" . ( $dir == "block" ? "1; mode=block" : $dir ) . "\";";
191
+ }
192
+
193
+ if ( $this->c->get_boolean( 'browsercache.security.xcto' ) ) {
194
+ $rules[] = "add_header X-Content-Type-Options \"nosniff\";";
195
+ }
196
+
197
+ if ( $this->c->get_boolean( 'browsercache.security.pkp' ) ) {
198
+ $pin = trim( $this->c->get_string( 'browsercache.security.pkp.pin' ) );
199
+ $pinbak = trim( $this->c->get_string( 'browsercache.security.pkp.pin.backup' ) );
200
+ $extra = $this->c->get_string( 'browsercache.security.pkp.extra' );
201
+ $url = trim( $this->c->get_string( 'browsercache.security.pkp.report.url' ) );
202
+ $rep_only = $this->c->get_string( 'browsercache.security.pkp.report.only' ) == '1' ? true : false;
203
+ $rules[] = "add_header " . ( $rep_only ? "Public-Key-Pins-Report-Only" : "Public-Key-Pins" ) . " 'pin-sha256=\"$pin\"; pin-sha256=\"$pinbak\"; max-age=$lifetime" . ( strpos( $extra,"inc" ) ? "; includeSubDomains" : "" ) . ( !empty( $url ) ? "; report-uri=\"$url\"" : "" ) . "';";
204
+ }
205
+
206
+ if ( $this->c->get_boolean( 'browsercache.security.referrer.policy' ) ) {
207
+ $dir = $this->c->get_string( 'browsercache.security.referrer.policy.directive' );
208
+ $rules[] = "add_header Referrer-Policy \"" . ( $dir == "0" ? "" : $dir ) . "\";";
209
+ }
210
+
211
+ if ( $this->c->get_boolean( 'browsercache.security.csp' ) ) {
212
+ $base = trim( $this->c->get_string( 'browsercache.security.csp.base' ) );
213
+ $frame = trim( $this->c->get_string( 'browsercache.security.csp.frame' ) );
214
+ $connect = trim( $this->c->get_string( 'browsercache.security.csp.connect' ) );
215
+ $font = trim( $this->c->get_string( 'browsercache.security.csp.font' ) );
216
+ $script = trim( $this->c->get_string( 'browsercache.security.csp.script' ) );
217
+ $style = trim( $this->c->get_string( 'browsercache.security.csp.style' ) );
218
+ $img = trim( $this->c->get_string( 'browsercache.security.csp.img' ) );
219
+ $media = trim( $this->c->get_string( 'browsercache.security.csp.media' ) );
220
+ $object = trim( $this->c->get_string( 'browsercache.security.csp.object' ) );
221
+ $plugin = trim( $this->c->get_string( 'browsercache.security.csp.plugin' ) );
222
+ $form = trim( $this->c->get_string( 'browsercache.security.csp.form' ) );
223
+ $frame_ancestors = trim( $this->c->get_string( 'browsercache.security.csp.frame.ancestors' ) );
224
+ $sandbox = $this->c->get_string( 'browsercache.security.csp.sandbox' );
225
+ $default = trim( $this->c->get_string( 'browsercache.security.csp.default' ) );
226
+
227
+ $dir = rtrim( ( !empty( $base ) ? "base-uri $base; " : "" ).
228
+ ( !empty( $frame ) ? "frame-src $frame; " : "" ).
229
+ ( !empty( $connect ) ? "connect-src $connect; " : "" ).
230
+ ( !empty( $font ) ? "font-src $font; " : "" ).
231
+ ( !empty( $script ) ? "script-src $script; " : "" ).
232
+ ( !empty( $style ) ? "style-src $style; " : "" ).
233
+ ( !empty( $img ) ? "img-src $img; " : "" ).
234
+ ( !empty( $media ) ? "media-src $media; " : "" ).
235
+ ( !empty( $object ) ? "object-src $object; " : "" ).
236
+ ( !empty( $plugin ) ? "plugin-types $plugin; " : "" ).
237
+ ( !empty( $form ) ? "form-action $form; " : "" ).
238
+ ( !empty( $frame_ancestors ) ? "frame-ancestors $frame_ancestors; " : "" ).
239
+ ( !empty( $sandbox ) ? "sandbox " . trim( $sandbox ) . "; " : "" ).
240
+ ( !empty( $default ) ? "default-src $default;" : "" ), "; " );
241
+
242
+ if ( !empty( $dir ) ) {
243
+ $rules[] = "add_header Content-Security-Policy \"$dir\";";
244
+ }
245
+ }
246
+ }
247
+
248
+ return $rules;
249
+ }
250
+
251
+
252
+
253
+ /**
254
+ * Adds cache rules for type to &$rules
255
+ *
256
+ * @param string $rules
257
+ * @param array $mime_types
258
+ * @param string $section
259
+ * @return void
260
+ */
261
+ private function generate_section( &$rules, $mime_types, $section ) {
262
+ $expires = $this->c->get_boolean( 'browsercache.' . $section . '.expires' );
263
+ $etag = $this->c->get_boolean( 'browsercache.' . $section . '.etag' );
264
+ $cache_control = $this->c->get_boolean( 'browsercache.' . $section . '.cache.control' );
265
+ $w3tc = $this->c->get_boolean( 'browsercache.' . $section . '.w3tc' );
266
+ $last_modified = $this->c->get_boolean( 'browsercache.' . $section . '.last_modified' );
267
+
268
+ if ( $etag || $expires || $cache_control || $w3tc || !$last_modified ) {
269
+ $lifetime = $this->c->get_integer( 'browsercache.' . $section . '.lifetime' );
270
+
271
+ $mime_types2 = apply_filters( 'w3tc_browsercache_rules_section_extensions',
272
+ $mime_types, $this->c, $section );
273
+ $extensions = array_keys( $mime_types2 );
274
+
275
+ // Remove ext from filesmatch if its the same as permalink extension
276
+ $pext = strtolower( pathinfo( get_option( 'permalink_structure' ), PATHINFO_EXTENSION ) );
277
+ if ( $pext ) {
278
+ $extensions = Util_Rule::remove_extension_from_list( $extensions, $pext );
279
+ }
280
+
281
+ $rules .= "location ~ \\.(" . implode( '|', $extensions ) . ")$ {\n";
282
+
283
+ $subrules = Dispatcher::nginx_rules_for_browsercache_section(
284
+ $this->c, $section );
285
+ $rules .= ' ' . implode( "\n ", $subrules ) . "\n";
286
+
287
+ if ( !$this->c->get_boolean( 'browsercache.no404wp' ) ) {
288
+ $wp_uri = network_home_url( '', 'relative' );
289
+ $wp_uri = rtrim( $wp_uri, '/' );
290
+
291
+ $rules .= ' try_files $uri $uri/ ' . $wp_uri .
292
+ '/index.php?$args;' . "\n";
293
+ }
294
+ $rules .= "}\n";
295
+ }
296
+ }
297
+
298
+
299
+
300
+ /**
301
+ * Returns directives plugin applies to files of specific section
302
+ * Without location
303
+ *
304
+ * $extra_add_headers_set specifies if other add_header directives will
305
+ * be added to location block generated
306
+ */
307
+ public function section_rules( $section, $extra_add_headers_set = false ) {
308
+ $rules = array();
309
+
310
+ $expires = $this->c->get_boolean( "browsercache.$section.expires" );
311
+ $lifetime = $this->c->get_integer( "browsercache.$section.lifetime" );
312
+
313
+ if ( $expires ) {
314
+ $rules[] = "expires ${lifetime}s;";
315
+ }
316
+ if ( version_compare( Util_Environment::get_server_version(), '1.3.3', '>=' ) ) {
317
+ if ( $this->c->get_boolean( "browsercache.$section.etag" ) ) {
318
+ $rules[] = 'etag on;';
319
+ } else {
320
+ $rules[] = 'etag off;';
321
+ }
322
+ }
323
+ if ( $this->c->get_boolean( "browsercache.$section.last_modified" ) ) {
324
+ $rules[] = 'if_modified_since exact;';
325
+ } else {
326
+ $rules[] = 'if_modified_since off;';
327
+ }
328
+
329
+ $add_header_rules = array();
330
+ if ( $this->c->get_boolean( "browsercache.$section.cache.control" ) ) {
331
+ $cache_policy = $this->c->get_string( "browsercache.$section.cache.policy" );
332
+
333
+ switch ( $cache_policy ) {
334
+ case 'cache':
335
+ $add_header_rules[] = 'add_header Pragma "public";';
336
+ $add_header_rules[] = 'add_header Cache-Control "public";';
337
+ break;
338
+
339
+ case 'cache_public_maxage':
340
+ $add_header_rules[] = 'add_header Pragma "public";';
341
+
342
+ if ( $expires ) {
343
+ $add_header_rules[] = 'add_header Cache-Control "public";';
344
+ } else {
345
+ $add_header_rules[] = "add_header Cache-Control \"max-age=$lifetime, public\";";
346
+ }
347
+ break;
348
+
349
+ case 'cache_validation':
350
+ $add_header_rules[] = 'add_header Pragma "public";';
351
+ $add_header_rules[] = 'add_header Cache-Control "public, must-revalidate, proxy-revalidate";';
352
+ break;
353
+
354
+ case 'cache_noproxy':
355
+ $add_header_rules[] = 'add_header Pragma "public";';
356
+ $add_header_rules[] = 'add_header Cache-Control "private, must-revalidate";';
357
+ break;
358
+
359
+ case 'cache_maxage':
360
+ $add_header_rules[] = 'add_header Pragma "public";';
361
+
362
+ if ( $expires ) {
363
+ $add_header_rules[] = 'add_header Cache-Control "public, must-revalidate, proxy-revalidate";';
364
+ } else {
365
+ $add_header_rules[] = "add_header Cache-Control \"max-age=$lifetime, public, must-revalidate, proxy-revalidate\";";
366
+ }
367
+ break;
368
+
369
+ case 'no_cache':
370
+ $add_header_rules[] = 'add_header Pragma "no-cache";';
371
+ $add_header_rules[] = 'add_header Cache-Control "max-age=0, private, no-store, no-cache, must-revalidate";';
372
+ break;
373
+ }
374
+ }
375
+
376
+ if ( $this->c->get_boolean( "browsercache.$section.w3tc" ) ) {
377
+ $add_header_rules[] = 'add_header X-Powered-y "' .
378
+ Util_Environment::w3tc_header() . '";';
379
+ }
380
+
381
+ if ( !empty( $add_header_rules ) || $extra_add_headers_set ) {
382
+ $add_header_rules = array_merge( $add_header_rules,
383
+ $this->security_rules() );
384
+ }
385
+
386
+ return array( 'add_header' => $add_header_rules, 'other' => $rules );
387
+ }
388
+ }
Cdn_Environment.php CHANGED
@@ -5,6 +5,11 @@ namespace W3TC;
5
  * class Cdn_Environment
6
  */
7
  class Cdn_Environment {
 
 
 
 
 
8
 
9
  /**
10
  * Fixes environment in each wp-admin request
@@ -189,34 +194,34 @@ class Cdn_Environment {
189
  $charset_collate .= " COLLATE $wpdb->collate";
190
 
191
  $sql = "CREATE TABLE IF NOT EXISTS `$tablename_queue` (
192
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
193
- `local_path` varchar(500) NOT NULL DEFAULT '',
194
- `remote_path` varchar(500) NOT NULL DEFAULT '',
195
- `command` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 - Upload, 2 - Delete, 3 - Purge',
196
- `last_error` varchar(150) NOT NULL DEFAULT '',
197
- `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
198
- PRIMARY KEY (`id`),
199
- KEY `date` (`date`)
200
- ) $charset_collate;";
201
 
202
  $wpdb->query( $sql );
203
  if ( !$wpdb->result )
204
  throw new Util_Environment_Exception( 'Can\'t create table ' .
205
  $tablename_queue );
206
 
207
- $sql = "
208
- CREATE TABLE IF NOT EXISTS `$tablename_map` (
209
- -- Relative file path.
210
- -- For reference, not actually used for finding files.
211
- path TEXT NOT NULL,
212
- -- MD5 hash of remote path, used for finding files.
213
- path_hash VARCHAR(32) CHARACTER SET ascii NOT NULL,
214
- type tinyint(1) NOT NULL DEFAULT '0',
215
- -- Google Drive: document identifier
216
- remote_id VARCHAR(200) CHARACTER SET ascii,
217
- PRIMARY KEY (path_hash),
218
- KEY `remote_id` (`remote_id`)
219
- ) $charset_collate";
220
 
221
  $wpdb->query( $sql );
222
  if ( !$wpdb->result )
@@ -237,15 +242,15 @@ class Cdn_Environment {
237
 
238
  $sql = sprintf( 'DROP TABLE IF EXISTS `%s%s`;', $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE );
239
  $sql .= "\n" . sprintf( "CREATE TABLE IF NOT EXISTS `%s%s` (
240
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
241
- `local_path` varchar(500) NOT NULL DEFAULT '',
242
- `remote_path` varchar(500) NOT NULL DEFAULT '',
243
- `command` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 - Upload, 2 - Delete, 3 - Purge',
244
- `last_error` varchar(150) NOT NULL DEFAULT '',
245
- `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
246
- PRIMARY KEY (`id`),
247
- KEY `date` (`date`)
248
- ) $charset_collate;", $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE );
249
 
250
  return $sql;
251
  }
@@ -323,44 +328,94 @@ class Cdn_Environment {
323
  * @return string
324
  */
325
  private function rules_generate( $config, $cdnftp = false ) {
 
 
 
 
 
 
 
 
 
326
  $rules = '';
327
- if ( Dispatcher::canonical_generated_by( $config, $cdnftp ) == 'cdn' )
328
- $rules .= Util_RuleSnippet::canonical( $cdnftp,
329
  $config->get_boolean( 'cdn.cors_header') );
 
330
 
331
  if ( $config->get_boolean( 'cdn.cors_header') ) {
332
  $rules .= $this->allow_origin( $cdnftp );
333
  }
334
 
335
- if ( strlen( $rules ) > 0 )
336
  $rules =
337
  W3TC_MARKER_BEGIN_CDN . "\n" .
338
  $rules .
339
  W3TC_MARKER_END_CDN . "\n";
 
340
 
341
  return $rules;
342
  }
343
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  /**
345
  * Returns allow-origin rules
346
  */
347
  private function allow_origin( $cdnftp = false ) {
348
- switch ( true ) {
349
- case Util_Environment::is_apache():
350
- case Util_Environment::is_litespeed():
351
- $r = "<IfModule mod_headers.c>\n";
352
- $r .= " Header set Access-Control-Allow-Origin \"*\"\n";
353
- $r .= "</IfModule>\n";
354
-
355
- if ( !$cdnftp )
356
- return $r;
357
- else
358
- return
359
- "<FilesMatch \"\.(ttf|ttc|otf|eot|woff|woff2|font.css)$\">\n" .
360
- $r .
361
- "</FilesMatch>\n";
 
 
 
 
 
 
 
362
  }
363
 
364
- return '';
365
  }
366
  }
5
  * class Cdn_Environment
6
  */
7
  class Cdn_Environment {
8
+ public function __construct() {
9
+ add_filter( 'w3tc_browsercache_rules_section_extensions',
10
+ array( $this, 'w3tc_browsercache_rules_section_extensions' ),
11
+ 10, 3 );
12
+ }
13
 
14
  /**
15
  * Fixes environment in each wp-admin request
194
  $charset_collate .= " COLLATE $wpdb->collate";
195
 
196
  $sql = "CREATE TABLE IF NOT EXISTS `$tablename_queue` (
197
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
198
+ `local_path` varchar(500) NOT NULL DEFAULT '',
199
+ `remote_path` varchar(500) NOT NULL DEFAULT '',
200
+ `command` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 - Upload, 2 - Delete, 3 - Purge',
201
+ `last_error` varchar(150) NOT NULL DEFAULT '',
202
+ `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
203
+ PRIMARY KEY (`id`),
204
+ KEY `date` (`date`)
205
+ ) $charset_collate;";
206
 
207
  $wpdb->query( $sql );
208
  if ( !$wpdb->result )
209
  throw new Util_Environment_Exception( 'Can\'t create table ' .
210
  $tablename_queue );
211
 
212
+ $sql = "
213
+ CREATE TABLE IF NOT EXISTS `$tablename_map` (
214
+ -- Relative file path.
215
+ -- For reference, not actually used for finding files.
216
+ path TEXT NOT NULL,
217
+ -- MD5 hash of remote path, used for finding files.
218
+ path_hash VARCHAR(32) CHARACTER SET ascii NOT NULL,
219
+ type tinyint(1) NOT NULL DEFAULT '0',
220
+ -- Google Drive: document identifier
221
+ remote_id VARCHAR(200) CHARACTER SET ascii,
222
+ PRIMARY KEY (path_hash),
223
+ KEY `remote_id` (`remote_id`)
224
+ ) $charset_collate";
225
 
226
  $wpdb->query( $sql );
227
  if ( !$wpdb->result )
242
 
243
  $sql = sprintf( 'DROP TABLE IF EXISTS `%s%s`;', $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE );
244
  $sql .= "\n" . sprintf( "CREATE TABLE IF NOT EXISTS `%s%s` (
245
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
246
+ `local_path` varchar(500) NOT NULL DEFAULT '',
247
+ `remote_path` varchar(500) NOT NULL DEFAULT '',
248
+ `command` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 - Upload, 2 - Delete, 3 - Purge',
249
+ `last_error` varchar(150) NOT NULL DEFAULT '',
250
+ `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
251
+ PRIMARY KEY (`id`),
252
+ KEY `date` (`date`)
253
+ ) $charset_collate;", $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE );
254
 
255
  return $sql;
256
  }
328
  * @return string
329
  */
330
  private function rules_generate( $config, $cdnftp = false ) {
331
+ if ( Util_Environment::is_nginx() ) {
332
+ $o = new Cdn_Environment_Nginx( $config );
333
+ return $o->generate( $cdnftp );
334
+ } else {
335
+ return $this->rules_generate_apache( $config, $cdnftp );
336
+ }
337
+ }
338
+
339
+ private function rules_generate_apache( $config, $cdnftp ) {
340
  $rules = '';
341
+ if ( $config->get_boolean( 'cdn.canonical_header' ) ) {
342
+ $rules .= $this->canonical( $cdnftp,
343
  $config->get_boolean( 'cdn.cors_header') );
344
+ }
345
 
346
  if ( $config->get_boolean( 'cdn.cors_header') ) {
347
  $rules .= $this->allow_origin( $cdnftp );
348
  }
349
 
350
+ if ( strlen( $rules ) > 0 ) {
351
  $rules =
352
  W3TC_MARKER_BEGIN_CDN . "\n" .
353
  $rules .
354
  W3TC_MARKER_END_CDN . "\n";
355
+ }
356
 
357
  return $rules;
358
  }
359
 
360
+
361
+
362
+ private function canonical( $cdnftp = false, $cors_header ) {
363
+ $rules = '';
364
+
365
+ $mime_types = include W3TC_INC_DIR . '/mime/other.php';
366
+ $extensions = array_keys( $mime_types );
367
+
368
+ $extensions_lowercase = array_map( 'strtolower', $extensions );
369
+ $extensions_uppercase = array_map( 'strtoupper', $extensions );
370
+ $rules .= "<FilesMatch \"\\.(" . implode( '|',
371
+ array_merge( $extensions_lowercase, $extensions_uppercase ) ) . ")$\">\n";
372
+
373
+ $host = ( $cdnftp ? Util_Environment::home_url_host() : '%{HTTP_HOST}' );
374
+ $rules .= " <IfModule mod_rewrite.c>\n";
375
+ $rules .= " RewriteEngine On\n";
376
+ $rules .= " RewriteCond %{HTTPS} !=on\n";
377
+ $rules .= " RewriteRule .* - [E=CANONICAL:http://$host%{REQUEST_URI},NE]\n";
378
+ $rules .= " RewriteCond %{HTTPS} =on\n";
379
+ $rules .= " RewriteRule .* - [E=CANONICAL:https://$host%{REQUEST_URI},NE]\n";
380
+ $rules .= " </IfModule>\n";
381
+ $rules .= " <IfModule mod_headers.c>\n";
382
+ $rules .= ' Header set Link "<%{CANONICAL}e>; rel=\"canonical\""' . "\n";
383
+ $rules .= " </IfModule>\n";
384
+
385
+ $rules .= "</FilesMatch>\n";
386
+
387
+ return $rules;
388
+ }
389
+
390
+
391
+
392
  /**
393
  * Returns allow-origin rules
394
  */
395
  private function allow_origin( $cdnftp = false ) {
396
+ $r = "<IfModule mod_headers.c>\n";
397
+ $r .= " Header set Access-Control-Allow-Origin \"*\"\n";
398
+ $r .= "</IfModule>\n";
399
+
400
+ if ( !$cdnftp )
401
+ return $r;
402
+ else
403
+ return
404
+ "<FilesMatch \"\.(ttf|ttc|otf|eot|woff|woff2|font.css)$\">\n" .
405
+ $r .
406
+ "</FilesMatch>\n";
407
+ }
408
+
409
+
410
+
411
+ public function w3tc_browsercache_rules_section_extensions(
412
+ $extensions, $config, $section ) {
413
+ if ( Util_Environment::is_nginx() ) {
414
+ $o = new Cdn_Environment_Nginx( $config );
415
+ $extensions = $o->w3tc_browsercache_rules_section_extensions(
416
+ $extensions, $section );
417
  }
418
 
419
+ return $extensions;
420
  }
421
  }
Cdn_Environment_Nginx.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * CDN rules generation for Nginx
6
+ */
7
+ class Cdn_Environment_Nginx {
8
+ private $c;
9
+
10
+
11
+
12
+ public function __construct( $config ) {
13
+ $this->c = $config;
14
+ }
15
+
16
+
17
+
18
+ public function generate( $cdnftp ) {
19
+ $rules = '';
20
+ $rule = $this->generate_canonical( $cdnftp );
21
+ if ( !empty( $rule ) ) {
22
+ $rules = $rule . "\n";
23
+ }
24
+
25
+ if ( $this->c->get_boolean( 'cdn.cors_header') ) {
26
+ $rules_a = Dispatcher::nginx_rules_for_browsercache_section(
27
+ $this->c, 'other', true );
28
+ $rules_a[] = 'add_header Access-Control-Allow-Origin "*";';
29
+
30
+ $rules .=
31
+ "location ~ \\.(ttf|ttc|otf|eot|woff|woff2|font.css)\$ {\n" .
32
+ ' ' . implode( "\n ", $rules_a ) . "\n" .
33
+ "}\n";
34
+ }
35
+
36
+ if ( strlen( $rules ) > 0 ) {
37
+ $rules =
38
+ W3TC_MARKER_BEGIN_CDN . "\n" .
39
+ $rules .
40
+ W3TC_MARKER_END_CDN . "\n";
41
+ }
42
+
43
+ return $rules;
44
+ }
45
+
46
+
47
+
48
+ public function generate_canonical( $cdnftp = false ) {
49
+ if ( !$this->c->get_boolean( 'cdn.canonical_header' ) ) {
50
+ return null;
51
+ }
52
+
53
+ $home = ( $cdnftp ? Util_Environment::home_url_host() : '$host' );
54
+
55
+ return 'add_header Link "<$scheme://' . $home .
56
+ '$request_uri>; rel=\"canonical\"";';
57
+ }
58
+
59
+
60
+
61
+ public function w3tc_browsercache_rules_section_extensions(
62
+ $extensions, $section ) {
63
+ // CDN adds own rules for those extensions
64
+ unset( $extensions['ttf|ttc'] );
65
+ unset( $extensions['otf'] );
66
+ unset( $extensions['eot'] );
67
+ unset( $extensions['woff'] );
68
+ unset( $extensions['woff2'] );
69
+
70
+ return $extensions;
71
+ }
72
+ }
Cdnfsd_CacheFlush.php CHANGED
@@ -60,6 +60,12 @@ class Cdnfsd_CacheFlush {
60
  }
61
  }
62
 
 
 
 
 
 
 
63
  $full_urls = array();
64
  $post = null;
65
  $terms = array();
60
  }
61
  }
62
 
63
+ global $wp_rewrite; // required by many Util_PageUrls methods
64
+ if ( empty( $wp_rewrite ) ) {
65
+ error_log('Post was modified before wp_rewrite initialization. Cant flush cache.');
66
+ return false;
67
+ }
68
+
69
  $full_urls = array();
70
  $post = null;
71
  $terms = array();
Config.php CHANGED
@@ -276,16 +276,31 @@ class Config {
276
  public function set_extension_active_frontend( $extension,
277
  $is_active_frontend ) {
278
  $a = $this->get_array( 'extensions.active_frontend' );
279
- if ( !$is_active_frontend )
280
  unset( $a[$extension] );
281
- else
282
  $a[$extension] = '*';
 
283
 
284
  $this->set( 'extensions.active_frontend', $a );
285
  }
286
 
287
 
288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  /**
290
  * Sets config value.
291
  * Method to override
276
  public function set_extension_active_frontend( $extension,
277
  $is_active_frontend ) {
278
  $a = $this->get_array( 'extensions.active_frontend' );
279
+ if ( !$is_active_frontend ) {
280
  unset( $a[$extension] );
281
+ } else {
282
  $a[$extension] = '*';
283
+ }
284
 
285
  $this->set( 'extensions.active_frontend', $a );
286
  }
287
 
288
 
289
 
290
+ public function set_extension_active_dropin( $extension,
291
+ $is_active_dropin ) {
292
+ $a = $this->get_array( 'extensions.active_dropin' );
293
+ if ( !$is_active_dropin ) {
294
+ unset( $a[$extension] );
295
+ } else {
296
+ $a[$extension] = '*';
297
+ }
298
+
299
+ $this->set( 'extensions.active_dropin', $a );
300
+ }
301
+
302
+
303
+
304
  /**
305
  * Sets config value.
306
  * Method to override
ConfigKeys.php CHANGED
@@ -2267,10 +2267,6 @@ $keys = array(
2267
  ),
2268
 
2269
 
2270
- 'common.support' => array(
2271
- 'type' => 'string',
2272
- 'default' => ''
2273
- ),
2274
  'common.track_usage' => array(
2275
  'type' => 'boolean',
2276
  'default' => false
@@ -2375,6 +2371,10 @@ $keys = array(
2375
  'type' => 'array',
2376
  'default' => array()
2377
  ),
 
 
 
 
2378
  'plugin.license_key' => array(
2379
  'type' => 'string',
2380
  'default' => '',
2267
  ),
2268
 
2269
 
 
 
 
 
2270
  'common.track_usage' => array(
2271
  'type' => 'boolean',
2272
  'default' => false
2371
  'type' => 'array',
2372
  'default' => array()
2373
  ),
2374
+ 'extensions.active_dropin' => array(
2375
+ 'type' => 'array',
2376
+ 'default' => array()
2377
+ ),
2378
  'plugin.license_key' => array(
2379
  'type' => 'string',
2380
  'default' => '',
Dispatcher.php CHANGED
@@ -20,10 +20,14 @@ class Dispatcher {
20
  return $v;
21
  }
22
 
 
 
23
  static public function config() {
24
  return self::component( 'Config' );
25
  }
26
 
 
 
27
  static public function config_master() {
28
  static $config_master = null;
29
 
@@ -34,6 +38,8 @@ class Dispatcher {
34
  return $config_master;
35
  }
36
 
 
 
37
  static public function config_state() {
38
  if ( Util_Environment::blog_id() <= 0 )
39
  return self::config_state_master();
@@ -46,6 +52,8 @@ class Dispatcher {
46
  return $config_state;
47
  }
48
 
 
 
49
  static public function config_state_master() {
50
  static $config_state = null;
51
 
@@ -55,6 +63,8 @@ class Dispatcher {
55
  return $config_state;
56
  }
57
 
 
 
58
  static public function config_state_note() {
59
  static $o = null;
60
 
@@ -65,6 +75,8 @@ class Dispatcher {
65
  return $o;
66
  }
67
 
 
 
68
  /**
69
  * Checks if specific local url is uploaded to CDN
70
  *
@@ -84,6 +96,8 @@ class Dispatcher {
84
  return false;
85
  }
86
 
 
 
87
  /**
88
  * Creates file for CDN upload.
89
  * Needed because minify can handle urls of non-existing files but CDN needs
@@ -113,6 +127,8 @@ class Dispatcher {
113
  }
114
  }
115
 
 
 
116
  /**
117
  * Called on successful file upload to CDN
118
  *
@@ -135,26 +151,38 @@ class Dispatcher {
135
  }
136
  }
137
 
 
 
138
  /**
139
- * Generates canonical header code for nginx if browsercache plugin has
140
- * to generate it
141
- *
142
- * @param Config $config
143
- * @param boolean $cdnftp if CDN FTP is used
144
- * @param string $section
145
- * @return string
146
  */
147
- static public function on_browsercache_rules_generation_for_section( $config, $cdnftp,
148
- $section, $add_header_rules ) {
149
- if ( $section != 'other' )
150
- return '';
151
- if ( self::canonical_generated_by( $config, $cdnftp ) != 'browsercache' )
152
- return '';
153
-
154
- return Util_RuleSnippet::canonical_without_location( $cdnftp,
155
- $add_header_rules, $config->get_boolean( 'cdn.cors_header') );
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  }
157
 
 
 
158
  /**
159
  * Called when minify going to process request of some minified file
160
  */
@@ -169,78 +197,7 @@ class Dispatcher {
169
  return $file;
170
  }
171
 
172
- /**
173
- * Checks whether canonical should be generated or not by browsercache plugin
174
- *
175
- * @param Config $config
176
- * @param boolean $cdnftp
177
- * @return string|null
178
- */
179
- static public function canonical_generated_by( $config, $cdnftp = false ) {
180
- if ( !self::_should_canonical_be_generated( $config, $cdnftp ) )
181
- return null;
182
-
183
- if ( Util_Environment::is_nginx() ) {
184
- // in nginx - browsercache generates canonical if its enabled,
185
- // since it does not allow multiple location tags
186
- if ( $config->get_boolean( 'browsercache.enabled' ) )
187
- return 'browsercache';
188
- }
189
-
190
- if ( $config->get_boolean( 'cdn.enabled' ) )
191
- return 'cdn';
192
-
193
- return null;
194
- }
195
-
196
- /**
197
- * Basic check if canonical generation should be done
198
- *
199
- * @param Config $config
200
- * @param boolean $cdnftp
201
- * @return bool
202
- */
203
- static private function _should_canonical_be_generated( $config, $cdnftp ) {
204
- if ( !$config->get_boolean( 'cdn.canonical_header' ) )
205
- return false;
206
-
207
- $cdncommon = Dispatcher::component( 'Cdn_Core' );
208
-
209
- $cdn = $cdncommon->get_cdn();
210
- return ( ( $config->get_string( 'cdn.engine' ) != 'ftp' || $cdnftp ) &&
211
- $cdn->headers_support() == W3TC_CDN_HEADER_MIRRORING );
212
- }
213
-
214
- /**
215
- * If BrowserCache should generate rules specific for CDN. Used with CDN FTP
216
- *
217
- * @param Config $config
218
- * @return boolean;
219
- */
220
- static public function should_browsercache_generate_rules_for_cdn( $config ) {
221
- if ( $config->get_boolean( 'cdn.enabled' ) &&
222
- $config->get_string( 'cdn.engine' ) == 'ftp' ) {
223
- $cdncommon = Dispatcher::component( 'Cdn_Core' );
224
- $cdn = $cdncommon->get_cdn();
225
- $domain = $cdn->get_domain();
226
-
227
- if ( $domain )
228
- return true;
229
- }
230
- return false;
231
- }
232
 
233
- /**
234
- * Returns the domain used with the cdn.
235
- *
236
- * @param string
237
- * @return string
238
- */
239
- static public function get_cdn_domain( $path = '' ) {
240
- $cdncommon = Dispatcher::component( 'Cdn_Core' );
241
- $cdn = $cdncommon->get_cdn();
242
- return $cdn->get_domain( $path );
243
- }
244
 
245
  /**
246
  * Usage statistics uses one of other module's cache
@@ -281,6 +238,8 @@ class Dispatcher {
281
  return $cache;
282
  }
283
 
 
 
284
  /**
285
  * In a case request processing has been finished before WP initialized,
286
  * but usage statistics metrics should be counted.
20
  return $v;
21
  }
22
 
23
+
24
+
25
  static public function config() {
26
  return self::component( 'Config' );
27
  }
28
 
29
+
30
+
31
  static public function config_master() {
32
  static $config_master = null;
33
 
38
  return $config_master;
39
  }
40
 
41
+
42
+
43
  static public function config_state() {
44
  if ( Util_Environment::blog_id() <= 0 )
45
  return self::config_state_master();
52
  return $config_state;
53
  }
54
 
55
+
56
+
57
  static public function config_state_master() {
58
  static $config_state = null;
59
 
63
  return $config_state;
64
  }
65
 
66
+
67
+
68
  static public function config_state_note() {
69
  static $o = null;
70
 
75
  return $o;
76
  }
77
 
78
+
79
+
80
  /**
81
  * Checks if specific local url is uploaded to CDN
82
  *
96
  return false;
97
  }
98
 
99
+
100
+
101
  /**
102
  * Creates file for CDN upload.
103
  * Needed because minify can handle urls of non-existing files but CDN needs
127
  }
128
  }
129
 
130
+
131
+
132
  /**
133
  * Called on successful file upload to CDN
134
  *
151
  }
152
  }
153
 
154
+
155
+
156
  /**
157
+ * Returns common rules used by nginx for files belonging to browsercache
158
+ * section
 
 
 
 
 
159
  */
160
+ static public function nginx_rules_for_browsercache_section( $config, $section,
161
+ $extra_add_headers_set = false ) {
162
+ $rules = array(
163
+ 'other' => array(),
164
+ 'add_header' => array()
165
+ );
166
+ if ( $config->get_boolean( 'browsercache.enabled' ) ) {
167
+ $o = new BrowserCache_Environment_Nginx( $config );
168
+ $rules = $o->section_rules( $section, $extra_add_headers_set );
169
+ }
170
+
171
+ if ( !empty( $rules['add_header'] ) &&
172
+ $config->get_boolean( 'cdn.enabled' ) ) {
173
+ $o = new Cdn_Environment_Nginx( $config );
174
+ $rule = $o->generate_canonical();
175
+
176
+ if ( !empty( $rule ) ) {
177
+ $rules['add_header'][] = $rule;
178
+ }
179
+ }
180
+
181
+ return array_merge( $rules['other'], $rules['add_header'] );
182
  }
183
 
184
+
185
+
186
  /**
187
  * Called when minify going to process request of some minified file
188
  */
197
  return $file;
198
  }
199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
  /**
203
  * Usage statistics uses one of other module's cache
238
  return $cache;
239
  }
240
 
241
+
242
+
243
  /**
244
  * In a case request processing has been finished before WP initialized,
245
  * but usage statistics metrics should be counted.
Extension_Amp_Page_View.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+
8
+ ?>
9
+ <form action="admin.php?page=w3tc_extensions&amp;extension=amp&amp;action=view" method="post">
10
+ <div class="metabox-holder">
11
+ <?php Util_Ui::postbox_header( __( 'Configuration', 'w3-total-cache' ), '', '' ) ?>
12
+ <table class="form-table">
13
+ <?php
14
+ Util_Ui::config_item( array(
15
+ 'key' => array( 'amp', 'url_type' ),
16
+ 'label' => __( 'AMP URL Type:', 'w3-total-cache' ),
17
+ 'control' => 'radiogroup',
18
+ 'radiogroup_values' => array(
19
+ 'tag' => 'tag',
20
+ 'querystring' => 'query string'
21
+ ),
22
+ 'description' =>
23
+ 'If AMP page URLs are tag based (/my-page/amp/) or query string based (/my-page?amp)'
24
+ )
25
+ );
26
+ Util_Ui::config_item( array(
27
+ 'key' => array( 'amp', 'url_postfix' ),
28
+ 'label' => __( 'AMP URL Postfix:', 'w3-total-cache' ),
29
+ 'control' => 'textbox',
30
+ 'description' => 'Postfix used'
31
+ )
32
+ );
33
+ ?>
34
+ </table>
35
+ <?php Util_Ui::button_config_save( 'extension_amp_configuration' ); ?>
36
+ <?php Util_Ui::postbox_footer(); ?>
37
+ </div>
38
+ </form>
Extension_Amp_Plugin.php CHANGED
@@ -6,23 +6,55 @@ class Extension_Amp_Plugin {
6
 
7
 
8
 
9
- public function run() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  add_filter( 'w3tc_minify_js_enable',
11
- array( $this, 'w3tc_minify_jscss_enable' ) );
12
  add_filter( 'w3tc_minify_css_enable',
13
- array( $this, 'w3tc_minify_jscss_enable' ) );
14
  add_filter( 'w3tc_lazyload_can_process',
15
- array( $this, 'w3tc_lazyload_can_process' ) );
16
  add_filter( 'w3tc_footer_comment',
17
- array( $this, 'w3tc_footer_comment' ) );
18
  add_filter( 'w3tc_newrelic_should_disable_auto_rum',
19
- array( $this, 'w3tc_newrelic_should_disable_auto_rum' ) );
20
  add_filter( 'pgcache_flush_post_queued_urls',
21
- array( $this, 'x_flush_post_queued_urls' ) );
22
  add_filter( 'varnish_flush_post_queued_urls',
23
- array( $this, 'x_flush_post_queued_urls' ) );
24
  add_filter( 'w3tc_pagecache_set',
25
- array( $this, 'w3tc_pagecache_set' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
 
28
 
@@ -78,9 +110,17 @@ class Extension_Amp_Plugin {
78
 
79
  public function x_flush_post_queued_urls( $queued_urls ) {
80
  $amp_urls = array();
 
 
81
 
82
- foreach ( $queued_urls as $url ) {
83
- $amp_urls[] = trailingslashit( $url ) . 'amp';
 
 
 
 
 
 
84
  }
85
 
86
  $queued_urls = array_merge( $queued_urls, $amp_urls );
@@ -138,14 +178,114 @@ class Extension_Amp_Plugin {
138
 
139
  return $header;
140
  }
141
- }
142
 
143
 
144
 
145
- $p = new Extension_Amp_Plugin();
146
- $p->run();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- if ( is_admin() ) {
149
- $p = new Extension_Amp_Plugin_Admin();
150
- $p->run();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
 
 
 
 
 
 
 
 
 
6
 
7
 
8
 
9
+ static public function wp_loaded() {
10
+ add_action( 'w3tc_extension_load', array(
11
+ '\W3TC\Extension_Amp_Plugin',
12
+ 'w3tc_extension_load'
13
+ ) );
14
+ add_action( 'w3tc_extension_load_admin', array(
15
+ '\W3TC\Extension_Amp_Plugin_Admin',
16
+ 'w3tc_extension_load_admin'
17
+ ) );
18
+ }
19
+
20
+
21
+
22
+ static public function w3tc_extension_load() {
23
+ $o = new Extension_Amp_Plugin();
24
+
25
  add_filter( 'w3tc_minify_js_enable',
26
+ array( $o, 'w3tc_minify_jscss_enable' ) );
27
  add_filter( 'w3tc_minify_css_enable',
28
+ array( $o, 'w3tc_minify_jscss_enable' ) );
29
  add_filter( 'w3tc_lazyload_can_process',
30
+ array( $o, 'w3tc_lazyload_can_process' ) );
31
  add_filter( 'w3tc_footer_comment',
32
+ array( $o, 'w3tc_footer_comment' ) );
33
  add_filter( 'w3tc_newrelic_should_disable_auto_rum',
34
+ array( $o, 'w3tc_newrelic_should_disable_auto_rum' ) );
35
  add_filter( 'pgcache_flush_post_queued_urls',
36
+ array( $o, 'x_flush_post_queued_urls' ) );
37
  add_filter( 'varnish_flush_post_queued_urls',
38
+ array( $o, 'x_flush_post_queued_urls' ) );
39
  add_filter( 'w3tc_pagecache_set',
40
+ array( $o, 'w3tc_pagecache_set' ) );
41
+ add_filter( 'w3tc_config_default_values',
42
+ array( $o, 'w3tc_config_default_values' ) );
43
+
44
+ // rules generation
45
+ add_filter( 'w3tc_pagecache_rules_apache_accept_qs',
46
+ array( $o, 'w3tc_pagecache_rules_x_accept_qs' ) );
47
+ add_filter( 'w3tc_pagecache_rules_apache_accept_qs_rules',
48
+ array( $o, 'w3tc_pagecache_rules_apache_accept_qs_rules' ), 10, 2 );
49
+ add_filter( 'w3tc_pagecache_rules_apache_uri_prefix',
50
+ array( $o, 'w3tc_pagecache_rules_apache_uri_prefix' ) );
51
+
52
+ add_filter( 'w3tc_pagecache_rules_nginx_accept_qs',
53
+ array( $o, 'w3tc_pagecache_rules_x_accept_qs' ) );
54
+ add_filter( 'w3tc_pagecache_rules_nginx_accept_qs_rules',
55
+ array( $o, 'w3tc_pagecache_rules_nginx_accept_qs_rules' ), 10, 2 );
56
+ add_filter( 'w3tc_pagecache_rules_nginx_uri_prefix',
57
+ array( $o, 'w3tc_pagecache_rules_nginx_uri_prefix' ) );
58
  }
59
 
60
 
110
 
111
  public function x_flush_post_queued_urls( $queued_urls ) {
112
  $amp_urls = array();
113
+ $c = Dispatcher::config();
114
+ $url_postfix = $c->get_string( array( 'amp', 'url_postfix' ) );
115
 
116
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' ) {
117
+ foreach ( $queued_urls as $url ) {
118
+ $amp_urls[] = $url . '?' . $url_postfix;
119
+ }
120
+ } else {
121
+ foreach ( $queued_urls as $url ) {
122
+ $amp_urls[] = trailingslashit( $url ) . $url_postfix;
123
+ }
124
  }
125
 
126
  $queued_urls = array_merge( $queued_urls, $amp_urls );
178
 
179
  return $header;
180
  }
 
181
 
182
 
183
 
184
+ public function w3tc_config_default_values( $default_values ) {
185
+ $default_values['amp'] = array(
186
+ 'url_type' => 'tag',
187
+ 'url_postfix' => 'amp'
188
+ );
189
+
190
+ return $default_values;
191
+ }
192
+
193
+
194
+
195
+ static public function pagecache_extract_accept_qs( $query_strings ) {
196
+ $c = Dispatcher::config();
197
+
198
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' ) {
199
+ $query_strings[] = $c->get_string( array( 'amp', 'url_postfix' ) );
200
+ }
201
+
202
+ return $query_strings;
203
+ }
204
+
205
+
206
+
207
+ static public function pagecache_page_key( $page_key, $url, $page_key_extension ) {
208
+ $c = Dispatcher::config();
209
+
210
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' ) {
211
+ $url_postfix = $c->get_string( array( 'amp', 'url_postfix' ) );
212
+ if ( preg_match( "~(\\?|&)$url_postfix(&|$)~", $url ) ) {
213
+ $page_key[1] .= '_amp';
214
+ }
215
+ }
216
+
217
+ return $page_key;
218
+ }
219
+
220
+
221
+
222
+ public function w3tc_pagecache_rules_x_accept_qs( $query_strings ) {
223
+ $c = Dispatcher::config();
224
+
225
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' ) {
226
+ $query_strings[] = $c->get_string( array( 'amp', 'url_postfix' ) );
227
+ }
228
+
229
+ return $query_strings;
230
+ }
231
+
232
+
233
+
234
+ public function w3tc_pagecache_rules_apache_accept_qs_rules( $query_rules, $query ) {
235
+ $c = Dispatcher::config();
236
+
237
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' &&
238
+ $query == $c->get_string( array( 'amp', 'url_postfix' ) ) ) {
239
+ $query_rules[1] = str_replace( '[E=', '[E=W3TC_AMP:_amp,E=', $query_rules[1] );
240
+ }
241
+
242
+ return $query_rules;
243
+ }
244
+
245
+
246
+
247
+ public function w3tc_pagecache_rules_apache_uri_prefix( $uri_prefix ) {
248
+ $c = Dispatcher::config();
249
+
250
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' ) {
251
+ $uri_prefix .= '%{ENV:W3TC_AMP}';
252
+ }
253
+
254
+ return $uri_prefix;
255
+ }
256
+
257
 
258
+
259
+ public function w3tc_pagecache_rules_nginx_accept_qs_rules( $query_rules, $query ) {
260
+ $c = Dispatcher::config();
261
+
262
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' &&
263
+ $query == $c->get_string( array( 'amp', 'url_postfix' ) ) ) {
264
+ array_splice( $query_rules, 1, 0, ' set $w3tc_amp "_amp";' );
265
+ array_unshift( $query_rules, 'set $w3tc_amp "";' );
266
+ }
267
+
268
+ return $query_rules;
269
+ }
270
+
271
+
272
+
273
+ public function w3tc_pagecache_rules_nginx_uri_prefix( $uri_prefix ) {
274
+ $c = Dispatcher::config();
275
+
276
+ if ( $c->get_string( array( 'amp', 'url_type' ) ) == 'querystring' ) {
277
+ $uri_prefix .= '$w3tc_amp';
278
+ }
279
+
280
+ return $uri_prefix;
281
+ }
282
  }
283
+
284
+
285
+
286
+ w3tc_add_action( 'pagecache_extract_accept_qs',
287
+ array( '\W3TC\Extension_Amp_Plugin', 'pagecache_extract_accept_qs' ) );
288
+ w3tc_add_action( 'pagecache_page_key',
289
+ array( '\W3TC\Extension_Amp_Plugin', 'pagecache_page_key' ) );
290
+ w3tc_add_action( 'wp_loaded',
291
+ array( '\W3TC\Extension_Amp_Plugin', 'wp_loaded' ) );
Extension_Amp_Plugin_Admin.php CHANGED
@@ -2,9 +2,6 @@
2
  namespace W3TC;
3
 
4
  class Extension_Amp_Plugin_Admin {
5
- function run() {
6
- }
7
-
8
  static public function w3tc_extensions( $extensions, $config ) {
9
  $enabled = true;
10
  $disabled_message = '';
@@ -19,7 +16,7 @@ class Extension_Amp_Plugin_Admin {
19
  'author_uri' => 'https://www.w3-edge.com/',
20
  'extension_uri' => 'https://www.w3-edge.com/',
21
  'extension_id' => 'amp',
22
- 'settings_exists' => false,
23
  'version' => '0.1',
24
  'enabled' => $enabled,
25
  'disabled_message' => $disabled_message,
@@ -29,4 +26,31 @@ class Extension_Amp_Plugin_Admin {
29
 
30
  return $extensions;
31
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
2
  namespace W3TC;
3
 
4
  class Extension_Amp_Plugin_Admin {
 
 
 
5
  static public function w3tc_extensions( $extensions, $config ) {
6
  $enabled = true;
7
  $disabled_message = '';
16
  'author_uri' => 'https://www.w3-edge.com/',
17
  'extension_uri' => 'https://www.w3-edge.com/',
18
  'extension_id' => 'amp',
19
+ 'settings_exists' => true,
20
  'version' => '0.1',
21
  'enabled' => $enabled,
22
  'disabled_message' => $disabled_message,
26
 
27
  return $extensions;
28
  }
29
+
30
+
31
+
32
+ static public function w3tc_extension_load_admin() {
33
+ $o = new Extension_Amp_Plugin_Admin();
34
+
35
+ add_action( 'w3tc_extension_page_amp',
36
+ array( $o, 'w3tc_extension_page_amp' ) );
37
+ add_action( 'w3tc_config_save',
38
+ array( $o, 'w3tc_config_save' ), 10, 1 );
39
+ }
40
+
41
+
42
+
43
+ public function w3tc_extension_page_amp() {
44
+ include W3TC_DIR . '/Extension_Amp_Page_View.php';
45
+ }
46
+
47
+
48
+
49
+ public function w3tc_config_save( $config ) {
50
+ // frontend activity
51
+ $url_type = $config->get_string( array( 'amp', 'url_type' ) );
52
+ $is_active_dropin = ($url_type == 'querystring');
53
+
54
+ $config->set_extension_active_dropin( 'amp', $is_active_dropin );
55
+ }
56
  }
Generic_AdminActions_Config.php CHANGED
@@ -157,11 +157,9 @@ class Generic_AdminActions_Config {
157
  * @return void
158
  */
159
  function w3tc_config_save_support_us() {
160
- $support = Util_Request::get_string( 'support' );
161
  $tweeted = Util_Request::get_boolean( 'tweeted' );
162
  $signmeup = Util_Request::get_boolean( 'signmeup' );
163
  $accept_terms = Util_Request::get_boolean( 'accept_terms' );
164
- $this->_config->set( 'common.support', $support );
165
  $this->_config->set( 'common.tweeted', $tweeted );
166
 
167
  $state_master = Dispatcher::config_state_master();
@@ -183,8 +181,6 @@ class Generic_AdminActions_Config {
183
  }
184
  $this->_config->save();
185
 
186
- Generic_AdminLinks::link_update( $this->_config );
187
-
188
  Util_Admin::redirect( array(
189
  'w3tc_note' => 'config_save'
190
  ) );
157
  * @return void
158
  */
159
  function w3tc_config_save_support_us() {
 
160
  $tweeted = Util_Request::get_boolean( 'tweeted' );
161
  $signmeup = Util_Request::get_boolean( 'signmeup' );
162
  $accept_terms = Util_Request::get_boolean( 'accept_terms' );
 
163
  $this->_config->set( 'common.tweeted', $tweeted );
164
 
165
  $state_master = Dispatcher::config_state_master();
181
  }
182
  $this->_config->save();
183
 
 
 
184
  Util_Admin::redirect( array(
185
  'w3tc_note' => 'config_save'
186
  ) );
Generic_AdminLinks.php DELETED
@@ -1,55 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- /**
5
- * class Environment
6
- */
7
- class Generic_AdminLinks {
8
- /**
9
- * Update plugin link
10
- *
11
- * @return void
12
- */
13
- static public function link_update( $config ) {
14
- self::link_delete();
15
- self::link_insert( $config );
16
- }
17
-
18
- /**
19
- * Insert plugin link into Blogroll
20
- *
21
- * @return void
22
- */
23
- static private function link_insert( $config ) {
24
- $support = $config->get_string( 'common.support' );
25
- $matches = null;
26
- if ( $support != '' && preg_match( '~^link_category_(\d+)$~', $support, $matches ) ) {
27
- require_once ABSPATH . 'wp-admin/includes/bookmark.php';
28
-
29
- wp_insert_link( array(
30
- 'link_url' => W3TC_LINK_URL,
31
- 'link_name' => W3TC_LINK_NAME,
32
- 'link_category' => array(
33
- (int) $matches[1]
34
- ),
35
- 'link_rel' => 'nofollow'
36
- ) );
37
- }
38
- }
39
-
40
- /**
41
- * Deletes plugin link from Blogroll
42
- *
43
- * @return void
44
- */
45
- static public function link_delete() {
46
- require_once ABSPATH . 'wp-admin/includes/bookmark.php';
47
- $bookmarks = get_bookmarks();
48
- $link_id = 0;
49
- foreach ( $bookmarks as $bookmark ) {
50
- if ( $bookmark->link_url == W3TC_LINK_URL ) {
51
- wp_delete_link( $bookmark->link_id );
52
- }
53
- }
54
- }
55
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Generic_Plugin.php CHANGED
@@ -75,13 +75,6 @@ class Generic_Plugin {
75
  ), 0, 5 );
76
  }
77
 
78
- if ( $this->_config->get_string( 'common.support' ) == 'footer' ) {
79
- add_action( 'wp_footer', array(
80
- $this,
81
- 'footer'
82
- ) );
83
- }
84
-
85
  if ( $this->can_ob() ) {
86
  add_filter( 'wp_die_xml_handler', array( $this, 'wp_die_handler' ) );
87
  add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );
@@ -494,15 +487,6 @@ class Generic_Plugin {
494
  return $stylesheet;
495
  }
496
 
497
- /**
498
- * Footer plugin action
499
- *
500
- * @return void
501
- */
502
- function footer() {
503
- echo '<div style="text-align: center;"><a href="https://www.w3-edge.com/products/" rel="external">Optimization WordPress Plugins &amp; Solutions by W3 EDGE</a></div>';
504
- }
505
-
506
  /**
507
  * Output buffering callback
508
  *
@@ -517,7 +501,8 @@ class Generic_Plugin {
517
  return $buffer;
518
  }
519
 
520
- if ( $this->is_wp_die ) {
 
521
  // wp_die is dynamic output (usually fatal errors), dont process it
522
  } else {
523
  $buffer = apply_filters( 'w3tc_process_content', $buffer );
@@ -534,8 +519,7 @@ class Generic_Plugin {
534
 
535
  $strings = array();
536
 
537
- if ( $this->_config->get_string( 'common.support' ) == '' &&
538
- !$this->_config->get_boolean( 'common.tweeted' ) ) {
539
  $strings[] = 'Performance optimized by W3 Total Cache. Learn more: https://www.w3-edge.com/products/';
540
  $strings[] = '';
541
  }
75
  ), 0, 5 );
76
  }
77
 
 
 
 
 
 
 
 
78
  if ( $this->can_ob() ) {
79
  add_filter( 'wp_die_xml_handler', array( $this, 'wp_die_handler' ) );
80
  add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );
487
  return $stylesheet;
488
  }
489
 
 
 
 
 
 
 
 
 
 
490
  /**
491
  * Output buffering callback
492
  *
501
  return $buffer;
502
  }
503
 
504
+ if ( $this->is_wp_die &&
505
+ !apply_filters( 'w3tc_process_wp_die', false, $buffer ) ) {
506
  // wp_die is dynamic output (usually fatal errors), dont process it
507
  } else {
508
  $buffer = apply_filters( 'w3tc_process_content', $buffer );
519
 
520
  $strings = array();
521
 
522
+ if ( !$this->_config->get_boolean( 'common.tweeted' ) ) {
 
523
  $strings[] = 'Performance optimized by W3 Total Cache. Learn more: https://www.w3-edge.com/products/';
524
  $strings[] = '';
525
  }
Generic_Plugin_AdminNotifications.php CHANGED
@@ -60,7 +60,6 @@ class Generic_Plugin_AdminNotifications {
60
  ( time() - $day7 ) ) &&
61
  ( $state->get_integer( 'common.next_support_us_invitation' ) <
62
  time() ) &&
63
- $this->_config->get_string( 'common.support' ) == '' &&
64
  !$this->_config->get_boolean( 'common.tweeted' );
65
 
66
  if ( $support_reminder ) {
@@ -93,7 +92,6 @@ class Generic_Plugin_AdminNotifications {
93
 
94
 
95
  public function w3tc_ajax_generic_support_us() {
96
- $supports = $this->get_supports();
97
  $current_user = wp_get_current_user();
98
  wp_get_current_user();
99
  $email = $current_user->user_email;
@@ -102,25 +100,6 @@ class Generic_Plugin_AdminNotifications {
102
 
103
 
104
 
105
- private function get_supports() {
106
- $supports = array(
107
- 'footer' => 'page footer'
108
- );
109
-
110
- $link_categories = get_terms( 'link_category', array(
111
- 'hide_empty' => 0
112
- ) );
113
-
114
- foreach ( $link_categories as $link_category ) {
115
- $supports['link_category_' . $link_category->term_id] =
116
- strtolower( $link_category->name );
117
- }
118
-
119
- return $supports;
120
- }
121
-
122
-
123
-
124
  /**
125
  * Display the support us nag
126
  */
60
  ( time() - $day7 ) ) &&
61
  ( $state->get_integer( 'common.next_support_us_invitation' ) <
62
  time() ) &&
 
63
  !$this->_config->get_boolean( 'common.tweeted' );
64
 
65
  if ( $support_reminder ) {
92
 
93
 
94
  public function w3tc_ajax_generic_support_us() {
 
95
  $current_user = wp_get_current_user();
96
  wp_get_current_user();
97
  $email = $current_user->user_email;
100
 
101
 
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  /**
104
  * Display the support us nag
105
  */
Generic_Plugin_WidgetForum.php CHANGED
@@ -89,38 +89,17 @@ class Generic_Plugin_WidgetForum {
89
  $items = array();
90
  $items_count = $this->_config->get_integer( 'widget.latest.items' );
91
 
92
- if ( $wp_version >= 2.8 ) {
93
- include_once ABSPATH . WPINC . '/feed.php';
94
- $feed = fetch_feed( W3TC_FEED_URL );
95
-
96
- if ( !is_wp_error( $feed ) ) {
97
- $feed_items = $feed->get_items( 0, $items_count );
98
-
99
- foreach ( $feed_items as $feed_item ) {
100
- $items[] = array(
101
- 'link' => $feed_item->get_link(),
102
- 'title' => $feed_item->get_title(),
103
- 'description' => $feed_item->get_description()
104
- );
105
- }
106
- }
107
- } else {
108
- include_once ABSPATH . WPINC . '/rss.php';
109
- $rss = fetch_rss( W3TC_FEED_URL );
110
 
111
- if ( is_object( $rss ) ) {
112
- $items = array_slice( $rss->items, 0, $items_count );
113
- }
114
- }
115
 
116
- // Removes feedburner tracking images when site is https
117
- if ( Util_Environment::is_https() ) {
118
- $total = sizeof( $items );
119
- for ( $i = 0; $i < $total; $i++ ) {
120
- if ( isset( $items[$i]['description'] ) ) {
121
- $items[$i]['description'] = preg_replace( '/<img[^>]+src[^>]+W3TOTALCACHE[^>]+>/',
122
- '', $items[$i]['description'] );
123
- }
124
  }
125
  }
126
 
89
  $items = array();
90
  $items_count = $this->_config->get_integer( 'widget.latest.items' );
91
 
92
+ include_once ABSPATH . WPINC . '/feed.php';
93
+ $feed = fetch_feed( W3TC_FEED_URL );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
+ if ( !is_wp_error( $feed ) ) {
96
+ $feed_items = $feed->get_items( 0, $items_count );
 
 
97
 
98
+ foreach ( $feed_items as $feed_item ) {
99
+ $items[] = array(
100
+ 'link' => $feed_item->get_link(),
101
+ 'title' => htmlspecialchars_decode( $feed_item->get_title() )
102
+ );
 
 
 
103
  }
104
  }
105
 
Generic_Plugin_WidgetNews.php CHANGED
@@ -82,38 +82,17 @@ class Generic_Plugin_WidgetNews {
82
  $items = array();
83
  $items_count = $this->_config->get_integer( 'widget.latest_news.items' );
84
 
85
- if ( $wp_version >= 2.8 ) {
86
- include_once ABSPATH . WPINC . '/feed.php';
87
- $feed = fetch_feed( W3TC_NEWS_FEED_URL );
88
-
89
- if ( !is_wp_error( $feed ) ) {
90
- $feed_items = $feed->get_items( 0, $items_count );
91
-
92
- foreach ( $feed_items as $feed_item ) {
93
- $items[] = array(
94
- 'link' => $feed_item->get_link(),
95
- 'title' => $feed_item->get_title(),
96
- 'description' => $feed_item->get_description()
97
- );
98
- }
99
- }
100
- } else {
101
- include_once ABSPATH . WPINC . '/rss.php';
102
- $rss = fetch_rss( W3TC_NEWS_FEED_URL );
103
 
104
- if ( is_object( $rss ) ) {
105
- $items = array_slice( $rss->items, 0, $items_count );
106
- }
107
- }
108
 
109
- // Removes feedburner tracking images when site is https
110
- if ( Util_Environment::is_https() ) {
111
- $total = sizeof( $items );
112
- for ( $i = 0; $i < $total; $i++ ) {
113
- if ( isset( $items[$i]['description'] ) ) {
114
- $items[$i]['description'] = preg_replace( '/<img[^>]+src[^>]+W3TOTALCACHE[^>]+>/',
115
- '', $items[$i]['description'] );
116
- }
117
  }
118
  }
119
 
82
  $items = array();
83
  $items_count = $this->_config->get_integer( 'widget.latest_news.items' );
84
 
85
+ include_once ABSPATH . WPINC . '/feed.php';
86
+ $feed = fetch_feed( W3TC_NEWS_FEED_URL );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ if ( !is_wp_error( $feed ) ) {
89
+ $feed_items = $feed->get_items( 0, $items_count );
 
 
90
 
91
+ foreach ( $feed_items as $feed_item ) {
92
+ $items[] = array(
93
+ 'link' => $feed_item->get_link(),
94
+ 'title' => htmlspecialchars_decode( $feed_item->get_title() )
95
+ );
 
 
 
96
  }
97
  }
98
 
Generic_WidgetSpreadTheWord.js CHANGED
@@ -9,7 +9,7 @@ jQuery(function() {
9
  });
10
 
11
  jQuery('.button-tweet').on('click', function () {
12
- window.open('https://twitter.com/?status=' +
13
  encodeURIComponent(w3tc_spread_the_word_tweet), '_blank');
14
  });
15
 
@@ -18,22 +18,6 @@ jQuery(function() {
18
  encodeURIComponent(w3tc_spread_the_word_product_url), '_blank');
19
  });
20
 
21
- var last_value = null;
22
- jQuery('#common_support').change(function() {
23
- var where = jQuery(this).val();
24
- if (last_value == where)
25
- return;
26
-
27
- last_value = where;
28
-
29
- jQuery.post(ajaxurl, {
30
- action:'w3tc_link_support',
31
- w3tc_common_support_us: where
32
- }, function(data) {
33
- alert(data);
34
- });
35
- });
36
-
37
  jQuery('.button-rating').on('click', function () {
38
  window.open(w3tc_spread_the_word_rate_url, '_blank');
39
  });
9
  });
10
 
11
  jQuery('.button-tweet').on('click', function () {
12
+ window.open('https://twitter.com/?status=' +
13
  encodeURIComponent(w3tc_spread_the_word_tweet), '_blank');
14
  });
15
 
18
  encodeURIComponent(w3tc_spread_the_word_product_url), '_blank');
19
  });
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  jQuery('.button-rating').on('click', function () {
22
  window.open(w3tc_spread_the_word_rate_url, '_blank');
23
  });
Generic_WidgetSpreadTheWord_Plugin.php CHANGED
@@ -30,10 +30,6 @@ class Generic_WidgetSpreadTheWord_Plugin {
30
  $this,
31
  'wp_dashboard_setup'
32
  ), 4000 );
33
-
34
- if ( is_admin() ) {
35
- add_action( 'wp_ajax_w3tc_link_support', array( $this, 'action_widget_link_support' ) );
36
- }
37
  }
38
 
39
  /**
@@ -53,48 +49,9 @@ class Generic_WidgetSpreadTheWord_Plugin {
53
  }
54
 
55
  function widget_form() {
56
- $support = $this->_config->get_string( 'common.support' );
57
- $supports = $this->get_supports();
58
-
59
  include W3TC_DIR . '/Generic_WidgetSpreadTheWord_View.php';
60
  }
61
 
62
- /**
63
- * Returns list of support types
64
- *
65
- * @return array
66
- */
67
- function get_supports() {
68
- $supports = array(
69
- 'footer' => 'page footer'
70
- );
71
-
72
- $link_categories = get_terms( 'link_category', array(
73
- 'hide_empty' => 0
74
- ) );
75
-
76
- foreach ( $link_categories as $link_category ) {
77
- $supports['link_category_' . $link_category->term_id] = strtolower( $link_category->name );
78
- }
79
-
80
- return $supports;
81
- }
82
-
83
- function action_widget_link_support() {
84
- $value = Util_Request::get_string( 'w3tc_common_support_us' );
85
- $this->_config->set( 'common.support', $value );
86
- $this->_config->save();
87
-
88
- Generic_AdminLinks::link_update( $this->_config );
89
-
90
- if ( $value ) {
91
- _e( 'Thank you for linking to us!', 'w3-total-cache' );
92
- } else {
93
- _e( 'You are no longer linking to us. Please support us in other ways instead!', 'w3-total-cache' );
94
- }
95
- die();
96
- }
97
-
98
  public function enqueue() {
99
  wp_enqueue_style( 'w3tc-widget' );
100
  wp_enqueue_script( 'w3tc-metadata' );
30
  $this,
31
  'wp_dashboard_setup'
32
  ), 4000 );
 
 
 
 
33
  }
34
 
35
  /**
49
  }
50
 
51
  function widget_form() {
 
 
 
52
  include W3TC_DIR . '/Generic_WidgetSpreadTheWord_View.php';
53
  }
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  public function enqueue() {
56
  wp_enqueue_style( 'w3tc-widget' );
57
  wp_enqueue_script( 'w3tc-metadata' );
Generic_WidgetSpreadTheWord_View.php CHANGED
@@ -7,21 +7,14 @@ if ( !defined( 'W3TC' ) )
7
  ?>
8
  <p><?php _e( "Enjoying W3TC? Please support us!", 'w3-total-cache' ) ?></p>
9
  <ul>
10
- <li><label>Vote: </label><input type="button" class="button button-vote" value="Give us a 5 stars!" />
11
- <!-- <li><label>Share: </label><input type="button" class="button button-share" value="Share on Google+ Now" /></li>
12
- <li><label>Tweet: </label><input type="button" class="button button-tweet" value="Post to Twitter Now" /></li>
13
- <li><label>Like: </label><input type="button" class="button button-like" value="Like on Facebook Now" /></li>
14
- <li><label><?php _e( 'Rate:', 'w3-total-cache' )?> </label><input type="button" class="button button-rating" value="Vote &amp; Rate Now" /></li>
15
- <li><label><?php _e( 'Link:', 'w3-total-cache' ) ?></label>
16
- <select id="common_support" name="common__support" class="w3tc-ignore-change">
17
- <option value=""><?php esc_attr_e( 'select one', 'w3-total-cache' )?></option>
18
- <?php foreach ( $supports as $support_id => $support_name ): ?>
19
- <option value="<?php echo esc_attr( $support_id ); ?>" <?php selected( $support, $support_id ); ?>><?php echo esc_attr( $support_name ); ?></option>
20
- <?php endforeach; ?>
21
- </select>
22
- </li>-->
23
  </ul>
24
 
25
- <p>Or please share <a href="admin.php?page=w3tc_support&amp;request_type=new_feature">your feedback</a> so that we can improve!</p>
26
- <!--<p><?php _e( 'Or manually place a link, here is the code:', 'w3-total-cache' ) ?></p>
27
- <div class="w3tc-manual-link widefat"><p><?php echo sprintf( __( 'Optimization %s by W3 EDGE', 'w3-total-cache' ), "&lt;a href=&quot;https://www.w3-edge.com/products/&quot; rel=&quot;nofollow&quot;&gt;WordPress Plugins&lt;/a&gt;" )?></p></div>-->
 
 
7
  ?>
8
  <p><?php _e( "Enjoying W3TC? Please support us!", 'w3-total-cache' ) ?></p>
9
  <ul>
10
+ <li>
11
+ <label>Vote: </label>
12
+ <input type="button" class="button button-vote" value="Give us a 5 stars!" />
13
+ </li>
 
 
 
 
 
 
 
 
 
14
  </ul>
15
 
16
+ <p>
17
+ Or please share
18
+ <a href="admin.php?page=w3tc_support&amp;request_type=new_feature">your feedback</a>
19
+ so that we can improve!
20
+ </p>
LazyLoad_Mutator.php ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class LazyLoad_Mutator {
7
+ private $config;
8
+ private $modified = false;
9
+ private $excludes;
10
+ private $posts_by_url;
11
+
12
+
13
+
14
+ public function __construct( $config, $posts_by_url ) {
15
+ $this->config = $config;
16
+ $this->posts_by_url = $posts_by_url;
17
+ }
18
+
19
+
20
+
21
+ public function run( $buffer ) {
22
+ $this->excludes = apply_filters( 'w3tc_lazyload_excludes',
23
+ $this->config->get_array( 'lazyload.exclude' ) );
24
+
25
+ $unmutable = new LazyLoad_Mutator_Unmutable();
26
+ $buffer = $unmutable->remove_unmutable( $buffer );
27
+
28
+ if ( $this->config->get_boolean( 'lazyload.process_img' ) ) {
29
+ $buffer = preg_replace_callback(
30
+ '~<picture(\s[^>]+)*>(.*?)</picture>~is',
31
+ array( $this, 'tag_picture' ), $buffer
32
+ );
33
+ $buffer = preg_replace_callback(
34
+ '~<img\s[^>]+>~is',
35
+ array( $this, 'tag_img' ), $buffer
36
+ );
37
+ }
38
+
39
+ if ( $this->config->get_boolean( 'lazyload.process_background' ) ) {
40
+ $buffer = preg_replace_callback(
41
+ '~<[^>]+background:\s*url[^>]+>~is',
42
+ array( $this, 'tag_with_background' ), $buffer
43
+ );
44
+ }
45
+
46
+ $buffer = $unmutable->restore_unmutable( $buffer );
47
+
48
+ return $buffer;
49
+ }
50
+
51
+
52
+
53
+ public function content_modified() {
54
+ return $this->modified;
55
+ }
56
+
57
+
58
+
59
+ public function tag_picture( $matches ) {
60
+ $content = $matches[0];
61
+
62
+ if ( $this->is_content_excluded( $content ) ) {
63
+ return $content;
64
+ }
65
+
66
+ $m = new LazyLoad_Mutator_Picture( $this );
67
+ return $m->run( $content );
68
+ }
69
+
70
+
71
+
72
+ public function tag_img( $matches ) {
73
+ $content = $matches[0];
74
+
75
+ if ( $this->is_content_excluded( $content ) ) {
76
+ return $content;
77
+ }
78
+
79
+ // get image dimensions
80
+ $dim = $this->tag_get_dimensions( $content );
81
+ return $this->tag_img_content_replace( $content, $dim );
82
+ }
83
+
84
+
85
+
86
+ /**
87
+ * Common replace code for picture and img tags
88
+ */
89
+ public function tag_img_content_replace( $content, $dim ) {
90
+ // do replace
91
+ $count = 0;
92
+ $content = preg_replace( '~(\s)src=~is',
93
+ '$1src="' . $this->placeholder( $dim['w'], $dim['h'] ) .
94
+ '" data-src=', $content, -1, $count );
95
+
96
+ if ( $count > 0 ) {
97
+ $content = preg_replace( '~(\s)(srcset|sizes)=~is',
98
+ '$1data-$2=', $content );
99
+
100
+ $content = $this->add_class_lazy( $content );
101
+ $this->modified = true;
102
+ }
103
+
104
+ return $content;
105
+ }
106
+
107
+
108
+
109
+ /**
110
+ * Common get dimensions of image
111
+ */
112
+ public function tag_get_dimensions( $content ) {
113
+ $dim = array( 'w' => 1, 'h' => 1 );
114
+ $m = null;
115
+ if ( preg_match( '~\swidth=[\s\'"]*([0-9]+)~is', $content, $m ) ) {
116
+ $dim['h'] = $dim['w'] = (int)$m[1];
117
+
118
+ if ( preg_match( '~\sheight=[\s\'"]*([0-9]+)~is', $content, $m ) ) {
119
+ $dim['h'] = (int)$m[1];
120
+ return $dim;
121
+ }
122
+ }
123
+
124
+ // if not in attributes - try to find via url
125
+ if ( !preg_match( '~\ssrc=(\'([^\']*)\'|"([^"]*)"|([^\'"][^\\s]*))~is',
126
+ $content, $m ) ) {
127
+ return $dim;
128
+ }
129
+
130
+ $url = ( !empty( $m[4] ) ? $m[4] : ( ( !empty( $m[3] ) ? $m[3] : $m2 ) ) );
131
+
132
+ // full url found
133
+ if ( isset( $this->posts_by_url[$url] ) ) {
134
+ $post_id = $this->posts_by_url[$url];
135
+
136
+ $image = wp_get_attachment_image_src( $post_id, 'full' );
137
+ if ( $image ) {
138
+ $dim['w'] = $image[1];
139
+ $dim['h'] = $image[2];
140
+ }
141
+
142
+ return $dim;
143
+ }
144
+
145
+ // try resized url by format
146
+ static $base_url = null;
147
+ if ( is_null( $base_url ) ) {
148
+ $base_url = wp_get_upload_dir()['baseurl'];
149
+ }
150
+
151
+ if ( substr( $url, 0, strlen( $base_url ) ) == $base_url &&
152
+ preg_match( '~(.+)-(\\d+)x(\\d+)(\\.[a-z0-9]+)$~is', $url, $m ) ) {
153
+ $dim['w'] = (int)$m[2];
154
+ $dim['h'] = (int)$m[3];
155
+ }
156
+
157
+ return $dim;
158
+ }
159
+
160
+
161
+
162
+ public function tag_with_background( $matches ) {
163
+ $content = $matches[0];
164
+
165
+ if ( $this->is_content_excluded( $content ) ) {
166
+ return $content;
167
+ }
168
+
169
+ $quote_match = null;
170
+ if ( !preg_match( '~\s+style\s*=\s*([\"\'])~is', $content, $quote_match ) ) {
171
+ return $content;
172
+ }
173
+ $quote = $quote_match[1];
174
+
175
+ $count = 0;
176
+ $content = preg_replace_callback(
177
+ '~(\s+)(style\s*=\s*[' . $quote . '])(.*?)([' . $quote . '])~is',
178
+ array( $this, 'style_offload_background' ), $content, -1, $count
179
+ );
180
+
181
+ if ( $count > 0 ) {
182
+ $content = $this->add_class_lazy( $content );
183
+ $this->modified = true;
184
+ }
185
+
186
+ return $content;
187
+ }
188
+
189
+
190
+
191
+ public function style_offload_background( $matches ) {
192
+ list( $match, $v1, $v2, $v, $quote ) = $matches;
193
+ $url_match = null;
194
+ preg_match( '~background:\s*(url\([^>]+\))~is', $v, $url_match );
195
+ $v = preg_replace( '~background:\s*url\([^>]+\)[;]?\s*~is', '', $v );
196
+
197
+ return $v1 . $v2 . $v . $quote . ' data-bg=' . $quote . $url_match[1] . $quote;
198
+ }
199
+
200
+
201
+
202
+ private function add_class_lazy( $content ) {
203
+ $count = 0;
204
+ $content = preg_replace_callback(
205
+ '~(\s+)(class=)([\"\'])(.*?)([\"\'])~is',
206
+ array( $this, 'class_process' ), $content, -1, $count
207
+ );
208
+
209
+ if ( $count <= 0) {
210
+ $content = preg_replace(
211
+ '~<(\S+)(\s+)~is', '<$1$2class="lazy" ', $content
212
+ );
213
+ }
214
+
215
+ return $content;
216
+ }
217
+
218
+
219
+
220
+ public function class_process( $matches ) {
221
+ list( $match, $v1, $v2, $quote, $v ) = $matches;
222
+ if ( preg_match( '~(^|\\s)lazy(\\s|$)~is', $v ) ) {
223
+ return $match;
224
+ }
225
+
226
+ $v .= ' lazy';
227
+
228
+ return $v1 . $v2 . $quote . $v . $quote;
229
+ }
230
+
231
+
232
+
233
+ private function is_content_excluded( $content ) {
234
+ foreach ( $this->excludes as $w ) {
235
+ if ( strpos( $content, $w ) !== FALSE ) {
236
+ return true;
237
+ }
238
+ }
239
+
240
+ return false;
241
+ }
242
+
243
+
244
+
245
+ public function placeholder( $w, $h ) {
246
+ return 'data:image/svg+xml,%3Csvg%20xmlns=\'http://www.w3.org/2000/svg\'%20viewBox=\'0%200%20' .
247
+ $w . '%20'. $h . '\'%3E%3C/svg%3E';
248
+ }
249
+ }
LazyLoad_Mutator_Picture.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class LazyLoad_Mutator_Picture {
7
+ private $common;
8
+
9
+
10
+
11
+ public function __construct( $common ) {
12
+ $this->common = $common;
13
+ }
14
+
15
+
16
+
17
+ public function run( $content ) {
18
+ $content = preg_replace_callback(
19
+ '~(<img\s[^>]+>)~i',
20
+ array( $this, 'tag_img' ), $content
21
+ );
22
+
23
+ $content = preg_replace_callback(
24
+ '~(<source\s[^>]+>)~i',
25
+ array( $this, 'tag_source' ), $content
26
+ );
27
+
28
+ return $content;
29
+ }
30
+
31
+
32
+
33
+ public function tag_img( $matches ) {
34
+ $content = $matches[0];
35
+
36
+ // get image dimensions
37
+ $dim = $this->common->tag_get_dimensions( $content );
38
+ return $this->common->tag_img_content_replace( $content, $dim );
39
+ }
40
+
41
+
42
+
43
+ /**
44
+ * Common replace code for picture and img tags
45
+ */
46
+ private function tag_source( $matches ) {
47
+ $content = $matches[0];
48
+
49
+ $content = preg_replace( '~(\s)(srcset|sizes)=~i',
50
+ '$1data-$2=', $content );
51
+
52
+ return $content;
53
+ }
54
+ }
LazyLoad_Mutator_Unmutable.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class LazyLoad_Mutator_Unmutable {
7
+ private $placeholders = array();
8
+
9
+
10
+
11
+ public function __construct() {
12
+ $this->placeholder_base = 'w3tc_lazyload_' .
13
+ md5( $_SERVER['REQUEST_TIME'] ) . '_';
14
+ }
15
+
16
+
17
+
18
+ public function remove_unmutable( $buffer ) {
19
+ // scripts
20
+ $buffer = preg_replace_callback(
21
+ '~<script(\b[^>]*)>(.*?)</script>~is',
22
+ array( $this, 'placeholder' ), $buffer );
23
+
24
+ // styles
25
+ $buffer = preg_replace_callback(
26
+ '~\s*<style(\b[^>]*)>(.*?)</style>~is',
27
+ array($this, 'placeholder'), $buffer);
28
+
29
+ return $buffer;
30
+ }
31
+
32
+
33
+
34
+ public function restore_unmutable( $buffer ) {
35
+ return str_replace(
36
+ array_keys( $this->placeholders ),
37
+ array_values( $this->placeholders ),
38
+ $buffer
39
+ );
40
+ }
41
+
42
+
43
+
44
+ public function placeholder( $matches ) {
45
+ $key = '{' .$this->placeholder_base . count( $this->placeholders ) . '}';
46
+ $this->placeholders[$key] = $matches[0];
47
+ return $key;
48
+ }
49
+ }
LazyLoad_Plugin.php CHANGED
@@ -5,12 +5,9 @@ namespace W3TC;
5
 
6
  class LazyLoad_Plugin {
7
  private $config;
8
- private $modified = false;
9
- private $excludes;
10
  private $posts_by_url = array();
11
 
12
 
13
-
14
  public function __construct() {
15
  $this->config = Dispatcher::config();
16
  }
@@ -23,6 +20,9 @@ class LazyLoad_Plugin {
23
 
24
  add_filter( 'wp_get_attachment_url',
25
  array( $this, 'wp_get_attachment_url' ), 10, 2 );
 
 
 
26
  }
27
 
28
 
@@ -37,31 +37,31 @@ class LazyLoad_Plugin {
37
  'buffer' => $buffer,
38
  'reason' => null
39
  );
 
40
  $can_process = $this->can_process( $can_process );
41
  $can_process = apply_filters( 'w3tc_lazyload_can_process', $can_process );
42
- if ( !$can_process['enabled'] ) {
43
- return $buffer;
 
 
 
 
 
44
  }
45
 
46
- $this->excludes = apply_filters( 'w3tc_lazyload_excludes',
47
- $this->config->get_array( 'lazyload.exclude' ) );
48
 
49
- if ( $this->config->get_boolean( 'lazyload.process_img' ) ) {
50
- $buffer = preg_replace_callback(
51
- '~(<img[^>]+>)~',
52
- array( $this, 'tag_with_src' ), $buffer
53
- );
54
  }
55
 
56
- if ( $this->config->get_boolean( 'lazyload.process_background' ) ) {
57
- $buffer = preg_replace_callback(
58
- '~(<[^>]+background:\s*url[^>]+>)~',
59
- array( $this, 'tag_with_background' ), $buffer
60
- );
61
- }
62
 
63
  // embed lazyload script
64
- if ( $this->modified ) {
65
  $buffer = apply_filters( 'w3tc_lazyload_embed_script', $buffer );
66
 
67
  $is_embed_script = apply_filters( 'w3tc_lazyload_is_embed_script', true );
@@ -90,174 +90,21 @@ class LazyLoad_Plugin {
90
  return $can_process;
91
  }
92
 
93
- return $can_process;
94
- }
95
-
96
-
97
-
98
- public function tag_with_src( $matches ) {
99
- $content = $matches[0];
100
-
101
- if ( $this->is_content_excluded( $content ) ) {
102
- return $content;
103
- }
104
-
105
- // get image dimensions
106
- $dim = $this->tag_get_dimensions( $content );
107
-
108
- // do replace
109
- $count = 0;
110
- $content = preg_replace( '~(\s)src=~i',
111
- '$1src="' . $this->placeholder( $dim['w'], $dim['h'] ) .
112
- '" data-src=', $content, -1, $count );
113
-
114
- if ( $count > 0 ) {
115
- $content = preg_replace( '~(\s)(srcset|sizes)=~i',
116
- '$1data-$2=', $content );
117
-
118
- $content = $this->add_class_lazy( $content );
119
- $this->modified = true;
120
- }
121
-
122
- return $content;
123
- }
124
-
125
-
126
-
127
- public function tag_get_dimensions( $content ) {
128
- $dim = array( 'w' => 1, 'h' => 1 );
129
- $m = null;
130
- if ( preg_match( '~\swidth=[\s\'"]*([0-9]+)~i', $content, $m ) ) {
131
- $dim['h'] = $dim['w'] = (int)$m[1];
132
-
133
- if ( preg_match( '~\sheight=[\s\'"]*([0-9]+)~i', $content, $m ) ) {
134
- $dim['h'] = (int)$m[1];
135
- return $dim;
136
- }
137
- }
138
-
139
- // if not in attributes - try to find via url
140
- if ( !preg_match( '~\ssrc=(\'([^\']*)\'|"([^"]*)"|([^\'"][^\\s]*))~i',
141
- $content, $m ) ) {
142
- return $dim;
143
- }
144
-
145
- $url = ( !empty( $m[4] ) ? $m[4] : ( ( !empty( $m[3] ) ? $m[3] : $m2 ) ) );
146
-
147
- // full url found
148
- if ( isset( $this->posts_by_url[$url] ) ) {
149
- $post_id = $this->posts_by_url[$url];
150
-
151
- $image = wp_get_attachment_image_src( $post_id, 'full' );
152
- if ( $image ) {
153
- $dim['w'] = $image[1];
154
- $dim['h'] = $image[2];
155
- }
156
-
157
- return $dim;
158
- }
159
-
160
- // try resized url by format
161
- static $base_url = null;
162
- if ( is_null( $base_url ) ) {
163
- $base_url = wp_get_upload_dir()['baseurl'];
164
- }
165
-
166
- if ( substr( $url, 0, strlen( $base_url ) ) == $base_url &&
167
- preg_match( '~(.+)-(\\d+)x(\\d+)(\\.[a-z0-9]+)$~i', $url, $m ) ) {
168
- $dim['w'] = (int)$m[2];
169
- $dim['h'] = (int)$m[3];
170
- }
171
-
172
- return $dim;
173
- }
174
-
175
-
176
-
177
- public function tag_with_background( $matches ) {
178
- $content = $matches[0];
179
-
180
- if ( $this->is_content_excluded( $content ) ) {
181
- return $content;
182
- }
183
-
184
- $quote_match = null;
185
- if ( !preg_match( '~\s+style\s*=\s*([\"\'])~', $content, $quote_match ) ) {
186
- return $content;
187
- }
188
- $quote = $quote_match[1];
189
-
190
- $count = 0;
191
- $content = preg_replace_callback(
192
- '~(\s+)(style\s*=\s*[' . $quote . '])(.*?)([' . $quote . '])~',
193
- array( $this, 'style_offload_background' ), $content, -1, $count
194
- );
195
-
196
- if ( $count > 0 ) {
197
- $content = $this->add_class_lazy( $content );
198
- $this->modified = true;
199
- }
200
-
201
- return $content;
202
- }
203
-
204
-
205
-
206
- public function style_offload_background( $matches ) {
207
- list( $match, $v1, $v2, $v, $quote ) = $matches;
208
- $url_match = null;
209
- preg_match( '~background:\s*(url\([^>]+\))~', $v, $url_match );
210
- $v = preg_replace( '~background:\s*url\([^>]+\)[;]?\s*~', '', $v );
211
-
212
- return $v1 . $v2 . $v . $quote . ' data-bg=' . $quote . $url_match[1] . $quote;
213
- }
214
-
215
-
216
-
217
- private function add_class_lazy( $content ) {
218
- $count = 0;
219
- $content = preg_replace_callback(
220
- '~(\s+)(class=)([\"\'])(.*?)([\"\'])~',
221
- array( $this, 'class_process' ), $content, -1, $count
222
- );
223
-
224
- if ( $count <= 0) {
225
- $content = preg_replace(
226
- '~<(\S+)(\s+)~', '<$1$2class="lazy" ', $content
227
- );
228
- }
229
-
230
- return $content;
231
- }
232
-
233
-
234
-
235
- public function class_process( $matches ) {
236
- list( $match, $v1, $v2, $quote, $v ) = $matches;
237
- if ( preg_match( '~(^|\\s)lazy($|\\s)~', $v ) ) {
238
- return $match;
239
- }
240
-
241
- $v .= ' lazy';
242
-
243
- return $v1 . $v2 . $quote . $v . $quote;
244
- }
245
-
246
 
247
- private function is_content_excluded( $content ) {
248
- foreach ( $this->excludes as $w ) {
249
- if ( strpos( $content, $w ) !== FALSE ) {
250
- return true;
251
- }
252
  }
253
 
254
- return false;
255
  }
256
 
257
 
258
 
259
- private function placeholder( $w, $h ) {
260
- return 'data:image/svg+xml,%3Csvg%20xmlns=\'http://www.w3.org/2000/svg\'%20viewBox=\'0%200%20' . $w . '%20'. $h . '\'%3E%3C/svg%3E';
 
261
  }
262
 
263
 
5
 
6
  class LazyLoad_Plugin {
7
  private $config;
 
 
8
  private $posts_by_url = array();
9
 
10
 
 
11
  public function __construct() {
12
  $this->config = Dispatcher::config();
13
  }
20
 
21
  add_filter( 'wp_get_attachment_url',
22
  array( $this, 'wp_get_attachment_url' ), 10, 2 );
23
+ add_filter( 'w3tc_footer_comment',
24
+ array( $this, 'w3tc_footer_comment' ) );
25
+
26
  }
27
 
28
 
37
  'buffer' => $buffer,
38
  'reason' => null
39
  );
40
+
41
  $can_process = $this->can_process( $can_process );
42
  $can_process = apply_filters( 'w3tc_lazyload_can_process', $can_process );
43
+
44
+ // set reject reason in comment
45
+ if ( $can_process['enabled'] ) {
46
+ $reject_reason = '';
47
+ } else {
48
+ $reject_reason = empty( $can_process['reason'] ) ?
49
+ ' (not specified)' : ' (' . $can_process['reason'] . ')';
50
  }
51
 
52
+ $buffer = str_replace( '{w3tc_lazyload_reject_reason}',
53
+ $reject_reason, $buffer );
54
 
55
+ // processing
56
+ if ( !$can_process['enabled'] ) {
57
+ return $buffer;
 
 
58
  }
59
 
60
+ $mutator = new LazyLoad_Mutator( $this->config, $this->posts_by_url );
61
+ $buffer = $mutator->run( $buffer );
 
 
 
 
62
 
63
  // embed lazyload script
64
+ if ( $mutator->content_modified() ) {
65
  $buffer = apply_filters( 'w3tc_lazyload_embed_script', $buffer );
66
 
67
  $is_embed_script = apply_filters( 'w3tc_lazyload_is_embed_script', true );
90
  return $can_process;
91
  }
92
 
93
+ if ( function_exists( 'is_feed' ) && is_feed() ) {
94
+ $can_process['enabled'] = false;
95
+ $can_process['reason'] = 'feed';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ return $can_process;
 
 
 
 
98
  }
99
 
100
+ return $can_process;
101
  }
102
 
103
 
104
 
105
+ public function w3tc_footer_comment( $strings ) {
106
+ $strings[] = __( 'Lazy Loading', 'w3-total-cache' ) . '{w3tc_lazyload_reject_reason}';
107
+ return $strings;
108
  }
109
 
110
 
Minify_Environment.php CHANGED
@@ -690,121 +690,50 @@ class Minify_Environment {
690
 
691
  $browsercache = $config->get_boolean( 'browsercache.enabled' );
692
  $brotli = ( $browsercache && $config->get_boolean( 'browsercache.cssjs.brotli' ) );
693
- $compression = ( $browsercache && $config->get_boolean( 'browsercache.cssjs.compression' ) );
694
- $expires = ( $browsercache && $config->get_boolean( 'browsercache.cssjs.expires' ) );
695
- $lifetime = ( $browsercache ? $config->get_integer( 'browsercache.cssjs.lifetime' ) : 0 );
696
- $cache_control = ( $browsercache && $config->get_boolean( 'browsercache.cssjs.cache.control' ) );
697
- $w3tc = ( $browsercache && $config->get_integer( 'browsercache.cssjs.w3tc' ) );
698
 
699
  $rules = '';
700
  $rules .= W3TC_MARKER_BEGIN_MINIFY_CACHE . "\n";
701
 
702
- $common_rules = '';
703
-
704
- if ( $expires ) {
705
- $common_rules .= " expires modified " . $lifetime . "s;\n";
706
- }
707
-
708
- if ( $w3tc ) {
709
- $common_rules .= " add_header X-Powered-By \"" .
710
- Util_Environment::w3tc_header() . "\";\n";
711
- }
712
-
713
- if ( $brotli || $compression ) {
714
- $common_rules .= " add_header Vary \"Accept-Encoding\";\n";
715
- }
716
-
717
- if ( $cache_control ) {
718
- $cache_policy = $config->get_string( 'browsercache.cssjs.cache.policy' );
719
-
720
- switch ( $cache_policy ) {
721
- case 'cache':
722
- $common_rules .= " add_header Pragma \"public\";\n";
723
- $common_rules .= " add_header Cache-Control \"public\";\n";
724
- break;
725
-
726
- case 'cache_public_maxage':
727
- $common_rules .= " add_header Pragma \"public\";\n";
728
-
729
- if ( $expires ) {
730
- $common_rules .= " add_header Cache-Control \"public\";\n";
731
- } else {
732
- $common_rules .= " add_header Cache-Control \"max-age=" . $lifetime . ", public\";\n";
733
- }
734
- break;
735
-
736
- case 'cache_validation':
737
- $common_rules .= " add_header Pragma \"public\";\n";
738
- $common_rules .= " add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n";
739
- break;
740
 
741
- case 'cache_noproxy':
742
- $common_rules .= " add_header Pragma \"public\";\n";
743
- $common_rules .= " add_header Cache-Control \"private, must-revalidate\";\n";
744
- break;
745
-
746
- case 'cache_maxage':
747
- $common_rules .= " add_header Pragma \"public\";\n";
748
-
749
- if ( $expires ) {
750
- $common_rules .= " add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n";
751
- } else {
752
- $common_rules .= " add_header Cache-Control \"max-age=" . $lifetime . ", public, must-revalidate, proxy-revalidate\";\n";
753
- }
754
- break;
755
-
756
- case 'no_cache':
757
- $common_rules .= " add_header Pragma \"no-cache\";\n";
758
- $common_rules .= " add_header Cache-Control \"max-age=0, private, no-store, no-cache, must-revalidate\";\n";
759
- break;
760
- }
761
- }
762
-
763
- $rules .= "location ~ " . $cache_uri . ".*\\.js$ {\n";
764
- $rules .= " types {}\n";
765
- $rules .= " default_type application/x-javascript;\n";
766
- $rules .= $common_rules;
767
- $rules .= "}\n";
768
-
769
- $rules .= "location ~ " . $cache_uri . ".*\\.css$ {\n";
770
- $rules .= " types {}\n";
771
- $rules .= " default_type text/css;\n";
772
- $rules .= $common_rules;
773
- $rules .= "}\n";
774
 
775
  if ( $brotli ) {
776
  $rules .= "location ~ " . $cache_uri . ".*js_br$ {\n";
777
  $rules .= " brotli off;\n";
778
  $rules .= " types {}\n";
779
  $rules .= " default_type application/x-javascript;\n";
780
- $rules .= $common_rules;
781
  $rules .= " add_header Content-Encoding br;\n";
 
782
  $rules .= "}\n";
783
 
784
  $rules .= "location ~ " . $cache_uri . ".*css_br$ {\n";
785
  $rules .= " brotli off;\n";
786
  $rules .= " types {}\n";
787
  $rules .= " default_type text/css;\n";
788
- $rules .= $common_rules;
789
  $rules .= " add_header Content-Encoding br;\n";
 
790
  $rules .= "}\n";
791
  }
792
 
793
- if ( $compression ) {
794
  $rules .= "location ~ " . $cache_uri . ".*js_gzip$ {\n";
795
  $rules .= " gzip off;\n";
796
  $rules .= " types {}\n";
797
  $rules .= " default_type application/x-javascript;\n";
798
- $rules .= $common_rules;
799
  $rules .= " add_header Content-Encoding gzip;\n";
 
800
  $rules .= "}\n";
801
 
802
  $rules .= "location ~ " . $cache_uri . ".*css_gzip$ {\n";
803
  $rules .= " gzip off;\n";
804
  $rules .= " types {}\n";
805
  $rules .= " default_type text/css;\n";
806
- $rules .= $common_rules;
807
  $rules .= " add_header Content-Encoding gzip;\n";
 
808
  $rules .= "}\n";
809
  }
810
 
690
 
691
  $browsercache = $config->get_boolean( 'browsercache.enabled' );
692
  $brotli = ( $browsercache && $config->get_boolean( 'browsercache.cssjs.brotli' ) );
693
+ $gzip = ( $browsercache && $config->get_boolean( 'browsercache.cssjs.compression' ) );
 
 
 
 
694
 
695
  $rules = '';
696
  $rules .= W3TC_MARKER_BEGIN_MINIFY_CACHE . "\n";
697
 
698
+ $common_rules_a = Dispatcher::nginx_rules_for_browsercache_section(
699
+ $config, 'cssjs', true );
700
+ $common_rules_a[] = 'add_header Vary "Accept-Encoding";';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701
 
702
+ $common_rules = ' ' . implode( "\n ", $common_rules_a ) . "\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
703
 
704
  if ( $brotli ) {
705
  $rules .= "location ~ " . $cache_uri . ".*js_br$ {\n";
706
  $rules .= " brotli off;\n";
707
  $rules .= " types {}\n";
708
  $rules .= " default_type application/x-javascript;\n";
 
709
  $rules .= " add_header Content-Encoding br;\n";
710
+ $rules .= $common_rules;
711
  $rules .= "}\n";
712
 
713
  $rules .= "location ~ " . $cache_uri . ".*css_br$ {\n";
714
  $rules .= " brotli off;\n";
715
  $rules .= " types {}\n";
716
  $rules .= " default_type text/css;\n";
 
717
  $rules .= " add_header Content-Encoding br;\n";
718
+ $rules .= $common_rules;
719
  $rules .= "}\n";
720
  }
721
 
722
+ if ( $gzip ) {
723
  $rules .= "location ~ " . $cache_uri . ".*js_gzip$ {\n";
724
  $rules .= " gzip off;\n";
725
  $rules .= " types {}\n";
726
  $rules .= " default_type application/x-javascript;\n";
 
727
  $rules .= " add_header Content-Encoding gzip;\n";
728
+ $rules .= $common_rules;
729
  $rules .= "}\n";
730
 
731
  $rules .= "location ~ " . $cache_uri . ".*css_gzip$ {\n";
732
  $rules .= " gzip off;\n";
733
  $rules .= " types {}\n";
734
  $rules .= " default_type text/css;\n";
 
735
  $rules .= " add_header Content-Encoding gzip;\n";
736
+ $rules .= $common_rules;
737
  $rules .= "}\n";
738
  }
739
 
Minify_MinifiedFileRequestHandler.php CHANGED
@@ -55,8 +55,8 @@ class Minify_MinifiedFileRequestHandler {
55
  echo 'error storing';
56
  } else {
57
  if ( ( function_exists( 'brotli_compress' ) &&
58
- $this->_config->get_boolean( 'browsercache.enabled' ) &&
59
- $this->_config->get_boolean( 'browsercache.cssjs.brotli' ) ) )
60
  if ( !$cache->store( basename( $file ) . '_br',
61
  array( 'content' => brotli_compress( 'content ok' ) ) ) ) {
62
  echo 'error storing';
@@ -143,8 +143,8 @@ class Minify_MinifiedFileRequestHandler {
143
  'encodeOutput' => ( $browsercache &&
144
  !defined( 'W3TC_PAGECACHE_OUTPUT_COMPRESSION_OFF' ) &&
145
  !$quiet &&
146
- ( $this->_config->get_boolean( 'browsercache.cssjs.compression' ) ||
147
- $this->_config->get_boolean( 'browsercache.cssjs.brotli' ) ) ),
148
  'bubbleCssImports' => ( $this->_config->get_string( 'minify.css.imports' ) == 'bubble' ),
149
  'processCssImports' => ( $this->_config->get_string( 'minify.css.imports' ) == 'process' ),
150
  'cacheHeaders' => array(
@@ -225,9 +225,11 @@ class Minify_MinifiedFileRequestHandler {
225
  return $this->finish_with_error( 'Nothing to minify', $quiet, false );
226
  }
227
 
228
- /**
229
- * Minify!
230
- */
 
 
231
  $return = array();
232
  try {
233
  $return = \Minify0_Minify::serve( 'MinApp', $serve_options );
55
  echo 'error storing';
56
  } else {
57
  if ( ( function_exists( 'brotli_compress' ) &&
58
+ $this->_config->get_boolean( 'browsercache.enabled' ) &&
59
+ $this->_config->get_boolean( 'browsercache.cssjs.brotli' ) ) )
60
  if ( !$cache->store( basename( $file ) . '_br',
61
  array( 'content' => brotli_compress( 'content ok' ) ) ) ) {
62
  echo 'error storing';
143
  'encodeOutput' => ( $browsercache &&
144
  !defined( 'W3TC_PAGECACHE_OUTPUT_COMPRESSION_OFF' ) &&
145
  !$quiet &&
146
+ ( $this->_config->get_boolean( 'browsercache.cssjs.compression' ) ||
147
+ $this->_config->get_boolean( 'browsercache.cssjs.brotli' ) ) ),
148
  'bubbleCssImports' => ( $this->_config->get_string( 'minify.css.imports' ) == 'bubble' ),
149
  'processCssImports' => ( $this->_config->get_string( 'minify.css.imports' ) == 'process' ),
150
  'cacheHeaders' => array(
225
  return $this->finish_with_error( 'Nothing to minify', $quiet, false );
226
  }
227
 
228
+ // Minify
229
+ $serve_options = apply_filters(
230
+ 'w3tc_minify_file_handler_minify_options',
231
+ $serve_options );
232
+
233
  $return = array();
234
  try {
235
  $return = \Minify0_Minify::serve( 'MinApp', $serve_options );
PgCache_ContentGrabber.php CHANGED
@@ -149,6 +149,8 @@ class PgCache_ContentGrabber {
149
  * Do cache logic
150
  */
151
  function process() {
 
 
152
  /**
153
  * Skip caching for some pages
154
  */
@@ -212,7 +214,6 @@ class PgCache_ContentGrabber {
212
  $this->_page_key_extension['cache_reject_reason'];
213
  }
214
 
215
-
216
  if ( $this->_caching && !$this->_late_caching ) {
217
  $this->_cached_data = $this->_extract_cached_page( false );
218
  if ( $this->_cached_data ) {
@@ -238,6 +239,28 @@ class PgCache_ContentGrabber {
238
  Util_Bus::add_ob_callback( 'pagecache', array( $this, 'ob_callback' ) );
239
  }
240
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  /**
242
  * Extracts page from cache
243
  *
@@ -532,7 +555,7 @@ class PgCache_ContentGrabber {
532
  /**
533
  * Skip if there is query in the request uri
534
  */
535
- if ( !$this->_is_ignored_query_string() ) {
536
  $should_reject_qs =
537
  ( !$this->_config->get_boolean( 'pgcache.cache.query' ) ||
538
  $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' );
@@ -1158,6 +1181,8 @@ class PgCache_ContentGrabber {
1158
 
1159
  // fill group
1160
  $extension['group'] = $this->get_cache_group_by_uri( $this->_request_uri );
 
 
1161
 
1162
  return $extension;
1163
  }
@@ -1385,38 +1410,34 @@ class PgCache_ContentGrabber {
1385
  * @return string
1386
  */
1387
  function _get_page_key( $page_key_extension, $request_url = '' ) {
 
1388
  if ( $request_url ) {
1389
  $parts = parse_url( $request_url );
1390
- $key = $parts['host'] .
1391
-
1392
  ( isset( $parts['port'] ) ? ':' . $parts['port'] : '' ) .
1393
  ( isset( $parts['path'] ) ? $parts['path'] : '' ) .
1394
  ( isset( $parts['query'] ) ? '?' . $parts['query'] : '' );
1395
  } else {
1396
- $key = $this->_request_host . $this->_request_uri;
1397
- $request_url = $this->_request_uri;
1398
  }
1399
 
1400
- // replace fragment
1401
- $key = preg_replace( '~#.*$~', '', $key );
1402
- $key = strtolower( $key ); // host/uri in different cases means the same page in wp
1403
 
1404
- $key = $this->_get_page_key_part1( $key, $page_key_extension );
1405
-
1406
- /**
1407
- * Append extensions
1408
- */
1409
- if ( !empty( $page_key_extension['useragent'] ) )
1410
- $key .= '_' . $page_key_extension['useragent'];
1411
- if ( !empty( $page_key_extension['referrer'] ) )
1412
- $key .= '_' . $page_key_extension['referrer'];
1413
- if ( !empty( $page_key_extension['cookie'] ) )
1414
- $key .= '_' . $page_key_extension['cookie'];
1415
- if ( !empty( $page_key_extension['encryption'] ) )
1416
- $key .= '_' . $page_key_extension['encryption'];
1417
- if ( Util_Environment::is_preview_mode() )
1418
- $key .= '_preview';
1419
 
 
 
1420
  if ( $this->_enhanced_mode && empty( $page_key_extension['group'] ) ) {
1421
  $key_postfix = '.html';
1422
  if ( $this->_config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
@@ -1429,20 +1450,31 @@ class PgCache_ContentGrabber {
1429
  $key_postfix = '.xml';
1430
  }
1431
  }
1432
-
1433
- $key .= $key_postfix;
1434
  }
1435
 
1436
- /**
1437
- * Append compression
1438
- */
1439
  if ( $page_key_extension['compression'] )
1440
- $key .= '_' . $page_key_extension['compression'];
 
 
 
 
 
 
 
 
1441
 
1442
- return $key;
1443
  }
1444
 
1445
- private function _get_page_key_part1( $key, $page_key_extension ) {
 
 
 
 
 
 
1446
  if ( empty( $page_key_extension['group'] ) ) {
1447
  if ( $this->_enhanced_mode || $this->_nginx_memcached ) {
1448
  // URL decode
@@ -1468,7 +1500,7 @@ class PgCache_ContentGrabber {
1468
  }
1469
  }
1470
 
1471
- if ( $this->_is_ignored_query_string() ) {
1472
  // remove query string
1473
  $key = preg_replace( '~\?.*$~', '', $key );
1474
  }
@@ -1888,28 +1920,38 @@ class PgCache_ContentGrabber {
1888
  return in_array( $content_type, $cache_headers );
1889
  }
1890
 
1891
- private function _is_ignored_query_string() {
1892
- $accept_qs = $this->_config->get_array( 'pgcache.accept.qs' );
1893
- Util_Rule::array_trim( $accept_qs );
 
1894
 
1895
- if ( empty( $accept_qs) ) {
1896
  return false;
1897
  }
1898
 
1899
- foreach ( $accept_qs as &$val ) {
1900
- $val = Util_Environment::preg_quote( str_replace( "+", " ", $val ) );
1901
- $val .= ( strpos( $val, '=' ) === false ? '=.*?' : '' );
1902
  }
 
1903
 
1904
- $accept_qs = implode( '|', $accept_qs );
 
 
 
 
 
 
 
 
1905
 
1906
- foreach ( $_GET as $key => $value ) {
1907
- if ( !@preg_match( '~^(' . $accept_qs . ')$~i', $key . "=$value" ) ) {
1908
- return false;
1909
  }
1910
  }
1911
 
1912
- return true;
1913
  }
1914
 
1915
  /**
149
  * Do cache logic
150
  */
151
  function process() {
152
+ $this->run_extensions_dropin();
153
+
154
  /**
155
  * Skip caching for some pages
156
  */
214
  $this->_page_key_extension['cache_reject_reason'];
215
  }
216
 
 
217
  if ( $this->_caching && !$this->_late_caching ) {
218
  $this->_cached_data = $this->_extract_cached_page( false );
219
  if ( $this->_cached_data ) {
239
  Util_Bus::add_ob_callback( 'pagecache', array( $this, 'ob_callback' ) );
240
  }
241
 
242
+
243
+
244
+ private function run_extensions_dropin() {
245
+ $c = $this->_config;
246
+ $extensions = $c->get_array( 'extensions.active' );
247
+
248
+ $dropin = $c->get_array( 'extensions.active_dropin' );
249
+ foreach ( $dropin as $extension => $nothing ) {
250
+ if ( isset( $extensions[$extension] ) ) {
251
+ $path = $extensions[$extension];
252
+ $filename = W3TC_EXTENSION_DIR . '/' .
253
+ str_replace( '..', '', trim( $path, '/' ) );
254
+
255
+ if ( file_exists( $filename ) ) {
256
+ include_once( $filename );
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+
263
+
264
  /**
265
  * Extracts page from cache
266
  *
555
  /**
556
  * Skip if there is query in the request uri
557
  */
558
+ if ( !$this->_is_ignored_query_string( $this->_request_uri ) ) {
559
  $should_reject_qs =
560
  ( !$this->_config->get_boolean( 'pgcache.cache.query' ) ||
561
  $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' );
1181
 
1182
  // fill group
1183
  $extension['group'] = $this->get_cache_group_by_uri( $this->_request_uri );
1184
+ $extension = w3tc_apply_filters( 'pagecache_key_extension', $extension,
1185
+ $this->_request_host, $this->_request_uri );
1186
 
1187
  return $extension;
1188
  }
1410
  * @return string
1411
  */
1412
  function _get_page_key( $page_key_extension, $request_url = '' ) {
1413
+ // key url part
1414
  if ( $request_url ) {
1415
  $parts = parse_url( $request_url );
1416
+ $key_urlpart = $parts['host'] .
 
1417
  ( isset( $parts['port'] ) ? ':' . $parts['port'] : '' ) .
1418
  ( isset( $parts['path'] ) ? $parts['path'] : '' ) .
1419
  ( isset( $parts['query'] ) ? '?' . $parts['query'] : '' );
1420
  } else {
1421
+ $request_url = $this->_request_host . $this->_request_uri;
1422
+ $key_urlpart = $request_url;
1423
  }
1424
 
1425
+ $key_urlpart = $this->_get_page_key_urlpart( $key_urlpart, $page_key_extension );
 
 
1426
 
1427
+ // key extension
1428
+ $key_extension = '';
1429
+ $extensions = array( 'useragent', 'referrer', 'cookie', 'encryption' );
1430
+ foreach ( $extensions as $e ) {
1431
+ if ( !empty( $page_key_extension[$e] ) ) {
1432
+ $key_extension .= '_' . $page_key_extension[$e];
1433
+ }
1434
+ }
1435
+ if ( Util_Environment::is_preview_mode() ) {
1436
+ $key_extension .= '_preview';
1437
+ }
 
 
 
 
1438
 
1439
+ // key postfix
1440
+ $key_postfix = '';
1441
  if ( $this->_enhanced_mode && empty( $page_key_extension['group'] ) ) {
1442
  $key_postfix = '.html';
1443
  if ( $this->_config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
1450
  $key_postfix = '.xml';
1451
  }
1452
  }
 
 
1453
  }
1454
 
1455
+ // key compression
1456
+ $key_compression = '';
 
1457
  if ( $page_key_extension['compression'] )
1458
+ $key_compression = '_' . $page_key_extension['compression'];
1459
+
1460
+ $key = w3tc_apply_filters( 'pagecache_page_key',
1461
+ array(
1462
+ $key_urlpart,
1463
+ $key_extension,
1464
+ $key_postfix,
1465
+ $key_compression
1466
+ ), $request_url, $page_key_extension );
1467
 
1468
+ return implode( '', $key );
1469
  }
1470
 
1471
+ private function _get_page_key_urlpart( $key, $page_key_extension ) {
1472
+ // remove fragments
1473
+ $key = preg_replace( '~#.*$~', '', $key );
1474
+
1475
+ // host/uri in different cases means the same page in wp
1476
+ $key = strtolower( $key );
1477
+
1478
  if ( empty( $page_key_extension['group'] ) ) {
1479
  if ( $this->_enhanced_mode || $this->_nginx_memcached ) {
1480
  // URL decode
1500
  }
1501
  }
1502
 
1503
+ if ( $this->_is_ignored_query_string( $key ) ) {
1504
  // remove query string
1505
  $key = preg_replace( '~\?.*$~', '', $key );
1506
  }
1920
  return in_array( $content_type, $cache_headers );
1921
  }
1922
 
1923
+ private function _is_ignored_query_string( $uri ) {
1924
+ $ignore_qs = $this->_config->get_array( 'pgcache.accept.qs' );
1925
+ $ignore_qs = w3tc_apply_filters( 'pagecache_extract_accept_qs', $ignore_qs );
1926
+ Util_Rule::array_trim( $ignore_qs );
1927
 
1928
+ if ( empty( $ignore_qs ) ) {
1929
  return false;
1930
  }
1931
 
1932
+ $p = strpos( $uri, '?' );
1933
+ if ( $p === false ) {
1934
+ return false;
1935
  }
1936
+ $uri = substr( $uri, $p + 1 );
1937
 
1938
+ foreach ( $ignore_qs as $qs ) {
1939
+ $m = null;
1940
+ if ( strpos( $qs, '=' ) === false ) {
1941
+ $regexp = Util_Environment::preg_quote( str_replace( '+', ' ', $qs ) );
1942
+ if ( @preg_match( "~^(.*?&|)$regexp(=[^&]*)?(&.*|)$~i", $uri, $m ) ) {
1943
+ $uri = $m[1] . $m[3];
1944
+ }
1945
+ } else {
1946
+ $regexp = Util_Environment::preg_quote( str_replace( '+', ' ', $qs ) );
1947
 
1948
+ if ( @preg_match( "~^(.*?&|)$regexp(&.*|)$~i", $uri, $m ) ) {
1949
+ $uri = $m[1] . $m[2];
1950
+ }
1951
  }
1952
  }
1953
 
1954
+ return preg_match( "~^[&]*$~", $uri );
1955
  }
1956
 
1957
  /**
PgCache_Environment.php CHANGED
@@ -397,102 +397,24 @@ class PgCache_Environment {
397
  * returns true if modifications has been made
398
  */
399
  private function rules_core_add( $config, $exs ) {
400
- $path = Util_Rule::get_pgcache_rules_core_path();
401
- if ( $path === false )
402
- return;
403
-
404
- $original_data = @file_get_contents( $path );
405
- if ( $original_data === false )
406
- $original_data = '';
407
-
408
- $data = $original_data;
409
-
410
- if ( $has_wpsc = Util_Rule::has_rules( $data, W3TC_MARKER_BEGIN_PGCACHE_WPSC, W3TC_MARKER_END_PGCACHE_WPSC ) )
411
- $data = Util_Rule::erase_rules( $data, W3TC_MARKER_BEGIN_PGCACHE_WPSC, W3TC_MARKER_END_PGCACHE_WPSC );
412
-
413
- $rules = $this->rules_core_generate( $config );
414
- $rules_missing = ( strstr( Util_Rule::clean_rules( $data ), Util_Rule::clean_rules( $rules ) ) === false );
415
-
416
-
417
- if ( !$has_wpsc && !$rules_missing )
418
- return; // modification of file not required
419
-
420
-
421
- $replace_start = strpos( $data, W3TC_MARKER_BEGIN_PGCACHE_CORE );
422
- $replace_end = strpos( $data, W3TC_MARKER_END_PGCACHE_CORE );
423
-
424
- if ( $replace_start !== false && $replace_end !== false && $replace_start < $replace_end ) {
425
- $replace_length = $replace_end - $replace_start +
426
- strlen( W3TC_MARKER_END_PGCACHE_CORE ) + 1;
427
- } else {
428
- $replace_start = false;
429
- $replace_length = 0;
430
-
431
- $search = array(
432
  W3TC_MARKER_BEGIN_BROWSERCACHE_NO404WP => 0,
433
  W3TC_MARKER_BEGIN_WORDPRESS => 0,
434
  W3TC_MARKER_END_MINIFY_CORE =>
435
- strlen( W3TC_MARKER_END_MINIFY_CORE ) + 1,
436
  W3TC_MARKER_END_BROWSERCACHE_CACHE =>
437
- strlen( W3TC_MARKER_END_BROWSERCACHE_CACHE ) + 1,
438
  W3TC_MARKER_END_PGCACHE_CACHE =>
439
- strlen( W3TC_MARKER_END_PGCACHE_CACHE ) + 1,
440
  W3TC_MARKER_END_MINIFY_CACHE =>
441
- strlen( W3TC_MARKER_END_MINIFY_CACHE ) + 1
442
- );
443
-
444
- foreach ( $search as $string => $length ) {
445
- $replace_start = strpos( $data, $string );
446
-
447
- if ( $replace_start !== false ) {
448
- $replace_start += $length;
449
- break;
450
- }
451
- }
452
- }
453
-
454
- if ( $replace_start !== false ) {
455
- $data = Util_Rule::trim_rules( substr_replace( $data, $rules,
456
- $replace_start, $replace_length ) );
457
- } else {
458
- $data = Util_Rule::trim_rules( $data . $rules );
459
- }
460
-
461
- try {
462
- Util_WpFile::write_to_file( $path, $data );
463
- } catch ( Util_WpFile_FilesystemOperationException $ex ) {
464
- if ( $has_wpsc )
465
- $exs->push( new Util_WpFile_FilesystemModifyException(
466
- $ex->getMessage(), $ex->credentials_form(),
467
- sprintf( __( 'Edit file <strong>%s</strong> and remove all lines between and including
468
- <strong>%s</strong> and <strong>%s</strong> markers.', 'w3-total-cache' )
469
- , $path
470
- , W3TC_MARKER_BEGIN_PGCACHE_WPSC
471
- , W3TC_MARKER_END_PGCACHE_WPSC
472
- ), $path ) );
473
-
474
- if ( $rules_missing ) {
475
- if ( strpos( $data, W3TC_MARKER_BEGIN_PGCACHE_CORE ) !== false )
476
- $exs->push( new Util_WpFile_FilesystemModifyException(
477
- $ex->getMessage(), $ex->credentials_form(),
478
- sprintf( __( 'Edit file <strong>%s</strong> and replace all lines between and including
479
- <strong>%s</strong> and <strong>%s</strong> markers with:', 'w3-total-cache' )
480
- , $path
481
- , W3TC_MARKER_BEGIN_PGCACHE_CORE
482
- , W3TC_MARKER_END_PGCACHE_CORE
483
- ), $path, $rules ) );
484
- else
485
- $exs->push( new Util_WpFile_FilesystemModifyException(
486
- $ex->getMessage(), $ex->credentials_form(),
487
- sprintf( __( 'Edit file <strong>%s</strong> and add the following rules above the WordPress
488
- directives:' )
489
- , $path
490
- ), $path, $rules ) );
491
- }
492
- return;
493
- }
494
-
495
- Util_Rule::after_rules_modified();
496
  }
497
 
498
  /**
@@ -604,7 +526,9 @@ class PgCache_Environment {
604
  /**
605
  * Set accept query strings
606
  */
607
- $w3tc_query_strings = $config->get_array( 'pgcache.accept.qs' );
 
 
608
  Util_Rule::array_trim( $w3tc_query_strings );
609
 
610
  if ( !empty( $w3tc_query_strings ) ) {
@@ -614,10 +538,21 @@ class PgCache_Environment {
614
  $rules .= " RewriteRule ^ - [E=W3TC_QUERY_STRING:%{QUERY_STRING}]\n";
615
 
616
  foreach ( $w3tc_query_strings as $query ) {
617
- $query .= ( strpos( $query, '=' ) === false ? '=.*?' : '' );
618
- $rules .= " RewriteCond %{ENV:W3TC_QUERY_STRING} ^(.*?&|)" .
619
- $query . "(&.*|)$ [NC]\n";
620
- $rules .= " RewriteRule ^ - [E=W3TC_QUERY_STRING:%1%2]\n";
 
 
 
 
 
 
 
 
 
 
 
621
  }
622
 
623
  $rules .= " RewriteCond %{ENV:W3TC_QUERY_STRING} ^&+$\n";
@@ -793,6 +728,9 @@ class PgCache_Environment {
793
  $uri_prefix = $cache_path . '/%{HTTP_HOST}/%{REQUEST_URI}/' .
794
  '_index' . $env_W3TC_UA . $env_W3TC_REF . $env_W3TC_COOKIE .
795
  $env_W3TC_SSL . $env_W3TC_PREVIEW;
 
 
 
796
  $switch = " -" . ( $config->get_boolean( 'pgcache.file.nfs' ) ? 'F' : 'f' );
797
 
798
  $document_root = Util_Rule::apache_docroot_variable();
@@ -903,7 +841,10 @@ class PgCache_Environment {
903
  /**
904
  * Set accept query strings
905
  */
906
- $w3tc_query_strings = $config->get_array( 'pgcache.accept.qs' );
 
 
 
907
  Util_Rule::array_trim( $w3tc_query_strings );
908
 
909
  if ( !empty( $w3tc_query_strings ) ) {
@@ -913,10 +854,21 @@ class PgCache_Environment {
913
  $rules .= "set \$w3tc_query_string \$query_string;\n";
914
 
915
  foreach ( $w3tc_query_strings as $query ) {
916
- $query .= ( strpos( $query, '=' ) === false ? '=.*?' : '' );
917
- $rules .= "if (\$w3tc_query_string ~* \"^(.*?&|)" . $query . "(&.*|)$\") {\n";
918
- $rules .= " set \$w3tc_query_string $1$2;\n";
919
- $rules .= "}\n";
 
 
 
 
 
 
 
 
 
 
 
920
  }
921
 
922
  $rules .= "if (\$w3tc_query_string ~ ^[?&]+$) {\n";
@@ -1192,8 +1144,9 @@ class PgCache_Environment {
1192
 
1193
  $cache_path = str_replace( Util_Environment::document_root(), '',
1194
  $cache_dir );
1195
- $uri_prefix = $cache_path . "/\$http_host/$env_request_uri/_index" .
1196
- $key_postfix;
 
1197
 
1198
  if ( !$config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
1199
  $env_w3tc_ext = '.html';
@@ -1516,85 +1469,17 @@ class PgCache_Environment {
1516
  $browsercache = $config->get_boolean( 'browsercache.enabled' );
1517
  $brotli = ( $browsercache && $config->get_boolean( 'browsercache.html.brotli' ) );
1518
  $compression = ( $browsercache && $config->get_boolean( 'browsercache.html.compression' ) );
1519
- $expires = ( $browsercache && $config->get_boolean( 'browsercache.html.expires' ) );
1520
- $lifetime = ( $browsercache ? $config->get_integer( 'browsercache.html.lifetime' ) : 0 );
1521
- $cache_control = ( $browsercache && $config->get_boolean( 'browsercache.html.cache.control' ) );
1522
- $w3tc = ( $browsercache && $config->get_integer( 'browsercache.html.w3tc' ) );
1523
- $hsts = ( $browsercache && $config->get_boolean( 'browsercache.hsts' ) );
1524
 
 
 
1525
  $common_rules = '';
1526
-
1527
- if ( $expires ) {
1528
- $common_rules .= " expires modified " . $lifetime . "s;\n";
1529
- }
1530
-
1531
- if ( $w3tc ) {
1532
- $common_rules .= " add_header X-Powered-By \"" .
1533
- Util_Environment::w3tc_header() . "\";\n";
1534
- }
1535
-
1536
- if ( $hsts ) {
1537
- $common_rules .= " add_header Strict-Transport-Security \"max-age=31536000; preload\";\n";
1538
- }
1539
- if ( $expires ) {
1540
- $common_rules .= " add_header Vary \"Accept-Encoding, Cookie\";\n";
1541
- }
1542
-
1543
- if ( $cache_control ) {
1544
- $cache_policy = $config->get_string( 'browsercache.html.cache.policy' );
1545
-
1546
- switch ( $cache_policy ) {
1547
- case 'cache':
1548
- $common_rules .= " add_header Pragma \"public\";\n";
1549
- $common_rules .= " add_header Cache-Control \"public\";\n";
1550
- break;
1551
-
1552
- case 'cache_public_maxage':
1553
- $common_rules .= " add_header Pragma \"public\";\n";
1554
-
1555
- if ( $expires ) {
1556
- $common_rules .= " add_header Cache-Control \"public\";\n";
1557
- } else {
1558
- $common_rules .= " add_header Cache-Control \"max-age=" . $lifetime . ", public\";\n";
1559
- }
1560
- break;
1561
-
1562
- case 'cache_validation':
1563
- $common_rules .= " add_header Pragma \"public\";\n";
1564
- $common_rules .= " add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n";
1565
- break;
1566
-
1567
- case 'cache_noproxy':
1568
- $common_rules .= " add_header Pragma \"public\";\n";
1569
- $common_rules .= " add_header Cache-Control \"private, must-revalidate\";\n";
1570
- break;
1571
-
1572
- case 'cache_maxage':
1573
- $common_rules .= " add_header Pragma \"public\";\n";
1574
-
1575
- if ( $expires ) {
1576
- $common_rules .= " add_header Cache-Control \"public, must-revalidate, proxy-revalidate\";\n";
1577
- } else {
1578
- $common_rules .= " add_header Cache-Control \"max-age=" . $lifetime . ", public, must-revalidate, proxy-revalidate\";\n";
1579
- }
1580
- break;
1581
-
1582
- case 'no_cache':
1583
- $common_rules .= " add_header Pragma \"no-cache\";\n";
1584
- $common_rules .= " add_header Cache-Control \"max-age=0, private, no-store, no-cache, must-revalidate\";\n";
1585
- break;
1586
- }
1587
  }
1588
 
1589
  $rules = '';
1590
  $rules .= W3TC_MARKER_BEGIN_PGCACHE_CACHE . "\n";
1591
 
1592
- if ( !empty( $common_rules ) ) {
1593
- $rules .= "location ~ " . $cache_dir . ".*html$ {\n";
1594
- $rules .= $common_rules;
1595
- $rules .= "}\n";
1596
- }
1597
-
1598
  if ( $brotli ) {
1599
  $maybe_xml = '';
1600
  if ($config->get_boolean('pgcache.cache.nginx_handle_xml')) {
@@ -1607,8 +1492,8 @@ class PgCache_Environment {
1607
  $rules .= " brotli off;\n";
1608
  $rules .= " types {" . $maybe_xml . "}\n";
1609
  $rules .= " default_type text/html;\n";
1610
- $rules .= $common_rules;
1611
  $rules .= " add_header Content-Encoding br;\n";
 
1612
  $rules .= "}\n";
1613
  }
1614
 
@@ -1624,8 +1509,8 @@ class PgCache_Environment {
1624
  $rules .= " gzip off;\n";
1625
  $rules .= " types {" . $maybe_xml . "}\n";
1626
  $rules .= " default_type text/html;\n";
1627
- $rules .= $common_rules;
1628
  $rules .= " add_header Content-Encoding gzip;\n";
 
1629
  $rules .= "}\n";
1630
  }
1631
 
397
  * returns true if modifications has been made
398
  */
399
  private function rules_core_add( $config, $exs ) {
400
+ Util_Rule::add_rules( $exs, Util_Rule::get_pgcache_rules_core_path(),
401
+ $this->rules_core_generate( $config ),
402
+ W3TC_MARKER_BEGIN_PGCACHE_CORE,
403
+ W3TC_MARKER_END_PGCACHE_CORE,
404
+ array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  W3TC_MARKER_BEGIN_BROWSERCACHE_NO404WP => 0,
406
  W3TC_MARKER_BEGIN_WORDPRESS => 0,
407
  W3TC_MARKER_END_MINIFY_CORE =>
408
+ strlen( W3TC_MARKER_END_MINIFY_CORE ) + 1,
409
  W3TC_MARKER_END_BROWSERCACHE_CACHE =>
410
+ strlen( W3TC_MARKER_END_BROWSERCACHE_CACHE ) + 1,
411
  W3TC_MARKER_END_PGCACHE_CACHE =>
412
+ strlen( W3TC_MARKER_END_PGCACHE_CACHE ) + 1,
413
  W3TC_MARKER_END_MINIFY_CACHE =>
414
+ strlen( W3TC_MARKER_END_MINIFY_CACHE ) + 1
415
+ ),
416
+ true
417
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  }
419
 
420
  /**
526
  /**
527
  * Set accept query strings
528
  */
529
+ $w3tc_query_strings = apply_filters(
530
+ 'w3tc_pagecache_rules_apache_accept_qs',
531
+ $config->get_array( 'pgcache.accept.qs' ) );
532
  Util_Rule::array_trim( $w3tc_query_strings );
533
 
534
  if ( !empty( $w3tc_query_strings ) ) {
538
  $rules .= " RewriteRule ^ - [E=W3TC_QUERY_STRING:%{QUERY_STRING}]\n";
539
 
540
  foreach ( $w3tc_query_strings as $query ) {
541
+ $query_rules = array();
542
+ if ( strpos( $query, '=' ) === false ) {
543
+ $query_rules[] = 'RewriteCond %{ENV:W3TC_QUERY_STRING} ^(.*?&|)' .
544
+ $query . '(=[^&]*)?(&.*|)$ [NC]';
545
+ $query_rules[] = 'RewriteRule ^ - [E=W3TC_QUERY_STRING:%1%3]';
546
+ } else {
547
+ $query_rules[] = 'RewriteCond %{ENV:W3TC_QUERY_STRING} ^(.*?&|)' .
548
+ $query . '(&.*|)$ [NC]';
549
+ $query_rules[] = 'RewriteRule ^ - [E=W3TC_QUERY_STRING:%1%2]';
550
+ }
551
+
552
+ $query_rules = apply_filters(
553
+ 'w3tc_pagecache_rules_apache_accept_qs_rules',
554
+ $query_rules, $query );
555
+ $rules .= ' ' . implode( "\n ", $query_rules ) . "\n";
556
  }
557
 
558
  $rules .= " RewriteCond %{ENV:W3TC_QUERY_STRING} ^&+$\n";
728
  $uri_prefix = $cache_path . '/%{HTTP_HOST}/%{REQUEST_URI}/' .
729
  '_index' . $env_W3TC_UA . $env_W3TC_REF . $env_W3TC_COOKIE .
730
  $env_W3TC_SSL . $env_W3TC_PREVIEW;
731
+ $uri_prefix = apply_filters( 'w3tc_pagecache_rules_apache_uri_prefix',
732
+ $uri_prefix );
733
+
734
  $switch = " -" . ( $config->get_boolean( 'pgcache.file.nfs' ) ? 'F' : 'f' );
735
 
736
  $document_root = Util_Rule::apache_docroot_variable();
841
  /**
842
  * Set accept query strings
843
  */
844
+ $w3tc_query_strings = apply_filters(
845
+ 'w3tc_pagecache_rules_nginx_accept_qs',
846
+ $config->get_array( 'pgcache.accept.qs' ) );
847
+
848
  Util_Rule::array_trim( $w3tc_query_strings );
849
 
850
  if ( !empty( $w3tc_query_strings ) ) {
854
  $rules .= "set \$w3tc_query_string \$query_string;\n";
855
 
856
  foreach ( $w3tc_query_strings as $query ) {
857
+ $query_rules = array();
858
+ if ( strpos( $query, '=' ) === false ) {
859
+ $query_rules[] = 'if ($w3tc_query_string ~* "^(.*?&|)' . $query . '(=[^&]*)?(&.*|)$") {';
860
+ $query_rules[] = ' set $w3tc_query_string $1$3;';
861
+ $query_rules[] = '}';
862
+ } else {
863
+ $query_rules[] = 'if ($w3tc_query_string ~* "^(.*?&|)' . $query . '(&.*|)$") {';
864
+ $query_rules[] = ' set $w3tc_query_string $1$2;';
865
+ $query_rules[] = '}';
866
+ }
867
+
868
+ $query_rules = apply_filters(
869
+ 'w3tc_pagecache_rules_nginx_accept_qs_rules',
870
+ $query_rules, $query );
871
+ $rules .= implode( "\n", $query_rules ) . "\n";
872
  }
873
 
874
  $rules .= "if (\$w3tc_query_string ~ ^[?&]+$) {\n";
1144
 
1145
  $cache_path = str_replace( Util_Environment::document_root(), '',
1146
  $cache_dir );
1147
+ $uri_prefix = "$cache_path/\$http_host/$env_request_uri/_index$key_postfix";
1148
+ $uri_prefix = apply_filters( 'w3tc_pagecache_rules_nginx_uri_prefix',
1149
+ $uri_prefix );
1150
 
1151
  if ( !$config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
1152
  $env_w3tc_ext = '.html';
1469
  $browsercache = $config->get_boolean( 'browsercache.enabled' );
1470
  $brotli = ( $browsercache && $config->get_boolean( 'browsercache.html.brotli' ) );
1471
  $compression = ( $browsercache && $config->get_boolean( 'browsercache.html.compression' ) );
 
 
 
 
 
1472
 
1473
+ $common_rules_a = Dispatcher::nginx_rules_for_browsercache_section(
1474
+ $config, 'html', true );
1475
  $common_rules = '';
1476
+ if ( !empty( $common_rules_a ) ) {
1477
+ $common_rules = ' ' . implode( "\n ", $common_rules_a ) . "\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1478
  }
1479
 
1480
  $rules = '';
1481
  $rules .= W3TC_MARKER_BEGIN_PGCACHE_CACHE . "\n";
1482
 
 
 
 
 
 
 
1483
  if ( $brotli ) {
1484
  $maybe_xml = '';
1485
  if ($config->get_boolean('pgcache.cache.nginx_handle_xml')) {
1492
  $rules .= " brotli off;\n";
1493
  $rules .= " types {" . $maybe_xml . "}\n";
1494
  $rules .= " default_type text/html;\n";
 
1495
  $rules .= " add_header Content-Encoding br;\n";
1496
+ $rules .= $common_rules;
1497
  $rules .= "}\n";
1498
  }
1499
 
1509
  $rules .= " gzip off;\n";
1510
  $rules .= " types {" . $maybe_xml . "}\n";
1511
  $rules .= " default_type text/html;\n";
 
1512
  $rules .= " add_header Content-Encoding gzip;\n";
1513
+ $rules .= $common_rules;
1514
  $rules .= "}\n";
1515
  }
1516
 
Root_AdminActivation.php CHANGED
@@ -39,8 +39,6 @@ class Root_AdminActivation {
39
  $config = Dispatcher::config();
40
  $e->fix_on_event( $config, 'activate' );
41
 
42
- Generic_AdminLinks::link_update( $config );
43
-
44
  // try to save config file if needed, optional thing so exceptions
45
  // hidden
46
  if ( !ConfigUtil::is_item_exists( 0, false ) ) {
@@ -74,8 +72,6 @@ class Root_AdminActivation {
74
  try {
75
  $e = Dispatcher::component( 'Root_Environment' );
76
  $e->fix_after_deactivation();
77
-
78
- Generic_AdminLinks::link_delete();
79
  } catch ( Util_Environment_Exceptions $exs ) {
80
  $r = Util_Activation::parse_environment_exceptions( $exs );
81
 
39
  $config = Dispatcher::config();
40
  $e->fix_on_event( $config, 'activate' );
41
 
 
 
42
  // try to save config file if needed, optional thing so exceptions
43
  // hidden
44
  if ( !ConfigUtil::is_item_exists( 0, false ) ) {
72
  try {
73
  $e = Dispatcher::component( 'Root_Environment' );
74
  $e->fix_after_deactivation();
 
 
75
  } catch ( Util_Environment_Exceptions $exs ) {
76
  $r = Util_Activation::parse_environment_exceptions( $exs );
77
 
Root_Loader.php CHANGED
@@ -127,8 +127,6 @@ class Root_Loader {
127
  $c = Dispatcher::config();
128
  $extensions = $c->get_array( 'extensions.active' );
129
 
130
- $loaded = array();
131
-
132
  $frontend = $c->get_array( 'extensions.active_frontend' );
133
  foreach ( $frontend as $extension => $nothing ) {
134
  if ( isset( $extensions[$extension] ) ) {
@@ -136,10 +134,9 @@ class Root_Loader {
136
  $filename = W3TC_EXTENSION_DIR . '/' .
137
  str_replace( '..', '', trim( $path, '/' ) );
138
 
139
- if ( file_exists( $filename ) && !isset( $loaded[$filename] ) )
140
- include $filename;
141
-
142
- $loaded[$filename] = '*';
143
  }
144
  }
145
 
@@ -149,12 +146,17 @@ class Root_Loader {
149
  $filename = W3TC_EXTENSION_DIR . '/' .
150
  str_replace( '..', '', trim( $path, '/' ) );
151
 
152
- if ( file_exists( $filename ) && !isset( $loaded[$filename] ) )
153
- include $filename;
154
-
155
- $loaded[$filename] = '*';
156
  }
157
  }
 
 
 
 
 
 
158
  }
159
  }
160
 
127
  $c = Dispatcher::config();
128
  $extensions = $c->get_array( 'extensions.active' );
129
 
 
 
130
  $frontend = $c->get_array( 'extensions.active_frontend' );
131
  foreach ( $frontend as $extension => $nothing ) {
132
  if ( isset( $extensions[$extension] ) ) {
134
  $filename = W3TC_EXTENSION_DIR . '/' .
135
  str_replace( '..', '', trim( $path, '/' ) );
136
 
137
+ if ( file_exists( $filename ) ) {
138
+ include_once( $filename );
139
+ }
 
140
  }
141
  }
142
 
146
  $filename = W3TC_EXTENSION_DIR . '/' .
147
  str_replace( '..', '', trim( $path, '/' ) );
148
 
149
+ if ( file_exists( $filename ) ) {
150
+ include_once( $filename );
151
+ }
 
152
  }
153
  }
154
+
155
+ w3tc_do_action( 'wp_loaded' );
156
+ do_action( 'w3tc_extension_load' );
157
+ if ( is_admin() ) {
158
+ do_action( 'w3tc_extension_load_admin' );
159
+ }
160
  }
161
  }
162
 
Util_Admin.php CHANGED
@@ -615,11 +615,6 @@ class Util_Admin {
615
  $environment = Dispatcher::component( 'Root_Environment' );
616
  $environment->fix_on_event( $new_config, 'config_change', $old_config );
617
 
618
- /**
619
- * Update support us option
620
- */
621
- Generic_AdminLinks::link_update( $current_config );
622
-
623
  /**
624
  * Auto upload browsercache files to CDN
625
  */
615
  $environment = Dispatcher::component( 'Root_Environment' );
616
  $environment->fix_on_event( $new_config, 'config_change', $old_config );
617
 
 
 
 
 
 
618
  /**
619
  * Auto upload browsercache files to CDN
620
  */
Util_Rule.php CHANGED
@@ -224,36 +224,59 @@ class Util_Rule {
224
  /**
225
  *
226
  *
227
- * @param Util_Environment_Exceptions $exs
228
- * @param string $path
229
- * @param string $rules
230
- * @param string $start
231
- * @param string $end
232
- * @param array $order
 
 
233
  */
234
- static public function add_rules( $exs, $path, $rules, $start, $end, $order ) {
235
- if ( empty( $path ) )
 
236
  return;
 
237
 
238
  $data = @file_get_contents( $path );
239
-
240
- if ( $data === false )
241
  $data = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
  if ( empty( $rules ) ) {
244
- $rules_present = ( strpos( $data, $start ) !== false );
245
- if ( !$rules_present )
 
246
  return;
 
247
  } else {
 
248
  $rules_missing = ( strstr( Util_Rule::clean_rules( $data ), Util_Rule::clean_rules( $rules ) ) === false );
249
- if ( !$rules_missing )
250
  return;
 
251
  }
252
 
253
  $replace_start = strpos( $data, $start );
254
  $replace_end = strpos( $data, $end );
255
 
256
  if ( $replace_start !== false && $replace_end !== false && $replace_start < $replace_end ) {
 
257
  $replace_length = $replace_end - $replace_start + strlen( $end ) + 1;
258
  } else {
259
  $replace_start = false;
@@ -274,28 +297,31 @@ class Util_Rule {
274
  if ( $replace_start !== false ) {
275
  $data = Util_Rule::trim_rules( substr_replace( $data, $rules, $replace_start, $replace_length ) );
276
  } else {
277
- $data = Util_Rule::trim_rules( $data . $rules );
278
  }
279
 
280
  if ( strpos( $path, W3TC_CACHE_DIR ) === false || Util_Environment::is_nginx() ) {
 
281
  try {
282
  Util_WpFile::write_to_file( $path, $data );
283
  } catch ( Util_WpFile_FilesystemOperationException $ex ) {
284
- if ( $replace_start !== false )
285
- $exs->push( new Util_WpFile_FilesystemModifyException(
286
- $ex->getMessage(), $ex->credentials_form(),
287
- sprintf( __( 'Edit file <strong>%s
288
- </strong> and replace all lines between and including <strong>%s</strong> and
289
- <strong>%s</strong> markers with:', 'w3-total-caceh' ), $path, $start, $end ), $path, $rules ) );
290
- else
291
- $exs->push( new Util_WpFile_FilesystemModifyException(
292
- $ex->getMessage(), $ex->credentials_form(),
293
- sprintf( __( 'Edit file <strong>%s</strong> and add the following rules
294
- above the WordPress directives:', 'w3-total-cache' ),
295
- $path ), $path, $rules ) );
 
296
  return;
297
  }
298
  } else {
 
299
  if ( !@file_exists( dirname( $path ) ) ) {
300
  Util_File::mkdir_from( dirname( $path ), W3TC_CACHE_DIR );
301
  }
@@ -351,7 +377,7 @@ class Util_Rule {
351
  $exs->push( new Util_WpFile_FilesystemModifyException(
352
  $ex->getMessage(), $ex->credentials_form(),
353
  sprintf( __( 'Edit file <strong>%s</strong> and remove all lines between and including <strong>%s</strong>
354
- and <strong>%s</strong> markers.', 'w3-total-cache' ), $path, $start, $end ), $path ) );
355
  }
356
  }
357
 
@@ -411,4 +437,30 @@ class Util_Rule {
411
  else
412
  return '%{DOCUMENT_ROOT}';
413
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  }
224
  /**
225
  *
226
  *
227
+ * @param Util_Environment_Exceptions $exs exceptions to fill on error
228
+ * @param string $path filename of rules file to modify
229
+ * @param string $rules rules to add
230
+ * @param string $start start marker
231
+ * @param string $end end marker
232
+ * @param array $order order where to place if some marker exists
233
+ * @param boolean $remove_wpsc if WPSC rules should be removed to avoid
234
+ * inconsistent rules generation
235
  */
236
+ static public function add_rules( $exs, $path, $rules, $start, $end, $order,
237
+ $remove_wpsc = false ) {
238
+ if ( empty( $path ) ) {
239
  return;
240
+ }
241
 
242
  $data = @file_get_contents( $path );
243
+ if ( empty( $data ) ) {
 
244
  $data = '';
245
+ }
246
+
247
+ $modified = false;
248
+ if ( $remove_wpsc ) {
249
+ if ( Util_Rule::has_rules(
250
+ $data,
251
+ W3TC_MARKER_BEGIN_PGCACHE_WPSC,
252
+ W3TC_MARKER_END_PGCACHE_WPSC ) ) {
253
+ $data = Util_Rule::erase_rules(
254
+ $data,
255
+ W3TC_MARKER_BEGIN_PGCACHE_WPSC,
256
+ W3TC_MARKER_END_PGCACHE_WPSC );
257
+ $modified = true;
258
+ }
259
+ }
260
 
261
  if ( empty( $rules ) ) {
262
+ // rules removal mode
263
+ $rules_present = ( strpos( $data, $start ) !== false );
264
+ if ( !$modified && !$rules_present ) {
265
  return;
266
+ }
267
  } else {
268
+ // rules creation mode
269
  $rules_missing = ( strstr( Util_Rule::clean_rules( $data ), Util_Rule::clean_rules( $rules ) ) === false );
270
+ if ( !$modified && !$rules_missing ) {
271
  return;
272
+ }
273
  }
274
 
275
  $replace_start = strpos( $data, $start );
276
  $replace_end = strpos( $data, $end );
277
 
278
  if ( $replace_start !== false && $replace_end !== false && $replace_start < $replace_end ) {
279
+ // old rules exists, replace mode
280
  $replace_length = $replace_end - $replace_start + strlen( $end ) + 1;
281
  } else {
282
  $replace_start = false;
297
  if ( $replace_start !== false ) {
298
  $data = Util_Rule::trim_rules( substr_replace( $data, $rules, $replace_start, $replace_length ) );
299
  } else {
300
+ $data = Util_Rule::trim_rules( rtrim( $data ) . "\n" . $rules );
301
  }
302
 
303
  if ( strpos( $path, W3TC_CACHE_DIR ) === false || Util_Environment::is_nginx() ) {
304
+ // writing to system rules file, may be potentially write-protected
305
  try {
306
  Util_WpFile::write_to_file( $path, $data );
307
  } catch ( Util_WpFile_FilesystemOperationException $ex ) {
308
+ if ( $replace_start !== false ) {
309
+ $message = sprintf( __( 'Edit file <strong>%s</strong> and replace all lines between and including <strong>%s</strong> and <strong>%s</strong> markers with:',
310
+ 'w3-total-caceh' ), $path, $start, $end );
311
+ } else {
312
+ $message = sprintf( __( 'Edit file <strong>%s</strong> and add the following rules above the WordPress directives:',
313
+ 'w3-total-cache' ), $path );
314
+ }
315
+
316
+ $ex = new Util_WpFile_FilesystemModifyException(
317
+ $ex->getMessage(), $ex->credentials_form(),
318
+ $message, $path, $rules );
319
+
320
+ $exs->push( $ex );
321
  return;
322
  }
323
  } else {
324
+ // writing to own rules file in cache folder
325
  if ( !@file_exists( dirname( $path ) ) ) {
326
  Util_File::mkdir_from( dirname( $path ), W3TC_CACHE_DIR );
327
  }
377
  $exs->push( new Util_WpFile_FilesystemModifyException(
378
  $ex->getMessage(), $ex->credentials_form(),
379
  sprintf( __( 'Edit file <strong>%s</strong> and remove all lines between and including <strong>%s</strong>
380
+ and <strong>%s</strong> markers.', 'w3-total-cache' ), $path, $start, $end ), $path ) );
381
  }
382
  }
383
 
437
  else
438
  return '%{DOCUMENT_ROOT}';
439
  }
440
+
441
+
442
+
443
+ /**
444
+ * Takes an array of extensions single per row and/or extensions delimited by |
445
+ *
446
+ * @param unknown $extensions
447
+ * @param unknown $ext
448
+ * @return array
449
+ */
450
+ static public function remove_extension_from_list( $extensions, $ext ) {
451
+ for ( $i = 0; $i < sizeof( $extensions ); $i++ ) {
452
+ if ( $extensions[$i] == $ext ) {
453
+ unset( $extensions[$i] );
454
+ return $extensions;
455
+ } elseif ( strpos( $extensions[$i], $ext ) !== false &&
456
+ strpos( $extensions[$i], '|' ) !== false ) {
457
+ $exts = explode( '|', $extensions[$i] );
458
+ $key = array_search( $ext, $exts );
459
+ unset( $exts[$key] );
460
+ $extensions[$i] = implode( '|', $exts );
461
+ return $extensions;
462
+ }
463
+ }
464
+ return $extensions;
465
+ }
466
  }
Util_RuleSnippet.php DELETED
@@ -1,99 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- class Util_RuleSnippet {
5
- /**
6
- * Return canonical rules
7
- *
8
- * @param bool $cdnftp
9
- * @return string
10
- */
11
- static public function canonical_without_location( $cdnftp = false,
12
- $add_header_rules, $cors_header ) {
13
- $rules = '';
14
-
15
- switch ( true ) {
16
- case Util_Environment::is_apache():
17
- case Util_Environment::is_litespeed():
18
- $host = ( $cdnftp ) ? Util_Environment::home_url_host() : '%{HTTP_HOST}';
19
- $rules .= " <IfModule mod_rewrite.c>\n";
20
- $rules .= " RewriteEngine On\n";
21
- $rules .= " RewriteCond %{HTTPS} !=on\n";
22
- $rules .= " RewriteRule .* - [E=CANONICAL:http://$host%{REQUEST_URI},NE]\n";
23
- $rules .= " RewriteCond %{HTTPS} =on\n";
24
- $rules .= " RewriteRule .* - [E=CANONICAL:https://$host%{REQUEST_URI},NE]\n";
25
- $rules .= " </IfModule>\n";
26
- $rules .= " <IfModule mod_headers.c>\n";
27
- $rules .= ' Header set Link "<%{CANONICAL}e>; rel=\"canonical\""' . "\n";
28
- $rules .= " </IfModule>\n";
29
- break;
30
-
31
- case Util_Environment::is_nginx():
32
- $home = ( $cdnftp ) ? Util_Environment::home_url_host() : '$host';
33
- // nginx overrides all add_header directives when context inherited
34
- // so add_header rules has to be repeated
35
- $link_header = ' add_header Link "<$scheme://' .
36
- $home . '$uri>; rel=\"canonical\"";' . "\n";
37
-
38
- $rules .= $link_header;
39
-
40
- if ( $cors_header ) {
41
- $rules .=
42
- ' if ($request_uri ~ ^[^?]*\\.(ttf|ttc|otf|eot|woff|woff2|font.css)(\\?|$)) {' .
43
- "\n " . $link_header .
44
- " " .
45
- str_replace( "\n", "\n ", $add_header_rules ) .
46
- " add_header Access-Control-Allow-Origin \"*\";\n" .
47
- " }\n";
48
- }
49
-
50
- break;
51
- }
52
-
53
- return $rules;
54
- }
55
-
56
- /**
57
- * Returns canonical rules
58
- *
59
- * @param bool $cdnftp
60
- * @return string
61
- */
62
- static public function canonical( $cdnftp = false, $cors_header ) {
63
- $rules = '';
64
-
65
- $mime_types = self::_get_other_types();
66
- $extensions = array_keys( $mime_types );
67
-
68
- switch ( true ) {
69
- case Util_Environment::is_apache():
70
- case Util_Environment::is_litespeed():
71
- $extensions_lowercase = array_map( 'strtolower', $extensions );
72
- $extensions_uppercase = array_map( 'strtoupper', $extensions );
73
- $rules .= "<FilesMatch \"\\.(" . implode( '|',
74
- array_merge( $extensions_lowercase, $extensions_uppercase ) ) . ")$\">\n";
75
- $rules .= self::canonical_without_location( $cdnftp, '', $cors_header );
76
- $rules .= "</FilesMatch>\n";
77
- break;
78
-
79
- case Util_Environment::is_nginx():
80
- $rules .= "location ~ \.(" . implode( '|', $extensions ) . ")$ {\n";
81
- $rules .= self::canonical_without_location( $cdnftp, '', $cors_header );
82
- $rules .= "}\n";
83
- break;
84
- }
85
-
86
- return $rules;
87
- }
88
-
89
- /**
90
- * Returns other mime types
91
- *
92
- * @return array
93
- */
94
- static private function _get_other_types() {
95
- $mime_types = include W3TC_INC_DIR . '/mime/other.php';
96
- return $mime_types;
97
- }
98
-
99
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Varnish_Flush.php CHANGED
@@ -96,7 +96,7 @@ class Varnish_Flush {
96
  $request_uri = $path . ( $query != '' ? '?' . $query : '' );
97
 
98
  list( $varnish_host, $varnish_port ) =
99
- Util_Content::endpoint_to_host_port( $server, 80 );
100
 
101
  // if url host is the same as varnish server - we can use regular
102
  // wordpress http infrastructure, otherwise custom request should be
96
  $request_uri = $path . ( $query != '' ? '?' . $query : '' );
97
 
98
  list( $varnish_host, $varnish_port ) =
99
+ Util_Content::endpoint_to_host_port( $varnish_server, 80 );
100
 
101
  // if url host is the same as varnish server - we can use regular
102
  // wordpress http infrastructure, otherwise custom request should be
inc/lightbox/support_us.php CHANGED
@@ -68,19 +68,6 @@ echo Util_Ui::hidden(
68
  '0' ) ?>
69
  </label>
70
  </li>
71
- <li>
72
- <label>
73
- Link to us: <br />
74
- <div class="styled-select">
75
- <select name="support" class="w3tc-size select">
76
- <option value=""><?php esc_attr_e( 'select location', 'w3-total-cache' ); ?></option>
77
- <?php foreach ( $supports as $support_id => $support_name ): ?>
78
- <option value="<?php echo esc_attr( $support_id ); ?>"<?php echo selected( $this->_config->get_string( 'common.support' ), $support_id ); ?>><?php echo htmlspecialchars( $support_name ); ?></option>
79
- <?php endforeach; ?>
80
- </select>
81
- </div>
82
- </label>
83
- </li>
84
  </ul>
85
  <p>
86
  <label class="w3tc_signup_email" for="email">Don't forget to join our newsletter:<br />
68
  '0' ) ?>
69
  </label>
70
  </li>
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  </ul>
72
  <p>
73
  <label class="w3tc_signup_email" for="email">Don't forget to join our newsletter:<br />
inc/widget/latest_ajax.php CHANGED
@@ -7,9 +7,11 @@ if ( !defined( 'W3TC' ) )
7
  ?>
8
  <?php foreach ( $items as $item ): ?>
9
  <h4>
10
- <a href="<?php echo $item['link']; ?>"><?php echo $item['title']; ?></a>
 
 
11
  </h4>
12
- <?php endforeach; ?>
13
 
14
  <p style="text-align: center;">
15
  <a href="<?php echo W3TC_FEED_URL; ?>" target="_blank">View Feed</a>
7
  ?>
8
  <?php foreach ( $items as $item ): ?>
9
  <h4>
10
+ <a href="<?php echo esc_url( $item['link'] ) ?>">
11
+ <?php echo esc_html( wp_strip_all_tags( $item['title'] ) ) ?>
12
+ </a>
13
  </h4>
14
+ <?php endforeach ?>
15
 
16
  <p style="text-align: center;">
17
  <a href="<?php echo W3TC_FEED_URL; ?>" target="_blank">View Feed</a>
inc/widget/latest_news_ajax.php CHANGED
@@ -7,9 +7,11 @@ if ( !defined( 'W3TC' ) )
7
  ?>
8
  <?php foreach ( $items as $item ): ?>
9
  <h4>
10
- <a href="<?php echo $item['link']; ?>"><?php echo $item['title']; ?></a>
 
 
11
  </h4>
12
- <?php endforeach; ?>
13
 
14
  <p style="text-align: center;">
15
  <a href="<?php echo W3TC_NEWS_FEED_URL; ?>" target="_blank">View Feed</a>
7
  ?>
8
  <?php foreach ( $items as $item ): ?>
9
  <h4>
10
+ <a href="<?php echo esc_url( $item['link'] ) ?>">
11
+ <?php echo esc_html( wp_strip_all_tags( $item['title'] ) ) ?>
12
+ </a>
13
  </h4>
14
+ <?php endforeach ?>
15
 
16
  <p style="text-align: center;">
17
  <a href="<?php echo W3TC_NEWS_FEED_URL; ?>" target="_blank">View Feed</a>
lib/Minify/Minify/HTML.php CHANGED
@@ -353,7 +353,7 @@ class Minify_HTML {
353
 
354
  public function _removeAttributeQuotesCallback( $m ) {
355
  // empty tag values like <div data-value=""> to <div data-value
356
- if ( empty( $m[3] ) ) {
357
  return $m[1] . $m[4];
358
  }
359
 
353
 
354
  public function _removeAttributeQuotesCallback( $m ) {
355
  // empty tag values like <div data-value=""> to <div data-value
356
+ if ( $m[3] === '' ) {
357
  return $m[1] . $m[4];
358
  }
359
 
pub/js/options.js CHANGED
@@ -1454,7 +1454,7 @@ jQuery(function() {
1454
  });
1455
 
1456
  // google analytics events
1457
- if (typeof ga != 'undefined') {
1458
  jQuery('.w3tc_error').each(function() {
1459
  var id = jQuery(this).attr('id');
1460
  var text = jQuery(this).text();
1454
  });
1455
 
1456
  // google analytics events
1457
+ if (typeof w3tc_ga != 'undefined') {
1458
  jQuery('.w3tc_error').each(function() {
1459
  var id = jQuery(this).attr('id');
1460
  var text = jQuery(this).text();
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: boldgrid, fredericktownes, maxicusc, gidomanders, bwmarkle
3
  Tags: seo, cache, caching, compression, maxcdn, nginx, varnish, redis, new relic, aws, amazon web services, s3, cloudfront, rackspace, cloudflare, azure, apache
4
  Requires at least: 3.2
5
  Tested up to: 5.3
6
- Stable tag: 0.11.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -271,6 +271,21 @@ Please reach out to all of these people and support their projects if you're so
271
 
272
  == Changelog ==
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  = 0.11.0 =
275
  * Added recommendation for BoldGrid's Total Upkeep plugin
276
  * Added new lazy loading feature
3
  Tags: seo, cache, caching, compression, maxcdn, nginx, varnish, redis, new relic, aws, amazon web services, s3, cloudfront, rackspace, cloudflare, azure, apache
4
  Requires at least: 3.2
5
  Tested up to: 5.3
6
+ Stable tag: 0.12.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
271
 
272
  == Changelog ==
273
 
274
+ = 0.12.0 =
275
+ * Added querystring based URL structures for AMP pages
276
+ * Added filter of minify options
277
+ * Added lazyload picture tag support
278
+ * Removed footer link "Support Us" option
279
+ * Improved wp_die handling
280
+ * Improved lazyload handling of content in script tags
281
+ * Improved lazyload handling of feeds
282
+ * Improved printing tags coming from feeds
283
+ * Improved handling of modified posts before wp_rewrite initialized
284
+ * Nginx rules changed a lot to avoid "location" block conflicts. That change may cause problems on some systems using non-default WordPress rules - keep a backup of your original rules
285
+ * Improved handling of .htaccess files in regard to EOF
286
+ * Fixed Varnish purging
287
+ * Fixed html minification of data tags equaling 0
288
+
289
  = 0.11.0 =
290
  * Added recommendation for BoldGrid's Total Upkeep plugin
291
  * Added new lazy loading feature
w3-total-cache-api.php CHANGED
@@ -5,7 +5,7 @@ if ( !defined( 'ABSPATH' ) ) {
5
  }
6
 
7
  define( 'W3TC', true );
8
- define( 'W3TC_VERSION', '0.11.0' );
9
  define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
10
  define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
11
  define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
@@ -631,3 +631,55 @@ function w3tc_er( $key, $default_value ) {
631
 
632
  return $default_value;
633
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  }
6
 
7
  define( 'W3TC', true );
8
+ define( 'W3TC_VERSION', '0.12.0' );
9
  define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
10
  define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
11
  define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
631
 
632
  return $default_value;
633
  }
634
+
635
+
636
+
637
+ $w3tc_actions = array();
638
+
639
+
640
+
641
+ /**
642
+ * add_action alternative used by W3TC when WP core is not available
643
+ */
644
+ function w3tc_add_action( $hook, $callback ) {
645
+ global $w3tc_actions;
646
+ if ( !isset( $w3tc_actions[$hook] ) ) {
647
+ $w3tc_actions[$hook] = array();
648
+ }
649
+
650
+ $w3tc_actions[$hook][] = $callback;
651
+ }
652
+
653
+
654
+
655
+ /**
656
+ * do_action alternative used by W3TC when WP core is not available
657
+ */
658
+ function w3tc_do_action( $hook ) {
659
+ global $w3tc_actions;
660
+ if (!empty($w3tc_actions[$hook])) {
661
+ foreach ( $w3tc_actions[$hook] as $callback ) {
662
+ call_user_func_array( $callback, array() );
663
+ }
664
+ }
665
+ }
666
+
667
+
668
+
669
+ /**
670
+ * do_action alternative used by W3TC when WP core is not available
671
+ */
672
+ function w3tc_apply_filters( $hook, $value ) {
673
+ $args = func_get_args();
674
+ array_shift( $args );
675
+
676
+ global $w3tc_actions;
677
+ if (!empty($w3tc_actions[$hook])) {
678
+ foreach ( $w3tc_actions[$hook] as $callback ) {
679
+ $value = call_user_func_array( $callback, $args );
680
+ $args[0] = $value;
681
+ }
682
+ }
683
+
684
+ return $value;
685
+ }
w3-total-cache.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: W3 Total Cache
4
  Description: The highest rated and most complete WordPress performance plugin. Dramatically improve the speed and user experience of your site. Add browser, page, object and database caching as well as minify and content delivery network (CDN) to WordPress.
5
- Version: 0.11.0
6
  Plugin URI: https://www.boldgrid.com/totalcache/
7
  Author: BoldGrid
8
  Author URI: https://www.boldgrid.com/
2
  /*
3
  Plugin Name: W3 Total Cache
4
  Description: The highest rated and most complete WordPress performance plugin. Dramatically improve the speed and user experience of your site. Add browser, page, object and database caching as well as minify and content delivery network (CDN) to WordPress.
5
+ Version: 0.12.0
6
  Plugin URI: https://www.boldgrid.com/totalcache/
7
  Author: BoldGrid
8
  Author URI: https://www.boldgrid.com/