W3 Total Cache - Version 0.11.0

Version Description

  • Added recommendation for BoldGrid's Total Upkeep plugin
  • Added new lazy loading feature
  • Removed New Relic extension by default for new installations
  • Updated usage of html minification and quote removal
  • Improved memcached config and added optional binary protocol setting
  • Improved process of renewing expired licenses
  • Improved page cache purging
  • Improved FAQ link by opening in new window
  • Improved detection of detect_post_id
  • Improved REST caching in relation to cache headers like X-WP-*
  • Improved Vary User-Agent header usage
  • Improved various features with AMP pages and HTTP2
  • Improved redis connection string to allow for tls://host:port format
  • Fixed file headers for Cloudfront S3 CDN
  • Fixed fatal error on with flush / SNS
  • Fixed comments with URLs within minify debug mode
  • Fixed ObjectCache statistics within footer
  • Fixed temporary hotfix with wp_die and regular output
  • Fixed fragment cache header link
  • Fixed flushing of /feed and /feed/ cache
  • Fixed js error in widget
  • Fixed fatal cache flush error caused by empty $wp_rewrite
  • Fixed path for file_generic REST caching on non-default port
  • Fixed test minify button with Closure Compiler engine
Download this release

Release Info

Developer fredericktownes
Plugin Icon 128x128 W3 Total Cache
Version 0.11.0
Comparing to
See all releases

Code changes from version 0.10.2 to 0.11.0

Files changed (87) hide show
  1. BrowserCache_Environment.php +3 -11
  2. BrowserCache_Plugin.php +70 -57
  3. Cache_File_Generic.php +42 -11
  4. Cache_Memcache.php +2 -6
  5. Cache_Memcached.php +7 -7
  6. Cache_Nginx_Memcached.php +2 -6
  7. Cache_Redis.php +9 -13
  8. CdnEngine_Azure.php +4 -10
  9. CdnEngine_Base.php +14 -71
  10. CdnEngine_Ftp.php +3 -9
  11. CdnEngine_S3.php +5 -9
  12. CdnEngine_S3_Compatible.php +2 -2
  13. Cdn_Core.php +6 -13
  14. Cdnfsd_GeneralPage_View.php +3 -3
  15. Config.php +46 -0
  16. ConfigCompiler.php +2 -0
  17. ConfigKeys.php +59 -1
  18. DbCache_Core.php +2 -1
  19. DbCache_WpdbInjection_QueryCaching.php +2 -1
  20. Enterprise_CacheFlush_MakeSnsEvent.php +6 -0
  21. Enterprise_Dbcache_WpdbInjection_Cluster.php +1 -6
  22. Enterprise_SnsServer.php +3 -0
  23. Extension_Amp_Plugin.php +65 -13
  24. Extension_FragmentCache_GeneralPage_View.php +1 -1
  25. Extension_FragmentCache_Page_View.php +26 -15
  26. Extension_FragmentCache_Plugin_Admin.php +1 -2
  27. Extension_Genesis_Plugin_Admin.php +1 -3
  28. Extension_NewRelic_Plugin_Admin.php +1 -1
  29. Extension_Wpml_Plugin_Admin.php +1 -2
  30. Generic_Page_Dashboard_View.css +8 -0
  31. Generic_Plugin.php +10 -3
  32. Generic_Plugin_Admin.php +10 -0
  33. Generic_WidgetBoldGrid.php +78 -0
  34. Generic_WidgetBoldGrid_AdminActions.php +25 -0
  35. Generic_WidgetBoldGrid_Logo.svg +1 -0
  36. Generic_WidgetBoldGrid_View.js +25 -0
  37. Generic_WidgetBoldGrid_View.php +23 -0
  38. LICENSE +339 -0
  39. LazyLoad_GeneralPage.php +34 -0
  40. LazyLoad_GeneralPage_View.php +28 -0
  41. LazyLoad_Page.php +11 -0
  42. LazyLoad_Page_View.php +67 -0
  43. LazyLoad_Plugin.php +341 -0
  44. LazyLoad_Plugin_Admin.php +36 -0
  45. Licensing_AdminActions.php +14 -5
  46. Licensing_Core.php +6 -2
  47. Licensing_Plugin_Admin.php +20 -9
  48. Minify_AutoCss.php +1 -1
  49. Minify_AutoJs.php +1 -1
  50. Minify_MinifiedFileRequestHandler.php +2 -1
  51. Minify_Plugin.php +22 -5
  52. Minify_Plugin_Admin.php +1 -0
  53. ObjectCache_Plugin.php +1 -0
  54. ObjectCache_WpObjectCache_Regular.php +33 -28
  55. PgCache_ContentGrabber.php +111 -114
  56. PgCache_Flush.php +106 -136
  57. PgCache_Plugin.php +18 -0
  58. Root_AdminActions.php +5 -4
  59. Root_AdminMenu.php +0 -9
  60. Root_Loader.php +3 -0
  61. UsageStatistics_GeneralPage_View.php +2 -2
  62. UsageStatistics_Widget.php +19 -15
  63. UsageStatistics_Widget_View_Disabled.php +1 -1
  64. Util_ConfigLabel.php +1 -0
  65. Util_Content.php +22 -0
  66. Util_Environment.php +2 -2
  67. Util_Mime.php +37 -0
  68. Util_Ui.php +88 -4
  69. Util_Widget.php +2 -2
  70. Varnish_Flush.php +21 -26
  71. inc/lightbox/upgrade.php +13 -12
  72. inc/options/common/header.php +2 -2
  73. inc/options/extensions/list.php +121 -111
  74. inc/options/minify/ccjs2.php +51 -25
  75. inc/options/minify/css.php +3 -4
  76. inc/options/minify/yuicss2.php +41 -17
  77. inc/options/parts/memcached.php +7 -0
  78. inc/options/pgcache.php +1 -2
  79. lib/Minify/Minify/HTML.php +26 -6
  80. lib/Minify/Minify/Lines.php +196 -128
  81. pub/css/options.css +30 -0
  82. pub/js/lazyload.min.js +1 -0
  83. pub/js/lazyload.version.txt +4 -0
  84. pub/js/lightbox.js +32 -13
  85. readme.txt +28 -2
  86. w3-total-cache-api.php +5 -1
  87. w3-total-cache.php +4 -4
