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