BrowserCache_Environment.php CHANGED
@@ -101,11 +101,7 @@ class BrowserCache_Environment {
101
  * @return array
102
  */
103
  public function get_mime_types() {
104
- $a = array(
105
- 'cssjs' => include W3TC_INC_DIR . '/mime/cssjs.php',
106
- 'html' => include W3TC_INC_DIR . '/mime/html.php',
107
- 'other' => include W3TC_INC_DIR . '/mime/other.php'
108
- );
109
 
110
  $other_compression = $a['other'];
111
  unset( $other_compression['asf|asx|wax|wmv|wmx'] );
@@ -510,10 +506,6 @@ class BrowserCache_Environment {
510
  $rules = '';
511
  $headers_rules = '';
512
 
513
- if ( $section == 'html' ) {
514
- $headers_rules .= " Header append Vary User-Agent env=!dont-vary\n";
515
- }
516
-
517
  if ( $cache_control ) {
518
  $cache_policy = $config->get_string( 'browsercache.' . $section . '.cache.policy' );
519
 
@@ -658,8 +650,8 @@ class BrowserCache_Environment {
658
  unset( $brotli_types['odp'] );
659
 
660
  $rules .= "brotli on;\n";
661
- $rules .= "brotli_types " .
662
- implode( ' ', array_unique( $brotli_types ) ) . ";\n";
663
  }
664
 
665
  $cssjs_compression = $config->get_boolean( 'browsercache.cssjs.compression' );
101
  * @return array
102
  */
103
  public function get_mime_types() {
104
+ $a = Util_Mime::sections_to_mime_types_map();
 
 
 
 
105
 
106
  $other_compression = $a['other'];
107
  unset( $other_compression['asf|asx|wax|wmv|wmx'] );
506
  $rules = '';
507
  $headers_rules = '';
508
 
 
 
 
 
509
  if ( $cache_control ) {
510
  $cache_policy = $config->get_string( 'browsercache.' . $section . '.cache.policy' );
511
 
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' );
BrowserCache_Plugin.php CHANGED
@@ -52,21 +52,23 @@ class BrowserCache_Plugin {
52
  }
53
  }
54
 
55
- $v = $this->_config->get_string( 'browsercache.security.session.cookie_httponly' );
56
- if ( !empty( $v ) ) {
57
- @ini_set( 'session.cookie_httponly', $v == 'on' ? '1': '0' );
58
- }
59
- $v = $this->_config->get_string( 'browsercache.security.session.cookie_secure' );
60
- if ( !empty( $v ) ) {
61
- @ini_set( 'session.cookie_secure', $v == 'on' ? '1': '0' );
62
- }
63
- $v = $this->_config->get_string( 'browsercache.security.session.use_only_cookies' );
64
- if ( !empty( $v ) ) {
65
- @ini_set( 'session.use_only_cookies', $v == 'on' ? '1': '0' );
66
- }
67
 
68
  add_filter( 'w3tc_minify_http2_preload_url',
69
  array( $this, 'w3tc_minify_http2_preload_url' ), 4000 );
 
 
70
  }
71
 
72
  private function url_clean_enabled() {
@@ -362,57 +364,68 @@ class BrowserCache_Plugin {
362
  }
363
 
364
  /**
365
- * Returns cache config for CDN
366
- *
367
- * @return array
368
  */
369
- function get_cache_config() {
370
- $config = array();
371
-
372
- $e = Dispatcher::component( 'BrowserCache_Environment' );
373
- $mime_types = $e->get_mime_types();
374
-
375
- foreach ( $mime_types as $type => $extensions )
376
- $this->_get_cache_config( $config, $extensions, $type );
377
 
378
  return $config;
379
  }
380
 
381
- /**
382
- * Writes cache config
383
- *
384
- * @param string $config
385
- * @param array $mime_types
386
- * @param array $section
387
- * @return void
388
- */
389
- function _get_cache_config( &$config, $mime_types, $section ) {
390
- $expires = $this->_config->get_boolean( 'browsercache.' . $section . '.expires' );
391
- $lifetime = $this->_config->get_integer( 'browsercache.' . $section . '.lifetime' );
392
- $cache_control = $this->_config->get_boolean( 'browsercache.' . $section . '.cache.control' );
393
- $cache_policy = $this->_config->get_string( 'browsercache.' . $section . '.cache.policy' );
394
- $etag = $this->_config->get_boolean( 'browsercache.' . $section . '.etag' );
395
- $w3tc = $this->_config->get_boolean( 'browsercache.' . $section . '.w3tc' );
396
-
397
- foreach ( $mime_types as $mime_type ) {
398
- if ( is_array( $mime_type ) ) {
399
- foreach ( $mime_type as $mime_type2 )
400
- $config[$mime_type2] = array(
401
- 'etag' => $etag,
402
- 'w3tc' => $w3tc,
403
- 'lifetime' => $lifetime,
404
- 'expires' => $expires,
405
- 'cache_control' => ( $cache_control ? $cache_policy : false )
406
- );
407
- } else
408
- $config[$mime_type] = array(
409
- 'etag' => $etag,
410
- 'w3tc' => $w3tc,
411
- 'lifetime' => $lifetime,
412
- 'expires' => $expires,
413
- 'cache_control' => ( $cache_control ? $cache_policy : false )
414
- );
415
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  }
417
 
418
  /**
52
  }
53
  }
54
 
55
+ $v = $this->_config->get_string( 'browsercache.security.session.cookie_httponly' );
56
+ if ( !empty( $v ) ) {
57
+ @ini_set( 'session.cookie_httponly', $v == 'on' ? '1': '0' );
58
+ }
59
+ $v = $this->_config->get_string( 'browsercache.security.session.cookie_secure' );
60
+ if ( !empty( $v ) ) {
61
+ @ini_set( 'session.cookie_secure', $v == 'on' ? '1': '0' );
62
+ }
63
+ $v = $this->_config->get_string( 'browsercache.security.session.use_only_cookies' );
64
+ if ( !empty( $v ) ) {
65
+ @ini_set( 'session.use_only_cookies', $v == 'on' ? '1': '0' );
66
+ }
67
 
68
  add_filter( 'w3tc_minify_http2_preload_url',
69
  array( $this, 'w3tc_minify_http2_preload_url' ), 4000 );
70
+ add_filter( 'w3tc_cdn_config_headers',
71
+ array( $this, 'w3tc_cdn_config_headers' ) );
72
  }
73
 
74
  private function url_clean_enabled() {
364
  }
365
 
366
  /**
367
+ * Returns headers config for CDN
 
 
368
  */
369
+ function w3tc_cdn_config_headers( $config ) {
370
+ $sections = Util_Mime::sections_to_mime_types_map();
371
+ foreach ( $sections as $section => $v ) {
372
+ $config[$section] = $this->w3tc_cdn_config_headers_section( $section );
373
+ }
 
 
 
374
 
375
  return $config;
376
  }
377
 
378
+ private function w3tc_cdn_config_headers_section( $section ) {
379
+ $c = $this->_config;
380
+ $prefix = 'browsercache.' . $section;
381
+ $lifetime = $c->get_integer( $prefix . '.lifetime' );
382
+
383
+ $headers = array();
384
+
385
+ if ( $c->get_boolean( $prefix . '.w3tc' ) ) {
386
+ $headers['X-Powered-By'] = Util_Environment::w3tc_header();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  }
388
+
389
+ if ( $c->get_boolean( $prefix . '.cache.control' ) ) {
390
+ switch ( $c->get_string( $prefix . '.cache.policy' ) ) {
391
+ case 'cache':
392
+ $headers['Pragma'] = 'public';
393
+ $headers['Cache-Control'] = 'public';
394
+ break;
395
+
396
+ case 'cache_public_maxage':
397
+ $headers['Pragma'] = 'public';
398
+ $headers['Cache-Control'] = "max-age=$lifetime, public";
399
+ break;
400
+
401
+ case 'cache_validation':
402
+ $headers['Pragma'] = 'public';
403
+ $headers['Cache-Control'] = 'public, must-revalidate, proxy-revalidate';
404
+ break;
405
+
406
+ case 'cache_noproxy':
407
+ $headers['Pragma'] = 'public';
408
+ $headers['Cache-Control'] = 'private, must-revalidate';
409
+ break;
410
+
411
+ case 'cache_maxage':
412
+ $headers['Pragma'] = 'public';
413
+ $headers['Cache-Control'] = "max-age=$lifetime, public, must-revalidate, proxy-revalidate";
414
+ break;
415
+
416
+ case 'no_cache':
417
+ $headers['Pragma'] = 'no-cache';
418
+ $headers['Cache-Control'] = 'max-age=0, private, no-store, no-cache, must-revalidate';
419
+ break;
420
+ }
421
+ }
422
+
423
+ return array(
424
+ 'etag' => $c->get_boolean( $prefix . 'etag' ),
425
+ 'expires' => $c->get_boolean( $prefix . '.expires' ),
426
+ 'lifetime' => $lifetime,
427
+ 'static' => $headers
428
+ );
429
  }
430
 
431
  /**
Cache_File_Generic.php CHANGED
@@ -92,23 +92,44 @@ class Cache_File_Generic extends Cache_File {
92
  }
93
 
94
  if ( isset( $var['headers'] ) ) {
95
- $links = '';
96
-
97
  foreach ( $var['headers'] as $h ) {
98
- if ( isset($h['n']) && isset($h['v']) && $h['n'] == 'Link' ) {
99
- $value = $h['v'];
100
- if ( false !== strpos( $value, 'rel=preload' ) ) {
101
- $links .= " Header add Link '" . trim($value) . "'\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  }
103
  }
104
  }
105
 
106
- if ( !empty( $links) ) {
 
 
 
 
 
 
 
 
 
107
  $rules .= "<IfModule mod_headers.c>\n";
108
- $rules .= " Header unset Link\n";
109
- $rules .= " <FilesMatch \"\.(html|html_gzip|html_br)$\">\n";
110
- $rules .= $links;
111
- $rules .= " </FilesMatch>\n";
112
  $rules .= "</IfModule>\n";
113
  }
114
  }
@@ -122,6 +143,16 @@ class Cache_File_Generic extends Cache_File {
122
  return true;
123
  }
124
 
 
 
 
 
 
 
 
 
 
 
125
  /**
126
  * Returns data
127
  *
92
  }
93
 
94
  if ( isset( $var['headers'] ) ) {
95
+ $headers = array();
 
96
  foreach ( $var['headers'] as $h ) {
97
+ if ( isset( $h['n'] ) && isset( $h['v'] ) ) {
98
+ $h2 = apply_filters( 'w3tc_pagecache_set_header', $h, $h,
99
+ 'file_generic' );
100
+
101
+ if ( !empty( $h2 ) ) {
102
+ $name_escaped = $this->escape_header_name( $h2['n'] );
103
+ if ( !isset( $headers[$name_escaped] ) ) {
104
+ $headers[$name_escaped] = array(
105
+ 'values' => array(),
106
+ 'files_match' => $h2['files_match']
107
+ );
108
+ }
109
+
110
+ $value_escaped = $this->escape_header_value( $h2['v'] );
111
+ if ( !empty( $value_escaped ) ) {
112
+ $headers[$name_escaped]['values'][] =
113
+ " Header add " .
114
+ $name_escaped .
115
+ " '" . $value_escaped . "'\n";
116
+ }
117
  }
118
  }
119
  }
120
 
121
+ $header_rules = '';
122
+ foreach ( $headers as $name_escaped => $value ) {
123
+ // Link header doesnt apply to .xml assets
124
+ $header_rules .= ' <FilesMatch "' . $value['files_match'] . "\">\n";
125
+ $header_rules .= " Header unset $name_escaped\n";
126
+ $header_rules .= implode( "\n", $value['values'] );
127
+ $header_rules .= " </FilesMatch>\n";
128
+ }
129
+
130
+ if ( !empty( $header_rules ) ) {
131
  $rules .= "<IfModule mod_headers.c>\n";
132
+ $rules .= $header_rules;
 
 
 
133
  $rules .= "</IfModule>\n";
134
  }
135
  }
143
  return true;
144
  }
145
 
146
+ private function escape_header_name( $v ) {
147
+ return preg_replace( '~[^0-9A-Za-z\-]~m', '_', $v );
148
+ }
149
+
150
+ private function escape_header_value( $v ) {
151
+ return str_replace( "'", "\\'",
152
+ str_replace( "\\", "\\\\\\", // htaccess need escape of \ to \\\
153
+ preg_replace( '~[\r\n]~m', '_', trim( $v ) ) ) );
154
+ }
155
+
156
  /**
157
  * Returns data
158
  *
Cache_Memcache.php CHANGED
@@ -33,12 +33,8 @@ class Cache_Memcache extends Cache_Base {
33
  $persistent = isset( $config['persistent'] ) ? (boolean) $config['persistent'] : false;
34
 
35
  foreach ( (array) $config['servers'] as $server ) {
36
- if ( substr( $server, 0, 5 ) == 'unix:' || strpos( $server, ':' ) === false ) {
37
- $this->_memcache->addServer( trim( $server ), 0, $persistent );
38
- } else {
39
- list( $ip, $port ) = explode( ':', $server );
40
- $this->_memcache->addServer( trim( $ip ), (integer) trim( $port ), $persistent );
41
- }
42
  }
43
  } else {
44
  return false;
33
  $persistent = isset( $config['persistent'] ) ? (boolean) $config['persistent'] : false;
34
 
35
  foreach ( (array) $config['servers'] as $server ) {
36
+ list( $ip, $port ) = Util_Content::endpoint_to_host_port( $server );
37
+ $this->_memcache->addServer( $ip, $port, $persistent );
 
 
 
 
38
  }
39
  } else {
40
  return false;
Cache_Memcached.php CHANGED
@@ -59,8 +59,12 @@ class Cache_Memcached extends Cache_Base {
59
  if ( defined( '\Memcached::OPT_REMOVE_FAILED_SERVERS' ) ) {
60
  $this->_memcache->setOption( \Memcached::OPT_REMOVE_FAILED_SERVERS, true );
61
  }
62
- if ( defined( '\Memcached::OPT_BINARY_PROTOCOL' ) && defined( '\Memcached::OPT_TCP_NODELAY' ) ) {
 
63
  $this->_memcache->setOption( \Memcached::OPT_BINARY_PROTOCOL, true );
 
 
 
64
  $this->_memcache->setOption( \Memcached::OPT_TCP_NODELAY, true );
65
  }
66
 
@@ -72,12 +76,8 @@ class Cache_Memcached extends Cache_Base {
72
  \Memcached::DYNAMIC_CLIENT_MODE );
73
 
74
  foreach ( (array)$config['servers'] as $server ) {
75
- if ( substr( $server, 0, 5 ) == 'unix:' || strpos( $server, ':' ) === false ) {
76
- $this->_memcache->addServer( trim( $server ), 0 );
77
- } else {
78
- list( $ip, $port ) = explode( ':', $server );
79
- $this->_memcache->addServer( trim( $ip ), (integer) trim( $port ) );
80
- }
81
  }
82
 
83
  if ( isset( $config['username'] ) && !empty( $config['username'] ) &&
59
  if ( defined( '\Memcached::OPT_REMOVE_FAILED_SERVERS' ) ) {
60
  $this->_memcache->setOption( \Memcached::OPT_REMOVE_FAILED_SERVERS, true );
61
  }
62
+
63
+ if ( isset( $config['binary_protocol'] ) && !empty( $config['binary_protocol'] ) && defined( '\Memcached::OPT_BINARY_PROTOCOL' ) ) {
64
  $this->_memcache->setOption( \Memcached::OPT_BINARY_PROTOCOL, true );
65
+ }
66
+
67
+ if ( defined( '\Memcached::OPT_TCP_NODELAY' ) ) {
68
  $this->_memcache->setOption( \Memcached::OPT_TCP_NODELAY, true );
69
  }
70
 
76
  \Memcached::DYNAMIC_CLIENT_MODE );
77
 
78
  foreach ( (array)$config['servers'] as $server ) {
79
+ list( $ip, $port ) = Util_Content::endpoint_to_host_port( $server );
80
+ $this->_memcache->addServer( $ip, $port );
 
 
 
 
81
  }
82
 
83
  if ( isset( $config['username'] ) && !empty( $config['username'] ) &&
Cache_Nginx_Memcached.php CHANGED
@@ -57,12 +57,8 @@ class Cache_Nginx_Memcached extends Cache_Base {
57
  \Memcached::DYNAMIC_CLIENT_MODE );
58
 
59
  foreach ( (array)$config['servers'] as $server ) {
60
- if ( substr( $server, 0, 5 ) == 'unix:' || strpos( $server, ':' ) === false ) {
61
- $this->_memcache->addServer( trim( $server ), 0 );
62
- } else {
63
- list( $ip, $port ) = explode( ':', $server );
64
- $this->_memcache->addServer( trim( $ip ), (integer) trim( $port ) );
65
- }
66
  }
67
 
68
  if ( isset( $config['username'] ) && !empty( $config['username'] ) &&
57
  \Memcached::DYNAMIC_CLIENT_MODE );
58
 
59
  foreach ( (array)$config['servers'] as $server ) {
60
+ list( $ip, $port ) = Util_Content::endpoint_to_host_port( $server );
61
+ $this->_memcache->addServer( $ip, $port );
 
 
 
 
62
  }
63
 
64
  if ( isset( $config['username'] ) && !empty( $config['username'] ) &&
Cache_Redis.php CHANGED
@@ -343,25 +343,21 @@ class Cache_Redis extends Cache_Base {
343
  $accessor = new \Redis();
344
 
345
  if ( substr( $server, 0, 5 ) == 'unix:' ) {
346
- if ( $this->_persistent )
347
  $accessor->pconnect( trim( substr( $server, 5 ) ),
348
  null, null, $this->_instance_id . '_' . $this->_dbid );
349
- else
350
  $accessor->connect( trim( substr( $server, 5 ) ) );
351
- } elseif ( strpos( $server, ':' ) === false ) {
352
- if ( $this->_persistent )
353
- $accessor->pconnect( trim( $server ),
354
- null, null, $this->_instance_id . '_' . $this->_dbid );
355
- else
356
- $accessor->connect( trim( $server ) );
357
  } else {
358
- list( $ip, $port ) = explode( ':', $server );
359
 
360
- if ( $this->_persistent )
361
- $accessor->pconnect( trim( $ip ), (integer) trim( $port ),
362
  null, $this->_instance_id . '_' . $this->_dbid );
363
- else
364
- $accessor->connect( trim( $ip ), (integer) trim( $port ) );
 
365
  }
366
 
367
  if ( !empty( $this->_password ) )
343
  $accessor = new \Redis();
344
 
345
  if ( substr( $server, 0, 5 ) == 'unix:' ) {
346
+ if ( $this->_persistent ) {
347
  $accessor->pconnect( trim( substr( $server, 5 ) ),
348
  null, null, $this->_instance_id . '_' . $this->_dbid );
349
+ } else {
350
  $accessor->connect( trim( substr( $server, 5 ) ) );
351
+ }
 
 
 
 
 
352
  } else {
353
+ list( $ip, $port ) = Util_Content::endpoint_to_host_port( $server, null );
354
 
355
+ if ( $this->_persistent ) {
356
+ $accessor->pconnect( $ip, $port,
357
  null, $this->_instance_id . '_' . $this->_dbid );
358
+ } else {
359
+ $accessor->connect( $ip, $port );
360
+ }
361
  }
362
 
363
  if ( !empty( $this->_password ) )
CdnEngine_Azure.php CHANGED
@@ -142,20 +142,14 @@ class CdnEngine_Azure extends CdnEngine_Base {
142
  }
143
  }
144
 
145
- $headers = $this->_get_headers( $file );
146
 
147
  try {
148
  // $headers
149
  $options = new \MicrosoftAzure\Storage\Blob\Models\CreateBlobOptions();
150
  $options->setBlobContentMD5( $content_md5 );
151
- if ( isset( $headers['Content-Length'] ) )
152
- $options->setBlobContentLength( $headers['Content-Length'] );
153
  if ( isset( $headers['Content-Type'] ) )
154
  $options->setBlobContentType( $headers['Content-Type'] );
155
- if ( isset( $headers['Content-Encoding'] ) )
156
- $options->setBlobContentEncoding( $headers['Content-Encoding'] );
157
- if ( isset( $headers['Content-Language'] ) )
158
- $options->setBlobContentLanguage( $headers['Content-Language'] );
159
  if ( isset( $headers['Cache-Control'] ) )
160
  $options->setBlobCacheControl( $headers['Cache-Control'] );
161
 
@@ -357,9 +351,9 @@ class CdnEngine_Azure extends CdnEngine_Base {
357
  }
358
 
359
  try {
360
- $createContainerOptions = new \MicrosoftAzure\Storage\Blob\Models\CreateContainerOptions();
361
- $createContainerOptions->setPublicAccess(
362
- \MicrosoftAzure\Storage\Blob\Models\PublicAccessType::CONTAINER_AND_BLOBS );
363
 
364
  $this->_client->createContainer( $this->_config['container'], $createContainerOptions );
365
  } catch ( \Exception $exception ) {
142
  }
143
  }
144
 
145
+ $headers = $this->get_headers_for_file( $file );
146
 
147
  try {
148
  // $headers
149
  $options = new \MicrosoftAzure\Storage\Blob\Models\CreateBlobOptions();
150
  $options->setBlobContentMD5( $content_md5 );
 
 
151
  if ( isset( $headers['Content-Type'] ) )
152
  $options->setBlobContentType( $headers['Content-Type'] );
 
 
 
 
153
  if ( isset( $headers['Cache-Control'] ) )
154
  $options->setBlobCacheControl( $headers['Cache-Control'] );
155
 
351
  }
352
 
353
  try {
354
+ $createContainerOptions = new \MicrosoftAzure\Storage\Blob\Models\CreateContainerOptions();
355
+ $createContainerOptions->setPublicAccess(
356
+ \MicrosoftAzure\Storage\Blob\Models\PublicAccessType::CONTAINER_AND_BLOBS );
357
 
358
  $this->_client->createContainer( $this->_config['container'], $createContainerOptions );
359
  } catch ( \Exception $exception ) {
CdnEngine_Base.php CHANGED
@@ -22,13 +22,6 @@ class CdnEngine_Base {
22
  */
23
  var $_config = array();
24
 
25
- /**
26
- * Cache config
27
- *
28
- * @var array
29
- */
30
- var $cache_config = array();
31
-
32
  /**
33
  * gzip extension
34
  *
@@ -52,7 +45,8 @@ class CdnEngine_Base {
52
  $this->_config = array_merge( array(
53
  'debug' => false,
54
  'ssl' => 'auto',
55
- 'compression' => false
 
56
  ), $config );
57
  }
58
 
@@ -370,89 +364,38 @@ class CdnEngine_Base {
370
  * Returns headers for file
371
  *
372
  * @param array $file CDN file array
 
373
  * @return array
374
  */
375
- function _get_headers( $file, $block_expires = false ) {
376
-
377
  $local_path = $file['local_path'];
378
  $mime_type = Util_Mime::get_mime_type( $local_path );
379
- $last_modified = time();
380
 
381
  $link = $file['original_url'];
382
 
383
  $headers = array(
384
  'Content-Type' => $mime_type,
385
- 'Last-Modified' => Util_Content::http_date( $last_modified ),
386
  'Access-Control-Allow-Origin' => '*',
387
  'Link' => '<' . $link .'>; rel="canonical"'
388
  );
389
 
390
- if ( isset( $this->cache_config[$mime_type] ) ) {
391
- if ( $this->cache_config[$mime_type]['etag'] ) {
392
- $headers['ETag'] = '"' . @md5_file( $local_path ) . '"';
393
- }
394
 
395
- if ( $this->cache_config[$mime_type]['w3tc'] ) {
396
- $headers['X-Powered-By'] =
397
- Util_Environment::w3tc_header();
398
- }
399
 
 
 
 
400
 
401
- $expires_set = false;
402
- if ( !$block_expires &&
403
- $this->cache_config[$mime_type]['expires'] ) {
404
  $headers['Expires'] = Util_Content::http_date( time() +
405
- $this->cache_config[$mime_type]['lifetime'] );
406
  $expires_set = true;
407
  }
408
 
409
- switch ( $this->cache_config[$mime_type]['cache_control'] ) {
410
- case 'cache':
411
- $headers = array_merge( $headers, array(
412
- 'Pragma' => 'public',
413
- 'Cache-Control' => 'public'
414
- ) );
415
- break;
416
-
417
- case 'cache_public_maxage':
418
- $headers = array_merge( $headers, array(
419
- 'Pragma' => 'public',
420
- 'Cache-Control' => ( $expires_set ? '' : 'max-age=' .
421
- $this->cache_config[$mime_type]['lifetime'] .', ' ) .
422
- 'public'
423
- ) );
424
- break;
425
-
426
- case 'cache_validation':
427
- $headers = array_merge( $headers, array(
428
- 'Pragma' => 'public',
429
- 'Cache-Control' => 'public, must-revalidate, proxy-revalidate'
430
- ) );
431
- break;
432
-
433
- case 'cache_noproxy':
434
- $headers = array_merge( $headers, array(
435
- 'Pragma' => 'public',
436
- 'Cache-Control' => 'private, must-revalidate'
437
- ) );
438
- break;
439
-
440
- case 'cache_maxage':
441
- $headers = array_merge( $headers, array(
442
- 'Pragma' => 'public',
443
- 'Cache-Control' => ( $expires_set ? '' : 'max-age=' .
444
- $this->cache_config[$mime_type]['lifetime'] .', ' ) .
445
- 'public, must-revalidate, proxy-revalidate'
446
- ) );
447
- break;
448
-
449
- case 'no_cache':
450
- $headers = array_merge( $headers, array(
451
- 'Pragma' => 'no-cache',
452
- 'Cache-Control' => 'max-age=0, private, no-store, no-cache, must-revalidate'
453
- ) );
454
- break;
455
- }
456
  }
457
 
458
  return $headers;
22
  */
23
  var $_config = array();
24
 
 
 
 
 
 
 
 
25
  /**
26
  * gzip extension
27
  *
45
  $this->_config = array_merge( array(
46
  'debug' => false,
47
  'ssl' => 'auto',
48
+ 'compression' => false,
49
+ 'headers' => array()
50
  ), $config );
51
  }
52
 
364
  * Returns headers for file
365
  *
366
  * @param array $file CDN file array
367
+ * @param array $whitelist which expensive headers to calculate
368
  * @return array
369
  */
370
+ function get_headers_for_file( $file, $whitelist = array() ) {
 
371
  $local_path = $file['local_path'];
372
  $mime_type = Util_Mime::get_mime_type( $local_path );
 
373
 
374
  $link = $file['original_url'];
375
 
376
  $headers = array(
377
  'Content-Type' => $mime_type,
378
+ 'Last-Modified' => Util_Content::http_date( time() ),
379
  'Access-Control-Allow-Origin' => '*',
380
  'Link' => '<' . $link .'>; rel="canonical"'
381
  );
382
 
383
+ $section = Util_Mime::mime_type_to_section( $mime_type );
 
 
 
384
 
385
+ if ( isset( $this->_config['headers'][$section] ) ) {
386
+ $hc = $this->_config['headers'][$section];
 
 
387
 
388
+ if ( isset( $whitelist['ETag'] ) && $hc['etag'] ) {
389
+ $headers['ETag'] = '"' . @md5_file( $local_path ) . '"';
390
+ }
391
 
392
+ if ( $hc['expires'] ) {
 
 
393
  $headers['Expires'] = Util_Content::http_date( time() +
394
+ $hc['lifetime'] );
395
  $expires_set = true;
396
  }
397
 
398
+ $headers = array_merge( $headers, $hc['static'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  }
400
 
401
  return $headers;
CdnEngine_Ftp.php CHANGED
@@ -38,11 +38,9 @@ class CdnEngine_Ftp extends CdnEngine_Base {
38
  'docroot' => ''
39
  ), $config );
40
 
41
- $host_port = explode( ':', $config['host'] );
42
- if ( sizeof( $host_port ) == 2 ) {
43
- $config['host'] = $host_port[0];
44
- $config['port'] = $host_port[1];
45
- }
46
 
47
  if ( $config['type'] == 'sftp' && $config['default_keys'] ) {
48
  $config['pubkey'] = $_SERVER['HOME'] . '/.ssh/id_rsa.pub';
@@ -65,10 +63,6 @@ class CdnEngine_Ftp extends CdnEngine_Base {
65
  return false;
66
  }
67
 
68
- if ( empty( $this->_config['port'] ) ) {
69
- $this->_config['port'] = 21;
70
- }
71
-
72
  $this->_set_error_handler();
73
 
74
  if ( $this->_config['type'] == 'sftp' ) {
38
  'docroot' => ''
39
  ), $config );
40
 
41
+ list( $ip, $port ) = Util_Content::endpoint_to_host_port( $config['host'], 21 );
42
+ $config['host'] = $ip;
43
+ $config['port'] = $port;
 
 
44
 
45
  if ( $config['type'] == 'sftp' && $config['default_keys'] ) {
46
  $config['pubkey'] = $_SERVER['HOME'] . '/.ssh/id_rsa.pub';
63
  return false;
64
  }
65
 
 
 
 
 
66
  $this->_set_error_handler();
67
 
68
  if ( $this->_config['type'] == 'sftp' ) {
CdnEngine_S3.php CHANGED
@@ -182,7 +182,7 @@ class CdnEngine_S3 extends CdnEngine_Base {
182
  }
183
  }
184
 
185
- $headers = $this->_get_headers( $file );
186
  $result = $this->_put_object( array(
187
  'Key' => $remote_path,
188
  'SourceFile' => $local_path,
@@ -248,11 +248,8 @@ class CdnEngine_S3 extends CdnEngine_Base {
248
  }
249
  }
250
 
251
- $headers = $this->_get_headers( $file );
252
- $headers = array_merge( $headers, array(
253
- 'Vary' => 'Accept-Encoding',
254
- 'Content-Encoding' => 'gzip'
255
- ) );
256
 
257
  $result = $this->_put_object( array(
258
  'Key' => $remote_path,
@@ -277,9 +274,8 @@ class CdnEngine_S3 extends CdnEngine_Base {
277
  $data['ACL'] = 'public-read';
278
  $data['Bucket'] = $this->_config['bucket'];
279
 
280
- if ( isset( $headers['Content-Type'] ) ) {
281
- $data['ContentType'] = $headers['Content-Type'];
282
- }
283
  if ( isset( $headers['Content-Encoding'] ) ) {
284
  $data['ContentEncoding'] = $headers['Content-Encoding'];
285
  }
182
  }
183
  }
184
 
185
+ $headers = $this->get_headers_for_file( $file );
186
  $result = $this->_put_object( array(
187
  'Key' => $remote_path,
188
  'SourceFile' => $local_path,
248
  }
249
  }
250
 
251
+ $headers = $this->get_headers_for_file( $file );
252
+ $headers['Content-Encoding'] = 'gzip';
 
 
 
253
 
254
  $result = $this->_put_object( array(
255
  'Key' => $remote_path,
274
  $data['ACL'] = 'public-read';
275
  $data['Bucket'] = $this->_config['bucket'];
276
 
277
+ $data['ContentType'] = $headers['Content-Type'];
278
+
 
279
  if ( isset( $headers['Content-Encoding'] ) ) {
280
  $data['ContentEncoding'] = $headers['Content-Encoding'];
281
  }
CdnEngine_S3_Compatible.php CHANGED
@@ -128,7 +128,7 @@ class CdnEngine_S3_Compatible extends CdnEngine_Base {
128
  }
129
  }
130
 
131
- $headers = $this->_get_headers( $file );
132
 
133
  $this->_set_error_handler();
134
  $result = @$this->_s3->putObjectFile( $local_path,
@@ -191,7 +191,7 @@ class CdnEngine_S3_Compatible extends CdnEngine_Base {
191
  }
192
  }
193
 
194
- $headers = $this->_get_headers( $file );
195
  $headers = array_merge( $headers, array(
196
  'Vary' => 'Accept-Encoding',
197
  'Content-Encoding' => 'gzip'
128
  }
129
  }
130
 
131
+ $headers = $this->get_headers_for_file( $file, array( 'ETag' => '*' ) );
132
 
133
  $this->_set_error_handler();
134
  $result = @$this->_s3->putObjectFile( $local_path,
191
  }
192
  }
193
 
194
+ $headers = $this->get_headers_for_file( $file, array( 'ETag' => '*' ) );
195
  $headers = array_merge( $headers, array(
196
  'Vary' => 'Accept-Encoding',
197
  'Content-Encoding' => 'gzip'
Cdn_Core.php CHANGED
@@ -347,9 +347,9 @@ class Cdn_Core {
347
  * Returns CDN object
348
  */
349
  function get_cdn() {
350
- static $cdn = array();
351
 
352
- if ( !isset( $cdn[0] ) ) {
353
  $c = $this->_config;
354
  $engine = $c->get_string( 'cdn.engine' );
355
  $compression = ( $c->get_boolean( 'browsercache.enabled' ) && $c->get_boolean( 'browsercache.html.compression' ) );
@@ -610,21 +610,14 @@ class Cdn_Core {
610
  }
611
 
612
  $engine_config = array_merge( $engine_config, array(
613
- 'debug' => $c->get_boolean( 'cdn.debug' )
 
614
  ) );
615
 
616
- $cdn[0] = CdnEngine::instance( $engine, $engine_config );
617
-
618
- /**
619
- * Set cache config for CDN
620
- */
621
- if ( $this->_config->get_boolean( 'browsercache.enabled' ) ) {
622
- $w3_plugin_browsercache = Dispatcher::component( 'BrowserCache_Plugin' );
623
- $cdn[0]->cache_config = $w3_plugin_browsercache->get_cache_config();
624
- }
625
  }
626
 
627
- return $cdn[0];
628
  }
629
 
630
  /**
347
  * Returns CDN object
348
  */
349
  function get_cdn() {
350
+ static $cdn = null;
351
 
352
+ if ( is_null( $cdn ) ) {
353
  $c = $this->_config;
354
  $engine = $c->get_string( 'cdn.engine' );
355
  $compression = ( $c->get_boolean( 'browsercache.enabled' ) && $c->get_boolean( 'browsercache.html.compression' ) );
610
  }
611
 
612
  $engine_config = array_merge( $engine_config, array(
613
+ 'debug' => $c->get_boolean( 'cdn.debug' ),
614
+ 'headers' => apply_filters( 'w3tc_cdn_config_headers', array() )
615
  ) );
616
 
617
+ $cdn = CdnEngine::instance( $engine, $engine_config );
 
 
 
 
 
 
 
 
618
  }
619
 
620
+ return $cdn;
621
  }
622
 
623
  /**
Cdnfsd_GeneralPage_View.php CHANGED
@@ -11,7 +11,7 @@ if ( !defined( 'W3TC' ) )
11
  <?php endif ?>
12
  </p>
13
  <table class="form-table">
14
- <?php
15
  Util_Ui::config_item( array(
16
  'key' => 'cdnfsd.enabled',
17
  'label' => __( '<acronym title="Full Site Delivery">FSD</acronym> <acronym title="Content Delivery Network">CDN</acronym>:', 'w3-total-cache' ),
@@ -19,8 +19,8 @@ Util_Ui::config_item( array(
19
  'checkbox_label' => __( 'Enable', 'w3-total-cache' ),
20
  'disabled' => ( $is_pro ? null : true ),
21
  'description' => __( 'The entire website will load quickly for site visitors.',
22
- 'w3-total-cache' ) .
23
- ( $is_pro ? '' : __( ' <strong>Available after upgrade.</strong>', 'w3-total-cache' ) )
24
  ) );
25
 
26
  Util_Ui::config_item( array(
11
  <?php endif ?>
12
  </p>
13
  <table class="form-table">
14
+ <?php
15
  Util_Ui::config_item( array(
16
  'key' => 'cdnfsd.enabled',
17
  'label' => __( '<acronym title="Full Site Delivery">FSD</acronym> <acronym title="Content Delivery Network">CDN</acronym>:', 'w3-total-cache' ),
19
  'checkbox_label' => __( 'Enable', 'w3-total-cache' ),
20
  'disabled' => ( $is_pro ? null : true ),
21
  'description' => __( 'The entire website will load quickly for site visitors.',
22
+ 'w3-total-cache' ),
23
+ 'pro_feature' => true
24
  ) );
25
 
26
  Util_Ui::config_item( array(
Config.php CHANGED
@@ -210,6 +210,52 @@ class Config {
210
 
211
 
212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  /**
214
  * Check if an extension is active
215
  */
210
 
211
 
212
 
213
+ /**
214
+ * Returns config value with ability to hook it.
215
+ * Should be called only when filters already loaded and
216
+ * call doesn't repeat too many times
217
+ */
218
+ public function getf( $key, $default = null ) {
219
+ $v = $this->get( $key, $default );
220
+ return apply_filters( 'w3tc_config_item_' . $key, $v );
221
+ }
222
+
223
+ /**
224
+ * Returns string value with ability to hook it
225
+ */
226
+ public function getf_string( $key, $default = '', $trim = true ) {
227
+ $value = (string)$this->getf( $key, $default );
228
+
229
+ return $trim ? trim( $value ) : $value;
230
+ }
231
+
232
+ /**
233
+ * Returns integer value with ability to hook it
234
+ */
235
+ public function getf_integer( $key, $default = 0 ) {
236
+ return (integer)$this->getf( $key, $default );
237
+ }
238
+
239
+
240
+
241
+ /**
242
+ * Returns boolean value ability to hook it
243
+ */
244
+ public function getf_boolean( $key, $default = false ) {
245
+ return (boolean)$this->getf( $key, $default );
246
+ }
247
+
248
+
249
+
250
+ /**
251
+ * Returns array value ability to hook it
252
+ */
253
+ public function getf_array( $key, $default = array() ) {
254
+ return (array)$this->getf( $key, $default );
255
+ }
256
+
257
+
258
+
259
  /**
260
  * Check if an extension is active
261
  */
ConfigCompiler.php CHANGED
@@ -387,6 +387,8 @@ class ConfigCompiler {
387
  'fragmentcache', 'memcached.username' );
388
  $this->_set_if_exists( $file_data, 'fragmentcache.memcached.password',
389
  'fragmentcache', 'memcached.password' );
 
 
390
  $this->_set_if_exists( $file_data, 'fragmentcache.redis.persistent',
391
  'fragmentcache', 'redis.persistent' );
392
  $this->_set_if_exists( $file_data, 'fragmentcache.redis.servers',
387
  'fragmentcache', 'memcached.username' );
388
  $this->_set_if_exists( $file_data, 'fragmentcache.memcached.password',
389
  'fragmentcache', 'memcached.password' );
390
+ $this->_set_if_exists( $file_data, 'fragmentcache.memcached.binary_protocol',
391
+ 'fragmentcache', 'memcached.binary_protocol' );
392
  $this->_set_if_exists( $file_data, 'fragmentcache.redis.persistent',
393
  'fragmentcache', 'redis.persistent' );
394
  $this->_set_if_exists( $file_data, 'fragmentcache.redis.servers',
ConfigKeys.php CHANGED
@@ -83,6 +83,10 @@ $keys = array(
83
  'type' => 'string',
84
  'default' => ''
85
  ),
 
 
 
 
86
  'dbcache.redis.persistent' => array(
87
  'type' => 'boolean',
88
  'default' => true
@@ -153,6 +157,49 @@ $keys = array(
153
  )
154
  ),
155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  'objectcache.configuration_overloaded' => array(
157
  'type' => 'boolean',
158
  'default' => false
@@ -207,6 +254,10 @@ $keys = array(
207
  'type' => 'string',
208
  'default' => ''
209
  ),
 
 
 
 
210
  'objectcache.redis.persistent' => array(
211
  'type' => 'boolean',
212
  'default' => true
@@ -316,6 +367,10 @@ $keys = array(
316
  'type' => 'string',
317
  'default' => ''
318
  ),
 
 
 
 
319
  'pgcache.redis.persistent' => array(
320
  'type' => 'boolean',
321
  'default' => true
@@ -682,6 +737,10 @@ $keys = array(
682
  'type' => 'string',
683
  'default' => ''
684
  ),
 
 
 
 
685
  'minify.redis.persistent' => array(
686
  'type' => 'boolean',
687
  'default' => true
@@ -2309,7 +2368,6 @@ $keys = array(
2309
  'extensions.active' => array(
2310
  'type' => 'array',
2311
  'default' => array(
2312
- 'newrelic' => 'w3-total-cache/Extension_NewRelic_Plugin.php',
2313
  'fragmentcache' => 'w3-total-cache/Extension_FragmentCache_Plugin.php'
2314
  )
2315
  ),
83
  'type' => 'string',
84
  'default' => ''
85
  ),
86
+ 'dbcache.memcached.binary_protocol' => array(
87
+ 'type' => 'boolean',
88
+ 'default' => true
89
+ ),
90
  'dbcache.redis.persistent' => array(
91
  'type' => 'boolean',
92
  'default' => true
157
  )
158
  ),
159
 
160
+ 'lazyload.enabled' => array(
161
+ 'type' => 'boolean',
162
+ 'default' => false
163
+ ),
164
+ 'lazyload.process_img' => array(
165
+ 'type' => 'boolean',
166
+ 'default' => true
167
+ ),
168
+ 'lazyload.process_background' => array(
169
+ 'type' => 'boolean',
170
+ 'default' => true
171
+ ),
172
+ 'lazyload.exclude' => array(
173
+ 'type' => 'array',
174
+ 'default' => array(
175
+ 'avia-bg-style-fixed',
176
+ 'data-bgposition=',
177
+ 'data-envira-src=',
178
+ 'data-large_image=',
179
+ 'data-lazy-original=',
180
+ 'data-lazy-src=',
181
+ 'data-lazyload=',
182
+ 'data-lazysrc=',
183
+ 'data-no-lazy=',
184
+ 'data-src=',
185
+ 'data-srcset=',
186
+ 'fullurl=',
187
+ 'lazy-slider-img=',
188
+ 'loading="eager"',
189
+ 'no-lazy',
190
+ 'rev-slidebg',
191
+ 'soliloquy-image',
192
+ 'swatch-img',
193
+ 'w3-total-cache',
194
+ 'woocommerce/assets/images/placeholder.png',
195
+ 'wpcf7_captcha',
196
+ )
197
+ ),
198
+ 'lazyload.embed_method' => array(
199
+ 'type' => 'string',
200
+ 'default' => 'async_head'
201
+ ),
202
+
203
  'objectcache.configuration_overloaded' => array(
204
  'type' => 'boolean',
205
  'default' => false
254
  'type' => 'string',
255
  'default' => ''
256
  ),
257
+ 'objectcache.memcached.binary_protocol' => array(
258
+ 'type' => 'boolean',
259
+ 'default' => true
260
+ ),
261
  'objectcache.redis.persistent' => array(
262
  'type' => 'boolean',
263
  'default' => true
367
  'type' => 'string',
368
  'default' => ''
369
  ),
370
+ 'pgcache.memcached.binary_protocol' => array(
371
+ 'type' => 'boolean',
372
+ 'default' => true
373
+ ),
374
  'pgcache.redis.persistent' => array(
375
  'type' => 'boolean',
376
  'default' => true
737
  'type' => 'string',
738
  'default' => ''
739
  ),
740
+ 'minify.memcached.binary_protocol' => array(
741
+ 'type' => 'boolean',
742
+ 'default' => true
743
+ ),
744
  'minify.redis.persistent' => array(
745
  'type' => 'boolean',
746
  'default' => true
2368
  'extensions.active' => array(
2369
  'type' => 'array',
2370
  'default' => array(
 
2371
  'fragmentcache' => 'w3-total-cache/Extension_FragmentCache_Plugin.php'
2372
  )
2373
  ),
DbCache_Core.php CHANGED
@@ -16,7 +16,8 @@ class DbCache_Core {
16
  'persistent' => $c->get_boolean( 'dbcache.memcached.persistent' ),
17
  'aws_autodiscovery' => $c->get_boolean( 'dbcache.memcached.aws_autodiscovery' ),
18
  'username' => $c->get_string( 'dbcache.memcached.username' ),
19
- 'password' => $c->get_string( 'dbcache.memcached.password' )
 
20
  );
21
  break;
22
 
16
  'persistent' => $c->get_boolean( 'dbcache.memcached.persistent' ),
17
  'aws_autodiscovery' => $c->get_boolean( 'dbcache.memcached.aws_autodiscovery' ),
18
  'username' => $c->get_string( 'dbcache.memcached.username' ),
19
+ 'password' => $c->get_string( 'dbcache.memcached.password' ),
20
+ 'binary_protocol' => $c->get_boolean( 'dbcache.memcached.binary_protocol' )
21
  );
22
  break;
23
 
DbCache_WpdbInjection_QueryCaching.php CHANGED
@@ -338,7 +338,8 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
338
  'persistent' => $this->_config->get_boolean( 'dbcache.memcached.persistent' ),
339
  'aws_autodiscovery' => $this->_config->get_boolean( 'dbcache.memcached.aws_autodiscovery' ),
340
  'username' => $this->_config->get_string( 'dbcache.memcached.username' ),
341
- 'password' => $this->_config->get_string( 'dbcache.memcached.password' )
 
342
  );
343
  break;
344
 
338
  'persistent' => $this->_config->get_boolean( 'dbcache.memcached.persistent' ),
339
  'aws_autodiscovery' => $this->_config->get_boolean( 'dbcache.memcached.aws_autodiscovery' ),
340
  'username' => $this->_config->get_string( 'dbcache.memcached.username' ),
341
+ 'password' => $this->_config->get_string( 'dbcache.memcached.password' ),
342
+ 'binary_protocol' => $this->_config->get_boolean( 'dbcache.memcached.binary_protocol' )
343
  );
344
  break;
345
 
Enterprise_CacheFlush_MakeSnsEvent.php CHANGED
@@ -58,6 +58,12 @@ class Enterprise_CacheFlush_MakeSnsEvent extends Enterprise_SnsBase {
58
  $this->_prepare_message( array( 'action' => 'browsercache_flush' ) );
59
  }
60
 
 
 
 
 
 
 
61
  /**
62
  * Purges Files from Varnish (If enabled) and CDN
63
  *
58
  $this->_prepare_message( array( 'action' => 'browsercache_flush' ) );
59
  }
60
 
61
+ function cdn_purge_all( $extras = null ) {
62
+ return $this->_prepare_message( array(
63
+ 'action' => 'cdn_purge_all',
64
+ 'extras' => $extras ) );
65
+ }
66
+
67
  /**
68
  * Purges Files from Varnish (If enabled) and CDN
69
  *
Enterprise_Dbcache_WpdbInjection_Cluster.php CHANGED
@@ -392,12 +392,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
392
  extract( $this->_cluster_servers[$dataset][$operation][$zone][$index], EXTR_OVERWRITE );
393
 
394
  // Split host:port into $host and $port
395
- if ( strpos( $host, ':' ) )
396
- list( $host, $port ) = explode( ':', $host );
397
-
398
- // Make sure there's always a port number
399
- if ( empty( $port ) )
400
- $port = 3306;
401
 
402
  $this->wpdb_mixin->timer_start();
403
 
392
  extract( $this->_cluster_servers[$dataset][$operation][$zone][$index], EXTR_OVERWRITE );
393
 
394
  // Split host:port into $host and $port
395
+ list( $host, $port ) = Util_Content::endpoint_to_host_port( $host, 3306 );
 
 
 
 
 
396
 
397
  $this->wpdb_mixin->timer_start();
398
 
Enterprise_SnsServer.php CHANGED
@@ -109,6 +109,9 @@ class Enterprise_SnsServer extends Enterprise_SnsBase {
109
  $executor->minifycache_flush();
110
  elseif ( $action == 'browsercache_flush' )
111
  $executor->browsercache_flush();
 
 
 
112
  elseif ( $action == 'cdn_purge_files' )
113
  $executor->cdn_purge_files( $m['purgefiles'] );
114
  elseif ( $action == 'pgcache_cleanup' )
109
  $executor->minifycache_flush();
110
  elseif ( $action == 'browsercache_flush' )
111
  $executor->browsercache_flush();
112
+ elseif ( $action == 'cdn_purge_all' )
113
+ $executor->cdn_purge_all(
114
+ isset( $m['extras'] ) ? $m['extras'] : null );
115
  elseif ( $action == 'cdn_purge_files' )
116
  $executor->cdn_purge_files( $m['purgefiles'] );
117
  elseif ( $action == 'pgcache_cleanup' )
Extension_Amp_Plugin.php CHANGED
@@ -11,6 +11,8 @@ class Extension_Amp_Plugin {
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_footer_comment',
15
  array( $this, 'w3tc_footer_comment' ) );
16
  add_filter( 'w3tc_newrelic_should_disable_auto_rum',
@@ -19,7 +21,8 @@ class Extension_Amp_Plugin {
19
  array( $this, 'x_flush_post_queued_urls' ) );
20
  add_filter( 'varnish_flush_post_queued_urls',
21
  array( $this, 'x_flush_post_queued_urls' ) );
22
-
 
23
  }
24
 
25
 
@@ -27,22 +30,22 @@ class Extension_Amp_Plugin {
27
  private function is_amp_endpoint() {
28
  // support for different plugins defining those own functions
29
  if ( is_null( $this->is_amp_endpoint ) ) {
30
- if ( function_exists('is_amp_endpoint') ) {
31
  $this->is_amp_endpoint = is_amp_endpoint();
32
- } elseif ( function_exists('ampforwp_is_amp_endpoint') ) {
33
  $this->is_amp_endpoint = ampforwp_is_amp_endpoint();
 
 
34
  }
35
  }
36
 
37
- return $this->is_amp_endpoint;
38
  }
39
 
40
 
41
 
42
  public function w3tc_minify_jscss_enable( $enabled ) {
43
- $is_amp_endpoint = $this->is_amp_endpoint();
44
-
45
- if ( !is_null( $is_amp_endpoint ) && $is_amp_endpoint ) {
46
  // amp has own rules for CSS and JS files, don't touch them by default
47
  return false;
48
  }
@@ -53,9 +56,7 @@ class Extension_Amp_Plugin {
53
 
54
 
55
  public function w3tc_newrelic_should_disable_auto_rum( $reject_reason ) {
56
- $is_amp_endpoint = $this->is_amp_endpoint();
57
-
58
- if ( !is_null( $is_amp_endpoint ) && $is_amp_endpoint ) {
59
  return 'AMP endpoint';
60
  }
61
 
@@ -64,6 +65,17 @@ class Extension_Amp_Plugin {
64
 
65
 
66
 
 
 
 
 
 
 
 
 
 
 
 
67
  public function x_flush_post_queued_urls( $queued_urls ) {
68
  $amp_urls = array();
69
 
@@ -78,14 +90,54 @@ class Extension_Amp_Plugin {
78
 
79
 
80
  public function w3tc_footer_comment( $strings ) {
81
- $is_amp_endpoint = $this->is_amp_endpoint();
82
-
83
- if ( !is_null( $is_amp_endpoint ) && $is_amp_endpoint ) {
84
  $strings[] = 'AMP page, minification is limited';
85
  }
86
 
87
  return $strings;
88
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
90
 
91
 
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',
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
 
30
  private function is_amp_endpoint() {
31
  // support for different plugins defining those own functions
32
  if ( is_null( $this->is_amp_endpoint ) ) {
33
+ if ( function_exists( 'is_amp_endpoint' ) ) {
34
  $this->is_amp_endpoint = is_amp_endpoint();
35
+ } elseif ( function_exists( 'ampforwp_is_amp_endpoint' ) ) {
36
  $this->is_amp_endpoint = ampforwp_is_amp_endpoint();
37
+ } elseif ( function_exists( 'is_better_amp' ) ) {
38
+ $this->is_amp_endpoint = is_better_amp();
39
  }
40
  }
41
 
42
+ return is_null( $this->is_amp_endpoint ) ? false : $this->is_amp_endpoint;
43
  }
44
 
45
 
46
 
47
  public function w3tc_minify_jscss_enable( $enabled ) {
48
+ if ( $this->is_amp_endpoint() ) {
 
 
49
  // amp has own rules for CSS and JS files, don't touch them by default
50
  return false;
51
  }
56
 
57
 
58
  public function w3tc_newrelic_should_disable_auto_rum( $reject_reason ) {
59
+ if ( $this->is_amp_endpoint() ) {
 
 
60
  return 'AMP endpoint';
61
  }
62
 
65
 
66
 
67
 
68
+ public function w3tc_lazyload_can_process( $can_process ) {
69
+ if ( $this->is_amp_endpoint() ) {
70
+ $can_process['enabled'] = false;
71
+ $can_process['reason'] = 'AMP endpoint';
72
+ }
73
+
74
+ return $can_process;
75
+ }
76
+
77
+
78
+
79
  public function x_flush_post_queued_urls( $queued_urls ) {
80
  $amp_urls = array();
81
 
90
 
91
 
92
  public function w3tc_footer_comment( $strings ) {
93
+ if ( $this->is_amp_endpoint() ) {
 
 
94
  $strings[] = 'AMP page, minification is limited';
95
  }
96
 
97
  return $strings;
98
  }
99
+
100
+
101
+
102
+ public function w3tc_pagecache_set( $data ) {
103
+ if ( $this->is_amp_endpoint() ) {
104
+ // workaround to prevent Link headers from parent page
105
+ // to appear in amp page coming from it's .htaccess
106
+ $c = Dispatcher::config();
107
+ if ( $c->getf_boolean( 'minify.css.http2push' ) ||
108
+ $c->getf_boolean( 'minify.js.http2push' ) ) {
109
+ $data['headers'][] = array(
110
+ 'n' => 'Link', 'v' => '', 'files_match' => '\\.html[_a-z]*$' );
111
+
112
+ $this->w3tc_pagecache_set_header_register_once();
113
+ }
114
+ }
115
+
116
+ return $data;
117
+ }
118
+
119
+
120
+
121
+ private function w3tc_pagecache_set_header_register_once() {
122
+ static $registered = false;
123
+
124
+ if ( !$registered ) {
125
+ add_filter( 'w3tc_pagecache_set_header',
126
+ array( $this, 'w3tc_pagecache_set_header' ), 20, 2 );
127
+ }
128
+ }
129
+
130
+
131
+
132
+ public function w3tc_pagecache_set_header( $header, $header_original ) {
133
+ if ( $header_original['n'] == 'Link' && empty( $header_original['v'] ) ) {
134
+ // forces removal of Link header for file_generic when its set by
135
+ // parent .htaccess
136
+ return $header_original;
137
+ }
138
+
139
+ return $header;
140
+ }
141
  }
142
 
143
 
Extension_FragmentCache_GeneralPage_View.php CHANGED
@@ -4,7 +4,7 @@ namespace W3TC;
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
- Util_Ui::postbox_header( 'Fragment Cache', '', 'fragment_cache' );
8
  ?>
9
  <p>Enable fragment caching reduce execution time for common operations.</p>
10
 
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
+ Util_Ui::postbox_header( 'Fragment Cache', '', 'fragmentcache' );
8
  ?>
9
  <p>Enable fragment caching reduce execution time for common operations.</p>
10
 
Extension_FragmentCache_Page_View.php CHANGED
@@ -4,6 +4,8 @@ namespace W3TC;
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
 
 
7
  ?>
8
  <p id="w3tc-options-menu">
9
  Jump to:
@@ -13,22 +15,31 @@ if ( !defined( 'W3TC' ) )
13
  <a href="#advanced"><?php _e( 'Advanced', 'w3-total-cache' ); ?></a>
14
  </p>
15
  <p>
16
- Fragment caching via <strong><?php
17
- echo Cache::engine_name( $config->get_string( array( 'fragmentcache', 'engine' ) ) )
18
- ?></strong> is currently <?php
19
- if ( $config->is_extension_active_frontend( 'fragmentcache' ) )
20
- echo '<span class="w3tc-enabled">enabled</span>';
21
- else {
22
- echo '<span class="w3tc-disabled">disabled</span>';
23
- $ext = Extensions_Util::get_extension( $config, 'fragmentcache' );
24
 
25
- if ( !empty( $ext['requirements'] ) ) {
26
- echo ' (<span class="description">' .
27
- $ext['requirements'] .
28
- '</span>)';
29
- }
30
- }
31
- ?>.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  <p>
33
 
34
  <form action="admin.php?page=w3tc_fragmentcache" method="post">
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
+ $engine = $config->get_string( array( 'fragmentcache', 'engine' ) );
8
+
9
  ?>
10
  <p id="w3tc-options-menu">
11
  Jump to:
15
  <a href="#advanced"><?php _e( 'Advanced', 'w3-total-cache' ); ?></a>
16
  </p>
17
  <p>
18
+ <?php Util_Ui::pro_wrap_maybe_start2() ?>
 
 
 
 
 
 
 
19
 
20
+ Fragment caching
21
+ <?php if ( !empty( $engine ) ): ?>
22
+ via
23
+ <strong><?php echo Cache::engine_name( $engine ) ?>?></strong>
24
+ <?php endif ?>
25
+
26
+ is currently
27
+ <?php if ( $config->is_extension_active_frontend( 'fragmentcache' ) ): ?>
28
+ <span class="w3tc-enabled">enabled</span>
29
+ <?php else: ?>
30
+ <span class="w3tc-disabled">disabled</span>
31
+ <?php
32
+ $ext = Extensions_Util::get_extension( $config, 'fragmentcache' );
33
+ if ( !empty( $ext['requirements'] ) ) {
34
+ echo ' (<span class="description">' .
35
+ $ext['requirements'] .
36
+ '</span>)';
37
+ }
38
+ ?>
39
+ <?php endif ?>
40
+ .
41
+
42
+ <?php Util_Ui::pro_wrap_maybe_end2('fragmentcache_header') ?>
43
  <p>
44
 
45
  <form action="admin.php?page=w3tc_fragmentcache" method="post">
Extension_FragmentCache_Plugin_Admin.php CHANGED
@@ -12,8 +12,6 @@ class Extension_FragmentCache_Plugin_Admin {
12
  */
13
  static public function w3tc_extensions( $extensions, $config ) {
14
  $requirements = array();
15
- if ( !Util_Environment::is_w3tc_pro( $config ) )
16
- $requirements[] = 'Available after <a href="#" class="button-buy-plugin" data-src="fc_requirements">upgrade</a>';
17
 
18
  $extensions['fragmentcache'] = array (
19
  'name' => 'Fragment Cache',
@@ -22,6 +20,7 @@ class Extension_FragmentCache_Plugin_Admin {
22
  'author_uri' => 'https://www.w3-edge.com/',
23
  'extension_uri' => 'https://www.w3-edge.com/',
24
  'extension_id' => 'fragmentcache',
 
25
  'settings_exists' => true,
26
  'version' => '1.0',
27
  'enabled' => empty( $requirements ),
12
  */
13
  static public function w3tc_extensions( $extensions, $config ) {
14
  $requirements = array();
 
 
15
 
16
  $extensions['fragmentcache'] = array (
17
  'name' => 'Fragment Cache',
20
  'author_uri' => 'https://www.w3-edge.com/',
21
  'extension_uri' => 'https://www.w3-edge.com/',
22
  'extension_id' => 'fragmentcache',
23
+ 'pro_feature' => true,
24
  'settings_exists' => true,
25
  'version' => '1.0',
26
  'enabled' => empty( $requirements ),
Extension_Genesis_Plugin_Admin.php CHANGED
@@ -29,9 +29,6 @@ class Extension_Genesis_Plugin_Admin {
29
  $requirements[] =
30
  'Optimizes "Genesis Framework" version >= 1.9.0, which is not active';
31
 
32
- if ( empty( $requirements ) && !Util_Environment::is_w3tc_pro( $config ) )
33
- $requirements[] = 'Available after <a href="#" class="button-buy-plugin" data-src="genesis_requirements">upgrade</a>';
34
-
35
  if ( !$config->is_extension_active( 'fragmentcache' ) )
36
  $requirements[] = 'Activate "Fragment Cache" extension first';
37
 
@@ -42,6 +39,7 @@ class Extension_Genesis_Plugin_Admin {
42
  'author_uri' => 'https://www.w3-edge.com/',
43
  'extension_uri' => 'https://www.w3-edge.com/',
44
  'extension_id' => 'genesis.theme',
 
45
  'settings_exists' => true,
46
  'version' => '0.1',
47
  'enabled' => empty( $requirements ),
29
  $requirements[] =
30
  'Optimizes "Genesis Framework" version >= 1.9.0, which is not active';
31
 
 
 
 
32
  if ( !$config->is_extension_active( 'fragmentcache' ) )
33
  $requirements[] = 'Activate "Fragment Cache" extension first';
34
 
39
  'author_uri' => 'https://www.w3-edge.com/',
40
  'extension_uri' => 'https://www.w3-edge.com/',
41
  'extension_id' => 'genesis.theme',
42
+ 'pro_feature' => true,
43
  'settings_exists' => true,
44
  'version' => '0.1',
45
  'enabled' => empty( $requirements ),
Extension_NewRelic_Plugin_Admin.php CHANGED
@@ -17,7 +17,7 @@ class Extension_NewRelic_Plugin_Admin {
17
  $extensions['newrelic'] = array (
18
  'name' => 'New Relic',
19
  'author' => 'W3 EDGE',
20
- 'description' => __( 'New Relic is software analytics platform offering app performance management and mobile monitoring solutions.', 'w3-total-cache' ),
21
  'author_uri' => 'https://www.w3-edge.com/',
22
  'extension_uri' => 'https://www.w3-edge.com/',
23
  'extension_id' => 'newrelic',
17
  $extensions['newrelic'] = array (
18
  'name' => 'New Relic',
19
  'author' => 'W3 EDGE',
20
+ 'description' => __( 'Legacy: New Relic is software analytics platform offering app performance management and mobile monitoring solutions.', 'w3-total-cache' ),
21
  'author_uri' => 'https://www.w3-edge.com/',
22
  'extension_uri' => 'https://www.w3-edge.com/',
23
  'extension_id' => 'newrelic',
Extension_Wpml_Plugin_Admin.php CHANGED
@@ -42,8 +42,6 @@ class Extension_Wpml_Plugin_Admin {
42
  $requirements[] = 'Ensure "WPML" plugin compatibility, which is not currently active.';
43
  if ( empty( $requirements ) && !Util_Environment::is_w3tc_pro( $config ) ) {
44
  $enabled = false;
45
- $requirements[] = 'Available after <a href="#" class="button-buy-plugin" data-src="wpml_requirements">upgrade</a>';
46
- $disabled_message = '<a href="#" class="button-buy-plugin" data-src="wpml_requirements2">upgrade</a>';
47
  }
48
 
49
  $extensions['wpml'] = array(
@@ -54,6 +52,7 @@ class Extension_Wpml_Plugin_Admin {
54
  'author_uri' => 'https://www.w3-edge.com/',
55
  'extension_uri' => 'https://www.w3-edge.com/',
56
  'extension_id' => 'wpml',
 
57
  'settings_exists' => false,
58
  'version' => '0.1',
59
  'enabled' => $enabled,
42
  $requirements[] = 'Ensure "WPML" plugin compatibility, which is not currently active.';
43
  if ( empty( $requirements ) && !Util_Environment::is_w3tc_pro( $config ) ) {
44
  $enabled = false;
 
 
45
  }
46
 
47
  $extensions['wpml'] = array(
52
  'author_uri' => 'https://www.w3-edge.com/',
53
  'extension_uri' => 'https://www.w3-edge.com/',
54
  'extension_id' => 'wpml',
55
+ 'pro_feature' => true,
56
  'settings_exists' => false,
57
  'version' => '0.1',
58
  'enabled' => $enabled,
Generic_Page_Dashboard_View.css CHANGED
@@ -107,6 +107,14 @@
107
  float: left;
108
  }
109
 
 
 
 
 
 
 
 
 
110
  #normal-sortables .postbox {
111
  float:left;
112
  margin-right:10px;
107
  float: left;
108
  }
109
 
110
+ .w3tc-widget-boldgrid-logo {
111
+ width: 70%;
112
+ height: 100%;
113
+ background: url("Generic_WidgetBoldGrid_Logo.svg") 0 0px no-repeat;
114
+ float: left;
115
+ margin-right: 10px;
116
+ }
117
+
118
  #normal-sortables .postbox {
119
  float:left;
120
  margin-right:10px;
Generic_Plugin.php CHANGED
@@ -518,7 +518,7 @@ class Generic_Plugin {
518
  }
519
 
520
  if ( $this->is_wp_die ) {
521
- status_header( 503 );
522
  } else {
523
  $buffer = apply_filters( 'w3tc_process_content', $buffer );
524
 
@@ -554,8 +554,15 @@ class Generic_Plugin {
554
  }
555
 
556
  $buffer = Util_Bus::do_ob_callbacks(
557
- array( 'swarmify', 'minify', 'newrelic', 'cdn', 'browsercache', 'pagecache' ),
558
- $buffer );
 
 
 
 
 
 
 
559
 
560
  $buffer = apply_filters( 'w3tc_processed_content', $buffer );
561
  }
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 );
524
 
554
  }
555
 
556
  $buffer = Util_Bus::do_ob_callbacks(
557
+ array(
558
+ 'swarmify',
559
+ 'lazyload',
560
+ 'minify',
561
+ 'newrelic',
562
+ 'cdn',
563
+ 'browsercache',
564
+ 'pagecache'
565
+ ), $buffer );
566
 
567
  $buffer = apply_filters( 'w3tc_processed_content', $buffer );
568
  }
Generic_Plugin_Admin.php CHANGED
@@ -41,6 +41,9 @@ class Generic_Plugin_Admin {
41
  add_action( 'admin_init_w3tc_dashboard', array(
42
  '\W3TC\Generic_WidgetServices',
43
  'admin_init_w3tc_dashboard' ) );
 
 
 
44
 
45
  add_action( 'admin_enqueue_scripts', array(
46
  $this,
@@ -302,6 +305,13 @@ class Generic_Plugin_Admin {
302
  font-family: 'w3tc';
303
  }
304
  </style>
 
 
 
 
 
 
 
305
  <?php
306
  }
307
 
41
  add_action( 'admin_init_w3tc_dashboard', array(
42
  '\W3TC\Generic_WidgetServices',
43
  'admin_init_w3tc_dashboard' ) );
44
+ add_action( 'admin_init_w3tc_dashboard', array(
45
+ '\W3TC\Generic_WidgetBoldGrid',
46
+ 'admin_init_w3tc_dashboard' ) );
47
 
48
  add_action( 'admin_enqueue_scripts', array(
49
  $this,
305
  font-family: 'w3tc';
306
  }
307
  </style>
308
+ <script>
309
+ jQuery(document).ready( function($) {
310
+ $('#toplevel_page_w3tc_dashboard ul li').find('a[href*="w3tc_faq"]')
311
+ .prop('target','_blank')
312
+ .prop('href', <?php echo json_encode(W3TC_FAQ_URL) ?>);
313
+ });
314
+ </script>
315
  <?php
316
  }
317
 
Generic_WidgetBoldGrid.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class Generic_WidgetBoldGrid {
5
+ static public function admin_init_w3tc_dashboard() {
6
+ $o = new Generic_WidgetBoldGrid();
7
+
8
+ add_action( 'w3tc_widget_setup', array( $o, 'wp_dashboard_setup' ), 3000 );
9
+ add_action( 'w3tc_network_dashboard_setup',
10
+ array( $o, 'wp_dashboard_setup' ), 5000 );
11
+
12
+ add_thickbox();
13
+ wp_enqueue_script( 'plugin-install' );
14
+
15
+ wp_enqueue_script( 'w3tc-boldgrid-widget',
16
+ plugins_url( 'Generic_WidgetBoldGrid_View.js', W3TC_FILE ),
17
+ array( 'thickbox' ), W3TC_VERSION );
18
+ }
19
+
20
+
21
+
22
+ function wp_dashboard_setup() {
23
+ $show = apply_filters( 'w3tc_generic_boldgrid_show', $this->should_show_widget() );
24
+ if ( !$show ) {
25
+ return;
26
+ }
27
+
28
+ Util_Widget::add( 'w3tc_boldgrid',
29
+ '<div class="w3tc-widget-boldgrid-logo"></div>',
30
+ array( $this, 'widget_form' ),
31
+ self_admin_url(
32
+ 'plugin-install.php?tab=plugin-information&amp;plugin=boldgrid-backup' .
33
+ '&amp;TB_iframe=true&amp;width=772&amp;height=550'
34
+ ), 'normal', __( 'View Details' ), 'thickbox open-plugin-details-modal' );
35
+ }
36
+
37
+
38
+
39
+ /**
40
+ * Determine whether or not we should show the backup widget.
41
+ *
42
+ * We will only recommend the backup plugin if we detect that the user is not already
43
+ * running a popular WordPress backup plugin.
44
+ *
45
+ * @since 0.11.0
46
+ *
47
+ * @return bool
48
+ */
49
+ private function should_show_widget() {
50
+ $plugins = get_option( 'active_plugins' );
51
+
52
+ $backup_plugins = array(
53
+ 'backup/backup.php',
54
+ 'backwpup/backwpup.php',
55
+ 'boldgrid-backup/boldgrid-backup.php',
56
+ 'duplicator/duplicator.php',
57
+ 'updraftplus/updraftplus.php',
58
+ 'wpvivid-backuprestore/wpvivid-backuprestore.php'
59
+ );
60
+
61
+ foreach ( $plugins as $plugin ) {
62
+ if ( in_array( $plugin, $backup_plugins ) ) {
63
+ return false;
64
+ }
65
+ }
66
+
67
+ return true;
68
+ }
69
+
70
+
71
+
72
+ public function widget_form() {
73
+ $install_url = wp_nonce_url(
74
+ 'admin.php?page=w3tc_dashboard&w3tc_boldgrid_install', 'w3tc' );
75
+
76
+ include W3TC_DIR . '/Generic_WidgetBoldGrid_View.php';
77
+ }
78
+ }
Generic_WidgetBoldGrid_AdminActions.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class Generic_WidgetBoldGrid_AdminActions {
5
+ function w3tc_boldgrid_install() {
6
+ $plugin_file = 'boldgrid-backup/boldgrid-backup.php';
7
+ $slug = 'boldgrid-backup';
8
+
9
+ $plugins = get_plugins();
10
+
11
+ if ( isset( $plugins[$plugin_file] ) ) {
12
+ $install_url = 'plugins.php?action=activate' .
13
+ '&plugin=' . urlencode( $plugin_file ) .
14
+ '&plugin_status=all&paged=1&s&_wpnonce=' .
15
+ wp_create_nonce( 'activate-plugin_' . $plugin_file );
16
+ } else {
17
+ $install_url =
18
+ 'update.php?action=install-plugin&plugin=' . $slug .
19
+ '&_wpnonce=' . wp_create_nonce( 'install-plugin_' . $slug );
20
+ }
21
+
22
+ wp_redirect( $install_url );
23
+ exit();
24
+ }
25
+ }
Generic_WidgetBoldGrid_Logo.svg ADDED
@@ -0,0 +1 @@
 
1
+ <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1027.74 143.07"><defs><style>.cls-1{fill:#000;}.cls-2{fill:#1a1a1a;}</style></defs><title>boldgrid-logo-horizontal-black</title><rect class="cls-1" x="28.5" y="78.46" width="68.07" height="38.4" rx="5.33" ry="5.33"/><rect class="cls-1" x="28.5" y="26.21" width="44.74" height="38.4" rx="4.64" ry="4.64"/><path class="cls-1" d="M123.55,143.07h-104A19.54,19.54,0,0,1,0,123.55v-104A19.54,19.54,0,0,1,19.51,0h104a19.54,19.54,0,0,1,19.51,19.51v4.39a5.25,5.25,0,1,1-10.51,0V19.51a9,9,0,0,0-9-9h-104a9,9,0,0,0-9,9v104a9,9,0,0,0,9,9h104a9,9,0,0,0,9-9V73a9,9,0,0,0-9-9H102.09a5.25,5.25,0,1,1,0-10.51h21.46A19.54,19.54,0,0,1,143.07,73v50.5A19.54,19.54,0,0,1,123.55,143.07Z"/><path class="cls-2" d="M237.06,123.24V19.83h27a55.25,55.25,0,0,1,13.22,1.48,28.51,28.51,0,0,1,10.19,4.58,21.12,21.12,0,0,1,6.57,8.05,27,27,0,0,1,2.36,11.75,29.66,29.66,0,0,1-4.36,16.1q-4.36,6.94-13.22,9.46a31.22,31.22,0,0,1,8.05,3,24,24,0,0,1,6.8,5.32A26.6,26.6,0,0,1,298.37,87a24.91,24.91,0,0,1,1.77,9.6,23.13,23.13,0,0,1-2.81,11.6,25.54,25.54,0,0,1-7.46,8.27,34.06,34.06,0,0,1-10.71,5,45.71,45.71,0,0,1-12.41,1.7ZM249.32,31.5V65.33h16q8.72,0,13.81-4.88t5.1-12.85q0-8.72-5.32-12.41T265,31.5Zm0,45.5v34.57h16.4a34,34,0,0,0,8.57-1,21.25,21.25,0,0,0,7-3.18,16.25,16.25,0,0,0,4.8-5.24,14.64,14.64,0,0,0,1.77-7.39,15.06,15.06,0,0,0-2.07-8,17.08,17.08,0,0,0-5.39-5.54A24.48,24.48,0,0,0,272.67,78a39.6,39.6,0,0,0-9-1Z"/><path class="cls-2" d="M332.94,71.68a51.5,51.5,0,0,1,4.14-20.46,53.43,53.43,0,0,1,28.07-28.37,52,52,0,0,1,41,0,54,54,0,0,1,28.37,28.37,52,52,0,0,1,0,41,53.44,53.44,0,0,1-28.37,28.07,52.86,52.86,0,0,1-41,0,52.9,52.9,0,0,1-28.07-28.07A51.33,51.33,0,0,1,332.94,71.68Zm12.26,0a40.76,40.76,0,0,0,11.89,29A42,42,0,0,0,370,109.5a40.07,40.07,0,0,0,31.62,0,42,42,0,0,0,12.93-8.79,41.59,41.59,0,0,0,8.72-45.06,41.36,41.36,0,0,0-21.64-21.94,40.07,40.07,0,0,0-31.62,0,41.36,41.36,0,0,0-21.64,21.94A40.47,40.47,0,0,0,345.2,71.68Z"/><path class="cls-2" d="M466.94,123.24V19.83H479.2v91.74h53.48v11.67Z"/><path class="cls-2" d="M565,19.83h24.08a55.74,55.74,0,0,1,20.09,3.62,49,49,0,0,1,16.55,10.42A49.78,49.78,0,0,1,637,50.19a53.47,53.47,0,0,1,4.14,21.5,56.8,56.8,0,0,1-3,17.88,45.9,45.9,0,0,1-9.83,16.62,51.76,51.76,0,0,1-17.65,12.26q-10.86,4.8-26.52,4.8H565ZM577.29,31.5v79.92h10.34a46.17,46.17,0,0,0,16.25-2.81A37.44,37.44,0,0,0,625.68,88a41,41,0,0,0,3.18-16.47A41.5,41.5,0,0,0,625.68,55,37.66,37.66,0,0,0,617,42.36a38.18,38.18,0,0,0-13.07-8.05,46.23,46.23,0,0,0-16.25-2.81Z"/><path class="cls-2" d="M725.62,84.83V78.92h19.5q4.43,0,6.21,1.63t1.77,5.91V117a58.78,58.78,0,0,1-12.63,5.39,49.9,49.9,0,0,1-14.26,2,51.32,51.32,0,0,1-20.54-4.14,52.89,52.89,0,0,1-28.07-28.07,51.34,51.34,0,0,1-4.14-20.54,51.88,51.88,0,0,1,4.14-20.61,53,53,0,0,1,11.3-16.84,54.28,54.28,0,0,1,16.77-11.38,50.55,50.55,0,0,1,20.54-4.21,51.71,51.71,0,0,1,14.26,1.92A55.35,55.35,0,0,1,753.25,26q-.89,1.19-1.7,2.51t-1.7,2.51a46.05,46.05,0,0,0-11.15-4.8,45.56,45.56,0,0,0-12.48-1.7,44.13,44.13,0,0,0-18.1,3.77,48,48,0,0,0-14.85,10.19,47.26,47.26,0,0,0-10,15,46.55,46.55,0,0,0-3.62,18.32,45.64,45.64,0,0,0,3.62,18.1,46.56,46.56,0,0,0,10,14.85,48.09,48.09,0,0,0,14.7,10,43.84,43.84,0,0,0,18,3.69,45.14,45.14,0,0,0,21-5V88.67a4.75,4.75,0,0,0-.74-2.81q-.74-1-3.25-1Z"/><path class="cls-2" d="M795.2,123.24V19.83h22.16a38.81,38.81,0,0,1,10,1.48A34.16,34.16,0,0,1,837.68,26a28.06,28.06,0,0,1,8.05,8.42A22.86,22.86,0,0,1,849,46.86q0,10.64-5.69,17.65t-16.47,9.23q5.91,12.56,11.75,24.82t11.6,24.67h-6.65Q837.75,110.83,832,98.72T820.47,74.34c-.89.1-1.75.17-2.58.22s-1.7.07-2.59.07h-14v48.61Zm6.06-54.66h15.37a34.18,34.18,0,0,0,12.78-2.07,22.43,22.43,0,0,0,8.13-5.32,18.37,18.37,0,0,0,4.21-7,24.4,24.4,0,0,0,1.18-7.31,17.11,17.11,0,0,0-2-8,22.06,22.06,0,0,0-5.54-6.8A27,27,0,0,0,827,27.43a30.58,30.58,0,0,0-10.27-1.7H801.26Z"/><path class="cls-2" d="M897.88,19.83h6.06V123.24h-6.06Z"/><path class="cls-2" d="M954,19.83h21.72a55.74,55.74,0,0,1,20.09,3.62,49.55,49.55,0,0,1,16.55,10.34,48.78,48.78,0,0,1,11.23,16.32,53.64,53.64,0,0,1,4.14,21.42,56.8,56.8,0,0,1-3,17.88,46.6,46.6,0,0,1-9.82,16.69,51.25,51.25,0,0,1-17.66,12.34q-10.86,4.8-26.52,4.8H954Zm6.06,5.91v91.45h12.85a54.16,54.16,0,0,0,21.42-3.92A45.26,45.26,0,0,0,1009.56,103a41.93,41.93,0,0,0,9.08-14.55,48.47,48.47,0,0,0,3-16.92,48,48,0,0,0-3.62-19,42.57,42.57,0,0,0-24.52-23.64,49.67,49.67,0,0,0-17.8-3.18Z"/></svg>
Generic_WidgetBoldGrid_View.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( document ).ready( function( $ ) {
2
+ $( window ).on( 'message', function( event ) {
3
+ var originalEvent = event.originalEvent,
4
+ expectedOrigin = document.location.protocol + '//' + document.location.hostname,
5
+ message;
6
+
7
+ if ( originalEvent.origin !== expectedOrigin ) {
8
+ return;
9
+ }
10
+
11
+ try {
12
+ message = $.parseJSON( originalEvent.data );
13
+ } catch ( e ) {
14
+ return;
15
+ }
16
+
17
+ if ( ! message || 'undefined' === typeof message.action ) {
18
+ return;
19
+ }
20
+
21
+ if (message.action == 'install-plugin') {
22
+ window.location = $('#w3tc-boldgrid-install').attr('href');
23
+ }
24
+ });
25
+ });
Generic_WidgetBoldGrid_View.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <div>
9
+ <p class="notice notice-error">W3 Total Cache has detected that you do not have a Backup Plugin installed.</p>
10
+ <p>
11
+ <strong>
12
+ Protect your WordPress site from data loss by installing the FREE
13
+ Total Upkeep plugin.
14
+ </strong>
15
+ </p>
16
+
17
+ <p>
18
+ It's easy to set up and manage, backs up your entire WordPress site, has automated fault protection if an update fails, and provides easy site migration options.
19
+ </p>
20
+
21
+ <a href="<?php echo esc_url( $install_url ) ?>" id="w3tc-boldgrid-install"
22
+ class="button-primary">Install Free Backup Plugin</a>
23
+ </div>
LICENSE ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Lesser General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Public License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Public License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Public License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Public License instead of this License.
LazyLoad_GeneralPage.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class LazyLoad_GeneralPage {
7
+ /**
8
+ * W3TC General settings page modifications
9
+ */
10
+ static public function admin_init_w3tc_general() {
11
+ $o = new LazyLoad_GeneralPage();
12
+
13
+ add_filter( 'w3tc_settings_general_anchors',
14
+ array( $o, 'w3tc_settings_general_anchors' ) );
15
+ add_action( 'w3tc_settings_general_boxarea_userexperience',
16
+ array( $o, 'w3tc_settings_general_boxarea_userexperience' ) );
17
+ }
18
+
19
+
20
+
21
+
22
+ public function w3tc_settings_general_anchors( $anchors ) {
23
+ $anchors[] = array( 'id' => 'userexperience', 'text' => 'User Experience' );
24
+ return $anchors;
25
+ }
26
+
27
+
28
+
29
+ public function w3tc_settings_general_boxarea_userexperience() {
30
+ $config = Dispatcher::config();
31
+
32
+ include W3TC_DIR . '/LazyLoad_GeneralPage_View.php';
33
+ }
34
+ }
LazyLoad_GeneralPage_View.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <?php
9
+ Util_Ui::postbox_header( __( 'User Experience', 'w3-total-cache' ), '', 'userexperience' );
10
+ Util_Ui::config_overloading_button( array(
11
+ 'key' => 'lazyload.configuration_overloaded'
12
+ ) );
13
+ ?>
14
+
15
+ <table class="form-table">
16
+ <?php
17
+ Util_Ui::config_item( array(
18
+ 'key' => 'lazyload.enabled',
19
+ 'control' => 'checkbox',
20
+ 'checkbox_label' => __( 'Lazy Loading', 'w3-total-cache' ),
21
+ 'description' => __( 'Defer loading offscreen images.',
22
+ 'w3-total-cache' )
23
+ ) );
24
+ ?>
25
+ </table>
26
+
27
+ <?php Util_Ui::button_config_save( 'general_userexperience' ); ?>
28
+ <?php Util_Ui::postbox_footer(); ?>
LazyLoad_Page.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class LazyLoad_Page {
7
+ public function render_content() {
8
+ $c = Dispatcher::config();
9
+ include W3TC_DIR . '/LazyLoad_Page_View.php';
10
+ }
11
+ }
LazyLoad_Page_View.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <p>
9
+ Lazy loading is currently
10
+ <?php if ( $c->get_boolean( 'lazyload.enabled' ) ): ?>
11
+ <span class="w3tc-enabled">enabled</span>
12
+ <?php else: ?>
13
+ <span class="w3tc-disabled">disabled</span>
14
+ <?php endif ?>
15
+ .
16
+ <p>
17
+
18
+ <form action="admin.php?page=w3tc_userexperience" method="post">
19
+ <div class="metabox-holder">
20
+ <?php Util_Ui::postbox_header( __( 'Lazy Loading', 'w3-total-cache' ), '', 'application' ); ?>
21
+ <table class="form-table">
22
+ <?php
23
+ Util_Ui::config_item( array(
24
+ 'key' => 'lazyload.process_img',
25
+ 'control' => 'checkbox',
26
+ 'checkbox_label' => __( 'Process HTML image tags', 'w3-total-cache' ),
27
+ 'description' => __( 'Process <code>img</code> tags',
28
+ 'w3-total-cache' )
29
+ ) );
30
+
31
+ Util_Ui::config_item( array(
32
+ 'key' => 'lazyload.process_background',
33
+ 'control' => 'checkbox',
34
+ 'checkbox_label' => __( 'Process background images', 'w3-total-cache' ),
35
+ 'description' => __( 'Process <code>background</code> styles',
36
+ 'w3-total-cache' )
37
+ ) );
38
+
39
+ Util_Ui::config_item( array(
40
+ 'key' => 'lazyload.exclude',
41
+ 'label' => 'Exclude words:',
42
+ 'control' => 'textarea',
43
+ 'description' => __( 'Exclude tags containing words',
44
+ 'w3-total-cache' )
45
+ ) );
46
+
47
+ Util_Ui::config_item( array(
48
+ 'key' => 'lazyload.embed_method',
49
+ 'label' => __( 'Script Embed method:', 'w3-total-cache' ),
50
+ 'control' => 'selectbox',
51
+ 'selectbox_values' => array(
52
+ 'async_head' => 'async',
53
+ 'sync_head' => 'sync (to head)',
54
+ 'inline_footer' => 'inline'
55
+ ),
56
+ 'description' => 'Use <code>inline</code> method only when your website has just a few pages'
57
+ )
58
+ );
59
+ ?>
60
+ </table>
61
+ <p class="submit">
62
+ <?php Util_Ui::button_config_save( 'lazyload' ); ?>
63
+ </p>
64
+
65
+ <?php Util_Ui::postbox_footer(); ?>
66
+ </form>
67
+ </div>
LazyLoad_Plugin.php ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
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
+ }
17
+
18
+
19
+
20
+ public function run() {
21
+ Util_Bus::add_ob_callback( 'lazyload', array( $this, 'ob_callback' ) );
22
+ $this->metaslider_hooks();
23
+
24
+ add_filter( 'wp_get_attachment_url',
25
+ array( $this, 'wp_get_attachment_url' ), 10, 2 );
26
+ }
27
+
28
+
29
+
30
+ public function ob_callback( $buffer ) {
31
+ if ( $buffer == '' || !\W3TC\Util_Content::is_html_xml( $buffer ) ) {
32
+ return $buffer;
33
+ }
34
+
35
+ $can_process = array(
36
+ 'enabled' => true,
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 );
68
+ if ( $is_embed_script ) {
69
+ $buffer = $this->embed_script( $buffer );
70
+ }
71
+ }
72
+
73
+ return $buffer;
74
+ }
75
+
76
+
77
+
78
+ private function can_process( $can_process ) {
79
+ if ( defined( 'WP_ADMIN' ) ) {
80
+ $can_process['enabled'] = false;
81
+ $can_process['reason'] = 'WP_ADMIN';
82
+
83
+ return $can_process;
84
+ }
85
+
86
+ if ( defined( 'SHORTINIT' ) && SHORTINIT ) {
87
+ $can_process['enabled'] = false;
88
+ $can_process['reason'] = 'SHORTINIT';
89
+
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
+
264
+
265
+ private function embed_script( $buffer ) {
266
+ $js_url = plugins_url( 'pub/js/lazyload.min.js', W3TC_FILE );
267
+ $method = $this->config->get_string( 'lazyload.embed_method' );
268
+
269
+ $fireEvent = 'function(t){var e;try{e=new CustomEvent("w3tc_lazyload_loaded",{detail:{e:t}})}catch(a){(e=document.createEvent("CustomEvent")).initCustomEvent("w3tc_lazyload_loaded",!1,!1,{e:t})}window.dispatchEvent(e)}';
270
+ $config = '{elements_selector:".lazy",callback_loaded:' . $fireEvent . '}';
271
+
272
+ if ( $method == 'async_head' ) {
273
+ $embed_script =
274
+ '<script>window.w3tc_lazyload=1,window.lazyLoadOptions=' . $config . '</script>' .
275
+ '<style>img.lazy{min-height:1px}</style>' .
276
+ '<script async src="' . $js_url . '"></script>';
277
+
278
+ $buffer = preg_replace( '~<head(\s+[^>]*)*>~Ui',
279
+ '\\0' . $embed_script, $buffer, 1 );
280
+
281
+ // add protection to footer if async script executed too early
282
+ $footer_script =
283
+ '<script>' .
284
+ 'document.addEventListener("DOMContentLoaded",function() {' .
285
+ 'if (typeof LazyLoad !== "undefined") {' .
286
+ 'window.w3tc_lazyload=new LazyLoad(window.lazyLoadOptions)' .
287
+ '}})</script>';
288
+ $buffer = preg_replace( '~</body(\s+[^>]*)*>~Ui',
289
+ $footer_script . '\\0', $buffer, 1 );
290
+
291
+ } elseif ( $method == 'inline_footer' ) {
292
+ $footer_script =
293
+ '<style>img.lazy{min-height:1px}</style>' .
294
+ '<script>' .
295
+ file_get_contents( W3TC_DIR . '/pub/js/lazyload.min.js' ) .
296
+ 'window.w3tc_lazyload=new LazyLoad(' . $config . ')</script>';
297
+ $buffer = preg_replace( '~</body(\s+[^>]*)*>~Ui',
298
+ $footer_script . '\\0', $buffer, 1 );
299
+ } else { // 'sync_head'
300
+ $head_script =
301
+ '<style>img.lazy{min-height:1px}</style>' .
302
+ '<script src="' . $js_url . '"></script>';
303
+ $buffer = preg_replace( '~<head(\s+[^>]*)*>~Ui',
304
+ '\\0' . $head_script, $buffer, 1 );
305
+
306
+ $footer_script =
307
+ '<script>window.w3tc_lazyload=new LazyLoad(' . $config . ')</script>';
308
+ $buffer = preg_replace( '~</body(\s+[^>]*)*>~Ui',
309
+ $footer_script . '\\0', $buffer, 1 );
310
+ }
311
+
312
+ return $buffer;
313
+ }
314
+
315
+
316
+
317
+ public function wp_get_attachment_url( $url, $post_id ) {
318
+ $this->posts_by_url[$url] = $post_id;
319
+ return $url;
320
+ }
321
+
322
+
323
+
324
+ private function metaslider_hooks() {
325
+ add_filter( 'metaslider_nivo_slider_get_html',
326
+ array( $this, 'metaslider_nivo_slider_get_html' ) );
327
+ }
328
+
329
+
330
+
331
+ public function metaslider_nivo_slider_get_html( $content ) {
332
+ // nivo slider use "src" attr of <img> tags to populate
333
+ // own image via JS, i.e. cant be replaced by lazyloading
334
+ $content = preg_replace(
335
+ '~(\s+)(class=)([\"\'])(.*?)([\"\'])~',
336
+ '$1$2$3$4 no-lazy$5', $content
337
+ );
338
+
339
+ return $content;
340
+ }
341
+ }
LazyLoad_Plugin_Admin.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class LazyLoad_Plugin_Admin {
7
+ function run() {
8
+ add_filter( 'w3tc_admin_menu', array( $this, 'w3tc_admin_menu' ) );
9
+ add_action( 'w3tc_settings_page-w3tc_userexperience',
10
+ array( $this, 'w3tc_settings_page_w3tc_userexperience' ) );
11
+ add_action( 'admin_init_w3tc_general',
12
+ array( '\W3TC\LazyLoad_GeneralPage', 'admin_init_w3tc_general' ) );
13
+ }
14
+
15
+
16
+
17
+ public function w3tc_admin_menu( $menu ) {
18
+ $c = Dispatcher::config();
19
+
20
+ $menu['w3tc_userexperience'] = array(
21
+ 'page_title' => __( 'User Experience', 'w3-total-cache' ),
22
+ 'menu_text' => __( 'User Experience', 'w3-total-cache' ),
23
+ 'visible_always' => false,
24
+ 'order' => 1200
25
+ );
26
+
27
+ return $menu;
28
+ }
29
+
30
+
31
+
32
+ public function w3tc_settings_page_w3tc_userexperience() {
33
+ $v = new LazyLoad_Page();
34
+ $v->render_content();
35
+ }
36
+ }
Licensing_AdminActions.php CHANGED
@@ -17,21 +17,30 @@ class Licensing_AdminActions {
17
  * test action
18
  */
19
  function w3tc_licensing_buy_plugin() {
20
- $iframe_url = Licensing_Core::purchase_url();
 
 
 
 
 
21
 
22
  include W3TC_INC_DIR . '/lightbox/purchase.php';
23
  }
24
 
25
 
26
 
 
 
 
 
 
27
  /**
28
  * Self test action
29
  */
30
  function w3tc_licensing_upgrade() {
31
- $data_src = '';
32
- if ( isset( $_REQUEST['data_src'] ) ) {
33
- $data_src = preg_replace( '/[^0-9a-z_]/', '', $_REQUEST['data_src'] );
34
- }
35
 
36
  include W3TC_INC_DIR . '/lightbox/upgrade.php';
37
  }
17
  * test action
18
  */
19
  function w3tc_licensing_buy_plugin() {
20
+ $data_src = $this->param( 'data_src' );
21
+ $renew_key = $this->param( 'renew_key' );
22
+ $client_id = $this->param( 'client_id' );
23
+
24
+ $iframe_url = Licensing_Core::purchase_url( $data_src, $renew_key,
25
+ $client_id );
26
 
27
  include W3TC_INC_DIR . '/lightbox/purchase.php';
28
  }
29
 
30
 
31
 
32
+ private function param( $name ) {
33
+ return preg_replace( '/[^0-9a-zA-Z._\-]/', '',
34
+ isset( $_REQUEST[$name] ) ? $_REQUEST[$name] : '' );
35
+ }
36
+
37
  /**
38
  * Self test action
39
  */
40
  function w3tc_licensing_upgrade() {
41
+ $data_src = $this->param( 'data_src' );
42
+ $renew_key = $this->param( 'renew_key' );
43
+ $client_id = $this->param( 'client_id' );
 
44
 
45
  include W3TC_INC_DIR . '/lightbox/upgrade.php';
46
  }
Licensing_Core.php CHANGED
@@ -122,9 +122,13 @@ class Licensing_Core {
122
 
123
 
124
 
125
- static public function purchase_url() {
126
  $state = Dispatcher::config_state_master();
127
  return W3TC_PURCHASE_URL .
128
- '?install_date=' . esc_attr( $state->get_integer( 'common.install' ) );
 
 
 
 
129
  }
130
  }
122
 
123
 
124
 
125
+ static public function purchase_url( $data_src = '', $renew_key = '', $client_id = '' ) {
126
  $state = Dispatcher::config_state_master();
127
  return W3TC_PURCHASE_URL .
128
+ ( strpos( W3TC_PURCHASE_URL, '?' ) === FALSE ? '?' : '&' ) .
129
+ 'install_date=' . urlencode( $state->get_integer( 'common.install' ) ) .
130
+ ( empty( $data_src ) ? '' : '&data_src=' . urlencode( $data_src ) ) .
131
+ ( empty( $renew_key ) ? '' : '&renew_key=' . urlencode( $renew_key ) ) .
132
+ ( empty( $client_id ) ? '' : '&client_id=' . urlencode( $client_id ) );
133
  }
134
  }
Licensing_Plugin_Admin.php CHANGED
@@ -46,7 +46,7 @@ class Licensing_Plugin_Admin {
46
 
47
  if ( defined( 'W3TC_DEBUG' ) && W3TC_DEBUG ) {
48
  $menu_items['90040.licensing'] = array(
49
- 'id' => 'w3tc_overlay_upgrade',
50
  'parent' => 'w3tc_debug_overlays',
51
  'title' => __( 'Upgrade', 'w3-total-cache' ),
52
  'href' => wp_nonce_url( network_admin_url(
@@ -66,7 +66,7 @@ class Licensing_Plugin_Admin {
66
  ?>
67
  <script type="text/javascript">
68
  jQuery(function() {
69
- w3tc_lightbox_upgrade(w3tc_nonce, 'test');
70
  jQuery('#w3tc-license-instruction').show();
71
  });
72
  </script>
@@ -120,9 +120,7 @@ class Licensing_Plugin_Admin {
120
  $this->maybe_update_license_status();
121
 
122
  if ( current_user_can( $capability ) ) {
123
- if ( is_admin() && Util_Admin::is_w3tc_admin_page() ) {
124
- add_filter( 'w3tc_notes', array( $this, 'w3tc_notes' ) );
125
-
126
  /**
127
  * Only admin can see W3TC notices and errors
128
  */
@@ -136,6 +134,10 @@ class Licensing_Plugin_Admin {
136
  $this,
137
  'admin_notices'
138
  ), 1, 1 );
 
 
 
 
139
  }
140
  }
141
  }
@@ -160,8 +162,11 @@ class Licensing_Plugin_Admin {
160
  if ( defined( 'W3TC_PRO' ) ) {
161
  } elseif ( $status == 'no_key' ) {
162
  } elseif ( $this->_status_is( $status, 'inactive.expired' ) ) {
163
- $message = sprintf( __( 'The W3 Total Cache license key has expired. Please renew it: %s', 'w3-total-cache' ),
164
- '<input type="button" class="button-primary button-buy-plugin {nonce: \''. wp_create_nonce( 'w3tc' ).'\'}" data-src="licensing_expired" value="'.__( 'Renew', 'w3-total-cache' ) . '" />' );
 
 
 
165
  } elseif ( $this->_status_is( $status, 'invalid' ) ) {
166
  $message = __( 'The W3 Total Cache license key you entered is not valid.', 'w3-total-cache' ) .
167
  '<a href="' . ( is_network_admin() ? network_admin_url( 'admin.php?page=w3tc_general#licensing' ):
@@ -181,10 +186,16 @@ class Licensing_Plugin_Admin {
181
  $message = __( 'The W3 Total Cache license key can\'t be verified.', 'w3-total-cache' );
182
  }
183
 
184
- if ( $message )
185
- Util_Ui::error_box( sprintf( "<p>$message. <a class='w3tc_licensing_check' href='%s'>" . __( 'check again' ) . '</a></p>',
 
 
 
 
 
186
  Util_Ui::url( array( 'page' => 'w3tc_general', 'w3tc_licensing_check_key' => 'y' ) ) )
187
  );
 
188
 
189
 
190
  if ( $this->site_inactivated ) {
46
 
47
  if ( defined( 'W3TC_DEBUG' ) && W3TC_DEBUG ) {
48
  $menu_items['90040.licensing'] = array(
49
+ 'id' => 'w3tc_debug_overlay_upgrade',
50
  'parent' => 'w3tc_debug_overlays',
51
  'title' => __( 'Upgrade', 'w3-total-cache' ),
52
  'href' => wp_nonce_url( network_admin_url(
66
  ?>
67
  <script type="text/javascript">
68
  jQuery(function() {
69
+ w3tc_lightbox_upgrade(w3tc_nonce, 'topbar_performance');
70
  jQuery('#w3tc-license-instruction').show();
71
  });
72
  </script>
120
  $this->maybe_update_license_status();
121
 
122
  if ( current_user_can( $capability ) ) {
123
+ if ( is_admin() ) {
 
 
124
  /**
125
  * Only admin can see W3TC notices and errors
126
  */
134
  $this,
135
  'admin_notices'
136
  ), 1, 1 );
137
+
138
+ if ( Util_Admin::is_w3tc_admin_page() ) {
139
+ add_filter( 'w3tc_notes', array( $this, 'w3tc_notes' ) );
140
+ }
141
  }
142
  }
143
  }
162
  if ( defined( 'W3TC_PRO' ) ) {
163
  } elseif ( $status == 'no_key' ) {
164
  } elseif ( $this->_status_is( $status, 'inactive.expired' ) ) {
165
+ $message = sprintf( __( 'It looks like your W3 Total Cache Pro License has expired. %s to continue using the Pro Features', 'w3-total-cache' ),
166
+ '<input type="button" class="button-primary button-buy-plugin"' .
167
+ ' data-nonce="'. wp_create_nonce( 'w3tc' ) . '"' .
168
+ ' data-renew-key="' . esc_attr( $this->get_license_key() ) . '"' .
169
+ ' data-src="licensing_expired" value="'.__( 'Renew Now', 'w3-total-cache' ) . '" />' );
170
  } elseif ( $this->_status_is( $status, 'invalid' ) ) {
171
  $message = __( 'The W3 Total Cache license key you entered is not valid.', 'w3-total-cache' ) .
172
  '<a href="' . ( is_network_admin() ? network_admin_url( 'admin.php?page=w3tc_general#licensing' ):
186
  $message = __( 'The W3 Total Cache license key can\'t be verified.', 'w3-total-cache' );
187
  }
188
 
189
+ if ( $message ) {
190
+ if ( !Util_Admin::is_w3tc_admin_page() ) {
191
+ echo '<script src="' . plugins_url( 'pub/js/lightbox.js', W3TC_FILE ) . '"></script>';
192
+ echo '<link rel="stylesheet" id="w3tc-lightbox-css" href="' . plugins_url( 'pub/css/lightbox.css', W3TC_FILE ) . '" type="text/css" media="all" />';
193
+ }
194
+
195
+ Util_Ui::error_box( sprintf( "<p>$message. <a class='w3tc_licensing_check' href='%s'>" . __( 'check license status again' ) . '</a></p>',
196
  Util_Ui::url( array( 'page' => 'w3tc_general', 'w3tc_licensing_check_key' => 'y' ) ) )
197
  );
198
+ }
199
 
200
 
201
  if ( $this->site_inactivated ) {
Minify_AutoCss.php CHANGED
@@ -290,7 +290,7 @@ class Minify_AutoCss {
290
  $data );
291
  $this->buffer = $data['buffer'];
292
 
293
- if ( $this->config->get_boolean( 'minify.css.http2push' ) ) {
294
  $this->minify_helpers->http2_header_add(
295
  $data['style_to_embed_url'], 'style' );
296
  }
290
  $data );
291
  $this->buffer = $data['buffer'];
292
 
293
+ if ( $this->config->getf_boolean( 'minify.css.http2push' ) ) {
294
  $this->minify_helpers->http2_header_add(
295
  $data['style_to_embed_url'], 'style' );
296
  }
Minify_AutoJs.php CHANGED
@@ -301,7 +301,7 @@ class Minify_AutoJs {
301
  $data );
302
  $this->buffer = $data['buffer'];
303
 
304
- if ( $this->config->get_boolean( 'minify.js.http2push' ) ) {
305
  $this->minify_helpers->http2_header_add(
306
  $data['script_to_embed_url'], 'script' );
307
  }
301
  $data );
302
  $this->buffer = $data['buffer'];
303
 
304
+ if ( $this->config->getf_boolean( 'minify.js.http2push' ) ) {
305
  $this->minify_helpers->http2_header_add(
306
  $data['script_to_embed_url'], 'script' );
307
  }
Minify_MinifiedFileRequestHandler.php CHANGED
@@ -651,7 +651,8 @@ class Minify_MinifiedFileRequestHandler {
651
  'persistent' => $this->_config->get_boolean( 'minify.memcached.persistent' ),
652
  'aws_autodiscovery' => $this->_config->get_boolean( 'minify.memcached.aws_autodiscovery' ),
653
  'username' => $this->_config->get_string( 'minify.memcached.username' ),
654
- 'password' => $this->_config->get_string( 'minify.memcached.password' )
 
655
  );
656
  if ( class_exists( 'Memcached' ) ) {
657
  $inner_cache = new Cache_Memcached( $config );
651
  'persistent' => $this->_config->get_boolean( 'minify.memcached.persistent' ),
652
  'aws_autodiscovery' => $this->_config->get_boolean( 'minify.memcached.aws_autodiscovery' ),
653
  'username' => $this->_config->get_string( 'minify.memcached.username' ),
654
+ 'password' => $this->_config->get_string( 'minify.memcached.password' ),
655
+ 'binary_protocol' => $this->_config->get_boolean( 'minify.memcached.binary_protocol' )
656
  );
657
  if ( class_exists( 'Memcached' ) ) {
658
  $inner_cache = new Cache_Memcached( $config );
Minify_Plugin.php CHANGED
@@ -60,9 +60,7 @@ class Minify_Plugin {
60
  array( $this, 'w3tc_admin_bar_menu' ) );
61
 
62
  add_filter( 'w3tc_footer_comment', array(
63
- $this,
64
- 'w3tc_footer_comment'
65
- ) );
66
 
67
  if ( $this->_config->get_string( 'minify.engine' ) == 'file' ) {
68
  add_action( 'w3_minify_cleanup', array(
@@ -70,6 +68,8 @@ class Minify_Plugin {
70
  'cleanup'
71
  ) );
72
  }
 
 
73
 
74
  // usage statistics handling
75
  add_action( 'w3tc_usage_statistics_of_request', array(
@@ -199,7 +199,7 @@ class Minify_Plugin {
199
  $this->remove_styles_group( $buffer, 'include' );
200
  }
201
 
202
- if ( $this->_config->get_boolean( 'minify.css.http2push' ) ) {
203
  $this->minify_helpers->http2_header_add( $style['url'],
204
  'style' );
205
  }
@@ -207,7 +207,7 @@ class Minify_Plugin {
207
 
208
  if ( $js_enable ) {
209
  $embed_type = $this->_config->get_string( 'minify.js.header.embed_type' );
210
- $http2push = $this->_config->get_boolean( 'minify.js.http2push' );
211
 
212
  $script = $this->get_script_group( 'include', $embed_type );
213
 
@@ -987,17 +987,34 @@ class Minify_Plugin {
987
  }
988
 
989
 
 
990
  public function w3tc_usage_statistics_of_request( $storage ) {
991
  $o = Dispatcher::component( 'Minify_MinifiedFileRequestHandler' );
992
  $o->w3tc_usage_statistics_of_request( $storage );
993
  }
994
 
 
 
995
  public function w3tc_usage_statistics_metrics( $metrics ) {
996
  return array_merge( $metrics, array(
997
  'minify_requests_total',
998
  'minify_original_length_css', 'minify_output_length_css',
999
  'minify_original_length_js', 'minify_output_length_js', ) );
1000
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1001
  }
1002
 
1003
 
60
  array( $this, 'w3tc_admin_bar_menu' ) );
61
 
62
  add_filter( 'w3tc_footer_comment', array(
63
+ $this, 'w3tc_footer_comment' ) );
 
 
64
 
65
  if ( $this->_config->get_string( 'minify.engine' ) == 'file' ) {
66
  add_action( 'w3_minify_cleanup', array(
68
  'cleanup'
69
  ) );
70
  }
71
+ add_filter( 'w3tc_pagecache_set_header',
72
+ array( $this, 'w3tc_pagecache_set_header' ), 20, 2 );
73
 
74
  // usage statistics handling
75
  add_action( 'w3tc_usage_statistics_of_request', array(
199
  $this->remove_styles_group( $buffer, 'include' );
200
  }
201
 
202
+ if ( $this->_config->getf_boolean( 'minify.css.http2push' ) ) {
203
  $this->minify_helpers->http2_header_add( $style['url'],
204
  'style' );
205
  }
207
 
208
  if ( $js_enable ) {
209
  $embed_type = $this->_config->get_string( 'minify.js.header.embed_type' );
210
+ $http2push = $this->_config->getf_boolean( 'minify.js.http2push' );
211
 
212
  $script = $this->get_script_group( 'include', $embed_type );
213
 
987
  }
988
 
989
 
990
+
991
  public function w3tc_usage_statistics_of_request( $storage ) {
992
  $o = Dispatcher::component( 'Minify_MinifiedFileRequestHandler' );
993
  $o->w3tc_usage_statistics_of_request( $storage );
994
  }
995
 
996
+
997
+
998
  public function w3tc_usage_statistics_metrics( $metrics ) {
999
  return array_merge( $metrics, array(
1000
  'minify_requests_total',
1001
  'minify_original_length_css', 'minify_output_length_css',
1002
  'minify_original_length_js', 'minify_output_length_js', ) );
1003
  }
1004
+
1005
+
1006
+
1007
+ public function w3tc_pagecache_set_header( $header, $header_original ) {
1008
+ if ( $header_original['n'] == 'Link' &&
1009
+ false !== strpos( $header_original['v'], 'rel=preload' ) ) {
1010
+ // store preload Link headers in cache
1011
+ $new = $header_original;
1012
+ $new['files_match'] = '\\.html[_a-z]*$';
1013
+ return $new;
1014
+ }
1015
+
1016
+ return $header;
1017
+ }
1018
  }
1019
 
1020
 
Minify_Plugin_Admin.php CHANGED
@@ -188,6 +188,7 @@ class Minify_Plugin_Admin {
188
  'servers' => $c->get_array( 'minify.memcached.servers' ),
189
  'username' => $c->get_string( 'minify.memcached.username' ),
190
  'password' => $c->get_string( 'minify.memcached.password' ),
 
191
  'name' => __( 'Minification', 'w3-total-cache' )
192
  );
193
  } elseif ( $c->get_string( 'minify.engine' ) == 'redis' ) {
188
  'servers' => $c->get_array( 'minify.memcached.servers' ),
189
  'username' => $c->get_string( 'minify.memcached.username' ),
190
  'password' => $c->get_string( 'minify.memcached.password' ),
191
+ 'binary_protocol' => $c->get_boolean( 'minify.memcached.binary_protocol' ),
192
  'name' => __( 'Minification', 'w3-total-cache' )
193
  );
194
  } elseif ( $c->get_string( 'minify.engine' ) == 'redis' ) {
ObjectCache_Plugin.php CHANGED
@@ -314,6 +314,7 @@ class ObjectCache_Plugin {
314
  'servers' => $c->get_array( 'objectcache.memcached.servers' ),
315
  'username' => $c->get_string( 'objectcache.memcached.username' ),
316
  'password' => $c->get_string( 'objectcache.memcached.password' ),
 
317
  'name' => __( 'Object Cache', 'w3-total-cache' )
318
  );
319
  } elseif ( $c->get_string( 'objectcache.engine' ) == 'redis' ) {
314
  'servers' => $c->get_array( 'objectcache.memcached.servers' ),
315
  'username' => $c->get_string( 'objectcache.memcached.username' ),
316
  'password' => $c->get_string( 'objectcache.memcached.password' ),
317
+ 'binary_protocol' => $c->get_boolean( 'objectcache.memcached.binary_protocol' ),
318
  'name' => __( 'Object Cache', 'w3-total-cache' )
319
  );
320
  } elseif ( $c->get_string( 'objectcache.engine' ) == 'redis' ) {
ObjectCache_WpObjectCache_Regular.php CHANGED
@@ -200,40 +200,43 @@ class ObjectCache_WpObjectCache_Regular {
200
  /**
201
  * Add debug info
202
  */
203
- if ( !$in_incall_cache && ( $this->_debug || $this->stats_enabled ) ) {
204
- $time = Util_Debug::microtime() - $time_start;
205
- $this->time_total += $time;
206
  $this->cache_total += $cache_total_inc;
207
  $this->cache_hits += $cache_hits_inc;
208
 
209
- if ( $this->_debug ) {
210
- if ( $fallback_used ) {
211
- if ( !$found ) {
212
- $returned = 'not in db';
213
- } else {
214
- $returned = 'from db fallback';
215
- }
216
- } else {
217
- if ( !$found ) {
218
- if ( $cache_total_inc <= 0 ) {
219
- $returned = 'not tried cache';
220
  } else {
221
- $returned = 'not in cache';
222
  }
223
  } else {
224
- $returned = 'from persistent cache';
 
 
 
 
 
 
 
 
225
  }
226
- }
227
 
228
- $this->log_call( array(
229
- date( 'r' ),
230
- 'get',
231
- $group,
232
- $id,
233
- $returned,
234
- ( $value ? strlen( serialize( $value ) ) : 0 ),
235
- (int)($time * 1000000)
236
- ) );
 
237
  }
238
  }
239
 
@@ -682,7 +685,8 @@ class ObjectCache_WpObjectCache_Regular {
682
  'persistent' => $this->_config->get_boolean( 'objectcache.memcached.persistent' ),
683
  'aws_autodiscovery' => $this->_config->get_boolean( 'objectcache.memcached.aws_autodiscovery' ),
684
  'username' => $this->_config->get_string( 'objectcache.memcached.username' ),
685
- 'password' => $this->_config->get_string( 'objectcache.memcached.password' )
 
686
  );
687
  break;
688
 
@@ -729,7 +733,8 @@ class ObjectCache_WpObjectCache_Regular {
729
  'objectcache.memcached.persistent' ),
730
  'aws_autodiscovery' => $this->_config->get_boolean( 'objectcache.memcached.aws_autodiscovery' ),
731
  'username' => $this->_config->get_string( 'objectcache.memcached.username' ),
732
- 'password' => $this->_config->get_string( 'objectcache.memcached.password' )
 
733
  );
734
  break;
735
 
200
  /**
201
  * Add debug info
202
  */
203
+ if ( !$in_incall_cache ) {
 
 
204
  $this->cache_total += $cache_total_inc;
205
  $this->cache_hits += $cache_hits_inc;
206
 
207
+ if ( $this->_debug || $this->stats_enabled ) {
208
+ $time = Util_Debug::microtime() - $time_start;
209
+ $this->time_total += $time;
210
+
211
+ if ( $this->_debug ) {
212
+ if ( $fallback_used ) {
213
+ if ( !$found ) {
214
+ $returned = 'not in db';
 
 
 
215
  } else {
216
+ $returned = 'from db fallback';
217
  }
218
  } else {
219
+ if ( !$found ) {
220
+ if ( $cache_total_inc <= 0 ) {
221
+ $returned = 'not tried cache';
222
+ } else {
223
+ $returned = 'not in cache';
224
+ }
225
+ } else {
226
+ $returned = 'from persistent cache';
227
+ }
228
  }
 
229
 
230
+ $this->log_call( array(
231
+ date( 'r' ),
232
+ 'get',
233
+ $group,
234
+ $id,
235
+ $returned,
236
+ ( $value ? strlen( serialize( $value ) ) : 0 ),
237
+ (int)($time * 1000000)
238
+ ) );
239
+ }
240
  }
241
  }
242
 
685
  'persistent' => $this->_config->get_boolean( 'objectcache.memcached.persistent' ),
686
  'aws_autodiscovery' => $this->_config->get_boolean( 'objectcache.memcached.aws_autodiscovery' ),
687
  'username' => $this->_config->get_string( 'objectcache.memcached.username' ),
688
+ 'password' => $this->_config->get_string( 'objectcache.memcached.password' ),
689
+ 'binary_protocol' => $this->_config->get_boolean( 'objectcache.memcached.binary_protocol' )
690
  );
691
  break;
692
 
733
  'objectcache.memcached.persistent' ),
734
  'aws_autodiscovery' => $this->_config->get_boolean( 'objectcache.memcached.aws_autodiscovery' ),
735
  'username' => $this->_config->get_string( 'objectcache.memcached.username' ),
736
+ 'password' => $this->_config->get_string( 'objectcache.memcached.password' ),
737
+ 'binary_protocol' => $this->_config->get_boolean( 'objectcache.memcached.binary_protocol' )
738
  );
739
  break;
740
 
PgCache_ContentGrabber.php CHANGED
@@ -244,7 +244,7 @@ class PgCache_ContentGrabber {
244
  * @return boolean
245
  */
246
  function _extract_cached_page( $with_filter ) {
247
- $cache = $this->_get_cache();
248
 
249
  $mobile_group = $this->_page_key_extension['useragent'];
250
  $referrer_group = $this->_page_key_extension['referrer'];
@@ -350,13 +350,6 @@ class PgCache_ContentGrabber {
350
  $has_dynamic = isset( $data['has_dynamic'] ) && $data['has_dynamic'];
351
  $etag = md5( $content );
352
 
353
- // for REST under disk-enhanced - return json content type
354
- if ( !empty( $this->_page_key_extension['content_type'] ) &&
355
- !isset( $headers['Content-Type'] ) ) {
356
- $headers['Content-Type'] = $this->_page_key_extension['content_type'];
357
- }
358
-
359
-
360
  if ( $has_dynamic ) {
361
  // its last modification date is now, and any compression
362
  // browser wants cant be used, since its compressed now
@@ -381,7 +374,7 @@ class PgCache_ContentGrabber {
381
  }
382
 
383
  echo $content;
384
- Util_Debug::log('pagecache', 'r3');
385
  Dispatcher::usage_statistics_apply_before_init_and_exit( array( $this,
386
  'w3tc_usage_statistics_of_request' ) );
387
  }
@@ -439,11 +432,8 @@ class PgCache_ContentGrabber {
439
  // remove cached entries if its not cached anymore
440
  if ( $this->cache_reject_reason ) {
441
  if ( $this->_old_exists ) {
442
- $cache = $this->_get_cache();
443
 
444
- $mobile_group = $this->_page_key_extension['useragent'];
445
- $referrer_group = $this->_page_key_extension['referrer'];
446
- $encryption = $this->_page_key_extension['encryption'];
447
  $compressions_to_store = $this->_get_compressions();
448
 
449
  foreach ( $compressions_to_store as $_compression ) {
@@ -542,18 +532,18 @@ class PgCache_ContentGrabber {
542
  /**
543
  * Skip if there is query in the request uri
544
  */
545
- if ( !$this->_is_whitelisted_query_string() ) {
546
- $should_skip_qs =
547
  ( !$this->_config->get_boolean( 'pgcache.cache.query' ) ||
548
  $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' );
549
 
550
- if ( $should_skip_qs &&
551
  $this->_config->get_string( 'pgcache.rest' ) == 'cache' &&
552
  Util_Environment::is_rest_request( $this->_request_uri ) ) {
553
- $should_skip_qs = false;
554
  }
555
 
556
- if ( $should_skip_qs && strstr( $this->_request_uri, '?' ) !== false ) {
557
  $this->cache_reject_reason = 'Requested URI contains query';
558
  $this->process_status = 'miss_query_string';
559
 
@@ -758,7 +748,8 @@ class PgCache_ContentGrabber {
758
  'persistent' => $this->_config->get_boolean( 'pgcache.memcached.persistent' ),
759
  'aws_autodiscovery' => $this->_config->get_boolean( 'pgcache.memcached.aws_autodiscovery' ),
760
  'username' => $this->_config->get_string( 'pgcache.memcached.username' ),
761
- 'password' => $this->_config->get_string( 'pgcache.memcached.password' )
 
762
  );
763
  break;
764
 
@@ -788,10 +779,14 @@ class PgCache_ContentGrabber {
788
  *
789
  * @return W3_Cache_Base
790
  */
791
- function _get_cache() {
792
- static $cache = null;
793
 
794
- if ( is_null( $cache ) ) {
 
 
 
 
795
  $engine = $this->_config->get_string( 'pgcache.engine' );
796
 
797
  switch ( $engine ) {
@@ -802,7 +797,8 @@ class PgCache_ContentGrabber {
802
  'persistent' => $this->_config->get_boolean( 'pgcache.memcached.persistent' ),
803
  'aws_autodiscovery' => $this->_config->get_boolean( 'pgcache.memcached.aws_autodiscovery' ),
804
  'username' => $this->_config->get_string( 'pgcache.memcached.username' ),
805
- 'password' => $this->_config->get_string( 'pgcache.memcached.password' )
 
806
  );
807
  break;
808
 
@@ -825,10 +821,29 @@ class PgCache_ContentGrabber {
825
  break;
826
 
827
  case 'file_generic':
828
- if ( Util_Environment::blog_id() == 0 )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
829
  $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR;
830
- else
831
- $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR . '/' . Util_Environment::host();
 
 
 
832
 
833
  $engineConfig = array(
834
  'exclude' => array(
@@ -851,10 +866,10 @@ class PgCache_ContentGrabber {
851
  $engineConfig['host'] = ''; // host is always put to a key
852
  $engineConfig['instance_id'] = Util_Environment::instance_id();
853
 
854
- $cache = Cache::instance( $engine, $engineConfig );
855
  }
856
 
857
- return $cache;
858
  }
859
 
860
  /**
@@ -1142,22 +1157,7 @@ class PgCache_ContentGrabber {
1142
  $this->_fill_key_extension_cookie( $extension );
1143
 
1144
  // fill group
1145
- $sitemap_regex = $this->_config->get_string(
1146
- 'pgcache.purge.sitemap_regex' );
1147
- if ( !$this->_enhanced_mode && $sitemap_regex &&
1148
- preg_match( '~' . $sitemap_regex . '~',
1149
- basename( $this->_request_uri ) ) ) {
1150
- // dont store to separate group under disk-enhanced
1151
- // so that rewrite rules still work.
1152
- // flushing is handled by workaround in this case
1153
- $extension['group'] = 'sitemaps';
1154
- } elseif ( $this->_config->get_string( 'pgcache.rest' ) == 'cache' &&
1155
- Util_Environment::is_rest_request( $this->_request_uri ) &&
1156
- Util_Environment::is_w3tc_pro( $this->_config ) ) {
1157
- $extension['group'] = 'rest';
1158
- $extension['querystring.processing'] = 'include';
1159
- $extension['content_type'] = 'application/json';
1160
- }
1161
 
1162
  return $extension;
1163
  }
@@ -1200,6 +1200,30 @@ class PgCache_ContentGrabber {
1200
  }
1201
  }
1202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1203
  /**
1204
  * Returns current compression
1205
  *
@@ -1316,7 +1340,7 @@ class PgCache_ContentGrabber {
1316
  function _get_cached_headers( $response_headers ) {
1317
  $data_headers = array();
1318
  $cache_headers = array_merge(
1319
- array( 'Location' ),
1320
  $this->_config->get_array( 'pgcache.cache.headers' )
1321
  );
1322
 
@@ -1377,69 +1401,7 @@ class PgCache_ContentGrabber {
1377
  $key = preg_replace( '~#.*$~', '', $key );
1378
  $key = strtolower( $key ); // host/uri in different cases means the same page in wp
1379
 
1380
- if ( $this->_enhanced_mode ) {
1381
- // URL decode
1382
- $key = urldecode( $key );
1383
-
1384
- // replace double slashes
1385
- $key = preg_replace( '~[/\\\]+~', '/', $key );
1386
-
1387
- // replace index.php
1388
- $key = str_replace( '/index.php', '/', $key );
1389
-
1390
- $key_query = '';
1391
- if ( isset( $page_key_extension['querystring.processing'] ) &&
1392
- $page_key_extension['querystring.processing'] == 'include' ) {
1393
-
1394
- if ( preg_match( '~\?.*$~', $key, $m ) ) {
1395
- $key_query = '_' . md5( $m[0] );
1396
- }
1397
- }
1398
-
1399
- $key = preg_replace( '~\?.*$~', '', $key );
1400
-
1401
- // make sure one slash is at the end
1402
- $key = ltrim( $key, '/' );
1403
- if ( $key && substr( $key, -1 ) != '/' ) {
1404
- $key .= '/';
1405
- }
1406
-
1407
- $key .= '_index';
1408
- } else if ( $this->_nginx_memcached ) {
1409
- // URL decode
1410
- $key = urldecode( $key );
1411
-
1412
- // replace double slashes
1413
- $key = preg_replace( '~[/\\\]+~', '/', $key );
1414
-
1415
- // replace index.php
1416
- $key = str_replace( '/index.php', '/', $key );
1417
-
1418
- $key_query = '';
1419
- if ( isset( $page_key_extension['querystring.processing'] ) &&
1420
- $page_key_extension['querystring.processing'] == 'include' ) {
1421
-
1422
- if ( preg_match( '~\?.*$~', $key, $m ) ) {
1423
- $key_query = '_' . md5( $m[0] );
1424
- }
1425
- }
1426
-
1427
- $key = preg_replace( '~\?.*$~', '', $key );
1428
-
1429
- // make sure one slash is at the end
1430
- $key = ltrim( $key, '/' );
1431
- $key = rtrim( $key, '/' ) . '/';
1432
- } else {
1433
- if ( isset( $page_key_extension['querystring.processing'] ) &&
1434
- $page_key_extension['querystring.processing'] == 'include' ) {
1435
- // include querystring in key
1436
- } elseif ( $this->_is_whitelisted_query_string() ) {
1437
- // replace query string
1438
- $key = preg_replace( '~\?.*$~', '', $key );
1439
- }
1440
-
1441
- $key = md5( $key );
1442
- }
1443
 
1444
  /**
1445
  * Append extensions
@@ -1455,20 +1417,20 @@ class PgCache_ContentGrabber {
1455
  if ( Util_Environment::is_preview_mode() )
1456
  $key .= '_preview';
1457
 
1458
- if ( $this->_enhanced_mode ) {
1459
  $key_postfix = '.html';
1460
  if ( $this->_config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
1461
  $content_type = isset( $page_key_extension['content_type'] ) ?
1462
  $page_key_extension['content_type'] : '';
1463
 
1464
  if ( @preg_match( "~(text/xml|text/xsl|application/rdf\+xml|application/rss\+xml|application/atom\+xml)~i", $content_type ) ||
1465
- preg_match( "~/feed(/|$)~", $request_url ) ||
1466
  strpos( $request_url, ".xsl" ) !== false ) {
1467
  $key_postfix = '.xml';
1468
  }
1469
  }
1470
 
1471
- $key .= $key_query . $key_postfix;
1472
  }
1473
 
1474
  /**
@@ -1480,6 +1442,40 @@ class PgCache_ContentGrabber {
1480
  return $key;
1481
  }
1482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1483
  /**
1484
  * Returns debug info
1485
  *
@@ -1892,7 +1888,7 @@ class PgCache_ContentGrabber {
1892
  return in_array( $content_type, $cache_headers );
1893
  }
1894
 
1895
- private function _is_whitelisted_query_string() {
1896
  $accept_qs = $this->_config->get_array( 'pgcache.accept.qs' );
1897
  Util_Rule::array_trim( $accept_qs );
1898
 
@@ -1981,11 +1977,12 @@ class PgCache_ContentGrabber {
1981
  // redirect issued, if we have some old cache entries
1982
  // they will be turned into fresh files and catch further requests
1983
  if ( isset( $response_headers['kv']['Location'] ) ) {
 
 
1984
  foreach ( $compressions_to_store as $_compression ) {
1985
  $_page_key = $this->_get_page_key(
1986
  array_merge( $this->_page_key_extension,
1987
  array( 'compression' => $_compression ) ) );
1988
- $cache = $this->_get_cache();
1989
  $cache->hard_delete( $_page_key );
1990
  }
1991
 
@@ -2006,7 +2003,7 @@ class PgCache_ContentGrabber {
2006
  }
2007
 
2008
  $time = time();
2009
- $cache = $this->_get_cache();
2010
 
2011
  /**
2012
  * Store different versions of cache
244
  * @return boolean
245
  */
246
  function _extract_cached_page( $with_filter ) {
247
+ $cache = $this->_get_cache( $this->_page_key_extension['group'] );
248
 
249
  $mobile_group = $this->_page_key_extension['useragent'];
250
  $referrer_group = $this->_page_key_extension['referrer'];
350
  $has_dynamic = isset( $data['has_dynamic'] ) && $data['has_dynamic'];
351
  $etag = md5( $content );
352
 
 
 
 
 
 
 
 
353
  if ( $has_dynamic ) {
354
  // its last modification date is now, and any compression
355
  // browser wants cant be used, since its compressed now
374
  }
375
 
376
  echo $content;
377
+
378
  Dispatcher::usage_statistics_apply_before_init_and_exit( array( $this,
379
  'w3tc_usage_statistics_of_request' ) );
380
  }
432
  // remove cached entries if its not cached anymore
433
  if ( $this->cache_reject_reason ) {
434
  if ( $this->_old_exists ) {
435
+ $cache = $this->_get_cache( $this->_page_key_extension['group'] );
436
 
 
 
 
437
  $compressions_to_store = $this->_get_compressions();
438
 
439
  foreach ( $compressions_to_store as $_compression ) {
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' );
539
 
540
+ if ( $should_reject_qs &&
541
  $this->_config->get_string( 'pgcache.rest' ) == 'cache' &&
542
  Util_Environment::is_rest_request( $this->_request_uri ) ) {
543
+ $should_reject_qs = false;
544
  }
545
 
546
+ if ( $should_reject_qs && strstr( $this->_request_uri, '?' ) !== false ) {
547
  $this->cache_reject_reason = 'Requested URI contains query';
548
  $this->process_status = 'miss_query_string';
549
 
748
  'persistent' => $this->_config->get_boolean( 'pgcache.memcached.persistent' ),
749
  'aws_autodiscovery' => $this->_config->get_boolean( 'pgcache.memcached.aws_autodiscovery' ),
750
  'username' => $this->_config->get_string( 'pgcache.memcached.username' ),
751
+ 'password' => $this->_config->get_string( 'pgcache.memcached.password' ),
752
+ 'binary_protocol' => $this->_config->get_boolean( 'pgcache.memcached.binary_protocol' )
753
  );
754
  break;
755
 
779
  *
780
  * @return W3_Cache_Base
781
  */
782
+ function _get_cache( $group = '*' ) {
783
+ static $caches = array();
784
 
785
+ if ( empty( $group ) ) {
786
+ $group = '*';
787
+ }
788
+
789
+ if ( empty( $caches[$group] ) ) {
790
  $engine = $this->_config->get_string( 'pgcache.engine' );
791
 
792
  switch ( $engine ) {
797
  'persistent' => $this->_config->get_boolean( 'pgcache.memcached.persistent' ),
798
  'aws_autodiscovery' => $this->_config->get_boolean( 'pgcache.memcached.aws_autodiscovery' ),
799
  'username' => $this->_config->get_string( 'pgcache.memcached.username' ),
800
+ 'password' => $this->_config->get_string( 'pgcache.memcached.password' ),
801
+ 'binary_protocol' => $this->_config->get_boolean( 'pgcache.memcached.binary_protocol' )
802
  );
803
  break;
804
 
821
  break;
822
 
823
  case 'file_generic':
824
+ if ( $group != '*' ) {
825
+ $engine = 'file';
826
+
827
+ $engineConfig = array(
828
+ 'section' => 'page',
829
+ 'cache_dir' =>
830
+ W3TC_CACHE_PAGE_ENHANCED_DIR .
831
+ DIRECTORY_SEPARATOR .
832
+ Util_Environment::host_port(),
833
+ 'flush_parent' => ( Util_Environment::blog_id() == 0 ),
834
+ 'locking' => $this->_config->get_boolean( 'pgcache.file.locking' ),
835
+ 'flush_timelimit' => $this->_config->get_integer( 'timelimit.cache_flush' )
836
+ );
837
+ break;
838
+ }
839
+
840
+ if ( Util_Environment::blog_id() == 0 ) {
841
  $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR;
842
+ } else {
843
+ $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR .
844
+ DIRECTORY_SEPARATOR .
845
+ Util_Environment::host();
846
+ }
847
 
848
  $engineConfig = array(
849
  'exclude' => array(
866
  $engineConfig['host'] = ''; // host is always put to a key
867
  $engineConfig['instance_id'] = Util_Environment::instance_id();
868
 
869
+ $caches[$group] = Cache::instance( $engine, $engineConfig );
870
  }
871
 
872
+ return $caches[$group];
873
  }
874
 
875
  /**
1157
  $this->_fill_key_extension_cookie( $extension );
1158
 
1159
  // fill group
1160
+ $extension['group'] = $this->get_cache_group_by_uri( $this->_request_uri );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1161
 
1162
  return $extension;
1163
  }
1200
  }
1201
  }
1202
 
1203
+ protected function get_cache_group_by_uri( $uri ) {
1204
+ // "!$this->_enhanced_mode" in condition above
1205
+ // prevents usage of separate group under disk-enhanced
1206
+ // so that rewrite rules still work.
1207
+ // flushing is handled by workaround in this case
1208
+ if ( !$this->_enhanced_mode ) {
1209
+ $sitemap_regex = $this->_config->get_string(
1210
+ 'pgcache.purge.sitemap_regex' );
1211
+
1212
+ if ( $sitemap_regex && preg_match( '~' . $sitemap_regex . '~',
1213
+ basename( $uri ) ) ) {
1214
+ return 'sitemaps';
1215
+ }
1216
+ }
1217
+
1218
+ if ( $this->_config->get_string( 'pgcache.rest' ) == 'cache' &&
1219
+ Util_Environment::is_rest_request( $uri ) &&
1220
+ Util_Environment::is_w3tc_pro( $this->_config ) ) {
1221
+ return 'rest';
1222
+ }
1223
+
1224
+ return '';
1225
+ }
1226
+
1227
  /**
1228
  * Returns current compression
1229
  *
1340
  function _get_cached_headers( $response_headers ) {
1341
  $data_headers = array();
1342
  $cache_headers = array_merge(
1343
+ array( 'Location', 'X-WP-Total', 'X-WP-TotalPages' ),
1344
  $this->_config->get_array( 'pgcache.cache.headers' )
1345
  );
1346
 
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
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' ) ) {
1423
  $content_type = isset( $page_key_extension['content_type'] ) ?
1424
  $page_key_extension['content_type'] : '';
1425
 
1426
  if ( @preg_match( "~(text/xml|text/xsl|application/rdf\+xml|application/rss\+xml|application/atom\+xml)~i", $content_type ) ||
1427
+ preg_match( W3TC_FEED_REGEXP, $request_url ) ||
1428
  strpos( $request_url, ".xsl" ) !== false ) {
1429
  $key_postfix = '.xml';
1430
  }
1431
  }
1432
 
1433
+ $key .= $key_postfix;
1434
  }
1435
 
1436
  /**
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
1449
+ $key = urldecode( $key );
1450
+
1451
+ // replace double slashes
1452
+ $key = preg_replace( '~[/\\\]+~', '/', $key );
1453
+
1454
+ // replace index.php
1455
+ $key = str_replace( '/index.php', '/', $key );
1456
+
1457
+ // remove querystring
1458
+ $key = preg_replace( '~\?.*$~', '', $key );
1459
+
1460
+ // make sure one slash is at the end
1461
+ $key = trim( $key, '/' ) . '/';
1462
+
1463
+ if ( $this->_nginx_memcached ) {
1464
+ return $key;
1465
+ }
1466
+
1467
+ return $key . '_index';
1468
+ }
1469
+ }
1470
+
1471
+ if ( $this->_is_ignored_query_string() ) {
1472
+ // remove query string
1473
+ $key = preg_replace( '~\?.*$~', '', $key );
1474
+ }
1475
+
1476
+ return md5( $key );
1477
+ }
1478
+
1479
  /**
1480
  * Returns debug info
1481
  *
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
 
1977
  // redirect issued, if we have some old cache entries
1978
  // they will be turned into fresh files and catch further requests
1979
  if ( isset( $response_headers['kv']['Location'] ) ) {
1980
+ $cache = $this->_get_cache( $this->_page_key_extension['group'] );
1981
+
1982
  foreach ( $compressions_to_store as $_compression ) {
1983
  $_page_key = $this->_get_page_key(
1984
  array_merge( $this->_page_key_extension,
1985
  array( 'compression' => $_compression ) ) );
 
1986
  $cache->hard_delete( $_page_key );
1987
  }
1988
 
2003
  }
2004
 
2005
  $time = time();
2006
+ $cache = $this->_get_cache( $this->_page_key_extension['group'] );
2007
 
2008
  /**
2009
  * Store different versions of cache
PgCache_Flush.php CHANGED
@@ -7,31 +7,24 @@ namespace W3TC;
7
  class PgCache_Flush extends PgCache_ContentGrabber {
8
  /**
9
  * Array of urls to flush
10
- *
11
- * @var array
12
  */
13
  private $queued_urls = array();
14
  private $queued_groups = array();
15
  private $flush_all_operation_requested = false;
16
 
17
- /**
18
- * PHP5 Constructor
19
- */
20
- function __construct() {
21
  parent::__construct();
22
  }
23
 
24
  /**
25
  * Flushes all caches
26
- *
27
- * @return boolean
28
  */
29
- function flush() {
30
  $this->flush_all_operation_requested = true;
31
  return true;
32
  }
33
 
34
- function flush_group( $group ) {
35
  $this->queued_groups[$group] = '*';
36
  }
37
 
@@ -39,9 +32,8 @@ class PgCache_Flush extends PgCache_ContentGrabber {
39
  * Flushes post cache
40
  *
41
  * @param integer $post_id
42
- * @return boolean
43
  */
44
- function flush_post( $post_id = null ) {
45
  if ( !$post_id ) {
46
  $post_id = Util_Environment::detect_post_id();
47
  }
@@ -49,6 +41,12 @@ class PgCache_Flush extends PgCache_ContentGrabber {
49
  if ( !$post_id )
50
  return false;
51
 
 
 
 
 
 
 
52
  $full_urls = array();
53
  $post = get_post( $post_id );
54
  $terms = array();
@@ -69,9 +67,7 @@ class PgCache_Flush extends PgCache_ContentGrabber {
69
 
70
  $front_page = get_option( 'show_on_front' );
71
 
72
- /**
73
- * Home (Frontpage) URL
74
- */
75
  if ( ( $this->_config->get_boolean( 'pgcache.purge.home' ) &&
76
  $front_page == 'posts' ) ||
77
  $this->_config->get_boolean( 'pgcache.purge.front_page' ) ) {
@@ -79,76 +75,58 @@ class PgCache_Flush extends PgCache_ContentGrabber {
79
  Util_PageUrls::get_frontpage_urls( $limit_post_pages ) );
80
  }
81
 
82
- /**
83
- * Home (Post page) URL
84
- */
85
  if ( $this->_config->get_boolean( 'pgcache.purge.home' ) &&
86
  $front_page != 'posts' ) {
87
  $full_urls = array_merge( $full_urls,
88
  Util_PageUrls::get_postpage_urls( $limit_post_pages ) );
89
  }
90
 
91
- /**
92
- * Post URL
93
- */
94
  if ( $this->_config->get_boolean( 'pgcache.purge.post' ) ) {
95
  $full_urls = array_merge( $full_urls,
96
  Util_PageUrls::get_post_urls( $post_id ) );
97
  }
98
 
99
- /**
100
- * Post comments URLs
101
- */
102
  if ( $this->_config->get_boolean( 'pgcache.purge.comments' ) &&
103
  function_exists( 'get_comments_pagenum_link' ) ) {
104
  $full_urls = array_merge( $full_urls,
105
  Util_PageUrls::get_post_comments_urls( $post_id ) );
106
  }
107
 
108
- /**
109
- * Post author URLs
110
- */
111
  if ( $this->_config->get_boolean( 'pgcache.purge.author' ) && $post ) {
112
  $full_urls = array_merge( $full_urls,
113
  Util_PageUrls::get_post_author_urls( $post->post_author,
114
  $limit_post_pages ) );
115
  }
116
 
117
- /**
118
- * Post terms URLs
119
- */
120
  if ( $this->_config->get_boolean( 'pgcache.purge.terms' ) ) {
121
  $full_urls = array_merge( $full_urls,
122
  Util_PageUrls::get_post_terms_urls( $terms, $limit_post_pages ) );
123
  }
124
 
125
- /**
126
- * Daily archive URLs
127
- */
128
  if ( $this->_config->get_boolean( 'pgcache.purge.archive.daily' ) && $post ) {
129
  $full_urls = array_merge( $full_urls,
130
  Util_PageUrls::get_daily_archive_urls( $post, $limit_post_pages ) );
131
  }
132
 
133
- /**
134
- * Monthly archive URLs
135
- */
136
  if ( $this->_config->get_boolean( 'pgcache.purge.archive.monthly' ) && $post ) {
137
  $full_urls = array_merge( $full_urls,
138
  Util_PageUrls::get_monthly_archive_urls( $post, $limit_post_pages ) );
139
  }
140
 
141
- /**
142
- * Yearly archive URLs
143
- */
144
  if ( $this->_config->get_boolean( 'pgcache.purge.archive.yearly' ) && $post ) {
145
  $full_urls = array_merge( $full_urls,
146
  Util_PageUrls::get_yearly_archive_urls( $post, $limit_post_pages ) );
147
  }
148
 
149
- /**
150
- * Feed URLs
151
- */
152
  if ( $this->_config->get_boolean( 'pgcache.purge.feed.blog' ) ) {
153
  $full_urls = array_merge( $full_urls,
154
  Util_PageUrls::get_feed_urls( $feeds, null ) );
@@ -169,9 +147,7 @@ class PgCache_Flush extends PgCache_ContentGrabber {
169
  Util_PageUrls::get_feed_terms_urls( $terms, $feeds ) );
170
  }
171
 
172
- /**
173
- * Purge selected pages
174
- */
175
  if ( $this->_config->get_array( 'pgcache.purge.pages' ) ) {
176
  $pages = $this->_config->get_array( 'pgcache.purge.pages' );
177
  $full_urls = array_merge( $full_urls,
@@ -182,9 +158,8 @@ class PgCache_Flush extends PgCache_ContentGrabber {
182
  $full_urls = Util_PageUrls::complement_with_mirror_urls( $full_urls );
183
  $full_urls = apply_filters( 'pgcache_flush_post_queued_urls',
184
  $full_urls );
185
- /**
186
- * Queue flush
187
- */
188
  if ( count( $full_urls ) ) {
189
  foreach ( $full_urls as $url )
190
  $this->queued_urls[$url] = '*';
@@ -195,120 +170,87 @@ class PgCache_Flush extends PgCache_ContentGrabber {
195
 
196
  /**
197
  * Flush a single url
198
- *
199
- * @param unknown $url
200
- * @param unknown $cache
201
- * @param unknown $mobile_groups
202
- * @param unknown $referrer_groups
203
- * @param unknown $cookies
204
- * @param unknown $encryptions
205
- * @param unknown $compressions
206
  */
207
- function _flush_url( $url, $cache, $mobile_groups, $referrer_groups,
208
- $cookies, $encryptions, $compressions ) {
209
- foreach ( $mobile_groups as $mobile_group ) {
210
- foreach ( $referrer_groups as $referrer_group ) {
211
- foreach ( $cookies as $cookie ) {
212
- foreach ( $encryptions as $encryption ) {
213
- foreach ( $compressions as $compression ) {
214
- $page_keys = array();
215
- $page_keys[] = $this->_get_page_key( array(
216
- 'useragent' => $mobile_group,
217
- 'referrer' => $referrer_group,
218
- 'cookie' => $cookie,
219
- 'encryption' => $encryption,
220
- 'compression' => $compression ),
221
- $url );
222
- $page_keys = apply_filters(
223
- 'w3tc_pagecache_flush_url_keys', $page_keys );
224
-
225
- foreach ( $page_keys as $page_key )
226
- $cache->delete( $page_key );
227
- }
228
- }
229
- }
230
- }
231
- }
232
- }
233
 
234
- /**
235
- * Flush a single url
236
- *
237
- * @param unknown $url
238
- */
239
- function flush_url( $url ) {
240
- static $cache, $mobile_groups, $referrer_groups, $cookies, $encryptions;
241
- static $compressions;
242
-
243
- if ( !isset( $cache ) )
244
- $cache = $this->_get_cache();
245
- if ( !isset( $mobile_groups ) )
246
- $mobile_groups = $this->_get_mobile_groups();
247
- if ( !isset( $referrer_groups ) )
248
- $referrer_groups = $this->_get_referrer_groups();
249
- if ( !isset( $cookies ) )
250
- $cookies = $this->_get_cookies();
251
- if ( !isset( $encryptions ) )
252
- $encryptions = $this->_get_encryptions();
253
- if ( !isset( $compressions ) )
254
- $compressions = $this->_get_compressions();
255
- $this->_flush_url( $url, $cache, $mobile_groups, $referrer_groups,
256
- $cookies, $encryptions, $compressions );
257
  }
258
 
259
  /**
260
- * Flushes global and repeated urls
261
- *
262
- * @return count of elements it has flushed
263
  */
264
- function flush_post_cleanup() {
265
  if ( $this->flush_all_operation_requested ) {
266
  if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
267
  self::log( 'flush all' );
268
  }
269
 
270
- $cache = $this->_get_cache();
271
- $cache->flush();
 
 
 
 
 
 
 
 
 
 
272
 
273
  $count = 999;
274
  $this->flush_all_operation_requested = false;
275
  $this->queued_urls = array();
276
  } else {
 
277
  if ( count( $this->queued_groups ) > 0 ) {
278
- $cache = $this->_get_cache();
279
-
280
  foreach ( $this->queued_groups as $group => $flag ) {
281
  if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
282
  self::log( 'pgcache flush "' . $group . '" group' );
283
  }
284
 
 
285
  $cache->flush( $group );
286
  }
287
  }
288
 
289
- $count = count( $this->queued_urls );
290
-
291
- if ( $count > 0 ) {
292
  if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
293
  self::log( 'pgcache flush ' . $count . ' urls' );
294
  }
295
 
296
- $cache = $this->_get_cache();
297
  $mobile_groups = $this->_get_mobile_groups();
298
  $referrer_groups = $this->_get_referrer_groups();
299
  $cookies = $this->_get_cookies();
300
  $encryptions = $this->_get_encryptions();
301
  $compressions = $this->_get_compressions();
302
 
303
- foreach ( $this->queued_urls as $url => $flag ) {
304
- $this->_flush_url( $url, $cache, $mobile_groups,
305
- $referrer_groups, $cookies, $encryptions, $compressions );
 
 
 
 
 
 
 
 
306
  }
307
 
 
 
308
  // Purge sitemaps if a sitemap option has a regex
309
  if ( $this->_config->get_string( 'pgcache.purge.sitemap_regex' ) ) {
310
- $cache = $this->_get_cache();
311
  $cache->flush( 'sitemaps' );
 
312
  }
313
 
314
  $this->queued_urls = array();
@@ -318,12 +260,45 @@ class PgCache_Flush extends PgCache_ContentGrabber {
318
  return $count;
319
  }
320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  /**
322
  * Returns array of mobile groups
323
- *
324
- * @return array
325
  */
326
- function _get_mobile_groups() {
327
  $mobile_groups = array( '' );
328
 
329
  if ( $this->_mobile ) {
@@ -336,10 +311,8 @@ class PgCache_Flush extends PgCache_ContentGrabber {
336
 
337
  /**
338
  * Returns array of referrer groups
339
- *
340
- * @return array
341
  */
342
- function _get_referrer_groups() {
343
  $referrer_groups = array( '' );
344
 
345
  if ( $this->_referrer ) {
@@ -352,23 +325,22 @@ class PgCache_Flush extends PgCache_ContentGrabber {
352
 
353
  /**
354
  * Returns array of cookies
355
- *
356
- * @return array
357
  */
358
- function _get_cookies() {
359
  $cookies = array( '' );
360
 
361
- $cookies = array_merge( $cookies, array_keys( $this->_config->get_array( 'pgcache.cookiegroups.groups' ) ) );
 
 
 
362
 
363
  return $cookies;
364
  }
365
 
366
  /**
367
  * Returns array of encryptions
368
- *
369
- * @return array
370
  */
371
- function _get_encryptions() {
372
  $is_https = ( substr( get_home_url(), 0, 5 ) == 'https' );
373
 
374
  $encryptions = array();
@@ -381,8 +353,6 @@ class PgCache_Flush extends PgCache_ContentGrabber {
381
  return $encryptions;
382
  }
383
 
384
-
385
-
386
  private function _append_parent_terms( $terms, $terms_to_check_parents ) {
387
  $terms_to_check_parents = $terms;
388
  $ids = null;
7
  class PgCache_Flush extends PgCache_ContentGrabber {
8
  /**
9
  * Array of urls to flush
 
 
10
  */
11
  private $queued_urls = array();
12
  private $queued_groups = array();
13
  private $flush_all_operation_requested = false;
14
 
15
+ public function __construct() {
 
 
 
16
  parent::__construct();
17
  }
18
 
19
  /**
20
  * Flushes all caches
 
 
21
  */
22
+ public function flush() {
23
  $this->flush_all_operation_requested = true;
24
  return true;
25
  }
26
 
27
+ public function flush_group( $group ) {
28
  $this->queued_groups[$group] = '*';
29
  }
30
 
32
  * Flushes post cache
33
  *
34
  * @param integer $post_id
 
35
  */
36
+ public function flush_post( $post_id = null ) {
37
  if ( !$post_id ) {
38
  $post_id = Util_Environment::detect_post_id();
39
  }
41
  if ( !$post_id )
42
  return false;
43
 
44
+ global $wp_rewrite; // required by many Util_PageUrls methods
45
+ if ( empty( $wp_rewrite ) ) {
46
+ error_log('Post was modified before wp_rewrite initialization. Cant flush cache.');
47
+ return false;
48
+ }
49
+
50
  $full_urls = array();
51
  $post = get_post( $post_id );
52
  $terms = array();
67
 
68
  $front_page = get_option( 'show_on_front' );
69
 
70
+ // Home (Frontpage) URL
 
 
71
  if ( ( $this->_config->get_boolean( 'pgcache.purge.home' ) &&
72
  $front_page == 'posts' ) ||
73
  $this->_config->get_boolean( 'pgcache.purge.front_page' ) ) {
75
  Util_PageUrls::get_frontpage_urls( $limit_post_pages ) );
76
  }
77
 
78
+ // Home (Post page) URL
 
 
79
  if ( $this->_config->get_boolean( 'pgcache.purge.home' ) &&
80
  $front_page != 'posts' ) {
81
  $full_urls = array_merge( $full_urls,
82
  Util_PageUrls::get_postpage_urls( $limit_post_pages ) );
83
  }
84
 
85
+ // Post URL
 
 
86
  if ( $this->_config->get_boolean( 'pgcache.purge.post' ) ) {
87
  $full_urls = array_merge( $full_urls,
88
  Util_PageUrls::get_post_urls( $post_id ) );
89
  }
90
 
91
+ // Post comments URLs
 
 
92
  if ( $this->_config->get_boolean( 'pgcache.purge.comments' ) &&
93
  function_exists( 'get_comments_pagenum_link' ) ) {
94
  $full_urls = array_merge( $full_urls,
95
  Util_PageUrls::get_post_comments_urls( $post_id ) );
96
  }
97
 
98
+ // Post author URLs
 
 
99
  if ( $this->_config->get_boolean( 'pgcache.purge.author' ) && $post ) {
100
  $full_urls = array_merge( $full_urls,
101
  Util_PageUrls::get_post_author_urls( $post->post_author,
102
  $limit_post_pages ) );
103
  }
104
 
105
+ // Post terms URLs
 
 
106
  if ( $this->_config->get_boolean( 'pgcache.purge.terms' ) ) {
107
  $full_urls = array_merge( $full_urls,
108
  Util_PageUrls::get_post_terms_urls( $terms, $limit_post_pages ) );
109
  }
110
 
111
+ // Daily archive URLs
 
 
112
  if ( $this->_config->get_boolean( 'pgcache.purge.archive.daily' ) && $post ) {
113
  $full_urls = array_merge( $full_urls,
114
  Util_PageUrls::get_daily_archive_urls( $post, $limit_post_pages ) );
115
  }
116
 
117
+ // Monthly archive URLs
 
 
118
  if ( $this->_config->get_boolean( 'pgcache.purge.archive.monthly' ) && $post ) {
119
  $full_urls = array_merge( $full_urls,
120
  Util_PageUrls::get_monthly_archive_urls( $post, $limit_post_pages ) );
121
  }
122
 
123
+ // Yearly archive URLs
 
 
124
  if ( $this->_config->get_boolean( 'pgcache.purge.archive.yearly' ) && $post ) {
125
  $full_urls = array_merge( $full_urls,
126
  Util_PageUrls::get_yearly_archive_urls( $post, $limit_post_pages ) );
127
  }
128
 
129
+ // Feed URLs
 
 
130
  if ( $this->_config->get_boolean( 'pgcache.purge.feed.blog' ) ) {
131
  $full_urls = array_merge( $full_urls,
132
  Util_PageUrls::get_feed_urls( $feeds, null ) );
147
  Util_PageUrls::get_feed_terms_urls( $terms, $feeds ) );
148
  }
149
 
150
+ // Purge selected pages
 
 
151
  if ( $this->_config->get_array( 'pgcache.purge.pages' ) ) {
152
  $pages = $this->_config->get_array( 'pgcache.purge.pages' );
153
  $full_urls = array_merge( $full_urls,
158
  $full_urls = Util_PageUrls::complement_with_mirror_urls( $full_urls );
159
  $full_urls = apply_filters( 'pgcache_flush_post_queued_urls',
160
  $full_urls );
161
+
162
+ // Queue flush
 
163
  if ( count( $full_urls ) ) {
164
  foreach ( $full_urls as $url )
165
  $this->queued_urls[$url] = '*';
170
 
171
  /**
172
  * Flush a single url
 
 
 
 
 
 
 
 
173
  */
174
+ public function flush_url( $url ) {
175
+ $parts = parse_url( $url );
176
+ $uri = ( isset( $parts['path'] ) ? $parts['path'] : '' ) .
177
+ ( isset( $parts['query'] ) ? '?' . $parts['query'] : '' );
178
+ $group = $this->get_cache_group_by_uri( $uri );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
+ $this->queued_urls[$url] = ( empty( $group ) ? '*' : $group );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  }
182
 
183
  /**
184
+ * Performs the actual flush at the end of request processing.
185
+ * Duplicate flushes avoided that way.
 
186
  */
187
+ public function flush_post_cleanup() {
188
  if ( $this->flush_all_operation_requested ) {
189
  if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
190
  self::log( 'flush all' );
191
  }
192
 
193
+ $groups_to_flush = array( '' );
194
+ if ( $this->_config->get_string( 'pgcache.rest' ) == 'cache' ) {
195
+ $groups_to_flush[] = 'rest';
196
+ }
197
+
198
+ $groups_to_flush = apply_filters(
199
+ 'w3tc_pagecache_flush_all_groups', $groups_to_flush );
200
+
201
+ foreach ( $groups_to_flush as $group ) {
202
+ $cache = $this->_get_cache( $group );
203
+ $cache->flush( $group );
204
+ }
205
 
206
  $count = 999;
207
  $this->flush_all_operation_requested = false;
208
  $this->queued_urls = array();
209
  } else {
210
+ $count = 0;
211
  if ( count( $this->queued_groups ) > 0 ) {
212
+ $count += count( $this->queued_urls );
 
213
  foreach ( $this->queued_groups as $group => $flag ) {
214
  if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
215
  self::log( 'pgcache flush "' . $group . '" group' );
216
  }
217
 
218
+ $cache = $this->_get_cache( $group );
219
  $cache->flush( $group );
220
  }
221
  }
222
 
223
+ if ( count( $this->queued_urls ) > 0 ) {
 
 
224
  if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
225
  self::log( 'pgcache flush ' . $count . ' urls' );
226
  }
227
 
 
228
  $mobile_groups = $this->_get_mobile_groups();
229
  $referrer_groups = $this->_get_referrer_groups();
230
  $cookies = $this->_get_cookies();
231
  $encryptions = $this->_get_encryptions();
232
  $compressions = $this->_get_compressions();
233
 
234
+ $caches = array(
235
+ '*' => $this->_get_cache()
236
+ );
237
+
238
+ foreach ( $this->queued_urls as $url => $group ) {
239
+ if ( !isset( $caches[$group] ) ) {
240
+ $caches[$group] = $this->_get_cache( $group );
241
+ }
242
+ $this->_flush_url( $url, $caches[$group], $mobile_groups,
243
+ $referrer_groups, $cookies, $encryptions, $compressions,
244
+ $group == '*' ? '' : $group );
245
  }
246
 
247
+ $count += count( $this->queued_urls );
248
+
249
  // Purge sitemaps if a sitemap option has a regex
250
  if ( $this->_config->get_string( 'pgcache.purge.sitemap_regex' ) ) {
251
+ $cache = $this->_get_cache( 'sitemaps' );
252
  $cache->flush( 'sitemaps' );
253
+ $count++;
254
  }
255
 
256
  $this->queued_urls = array();
260
  return $count;
261
  }
262
 
263
+ /**
264
+ * Does the actual job - flushing of a single url cache entries
265
+ */
266
+ private function _flush_url( $url, $cache, $mobile_groups, $referrer_groups,
267
+ $cookies, $encryptions, $compressions, $group ) {
268
+ foreach ( $mobile_groups as $mobile_group ) {
269
+ foreach ( $referrer_groups as $referrer_group ) {
270
+ foreach ( $cookies as $cookie ) {
271
+ foreach ( $encryptions as $encryption ) {
272
+ foreach ( $compressions as $compression ) {
273
+ $page_keys = array();
274
+ $page_keys[] = $this->_get_page_key(
275
+ array(
276
+ 'useragent' => $mobile_group,
277
+ 'referrer' => $referrer_group,
278
+ 'cookie' => $cookie,
279
+ 'encryption' => $encryption,
280
+ 'compression' => $compression,
281
+ 'group' => $group
282
+ ),
283
+ $url );
284
+
285
+ $page_keys = apply_filters(
286
+ 'w3tc_pagecache_flush_url_keys', $page_keys );
287
+
288
+ foreach ( $page_keys as $page_key ) {
289
+ $cache->delete( $page_key, $group );
290
+ }
291
+ }
292
+ }
293
+ }
294
+ }
295
+ }
296
+ }
297
+
298
  /**
299
  * Returns array of mobile groups
 
 
300
  */
301
+ private function _get_mobile_groups() {
302
  $mobile_groups = array( '' );
303
 
304
  if ( $this->_mobile ) {
311
 
312
  /**
313
  * Returns array of referrer groups
 
 
314
  */
315
+ private function _get_referrer_groups() {
316
  $referrer_groups = array( '' );
317
 
318
  if ( $this->_referrer ) {
325
 
326
  /**
327
  * Returns array of cookies
 
 
328
  */
329
+ private function _get_cookies() {
330
  $cookies = array( '' );
331
 
332
+ if ( $this->_config->get_boolean( 'pgcache.cookiegroups.enabled' ) ) {
333
+ $cookies = array_merge( $cookies,
334
+ array_keys( $this->_config->get_array( 'pgcache.cookiegroups.groups' ) ) );
335
+ }
336
 
337
  return $cookies;
338
  }
339
 
340
  /**
341
  * Returns array of encryptions
 
 
342
  */
343
+ private function _get_encryptions() {
344
  $is_https = ( substr( get_home_url(), 0, 5 ) == 'https' );
345
 
346
  $encryptions = array();
353
  return $encryptions;
354
  }
355
 
 
 
356
  private function _append_parent_terms( $terms, $terms_to_check_parents ) {
357
  $terms_to_check_parents = $terms;
358
  $ids = null;
PgCache_Plugin.php CHANGED
@@ -36,6 +36,9 @@ class PgCache_Plugin {
36
  add_action( 'w3tc_flush_url',
37
  array( $this, 'w3tc_flush_url' ),
38
  1100, 1 );
 
 
 
39
  add_filter( 'w3tc_admin_bar_menu',
40
  array( $this, 'w3tc_admin_bar_menu' ) );
41
 
@@ -274,6 +277,7 @@ class PgCache_Plugin {
274
  'servers' => $c->get_array( 'pgcache.memcached.servers' ),
275
  'username' => $c->get_string( 'pgcache.memcached.username' ),
276
  'password' => $c->get_string( 'pgcache.memcached.password' ),
 
277
  'name' => __( 'Page Cache', 'w3-total-cache' )
278
  );
279
  } elseif ( $c->get_string( 'pgcache.engine' ) == 'redis' ) {
@@ -362,4 +366,18 @@ class PgCache_Plugin {
362
 
363
  return $v;
364
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  }
36
  add_action( 'w3tc_flush_url',
37
  array( $this, 'w3tc_flush_url' ),
38
  1100, 1 );
39
+
40
+ add_filter( 'w3tc_pagecache_set_header',
41
+ array( $this, 'w3tc_pagecache_set_header' ), 10, 3 );
42
  add_filter( 'w3tc_admin_bar_menu',
43
  array( $this, 'w3tc_admin_bar_menu' ) );
44
 
277
  'servers' => $c->get_array( 'pgcache.memcached.servers' ),
278
  'username' => $c->get_string( 'pgcache.memcached.username' ),
279
  'password' => $c->get_string( 'pgcache.memcached.password' ),
280
+ 'binary_protocol' => $c->get_boolean( 'pgcache.memcached.binary_protocol' ),
281
  'name' => __( 'Page Cache', 'w3-total-cache' )
282
  );
283
  } elseif ( $c->get_string( 'pgcache.engine' ) == 'redis' ) {
366
 
367
  return $v;
368
  }
369
+
370
+
371
+
372
+ /**
373
+ * By default headers are not cached by file_generic
374
+ */
375
+ public function w3tc_pagecache_set_header( $header, $header_original,
376
+ $pagecache_engine ) {
377
+ if ( $pagecache_engine == 'file_generic' ) {
378
+ return null;
379
+ }
380
+
381
+ return $header;
382
+ }
383
  }
Root_AdminActions.php CHANGED
@@ -39,15 +39,16 @@ class Root_AdminActions {
39
  static $handlers = null;
40
  if ( is_null( $handlers ) ) {
41
  $handlers = array(
42
- 'flush' => 'Generic_AdminActions_Flush',
43
  'cdn_google_drive' => 'Cdn_GoogleDrive_AdminActions',
44
  'cdn' => 'Cdn_AdminActions',
45
  'config' => 'Generic_AdminActions_Config',
46
- 'test' => 'Generic_AdminActions_Test',
47
- 'licensing' => 'Licensing_AdminActions',
48
- 'extensions' => 'Extensions_AdminActions',
49
  'default' => 'Generic_AdminActions_Default',
 
 
 
50
  'support' => 'Support_AdminActions',
 
51
  'ustats' => 'UsageStatistics_AdminActions'
52
  );
53
  $handlers = apply_filters( 'w3tc_admin_actions', $handlers );
39
  static $handlers = null;
40
  if ( is_null( $handlers ) ) {
41
  $handlers = array(
42
+ 'boldgrid' => 'Generic_WidgetBoldGrid_AdminActions',
43
  'cdn_google_drive' => 'Cdn_GoogleDrive_AdminActions',
44
  'cdn' => 'Cdn_AdminActions',
45
  'config' => 'Generic_AdminActions_Config',
 
 
 
46
  'default' => 'Generic_AdminActions_Default',
47
+ 'extensions' => 'Extensions_AdminActions',
48
+ 'flush' => 'Generic_AdminActions_Flush',
49
+ 'licensing' => 'Licensing_AdminActions',
50
  'support' => 'Support_AdminActions',
51
+ 'test' => 'Generic_AdminActions_Test',
52
  'ustats' => 'UsageStatistics_AdminActions'
53
  );
54
  $handlers = apply_filters( 'w3tc_admin_actions', $handlers );
Root_AdminMenu.php CHANGED
@@ -142,20 +142,11 @@ class Root_AdminMenu {
142
  array( $this, 'options' )
143
  );
144
  $submenu_pages[] = $hook;
145
-
146
- if ( isset( $titles['redirect_faq'] ) ) {
147
- add_action( 'load-' . $hook, array( $this, 'redirect_faq' ) );
148
- }
149
  }
150
  }
151
  return $submenu_pages;
152
  }
153
 
154
- public function redirect_faq() {
155
- wp_redirect( W3TC_FAQ_URL );
156
- exit;
157
- }
158
-
159
  /**
160
  * Options page
161
  *
142
  array( $this, 'options' )
143
  );
144
  $submenu_pages[] = $hook;
 
 
 
 
145
  }
146
  }
147
  return $submenu_pages;
148
  }
149
 
 
 
 
 
 
150
  /**
151
  * Options page
152
  *
Root_Loader.php CHANGED
@@ -31,6 +31,8 @@ class Root_Loader {
31
  $plugins[] = new Cdn_Plugin();
32
  if ( $c->get_boolean( 'cdnfsd.enabled' ) )
33
  $plugins[] = new Cdnfsd_Plugin();
 
 
34
  if ( $c->get_boolean( 'browsercache.enabled' ) )
35
  $plugins[] = new BrowserCache_Plugin();
36
  if ( $c->get_boolean( 'minify.enabled' ) )
@@ -44,6 +46,7 @@ class Root_Loader {
44
  $plugins[] = new Generic_Plugin_Admin();
45
  $plugins[] = new BrowserCache_Plugin_Admin();
46
  $plugins[] = new DbCache_Plugin_Admin();
 
47
  $plugins[] = new ObjectCache_Plugin_Admin();
48
  $plugins[] = new PgCache_Plugin_Admin();
49
  $plugins[] = new Minify_Plugin_Admin();
31
  $plugins[] = new Cdn_Plugin();
32
  if ( $c->get_boolean( 'cdnfsd.enabled' ) )
33
  $plugins[] = new Cdnfsd_Plugin();
34
+ if ( $c->get_boolean( 'lazyload.enabled' ) )
35
+ $plugins[] = new LazyLoad_Plugin();
36
  if ( $c->get_boolean( 'browsercache.enabled' ) )
37
  $plugins[] = new BrowserCache_Plugin();
38
  if ( $c->get_boolean( 'minify.enabled' ) )
46
  $plugins[] = new Generic_Plugin_Admin();
47
  $plugins[] = new BrowserCache_Plugin_Admin();
48
  $plugins[] = new DbCache_Plugin_Admin();
49
+ $plugins[] = new LazyLoad_Plugin_Admin();
50
  $plugins[] = new ObjectCache_Plugin_Admin();
51
  $plugins[] = new PgCache_Plugin_Admin();
52
  $plugins[] = new Minify_Plugin_Admin();
UsageStatistics_GeneralPage_View.php CHANGED
@@ -20,8 +20,8 @@ Util_Ui::config_item( array(
20
  'checkbox_label' => __( 'Enable', 'w3-total-cache' ),
21
  'disabled' => ( $is_pro ? null : true ),
22
  'description' => __( 'Enable statistics collection. Note that this consumes additional resources and is not recommended to be run continuously.',
23
- 'w3-total-cache' ) .
24
- ( $is_pro ? '' : __( ' <strong>Available after <a href="#" class="button-buy-plugin" data-src="stats_requirements">upgrade</a>.</strong>', 'w3-total-cache' ) )
25
  ) );
26
  Util_Ui::config_item( array(
27
  'key' => 'stats.slot_seconds',
20
  'checkbox_label' => __( 'Enable', 'w3-total-cache' ),
21
  'disabled' => ( $is_pro ? null : true ),
22
  'description' => __( 'Enable statistics collection. Note that this consumes additional resources and is not recommended to be run continuously.',
23
+ 'w3-total-cache' ),
24
+ 'pro_feature' => true
25
  ) );
26
  Util_Ui::config_item( array(
27
  'key' => 'stats.slot_seconds',
UsageStatistics_Widget.php CHANGED
@@ -5,15 +5,20 @@ namespace W3TC;
5
  * widget with stats
6
  */
7
  class UsageStatistics_Widget {
8
- private $enabled = false;
 
 
 
 
 
 
9
 
 
 
10
 
11
 
12
- public function init() {
13
- $c = Dispatcher::config();
14
- $this->enabled = ( $c->get_boolean( 'stats.enabled' ) &&
15
- Util_Environment::is_w3tc_pro( $c ) );
16
 
 
17
  add_action( 'w3tc_widget_setup', array(
18
  $this,
19
  'w3tc_widget_setup'
@@ -37,21 +42,20 @@ class UsageStatistics_Widget {
37
 
38
 
39
  static public function admin_init_w3tc_dashboard() {
40
- wp_enqueue_script( 'w3tc-canvasjs',
41
- plugins_url( 'pub/js/chartjs.min.js', W3TC_FILE ),
42
- array(), W3TC_VERSION );
43
- wp_enqueue_script( 'w3tc-widget-usagestatistics',
44
- plugins_url( 'UsageStatistics_Widget_View.js', W3TC_FILE ),
45
- array(), W3TC_VERSION );
 
 
46
  }
47
 
48
 
49
 
50
  public function widget_form() {
51
- $c = Dispatcher::config();
52
- $enabled = ( $c->get_boolean( 'stats.enabled' ) &&
53
- Util_Environment::is_w3tc_pro( $c ) );
54
- if ( $enabled ) {
55
  include W3TC_DIR . '/UsageStatistics_Widget_View.php';
56
  } else {
57
  include W3TC_DIR . '/UsageStatistics_Widget_View_Disabled.php';
5
  * widget with stats
6
  */
7
  class UsageStatistics_Widget {
8
+ static private function enabled() {
9
+ static $_enabled = null;
10
+ if ( is_null( $_enabled ) ) {
11
+ $c = Dispatcher::config();
12
+ $_enabled = ( $c->get_boolean( 'stats.enabled' ) &&
13
+ Util_Environment::is_w3tc_pro( $c ) );
14
+ }
15
 
16
+ return $_enabled;
17
+ }
18
 
19
 
 
 
 
 
20
 
21
+ public function init() {
22
  add_action( 'w3tc_widget_setup', array(
23
  $this,
24
  'w3tc_widget_setup'
42
 
43
 
44
  static public function admin_init_w3tc_dashboard() {
45
+ if ( self::enabled() ) {
46
+ wp_enqueue_script( 'w3tc-canvasjs',
47
+ plugins_url( 'pub/js/chartjs.min.js', W3TC_FILE ),
48
+ array(), W3TC_VERSION );
49
+ wp_enqueue_script( 'w3tc-widget-usagestatistics',
50
+ plugins_url( 'UsageStatistics_Widget_View.js', W3TC_FILE ),
51
+ array(), W3TC_VERSION );
52
+ }
53
  }
54
 
55
 
56
 
57
  public function widget_form() {
58
+ if ( self::enabled() ) {
 
 
 
59
  include W3TC_DIR . '/UsageStatistics_Widget_View.php';
60
  } else {
61
  include W3TC_DIR . '/UsageStatistics_Widget_View_Disabled.php';
UsageStatistics_Widget_View_Disabled.php CHANGED
@@ -27,7 +27,7 @@ if ( !defined( 'W3TC' ) )
27
 
28
  </style>
29
  <p class="w3tcuw_inactive">
30
- <?php if ( !Util_Environment::is_w3tc_pro( $c ) ): ?>
31
  <input type="button"
32
  class="button-primary button-buy-plugin {nonce: '<?php echo wp_create_nonce( 'w3tc' ) ?>'}" data-src="usagestatistics_widget" value="<?php _e( 'Upgrade to Pro', 'w3-total-cache' ) ?>" />
33
  <?php else: ?>
27
 
28
  </style>
29
  <p class="w3tcuw_inactive">
30
+ <?php if ( !Util_Environment::is_w3tc_pro( Dispatcher::config() ) ): ?>
31
  <input type="button"
32
  class="button-primary button-buy-plugin {nonce: '<?php echo wp_create_nonce( 'w3tc' ) ?>'}" data-src="usagestatistics_widget" value="<?php _e( 'Upgrade to Pro', 'w3-total-cache' ) ?>" />
33
  <?php else: ?>
Util_ConfigLabel.php CHANGED
@@ -10,6 +10,7 @@ class Util_ConfigLabel {
10
  'memcached.persistent' => __( 'Persistent connection', 'w3-total-cache' ),
11
  'memcached.username' => __( 'Memcached username:', 'w3-total-cache' ),
12
  'memcached.password' => __( 'Memcached password:', 'w3-total-cache' ),
 
13
  'redis.servers' => __( 'Redis hostname:port / <acronym title="Internet Protocol">IP</acronym>:port:', 'w3-total-cache' ),
14
  'redis.persistent' => __( 'Persistent connection', 'w3-total-cache' ),
15
  'redis.dbid' => __( 'Redis Database ID:', 'w3-total-cache' ),
10
  'memcached.persistent' => __( 'Persistent connection', 'w3-total-cache' ),
11
  'memcached.username' => __( 'Memcached username:', 'w3-total-cache' ),
12
  'memcached.password' => __( 'Memcached password:', 'w3-total-cache' ),
13
+ 'memcached.binary_protocol' => __( 'Binary protocol', 'w3-total-cache' ),
14
  'redis.servers' => __( 'Redis hostname:port / <acronym title="Internet Protocol">IP</acronym>:port:', 'w3-total-cache' ),
15
  'redis.persistent' => __( 'Persistent connection', 'w3-total-cache' ),
16
  'redis.dbid' => __( 'Redis Database ID:', 'w3-total-cache' ),
Util_Content.php CHANGED
@@ -85,4 +85,26 @@ class Util_Content {
85
  static public function is_database_error() {
86
  return false;
87
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
85
  static public function is_database_error() {
86
  return false;
87
  }
88
+
89
+
90
+
91
+ /**
92
+ * Converts
93
+ * 127.0.0.1:1234 to ( '123.0.0.1', 1234 )
94
+ * tls://127.0.0.1:1234 to ( 'tls://123.0.0.1', 1234 )
95
+ * unix:/my/pipe to ( 'unix:/my/pipe', 0 )
96
+ *
97
+ * Doesnt fit to that class perfectly but selected due to common usage
98
+ * of loaded classes
99
+ */
100
+ static public function endpoint_to_host_port( $server, $port_default = 0 ) {
101
+ $p = strrpos( $server, ':' );
102
+ if ( substr( $server, 0, 5 ) == 'unix:' || $p === false ) {
103
+ return array( trim( $server ), $port_default );
104
+ }
105
+
106
+ return array(
107
+ trim( substr( $server, 0, $p ) ),
108
+ (int)substr( $server, $p + 1 ) );
109
+ }
110
  }
Util_Environment.php CHANGED
@@ -1038,9 +1038,9 @@ class Util_Environment {
1038
  return $post_ID;
1039
  } elseif ( $comment_post_ID ) {
1040
  return $comment_post_ID;
1041
- } elseif ( ( is_single() || is_page() ) && is_array( $posts ) ) {
1042
  return $posts[0]->ID;
1043
- } elseif ( is_object( $posts ) && property_exists( $posts, 'ID' ) ) {
1044
  return $posts->ID;
1045
  } elseif ( isset( $_REQUEST['p'] ) ) {
1046
  return (integer) $_REQUEST['p'];
1038
  return $post_ID;
1039
  } elseif ( $comment_post_ID ) {
1040
  return $comment_post_ID;
1041
+ } elseif ( ( is_single() || is_page() ) && isset( $posts[0]->ID ) ) {
1042
  return $posts[0]->ID;
1043
+ } elseif ( isset( $posts->ID ) ) {
1044
  return $posts->ID;
1045
  } elseif ( isset( $_REQUEST['p'] ) ) {
1046
  return (integer) $_REQUEST['p'];
Util_Mime.php CHANGED
@@ -77,4 +77,41 @@ class Util_Mime {
77
 
78
  return $cache[$file];
79
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  }
77
 
78
  return $cache[$file];
79
  }
80
+
81
+
82
+
83
+ static public function sections_to_mime_types_map() {
84
+ static $sections_to_mime_types_array = null;
85
+
86
+ if ( is_null( $sections_to_mime_types_array ) ) {
87
+ $sections_to_mime_types_array = array(
88
+ 'cssjs' => include W3TC_INC_DIR . '/mime/cssjs.php',
89
+ 'html' => include W3TC_INC_DIR . '/mime/html.php',
90
+ 'other' => include W3TC_INC_DIR . '/mime/other.php'
91
+ );
92
+ }
93
+
94
+ return $sections_to_mime_types_array;
95
+ }
96
+
97
+
98
+
99
+ static public function mime_type_to_section( $mime_type ) {
100
+ static $mime_type_to_section_array = null;
101
+
102
+ if ( is_null( $mime_type_to_section_array ) ) {
103
+ $sections = self::sections_to_mime_types_map();
104
+
105
+ $mime_type_to_section_array = array();
106
+
107
+ foreach ( $sections as $section => $mime_types ) {
108
+ foreach ( $mime_types as $mime_type ) {
109
+ $mime_type_to_section_array[$mime_type] = $section;
110
+ }
111
+ }
112
+ }
113
+
114
+ return isset( $mime_type_to_section_array[$mime_type] ) ?
115
+ $mime_type_to_section_array[$mime_type] : null;
116
+ }
117
  }
Util_Ui.php CHANGED
@@ -458,15 +458,22 @@ class Util_Ui {
458
  $label = '';
459
  $item_disabled = false;
460
  $postfix = '';
 
461
 
462
  if ( !is_array( $label_or_array ) ) {
463
  $label = $label_or_array;
464
  } else {
465
  $label = $label_or_array['label'];
466
  $item_disabled = $label_or_array['disabled'];
467
- $postfix = $label_or_array['postfix'];
 
 
 
468
  }
469
 
 
 
 
470
  echo '<label><input type="radio" id="' . esc_attr( $name . '__' . $key ) .
471
  '" name="' . esc_attr( $name ) .
472
  '" value="' . esc_attr( $key ) . '"';
@@ -475,6 +482,9 @@ class Util_Ui {
475
  echo ' />';
476
  echo $label;
477
  echo '</label>' . $postfix . "\n";
 
 
 
478
  }
479
  }
480
 
@@ -575,6 +585,10 @@ class Util_Ui {
575
  echo "</th>\n<td>\n";
576
  }
577
 
 
 
 
 
578
  foreach ( $a as $key => $e ) {
579
  if ( $key == 'checkbox' )
580
  Util_Ui::checkbox( $id,
@@ -605,6 +619,10 @@ class Util_Ui {
605
  ( isset( $e['disabled'] ) ? $e['disabled'] : false ) );
606
  }
607
 
 
 
 
 
608
  if ( isset( $a['style'] ) )
609
  echo "</th>";
610
  else
@@ -704,11 +722,15 @@ class Util_Ui {
704
  );
705
  }
706
 
707
- if ( isset( $a['control_after'] ) )
708
  $table_tr['html'] = $a['control_after'];
709
-
710
- if ( isset( $a['description'] ) )
711
  $table_tr['description'] = $a['description'];
 
 
 
 
712
 
713
  Util_Ui::table_tr( $table_tr );
714
  }
@@ -776,6 +798,68 @@ class Util_Ui {
776
 
777
 
778
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779
  /**
780
  * On subblogs - shows button to enable/disable custom configuration
781
  * $a['key'] - config key *_overloaded which are managed
458
  $label = '';
459
  $item_disabled = false;
460
  $postfix = '';
461
+ $pro_feature = false;
462
 
463
  if ( !is_array( $label_or_array ) ) {
464
  $label = $label_or_array;
465
  } else {
466
  $label = $label_or_array['label'];
467
  $item_disabled = $label_or_array['disabled'];
468
+ $postfix = isset( $label_or_array['postfix'] ) ?
469
+ $label_or_array['postfix'] : '';
470
+ $pro_feature = isset( $label_or_array['pro_feature'] ) ?
471
+ $label_or_array['pro_feature'] : false;
472
  }
473
 
474
+ if ( $pro_feature ) {
475
+ Util_Ui::pro_wrap_maybe_start();
476
+ }
477
  echo '<label><input type="radio" id="' . esc_attr( $name . '__' . $key ) .
478
  '" name="' . esc_attr( $name ) .
479
  '" value="' . esc_attr( $key ) . '"';
482
  echo ' />';
483
  echo $label;
484
  echo '</label>' . $postfix . "\n";
485
+ if ( $pro_feature ) {
486
+ Util_Ui::pro_wrap_maybe_end( $name . '__' . $key );
487
+ }
488
  }
489
  }
490
 
585
  echo "</th>\n<td>\n";
586
  }
587
 
588
+ if ( isset( $a['pro_feature'] ) && $a['pro_feature'] ) {
589
+ Util_Ui::pro_wrap_maybe_start();
590
+ }
591
+
592
  foreach ( $a as $key => $e ) {
593
  if ( $key == 'checkbox' )
594
  Util_Ui::checkbox( $id,
619
  ( isset( $e['disabled'] ) ? $e['disabled'] : false ) );
620
  }
621
 
622
+ if ( isset( $a['pro_feature'] ) && $a['pro_feature'] ) {
623
+ Util_Ui::pro_wrap_maybe_end( $id );
624
+ }
625
+
626
  if ( isset( $a['style'] ) )
627
  echo "</th>";
628
  else
722
  );
723
  }
724
 
725
+ if ( isset( $a['control_after'] ) ) {
726
  $table_tr['html'] = $a['control_after'];
727
+ }
728
+ if ( isset( $a['description'] ) ) {
729
  $table_tr['description'] = $a['description'];
730
+ }
731
+ if ( isset( $a['pro_feature'] ) ) {
732
+ $table_tr['pro_feature'] = $a['pro_feature'];
733
+ }
734
 
735
  Util_Ui::table_tr( $table_tr );
736
  }
798
 
799
 
800
 
801
+ static public function pro_wrap_maybe_start() {
802
+ if ( Util_Environment::is_w3tc_pro( Dispatcher::config() ) ) {
803
+ return;
804
+ }
805
+
806
+ ?>
807
+ <div class="w3tc-gopro">
808
+ <div>
809
+ <?php
810
+ }
811
+
812
+
813
+
814
+ static public function pro_wrap_maybe_end( $button_data_src ) {
815
+ if ( Util_Environment::is_w3tc_pro( Dispatcher::config() ) ) {
816
+ return;
817
+ }
818
+
819
+ ?>
820
+ </div>
821
+ <div style="text-align:right">
822
+ <button class="button w3tc-gopro-button button-buy-plugin" data-src="<?php echo esc_attr( $button_data_src ) ?>">
823
+ Unlock Feature
824
+ </button>
825
+ </div>
826
+ </div>
827
+ <?php
828
+ }
829
+
830
+
831
+
832
+ static public function pro_wrap_maybe_start2() {
833
+ if ( Util_Environment::is_w3tc_pro( Dispatcher::config() ) ) {
834
+ return;
835
+ }
836
+
837
+ ?>
838
+ <div class="updated w3tc_note" id="licensing_terms" style="display: flex; align-items: center">
839
+ <p style="flex-grow: 1">
840
+ <?php
841
+ }
842
+
843
+
844
+
845
+ static public function pro_wrap_maybe_end2( $button_data_src ) {
846
+ if ( Util_Environment::is_w3tc_pro( Dispatcher::config() ) ) {
847
+ return;
848
+ }
849
+
850
+ ?>
851
+ </p>
852
+ <div style="text-align: right">
853
+ <button class="button w3tc-gopro-button button-buy-plugin" data-src="<?php echo esc_attr( $button_data_src ) ?>">
854
+ Unlock Feature
855
+ </button>
856
+ </div>
857
+ </div>
858
+ <?php
859
+ }
860
+
861
+
862
+
863
  /**
864
  * On subblogs - shows button to enable/disable custom configuration
865
  * $a['key'] - config key *_overloaded which are managed
Util_Widget.php CHANGED
@@ -52,7 +52,7 @@ class Util_Widget {
52
  * Registers widget
53
  */
54
  static public function add( $widget_id, $widget_name, $callback,
55
- $control_callback = null, $location = 'normal', $header_text = null ) {
56
  $screen = get_current_screen();
57
  global $w3tc_dashboard_control_callbacks;
58
 
@@ -69,7 +69,7 @@ class Util_Widget {
69
 
70
  $widget_name .= ' <div class="w3tc-widget-configure postbox-title-action">' .
71
  '<a href="' . esc_url( $control_callback ) .
72
- '" class="edit-box open-box">' . $header_text .
73
  '</a></span>';
74
  }
75
 
52
  * Registers widget
53
  */
54
  static public function add( $widget_id, $widget_name, $callback,
55
+ $control_callback = null, $location = 'normal', $header_text = null, $header_class = '') {
56
  $screen = get_current_screen();
57
  global $w3tc_dashboard_control_callbacks;
58
 
69
 
70
  $widget_name .= ' <div class="w3tc-widget-configure postbox-title-action">' .
71
  '<a href="' . esc_url( $control_callback ) .
72
+ '" class="edit-box open-box ' . esc_attr($header_class) . '">' . $header_text .
73
  '</a></span>';
74
  }
75
 
Varnish_Flush.php CHANGED
@@ -78,11 +78,11 @@ class Varnish_Flush {
78
  }
79
 
80
  /*
81
- * Sends purge request. Cannt use default wp HTTP implementation
82
- * if we send request to different host than specified in $url
83
- *
84
- * @param $url string
85
- */
86
  function _request( $varnish_server, $url ) {
87
  $parse_url = @parse_url( $url );
88
 
@@ -95,12 +95,8 @@ class Varnish_Flush {
95
  $query = ( isset( $parse_url['query'] ) ? $parse_url['query'] : '' );
96
  $request_uri = $path . ( $query != '' ? '?' . $query : '' );
97
 
98
- if ( strpos( $varnish_server, ':' ) )
99
- list( $varnish_host, $varnish_port ) = explode( ':', $varnish_server );
100
- else {
101
- $varnish_host = $varnish_server;
102
- $varnish_port = 80;
103
- }
104
 
105
  // if url host is the same as varnish server - we can use regular
106
  // wordpress http infrastructure, otherwise custom request should be
@@ -205,14 +201,14 @@ class Varnish_Flush {
205
 
206
  // If WPMU Domain Mapping plugin is installed and active
207
  if ( defined( 'SUNRISE_LOADED' ) && SUNRISE_LOADED && isset( $wpdb->dmtable ) && !empty( $wpdb->dmtable ) ) {
208
- $blogs = $wpdb->get_results( "SELECT {$wpdb->blogs}.domain, {$wpdb->blogs}.path, {$wpdb->dmtable}.domain AS mapped_domain
209
- FROM {$wpdb->dmtable}
210
- RIGHT JOIN {$wpdb->blogs} ON {$wpdb->dmtable}.blog_id = {$wpdb->blogs}.blog_id
211
- WHERE site_id = {$wpdb->siteid}
212
- AND spam = 0
213
- AND deleted = 0
214
- AND archived = '0'
215
- " );
216
  foreach ( $blogs as $blog ) {
217
  if ( !isset( $blog->mapped_domain ) )
218
  $url = $protocall . $blog->domain . ( strlen( $blog->path )>1? '/' . trim( $blog->path, '/' ) : '' ) . '/.*';
@@ -226,13 +222,12 @@ class Varnish_Flush {
226
  $this->_purge( get_home_url().'/.*' );
227
  } else {
228
  $blogs = $wpdb->get_results( "
229
- SELECT domain, path
230
- FROM {$wpdb->blogs}
231
- WHERE site_id = '{$wpdb->siteid}'
232
- AND spam = 0
233
- AND deleted = 0
234
- AND archived = '0'
235
- " );
236
 
237
  foreach ( $blogs as $blog ) {
238
  $url = $protocall . $blog->domain . ( strlen( $blog->path )>1? '/' . trim( $blog->path, '/' ) : '' ) . '/.*';
78
  }
79
 
80
  /*
81
+ * Sends purge request. Cannt use default wp HTTP implementation
82
+ * if we send request to different host than specified in $url
83
+ *
84
+ * @param $url string
85
+ */
86
  function _request( $varnish_server, $url ) {
87
  $parse_url = @parse_url( $url );
88
 
95
  $query = ( isset( $parse_url['query'] ) ? $parse_url['query'] : '' );
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
201
 
202
  // If WPMU Domain Mapping plugin is installed and active
203
  if ( defined( 'SUNRISE_LOADED' ) && SUNRISE_LOADED && isset( $wpdb->dmtable ) && !empty( $wpdb->dmtable ) ) {
204
+ $blogs = $wpdb->get_results( "
205
+ SELECT {$wpdb->blogs}.domain, {$wpdb->blogs}.path, {$wpdb->dmtable}.domain AS mapped_domain
206
+ FROM {$wpdb->dmtable}
207
+ RIGHT JOIN {$wpdb->blogs} ON {$wpdb->dmtable}.blog_id = {$wpdb->blogs}.blog_id
208
+ WHERE site_id = {$wpdb->siteid}
209
+ AND spam = 0
210
+ AND deleted = 0
211
+ AND archived = '0'" );
212
  foreach ( $blogs as $blog ) {
213
  if ( !isset( $blog->mapped_domain ) )
214
  $url = $protocall . $blog->domain . ( strlen( $blog->path )>1? '/' . trim( $blog->path, '/' ) : '' ) . '/.*';
222
  $this->_purge( get_home_url().'/.*' );
223
  } else {
224
  $blogs = $wpdb->get_results( "
225
+ SELECT domain, path
226
+ FROM {$wpdb->blogs}
227
+ WHERE site_id = '{$wpdb->siteid}'
228
+ AND spam = 0
229
+ AND deleted = 0
230
+ AND archived = '0'" );
 
231
 
232
  foreach ( $blogs as $blog ) {
233
  $url = $protocall . $blog->domain . ( strlen( $blog->path )>1? '/' . trim( $blog->path, '/' ) : '' ) . '/.*';
inc/lightbox/upgrade.php CHANGED
@@ -9,21 +9,22 @@ if ( !defined( 'W3TC' ) )
9
  <div id="w3tc-upgrade">
10
  <div class="w3tc-overlay-logo"></div>
11
  <div class="w3tc_overlay_upgrade_header">
12
- <iframe src="https://www.w3-edge.com/checkout-ad/?data_src=<?php echo esc_attr($data_src) ?>" width="100%" height="420px"></iframe>
13
  </div>
14
  <div class="w3tc_overlay_content"></div>
15
  <div class="w3tc_overlay_footer">
16
- <?php if ( \W3TC\Util_Environment::is_https() ): ?>
17
- <input id="w3tc-purchase" type="button"
18
- class="btn w3tc-size image btn-default palette-turquoise secure"
19
- value="<?php _e( 'Subscribe to Go Faster Now', 'w3-total-cache' ) ?> " />
20
- <?php else: ?>
21
- <a id="w3tc-purchase-link" href="<?php echo \W3TC\Licensing_Core::purchase_url() ?>"
22
- target="_blank"
23
- class="btn w3tc-size image btn-default palette-turquoise secure">
24
- <?php _e( 'Subscribe to Go Faster Now', 'w3-total-cache' ) ?>
25
- </a>
26
- <?php endif ?>
 
27
  </div>
28
  <div style="clear: both"></div>
29
  </div>
9
  <div id="w3tc-upgrade">
10
  <div class="w3tc-overlay-logo"></div>
11
  <div class="w3tc_overlay_upgrade_header">
12
+ <iframe src="https://www.w3-edge.com/checkout-ad/?data_src=<?php echo esc_attr( $data_src ) ?>&client_id=<?php echo esc_attr( $client_id ) ?>" width="100%" height="420px"></iframe>
13
  </div>
14
  <div class="w3tc_overlay_content"></div>
15
  <div class="w3tc_overlay_footer">
16
+ <?php if ( \W3TC\Util_Environment::is_https() ): ?>
17
+ <input id="w3tc-purchase" type="button"
18
+ class="btn w3tc-size image btn-default palette-turquoise secure"
19
+ value="<?php _e( 'Subscribe to Go Faster Now', 'w3-total-cache' ) ?> " />
20
+ <?php else: ?>
21
+ <a id="w3tc-purchase-link"
22
+ href="<?php echo \W3TC\Licensing_Core::purchase_url( $data_src, $renew_key, $client_id ) ?>"
23
+ target="_blank"
24
+ class="btn w3tc-size image btn-default palette-turquoise secure">
25
+ <?php _e( 'Subscribe to Go Faster Now', 'w3-total-cache' ) ?>
26
+ </a>
27
+ <?php endif ?>
28
  </div>
29
  <div style="clear: both"></div>
30
  </div>
inc/options/common/header.php CHANGED
@@ -29,7 +29,7 @@ $licensing_visible = ( ( !Util_Environment::is_wpmu() || is_network_admin() ) &&
29
  array( 'id' => 'database_cache', 'text' => __( 'Database Cache', 'w3-total-cache' ) ),
30
  array( 'id' => 'object_cache', 'text' => __( 'Object Cache', 'w3-total-cache' ) ) );
31
  if ( Util_Environment::is_w3tc_pro( $config ) )
32
- $anchors[] = array( 'id' => 'fragment_cache', 'text' => __( 'Fragment Cache', 'w3-total-cache' ) );
33
 
34
  $anchors = array_merge( $anchors, array(
35
  array( 'id' => 'browser_cache', 'text' => __( 'Browser Cache', 'w3-total-cache' ) ),
@@ -161,7 +161,7 @@ $licensing_visible = ( ( !Util_Environment::is_wpmu() || is_network_admin() ) &&
161
  <a href="#rules"><?php _e( 'Rewrite Rules', 'w3-total-cache' ); ?></a> |
162
  <?php endif ?>
163
  <?php if ( count( $other_areas ) ): ?>
164
- <a href="#other"><?php _e( 'Other', 'w3-total-cache' ); ?></a> |
165
  <?php endif ?>
166
  <a href="#additional"><?php _e( 'Services', 'w3-total-cache' ); ?></a> |
167
  <a href="#modules"><?php _e( '<acronym title="Hypertext Preprocessor">PHP</acronym> Modules', 'w3-total-cache' ); ?></a>
29
  array( 'id' => 'database_cache', 'text' => __( 'Database Cache', 'w3-total-cache' ) ),
30
  array( 'id' => 'object_cache', 'text' => __( 'Object Cache', 'w3-total-cache' ) ) );
31
  if ( Util_Environment::is_w3tc_pro( $config ) )
32
+ $anchors[] = array( 'id' => 'fragmentcache', 'text' => __( 'Fragment Cache', 'w3-total-cache' ) );
33
 
34
  $anchors = array_merge( $anchors, array(
35
  array( 'id' => 'browser_cache', 'text' => __( 'Browser Cache', 'w3-total-cache' ) ),
161
  <a href="#rules"><?php _e( 'Rewrite Rules', 'w3-total-cache' ); ?></a> |
162
  <?php endif ?>
163
  <?php if ( count( $other_areas ) ): ?>
164
+ <a href="#other"><?php _e( 'Other', 'w3-total-cache' ); ?></a> |
165
  <?php endif ?>
166
  <a href="#additional"><?php _e( 'Services', 'w3-total-cache' ); ?></a> |
167
  <a href="#modules"><?php _e( '<acronym title="Hypertext Preprocessor">PHP</acronym> Modules', 'w3-total-cache' ); ?></a>
inc/options/extensions/list.php CHANGED
@@ -17,60 +17,60 @@ if ( !defined( 'W3TC' ) )
17
  */
18
  ?>
19
  <ul class="subsubsub">
20
- <li class="all"><a href="?page=w3tc_extensions&extension_status=all"<?php echo $extension_status == 'all' ? ' class="current"':''?>>All <span class="count">(<?php echo sizeof( $extensions_all ) ?>)</span></a> |</li>
21
- <li class="active"><a href="?page=w3tc_extensions&extension_status=active"<?php echo $extension_status == 'active' ? ' class="current"':''?>>Active <span class="count">(<?php echo sizeof( $extensions_active ) ?>)</span></a> |</li>
22
- <li class="inactive"><a href="?page=w3tc_extensions&extension_status=inactive"<?php echo $extension_status == 'inactive' ? ' class="current"':''?>>Inactive <span class="count">(<?php echo sizeof( $extensions_inactive ) ?>)</span></a></li>
23
  </ul>
24
 
25
  <div class="tablenav top">
26
 
27
- <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
28
- <div class="alignleft actions">
29
- <select name="action">
30
- <option value="-1" selected="selected"><?php _e( 'Bulk Actions', 'w3-total-cache' )?></option>
31
- <option value="activate-selected"><?php _e( 'Activate', 'w3-total-cache' )?></option>
32
- <option value="deactivate-selected"><?php _e( 'Deactivate', 'w3-total-cache' )?></option>
33
- </select>
34
- <input type="submit" name="" id="doaction" class="w3tc-button-save button action" value="<?php esc_attr_e( 'Apply' )?>">
35
- </div>
36
- <?php endif ?>
37
 
38
- <div class="tablenav-pages one-page">
39
- <span class="displaying-num"><?php printf( translate_nooped_plural( _n_noop( '%s extension', '%s extensions' ), sizeof( $extensions ), 'w3-total-cache' ), sizeof( $extensions ) ); ?></span>
40
- </div>
41
- <br class="clear">
42
  </div>
43
  <table class="wp-list-table widefat plugins w3tc_extensions" cellspacing="0">
44
- <thead>
45
- <tr>
46
- <th scope="col" id="cb" class="w3tc_extensions_manage_column_check"><label class="screen-reader-text" for="cb-select-all-1"><?php _e( 'Select All', 'w3-total-cache' )?></label><input id="cb-select-all-1" type="checkbox" class="w3tc_extensions_manage_input_checkall"></th><th scope="col" id="name" class="manage-column column-name" style=""><?php _e( 'Extension', 'w3-total-cache' )?></th><th scope="col" id="description" class="manage-column column-description" style=""><?php _e( 'Description', 'w3-total-cache' )?></th>
47
- </tr>
48
- </thead>
49
- <tfoot>
50
- <tr>
51
- <th scope="col" class="w3tc_extensions_manage_column_check"><label class="screen-reader-text" for="cb-select-all-2"><?php _e( 'Select All', 'w3-total-cache' )?></label><input id="cb-select-all-2" type="checkbox" class="w3tc_extensions_manage_input_checkall"></th><th scope="col" class="manage-column column-name" style=""><?php _e( 'Extension', 'w3-total-cache' )?></th><th scope="col" class="manage-column column-description" style=""><?php _e( 'Description', 'w3-total-cache' )?></th>
52
- </tr>
53
- </tfoot>
54
- <tbody id="the-list">
55
- <?php
56
  $cb_id = 0;
57
  foreach ( $extension_keys as $extension ):
58
- $meta = $extensions[$extension];
59
  $meta = $this->default_meta( $meta );
60
  $cb_id++;
61
  ?>
62
- <?php do_action( "w3tc_extension_before_row-{$extension}" ) ?>
63
- <tr id="<?php echo esc_attr( $extension )?>" class="<?php echo $config->is_extension_active( $extension ) ? 'active' : 'inactive'?>">
64
- <th scope="row" class="check-column">
65
- <label class="screen-reader-text" for="checkbox_<?php echo $cb_id?>"><?php printf( __( 'Select %s' ), $meta['name'] ) ?></label>
66
- <input type="checkbox" name="checked[]" value="<?php echo esc_attr( $extension ) ?>" id="checkbox_<?php echo $cb_id?>" class="w3tc_extensions_input_active" <?php disabled( !$meta['enabled'] )?>>
67
- </th>
68
- <td class="plugin-title">
69
- <strong><?php esc_html_e( $meta['name'] ) ?></strong>
70
- <div class="row-actions-visible">
71
- <?php if ( $config->is_extension_active( $extension ) ):
72
- $extra_links = array();
73
- if ( isset( $meta['settings_exists'] ) && $meta['settings_exists'] )
74
  $extra_links[] = '<a class="edit" href="' . esc_attr( Util_Ui::admin_url( sprintf( 'admin.php?page=w3tc_extensions&extension=%s', $extension ) ) ).'&action=view">'. __( 'Settings' ).'</a>';
75
  $extra_links = apply_filters( "w3tc_extension_plugin_links_{$extension}", $extra_links );
76
  $links = implode( ' | ', $extra_links );
@@ -78,85 +78,95 @@ if ( $links ) {
78
  echo $links;
79
  }
80
  ?>
81
- <span class="0">
82
- </span>
83
 
84
- <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
85
- <?php if ( $links ) echo ' | '; ?>
86
- <span class="deactivate">
87
- <a href="<?php esc_attr_e( wp_nonce_url( Util_Ui::admin_url( sprintf( 'admin.php?page=w3tc_extensions&action=deactivate&extension=%s&amp;extension_status=%s&amp;paged=%d', $extension, $extension_status, $page ) ), 'w3tc' ) ) ?>" title="<?php esc_attr_e( 'Deactivate this extension', 'w3-total-cache' ) ?> ">
88
- <?php _e( 'Deactivate' ) ?>
89
- </a>
90
- </span>
91
- <?php endif ?>
92
- <?php else: ?>
93
- <span class="activate">
94
- <?php if ( $meta['enabled'] ): ?>
95
- <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
96
- <a href="<?php esc_attr_e( wp_nonce_url( Util_Ui::admin_url( sprintf( 'admin.php?page=w3tc_extensions&action=activate&extension=%s&amp;extension_status=%s&amp;paged=%d', $extension, $extension_status, $page ) ), 'w3tc' ) ) ?>" title="<?php esc_attr_e( 'Activate this extension', 'w3-total-cache' ) ?> ">
97
- <?php _e( 'Activate' ) ?>
98
- </a>
99
- <?php endif ?>
100
- <?php else: ?>
101
- <?php if ( !empty( $meta['disabled_message'] ) ): ?>
102
- <?php echo $meta['disabled_message'] ?>
103
- <?php else: ?>
104
- <?php _e( 'Disabled: see Requirements', 'w3-total-cache' ) ?>
105
- <?php endif; ?>
106
- <?php endif; ?>
107
- </span>
108
- <?php endif ?>
109
 
110
- </div>
111
- </td>
112
- <td class="column-description desc">
113
- <div class="plugin-description">
114
- <p>
115
- <?php _e( $meta['description'] ) ?>
116
- <?php if ( !empty( $meta['requirements'] ) ): ?>
117
- <br />
118
- <span class="description"><?php printf( __( 'Requirements: %s', 'w3-total-cache' ), apply_filters( "w3tc_extension_requirements-{$extension}", $meta['requirements'] ) ) ?></span>
119
- <?php do_action( "w3tc_extension_requirements-{$extension}" ) ?>
120
- <?php endif ?>
121
- </p>
122
- </div>
123
- <div class="<?php echo $config->is_extension_active( $extension ) ? 'active' : 'inactive'?> second plugin-version-author-uri">
124
- <?php printf( __( 'Version %s', 'w3-total-cache' ), $meta['version'] )?>
125
- |
126
- <?php printf( __( 'By %s', 'w3-total-cache' ),
 
 
 
 
 
 
 
 
 
 
127
  sprintf( '<a href="%s" title="' . __( 'Visit author homepage' ) .
128
  '">%s</a>', $meta['author_uri'], $meta['author'] ) ) ?>
129
- |
130
- <a href="<?php esc_attr_e( $meta['extension_uri'] ) ?>"
131
- title="<?php esc_attr_e( 'Visit extension site', 'w3-total-cache' ) ?>"><?php
132
  _e( 'Visit extension site', 'w3-total-cache' )?></a>
133
- </div>
134
- </td>
135
- </tr>
136
- <?php do_action( "w3tc_extension_after_row", $extension ) ?>
137
- <?php do_action( "w3tc_extension_after_row-{$extension}" ) ?>
138
- <?php endforeach ?>
139
- </tbody>
140
  </table>
141
  <div class="tablenav bottom">
142
 
143
- <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
144
- <div class="alignleft actions">
145
- <select name="action2">
146
- <option value="-1" selected="selected"><?php _e( 'Bulk Actions', 'w3-total-cache' )?></option>
147
- <option value="activate-selected"><?php _e( 'Activate', 'w3-total-cache' )?></option>
148
- <option value="deactivate-selected"><?php _e( 'Deactivate', 'w3-total-cache' )?></option>
149
- </select>
150
- <input type="submit" name="" id="doaction" class="w3tc-button-save button action" value="<?php esc_attr_e( 'Apply' )?>">
151
- </div>
152
- <?php endif ?>
153
 
154
- <div class="tablenav-pages one-page">
155
- <span class="displaying-num"><?php printf( translate_nooped_plural( _n_noop( '%s extension', '%s extensions' ), sizeof( $extensions ), 'w3-total-cache' ), sizeof( $extensions ) ); ?></span>
156
- </div>
157
- <br class="clear">
158
  </div>
159
 
160
  <?php if ( is_network_admin() ): ?>
161
- <?php Util_Ui::button_config_save( 'extensions' ); ?>
162
  <?php endif ?>
17
  */
18
  ?>
19
  <ul class="subsubsub">
20
+ <li class="all"><a href="?page=w3tc_extensions&extension_status=all"<?php echo $extension_status == 'all' ? ' class="current"':''?>>All <span class="count">(<?php echo sizeof( $extensions_all ) ?>)</span></a> |</li>
21
+ <li class="active"><a href="?page=w3tc_extensions&extension_status=active"<?php echo $extension_status == 'active' ? ' class="current"':''?>>Active <span class="count">(<?php echo sizeof( $extensions_active ) ?>)</span></a> |</li>
22
+ <li class="inactive"><a href="?page=w3tc_extensions&extension_status=inactive"<?php echo $extension_status == 'inactive' ? ' class="current"':''?>>Inactive <span class="count">(<?php echo sizeof( $extensions_inactive ) ?>)</span></a></li>
23
  </ul>
24
 
25
  <div class="tablenav top">
26
 
27
+ <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
28
+ <div class="alignleft actions">
29
+ <select name="action">
30
+ <option value="-1" selected="selected"><?php _e( 'Bulk Actions', 'w3-total-cache' )?></option>
31
+ <option value="activate-selected"><?php _e( 'Activate', 'w3-total-cache' )?></option>
32
+ <option value="deactivate-selected"><?php _e( 'Deactivate', 'w3-total-cache' )?></option>
33
+ </select>
34
+ <input type="submit" name="" id="doaction" class="w3tc-button-save button action" value="<?php esc_attr_e( 'Apply' )?>">
35
+ </div>
36
+ <?php endif ?>
37
 
38
+ <div class="tablenav-pages one-page">
39
+ <span class="displaying-num"><?php printf( translate_nooped_plural( _n_noop( '%s extension', '%s extensions' ), sizeof( $extensions ), 'w3-total-cache' ), sizeof( $extensions ) ); ?></span>
40
+ </div>
41
+ <br class="clear">
42
  </div>
43
  <table class="wp-list-table widefat plugins w3tc_extensions" cellspacing="0">
44
+ <thead>
45
+ <tr>
46
+ <th scope="col" id="cb" class="w3tc_extensions_manage_column_check"><label class="screen-reader-text" for="cb-select-all-1"><?php _e( 'Select All', 'w3-total-cache' )?></label><input id="cb-select-all-1" type="checkbox" class="w3tc_extensions_manage_input_checkall"></th><th scope="col" id="name" class="manage-column column-name" style=""><?php _e( 'Extension', 'w3-total-cache' )?></th><th scope="col" id="description" class="manage-column column-description" style=""><?php _e( 'Description', 'w3-total-cache' )?></th>
47
+ </tr>
48
+ </thead>
49
+ <tfoot>
50
+ <tr>
51
+ <th scope="col" class="w3tc_extensions_manage_column_check"><label class="screen-reader-text" for="cb-select-all-2"><?php _e( 'Select All', 'w3-total-cache' )?></label><input id="cb-select-all-2" type="checkbox" class="w3tc_extensions_manage_input_checkall"></th><th scope="col" class="manage-column column-name" style=""><?php _e( 'Extension', 'w3-total-cache' )?></th><th scope="col" class="manage-column column-description" style=""><?php _e( 'Description', 'w3-total-cache' )?></th>
52
+ </tr>
53
+ </tfoot>
54
+ <tbody id="the-list">
55
+ <?php
56
  $cb_id = 0;
57
  foreach ( $extension_keys as $extension ):
58
+ $meta = $extensions[$extension];
59
  $meta = $this->default_meta( $meta );
60
  $cb_id++;
61
  ?>
62
+ <?php do_action( "w3tc_extension_before_row-{$extension}" ) ?>
63
+ <tr id="<?php echo esc_attr( $extension )?>" class="<?php echo $config->is_extension_active( $extension ) ? 'active' : 'inactive'?>">
64
+ <th scope="row" class="check-column">
65
+ <label class="screen-reader-text" for="checkbox_<?php echo $cb_id?>"><?php printf( __( 'Select %s' ), $meta['name'] ) ?></label>
66
+ <input type="checkbox" name="checked[]" value="<?php echo esc_attr( $extension ) ?>" id="checkbox_<?php echo $cb_id?>" class="w3tc_extensions_input_active" <?php disabled( !$meta['enabled'] )?>>
67
+ </th>
68
+ <td class="plugin-title">
69
+ <strong><?php esc_html_e( $meta['name'] ) ?></strong>
70
+ <div class="row-actions-visible">
71
+ <?php if ( $config->is_extension_active( $extension ) ):
72
+ $extra_links = array();
73
+ if ( isset( $meta['settings_exists'] ) && $meta['settings_exists'] )
74
  $extra_links[] = '<a class="edit" href="' . esc_attr( Util_Ui::admin_url( sprintf( 'admin.php?page=w3tc_extensions&extension=%s', $extension ) ) ).'&action=view">'. __( 'Settings' ).'</a>';
75
  $extra_links = apply_filters( "w3tc_extension_plugin_links_{$extension}", $extra_links );
76
  $links = implode( ' | ', $extra_links );
78
  echo $links;
79
  }
80
  ?>
81
+ <span class="0">
82
+ </span>
83
 
84
+ <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
85
+ <?php if ( $links ) echo ' | '; ?>
86
+ <span class="deactivate">
87
+ <a href="<?php esc_attr_e( wp_nonce_url( Util_Ui::admin_url( sprintf( 'admin.php?page=w3tc_extensions&action=deactivate&extension=%s&amp;extension_status=%s&amp;paged=%d', $extension, $extension_status, $page ) ), 'w3tc' ) ) ?>" title="<?php esc_attr_e( 'Deactivate this extension', 'w3-total-cache' ) ?> ">
88
+ <?php _e( 'Deactivate' ) ?>
89
+ </a>
90
+ </span>
91
+ <?php endif ?>
92
+ <?php else: ?>
93
+ <span class="activate">
94
+ <?php if ( $meta['enabled'] ): ?>
95
+ <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
96
+ <a href="<?php esc_attr_e( wp_nonce_url( Util_Ui::admin_url( sprintf( 'admin.php?page=w3tc_extensions&action=activate&extension=%s&amp;extension_status=%s&amp;paged=%d', $extension, $extension_status, $page ) ), 'w3tc' ) ) ?>" title="<?php esc_attr_e( 'Activate this extension', 'w3-total-cache' ) ?> ">
97
+ <?php _e( 'Activate' ) ?>
98
+ </a>
99
+ <?php endif ?>
100
+ <?php else: ?>
101
+ <?php if ( !empty( $meta['disabled_message'] ) ): ?>
102
+ <?php echo $meta['disabled_message'] ?>
103
+ <?php else: ?>
104
+ <?php _e( 'Disabled: see Requirements', 'w3-total-cache' ) ?>
105
+ <?php endif; ?>
106
+ <?php endif; ?>
107
+ </span>
108
+ <?php endif ?>
109
 
110
+ </div>
111
+ </td>
112
+ <td class="column-description desc">
113
+ <div class="plugin-description">
114
+ <p>
115
+ <?php if ( isset( $meta['pro_feature'] ) && $meta['pro_feature'] ): ?>
116
+ <?php Util_Ui::pro_wrap_maybe_start() ?>
117
+ <?php endif ?>
118
+
119
+ <?php _e( $meta['description'] ) ?>
120
+
121
+ <?php if ( isset( $meta['pro_feature'] ) && $meta['pro_feature'] ): ?>
122
+ <?php Util_Ui::pro_wrap_maybe_end( "extension_$extension" ) ?>
123
+ <?php endif ?>
124
+
125
+ <?php if ( !empty( $meta['requirements'] ) ): ?>
126
+ <br />
127
+ <span class="description"><?php printf( __( 'Requirements: %s', 'w3-total-cache' ), apply_filters( "w3tc_extension_requirements-{$extension}", $meta['requirements'] ) ) ?></span>
128
+ <?php do_action( "w3tc_extension_requirements-{$extension}" ) ?>
129
+ <?php endif ?>
130
+ </p>
131
+ </div>
132
+
133
+ <div class="<?php echo $config->is_extension_active( $extension ) ? 'active' : 'inactive'?> second plugin-version-author-uri">
134
+ <?php printf( __( 'Version %s', 'w3-total-cache' ), $meta['version'] )?>
135
+ |
136
+ <?php printf( __( 'By %s', 'w3-total-cache' ),
137
  sprintf( '<a href="%s" title="' . __( 'Visit author homepage' ) .
138
  '">%s</a>', $meta['author_uri'], $meta['author'] ) ) ?>
139
+ |
140
+ <a href="<?php esc_attr_e( $meta['extension_uri'] ) ?>"
141
+ title="<?php esc_attr_e( 'Visit extension site', 'w3-total-cache' ) ?>"><?php
142
  _e( 'Visit extension site', 'w3-total-cache' )?></a>
143
+ </div>
144
+ </td>
145
+ </tr>
146
+ <?php do_action( "w3tc_extension_after_row", $extension ) ?>
147
+ <?php do_action( "w3tc_extension_after_row-{$extension}" ) ?>
148
+ <?php endforeach ?>
149
+ </tbody>
150
  </table>
151
  <div class="tablenav bottom">
152
 
153
+ <?php if ( !$config->is_sealed( 'extensions.active' ) ): ?>
154
+ <div class="alignleft actions">
155
+ <select name="action2">
156
+ <option value="-1" selected="selected"><?php _e( 'Bulk Actions', 'w3-total-cache' )?></option>
157
+ <option value="activate-selected"><?php _e( 'Activate', 'w3-total-cache' )?></option>
158
+ <option value="deactivate-selected"><?php _e( 'Deactivate', 'w3-total-cache' )?></option>
159
+ </select>
160
+ <input type="submit" name="" id="doaction" class="w3tc-button-save button action" value="<?php esc_attr_e( 'Apply' )?>">
161
+ </div>
162
+ <?php endif ?>
163
 
164
+ <div class="tablenav-pages one-page">
165
+ <span class="displaying-num"><?php printf( translate_nooped_plural( _n_noop( '%s extension', '%s extensions' ), sizeof( $extensions ), 'w3-total-cache' ), sizeof( $extensions ) ); ?></span>
166
+ </div>
167
+ <br class="clear">
168
  </div>
169
 
170
  <?php if ( is_network_admin() ): ?>
171
+ <?php Util_Ui::button_config_save( 'extensions' ); ?>
172
  <?php endif ?>
inc/options/minify/ccjs2.php CHANGED
@@ -10,37 +10,63 @@ $compilation_levels = array(
10
  'ADVANCED_OPTIMIZATIONS' => __( 'Advanced optimizations', 'w3-total-cache' )
11
  );
12
 
13
- $compilation_level = $this->_config->get_string( 'minify.ccjs.options.compilation_level' );
 
 
14
  ?>
15
  <tr>
16
- <th><label for="minify_ccjs_path_java"><?php Util_Ui::e_config_label( 'minify.ccjs.path.java' ) ?></label></th>
17
- <td>
18
- <input id="minify_ccjs_path_java" class="js_enabled" type="text"
19
- <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__ccjs__path__java" value="<?php echo esc_attr( $this->_config->get_string( 'minify.ccjs.path.java' ) ); ?>" size="60" />
20
- </td>
 
 
 
 
 
 
 
21
  </tr>
22
  <tr>
23
- <th><label for="minify_ccjs_path_jar"><?php Util_Ui::e_config_label( 'minify.ccjs.path.jar' ) ?></label></th>
24
- <td>
25
- <input id="minify_ccjs_path_jar" class="js_enabled" type="text"
26
- <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__ccjs__path__jar" value="<?php echo esc_attr( $this->_config->get_string( 'minify.ccjs.path.jar' ) ); ?>" size="60" />
27
- </td>
 
 
 
 
 
 
 
28
  </tr>
29
  <tr>
30
- <th>&nbsp;</th>
31
- <td>
32
- <input class="minifier_test js_enabled button {type: 'ccjs', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Test Closure Compiler', 'w3-total-cache' ); ?>" />
33
- <span class="minifier_test_status w3tc-status w3tc-process"></span>
34
- </td>
 
 
35
  </tr>
36
  <tr>
37
- <th><label for="minify_ccjs_options_compilation_level"><?php Util_Ui::e_config_label( 'minify.ccjs.options.compilation_level' ) ?></label></th>
38
- <td>
39
- <select id="minify_ccjs_options_compilation_level" class="js_enabled" name="minify__ccjs__options__compilation_level"
40
- <?php Util_Ui::sealing_disabled( 'minify.' ) ?>>
41
- <?php foreach ( $compilation_levels as $compilation_level_key => $compilation_level_name ): ?>
42
- <option value="<?php echo esc_attr( $compilation_level_key ); ?>" <?php selected( $compilation_level, $compilation_level_key ); ?>><?php echo $compilation_level_name; ?></option>
43
- <?php endforeach; ?>
44
- </select>
45
- </td>
 
 
 
 
 
 
 
 
46
  </tr>
10
  'ADVANCED_OPTIMIZATIONS' => __( 'Advanced optimizations', 'w3-total-cache' )
11
  );
12
 
13
+ $c = $this->_config;
14
+ $compilation_level = $c->get_string( 'minify.ccjs.options.compilation_level' );
15
+
16
  ?>
17
  <tr>
18
+ <th>
19
+ <label for="minify__ccjs__path__java">
20
+ <?php Util_Ui::e_config_label( 'minify.ccjs.path.java' ) ?>
21
+ </label>
22
+ </th>
23
+ <td>
24
+ <input id="minify__ccjs__path__java" class="js_enabled" type="text"
25
+ <?php Util_Ui::sealing_disabled( 'minify.' ) ?>
26
+ name="minify__ccjs__path__java"
27
+ value="<?php echo esc_attr( $c->get_string( 'minify.ccjs.path.java' ) ) ?>"
28
+ size="60" />
29
+ </td>
30
  </tr>
31
  <tr>
32
+ <th>
33
+ <label for="minify__ccjs__path__jar">
34
+ <?php Util_Ui::e_config_label( 'minify.ccjs.path.jar' ) ?>
35
+ </label>
36
+ </th>
37
+ <td>
38
+ <input id="minify__ccjs__path__jar" class="js_enabled" type="text"
39
+ <?php Util_Ui::sealing_disabled( 'minify.' ) ?>
40
+ name="minify__ccjs__path__jar"
41
+ value="<?php echo esc_attr( $c->get_string( 'minify.ccjs.path.jar' ) ) ?>"
42
+ size="60" />
43
+ </td>
44
  </tr>
45
  <tr>
46
+ <th>&nbsp;</th>
47
+ <td>
48
+ <input class="minifier_test js_enabled button {type: 'ccjs', nonce: '<?php echo wp_create_nonce( 'w3tc' ) ?>'}"
49
+ type="button"
50
+ value="<?php _e( 'Test Closure Compiler', 'w3-total-cache' ) ?>" />
51
+ <span class="minifier_test_status w3tc-status w3tc-process"></span>
52
+ </td>
53
  </tr>
54
  <tr>
55
+ <th>
56
+ <label for="minify_ccjs_options_compilation_level">
57
+ <?php Util_Ui::e_config_label( 'minify.ccjs.options.compilation_level' ) ?>
58
+ </label>
59
+ </th>
60
+ <td>
61
+ <select id="minify_ccjs_options_compilation_level" class="js_enabled"
62
+ name="minify__ccjs__options__compilation_level"
63
+ <?php Util_Ui::sealing_disabled( 'minify.' ) ?>>
64
+ <?php foreach ( $compilation_levels as $compilation_level_key => $compilation_level_name ): ?>
65
+ <option value="<?php echo esc_attr( $compilation_level_key ); ?>"
66
+ <?php selected( $compilation_level, $compilation_level_key ) ?>>
67
+ <?php echo $compilation_level_name; ?>
68
+ </option>
69
+ <?php endforeach ?>
70
+ </select>
71
+ </td>
72
  </tr>
inc/options/minify/css.php CHANGED
@@ -9,9 +9,8 @@ $is_pro = Util_Environment::is_w3tc_pro( $this->_config );
9
  ?>
10
  <?php $this->checkbox( 'minify.css.strip.comments', false, 'css_' ) ?> <?php Util_Ui::e_config_label( 'minify.css.strip.comments' ) ?></label><br />
11
  <?php $this->checkbox( 'minify.css.strip.crlf', false, 'css_' ) ?> <?php Util_Ui::e_config_label( 'minify.css.strip.crlf' ) ?></label><br />
 
 
12
  <?php $this->checkbox( 'minify.css.embed', !$is_pro, 'csse_', true, ( $is_pro ? null : false ) ) ?> Eliminate render-blocking <acronym title="Cascading Style Sheet">CSS</acronym> by moving it to <acronym title="Hypertext Markup Language">HTTP</acronym> body</label>
13
- <?php
14
- if ( !$is_pro )
15
- echo ' (Available after <a href="#" class="button-buy-plugin" data-src="minify_css_renderblocking">upgrade</a>)';
16
- ?>
17
  <br />
9
  ?>
10
  <?php $this->checkbox( 'minify.css.strip.comments', false, 'css_' ) ?> <?php Util_Ui::e_config_label( 'minify.css.strip.comments' ) ?></label><br />
11
  <?php $this->checkbox( 'minify.css.strip.crlf', false, 'css_' ) ?> <?php Util_Ui::e_config_label( 'minify.css.strip.crlf' ) ?></label><br />
12
+
13
+ <?php Util_Ui::pro_wrap_maybe_start() ?>
14
  <?php $this->checkbox( 'minify.css.embed', !$is_pro, 'csse_', true, ( $is_pro ? null : false ) ) ?> Eliminate render-blocking <acronym title="Cascading Style Sheet">CSS</acronym> by moving it to <acronym title="Hypertext Markup Language">HTTP</acronym> body</label>
15
+ <?php Util_Ui::pro_wrap_maybe_end('minify_css_renderblocking') ?>
 
 
 
16
  <br />
inc/options/minify/yuicss2.php CHANGED
@@ -4,29 +4,53 @@ namespace W3TC;
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
 
 
7
  ?>
8
  <tr>
9
- <th><label for="minify__yuicss__path__java"><?php Util_Ui::e_config_label( 'minify.yuicss.path.java' ) ?></label></th>
10
- <td>
11
- <input class="css_enabled" id="minify__yuicss__path__java" type="text"
12
- <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__yuicss__path__java" value="<?php echo esc_attr( $this->_config->get_string( 'minify.yuicss.path.java' ) ); ?>" size="100" /></td>
 
 
 
 
 
 
 
13
  </tr>
14
  <tr>
15
- <th><label for="minify__yuicss__path__jar"><?php Util_Ui::e_config_label( 'minify.yuicss.path.jar' ) ?></label></th>
16
- <td>
17
- <input class="css_enabled" id="minify__yuicss__path__jar" type="text"
18
- <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__yuicss__path__jar" value="<?php echo esc_attr( $this->_config->get_string( 'minify.yuicss.path.jar' ) ); ?>" size="100" /></td>
 
 
 
 
19
  </tr>
20
  <tr>
21
- <th>&nbsp;</th>
22
- <td>
23
- <input class="minifier_test button css_enabled {type: 'yuicss', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Test YUI Compressor', 'w3-total-cache' ); ?>" />
24
- <span class="minifier_test_status w3tc-status w3tc-process"></span>
25
- </td>
 
26
  </tr>
27
  <tr>
28
- <th><label for="minify_yuicss_options_line-break"><?php Util_Ui::e_config_label( 'minify.yuicss.options.line-break' ) ?></label></th>
29
- <td>
30
- <input class="css_enabled" id="minify_yuicss_options_line-break"
31
- <?php Util_Ui::sealing_disabled( 'minify.' ) ?> type="text" name="minify__yuicss__options__line-break" value="<?php echo esc_attr( $this->_config->get_integer( 'minify.yuicss.options.line-break' ) ); ?>" size="8" style="text-align: right;" /> symbols (set to 0 to disable)</td>
 
 
 
 
 
 
 
 
 
 
32
  </tr>
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
+ $c = $this->_config;
8
+
9
  ?>
10
  <tr>
11
+ <th>
12
+ <label for="minify__yuicss__path__java">
13
+ <?php Util_Ui::e_config_label( 'minify.yuicss.path.java' ) ?>
14
+ </label>
15
+ </th>
16
+ <td>
17
+ <input class="css_enabled" id="minify__yuicss__path__java" type="text"
18
+ <?php Util_Ui::sealing_disabled( 'minify.' ) ?>
19
+ name="minify__yuicss__path__java" value="<?php echo esc_attr( $c->get_string( 'minify.yuicss.path.java' ) ) ?>"
20
+ size="100" />
21
+ </td>
22
  </tr>
23
  <tr>
24
+ <th><label for="minify__yuicss__path__jar"><?php Util_Ui::e_config_label( 'minify.yuicss.path.jar' ) ?></label></th>
25
+ <td>
26
+ <input class="css_enabled" id="minify__yuicss__path__jar" type="text"
27
+ <?php Util_Ui::sealing_disabled( 'minify.' ) ?>
28
+ name="minify__yuicss__path__jar"
29
+ value="<?php echo esc_attr( $c->get_string( 'minify.yuicss.path.jar' ) ) ?>"
30
+ size="100" />
31
+ </td>
32
  </tr>
33
  <tr>
34
+ <th>&nbsp;</th>
35
+ <td>
36
+ <input class="minifier_test button css_enabled {type: 'yuicss', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"
37
+ type="button" value="<?php _e( 'Test YUI Compressor', 'w3-total-cache' ) ?>" />
38
+ <span class="minifier_test_status w3tc-status w3tc-process"></span>
39
+ </td>
40
  </tr>
41
  <tr>
42
+ <th>
43
+ <label for="minify_yuicss_options_line-break">
44
+ <?php Util_Ui::e_config_label( 'minify.yuicss.options.line-break' ) ?>
45
+ </label>
46
+ </th>
47
+ <td>
48
+ <input class="css_enabled" id="minify_yuicss_options_line-break"
49
+ <?php Util_Ui::sealing_disabled( 'minify.' ) ?>
50
+ type="text"
51
+ name="minify__yuicss__options__line-break"
52
+ value="<?php echo esc_attr( $c->get_integer( 'minify.yuicss.options.line-break' ) ) ?>"
53
+ size="8" style="text-align: right" />
54
+ symbols (set to 0 to disable)
55
+ </td>
56
  </tr>
inc/options/parts/memcached.php CHANGED
@@ -45,6 +45,13 @@ else
45
  </span>
46
  </td>
47
  </tr>
 
 
 
 
 
 
 
48
 
49
  <tr>
50
  <th><label for="memcached_username"><?php echo Util_ConfigLabel::get( 'memcached.username' ) ?></label></th>
45
  </span>
46
  </td>
47
  </tr>
48
+ <tr>
49
+ <th><label><?php _e( 'Use binary protocol:', 'w3-total-cache' ); ?></label></th>
50
+ <td>
51
+ <?php $this->checkbox( $module . '.memcached.binary_protocol' ) ?> <?php echo Util_ConfigLabel::get( 'memcached.binary_protocol' ) ?></label><br />
52
+ <span class="description"><?php _e( 'Using binary protocol can increase throughput.', 'w3-total-cache' ); ?></span>
53
+ </td>
54
+ </tr>
55
 
56
  <tr>
57
  <th><label for="memcached_username"><?php echo Util_ConfigLabel::get( 'memcached.username' ) ?></label></th>
inc/options/pgcache.php CHANGED
@@ -260,8 +260,7 @@ Util_Ui::postbox_header( __( 'Purge Policy: ', 'w3-total-cache' ) . implode( ',
260
  'cache' => array(
261
  'label' => "Cache",
262
  'disabled' => !Util_Environment::is_w3tc_pro( $this->_config ),
263
- 'postfix' => ( Util_Environment::is_w3tc_pro( $this->_config ) ? '' :
264
- '&nbsp;&nbsp;&nbsp;(<a href="#" class="button-buy-plugin" data-src="pagecache_rest">Upgrade</a> now to enable)')
265
  ),
266
  'disable' => 'Disable <acronym title="REpresentational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym>',
267
  ),
260
  'cache' => array(
261
  'label' => "Cache",
262
  'disabled' => !Util_Environment::is_w3tc_pro( $this->_config ),
263
+ 'pro_feature' => true
 
264
  ),
265
  'disable' => 'Disable <acronym title="REpresentational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym>',
266
  ),
lib/Minify/Minify/HTML.php CHANGED
@@ -343,12 +343,32 @@ class Minify_HTML {
343
  }
344
 
345
  protected function _removeAttributeQuotes($m) {
346
- $m[2] = preg_replace( '/([a-z0-9]=)\'([^"\'\\s=]+)\'(\\s(?!\\/)|>)/i', '$1$2$3', $m[2] );
347
- $m[2] = preg_replace( '/([a-z0-9]=)"([^"\'\\s=]+)"(\\s(?!\\/)|>)/i', '$1$2$3', $m[2] );
348
- $m[2] = preg_replace( '/([a-z0-9]=)\'([^\'\\s=]+)\'\\//i', '$1$2 /', $m[2] );
349
- $m[2] = preg_replace( '/([a-z0-9]=)"([^"\\s=]+)"\\//i', '$1$2 /', $m[2] );
350
- $m[2] = preg_replace( '/([a-z0-9])=\'\'/i', '$1', $m[2] );
351
- $m[2] = preg_replace( '/([a-z0-9])=""/i', '$1', $m[2] );
352
  return $m[1] . $m[2];
353
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  }
343
  }
344
 
345
  protected function _removeAttributeQuotes($m) {
346
+ $m[2] = preg_replace_callback( '~([a-z0-9\\-])=(?<quote>[\'"])([^"\'\\s=]*)\k<quote>(\\s|>|/>)~i',
347
+ array( $this, '_removeAttributeQuotesCallback'), $m[2] );
348
+
 
 
 
349
  return $m[1] . $m[2];
350
  }
351
+
352
+
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
+
360
+ // 1. <a href=bla/>hi</a> is sometimes (XHTML? HTML5 specs doesnt allow that)
361
+ // parsed as <a href=bla></a>hi</a> by browsers
362
+ // avoid that by turning it to <a href=bla/ >hi</a>
363
+
364
+ // 2. auto-closing tags without space at the end e.g. <div data-value="aa"/>
365
+ // should have space after value <div data-value=aa />
366
+ // otherwise some browsers assume data-value="aa/"
367
+ if ( /* 1 */ $m[4] == '/>' ||
368
+ /* 2 */ ( $m[4] == '>' && substr( $m[3], -1, 1 ) == '/' ) ) {
369
+ return $m[1] . '=' . $m[3] . ' ' . $m[4];
370
+ }
371
+
372
+ return $m[1] . '=' . $m[3] . $m[4];
373
+ }
374
  }
lib/Minify/Minify/Lines.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /**
3
- * Class Minify_Lines
4
  * @package Minify
5
  */
6
 
@@ -11,131 +11,199 @@
11
  * @author Stephen Clay <steve@mrclay.org>
12
  * @author Adam Pedersen (Issue 55 fix)
13
  */
14
- class Minify_Lines {
15
-
16
- /**
17
- * Add line numbers in C-style comments
18
- *
19
- * This uses a very basic parser easily fooled by comment tokens inside
20
- * strings or regexes, but, otherwise, generally clean code will not be
21
- * mangled. URI rewriting can also be performed.
22
- *
23
- * @param string $content
24
- *
25
- * @param array $options available options:
26
- *
27
- * 'id': (optional) string to identify file. E.g. file name/path
28
- *
29
- * 'currentDir': (default null) if given, this is assumed to be the
30
- * directory of the current CSS file. Using this, minify will rewrite
31
- * all relative URIs in import/url declarations to correctly point to
32
- * the desired files, and prepend a comment with debugging information about
33
- * this process.
34
- *
35
- * @return string
36
- */
37
- public static function minify($content, $options = array())
38
- {
39
- $id = (isset($options['id']) && $options['id'])
40
- ? $options['id']
41
- : '';
42
- $content = str_replace("\r\n", "\n", $content);
43
-
44
- // Hackily rewrite strings with XPath expressions that are
45
- // likely to throw off our dumb parser (for Prototype 1.6.1).
46
- $content = str_replace('"/*"', '"/"+"*"', $content);
47
- $content = preg_replace('@([\'"])(\\.?//?)\\*@', '$1$2$1+$1*', $content);
48
-
49
- $lines = explode("\n", $content);
50
- $numLines = count($lines);
51
- // determine left padding
52
- $padTo = strlen((string) $numLines); // e.g. 103 lines = 3 digits
53
- $inComment = false;
54
- $i = 0;
55
- $newLines = array();
56
- while (null !== ($line = array_shift($lines))) {
57
- if (('' !== $id) && (0 == $i % 50)) {
58
- if ($inComment) {
59
- array_push($newLines, '', "/* {$id} *|", '');
60
- } else {
61
- array_push($newLines, '', "/* {$id} */", '');
62
- }
63
- }
64
- ++$i;
65
- $newLines[] = self::_addNote($line, $i, $inComment, $padTo);
66
- $inComment = self::_eolInComment($line, $inComment);
67
- }
68
- $content = implode("\n", $newLines) . "\n";
69
-
70
- // check for desired URI rewriting
71
- if (isset($options['currentDir'])) {
72
- Minify_CSS_UriRewriter::$debugText = '';
73
- $content = Minify_CSS_UriRewriter::rewrite(
74
- $content
75
- ,$options
76
- );
77
- $content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
78
- . Minify_CSS_UriRewriter::$debugText . "*/\n"
79
- . $content;
80
- }
81
-
82
- return $content;
83
- }
84
-
85
- /**
86
- * Is the parser within a C-style comment at the end of this line?
87
- *
88
- * @param string $line current line of code
89
- *
90
- * @param bool $inComment was the parser in a comment at the
91
- * beginning of the line?
92
- *
93
- * @return bool
94
- */
95
- private static function _eolInComment($line, $inComment)
96
- {
97
- // crude way to avoid things like // */
98
- $line = preg_replace('~//.*?(\\*/|/\\*).*~', '', $line);
99
-
100
- while (strlen($line)) {
101
- $search = $inComment
102
- ? '*/'
103
- : '/*';
104
- $pos = strpos($line, $search);
105
- if (false === $pos) {
106
- return $inComment;
107
- } else {
108
- if ($pos == 0
109
- || ($inComment
110
- ? substr($line, $pos, 3)
111
- : substr($line, $pos-1, 3)) != '*/*')
112
- {
113
- $inComment = ! $inComment;
114
- }
115
- $line = substr($line, $pos + 2);
116
- }
117
- }
118
- return $inComment;
119
- }
120
-
121
- /**
122
- * Prepend a comment (or note) to the given line
123
- *
124
- * @param string $line current line of code
125
- *
126
- * @param string $note content of note/comment
127
- *
128
- * @param bool $inComment was the parser in a comment at the
129
- * beginning of the line?
130
- *
131
- * @param int $padTo minimum width of comment
132
- *
133
- * @return string
134
- */
135
- private static function _addNote($line, $note, $inComment, $padTo)
136
- {
137
- return $inComment
138
- ? '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line
139
- : '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line;
140
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  }
1
  <?php
2
  /**
3
+ * Class Minify_Lines
4
  * @package Minify
5
  */
6
 
11
  * @author Stephen Clay <steve@mrclay.org>
12
  * @author Adam Pedersen (Issue 55 fix)
13
  */
14
+ class Minify_Lines
15
+ {
16
+
17
+ /**
18
+ * Add line numbers in C-style comments
19
+ *
20
+ * This uses a very basic parser easily fooled by comment tokens inside
21
+ * strings or regexes, but, otherwise, generally clean code will not be
22
+ * mangled. URI rewriting can also be performed.
23
+ *
24
+ * @param string $content
25
+ *
26
+ * @param array $options available options:
27
+ *
28
+ * 'id': (optional) string to identify file. E.g. file name/path
29
+ *
30
+ * 'currentDir': (default null) if given, this is assumed to be the
31
+ * directory of the current CSS file. Using this, minify will rewrite
32
+ * all relative URIs in import/url declarations to correctly point to
33
+ * the desired files, and prepend a comment with debugging information about
34
+ * this process.
35
+ *
36
+ * @return string
37
+ */
38
+ public static function minify($content, $options = array())
39
+ {
40
+ $id = (isset($options['id']) && $options['id']) ? $options['id'] : '';
41
+ $content = str_replace("\r\n", "\n", $content);
42
+
43
+ $lines = explode("\n", $content);
44
+ $numLines = count($lines);
45
+ // determine left padding
46
+ $padTo = strlen((string) $numLines); // e.g. 103 lines = 3 digits
47
+ $inComment = false;
48
+ $i = 0;
49
+ $newLines = array();
50
+
51
+ while (null !== ($line = array_shift($lines))) {
52
+ if (('' !== $id) && (0 === $i % 50)) {
53
+ if ($inComment) {
54
+ array_push($newLines, '', "/* {$id} *|", '');
55
+ } else {
56
+ array_push($newLines, '', "/* {$id} */", '');
57
+ }
58
+ }
59
+
60
+ ++$i;
61
+ $newLines[] = self::_addNote($line, $i, $inComment, $padTo);
62
+ $inComment = self::_eolInComment($line, $inComment);
63
+ }
64
+
65
+ $content = implode("\n", $newLines) . "\n";
66
+
67
+ // check for desired URI rewriting
68
+ if (isset($options['currentDir'])) {
69
+ Minify_CSS_UriRewriter::$debugText = '';
70
+ $docRoot = isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT'];
71
+ $symlinks = isset($options['symlinks']) ? $options['symlinks'] : array();
72
+
73
+ $content = Minify_CSS_UriRewriter::rewrite($content, $options['currentDir'], $docRoot, $symlinks);
74
+
75
+ $content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
76
+ . Minify_CSS_UriRewriter::$debugText . "*/\n"
77
+ . $content;
78
+ }
79
+
80
+ return $content;
81
+ }
82
+
83
+ /**
84
+ * Is the parser within a C-style comment at the end of this line?
85
+ *
86
+ * @param string $line current line of code
87
+ *
88
+ * @param bool $inComment was the parser in a C-style comment at the
89
+ * beginning of the previous line?
90
+ *
91
+ * @return bool
92
+ */
93
+ private static function _eolInComment($line, $inComment)
94
+ {
95
+ while (strlen($line)) {
96
+ if ($inComment) {
97
+ // only "*/" can end the comment
98
+ $index = self::_find($line, '*/');
99
+ if ($index === false) {
100
+ return true;
101
+ }
102
+
103
+ // stop comment and keep walking line
104
+ $inComment = false;
105
+ @$line = (string)substr($line, $index + 2);
106
+ continue;
107
+ }
108
+
109
+ // look for "//" and "/*"
110
+ $single = self::_find($line, '//');
111
+ $multi = self::_find($line, '/*');
112
+ if ($multi === false) {
113
+ return false;
114
+ }
115
+
116
+ if ($single === false || $multi < $single) {
117
+ // start comment and keep walking line
118
+ $inComment = true;
119
+ @$line = (string)substr($line, $multi + 2);
120
+ continue;
121
+ }
122
+
123
+ // a single-line comment preceeded it
124
+ return false;
125
+ }
126
+
127
+ return $inComment;
128
+ }
129
+
130
+ /**
131
+ * Prepend a comment (or note) to the given line
132
+ *
133
+ * @param string $line current line of code
134
+ *
135
+ * @param string $note content of note/comment
136
+ *
137
+ * @param bool $inComment was the parser in a comment at the
138
+ * beginning of the line?
139
+ *
140
+ * @param int $padTo minimum width of comment
141
+ *
142
+ * @return string
143
+ */
144
+ private static function _addNote($line, $note, $inComment, $padTo)
145
+ {
146
+ if ($inComment) {
147
+ $line = '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line;
148
+ } else {
149
+ $line = '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line;
150
+ }
151
+
152
+ return rtrim($line);
153
+ }
154
+
155
+ /**
156
+ * Find a token trying to avoid false positives
157
+ *
158
+ * @param string $str String containing the token
159
+ * @param string $token Token being checked
160
+ * @return bool
161
+ */
162
+ private static function _find($str, $token)
163
+ {
164
+ switch ($token) {
165
+ case '//':
166
+ $fakes = array(
167
+ '://' => 1,
168
+ '"//' => 1,
169
+ '\'//' => 1,
170
+ '".//' => 2,
171
+ '\'.//' => 2,
172
+ );
173
+ break;
174
+ case '/*':
175
+ $fakes = array(
176
+ '"/*' => 1,
177
+ '\'/*' => 1,
178
+ '"//*' => 2,
179
+ '\'//*' => 2,
180
+ '".//*' => 3,
181
+ '\'.//*' => 3,
182
+ '*/*' => 1,
183
+ '\\/*' => 1,
184
+ );
185
+ break;
186
+ default:
187
+ $fakes = array();
188
+ }
189
+
190
+ $index = strpos($str, $token);
191
+ $offset = 0;
192
+
193
+ while ($index !== false) {
194
+ foreach ($fakes as $fake => $skip) {
195
+ $check = substr($str, $index - $skip, strlen($fake));
196
+ if ($check === $fake) {
197
+ // move offset and scan again
198
+ $offset += $index + strlen($token);
199
+ $index = strpos($str, $token, $offset);
200
+ break;
201
+ }
202
+ }
203
+ // legitimate find
204
+ return $index;
205
+ }
206
+
207
+ return $index;
208
+ }
209
  }
pub/css/options.css CHANGED
@@ -469,3 +469,33 @@ th.w3tc_extensions_manage_column_check {
469
  .w3tcbc_qrf td code {
470
  white-space: nowrap;
471
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  .w3tcbc_qrf td code {
470
  white-space: nowrap;
471
  }
472
+
473
+ .w3tc-gopro {
474
+ background: #fbfbfb;
475
+ border-left: 4px solid #46b450;
476
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
477
+ padding: 5px;
478
+ grid-template-columns: 3fr 1fr;
479
+ display: grid;
480
+ grid-gap: 10px;
481
+ align-items: center;
482
+ }
483
+
484
+ /* For pro features in a table, ensure the checkboxes / etc remained aligned. */
485
+ .form-table .w3tc-gopro {
486
+ margin-left: -9px;
487
+ }
488
+
489
+ .button.w3tc-gopro-button {
490
+ border-color: darkgreen;
491
+ box-shadow: 0 1px 0 darkgreen;
492
+ background: green;
493
+ color: #fff;
494
+ }
495
+ .button.w3tc-gopro-button:hover,
496
+ .button.w3tc-gopro-button:focus {
497
+ border-color: green;
498
+ box-shadow: 0 1px 0 green;
499
+ background: #009900;
500
+ color: #fff;
501
+ }
pub/js/lazyload.min.js ADDED
@@ -0,0 +1 @@
 
1
+ function _toConsumableArray(t){return _arrayWithoutHoles(t)||_iterableToArray(t)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function _iterableToArray(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}function _arrayWithoutHoles(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}function _extends(){return(_extends=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t}).apply(this,arguments)}function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(t,e){"object"===("undefined"==typeof exports?"undefined":_typeof(exports))&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.LazyLoad=e()}(this,function(){"use strict";var t="undefined"!=typeof window,e=t&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),n=t&&"IntersectionObserver"in window,r=t&&"classList"in document.createElement("p"),o={elements_selector:"img",container:e||t?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",class_loading:"loading",class_loaded:"loaded",class_error:"error",load_delay:0,auto_unobserve:!0,callback_enter:null,callback_exit:null,callback_reveal:null,callback_loaded:null,callback_error:null,callback_finish:null,use_native:!1},a=function(t,e){var n,r=new t(e);try{n=new CustomEvent("LazyLoad::Initialized",{detail:{instance:r}})}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent("LazyLoad::Initialized",!1,!1,{instance:r})}window.dispatchEvent(n)};var i=function(t,e){return t.getAttribute("data-"+e)},s=function(t,e,n){var r="data-"+e;null!==n?t.setAttribute(r,n):t.removeAttribute(r)},c=function(t){return"true"===i(t,"was-processed")},l=function(t,e){return s(t,"ll-timeout",e)},u=function(t){return i(t,"ll-timeout")},f=function(t,e){t&&t(e)},d=function(t,e){t._loadingCount+=e,0===t._elements.length&&0===t._loadingCount&&f(t._settings.callback_finish)},_=function(t){for(var e,n=[],r=0;e=t.children[r];r+=1)"SOURCE"===e.tagName&&n.push(e);return n},v=function(t,e,n){n&&t.setAttribute(e,n)},b=function(t,e){v(t,"sizes",i(t,e.data_sizes)),v(t,"srcset",i(t,e.data_srcset)),v(t,"src",i(t,e.data_src))},m={IMG:function(t,e){var n=t.parentNode;n&&"PICTURE"===n.tagName&&_(n).forEach(function(t){b(t,e)});b(t,e)},IFRAME:function(t,e){v(t,"src",i(t,e.data_src))},VIDEO:function(t,e){_(t).forEach(function(t){v(t,"src",i(t,e.data_src))}),v(t,"src",i(t,e.data_src)),t.load()}},g=function(t,e){var n,r,o=e._settings,a=t.tagName,s=m[a];if(s)return s(t,o),d(e,1),void(e._elements=(n=e._elements,r=t,n.filter(function(t){return t!==r})));!function(t,e){var n=i(t,e.data_src),r=i(t,e.data_bg);n&&(t.style.backgroundImage='url("'.concat(n,'")')),r&&(t.style.backgroundImage=r)}(t,o)},y=function(t,e){r?t.classList.add(e):t.className+=(t.className?" ":"")+e},h=function(t,e){r?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")},p=function(t,e,n){t.addEventListener(e,n)},E=function(t,e,n){t.removeEventListener(e,n)},w=function(t,e,n){E(t,"load",e),E(t,"loadeddata",e),E(t,"error",n)},A=function(t,e,n){var r=n._settings,o=e?r.class_loaded:r.class_error,a=e?r.callback_loaded:r.callback_error,i=t.target;h(i,r.class_loading),y(i,o),f(a,i),d(n,-1)},I=function(t,e){var n=function n(o){A(o,!0,e),w(t,n,r)},r=function r(o){A(o,!1,e),w(t,n,r)};!function(t,e,n){p(t,"load",e),p(t,"loadeddata",e),p(t,"error",n)}(t,n,r)},k=["IMG","IFRAME","VIDEO"],L=function(t,e){var n=e._observer;S(t,e),n&&e._settings.auto_unobserve&&n.unobserve(t)},O=function(t){var e=u(t);e&&(clearTimeout(e),l(t,null))},x=function(t,e){var n=e._settings.load_delay,r=u(t);r||(r=setTimeout(function(){L(t,e),O(t)},n),l(t,r))},S=function(t,e,n){var r=e._settings;!n&&c(t)||(k.indexOf(t.tagName)>-1&&(I(t,e),y(t,r.class_loading)),g(t,e),function(t){s(t,"was-processed","true")}(t),f(r.callback_reveal,t),f(r.callback_set,t))},z=function(t){return!!n&&(t._observer=new IntersectionObserver(function(e){e.forEach(function(e){return function(t){return t.isIntersecting||t.intersectionRatio>0}(e)?function(t,e){var n=e._settings;f(n.callback_enter,t),n.load_delay?x(t,e):L(t,e)}(e.target,t):function(t,e){var n=e._settings;f(n.callback_exit,t),n.load_delay&&O(t)}(e.target,t)})},{root:(e=t._settings).container===document?null:e.container,rootMargin:e.thresholds||e.threshold+"px"}),!0);var e},C=["IMG","IFRAME"],N=function(t,e){return function(t){return t.filter(function(t){return!c(t)})}((n=t||function(t){return t.container.querySelectorAll(t.elements_selector)}(e),Array.prototype.slice.call(n)));var n},M=function(t){var e=t._settings;_toConsumableArray(e.container.querySelectorAll("."+e.class_error)).forEach(function(t){h(t,e.class_error),function(t){s(t,"was-processed",null)}(t)}),t.update()},R=function(e,n){var r;this._settings=function(t){return _extends({},o,t)}(e),this._loadingCount=0,z(this),this.update(n),r=this,t&&window.addEventListener("online",function(t){M(r)})};return R.prototype={update:function(t){var n,r=this,o=this._settings;(this._elements=N(t,o),!e&&this._observer)?(function(t){return t.use_native&&"loading"in HTMLImageElement.prototype}(o)&&((n=this)._elements.forEach(function(t){-1!==C.indexOf(t.tagName)&&(t.setAttribute("loading","lazy"),S(t,n))}),this._elements=N(t,o)),this._elements.forEach(function(t){r._observer.observe(t)})):this.loadAll()},destroy:function(){var t=this;this._observer&&(this._elements.forEach(function(e){t._observer.unobserve(e)}),this._observer=null),this._elements=null,this._settings=null},load:function(t,e){S(t,this,e)},loadAll:function(){var t=this;this._elements.forEach(function(e){L(e,t)})}},t&&function(t,e){if(e)if(e.length)for(var n,r=0;n=e[r];r+=1)a(t,n);else a(t,e)}(R,window.lazyLoadOptions),R});
pub/js/lazyload.version.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ lazyload version 12.2.0
2
+ author
3
+ https://www.andreaverlicchi.eu/lazyload/
4
+ https://github.com/verlok/lazyload
pub/js/lightbox.js CHANGED
@@ -16,7 +16,7 @@ var W3tc_Lightbox = {
16
  display: 'none'
17
  });
18
 
19
- jQuery('#w3tc').append(this.container);
20
  me.resize();
21
  this.window.resize(function() {
22
  me.resize();
@@ -382,14 +382,23 @@ function w3tc_lightbox_self_test(nonce) {
382
  });
383
  }
384
 
385
- function w3tc_lightbox_upgrade(nonce, data_src) {
386
- W3tc_Lightbox.open({
387
- id: 'w3tc-overlay',
388
- close: '',
389
- width: 800,
390
- height: 350,
391
- url: 'admin.php?page=w3tc_dashboard&w3tc_licensing_upgrade&_wpnonce=' +
392
- encodeURIComponent(nonce) + '&data_src=' + encodeURIComponent(data_src),
 
 
 
 
 
 
 
 
 
393
  callback: function(lightbox) {
394
  lightbox.options.height = jQuery('#w3tc-upgrade').height() - 57;
395
  jQuery('.button-primary', lightbox.container).click(function() {
@@ -397,7 +406,7 @@ function w3tc_lightbox_upgrade(nonce, data_src) {
397
  });
398
  jQuery('#w3tc-purchase', lightbox.container).click(function() {
399
  lightbox.close();
400
- w3tc_lightbox_buy_plugin(nonce);
401
  });
402
  jQuery('#w3tc-purchase-link', lightbox.container).click(function() {
403
  lightbox.close();
@@ -411,13 +420,17 @@ function w3tc_lightbox_upgrade(nonce, data_src) {
411
  });
412
  }
413
 
414
- function w3tc_lightbox_buy_plugin(nonce) {
415
  W3tc_Lightbox.open({
416
  width: 800,
417
  minHeight: 350,
418
  maxWidth: jQuery(window).width() - 40,
419
  maxHeight: jQuery(window).height() - 40,
420
- url: 'admin.php?page=w3tc_dashboard&w3tc_licensing_buy_plugin&_wpnonce=' + nonce,
 
 
 
 
421
  callback: function(lightbox) {
422
  var w3tc_license_listener = function(event) {
423
  if (event.origin.substr(event.origin.length - 12) !== ".w3-edge.com")
@@ -486,7 +499,13 @@ jQuery(function() {
486
 
487
  jQuery('.button-buy-plugin').click(function() {
488
  var data_src = jQuery(this).attr('data-src');
489
- w3tc_lightbox_upgrade(w3tc_nonce, data_src);
 
 
 
 
 
 
490
  jQuery('#w3tc-license-instruction').show();
491
  return false;
492
  });
16
  display: 'none'
17
  });
18
 
19
+ jQuery('body').append(this.container);
20
  me.resize();
21
  this.window.resize(function() {
22
  me.resize();
382
  });
383
  }
384
 
385
+ function w3tc_lightbox_upgrade(nonce, data_src, renew_key) {
386
+ var client_id = '';
387
+ if (window.w3tc_ga) {
388
+ w3tc_ga(function(tracker) {
389
+ client_id = tracker.get('clientId');
390
+ });
391
+ }
392
+
393
+ W3tc_Lightbox.open({
394
+ id: 'w3tc-overlay',
395
+ close: '',
396
+ width: 800,
397
+ height: 350,
398
+ url: 'admin.php?page=w3tc_dashboard&w3tc_licensing_upgrade&_wpnonce=' +
399
+ encodeURIComponent(nonce) + '&data_src=' + encodeURIComponent(data_src) +
400
+ (renew_key ? '&renew_key=' + encodeURIComponent(renew_key) : '') +
401
+ (client_id ? '&client_id=' + encodeURIComponent(client_id) : ''),
402
  callback: function(lightbox) {
403
  lightbox.options.height = jQuery('#w3tc-upgrade').height() - 57;
404
  jQuery('.button-primary', lightbox.container).click(function() {
406
  });
407
  jQuery('#w3tc-purchase', lightbox.container).click(function() {
408
  lightbox.close();
409
+ w3tc_lightbox_buy_plugin(nonce, data_src, renew_key, client_id);
410
  });
411
  jQuery('#w3tc-purchase-link', lightbox.container).click(function() {
412
  lightbox.close();
420
  });
421
  }
422
 
423
+ function w3tc_lightbox_buy_plugin(nonce, data_src, renew_key, client_id) {
424
  W3tc_Lightbox.open({
425
  width: 800,
426
  minHeight: 350,
427
  maxWidth: jQuery(window).width() - 40,
428
  maxHeight: jQuery(window).height() - 40,
429
+ url: 'admin.php?page=w3tc_dashboard&w3tc_licensing_buy_plugin' +
430
+ '&_wpnonce=' + encodeURIComponent(nonce) +
431
+ '&data_src=' + encodeURIComponent(data_src) +
432
+ (renew_key ? '&renew_key=' + encodeURIComponent(renew_key) : '') +
433
+ (client_id ? '&client_id=' + encodeURIComponent(client_id) : ''),
434
  callback: function(lightbox) {
435
  var w3tc_license_listener = function(event) {
436
  if (event.origin.substr(event.origin.length - 12) !== ".w3-edge.com")
499
 
500
  jQuery('.button-buy-plugin').click(function() {
501
  var data_src = jQuery(this).attr('data-src');
502
+ var nonce = jQuery(this).attr('data-nonce');
503
+ if (!nonce) {
504
+ nonce = w3tc_nonce;
505
+ }
506
+ var renew_key = jQuery(this).attr('data-renew-key');
507
+
508
+ w3tc_lightbox_upgrade(nonce, data_src, renew_key);
509
  jQuery('#w3tc-license-instruction').show();
510
  return false;
511
  });
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Plugin Name ===
2
- Contributors: fredericktownes
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.10.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -271,6 +271,32 @@ Please reach out to all of these people and support their projects if you're so
271
 
272
  == Changelog ==
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  = 0.10.2 =
275
  * Fixed compatibility with wpdb::prepare in WordPress 5.3
276
 
1
  === Plugin Name ===
2
+ 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
 
272
  == Changelog ==
273
 
274
+ = 0.11.0 =
275
+ * Added recommendation for BoldGrid's Total Upkeep plugin
276
+ * Added new lazy loading feature
277
+ * Removed New Relic extension by default for new installations
278
+ * Updated usage of html minification and quote removal
279
+ * Improved memcached config and added optional binary protocol setting
280
+ * Improved process of renewing expired licenses
281
+ * Improved page cache purging
282
+ * Improved FAQ link by opening in new window
283
+ * Improved detection of detect_post_id
284
+ * Improved REST caching in relation to cache headers like X-WP-*
285
+ * Improved Vary User-Agent header usage
286
+ * Improved various features with AMP pages and HTTP2
287
+ * Improved redis connection string to allow for tls://host:port format
288
+ * Fixed file headers for Cloudfront S3 CDN
289
+ * Fixed fatal error on with flush / SNS
290
+ * Fixed comments with URLs within minify debug mode
291
+ * Fixed ObjectCache statistics within footer
292
+ * Fixed temporary hotfix with wp_die and regular output
293
+ * Fixed fragment cache header link
294
+ * Fixed flushing of /feed and /feed/ cache
295
+ * Fixed js error in widget
296
+ * Fixed fatal cache flush error caused by empty $wp_rewrite
297
+ * Fixed path for file_generic REST caching on non-default port
298
+ * Fixed test minify button with Closure Compiler engine
299
+
300
  = 0.10.2 =
301
  * Fixed compatibility with wpdb::prepare in WordPress 5.3
302
 
w3-total-cache-api.php CHANGED
@@ -5,7 +5,7 @@ if ( !defined( 'ABSPATH' ) ) {
5
  }
6
 
7
  define( 'W3TC', true );
8
- define( 'W3TC_VERSION', '0.10.2' );
9
  define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
10
  define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
11
  define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
@@ -127,6 +127,10 @@ if ( !defined( 'W3TC_EXTENSION_DIR' ) ) {
127
  if ( !defined( 'W3TC_WP_JSON_URI' ) ) {
128
  define( 'W3TC_WP_JSON_URI', '/wp-json/' );
129
  }
 
 
 
 
130
 
131
  @ini_set( 'pcre.backtrack_limit', 4194304 );
132
  @ini_set( 'pcre.recursion_limit', 4194304 );
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' );
127
  if ( !defined( 'W3TC_WP_JSON_URI' ) ) {
128
  define( 'W3TC_WP_JSON_URI', '/wp-json/' );
129
  }
130
+ if ( !defined( 'W3TC_FEED_REGEXP' ) ) {
131
+ define( 'W3TC_FEED_REGEXP', '~/feed(/|$)~' );
132
+ }
133
+
134
 
135
  @ini_set( 'pcre.backtrack_limit', 4194304 );
136
  @ini_set( 'pcre.recursion_limit', 4194304 );
w3-total-cache.php CHANGED
@@ -2,10 +2,10 @@
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.10.2
6
- Plugin URI: https://www.w3-edge.com/wordpress-plugins/w3-total-cache/
7
- Author: Frederick Townes
8
- Author URI: http://www.linkedin.com/in/fredericktownes
9
  Network: True
10
  */
11
 
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/
9
  Network: True
10
  */
11