W3 Total Cache - Version 0.9.7

Version Description

  • Fixed minified files not being hosted by CDN when enabled if "host minified files" is disabled
  • Fixed warning thrown when purge all was selected (via nigrosimone)
  • Fixed undefined offset error in fragment cache
  • Fixed MaxCDN test button failure when debug mode is enabled
  • Fixed purging of feeds when cache feeds option is enabeld
  • Improved handling of errors when full site delivery isn't set
  • Improved nginx.conf to support xml caching
  • Improved nginx.conf to support HSTS for static files
  • Improved minify's handling of query strings
  • Improved database caching, frequent wp_options no longer flush posts or comments data
  • Improved Limelight Networks CDN integration
  • Improved FAQ, they're now hosted in the GitHub public repository
  • Improved handling for /<![CDATA[/ in HTML minify engine
  • Imporved garbage collection for basic disk caching
  • Improved HSTS support (via Dave Welsh)
  • Improved reliabilty of CSS embed options
  • Improved New Relic requirements in compatibility test
  • Added StackPath CDN integration (including full site delivery)
  • Added support for page cache priming via WP-CLI via prime function
  • Added filter support for managing cache groups
  • Added API for flushing individual cache groups via flush_group function
  • Added purge support for JSON cache e.g. cached REST API requests
  • Added filter support for managing database cache settings
  • Added filter support before (w3tc_process_content) and after (w3tc_processed_content) a cache object is created
  • Added compatibility for AMPforWP plugin
  • Added JSON caching support for Pro subscribers
  • Added additional security headers (via amiga-500)
Download this release

Release Info

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

Code changes from version 0.9.6 to 0.9.7

Files changed (152) hide show
  1. BrowserCache_ConfigLabels.php +34 -1
  2. BrowserCache_Environment.php +227 -5
  3. CacheFlush.php +11 -0
  4. CacheFlush_Locally.php +10 -4
  5. Cache_Apc.php +1 -1
  6. Cache_Apcu.php +1 -1
  7. Cache_Base.php +1 -1
  8. Cache_Eaccelerator.php +1 -1
  9. Cache_File.php +7 -7
  10. Cache_File_Cleaner_Generic.php +26 -13
  11. Cache_File_Cleaner_Generic_HardDelete.php +20 -0
  12. Cache_File_Generic.php +30 -16
  13. Cache_Memcache.php +3 -1
  14. Cache_Memcached.php +3 -1
  15. Cache_Redis.php +1 -1
  16. Cache_Wincache.php +1 -1
  17. Cache_Xcache.php +1 -1
  18. CdnEngine.php +8 -0
  19. CdnEngine_Base.php +3 -5
  20. CdnEngine_Mirror_LimeLight.php +136 -0
  21. CdnEngine_Mirror_StackPath.php +113 -0
  22. Cdn_AdminActions.php +4 -2
  23. Cdn_CacheFlush.php +1 -1
  24. Cdn_Core.php +131 -89
  25. Cdn_Core_Admin.php +1 -1
  26. Cdn_LimeLight_Page.php +18 -0
  27. Cdn_LimeLight_Page_View.js +42 -0
  28. Cdn_LimeLight_Page_View.php +51 -0
  29. Cdn_LimeLight_Popup.php +75 -0
  30. Cdn_LimeLight_Popup_View_Intro.php +57 -0
  31. Cdn_LimeLight_Popup_View_Success.php +22 -0
  32. Cdn_MaxCdn_Page_View.js +0 -6
  33. Cdn_MaxCdn_Popup.php +2 -2
  34. Cdn_Plugin.php +32 -51
  35. Cdn_Plugin_Admin.php +36 -0
  36. Cdn_Plugin_WidgetMaxCdn.php +78 -102
  37. Cdn_Plugin_WidgetMaxCdn_View.css +95 -0
  38. Cdn_Plugin_WidgetMaxCdn_View.js +62 -0
  39. Cdn_Plugin_WidgetMaxCdn_View_Authorized.php +86 -0
  40. Cdn_Plugin_WidgetMaxCdn_View_Unauthorized.php +17 -0
  41. Cdn_StackPath_Api.php +249 -0
  42. Cdn_StackPath_Page.php +28 -0
  43. Cdn_StackPath_Page_View.js +62 -0
  44. Cdn_StackPath_Page_View.php +96 -0
  45. Cdn_StackPath_Popup.php +276 -0
  46. Cdn_StackPath_Popup_View_Intro.php +39 -0
  47. Cdn_StackPath_Popup_View_Success.php +23 -0
  48. Cdn_StackPath_Popup_View_Zone.php +42 -0
  49. Cdn_StackPath_Popup_View_Zones.php +53 -0
  50. Cdn_StackPath_Widget.php +141 -0
  51. Cdn_StackPath_Widget_View.css +98 -0
  52. Cdn_StackPath_Widget_View.js +62 -0
  53. Cdn_StackPath_Widget_View_Authorized.php +75 -0
  54. Cdn_StackPath_Widget_View_Unauthorized.php +17 -0
  55. Cdn_Util.php +8 -1
  56. Cdnfsd_CacheFlush.php +11 -3
  57. Cdnfsd_Core.php +9 -2
  58. Cdnfsd_Limelight_Api.php → Cdnfsd_LimeLight_Api.php +1 -1
  59. Cdnfsd_Limelight_Engine.php → Cdnfsd_LimeLight_Engine.php +3 -3
  60. Cdnfsd_Limelight_Page.php → Cdnfsd_LimeLight_Page.php +3 -3
  61. Cdnfsd_Limelight_Page_View.js → Cdnfsd_LimeLight_Page_View.js +0 -0
  62. Cdnfsd_Limelight_Page_View.php → Cdnfsd_LimeLight_Page_View.php +0 -0
  63. Cdnfsd_Limelight_Popup.php → Cdnfsd_LimeLight_Popup.php +5 -5
  64. Cdnfsd_Limelight_Popup_View_Intro.php → Cdnfsd_LimeLight_Popup_View_Intro.php +1 -1
  65. Cdnfsd_Limelight_Popup_View_Success.php → Cdnfsd_LimeLight_Popup_View_Success.php +0 -0
  66. Cdnfsd_MaxCdn_Popup.php +1 -1
  67. Cdnfsd_Plugin.php +6 -0
  68. Cdnfsd_Plugin_Admin.php +20 -5
  69. Cdnfsd_StackPath_Engine.php +48 -0
  70. Cdnfsd_StackPath_Page.php +20 -0
  71. Cdnfsd_StackPath_Page_View.js +102 -0
  72. Cdnfsd_StackPath_Page_View.php +61 -0
  73. Cdnfsd_StackPath_Popup.php +319 -0
  74. Cdnfsd_StackPath_Popup_View_Intro.php +39 -0
  75. Cdnfsd_StackPath_Popup_View_Success.php +26 -0
  76. Cdnfsd_StackPath_Popup_View_Zone.php +59 -0
  77. Cdnfsd_StackPath_Popup_View_Zones.php +53 -0
  78. Cli.php +38 -6
  79. ConfigCompiler.php +9 -0
  80. ConfigKeys.php +225 -7
  81. DbCache_Wpdb.php +2 -2
  82. DbCache_WpdbInjection.php +1 -1
  83. DbCache_WpdbInjection_QueryCaching.php +131 -39
  84. Enterprise_CacheFlush_MakeSnsEvent.php +9 -0
  85. Enterprise_SnsServer.php +4 -0
  86. Extension_Amp_Plugin.php +7 -2
  87. Extension_CloudFlare_AdminActions.php +1 -1
  88. Extension_CloudFlare_Api.php +6 -1
  89. Extension_CloudFlare_Plugin.php +1 -1
  90. Extension_FragmentCache_WpObjectCache.php +1 -1
  91. Extension_NewRelic_Page_View_Apm.php +1 -1
  92. Extension_NewRelic_Service.php +4 -5
  93. Extension_NewRelic_Widget_View.css +3 -3
  94. Extension_Swarmify_Plugin_Admin.php +0 -25
  95. Generic_AdminActions_Default.php +37 -22
  96. Generic_AdminActions_Flush.php +1 -1
  97. Generic_Faq.php +40 -80
  98. Generic_Page_Faq.php +0 -32
  99. Generic_Plugin.php +4 -2
  100. Generic_Plugin_Admin.php +28 -34
  101. Generic_Plugin_AdminNotifications.php +13 -5
  102. inc/options/common/help.php → Generic_Plugin_Admin_View_Faq.php +2 -4
  103. Generic_WidgetSpreadTheWord.js +4 -0
  104. Generic_WidgetSpreadTheWord_View.php +7 -5
  105. Minify_ContentMinifier.php +1 -1
  106. Minify_MinifiedFileRequestHandler.php +12 -8
  107. Minify_Plugin.php +17 -11
  108. ObjectCache_WpObjectCache_Regular.php +14 -13
  109. PgCache_ContentGrabber.php +87 -46
  110. PgCache_Environment.php +5 -1
  111. PgCache_Flush.php +35 -13
  112. PgCache_Plugin.php +37 -2
  113. PgCache_Plugin_Admin.php +29 -27
  114. Root_AdminMenu.php +12 -7
  115. Root_Loader.php +2 -1
  116. Util_Environment.php +43 -25
  117. Util_PageUrls.php +46 -0
  118. Util_Ui.php +30 -11
  119. inc/lightbox/self_test.php +1 -1
  120. inc/lightbox/support_us.php +26 -27
  121. inc/lightbox/upgrade.php +7 -4
  122. inc/options/browsercache.php +359 -11
  123. inc/options/cdn.php +5 -4
  124. inc/options/common/header.php +2 -1
  125. inc/options/dashboard.php +1 -1
  126. inc/options/faq.php +0 -40
  127. inc/options/general.php +1 -2
  128. inc/options/pgcache.php +29 -2
  129. inc/widget/maxcdn.php +0 -64
  130. inc/widget/maxcdn_signup.php +0 -22
  131. ini/apache_conf/mod_deflate.conf +48 -0
  132. ini/apache_conf/mod_expires.conf +95 -0
  133. ini/apache_conf/mod_mime.conf +59 -0
  134. ini/apache_conf/mod_rewrite.conf +18 -0
  135. languages/faq-en_US.xml +0 -826
  136. languages/faq-enterprise-en_US.xml +0 -61
  137. languages/faq-pro-en_US.xml +0 -221
  138. lib/Minify/Minify.php +2 -1
  139. lib/Minify/Minify/HTML.php +3 -2
  140. lib/NetDNA/NetDNA.php +0 -66
  141. lib/OAuth/W3tcOAuth.php +14 -11
  142. pub/css/lightbox.css +21 -0
  143. pub/css/options.css +16 -7
  144. pub/css/widget.css +0 -63
  145. pub/img/cspref.png +0 -0
  146. pub/img/w3tc_stackpath-logo-retina.png +0 -0
  147. pub/img/w3tc_stackpath-logo.png +0 -0
  148. pub/js/lightbox.js +7 -0
  149. pub/js/options.js +1435 -1355
  150. readme.txt +34 -5
  151. w3-total-cache-api.php +20 -5
  152. w3-total-cache.php +1 -1
BrowserCache_ConfigLabels.php CHANGED
@@ -35,7 +35,40 @@ class BrowserCache_ConfigLabels {
35
  'browsercache.other.w3tc' => __( 'Set W3 Total Cache header', 'w3-total-cache' ),
36
  'browsercache.other.compression' => __( 'Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> (gzip) compression</label>', 'w3-total-cache' ),
37
  'browsercache.other.replace' => __( 'Prevent caching of objects after settings change', 'w3-total-cache' ),
38
- 'browsercache.other.nocookies' => __( 'Disable cookies for static files', 'w3-total-cache' )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  ) );
40
  }
41
  }
35
  'browsercache.other.w3tc' => __( 'Set W3 Total Cache header', 'w3-total-cache' ),
36
  'browsercache.other.compression' => __( 'Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> (gzip) compression</label>', 'w3-total-cache' ),
37
  'browsercache.other.replace' => __( 'Prevent caching of objects after settings change', 'w3-total-cache' ),
38
+ 'browsercache.other.nocookies' => __( 'Disable cookies for static files', 'w3-total-cache' ),
39
+ 'browsercache.security.session.cookie_httponly' => __( 'Access session cookies through the <acronym title="Hypertext Transfer Protocol">HTTP</acronym> only:', 'w3-total-cache' ),
40
+ 'browsercache.security.session.cookie_secure' => __( 'Send session cookies only to secure connections:', 'w3-total-cache' ),
41
+ 'browsercache.security.session.use_only_cookies' => __( 'Use cookies to store session IDs:', 'w3-total-cache' ),
42
+ 'browsercache.hsts' => __( '<acronym title="Hypertext Transfer Protocol">HTTP</acronym> Strict Transport Security policy', 'w3-total-cache' ),
43
+ 'browsercache.security.hsts.directive' => __( 'Directive:', 'w3-total-cache' ),
44
+ 'browsercache.security.xfo' => __( 'X-Frame-Options', 'w3-total-cache' ),
45
+ 'browsercache.security.xfo.directive' => __( 'Directive:', 'w3-total-cache' ),
46
+ 'browsercache.security.xss' => __( 'X-XSS-Protection', 'w3-total-cache' ),
47
+ 'browsercache.security.xss.directive' => __( 'Directive:', 'w3-total-cache' ),
48
+ 'browsercache.security.xcto' => __( 'X-Content-Type-Options', 'w3-total-cache' ),
49
+ 'browsercache.security.pkp' => __( '<acronym title="Hypertext Transfer Protocol">HTTP</acronym> Public Key Pinning', 'w3-total-cache' ),
50
+ 'browsercache.security.pkp.pin' => __( 'Public Key:', 'w3-total-cache' ),
51
+ 'browsercache.security.pkp.pin.backup' => __( 'Public Key (Backup):', 'w3-total-cache' ),
52
+ 'browsercache.security.pkp.extra' => __( 'Extra Parameters:', 'w3-total-cache' ),
53
+ 'browsercache.security.pkp.report.url' => __( 'Report <acronym title="Uniform Resource Locator">URL</acronym>:', 'w3-total-cache' ),
54
+ 'browsercache.security.pkp.report.only' => __( 'Report Mode Only:', 'w3-total-cache' ),
55
+ 'browsercache.security.referrer.policy' => __( 'Referrer Policy', 'w3-total-cache' ),
56
+ 'browsercache.security.referrer.policy.directive' => __( 'Directive:', 'w3-total-cache' ),
57
+ 'browsercache.security.csp' => __( 'Content Security Policy', 'w3-total-cache' ),
58
+ 'browsercache.security.csp.base' => __( 'base-uri:', 'w3-total-cache' ),
59
+ 'browsercache.security.csp.frame' => __( 'frame-src:', 'w3-total-cache' ),
60
+ 'browsercache.security.csp.connect' => __( 'connect-src:', 'w3-total-cache' ),
61
+ 'browsercache.security.csp.font' => __( 'font-src:', 'w3-total-cache' ),
62
+ 'browsercache.security.csp.script' => __( 'script-src:', 'w3-total-cache' ),
63
+ 'browsercache.security.csp.style' => __( 'style-src:', 'w3-total-cache' ),
64
+ 'browsercache.security.csp.img' => __( 'img-src:', 'w3-total-cache' ),
65
+ 'browsercache.security.csp.media' => __( 'media-src:', 'w3-total-cache' ),
66
+ 'browsercache.security.csp.object' => __( 'object-src:', 'w3-total-cache' ),
67
+ 'browsercache.security.csp.plugin' => __( 'plugin-types:', 'w3-total-cache' ),
68
+ 'browsercache.security.csp.form' => __( 'form-action:', 'w3-total-cache' ),
69
+ 'browsercache.security.csp.frame.ancestors' => __( 'frame-ancestors:', 'w3-total-cache' ),
70
+ 'browsercache.security.csp.sandbox' => __( 'sandbox:', 'w3-total-cache' ),
71
+ 'browsercache.security.csp.default' => __( 'default-src:', 'w3-total-cache' )
72
  ) );
73
  }
74
  }
BrowserCache_Environment.php CHANGED
@@ -258,7 +258,6 @@ class BrowserCache_Environment {
258
 
259
  $rules .= "</IfModule>\n";
260
 
261
-
262
  $rules .= "<IfModule mod_expires.c>\n";
263
  $rules .= " ExpiresActive On\n";
264
 
@@ -335,10 +334,121 @@ class BrowserCache_Environment {
335
  $rules .= $this->_rules_cache_generate_apache_for_type( $config,
336
  $extensions, $type );
337
 
338
- if ( $config->get_boolean( 'browsercache.hsts' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  $lifetime = $config->get_integer( 'browsercache.other.lifetime' );
 
340
  $rules .= "<IfModule mod_headers.c>\n";
341
- $rules .= " Header set strict-transport-security \"max-age=$lifetime\"\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  $rules .= "</IfModule>\n";
343
  }
344
 
@@ -562,9 +672,109 @@ class BrowserCache_Environment {
562
  $this->_rules_cache_generate_nginx_for_type( $config, $rules,
563
  $extensions, $type );
564
 
565
- if ( $config->get_boolean( 'browsercache.hsts' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
  $lifetime = $config->get_integer( 'browsercache.other.lifetime' );
567
- $rules .= "add_header strict-transport-security \"max-age=$lifetime\";\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  }
569
 
570
  $rules .= W3TC_MARKER_END_BROWSERCACHE_CACHE . "\n";
@@ -808,6 +1018,18 @@ class BrowserCache_Environment {
808
  return $rules;
809
  }
810
 
 
 
 
 
 
 
 
 
 
 
 
 
811
  /**
812
  * Takes an array of extensions single per row and/or extensions delimited by |
813
  *
258
 
259
  $rules .= "</IfModule>\n";
260
 
 
261
  $rules .= "<IfModule mod_expires.c>\n";
262
  $rules .= " ExpiresActive On\n";
263
 
334
  $rules .= $this->_rules_cache_generate_apache_for_type( $config,
335
  $extensions, $type );
336
 
337
+ $sec = '';
338
+ $v = $config->get_string( 'browsercache.security.session.cookie_httponly' );
339
+ if ( !empty( $v ) ) {
340
+ $sec .= ' php_flag session.cookie_httponly ' .
341
+ ( $v == 'on' ? 'on' : 'off' ) . "\n";
342
+ }
343
+ $v = $config->get_string( 'browsercache.security.session.cookie_secure' );
344
+ if ( !empty( $v ) ) {
345
+ $sec .= ' php_flag session.cookie_secure ' .
346
+ ( $v == 'on' ? 'on' : 'off' ) . "\n";
347
+ }
348
+ $v = $config->get_string( 'browsercache.security.session.use_only_cookies' );
349
+ if ( !empty( $v ) ) {
350
+ $sec .= ' php_flag session.use_only_cookies ' .
351
+ ( $v == 'on' ? 'on' : 'off' ) . "\n";
352
+ }
353
+
354
+ if ( !empty( $sec ) ) {
355
+ $rules .= "<IfModule mod_php5.c>\n";
356
+ $rules .= $sec;
357
+ $rules .= "</IfModule>\n";
358
+ $rules .= "<IfModule mod_php7.c>\n";
359
+ $rules .= $sec;
360
+ $rules .= "</IfModule>\n";
361
+ $rules .= "<IfModule mod_suphp.c>\n";
362
+ $rules .= $sec;
363
+ $rules .= "</IfModule>\n";
364
+ }
365
+
366
+ if ( $config->get_boolean( 'browsercache.hsts' ) ||
367
+ $config->get_boolean( 'browsercache.security.xfo' ) ||
368
+ $config->get_boolean( 'browsercache.security.xss' ) ||
369
+ $config->get_boolean( 'browsercache.security.xcto' ) ||
370
+ $config->get_boolean( 'browsercache.security.pkp' ) ||
371
+ $config->get_boolean( 'browsercache.security.referrer.policy' ) ||
372
+ $config->get_boolean( 'browsercache.security.csp' )
373
+ ) {
374
  $lifetime = $config->get_integer( 'browsercache.other.lifetime' );
375
+
376
  $rules .= "<IfModule mod_headers.c>\n";
377
+
378
+ if ( $config->get_boolean( 'browsercache.hsts' ) ) {
379
+ $dir = $config->get_string( 'browsercache.security.hsts.directive' );
380
+ $rules .= " Header set Strict-Transport-Security \"max-age=$lifetime" . ( strpos( $dir,"inc" ) ? "; includeSubDomains" : "" ) . ( strpos( $dir, "pre" ) ? "; preload" : "" ) . "\"\n";
381
+ }
382
+
383
+ if ( $config->get_boolean( 'browsercache.security.xfo' ) ) {
384
+ $dir = $config->get_string( 'browsercache.security.xfo.directive' );
385
+ $url = trim( $config->get_string( 'browsercache.security.xfo.allow' ) );
386
+ if ( empty( $url ) ) {
387
+ $url = Util_Environment::home_url_maybe_https();
388
+ }
389
+ $rules .= " Header always append X-Frame-Options \"" . ( $dir == "same" ? "SAMEORIGIN" : ( $dir == "deny" ? "DENY" : "ALLOW-FROM $url" ) ) . "\"\n";
390
+ }
391
+
392
+ if ( $config->get_boolean( 'browsercache.security.xss' ) ) {
393
+ $dir = $config->get_string( 'browsercache.security.xss.directive' );
394
+ $rules .= " Header set X-XSS-Protection \"" . ( $dir == "block" ? "1; mode=block" : $dir ) . "\"\n";
395
+
396
+ }
397
+
398
+ if ( $config->get_boolean( 'browsercache.security.xcto' ) ) {
399
+ $rules .= " Header set X-Content-Type-Options \"nosniff\"\n";
400
+ }
401
+
402
+ if ( $config->get_boolean( 'browsercache.security.pkp' ) ) {
403
+ $pin = trim( $config->get_string( 'browsercache.security.pkp.pin' ) );
404
+ $pinbak = trim( $config->get_string( 'browsercache.security.pkp.pin.backup' ) );
405
+ $extra = $config->get_string( 'browsercache.security.pkp.extra' );
406
+ $url = trim( $config->get_string( 'browsercache.security.pkp.report.url' ) );
407
+ $rep_only = $config->get_string( 'browsercache.security.pkp.report.only' ) == '1' ? true : false;
408
+ $rules .= " Header set " . ( $rep_only ? "Public-Key-Pins-Report-Only" : "Public-Key-Pins" ) . " \"pin-sha256=\\\"$pin\\\"; pin-sha256=\\\"$pinbak\\\"; max-age=$lifetime" . ( strpos( $extra,"inc" ) ? "; includeSubDomains" : "" ) . ( !empty( $url ) ? "; report-uri=\\\"$url\\\"" : "" ) . "\"\n";
409
+ }
410
+
411
+ if ( $config->get_boolean( 'browsercache.security.referrer.policy' ) ) {
412
+ $dir = $config->get_string( 'browsercache.security.referrer.policy.directive' );
413
+ $rules .= " Header set Referrer-Policy \"" . ($dir == "0" ? "" : $dir ) . "\"\n";
414
+ }
415
+
416
+ if ( $config->get_boolean( 'browsercache.security.csp' ) ) {
417
+ $base = trim( $config->get_string( 'browsercache.security.csp.base' ) );
418
+ $frame = trim( $config->get_string( 'browsercache.security.csp.frame' ) );
419
+ $connect = trim( $config->get_string( 'browsercache.security.csp.connect' ) );
420
+ $font = trim( $config->get_string( 'browsercache.security.csp.font' ) );
421
+ $script = trim( $config->get_string( 'browsercache.security.csp.script' ) );
422
+ $style = trim( $config->get_string( 'browsercache.security.csp.style' ) );
423
+ $img = trim( $config->get_string( 'browsercache.security.csp.img' ) );
424
+ $media = trim( $config->get_string( 'browsercache.security.csp.media' ) );
425
+ $object = trim( $config->get_string( 'browsercache.security.csp.object' ) );
426
+ $plugin = trim( $config->get_string( 'browsercache.security.csp.plugin' ) );
427
+ $form = trim( $config->get_string( 'browsercache.security.csp.form' ) );
428
+ $frame_ancestors = trim( $config->get_string( 'browsercache.security.csp.frame.ancestors' ) );
429
+ $sandbox = $config->get_string( 'browsercache.security.csp.sandbox' );
430
+ $default = trim( $config->get_string( 'browsercache.security.csp.default' ) );
431
+
432
+ $dir = rtrim( ( !empty( $base ) ? "base-uri $base; " : "" ).
433
+ ( !empty( $frame ) ? "frame-src $frame; " : "" ).
434
+ ( !empty( $connect ) ? "connect-src $connect; " : "" ).
435
+ ( !empty( $font ) ? "font-src $font; " : "" ).
436
+ ( !empty( $script ) ? "script-src $script; " : "" ).
437
+ ( !empty( $style ) ? "style-src $style; " : "" ).
438
+ ( !empty( $img ) ? "img-src $img; " : "" ).
439
+ ( !empty( $media ) ? "media-src $media; " : "" ).
440
+ ( !empty( $object ) ? "object-src $object; " : "" ).
441
+ ( !empty( $plugin ) ? "plugin-types $plugin; " : "" ).
442
+ ( !empty( $form ) ? "form-action $form; " : "" ).
443
+ ( !empty( $frame_ancestors ) ? "frame-ancestors $frame_ancestors; " : "" ).
444
+ ( !empty( $sandbox ) ? "sandbox " . trim( $sandbox ) . "; " : "" ).
445
+ ( !empty( $default ) ? "default-src $default;" : "" ), "; " );
446
+
447
+ if ( !empty( $dir ) ) {
448
+ $rules .= " Header set Content-Security-Policy \"$dir\"\n";
449
+ }
450
+ }
451
+
452
  $rules .= "</IfModule>\n";
453
  }
454
 
672
  $this->_rules_cache_generate_nginx_for_type( $config, $rules,
673
  $extensions, $type );
674
 
675
+ $sec = '';
676
+ $v = $config->get_string( 'browsercache.security.session.cookie_httponly' );
677
+ if ( !empty( $v ) ) {
678
+ $sec .= 'session.cookie_httponly=' .
679
+ ( $v == 'on' ? "on" : "off" ) . "\n";
680
+ }
681
+ $v = $config->get_string( 'browsercache.security.session.cookie_secure' );
682
+ if ( !empty( $v ) ) {
683
+ $sec .= 'session.cookie_secure=' .
684
+ ( $v == 'on' ? "on" : "off" ) . "\n";
685
+ }
686
+ $v = $config->get_string( 'browsercache.security.session.use_only_cookies' );
687
+ if ( !empty( $v ) ) {
688
+ $sec .= 'session.use_only_cookies=' .
689
+ ( $v == 'on' ? "on" : "off" ) . "\n";
690
+ }
691
+ if ( !empty( $sec ) ) {
692
+ $rules .= "fastcgi_param PHP_FLAG \"$sec\";";
693
+ }
694
+
695
+ if ( $config->get_boolean( 'browsercache.hsts' ) ||
696
+ $config->get_boolean( 'browsercache.security.xfo' ) ||
697
+ $config->get_boolean( 'browsercache.security.xss' ) ||
698
+ $config->get_boolean( 'browsercache.security.xcto' ) ||
699
+ $config->get_boolean( 'browsercache.security.pkp' ) ||
700
+ $config->get_boolean( 'browsercache.security.referrer.policy' ) ||
701
+ $config->get_boolean( 'browsercache.security.csp' )
702
+ ) {
703
  $lifetime = $config->get_integer( 'browsercache.other.lifetime' );
704
+
705
+ if ( $config->get_boolean( 'browsercache.hsts' ) ) {
706
+ $dir = $config->get_string( 'browsercache.security.hsts.directive' );
707
+ $rules .= "add_header Strict-Transport-Security \"max-age=$lifetime" . ( strpos( $dir,"inc" ) ? "; includeSubDomains" : "" ) . ( strpos( $dir, "pre" ) ? "; preload" : "" ) . "\";\n";
708
+ }
709
+
710
+ if ( $config->get_boolean( 'browsercache.security.xfo' ) ) {
711
+ $dir = $config->get_string( 'browsercache.security.xfo.directive' );
712
+ $url = trim( $config->get_string( 'browsercache.security.xfo.allow' ) );
713
+ if ( empty( $url ) ) {
714
+ $url = Util_Environment::home_url_maybe_https();
715
+ }
716
+ $rules .= "add_header X-Frame-Options \"" . ( $dir == "same" ? "SAMEORIGIN" : ( $dir == "deny" ? "DENY" : "ALLOW-FROM $url" ) ) . "\";\n";
717
+ }
718
+
719
+ if ( $config->get_boolean( 'browsercache.security.xss' ) ) {
720
+ $dir = $config->get_string( 'browsercache.security.xss.directive' );
721
+ $rules .= "add_header X-XSS-Protection \"" . ( $dir == "block" ? "1; mode=block" : $dir ) . "\";\n";
722
+
723
+ }
724
+
725
+ if ( $config->get_boolean( 'browsercache.security.xcto' ) ) {
726
+ $rules .= "add_header X-Content-Type-Options \"nosniff\";\n";
727
+ }
728
+
729
+ if ( $config->get_boolean( 'browsercache.security.pkp' ) ) {
730
+ $pin = trim( $config->get_string( 'browsercache.security.pkp.pin' ) );
731
+ $pinbak = trim( $config->get_string( 'browsercache.security.pkp.pin.backup' ) );
732
+ $extra = $config->get_string( 'browsercache.security.pkp.extra' );
733
+ $url = trim( $config->get_string( 'browsercache.security.pkp.report.url' ) );
734
+ $rep_only = $config->get_string( 'browsercache.security.pkp.report.only' ) == '1' ? true : false;
735
+ $rules .= "add_header " . ( $rep_only ? "Public-Key-Pins-Report-Only" : "Public-Key-Pins" ) . " 'pin-sha256=\"$pin\"; pin-sha256=\"$pinbak\"; max-age=$lifetime" . ( strpos( $extra,"inc" ) ? "; includeSubDomains" : "" ) . ( !empty( $url ) ? "; report-uri=\"$url\"" : "" ) . "';\n";
736
+ }
737
+
738
+ if ( $config->get_boolean( 'browsercache.security.referrer.policy' ) ) {
739
+ $dir = $config->get_string( 'browsercache.security.referrer.policy.directive' );
740
+ $rules .= "add_header Referrer-Policy \"" . ( $dir == "0" ? "" : $dir ) . "\";\n";
741
+ }
742
+
743
+ if ( $config->get_boolean( 'browsercache.security.csp' ) ) {
744
+ $base = trim( $config->get_string( 'browsercache.security.csp.base' ) );
745
+ $frame = trim( $config->get_string( 'browsercache.security.csp.frame' ) );
746
+ $connect = trim( $config->get_string( 'browsercache.security.csp.connect' ) );
747
+ $font = trim( $config->get_string( 'browsercache.security.csp.font' ) );
748
+ $script = trim( $config->get_string( 'browsercache.security.csp.script' ) );
749
+ $style = trim( $config->get_string( 'browsercache.security.csp.style' ) );
750
+ $img = trim( $config->get_string( 'browsercache.security.csp.img' ) );
751
+ $media = trim( $config->get_string( 'browsercache.security.csp.media' ) );
752
+ $object = trim( $config->get_string( 'browsercache.security.csp.object' ) );
753
+ $plugin = trim( $config->get_string( 'browsercache.security.csp.plugin' ) );
754
+ $form = trim( $config->get_string( 'browsercache.security.csp.form' ) );
755
+ $frame_ancestors = trim( $config->get_string( 'browsercache.security.csp.frame.ancestors' ) );
756
+ $sandbox = $config->get_string( 'browsercache.security.csp.sandbox' );
757
+ $default = trim( $config->get_string( 'browsercache.security.csp.default' ) );
758
+
759
+ $dir = rtrim( ( !empty( $base ) ? "base-uri $base; " : "" ).
760
+ ( !empty( $frame ) ? "frame-src $frame; " : "" ).
761
+ ( !empty( $connect ) ? "connect-src $connect; " : "" ).
762
+ ( !empty( $font ) ? "font-src $font; " : "" ).
763
+ ( !empty( $script ) ? "script-src $script; " : "" ).
764
+ ( !empty( $style ) ? "style-src $style; " : "" ).
765
+ ( !empty( $img ) ? "img-src $img; " : "" ).
766
+ ( !empty( $media ) ? "media-src $media; " : "" ).
767
+ ( !empty( $object ) ? "object-src $object; " : "" ).
768
+ ( !empty( $plugin ) ? "plugin-types $plugin; " : "" ).
769
+ ( !empty( $form ) ? "form-action $form; " : "" ).
770
+ ( !empty( $frame_ancestors ) ? "frame-ancestors $frame_ancestors; " : "" ).
771
+ ( !empty( $sandbox ) ? "sandbox " . trim( $sandbox ) . "; " : "" ).
772
+ ( !empty( $default ) ? "default-src $default;" : "" ), "; " );
773
+
774
+ if ( !empty( $dir ) ) {
775
+ $rules .= "add_header Content-Security-Policy \"$dir\";\n";
776
+ }
777
+ }
778
  }
779
 
780
  $rules .= W3TC_MARKER_END_BROWSERCACHE_CACHE . "\n";
1018
  return $rules;
1019
  }
1020
 
1021
+ /**
1022
+ * Returns the apache, nginx version
1023
+ *
1024
+ * @return string
1025
+ */
1026
+ private function _get_server_version() {
1027
+ $sig= explode( '/', $_SERVER['SERVER_SOFTWARE'] );
1028
+ $temp = isset( $sig[1] ) ? explode( ' ', $sig[1] ) : array( '0' );
1029
+ $version = $temp[0];
1030
+ return $version;
1031
+ }
1032
+
1033
  /**
1034
  * Takes an array of extensions single per row and/or extensions delimited by |
1035
  *
CacheFlush.php CHANGED
@@ -159,6 +159,17 @@ class CacheFlush {
159
  }
160
  }
161
 
 
 
 
 
 
 
 
 
 
 
 
162
  /**
163
  * Purges/Flushes url
164
  */
159
  }
160
  }
161
 
162
+ /**
163
+ * Purges/Flushes cache group
164
+ */
165
+ function flush_group( $group, $extras = null ) {
166
+ static $flushed_groups = array();
167
+ if ( !isset( $flushed_groups[$group] ) ) {
168
+ $flushed_groups[$group] = '*';
169
+ $this->_executor->flush_group( $group, $extras );
170
+ }
171
+ }
172
+
173
  /**
174
  * Purges/Flushes url
175
  */
CacheFlush_Locally.php CHANGED
@@ -26,7 +26,7 @@ class CacheFlush_Locally {
26
  if ( !method_exists( $GLOBALS['wpdb'], 'flush_cache' ) )
27
  return false;
28
 
29
- return $GLOBALS['wpdb']->flush_cache();
30
  }
31
 
32
  /**
@@ -81,7 +81,7 @@ class CacheFlush_Locally {
81
  }
82
 
83
  function minifycache_flush_all( $extras = array() ) {
84
- if ( $extras['minify'] == 'purge_map' )
85
  delete_option( 'w3tc_minify' );
86
 
87
  $this->minifycache_flush( $extras );
@@ -125,7 +125,7 @@ class CacheFlush_Locally {
125
  do_action( 'w3tc_cdn_purge_files', $purgefiles );
126
  $common = Dispatcher::component( 'Cdn_Core' );
127
  $results = array();
128
- $v = $common->purge( $purgefiles, false, $results );
129
  do_action( 'w3tc_cdn_purge_files_after', $purgefiles );
130
 
131
  return $v;
@@ -189,7 +189,7 @@ class CacheFlush_Locally {
189
  if ( $config->get_boolean( 'dbcache.enabled' ) )
190
  add_action( 'w3tc_flush_all',
191
  array( $this, 'dbcache_flush' ),
192
- 100, 1 );
193
  if ( $config->get_boolean( 'objectcache.enabled' ) )
194
  add_action( 'w3tc_flush_all',
195
  array( $this, 'objectcache_flush' ),
@@ -207,6 +207,12 @@ class CacheFlush_Locally {
207
  do_action( 'w3tc_flush_all', $extras );
208
  }
209
 
 
 
 
 
 
 
210
  /**
211
  * Purges/Flushes url from page cache, varnish and cdn cache
212
  */
26
  if ( !method_exists( $GLOBALS['wpdb'], 'flush_cache' ) )
27
  return false;
28
 
29
+ return $GLOBALS['wpdb']->flush_cache( $extras );
30
  }
31
 
32
  /**
81
  }
82
 
83
  function minifycache_flush_all( $extras = array() ) {
84
+ if ( isset( $extras['minify'] ) && $extras['minify'] == 'purge_map' )
85
  delete_option( 'w3tc_minify' );
86
 
87
  $this->minifycache_flush( $extras );
125
  do_action( 'w3tc_cdn_purge_files', $purgefiles );
126
  $common = Dispatcher::component( 'Cdn_Core' );
127
  $results = array();
128
+ $v = $common->purge( $purgefiles, $results );
129
  do_action( 'w3tc_cdn_purge_files_after', $purgefiles );
130
 
131
  return $v;
189
  if ( $config->get_boolean( 'dbcache.enabled' ) )
190
  add_action( 'w3tc_flush_all',
191
  array( $this, 'dbcache_flush' ),
192
+ 100, 2 );
193
  if ( $config->get_boolean( 'objectcache.enabled' ) )
194
  add_action( 'w3tc_flush_all',
195
  array( $this, 'objectcache_flush' ),
207
  do_action( 'w3tc_flush_all', $extras );
208
  }
209
 
210
+ function flush_group( $group, $extras ) {
211
+ $do_flush = apply_filters( 'w3tc_preflush_group', true, $group, $extras );
212
+ if ( $do_flush )
213
+ do_action( 'w3tc_flush_group', $group, $extras );
214
+ }
215
+
216
  /**
217
  * Purges/Flushes url from page cache, varnish and cdn cache
218
  */
Cache_Apc.php CHANGED
@@ -135,7 +135,7 @@ class Cache_Apc extends Cache_Base {
135
  * @param unknown $key
136
  * @return bool
137
  */
138
- function hard_delete( $key ) {
139
  $storage_key = $this->get_item_key( $key );
140
  return apc_delete( $storage_key );
141
  }
135
  * @param unknown $key
136
  * @return bool
137
  */
138
+ function hard_delete( $key, $group = '' ) {
139
  $storage_key = $this->get_item_key( $key );
140
  return apc_delete( $storage_key );
141
  }
Cache_Apcu.php CHANGED
@@ -134,7 +134,7 @@ class Cache_Apcu extends Cache_Base {
134
  * @param unknown $key
135
  * @return bool
136
  */
137
- function hard_delete( $key ) {
138
  $storage_key = $this->get_item_key( $key );
139
  return apcu_delete( $storage_key );
140
  }
134
  * @param unknown $key
135
  * @return bool
136
  */
137
+ function hard_delete( $key, $group = '' ) {
138
  $storage_key = $this->get_item_key( $key );
139
  return apcu_delete( $storage_key );
140
  }
Cache_Base.php CHANGED
@@ -153,7 +153,7 @@ class Cache_Base {
153
  * @param string $key
154
  * @return boolean
155
  */
156
- function hard_delete( $key ) {
157
  return false;
158
  }
159
 
153
  * @param string $key
154
  * @return boolean
155
  */
156
+ function hard_delete( $key, $group = '' ) {
157
  return false;
158
  }
159
 
Cache_Eaccelerator.php CHANGED
@@ -135,7 +135,7 @@ class Cache_Eaccelerator extends Cache_Base {
135
  * @param unknown $key
136
  * @return bool
137
  */
138
- function hard_delete( $key ) {
139
  $storage_key = $this->get_item_key( $key );
140
  return eaccelerator_rm( $storage_key );
141
  }
135
  * @param unknown $key
136
  * @return bool
137
  */
138
+ function hard_delete( $key, $group = '' ) {
139
  $storage_key = $this->get_item_key( $key );
140
  return eaccelerator_rm( $storage_key );
141
  }
Cache_File.php CHANGED
@@ -151,7 +151,7 @@ class Cache_File extends Cache_Base {
151
 
152
  $path = $this->_cache_dir . DIRECTORY_SEPARATOR .
153
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) .
154
- $this->_get_path( $storage_key );
155
  if ( !is_readable( $path ) )
156
  return array( null, $has_old_data );
157
 
@@ -227,7 +227,7 @@ class Cache_File extends Cache_Base {
227
 
228
  $path = $this->_cache_dir . DIRECTORY_SEPARATOR .
229
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) .
230
- $this->_get_path( $storage_key );
231
 
232
  if ( !file_exists( $path ) )
233
  return true;
@@ -259,9 +259,9 @@ class Cache_File extends Cache_Base {
259
  *
260
  * @return bool
261
  */
262
- function hard_delete( $key ) {
263
  $key = $this->get_item_key( $key );
264
- $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key );
265
  return @unlink( $path );
266
  }
267
 
@@ -292,7 +292,7 @@ class Cache_File extends Cache_Base {
292
  $path =
293
  $this->_cache_dir . DIRECTORY_SEPARATOR .
294
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) .
295
- $this->_get_path( $key );
296
 
297
  if ( file_exists( $path ) ) {
298
  return @filemtime( $path );
@@ -307,7 +307,7 @@ class Cache_File extends Cache_Base {
307
  * @param string $key
308
  * @return string
309
  */
310
- function _get_path( $key ) {
311
  if ( $this->_use_wp_hash && function_exists( 'wp_hash' ) )
312
  $hash = wp_hash( $key );
313
  else
@@ -438,7 +438,7 @@ class Cache_File extends Cache_Base {
438
  private function fopen_write( $key, $group, $mode ) {
439
  $storage_key = $this->get_item_key( $key );
440
 
441
- $sub_path = $this->_get_path( $storage_key );
442
  $path = $this->_cache_dir . DIRECTORY_SEPARATOR .
443
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) . $sub_path;
444
 
151
 
152
  $path = $this->_cache_dir . DIRECTORY_SEPARATOR .
153
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) .
154
+ $this->_get_path( $storage_key, $group );
155
  if ( !is_readable( $path ) )
156
  return array( null, $has_old_data );
157
 
227
 
228
  $path = $this->_cache_dir . DIRECTORY_SEPARATOR .
229
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) .
230
+ $this->_get_path( $storage_key, $group );
231
 
232
  if ( !file_exists( $path ) )
233
  return true;
259
  *
260
  * @return bool
261
  */
262
+ function hard_delete( $key, $group = '' ) {
263
  $key = $this->get_item_key( $key );
264
+ $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key, $group );
265
  return @unlink( $path );
266
  }
267
 
292
  $path =
293
  $this->_cache_dir . DIRECTORY_SEPARATOR .
294
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) .
295
+ $this->_get_path( $key, $group );
296
 
297
  if ( file_exists( $path ) ) {
298
  return @filemtime( $path );
307
  * @param string $key
308
  * @return string
309
  */
310
+ function _get_path( $key, $group = '' ) {
311
  if ( $this->_use_wp_hash && function_exists( 'wp_hash' ) )
312
  $hash = wp_hash( $key );
313
  else
438
  private function fopen_write( $key, $group, $mode ) {
439
  $storage_key = $this->get_item_key( $key );
440
 
441
+ $sub_path = $this->_get_path( $storage_key, $group );
442
  $path = $this->_cache_dir . DIRECTORY_SEPARATOR .
443
  ( $group ? $group . DIRECTORY_SEPARATOR : '' ) . $sub_path;
444
 
Cache_File_Cleaner_Generic.php CHANGED
@@ -18,6 +18,8 @@ class Cache_File_Cleaner_Generic extends Cache_File_Cleaner {
18
  */
19
  var $_expire = 0;
20
 
 
 
21
  /**
22
  * PHP5-style constructor
23
  *
@@ -47,7 +49,8 @@ class Cache_File_Cleaner_Generic extends Cache_File_Cleaner {
47
 
48
  $full_path = $path . DIRECTORY_SEPARATOR . $entry;
49
 
50
- if ( substr( $entry, -4 ) === '_old' && !$this->is_old_file_expired( $full_path ) ) {
 
51
  continue;
52
  }
53
 
@@ -60,18 +63,8 @@ class Cache_File_Cleaner_Generic extends Cache_File_Cleaner {
60
 
61
  if ( @is_dir( $full_path ) ) {
62
  $this->_clean( $full_path );
63
- } elseif ( substr( $entry, -4 ) === '_old' ) {
64
- $this->processed_count++;
65
- @unlink( $full_path );
66
- } elseif ( !$this->is_valid( $full_path ) ) {
67
- $old_entry_path = $full_path . '_old';
68
- $this->processed_count++;
69
- if ( !@rename( $full_path, $old_entry_path ) ) {
70
- // if we can delete old entry - do second attempt to store in old-entry file
71
- if ( @unlink( $old_entry_path ) ) {
72
- @rename( $full_path, $old_entry_path );
73
- }
74
- }
75
  }
76
  }
77
 
@@ -81,6 +74,26 @@ class Cache_File_Cleaner_Generic extends Cache_File_Cleaner {
81
  }
82
  }
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  /**
85
  * Checks if file is valid
86
  *
18
  */
19
  var $_expire = 0;
20
 
21
+ private $hard_delete = false;
22
+
23
  /**
24
  * PHP5-style constructor
25
  *
49
 
50
  $full_path = $path . DIRECTORY_SEPARATOR . $entry;
51
 
52
+ if ( substr( $entry, -4 ) === '_old' &&
53
+ !$this->is_old_file_expired( $full_path ) ) {
54
  continue;
55
  }
56
 
63
 
64
  if ( @is_dir( $full_path ) ) {
65
  $this->_clean( $full_path );
66
+ } else {
67
+ $this->_clean_file( $entry, $full_path );
 
 
 
 
 
 
 
 
 
 
68
  }
69
  }
70
 
74
  }
75
  }
76
 
77
+ function _clean_file( $entry, $full_path ) {
78
+ if ( substr( $entry, -4 ) === '_old' ) {
79
+ $this->processed_count++;
80
+ @unlink( $full_path );
81
+ } elseif ( !$this->is_valid( $full_path ) ) {
82
+ $old_entry_path = $full_path . '_old';
83
+ $this->processed_count++;
84
+ if ( !@rename( $full_path, $old_entry_path ) ) {
85
+ // if we can delete old entry -
86
+ // do second attempt to store in old-entry file
87
+ if ( @unlink( $old_entry_path ) ) {
88
+ if ( !@rename( $full_path, $old_entry_path ) ) {
89
+ // last attempt - just remove entry
90
+ @unlink( $full_path );
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
  /**
98
  * Checks if file is valid
99
  *
Cache_File_Cleaner_Generic_HardDelete.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * Disk-enhanced file cache cleaner
6
+ */
7
+ class Cache_File_Cleaner_Generic_HardDelete extends Cache_File_Cleaner_Generic {
8
+ function __construct( $config = array() ) {
9
+ parent::__construct( $config );
10
+ }
11
+
12
+ function _clean_file( $entry, $full_path ) {
13
+ if ( substr( $entry, -4 ) === '_old' ) {
14
+ $this->processed_count++;
15
+ @unlink( $full_path );
16
+ } elseif ( !$this->is_valid( $full_path ) ) {
17
+ @unlink( $full_path );
18
+ }
19
+ }
20
+ }
Cache_File_Generic.php CHANGED
@@ -38,8 +38,8 @@ class Cache_File_Generic extends Cache_File {
38
  */
39
  function set( $key, $var, $expire = 0, $group = '' ) {
40
  $key = $this->get_item_key( $key );
41
- $sub_path = $this->_get_path( $key );
42
- $path = $this->_cache_dir . '/' . $sub_path;
43
 
44
  $dir = dirname( $path );
45
 
@@ -112,7 +112,8 @@ class Cache_File_Generic extends Cache_File {
112
  }
113
 
114
  if ( !empty($rules) ) {
115
- @file_put_contents( dirname( $path ) . '/.htaccess', $rules );
 
116
  }
117
  }
118
 
@@ -129,7 +130,8 @@ class Cache_File_Generic extends Cache_File {
129
  function get_with_old( $key, $group = '' ) {
130
  $has_old_data = false;
131
  $key = $this->get_item_key( $key );
132
- $path = $this->_cache_dir . '/' . $this->_get_path( $key );
 
133
 
134
  $data = $this->_read( $path );
135
  if ( $data != null )
@@ -202,7 +204,7 @@ class Cache_File_Generic extends Cache_File {
202
  */
203
  function delete( $key, $group = '' ) {
204
  $key = $this->get_item_key( $key );
205
- $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key );
206
 
207
  if ( !file_exists( $path ) )
208
  return true;
@@ -225,9 +227,9 @@ class Cache_File_Generic extends Cache_File {
225
  * @param unknown $key
226
  * @return bool
227
  */
228
- function hard_delete( $key ) {
229
  $key = $this->get_item_key( $key );
230
- $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key );
231
  $old_entry_path = $path . '_old';
232
  @unlink( $old_entry_path );
233
 
@@ -249,11 +251,21 @@ class Cache_File_Generic extends Cache_File {
249
  $sitemap_regex = $config->get_string( 'pgcache.purge.sitemap_regex' );
250
  $this->_flush_based_on_regex( $sitemap_regex );
251
  } else {
252
- $c = new Cache_File_Cleaner_Generic( array(
253
- 'cache_dir' => $this->_flush_dir,
254
- 'exclude' => $this->_exclude,
255
- 'clean_timelimit' => $this->_flush_timelimit
256
- ) );
 
 
 
 
 
 
 
 
 
 
257
 
258
  $c->clean();
259
  }
@@ -265,8 +277,8 @@ class Cache_File_Generic extends Cache_File {
265
  * @param string $key
266
  * @return string
267
  */
268
- function _get_path( $key ) {
269
- return $key;
270
  }
271
 
272
  function get_item_key( $key ) {
@@ -285,9 +297,11 @@ class Cache_File_Generic extends Cache_File {
285
  $parsed = parse_url( $domain );
286
  $host = $parsed['host'];
287
  $path = isset( $parsed['path'] ) ? '/' . trim( $parsed['path'], '/' ) : '';
288
- $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR . '/' . $host . $path;
 
289
  } else
290
- $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR . '/' . Util_Environment::host();
 
291
 
292
  $dir = @opendir( $flush_dir );
293
  if ( $dir ) {
38
  */
39
  function set( $key, $var, $expire = 0, $group = '' ) {
40
  $key = $this->get_item_key( $key );
41
+ $sub_path = $this->_get_path( $key, $group );
42
+ $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $sub_path;
43
 
44
  $dir = dirname( $path );
45
 
112
  }
113
 
114
  if ( !empty($rules) ) {
115
+ @file_put_contents( dirname( $path ) .
116
+ DIRECTORY_SEPARATOR . '.htaccess', $rules );
117
  }
118
  }
119
 
130
  function get_with_old( $key, $group = '' ) {
131
  $has_old_data = false;
132
  $key = $this->get_item_key( $key );
133
+ $path = $this->_cache_dir . DIRECTORY_SEPARATOR .
134
+ $this->_get_path( $key, $group );
135
 
136
  $data = $this->_read( $path );
137
  if ( $data != null )
204
  */
205
  function delete( $key, $group = '' ) {
206
  $key = $this->get_item_key( $key );
207
+ $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key, $group );
208
 
209
  if ( !file_exists( $path ) )
210
  return true;
227
  * @param unknown $key
228
  * @return bool
229
  */
230
+ function hard_delete( $key, $group = '' ) {
231
  $key = $this->get_item_key( $key );
232
+ $path = $this->_cache_dir . DIRECTORY_SEPARATOR . $this->_get_path( $key, $group );
233
  $old_entry_path = $path . '_old';
234
  @unlink( $old_entry_path );
235
 
251
  $sitemap_regex = $config->get_string( 'pgcache.purge.sitemap_regex' );
252
  $this->_flush_based_on_regex( $sitemap_regex );
253
  } else {
254
+ $dir = $this->_flush_dir;
255
+ if ( !empty( $group ) ) {
256
+ $c = new Cache_File_Cleaner_Generic_HardDelete( array(
257
+ 'cache_dir' => $this->_flush_dir .
258
+ DIRECTORY_SEPARATOR . $group,
259
+ 'exclude' => $this->_exclude,
260
+ 'clean_timelimit' => $this->_flush_timelimit
261
+ ) );
262
+ } else {
263
+ $c = new Cache_File_Cleaner_Generic( array(
264
+ 'cache_dir' => $this->_flush_dir,
265
+ 'exclude' => $this->_exclude,
266
+ 'clean_timelimit' => $this->_flush_timelimit
267
+ ) );
268
+ }
269
 
270
  $c->clean();
271
  }
277
  * @param string $key
278
  * @return string
279
  */
280
+ function _get_path( $key, $group = '' ) {
281
+ return ( empty( $group ) ? '' : $group . DIRECTORY_SEPARATOR ) . $key;
282
  }
283
 
284
  function get_item_key( $key ) {
297
  $parsed = parse_url( $domain );
298
  $host = $parsed['host'];
299
  $path = isset( $parsed['path'] ) ? '/' . trim( $parsed['path'], '/' ) : '';
300
+ $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR .
301
+ DIRECTORY_SEPARATOR . $host . $path;
302
  } else
303
+ $flush_dir = W3TC_CACHE_PAGE_ENHANCED_DIR .
304
+ DIRECTORY_SEPARATOR . Util_Environment::host();
305
 
306
  $dir = @opendir( $flush_dir );
307
  if ( $dir ) {
Cache_Memcache.php CHANGED
@@ -168,7 +168,7 @@ class Cache_Memcache extends Cache_Base {
168
  * @param unknown $key
169
  * @return bool
170
  */
171
- function hard_delete( $key ) {
172
  $storage_key = $this->get_item_key( $key );
173
  return @$this->_memcache->delete( $storage_key, 0 );
174
  }
@@ -223,6 +223,8 @@ class Cache_Memcache extends Cache_Base {
223
  * @return boolean
224
  */
225
  private function _set_key_version( $v, $group = '' ) {
 
 
226
  @$this->_memcache->set( $this->_get_key_version_key( $group ), $v, false, 0 );
227
  }
228
 
168
  * @param unknown $key
169
  * @return bool
170
  */
171
+ function hard_delete( $key, $group = '' ) {
172
  $storage_key = $this->get_item_key( $key );
173
  return @$this->_memcache->delete( $storage_key, 0 );
174
  }
223
  * @return boolean
224
  */
225
  private function _set_key_version( $v, $group = '' ) {
226
+ // expiration has to be as long as possible since
227
+ // all cache data expires when key version expires
228
  @$this->_memcache->set( $this->_get_key_version_key( $group ), $v, false, 0 );
229
  }
230
 
Cache_Memcached.php CHANGED
@@ -206,7 +206,7 @@ class Cache_Memcached extends Cache_Base {
206
  * @param unknown $key
207
  * @return bool
208
  */
209
- function hard_delete( $key ) {
210
  $storage_key = $this->get_item_key( $key );
211
  return @$this->_memcache->delete( $storage_key );
212
  }
@@ -278,6 +278,8 @@ class Cache_Memcached extends Cache_Base {
278
  * @return boolean
279
  */
280
  private function _set_key_version( $v, $group = '' ) {
 
 
281
  @$this->_memcache->set( $this->_get_key_version_key( $group ), $v, 0 );
282
  }
283
 
206
  * @param unknown $key
207
  * @return bool
208
  */
209
+ function hard_delete( $key, $group = '' ) {
210
  $storage_key = $this->get_item_key( $key );
211
  return @$this->_memcache->delete( $storage_key );
212
  }
278
  * @return boolean
279
  */
280
  private function _set_key_version( $v, $group = '' ) {
281
+ // expiration has to be as long as possible since
282
+ // all cache data expires when key version expires
283
  @$this->_memcache->set( $this->_get_key_version_key( $group ), $v, 0 );
284
  }
285
 
Cache_Redis.php CHANGED
@@ -161,7 +161,7 @@ class Cache_Redis extends Cache_Base {
161
  * @param unknown $key
162
  * @return bool
163
  */
164
- function hard_delete( $key ) {
165
  $storage_key = $this->get_item_key( $key );
166
  $accessor = $this->_get_accessor( $storage_key );
167
  if ( is_null( $accessor ) )
161
  * @param unknown $key
162
  * @return bool
163
  */
164
+ function hard_delete( $key, $group = '' ) {
165
  $storage_key = $this->get_item_key( $key );
166
  $accessor = $this->_get_accessor( $storage_key );
167
  if ( is_null( $accessor ) )
Cache_Wincache.php CHANGED
@@ -131,7 +131,7 @@ class Cache_Wincache extends Cache_Base {
131
  * @param unknown $key
132
  * @return bool
133
  */
134
- function hard_delete( $key ) {
135
  $storage_key = $this->get_item_key( $key );
136
  return wincache_ucache_delete( $storage_key );
137
  }
131
  * @param unknown $key
132
  * @return bool
133
  */
134
+ function hard_delete( $key, $group = '' ) {
135
  $storage_key = $this->get_item_key( $key );
136
  return wincache_ucache_delete( $storage_key );
137
  }
Cache_Xcache.php CHANGED
@@ -135,7 +135,7 @@ class Cache_Xcache extends Cache_Base {
135
  * @param unknown $key
136
  * @return bool
137
  */
138
- function hard_delete( $key ) {
139
  $storage_key = $this->get_item_key( $key );
140
  return xcache_unset( $storage_key );
141
  }
135
  * @param unknown $key
136
  * @return bool
137
  */
138
+ function hard_delete( $key, $group = '' ) {
139
  $storage_key = $this->get_item_key( $key );
140
  return xcache_unset( $storage_key );
141
  }
CdnEngine.php CHANGED
@@ -59,6 +59,10 @@ class CdnEngine {
59
  $instances[$instance_key] = new CdnEngine_Mirror_Highwinds( $config );
60
  break;
61
 
 
 
 
 
62
  case 'maxcdn':
63
  $instances[$instance_key] = new CdnEngine_Mirror_MaxCdn( $config );
64
  break;
@@ -84,6 +88,10 @@ class CdnEngine {
84
  $instances[$instance_key] = new CdnEngine_S3_Compatible( $config );
85
  break;
86
 
 
 
 
 
87
  default :
88
  trigger_error( 'Incorrect CDN engine', E_USER_WARNING );
89
  $instances[$instance_key] = new CdnEngine_Base();
59
  $instances[$instance_key] = new CdnEngine_Mirror_Highwinds( $config );
60
  break;
61
 
62
+ case 'limelight':
63
+ $instances[$instance_key] = new CdnEngine_Mirror_LimeLight( $config );
64
+ break;
65
+
66
  case 'maxcdn':
67
  $instances[$instance_key] = new CdnEngine_Mirror_MaxCdn( $config );
68
  break;
88
  $instances[$instance_key] = new CdnEngine_S3_Compatible( $config );
89
  break;
90
 
91
+ case 'stackpath':
92
+ $instances[$instance_key] = new CdnEngine_Mirror_StackPath( $config );
93
+ break;
94
+
95
  default :
96
  trigger_error( 'Incorrect CDN engine', E_USER_WARNING );
97
  $instances[$instance_key] = new CdnEngine_Base();
CdnEngine_Base.php CHANGED
@@ -181,7 +181,7 @@ class CdnEngine_Base {
181
  default:
182
  if ( !isset( $domains[0] ) ) {
183
  $scheme = $this->_get_scheme();
184
- if ( 'https' == $scheme && isset( $domains['https_default'] ) ) {
185
  return $domains['https_default'];
186
  } else {
187
  return isset( $domains['http_default'] ) ? $domains['http_default'] :
@@ -515,10 +515,8 @@ class CdnEngine_Base {
515
  $hostname = $_domain;
516
  }
517
 
518
- if ( !$hostname ) {
519
- $error = 'Empty hostname';
520
-
521
- return false;
522
  }
523
 
524
  if ( gethostbyname( $hostname ) === $hostname ) {
181
  default:
182
  if ( !isset( $domains[0] ) ) {
183
  $scheme = $this->_get_scheme();
184
+ if ( 'https' == $scheme && !empty( $domains['https_default'] ) ) {
185
  return $domains['https_default'];
186
  } else {
187
  return isset( $domains['http_default'] ) ? $domains['http_default'] :
515
  $hostname = $_domain;
516
  }
517
 
518
+ if ( empty( $hostname ) ) {
519
+ continue;
 
 
520
  }
521
 
522
  if ( gethostbyname( $hostname ) === $hostname ) {
CdnEngine_Mirror_LimeLight.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * class CdnEngine_Mirror_Highwinds
6
+ */
7
+ class CdnEngine_Mirror_LimeLight extends CdnEngine_Mirror {
8
+ private $short_name;
9
+ private $username;
10
+ private $api_key;
11
+ private $debug;
12
+ private $domains;
13
+
14
+ /**
15
+ * PHP5 Constructor
16
+ *
17
+ * @param array $config
18
+ * account_hash
19
+ * username
20
+ * password
21
+ */
22
+ function __construct( $config = array() ) {
23
+ $this->short_name = $config['short_name'];
24
+ $this->username = $config['username'];
25
+ $this->api_key = $config['api_key'];
26
+ $this->debug = $config['debug'];
27
+
28
+ $this->domains = (array)$config['domains'];
29
+
30
+ parent::__construct( $config );
31
+ }
32
+
33
+ /**
34
+ * Purges remote files
35
+ *
36
+ * @param array $files
37
+ * @param array $results
38
+ * @return boolean
39
+ */
40
+ function purge( $files, &$results ) {
41
+ if ( empty( $this->short_name ) || empty( $this->username ) ||
42
+ empty( $this->api_key ) )
43
+ throw new \Exception( __( 'Credentials are not specified.', 'w3-total-cache' ) );
44
+
45
+ $api = new Cdnfsd_LimeLight_Api( $this->short_name, $this->username, $this->api_key );
46
+
47
+ $results = array();
48
+ try {
49
+ $items = array();
50
+ foreach ( $files as $file ) {
51
+ $url = $this->_format_url( $file['remote_path'] );
52
+ $items[] = array(
53
+ 'pattern' => $url,
54
+ 'exact' => true,
55
+ 'evict' => false,
56
+ 'incqs' => false
57
+ );
58
+
59
+ // max number of items per request based on API docs
60
+ if ( count( $items ) >= 100 ) {
61
+ if ( $this->debug ) {
62
+ Util_Debug::log( 'cdn', json_encode( $items, JSON_PRETTY_PRINT ) );
63
+ }
64
+
65
+ $api->purge( $items );
66
+ $items = array();
67
+ }
68
+ }
69
+
70
+ if ( $this->debug ) {
71
+ Util_Debug::log( 'cdn', json_encode( $items, JSON_PRETTY_PRINT ) );
72
+ }
73
+
74
+ $api->purge( $items );
75
+
76
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, 'OK' );
77
+ } catch ( \Exception $e ) {
78
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT,
79
+ __( 'Failed to purge: ', 'w3-total-cache' ) . $e->getMessage() );
80
+ }
81
+
82
+ return !$this->_is_error( $results );
83
+ }
84
+
85
+ /**
86
+ * Purge CDN completely
87
+ *
88
+ * @param unknown $results
89
+ * @return bool
90
+ */
91
+ function purge_all( &$results ) {
92
+ if ( empty( $this->short_name ) || empty( $this->username ) ||
93
+ empty( $this->api_key ) )
94
+ throw new \Exception( __( 'Access key not specified.', 'w3-total-cache' ) );
95
+
96
+ $api = new Cdnfsd_LimeLight_Api( $this->short_name, $this->username, $this->api_key );
97
+
98
+ $results = array();
99
+ try {
100
+ $items = array();
101
+ foreach ( $this->domains as $domain ) {
102
+ $items[] = array(
103
+ 'pattern' => 'http://' . $domain . '/*',
104
+ 'exact' => false,
105
+ 'evict' => false,
106
+ 'incqs' => false
107
+ );
108
+ $items[] = array(
109
+ 'pattern' => 'https://' . $domain . '/*',
110
+ 'exact' => false,
111
+ 'evict' => false,
112
+ 'incqs' => false
113
+ );
114
+ }
115
+
116
+ if ( $this->debug ) {
117
+ Util_Debug::log( 'cdn', json_encode( $items, JSON_PRETTY_PRINT ) );
118
+ }
119
+
120
+ $api->purge( $items );
121
+
122
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, 'OK' );
123
+ } catch ( \Exception $e ) {
124
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT,
125
+ __( 'Failed to purge all: ', 'w3-total-cache' ) . $e->getMessage() );
126
+ }
127
+
128
+ return !$this->_is_error( $results );
129
+ }
130
+
131
+
132
+
133
+ function get_domains() {
134
+ return $this->domains;
135
+ }
136
+ }
CdnEngine_Mirror_StackPath.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class CdnEngine_Mirror_StackPath extends CdnEngine_Mirror {
5
+ /**
6
+ * PHP5 Constructor
7
+ *
8
+ * @param array $config
9
+ */
10
+ function __construct( $config = array() ) {
11
+ $config = array_merge( array(
12
+ 'authorization_key' => '',
13
+ 'alias' => '',
14
+ 'consumerkey' => '',
15
+ 'consumersecret' => '',
16
+ 'zone_id' => 0
17
+ ), $config );
18
+ $split_keys = explode( '+', $config['authorization_key'] );
19
+ if ( sizeof( $split_keys )==3 )
20
+ list( $config['alias'], $config['consumerkey'], $config['consumersecret'] ) = $split_keys;
21
+ parent::__construct( $config );
22
+ }
23
+
24
+ /**
25
+ * Purges remote files
26
+ *
27
+ * @param array $files
28
+ * @param array $results
29
+ * @return boolean
30
+ */
31
+ function purge( $files, &$results ) {
32
+ if ( empty( $this->_config['authorization_key'] ) ) {
33
+ $results = $this->_get_results( $files, W3TC_CDN_RESULT_HALT, __( 'Empty Authorization Key.', 'w3-total-cache' ) );
34
+
35
+ return false;
36
+ }
37
+
38
+ if ( empty( $this->_config['alias'] ) ||
39
+ empty( $this->_config['consumerkey'] ) ||
40
+ empty( $this->_config['consumersecret'] ) ) {
41
+ $results = $this->_get_results( $files, W3TC_CDN_RESULT_HALT, __( 'Malformed Authorization Key.', 'w3-total-cache' ) );
42
+
43
+ return false;
44
+ }
45
+
46
+ $api = new Cdn_StackPath_Api( $this->_config['alias'],
47
+ $this->_config['consumerkey'], $this->_config['consumersecret'] );
48
+ $results = array();
49
+
50
+ try {
51
+ $zone_id = $this->_config['zone_id'];
52
+
53
+ if ( $zone_id == 0 || is_null( $zone_id ) ) {
54
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR,
55
+ __( 'No zone defined', 'w3-total-cache' ) );
56
+ return !$this->_is_error( $results );
57
+ }
58
+
59
+
60
+ $files_to_pass = array();
61
+ foreach ( $files as $file )
62
+ $files_to_pass[] = '/' . $file['remote_path'];
63
+ $params = array( 'files' => $files_to_pass );
64
+ $api->delete_site_cache( $zone_id, $params );
65
+
66
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, 'OK' );
67
+ } catch ( \Exception $e ) {
68
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, __( 'Failure to pull zone: ', 'w3-total-cache' ) . $e->getMessage() );
69
+ }
70
+
71
+ return !$this->_is_error( $results );
72
+ }
73
+
74
+ /**
75
+ * Purge CDN completely
76
+ *
77
+ * @param unknown $results
78
+ * @return bool
79
+ */
80
+ function purge_all( &$results ) {
81
+ if ( empty( $this->_config['authorization_key'] ) ) {
82
+ $results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Empty Authorization Key.', 'w3-total-cache' ) );
83
+
84
+ return false;
85
+ }
86
+
87
+ if ( empty( $this->_config['alias'] ) || empty( $this->_config['consumerkey'] ) || empty( $this->_config['consumersecret'] ) ) {
88
+ $results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Malformed Authorization Key.', 'w3-total-cache' ) );
89
+
90
+ return false;
91
+ }
92
+
93
+ $api = new Cdn_StackPath_Api( $this->_config['alias'], $this->_config['consumerkey'], $this->_config['consumersecret'] );
94
+
95
+ $results = array();
96
+
97
+ try {
98
+ $zone_id = $this->_config['zone_id'];
99
+
100
+ if ( $zone_id == 0 || is_null( $zone_id ) ) {
101
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR,
102
+ __( 'No zone defined', 'w3-total-cache' ) );
103
+ return !$this->_is_error( $results );
104
+ }
105
+
106
+ $file_purge = $api->delete_site_cache( $zone_id );
107
+ } catch ( \Exception $e ) {
108
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, __( 'Failure to pull zone: ', 'w3-total-cache' ) . $e->getMessage() );
109
+ }
110
+
111
+ return !$this->_is_error( $results );
112
+ }
113
+ }
Cdn_AdminActions.php CHANGED
@@ -96,7 +96,7 @@ class Cdn_AdminActions {
96
  ), true );
97
  } else {
98
  Util_Admin::redirect_with_custom_messages2( array(
99
- 'errors' => array( 'Failed to flush CDN: ' .
100
  implode( ', ', $errors ) )
101
  ), true );
102
  }
@@ -340,7 +340,7 @@ class Cdn_AdminActions {
340
  }
341
 
342
  if ( count( $purge ) ) {
343
- $common->purge( $purge, false, $results );
344
  } else {
345
  $errors[] = __( 'Empty files list.', 'w3-total-cache' );
346
  }
@@ -406,6 +406,8 @@ class Cdn_AdminActions {
406
 
407
  if ( $result ) {
408
  if ( $engine == 'google_drive' || $engine == 'highwinds' ||
 
 
409
  $engine == 'rackspace_cdn' ||
410
  $engine == 'rscf' || $engine == 's3_compatible' ) {
411
  // those use already stored w3tc config
96
  ), true );
97
  } else {
98
  Util_Admin::redirect_with_custom_messages2( array(
99
+ 'errors' => array( 'Failed to purge CDN: ' .
100
  implode( ', ', $errors ) )
101
  ), true );
102
  }
340
  }
341
 
342
  if ( count( $purge ) ) {
343
+ $common->purge( $purge, $results );
344
  } else {
345
  $errors[] = __( 'Empty files list.', 'w3-total-cache' );
346
  }
406
 
407
  if ( $result ) {
408
  if ( $engine == 'google_drive' || $engine == 'highwinds' ||
409
+ $engine == 'limelight' ||
410
+ $engine == 'maxcdn' || $engine == 'stackpath' ||
411
  $engine == 'rackspace_cdn' ||
412
  $engine == 'rscf' || $engine == 's3_compatible' ) {
413
  // those use already stored w3tc config
Cdn_CacheFlush.php CHANGED
@@ -51,7 +51,7 @@ class Cdn_CacheFlush {
51
  $remote_path = $common->uri_to_cdn_uri( $local_site_path );
52
  $files[] = $common->build_file_descriptor( $local_site_path, $remote_path );
53
  $this->_flushed_urls[] = $url;
54
- $common->purge( $files, false, $results );
55
  }
56
 
57
  /**
51
  $remote_path = $common->uri_to_cdn_uri( $local_site_path );
52
  $files[] = $common->build_file_descriptor( $local_site_path, $remote_path );
53
  $this->_flushed_urls[] = $url;
54
+ $common->purge( $files, $results );
55
  }
56
 
57
  /**
Cdn_Core.php CHANGED
@@ -15,12 +15,14 @@ class Cdn_Core {
15
  * Config
16
  */
17
  private $_config = null;
 
18
 
19
  /**
20
  * Runs plugin
21
  */
22
  function __construct() {
23
  $this->_config = Dispatcher::config();
 
24
  }
25
 
26
  /**
@@ -175,6 +177,11 @@ class Cdn_Core {
175
  * @return boolean
176
  */
177
  function upload( $files, $queue_failed, &$results, $timeout_time = NULL ) {
 
 
 
 
 
178
  $cdn = $this->get_cdn();
179
  $force_rewrite = $this->_config->get_boolean( 'cdn.force.rewrite' );
180
 
@@ -208,6 +215,10 @@ class Cdn_Core {
208
  @set_time_limit( $this->_config->get_integer( 'timelimit.cdn_delete' ) );
209
 
210
  $return = $cdn->delete( $files, $results );
 
 
 
 
211
 
212
  if ( !$return && $queue_failed ) {
213
  foreach ( $results as $result ) {
@@ -228,7 +239,12 @@ class Cdn_Core {
228
  * @param array $results
229
  * @return boolean
230
  */
231
- function purge( $files, $queue_failed, &$results ) {
 
 
 
 
 
232
  /**
233
  * Purge varnish servers before mirror purging
234
  */
@@ -288,7 +304,11 @@ class Cdn_Core {
288
  */
289
  function queue_upload_url( $url ) {
290
  $docroot_filename = Util_Environment::url_to_docroot_filename( $url );
291
- $filename = Util_Environment::document_root() . '/' . $docroot_filename;
 
 
 
 
292
 
293
  $a = parse_url( $url );
294
  $uri = $a['path'];
@@ -325,98 +345,99 @@ class Cdn_Core {
325
  static $cdn = array();
326
 
327
  if ( !isset( $cdn[0] ) ) {
328
- $engine = $this->_config->get_string( 'cdn.engine' );
329
- $compression = ( $this->_config->get_boolean( 'browsercache.enabled' ) && $this->_config->get_boolean( 'browsercache.html.compression' ) );
 
330
 
331
  switch ( $engine ) {
332
  case 'akamai':
333
  $engine_config = array(
334
- 'username' => $this->_config->get_string( 'cdn.akamai.username' ),
335
- 'password' => $this->_config->get_string( 'cdn.akamai.password' ),
336
- 'zone' => $this->_config->get_string( 'cdn.akamai.zone' ),
337
- 'domain' => $this->_config->get_array( 'cdn.akamai.domain' ),
338
- 'ssl' => $this->_config->get_string( 'cdn.akamai.ssl' ),
339
- 'email_notification' => $this->_config->get_array( 'cdn.akamai.email_notification' ),
340
  'compression' => false
341
  );
342
  break;
343
 
344
  case 'att':
345
  $engine_config = array(
346
- 'account' => $this->_config->get_string( 'cdn.att.account' ),
347
- 'token' => $this->_config->get_string( 'cdn.att.token' ),
348
- 'domain' => $this->_config->get_array( 'cdn.att.domain' ),
349
- 'ssl' => $this->_config->get_string( 'cdn.att.ssl' ),
350
  'compression' => false
351
  );
352
  break;
353
 
354
  case 'azure':
355
  $engine_config = array(
356
- 'user' => $this->_config->get_string( 'cdn.azure.user' ),
357
- 'key' => $this->_config->get_string( 'cdn.azure.key' ),
358
- 'container' => $this->_config->get_string( 'cdn.azure.container' ),
359
- 'cname' => $this->_config->get_array( 'cdn.azure.cname' ),
360
- 'ssl' => $this->_config->get_string( 'cdn.azure.ssl' ),
361
  'compression' => false
362
  );
363
  break;
364
 
365
  case 'cf':
366
  $engine_config = array(
367
- 'key' => $this->_config->get_string( 'cdn.cf.key' ),
368
- 'secret' => $this->_config->get_string( 'cdn.cf.secret' ),
369
- 'bucket' => $this->_config->get_string( 'cdn.cf.bucket' ),
370
- 'bucket_location' => $this->_config->get_string( 'cdn.cf.bucket.location' ),
371
- 'id' => $this->_config->get_string( 'cdn.cf.id' ),
372
- 'cname' => $this->_config->get_array( 'cdn.cf.cname' ),
373
- 'ssl' => $this->_config->get_string( 'cdn.cf.ssl' ),
374
  'compression' => $compression
375
  );
376
  break;
377
 
378
  case 'cf2':
379
  $engine_config = array(
380
- 'key' => $this->_config->get_string( 'cdn.cf2.key' ),
381
- 'secret' => $this->_config->get_string( 'cdn.cf2.secret' ),
382
- 'id' => $this->_config->get_string( 'cdn.cf2.id' ),
383
- 'cname' => $this->_config->get_array( 'cdn.cf2.cname' ),
384
- 'ssl' => $this->_config->get_string( 'cdn.cf2.ssl' ),
385
  'compression' => false
386
  );
387
  break;
388
 
389
  case 'cotendo':
390
  $engine_config = array(
391
- 'username' => $this->_config->get_string( 'cdn.cotendo.username' ),
392
- 'password' => $this->_config->get_string( 'cdn.cotendo.password' ),
393
- 'zones' => $this->_config->get_array( 'cdn.cotendo.zones' ),
394
- 'domain' => $this->_config->get_array( 'cdn.cotendo.domain' ),
395
- 'ssl' => $this->_config->get_string( 'cdn.cotendo.ssl' ),
396
  'compression' => false
397
  );
398
  break;
399
 
400
  case 'edgecast':
401
  $engine_config = array(
402
- 'account' => $this->_config->get_string( 'cdn.edgecast.account' ),
403
- 'token' => $this->_config->get_string( 'cdn.edgecast.token' ),
404
- 'domain' => $this->_config->get_array( 'cdn.edgecast.domain' ),
405
- 'ssl' => $this->_config->get_string( 'cdn.edgecast.ssl' ),
406
  'compression' => false
407
  );
408
  break;
409
 
410
  case 'ftp':
411
  $engine_config = array(
412
- 'host' => $this->_config->get_string( 'cdn.ftp.host' ),
413
- 'type' => $this->_config->get_string( 'cdn.ftp.type' ),
414
- 'user' => $this->_config->get_string( 'cdn.ftp.user' ),
415
- 'pass' => $this->_config->get_string( 'cdn.ftp.pass' ),
416
- 'path' => $this->_config->get_string( 'cdn.ftp.path' ),
417
- 'pasv' => $this->_config->get_boolean( 'cdn.ftp.pasv' ),
418
- 'domain' => $this->_config->get_array( 'cdn.ftp.domain' ),
419
- 'ssl' => $this->_config->get_string( 'cdn.ftp.ssl' ),
420
  'compression' => false,
421
  'docroot' => Util_Environment::document_root()
422
  );
@@ -427,15 +448,15 @@ class Cdn_Core {
427
 
428
  $engine_config = array(
429
  'client_id' =>
430
- $this->_config->get_string( 'cdn.google_drive.client_id' ),
431
  'access_token' =>
432
  $state->get_string( 'cdn.google_drive.access_token' ),
433
  'refresh_token' =>
434
- $this->_config->get_string( 'cdn.google_drive.refresh_token' ),
435
  'root_url' =>
436
- $this->_config->get_string( 'cdn.google_drive.folder.url' ),
437
  'root_folder_id' =>
438
- $this->_config->get_string( 'cdn.google_drive.folder.id' ),
439
  'new_access_token_callback' => array(
440
  $this,
441
  'on_google_drive_new_access_token'
@@ -448,32 +469,42 @@ class Cdn_Core {
448
 
449
  $engine_config = array(
450
  'domains' =>
451
- $this->_config->get_array( 'cdn.highwinds.host.domains' ),
452
  'ssl' =>
453
- $this->_config->get_string( 'cdn.highwinds.ssl' ),
454
  'api_token' =>
455
- $this->_config->get_string( 'cdn.highwinds.api_token' ),
456
  'account_hash' =>
457
- $this->_config->get_string( 'cdn.highwinds.account_hash' ),
458
  'host_hash_code' =>
459
- $this->_config->get_string( 'cdn.highwinds.host.hash_code' )
460
  );
461
  break;
462
 
 
 
 
 
 
 
 
 
 
 
463
  case 'maxcdn':
464
  $engine_config = array(
465
- 'authorization_key' => $this->_config->get_string( 'cdn.maxcdn.authorization_key' ),
466
- 'zone_id' => $this->_config->get_integer( 'cdn.maxcdn.zone_id' ),
467
- 'domain' => $this->_config->get_array( 'cdn.maxcdn.domain' ),
468
- 'ssl' => $this->_config->get_string( 'cdn.maxcdn.ssl' ),
469
  'compression' => false
470
  );
471
  break;
472
 
473
  case 'mirror':
474
  $engine_config = array(
475
- 'domain' => $this->_config->get_array( 'cdn.mirror.domain' ),
476
- 'ssl' => $this->_config->get_string( 'cdn.mirror.ssl' ),
477
  'compression' => false
478
  );
479
  break;
@@ -482,13 +513,13 @@ class Cdn_Core {
482
  $state = Dispatcher::config_state();
483
 
484
  $engine_config = array(
485
- 'user_name' => $this->_config->get_string( 'cdn.rackspace_cdn.user_name' ),
486
- 'api_key' => $this->_config->get_string( 'cdn.rackspace_cdn.api_key' ),
487
- 'region' => $this->_config->get_string( 'cdn.rackspace_cdn.region' ),
488
- 'service_access_url' => $this->_config->get_string( 'cdn.rackspace_cdn.service.access_url' ),
489
- 'service_id' => $this->_config->get_string( 'cdn.rackspace_cdn.service.id' ),
490
- 'service_protocol' => $this->_config->get_string( 'cdn.rackspace_cdn.service.protocol' ),
491
- 'domains' => $this->_config->get_array( 'cdn.rackspace_cdn.domains' ),
492
  'access_state' =>
493
  $state->get_string( 'cdn.rackspace_cdn.access_state' ),
494
  'new_access_state_callback' => array(
@@ -502,12 +533,12 @@ class Cdn_Core {
502
  $state = Dispatcher::config_state();
503
 
504
  $engine_config = array(
505
- 'user_name' => $this->_config->get_string( 'cdn.rscf.user' ),
506
- 'api_key' => $this->_config->get_string( 'cdn.rscf.key' ),
507
- 'region' => $this->_config->get_string( 'cdn.rscf.location' ),
508
- 'container' => $this->_config->get_string( 'cdn.rscf.container' ),
509
- 'cname' => $this->_config->get_array( 'cdn.rscf.cname' ),
510
- 'ssl' => $this->_config->get_string( 'cdn.rscf.ssl' ),
511
  'compression' => false,
512
  'access_state' =>
513
  $state->get_string( 'cdn.rackspace_cf.access_state' ),
@@ -521,31 +552,42 @@ class Cdn_Core {
521
 
522
  case 's3':
523
  $engine_config = array(
524
- 'key' => $this->_config->get_string( 'cdn.s3.key' ),
525
- 'secret' => $this->_config->get_string( 'cdn.s3.secret' ),
526
- 'bucket' => $this->_config->get_string( 'cdn.s3.bucket' ),
527
- 'bucket_location' => $this->_config->get_string( 'cdn.s3.bucket.location' ),
528
- 'cname' => $this->_config->get_array( 'cdn.s3.cname' ),
529
- 'ssl' => $this->_config->get_string( 'cdn.s3.ssl' ),
530
  'compression' => $compression
531
  );
532
  break;
533
 
534
  case 's3_compatible':
535
  $engine_config = array(
536
- 'key' => $this->_config->get_string( 'cdn.s3.key' ),
537
- 'secret' => $this->_config->get_string( 'cdn.s3.secret' ),
538
- 'bucket' => $this->_config->get_string( 'cdn.s3.bucket' ),
539
- 'cname' => $this->_config->get_array( 'cdn.s3.cname' ),
540
- 'ssl' => $this->_config->get_string( 'cdn.s3.ssl' ),
541
  'compression' => $compression,
542
- 'api_host' => $this->_config->get_string( 'cdn.s3_compatible.api_host' )
 
 
 
 
 
 
 
 
 
 
543
  );
544
  break;
 
545
  }
546
 
547
  $engine_config = array_merge( $engine_config, array(
548
- 'debug' => $this->_config->get_boolean( 'cdn.debug' )
549
  ) );
550
 
551
  $cdn[0] = CdnEngine::instance( $engine, $engine_config );
15
  * Config
16
  */
17
  private $_config = null;
18
+ private $debug;
19
 
20
  /**
21
  * Runs plugin
22
  */
23
  function __construct() {
24
  $this->_config = Dispatcher::config();
25
+ $this->debug = $this->_config->get_boolean( 'cdn.debug' );
26
  }
27
 
28
  /**
177
  * @return boolean
178
  */
179
  function upload( $files, $queue_failed, &$results, $timeout_time = NULL ) {
180
+ if ( $this->debug ) {
181
+ Util_Debug::log( 'cdn', 'upload: ' .
182
+ json_encode( $files, JSON_PRETTY_PRINT ) );
183
+ }
184
+
185
  $cdn = $this->get_cdn();
186
  $force_rewrite = $this->_config->get_boolean( 'cdn.force.rewrite' );
187
 
215
  @set_time_limit( $this->_config->get_integer( 'timelimit.cdn_delete' ) );
216
 
217
  $return = $cdn->delete( $files, $results );
218
+ if ( $this->debug ) {
219
+ Util_Debug::log( 'cdn', 'delete: ' .
220
+ json_encode( $files, JSON_PRETTY_PRINT ) );
221
+ }
222
 
223
  if ( !$return && $queue_failed ) {
224
  foreach ( $results as $result ) {
239
  * @param array $results
240
  * @return boolean
241
  */
242
+ function purge( $files, &$results ) {
243
+ if ( $this->debug ) {
244
+ Util_Debug::log( 'cdn', 'purge: ' .
245
+ json_encode( $files, JSON_PRETTY_PRINT ) );
246
+ }
247
+
248
  /**
249
  * Purge varnish servers before mirror purging
250
  */
304
  */
305
  function queue_upload_url( $url ) {
306
  $docroot_filename = Util_Environment::url_to_docroot_filename( $url );
307
+ if ( is_null( $docroot_filename ) ) {
308
+ return;
309
+ }
310
+
311
+ $filename = Util_Environment::docroot_to_full_filename( $docroot_filename );
312
 
313
  $a = parse_url( $url );
314
  $uri = $a['path'];
345
  static $cdn = array();
346
 
347
  if ( !isset( $cdn[0] ) ) {
348
+ $c = $this->_config;
349
+ $engine = $c->get_string( 'cdn.engine' );
350
+ $compression = ( $c->get_boolean( 'browsercache.enabled' ) && $c->get_boolean( 'browsercache.html.compression' ) );
351
 
352
  switch ( $engine ) {
353
  case 'akamai':
354
  $engine_config = array(
355
+ 'username' => $c->get_string( 'cdn.akamai.username' ),
356
+ 'password' => $c->get_string( 'cdn.akamai.password' ),
357
+ 'zone' => $c->get_string( 'cdn.akamai.zone' ),
358
+ 'domain' => $c->get_array( 'cdn.akamai.domain' ),
359
+ 'ssl' => $c->get_string( 'cdn.akamai.ssl' ),
360
+ 'email_notification' => $c->get_array( 'cdn.akamai.email_notification' ),
361
  'compression' => false
362
  );
363
  break;
364
 
365
  case 'att':
366
  $engine_config = array(
367
+ 'account' => $c->get_string( 'cdn.att.account' ),
368
+ 'token' => $c->get_string( 'cdn.att.token' ),
369
+ 'domain' => $c->get_array( 'cdn.att.domain' ),
370
+ 'ssl' => $c->get_string( 'cdn.att.ssl' ),
371
  'compression' => false
372
  );
373
  break;
374
 
375
  case 'azure':
376
  $engine_config = array(
377
+ 'user' => $c->get_string( 'cdn.azure.user' ),
378
+ 'key' => $c->get_string( 'cdn.azure.key' ),
379
+ 'container' => $c->get_string( 'cdn.azure.container' ),
380
+ 'cname' => $c->get_array( 'cdn.azure.cname' ),
381
+ 'ssl' => $c->get_string( 'cdn.azure.ssl' ),
382
  'compression' => false
383
  );
384
  break;
385
 
386
  case 'cf':
387
  $engine_config = array(
388
+ 'key' => $c->get_string( 'cdn.cf.key' ),
389
+ 'secret' => $c->get_string( 'cdn.cf.secret' ),
390
+ 'bucket' => $c->get_string( 'cdn.cf.bucket' ),
391
+ 'bucket_location' => $c->get_string( 'cdn.cf.bucket.location' ),
392
+ 'id' => $c->get_string( 'cdn.cf.id' ),
393
+ 'cname' => $c->get_array( 'cdn.cf.cname' ),
394
+ 'ssl' => $c->get_string( 'cdn.cf.ssl' ),
395
  'compression' => $compression
396
  );
397
  break;
398
 
399
  case 'cf2':
400
  $engine_config = array(
401
+ 'key' => $c->get_string( 'cdn.cf2.key' ),
402
+ 'secret' => $c->get_string( 'cdn.cf2.secret' ),
403
+ 'id' => $c->get_string( 'cdn.cf2.id' ),
404
+ 'cname' => $c->get_array( 'cdn.cf2.cname' ),
405
+ 'ssl' => $c->get_string( 'cdn.cf2.ssl' ),
406
  'compression' => false
407
  );
408
  break;
409
 
410
  case 'cotendo':
411
  $engine_config = array(
412
+ 'username' => $c->get_string( 'cdn.cotendo.username' ),
413
+ 'password' => $c->get_string( 'cdn.cotendo.password' ),
414
+ 'zones' => $c->get_array( 'cdn.cotendo.zones' ),
415
+ 'domain' => $c->get_array( 'cdn.cotendo.domain' ),
416
+ 'ssl' => $c->get_string( 'cdn.cotendo.ssl' ),
417
  'compression' => false
418
  );
419
  break;
420
 
421
  case 'edgecast':
422
  $engine_config = array(
423
+ 'account' => $c->get_string( 'cdn.edgecast.account' ),
424
+ 'token' => $c->get_string( 'cdn.edgecast.token' ),
425
+ 'domain' => $c->get_array( 'cdn.edgecast.domain' ),
426
+ 'ssl' => $c->get_string( 'cdn.edgecast.ssl' ),
427
  'compression' => false
428
  );
429
  break;
430
 
431
  case 'ftp':
432
  $engine_config = array(
433
+ 'host' => $c->get_string( 'cdn.ftp.host' ),
434
+ 'type' => $c->get_string( 'cdn.ftp.type' ),
435
+ 'user' => $c->get_string( 'cdn.ftp.user' ),
436
+ 'pass' => $c->get_string( 'cdn.ftp.pass' ),
437
+ 'path' => $c->get_string( 'cdn.ftp.path' ),
438
+ 'pasv' => $c->get_boolean( 'cdn.ftp.pasv' ),
439
+ 'domain' => $c->get_array( 'cdn.ftp.domain' ),
440
+ 'ssl' => $c->get_string( 'cdn.ftp.ssl' ),
441
  'compression' => false,
442
  'docroot' => Util_Environment::document_root()
443
  );
448
 
449
  $engine_config = array(
450
  'client_id' =>
451
+ $c->get_string( 'cdn.google_drive.client_id' ),
452
  'access_token' =>
453
  $state->get_string( 'cdn.google_drive.access_token' ),
454
  'refresh_token' =>
455
+ $c->get_string( 'cdn.google_drive.refresh_token' ),
456
  'root_url' =>
457
+ $c->get_string( 'cdn.google_drive.folder.url' ),
458
  'root_folder_id' =>
459
+ $c->get_string( 'cdn.google_drive.folder.id' ),
460
  'new_access_token_callback' => array(
461
  $this,
462
  'on_google_drive_new_access_token'
469
 
470
  $engine_config = array(
471
  'domains' =>
472
+ $c->get_array( 'cdn.highwinds.host.domains' ),
473
  'ssl' =>
474
+ $c->get_string( 'cdn.highwinds.ssl' ),
475
  'api_token' =>
476
+ $c->get_string( 'cdn.highwinds.api_token' ),
477
  'account_hash' =>
478
+ $c->get_string( 'cdn.highwinds.account_hash' ),
479
  'host_hash_code' =>
480
+ $c->get_string( 'cdn.highwinds.host.hash_code' )
481
  );
482
  break;
483
 
484
+ case 'limelight':
485
+ $engine_config = array(
486
+ 'short_name' => $c->get_string( 'cdn.limelight.short_name' ),
487
+ 'username' => $c->get_string( 'cdn.limelight.username' ),
488
+ 'api_key' => $c->get_string( 'cdn.limelight.api_key' ),
489
+ 'domains' => $c->get_array( 'cdn.limelight.host.domains' ),
490
+ 'debug' => $c->get_string( 'cdn.debug' )
491
+ );
492
+ break;
493
+
494
  case 'maxcdn':
495
  $engine_config = array(
496
+ 'authorization_key' => $c->get_string( 'cdn.maxcdn.authorization_key' ),
497
+ 'zone_id' => $c->get_integer( 'cdn.maxcdn.zone_id' ),
498
+ 'domain' => $c->get_array( 'cdn.maxcdn.domain' ),
499
+ 'ssl' => $c->get_string( 'cdn.maxcdn.ssl' ),
500
  'compression' => false
501
  );
502
  break;
503
 
504
  case 'mirror':
505
  $engine_config = array(
506
+ 'domain' => $c->get_array( 'cdn.mirror.domain' ),
507
+ 'ssl' => $c->get_string( 'cdn.mirror.ssl' ),
508
  'compression' => false
509
  );
510
  break;
513
  $state = Dispatcher::config_state();
514
 
515
  $engine_config = array(
516
+ 'user_name' => $c->get_string( 'cdn.rackspace_cdn.user_name' ),
517
+ 'api_key' => $c->get_string( 'cdn.rackspace_cdn.api_key' ),
518
+ 'region' => $c->get_string( 'cdn.rackspace_cdn.region' ),
519
+ 'service_access_url' => $c->get_string( 'cdn.rackspace_cdn.service.access_url' ),
520
+ 'service_id' => $c->get_string( 'cdn.rackspace_cdn.service.id' ),
521
+ 'service_protocol' => $c->get_string( 'cdn.rackspace_cdn.service.protocol' ),
522
+ 'domains' => $c->get_array( 'cdn.rackspace_cdn.domains' ),
523
  'access_state' =>
524
  $state->get_string( 'cdn.rackspace_cdn.access_state' ),
525
  'new_access_state_callback' => array(
533
  $state = Dispatcher::config_state();
534
 
535
  $engine_config = array(
536
+ 'user_name' => $c->get_string( 'cdn.rscf.user' ),
537
+ 'api_key' => $c->get_string( 'cdn.rscf.key' ),
538
+ 'region' => $c->get_string( 'cdn.rscf.location' ),
539
+ 'container' => $c->get_string( 'cdn.rscf.container' ),
540
+ 'cname' => $c->get_array( 'cdn.rscf.cname' ),
541
+ 'ssl' => $c->get_string( 'cdn.rscf.ssl' ),
542
  'compression' => false,
543
  'access_state' =>
544
  $state->get_string( 'cdn.rackspace_cf.access_state' ),
552
 
553
  case 's3':
554
  $engine_config = array(
555
+ 'key' => $c->get_string( 'cdn.s3.key' ),
556
+ 'secret' => $c->get_string( 'cdn.s3.secret' ),
557
+ 'bucket' => $c->get_string( 'cdn.s3.bucket' ),
558
+ 'bucket_location' => $c->get_string( 'cdn.s3.bucket.location' ),
559
+ 'cname' => $c->get_array( 'cdn.s3.cname' ),
560
+ 'ssl' => $c->get_string( 'cdn.s3.ssl' ),
561
  'compression' => $compression
562
  );
563
  break;
564
 
565
  case 's3_compatible':
566
  $engine_config = array(
567
+ 'key' => $c->get_string( 'cdn.s3.key' ),
568
+ 'secret' => $c->get_string( 'cdn.s3.secret' ),
569
+ 'bucket' => $c->get_string( 'cdn.s3.bucket' ),
570
+ 'cname' => $c->get_array( 'cdn.s3.cname' ),
571
+ 'ssl' => $c->get_string( 'cdn.s3.ssl' ),
572
  'compression' => $compression,
573
+ 'api_host' => $c->get_string( 'cdn.s3_compatible.api_host' )
574
+ );
575
+ break;
576
+
577
+ case 'stackpath':
578
+ $engine_config = array(
579
+ 'authorization_key' => $c->get_string( 'cdn.stackpath.authorization_key' ),
580
+ 'zone_id' => $c->get_integer( 'cdn.stackpath.zone_id' ),
581
+ 'domain' => $c->get_array( 'cdn.stackpath.domain' ),
582
+ 'ssl' => $c->get_string( 'cdn.stackpath.ssl' ),
583
+ 'compression' => false
584
  );
585
  break;
586
+
587
  }
588
 
589
  $engine_config = array_merge( $engine_config, array(
590
+ 'debug' => $c->get_boolean( 'cdn.debug' )
591
  ) );
592
 
593
  $cdn[0] = CdnEngine::instance( $engine, $engine_config );
Cdn_Core_Admin.php CHANGED
@@ -37,7 +37,7 @@ class Cdn_Core_Admin {
37
  $common = Dispatcher::component( 'Cdn_Core' );
38
  $files = $common->get_attachment_files( $attachment_id );
39
 
40
- return $common->purge( $files, false, $results );
41
  }
42
 
43
  /**
37
  $common = Dispatcher::component( 'Cdn_Core' );
38
  $files = $common->get_attachment_files( $attachment_id );
39
 
40
+ return $common->purge( $files, $results );
41
  }
42
 
43
  /**
Cdn_LimeLight_Page.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class Cdn_LimeLight_Page {
5
+ // called from plugin-admin
6
+ static public function admin_print_scripts_w3tc_cdn() {
7
+ wp_enqueue_script( 'w3tc_cdn_limelight',
8
+ plugins_url( 'Cdn_LimeLight_Page_View.js', W3TC_FILE ),
9
+ array( 'jquery' ), '1.0' );
10
+ }
11
+
12
+
13
+
14
+ static public function w3tc_settings_cdn_boxarea_configuration() {
15
+ $config = Dispatcher::config();
16
+ include W3TC_DIR . '/Cdn_LimeLight_Page_View.php';
17
+ }
18
+ }
Cdn_LimeLight_Page_View.js ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ function w3tc_popup_resize(o) {
3
+ o.options.height = jQuery('.w3tc_popup_form').height() + 30;
4
+ o.resize();
5
+ }
6
+
7
+ $('body')
8
+ .on('click', '.w3tc_cdn_limelight_authorize', function() {
9
+ W3tc_Lightbox.open({
10
+ id:'w3tc-overlay',
11
+ close: '',
12
+ width: 800,
13
+ height: 300,
14
+ url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
15
+ '&w3tc_action=cdn_limelight_intro',
16
+ callback: w3tc_popup_resize
17
+ });
18
+ })
19
+
20
+
21
+
22
+ .on('click', '.w3tc_cdn_limelight_save', function() {
23
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
24
+ '&w3tc_action=cdn_limelight_save';
25
+
26
+ var v = $('.w3tc_popup_form').find('input').each(function(i) {
27
+ var name = $(this).attr('name');
28
+ if (name)
29
+ url += '&' + encodeURIComponent(name) + '=' +
30
+ encodeURIComponent($(this).val());
31
+ });
32
+
33
+ W3tc_Lightbox.load(url, w3tc_popup_resize);
34
+ })
35
+
36
+
37
+
38
+ .on('click', '.w3tc_cdn_limelight_done', function() {
39
+ // refresh page
40
+ window.location = window.location + '&';
41
+ })
42
+ });
Cdn_LimeLight_Page_View.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ $api_key = $config->get_string( 'cdn.limelight.api_key' );
8
+ ?>
9
+ <tr>
10
+ <th style="width: 300px;"><label><?php _e( 'Authorize:', 'w3-total-cache' ); ?></label></th>
11
+ <td>
12
+ <?php if ( empty( $api_key ) ): ?>
13
+ <input class="w3tc_cdn_limelight_authorize button" type="button"
14
+ value="<?php _e( 'Authorize', 'w3-total-cache' ); ?>" />
15
+ <?php else: ?>
16
+ <input class="w3tc_cdn_limelight_authorize button" type="button"
17
+ value="<?php _e( 'Reauthorize', 'w3-total-cache' ); ?>" />
18
+ <?php endif ?>
19
+ </td>
20
+ </tr>
21
+
22
+ <?php if ( !empty( $api_key ) ): ?>
23
+ <tr>
24
+ <th><label for="cdn_limelight_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support:</label>', 'w3-total-cache' ); ?></th>
25
+ <td>
26
+ <select id="cdn_limelight_ssl" name="cdn__limelight__ssl">
27
+ <option value="auto"<?php selected( $config->get_string( 'cdn.limelight.ssl' ), 'auto' ); ?>><?php _e( 'Auto (determine connection type automatically)', 'w3-total-cache' ); ?></option>
28
+ <option value="enabled"<?php selected( $config->get_string( 'cdn.limelight.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
29
+ <option value="disabled"<?php selected( $config->get_string( 'cdn.limelight.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
30
+ </select>
31
+ <br /><span class="description"><?php _e( 'Some <acronym title="Content Delivery Network">CDN</acronym> providers may or may not support <acronym title="Secure Sockets Layer">SSL</acronym>, contact your vendor for more information.', 'w3-total-cache' ); ?></span>
32
+ </td>
33
+ </tr>
34
+ <tr>
35
+ <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
36
+ <td>
37
+ <?php $cnames = $config->get_array( 'cdn.limelight.host.domains' ); include W3TC_INC_DIR . '/options/cdn/common/cnames-readonly.php'; ?>
38
+ <br />
39
+ <span class="description"><?php _e( 'Hostname provided by your <acronym title="Content Delivery Network">CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
40
+ </td>
41
+ </tr>
42
+ <tr>
43
+ <th colspan="2">
44
+ <input id="cdn_test"
45
+ class="button {type: 'limelight', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"
46
+ type="button"
47
+ value="<?php _e( 'Test', 'w3-total-cache' ); ?>" />
48
+ <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
49
+ </th>
50
+ </tr>
51
+ <?php endif ?>
Cdn_LimeLight_Popup.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdnfsd_LimeLight_Popup {
7
+ static public function w3tc_ajax() {
8
+ $o = new Cdnfsd_LimeLight_Popup();
9
+
10
+ add_action( 'w3tc_ajax_cdn_limelight_intro',
11
+ array( $o, 'w3tc_ajax_cdn_limelight_intro' ) );
12
+ add_action( 'w3tc_ajax_cdn_limelight_save',
13
+ array( $o, 'w3tc_ajax_cdn_limelight_save' ) );
14
+ }
15
+
16
+
17
+
18
+ public function w3tc_ajax_cdn_limelight_intro() {
19
+ $this->render_intro( array() );
20
+ }
21
+
22
+
23
+
24
+ private function render_intro( $details ) {
25
+ $config = Dispatcher::config();
26
+ $domain = '';
27
+ $domains = $config->get_array('cdn.limelight.host.domains');
28
+ if ( count( $domains ) > 0 ) {
29
+ $domain = $domains[0];
30
+ }
31
+
32
+ include W3TC_DIR . '/Cdn_LimeLight_Popup_View_Intro.php';
33
+ exit();
34
+ }
35
+
36
+
37
+
38
+ public function w3tc_ajax_cdn_limelight_save() {
39
+ $short_name = $_REQUEST['short_name'];
40
+ $username = $_REQUEST['username'];
41
+ $api_key = $_REQUEST['api_key'];
42
+ $domain = $_REQUEST['domain'];
43
+
44
+ try {
45
+ $api = new Cdnfsd_LimeLight_Api( $short_name, $username, $api_key );
46
+ $url = ( Util_Environment::is_https() ? 'https://' : 'http://' ) . $domain . '/test';
47
+
48
+ $items = array(
49
+ array(
50
+ 'pattern' => $url,
51
+ 'exact' => true,
52
+ 'evict' => false,
53
+ 'incqs' => false
54
+ )
55
+ );
56
+
57
+ $api->purge( $items );
58
+ } catch ( \Exception $ex ) {
59
+ $this->render_intro( array(
60
+ 'error_message' => 'Failed to make test purge request: ' . $ex->getMessage()
61
+ ) );
62
+ exit();
63
+ }
64
+
65
+ $c = Dispatcher::config();
66
+ $c->set( 'cdn.limelight.short_name', $short_name );
67
+ $c->set( 'cdn.limelight.username', $username );
68
+ $c->set( 'cdn.limelight.api_key', $api_key );
69
+ $c->set( 'cdn.limelight.host.domains', array( $domain ) );
70
+ $c->save();
71
+
72
+ include W3TC_DIR . '/Cdn_LimeLight_Popup_View_Success.php';
73
+ exit();
74
+ }
75
+ }
Cdn_LimeLight_Popup_View_Intro.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_popup_form">
8
+ <?php
9
+ if ( isset( $details['error_message'] ) )
10
+ echo '<div class="error">' . $details['error_message'] . '</div>';
11
+ ?>
12
+ <div class="metabox-holder">
13
+ <?php Util_Ui::postbox_header(
14
+ __( 'Your LimeLight Account credentials', 'w3-total-cache' ) ); ?>
15
+ <table class="form-table">
16
+ <tr>
17
+ <td>Account Short Name:</td>
18
+ <td>
19
+ <input name="short_name" type="text" class="w3tc-ignore-change"
20
+ style="width: 550px"
21
+ value="<?php echo $config->get_string( 'cdn.limelight.short_name' ) ?>" />
22
+ </td>
23
+ </tr>
24
+ <tr>
25
+ <td>Username:</td>
26
+ <td>
27
+ <input name="username" type="text" class="w3tc-ignore-change"
28
+ style="width: 550px"
29
+ value="<?php echo $config->get_string( 'cdn.limelight.username' ) ?>" />
30
+ </td>
31
+ </tr>
32
+ <tr>
33
+ <td>API Key:</td>
34
+ <td>
35
+ <input name="api_key" type="text" class="w3tc-ignore-change"
36
+ style="width: 550px"
37
+ value="<?php echo $config->get_string( 'cdn.limelight.api_key' ) ?>" />
38
+ </td>
39
+ </tr>
40
+ <tr>
41
+ <td>CDN hostname:</td>
42
+ <td>
43
+ <input name="domain" type="text" class="w3tc-ignore-change"
44
+ style="width: 550px"
45
+ value="<?php echo esc_attr($domain) ?>" />
46
+ </td>
47
+ </tr>
48
+ </table>
49
+
50
+ <p class="submit">
51
+ <input type="button"
52
+ class="w3tc_cdn_limelight_save w3tc-button-save button-primary"
53
+ value="<?php _e( 'Next', 'w3-total-cache' ); ?>" />
54
+ </p>
55
+ <?php Util_Ui::postbox_footer(); ?>
56
+ </div>
57
+ </form>
Cdn_LimeLight_Popup_View_Success.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_popup_form">
8
+ <div class="metabox-holder">
9
+ <?php Util_Ui::postbox_header(
10
+ __( 'Succeeded', 'w3-total-cache' ) ); ?>
11
+
12
+ <div style="text-align: center">
13
+ Plugin was successfully configured to use this service.<br />
14
+ Make sure you have updated domain DNS records.
15
+ <p class="submit">
16
+ <input type="button"
17
+ class="w3tc_cdn_limelight_done w3tc-button-save button-primary"
18
+ value="<?php _e( 'Done', 'w3-total-cache' ); ?>" />
19
+ </p>
20
+ <?php Util_Ui::postbox_footer(); ?>
21
+ </div>
22
+ </form>
Cdn_MaxCdn_Page_View.js CHANGED
@@ -59,10 +59,4 @@ jQuery(function($) {
59
  // refresh page
60
  window.location = window.location + '&';
61
  })
62
-
63
-
64
-
65
- .on('size_change', '#cdn_cname_add', function() {
66
- w3tc_maxcdn_resize(W3tc_Lightbox);
67
- })
68
  });
59
  // refresh page
60
  window.location = window.location + '&';
61
  })
 
 
 
 
 
 
62
  });
Cdn_MaxCdn_Popup.php CHANGED
@@ -239,11 +239,11 @@ class Cdn_MaxCdn_Popup {
239
  echo 'currently set to <strong>';
240
  echo htmlspecialchars( $details[$field]['current'] );
241
  echo '</strong><br />';
242
- echo '<input type="checkbox" name="' . $field . '_change" value="y"' .
243
  ' checked="checked" /> ';
244
  echo 'change to <strong>';
245
  echo htmlspecialchars( $details[$field]['new'] );
246
- echo '</strong><br />';
247
  }
248
  }
249
 
239
  echo 'currently set to <strong>';
240
  echo htmlspecialchars( $details[$field]['current'] );
241
  echo '</strong><br />';
242
+ echo '<label class="w3tc_change_label"><input type="checkbox" name="' . $field . '_change" value="y"' .
243
  ' checked="checked" /> ';
244
  echo 'change to <strong>';
245
  echo htmlspecialchars( $details[$field]['new'] );
246
+ echo '</strong></label><br />';
247
  }
248
  }
249
 
Cdn_Plugin.php CHANGED
@@ -41,21 +41,6 @@ class Cdn_Plugin {
41
  ) );
42
 
43
  if ( !Cdn_Util::is_engine_mirror( $cdn_engine ) ) {
44
- add_action( 'delete_attachment', array(
45
- $this,
46
- 'delete_attachment'
47
- ) );
48
-
49
- add_filter( 'update_attached_file', array(
50
- $this,
51
- 'update_attached_file'
52
- ) );
53
-
54
- add_filter( 'wp_update_attachment_metadata', array(
55
- $this,
56
- 'update_attachment_metadata'
57
- ) );
58
-
59
  add_action( 'w3_cdn_cron_queue_process', array(
60
  $this,
61
  'cron_queue_process'
@@ -76,12 +61,17 @@ class Cdn_Plugin {
76
  'update_feedback'
77
  ) );
78
 
79
- add_filter( 'wp_prepare_attachment_for_js', array(
80
- $this,
81
- 'wp_prepare_attachment_for_js'
82
- ), 0 );
83
  }
84
 
 
 
 
 
 
 
 
 
 
85
  add_filter( 'w3tc_admin_bar_menu',
86
  array( $this, 'w3tc_admin_bar_menu' ) );
87
 
@@ -91,6 +81,11 @@ class Cdn_Plugin {
91
  add_filter( 'w3tc_module_is_running-cdn', array( $this, 'cdn_is_running' ) );
92
  }
93
 
 
 
 
 
 
94
  /**
95
  * Start rewrite engine
96
  */
@@ -106,35 +101,6 @@ class Cdn_Plugin {
106
  }
107
  }
108
 
109
- /**
110
- * run code for FSD CDN
111
- */
112
- private function run_fsd() {
113
- add_action( 'w3tc_flush_all', array(
114
- '\W3TC\Cdnfsd_CacheFlush',
115
- 'w3tc_flush_all'
116
- ), 3000, 1 );
117
- add_action( 'w3tc_flush_post', array(
118
- '\W3TC\Cdnfsd_CacheFlush',
119
- 'w3tc_flush_post'
120
- ), 3000, 1 );
121
- add_action( 'w3tc_flushable_posts', '__return_true', 3000 );
122
- add_action( 'w3tc_flush_posts', array(
123
- '\W3TC\Cdnfsd_CacheFlush',
124
- 'w3tc_flush_all'
125
- ), 3000 );
126
- add_action( 'w3tc_flush_url', array(
127
- '\W3TC\Cdnfsd_CacheFlush',
128
- 'w3tc_flush_url'
129
- ), 3000, 1 );
130
- add_filter( 'w3tc_flush_execute_delayed_operations', array(
131
- '\W3TC\Cdnfsd_CacheFlush',
132
- 'w3tc_flush_execute_delayed_operations'
133
- ), 3000 );
134
-
135
- Util_AttachToActions::flush_posts_on_actions();
136
- }
137
-
138
  /**
139
  * Instantiates worker with admin functionality on demand
140
  *
@@ -187,7 +153,12 @@ class Cdn_Plugin {
187
 
188
  $results = array();
189
 
190
- $common->upload( $files, true, $results );
 
 
 
 
 
191
 
192
  return $attached_file;
193
  }
@@ -206,7 +177,12 @@ class Cdn_Plugin {
206
 
207
  $results = array();
208
 
209
- $common->delete( $files, true, $results );
 
 
 
 
 
210
  }
211
 
212
  /**
@@ -224,7 +200,12 @@ class Cdn_Plugin {
224
 
225
  $results = array();
226
 
227
- $common->upload( $files, true, $results );
 
 
 
 
 
228
 
229
  return $metadata;
230
  }
41
  ) );
42
 
43
  if ( !Cdn_Util::is_engine_mirror( $cdn_engine ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  add_action( 'w3_cdn_cron_queue_process', array(
45
  $this,
46
  'cron_queue_process'
61
  'update_feedback'
62
  ) );
63
 
 
 
 
 
64
  }
65
 
66
+ add_action( 'delete_attachment',
67
+ array( $this, 'delete_attachment' ) );
68
+
69
+ add_filter( 'update_attached_file',
70
+ array( $this, 'update_attached_file' ) );
71
+
72
+ add_filter( 'wp_update_attachment_metadata',
73
+ array( $this, 'update_attachment_metadata' ) );
74
+
75
  add_filter( 'w3tc_admin_bar_menu',
76
  array( $this, 'w3tc_admin_bar_menu' ) );
77
 
81
  add_filter( 'w3tc_module_is_running-cdn', array( $this, 'cdn_is_running' ) );
82
  }
83
 
84
+ if ( !is_admin() || $this->_config->get_boolean( 'cdn.admin.media_library' ) ) {
85
+ add_filter( 'wp_prepare_attachment_for_js',
86
+ array( $this, 'wp_prepare_attachment_for_js' ), 0 );
87
+ }
88
+
89
  /**
90
  * Start rewrite engine
91
  */
101
  }
102
  }
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  /**
105
  * Instantiates worker with admin functionality on demand
106
  *
153
 
154
  $results = array();
155
 
156
+ $cdn_engine = $this->_config->get_string( 'cdn.engine' );
157
+ if ( Cdn_Util::is_engine_mirror( $cdn_engine ) ) {
158
+ $common->purge( $files, $results );
159
+ } else {
160
+ $common->upload( $files, true, $results );
161
+ }
162
 
163
  return $attached_file;
164
  }
177
 
178
  $results = array();
179
 
180
+ $cdn_engine = $this->_config->get_string( 'cdn.engine' );
181
+ if ( Cdn_Util::is_engine_mirror( $cdn_engine ) ) {
182
+ $common->purge( $files, $results );
183
+ } else {
184
+ $common->delete( $files, true, $results );
185
+ }
186
  }
187
 
188
  /**
200
 
201
  $results = array();
202
 
203
+ $cdn_engine = $this->_config->get_string( 'cdn.engine' );
204
+ if ( Cdn_Util::is_engine_mirror( $cdn_engine ) ) {
205
+ $common->purge( $files, $results );
206
+ } else {
207
+ $common->upload( $files, true, $results );
208
+ }
209
 
210
  return $metadata;
211
  }
Cdn_Plugin_Admin.php CHANGED
@@ -51,6 +51,17 @@ class Cdn_Plugin_Admin {
51
  add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
52
  '\W3TC\Cdn_Highwinds_Page',
53
  'w3tc_settings_cdn_boxarea_configuration' ) );
 
 
 
 
 
 
 
 
 
 
 
54
  } elseif ( $cdn_engine == 'maxcdn' ) {
55
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
56
  '\W3TC\Cdn_MaxCdn_Page',
@@ -85,6 +96,23 @@ class Cdn_Plugin_Admin {
85
  add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
86
  '\W3TC\Cdn_RackSpaceCloudFiles_Page',
87
  'w3tc_settings_cdn_boxarea_configuration' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
89
 
90
  add_action( 'w3tc_settings_general_boxarea_cdn', array(
@@ -133,6 +161,10 @@ class Cdn_Plugin_Admin {
133
  'label' => __( 'Highwinds', 'w3-total-cache' ),
134
  'optgroup' => $optgroup_pull
135
  );
 
 
 
 
136
  $engine_values['maxcdn'] = array(
137
  'label' => __( 'MaxCDN', 'w3-total-cache' ),
138
  'optgroup' => $optgroup_pull
@@ -141,6 +173,10 @@ class Cdn_Plugin_Admin {
141
  'label' => __( 'RackSpace CDN', 'w3-total-cache' ),
142
  'optgroup' => $optgroup_pull
143
  );
 
 
 
 
144
  $engine_values['edgecast'] = array(
145
  'label' => __( 'Verizon Digital Media Services (EdgeCast) / Media Temple ProCDN', 'w3-total-cache' ),
146
  'optgroup' => $optgroup_pull
51
  add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
52
  '\W3TC\Cdn_Highwinds_Page',
53
  'w3tc_settings_cdn_boxarea_configuration' ) );
54
+ } elseif ( $cdn_engine == 'limelight' ) {
55
+ add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
56
+ '\W3TC\Cdn_LimeLight_Page',
57
+ 'admin_print_scripts_w3tc_cdn' ) );
58
+ add_action( 'w3tc_ajax', array(
59
+ '\W3TC\Cdn_LimeLight_Popup',
60
+ 'w3tc_ajax' ) );
61
+ add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
62
+ '\W3TC\Cdn_LimeLight_Page',
63
+ 'w3tc_settings_cdn_boxarea_configuration'
64
+ ) );
65
  } elseif ( $cdn_engine == 'maxcdn' ) {
66
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
67
  '\W3TC\Cdn_MaxCdn_Page',
96
  add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
97
  '\W3TC\Cdn_RackSpaceCloudFiles_Page',
98
  'w3tc_settings_cdn_boxarea_configuration' ) );
99
+ } elseif ( $cdn_engine == 'stackpath' ) {
100
+ add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
101
+ '\W3TC\Cdn_StackPath_Page',
102
+ 'admin_print_scripts_w3tc_cdn' ) );
103
+ add_action( 'w3tc_ajax', array(
104
+ '\W3TC\Cdn_StackPath_Popup',
105
+ 'w3tc_ajax' ) );
106
+ add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
107
+ '\W3TC\Cdn_StackPath_Page',
108
+ 'w3tc_settings_cdn_boxarea_configuration'
109
+ ) );
110
+ add_action( 'admin_init_w3tc_dashboard', array(
111
+ '\W3TC\Cdn_StackPath_Widget',
112
+ 'admin_init_w3tc_dashboard' ) );
113
+ add_action( 'w3tc_ajax_cdn_stackpath_widgetdata', array(
114
+ '\W3TC\Cdn_StackPath_Widget',
115
+ 'w3tc_ajax_cdn_stackpath_widgetdata' ) );
116
  }
117
 
118
  add_action( 'w3tc_settings_general_boxarea_cdn', array(
161
  'label' => __( 'Highwinds', 'w3-total-cache' ),
162
  'optgroup' => $optgroup_pull
163
  );
164
+ $engine_values['limelight'] = array(
165
+ 'label' => __( 'LimeLight', 'w3-total-cache' ),
166
+ 'optgroup' => $optgroup_pull
167
+ );
168
  $engine_values['maxcdn'] = array(
169
  'label' => __( 'MaxCDN', 'w3-total-cache' ),
170
  'optgroup' => $optgroup_pull
173
  'label' => __( 'RackSpace CDN', 'w3-total-cache' ),
174
  'optgroup' => $optgroup_pull
175
  );
176
+ $engine_values['stackpath'] = array(
177
+ 'label' => __( 'StackPath', 'w3-total-cache' ),
178
+ 'optgroup' => $optgroup_pull
179
+ );
180
  $engine_values['edgecast'] = array(
181
  'label' => __( 'Verizon Digital Media Services (EdgeCast) / Media Temple ProCDN', 'w3-total-cache' ),
182
  'optgroup' => $optgroup_pull
Cdn_Plugin_WidgetMaxCdn.php CHANGED
@@ -7,9 +7,6 @@ namespace W3TC;
7
  class Cdn_Plugin_WidgetMaxCdn {
8
  private $authorized;
9
  private $have_zone;
10
- private $_sealed;
11
-
12
- private $api;
13
  private $_config = null;
14
 
15
  function __construct() {
@@ -33,63 +30,84 @@ class Cdn_Plugin_WidgetMaxCdn {
33
  ), 100 );
34
 
35
  // Configure authorize and have_zone
36
- $this->_setup( $this->_config );
 
 
 
 
37
 
38
- if ( $this->have_zone && $this->authorized && isset( $_GET['page'] ) && strpos( $_GET['page'], 'w3tc_dashboard' ) !== false ) {
39
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
40
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNAPresentation.php';
41
- $authorization_key = $this->_config->get_string( 'cdn.maxcdn.authorization_key' );
42
- $alias = $consumerkey = $consumersecret = '';
43
- $keys = explode( '+', $authorization_key );
44
- if ( sizeof( $keys ) == 3 )
45
- list( $alias, $consumerkey, $consumersecret ) = $keys;
46
 
47
- $this->api = new \NetDNA( $alias, $consumerkey, $consumersecret );
 
48
 
49
- add_action( 'admin_head', array( $this, 'admin_head' ) );
50
  }
51
  }
52
 
53
- function admin_head() {
 
 
 
 
54
  $zone_id = $this->_config->get_string( 'cdn.maxcdn.zone_id' );
55
- try {
56
- $zone_info = $this->api->get_pull_zone( $zone_id );
57
 
 
 
58
  if ( !$zone_info )
59
- return;
60
- $filetypes = $this->api->get_list_of_file_types_per_zone( $zone_id );
61
 
62
  if ( !isset( $filetypes['filetypes'] ) )
63
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  } catch ( \Exception $ex ) {
65
- return;
66
- }
67
- $filetypes = $filetypes['filetypes'];
68
- $group_hits = \NetDNAPresentation::group_hits_per_filetype_group( $filetypes );
69
-
70
- $list = array();
71
- $colors = array();
72
- foreach ( $group_hits as $group => $hits ) {
73
- $list[] = sprintf( "['%s', %d]", $group, $hits );
74
- $colors[] = '\'' . \NetDNAPresentation::get_file_group_color( $group ) . '\'';
75
  }
76
- ?>
77
- <script type="text/javascript" src="https://www.google.com/jsapi"></script>
78
- <script type="text/javascript">
79
- google.load("visualization", "1", {packages:["corechart"]});
80
- google.setOnLoadCallback(drawChart);
81
- function drawChart() {
82
- var data = google.visualization.arrayToDataTable([
83
- ['Filetype', 'Hits'],<?php
84
- echo " ", implode( ',', $list );
85
- ?>
86
- ]);
87
- var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
88
- var options = {colors: [<?php echo implode( ',', $colors ) ?>]};
89
- chart.draw(data, options);
90
- }
91
- </script>
92
- <?php
93
  }
94
 
95
  /**
@@ -112,70 +130,28 @@ class Cdn_Plugin_WidgetMaxCdn {
112
  * @param array $form_inputs
113
  */
114
  function widget_maxcdn( $widget_id, $form_inputs = array() ) {
115
-
116
- $authorized = $this->authorized;
117
- $have_zone = $this->have_zone;
118
- $error = '';
119
- $no_zone = $this->_config->get_integer( 'cdn.maxcdn.zone_id' ) == 0;
120
- $is_sealed = $this->_sealed;
121
- $pull_zones = array();
122
- $zone_info = false;
123
- if ( $this->authorized && $this->have_zone ) {
124
- $zone_id = $this->_config->get_integer( 'cdn.maxcdn.zone_id' );
125
-
126
- try{
127
- $zone_info = $this->api->get_pull_zone( $zone_id );
128
- } catch ( \Exception $ex ) {
129
- $zone_info = false;
130
- $error = $ex->getMessage();
131
- }
132
-
133
- if ( $zone_info ) {
134
- $content_zone = $zone_info['name'];
135
- try {
136
- $summary = $this->api->get_stats_per_zone( $zone_id );
137
- $filetypes = $this->api->get_list_of_file_types_per_zone( $zone_id );
138
- $popular_files = $this->api->get_list_of_popularfiles_per_zone( $zone_id );
139
- $popular_files = \NetDNAPresentation::format_popular( $popular_files );
140
- $popular_files = array_slice( $popular_files, 0 , 5 );
141
- $account = $this->api->get_account();
142
- $account_status = \NetDNAPresentation::get_account_status( $account['status'] );
143
- include W3TC_INC_WIDGET_DIR . '/maxcdn.php';
144
- } catch ( \Exception $ex ) {
145
- $error = $ex->getMessage();
146
- try {
147
- $pull_zones = $this->api->get_zones_by_url( home_url() );
148
- } catch ( \Exception $ex ) {}
149
- include W3TC_INC_WIDGET_DIR . '/maxcdn_signup.php';
150
- }
151
- } else {
152
- try {
153
- $pull_zones = $this->api->get_zones_by_url( home_url() );
154
- } catch ( \Exception $ex ) {}
155
- include W3TC_INC_WIDGET_DIR . '/maxcdn_signup.php';
156
- }
157
  } else {
158
- include W3TC_INC_WIDGET_DIR . '/maxcdn_signup.php';
 
159
  }
160
  }
161
 
162
- /**
163
- *
164
- *
165
- * @param Config $config
166
- */
167
- private function _setup( $config ) {
168
- $this->authorized = $config->get_string( 'cdn.maxcdn.authorization_key' ) != '' &&
169
- $config->get_string( 'cdn.engine' ) == 'maxcdn';
170
- $keys = explode( '+', $config->get_string( 'cdn.maxcdn.authorization_key' ) );
171
- $this->authorized = $this->authorized && sizeof( $keys ) == 3;
172
 
173
- $this->have_zone = $config->get_string( 'cdn.maxcdn.zone_id' ) != 0;
174
- }
175
 
176
  public function enqueue() {
177
  wp_enqueue_style( 'w3tc-widget' );
 
 
178
  wp_enqueue_script( 'w3tc-metadata' );
179
  wp_enqueue_script( 'w3tc-widget' );
 
 
 
 
 
180
  }
181
  }
7
  class Cdn_Plugin_WidgetMaxCdn {
8
  private $authorized;
9
  private $have_zone;
 
 
 
10
  private $_config = null;
11
 
12
  function __construct() {
30
  ), 100 );
31
 
32
  // Configure authorize and have_zone
33
+ $this->authorized = $this->_config->get_string( 'cdn.maxcdn.authorization_key' ) != '' &&
34
+ $this->_config->get_string( 'cdn.engine' ) == 'maxcdn';
35
+ $keys = explode( '+', $this->_config->get_string( 'cdn.maxcdn.authorization_key' ) );
36
+ $this->authorized = $this->authorized && sizeof( $keys ) == 3;
37
+ $this->have_zone = $this->_config->get_string( 'cdn.maxcdn.zone_id' ) != 0;
38
 
39
+ add_action( 'w3tc_ajax_cdn_maxcdn_widgetdata', array(
40
+ $this, 'w3tc_ajax_cdn_maxcdn_widgetdata' ) );
 
 
 
 
 
 
41
 
42
+ if ( $this->have_zone && $this->authorized && isset( $_GET['page'] ) &&
43
+ strpos( $_GET['page'], 'w3tc_dashboard' ) !== false ) {
44
 
 
45
  }
46
  }
47
 
48
+ function w3tc_ajax_cdn_maxcdn_widgetdata() {
49
+ require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
50
+ require_once W3TC_LIB_NETDNA_DIR . '/NetDNAPresentation.php';
51
+ $api = \NetDNA::create( $this->_config->get_string( 'cdn.maxcdn.authorization_key' ) );
52
+
53
  $zone_id = $this->_config->get_string( 'cdn.maxcdn.zone_id' );
54
+ $response = array();
 
55
 
56
+ try {
57
+ $zone_info = $api->get_pull_zone( $zone_id );
58
  if ( !$zone_info )
59
+ throw new \Exception("Zone not found");
60
+ $filetypes = $api->get_list_of_file_types_per_zone( $zone_id );
61
 
62
  if ( !isset( $filetypes['filetypes'] ) )
63
+ $filetypes['filetypes'] = array();
64
+
65
+ $group_hits = \NetDNAPresentation::group_hits_per_filetype_group(
66
+ $filetypes['filetypes'] );
67
+
68
+ $graph = array( array('Filetype', 'Hits' ) );
69
+ $colors = array();
70
+ foreach ( $group_hits as $group => $hits ) {
71
+ $graph[] = array( $group, $hits );
72
+ $colors[] = \NetDNAPresentation::get_file_group_color( $group );
73
+ }
74
+
75
+ $response['graph'] = $graph;
76
+ $response['colors'] = $colors;
77
+
78
+ $summary = $api->get_stats_per_zone( $zone_id );
79
+
80
+ $response['zone_name'] = $zone_info['name'];
81
+ $response['summary'] = $summary;
82
+ $response['summary_size'] = Util_Ui::format_bytes( $summary['size'] );
83
+ $response['summary_cache_hit'] = $summary['cache_hit'];
84
+ $response['summary_cache_hit_percentage'] = $summary['hit'] ?
85
+ ( $summary['cache_hit'] / $summary['hit'] ) * 100 :
86
+ $summary['hit'];
87
+ $response['summary_noncache_hit'] = $summary['noncache_hit'];
88
+ $response['summary_noncache_hit_percentage'] = $summary['hit'] ?
89
+ ( $summary['noncache_hit'] / $summary['hit'] ) * 100 :
90
+ $summary['hit'];
91
+
92
+ $response['filetypes'] = $filetypes;
93
+ $popular_files = $api->get_list_of_popularfiles_per_zone( $zone_id );
94
+ $popular_files = \NetDNAPresentation::format_popular( $popular_files );
95
+ $response['popular_files'] = array_slice( $popular_files, 0 , 5 );
96
+ for ($n = 0; $n < count( $response['popular_files'] ); $n++) {
97
+ $response['popular_files'][$n]['color'] =
98
+ \NetDNAPresentation::get_file_group_color(
99
+ $response['popular_files'][$n]['group'] );
100
+ }
101
+
102
+ $account = $api->get_account();
103
+ $response['account_status'] = \NetDNAPresentation::get_account_status( $account['status'] );
104
+ $response['url_manage'] = 'https://cp.maxcdn.com/zones/pull/' . $zone_id;
105
+ $response['url_reports'] = 'https://cp.maxcdn.com/reporting/' . $zone_id;
106
  } catch ( \Exception $ex ) {
107
+ $response['error'] = $ex->getMessage();
 
 
 
 
 
 
 
 
 
108
  }
109
+
110
+ echo json_encode( $response );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
 
113
  /**
130
  * @param array $form_inputs
131
  */
132
  function widget_maxcdn( $widget_id, $form_inputs = array() ) {
133
+ if ( $this->authorized && $this->have_zone &&
134
+ $this->_config->get_integer( 'cdn.maxcdn.zone_id' ) ) {
135
+ include dirname( __FILE__ ) . DIRECTORY_SEPARATOR .
136
+ 'Cdn_Plugin_WidgetMaxCdn_View_Authorized.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  } else {
138
+ include dirname( __FILE__ ) . DIRECTORY_SEPARATOR .
139
+ 'Cdn_Plugin_WidgetMaxCdn_View_Unauthorized.php';
140
  }
141
  }
142
 
 
 
 
 
 
 
 
 
 
 
143
 
 
 
144
 
145
  public function enqueue() {
146
  wp_enqueue_style( 'w3tc-widget' );
147
+ wp_enqueue_style( 'w3tc_maxcdn_widget',
148
+ plugins_url( 'Cdn_Plugin_WidgetMaxCdn_View.css', W3TC_FILE ) );
149
  wp_enqueue_script( 'w3tc-metadata' );
150
  wp_enqueue_script( 'w3tc-widget' );
151
+ wp_enqueue_script( 'google-jsapi', 'https://www.google.com/jsapi');
152
+ wp_enqueue_script( 'google-jsapi', 'https://www.google.com/jsapi');
153
+ wp_enqueue_script( 'w3tc_maxcdn_widget',
154
+ plugins_url( 'Cdn_Plugin_WidgetMaxCdn_View.js', W3TC_FILE ),
155
+ array( 'jquery' ), '1.0' );
156
  }
157
  }
Cdn_Plugin_WidgetMaxCdn_View.css ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+
4
+
5
+ .w3tcmaxcdn_h4 {
6
+ text-align: center;
7
+ }
8
+ .w3tcmaxcdn_summary_h4 {
9
+ text-align: center;
10
+ color: #8F8F8F;
11
+ text-align: left;
12
+ margin: 0;
13
+ }
14
+ .w3tcmaxcdn_status,
15
+ .w3tcmaxcdn_summary {
16
+ border-bottom: 1px solid #d2d2d2;
17
+ padding-left: 10px;
18
+ padding-right: 10px;
19
+ }
20
+ .w3tcmaxcdn_wrapper {
21
+ margin-left: -10px;
22
+ margin-right: -10px;
23
+ }
24
+ .w3tcmaxcdn_ul li {
25
+ margin-bottom: 3px;
26
+ padding: 0;
27
+ }
28
+ .w3tcmaxcdn_summary_col1 {
29
+ display: block;
30
+ font-weight: bold;
31
+ width: 90px;
32
+ float:left;
33
+ }
34
+ .w3tcmaxcdn_summary_col2 {
35
+ display: block;
36
+ font-weight: bold;
37
+ width: 80px;
38
+ float:left;
39
+ }
40
+ .w3tcmaxcdn_tools {
41
+ margin-top:15px;
42
+ padding-left: 10px;
43
+ padding-right: 10px;
44
+ }
45
+ .w3tcmaxcdn_tools li {
46
+ display:inline-block;
47
+ margin-right:10px;
48
+ }
49
+ ul.w3tcmaxcdn_file_hits li {
50
+ line-height: 12px;
51
+ font-size:10px;
52
+ }
53
+ ul.w3tcmaxcdn_file_hits li span {
54
+ color: #fff;
55
+ padding-top: 2px;
56
+ padding-left: 5px;
57
+ }
58
+ .w3tcmaxcdn_chart {
59
+ clear: both;
60
+ padding-left: 10px;
61
+ padding-right: 10px;
62
+ }
63
+ .w3tcmaxcdn_status p, .w3tcmaxcdn_chart p {
64
+ color:#8F8F8F;
65
+ margin:0;
66
+ }
67
+
68
+ .w3tcmaxcdn_account_status {
69
+ font-weight: bold;
70
+ color: #000;
71
+ }
72
+ .w3tcmaxcdn_zone_name {
73
+ color: #c0d9e4
74
+ }
75
+
76
+
77
+
78
+ .maxcdn-netdna-widget-base .button-secondary{
79
+ margin-bottom: 3px;
80
+ }
81
+
82
+ .w3tcmaxcdn_signup_h4 {
83
+ text-align: left;
84
+ margin-bottom: 0;
85
+ padding-bottom: 0;
86
+ }
87
+
88
+ .w3tcmaxcdn_signup p{
89
+ margin-top: 4px;
90
+ padding-top: 0;
91
+
92
+ }
93
+ .w3tcmaxcdn_signup p span.desc {
94
+ color:#8F8F8F;
95
+ }
Cdn_Plugin_WidgetMaxCdn_View.js ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var w3tcmaxcdn_graph_data;
2
+
3
+ function w3tcmaxcdn_load() {
4
+ jQuery('.w3tcmaxcdn_loading').removeClass('w3tc_hidden');
5
+ jQuery('.w3tcmaxcdn_content').addClass('w3tc_hidden');
6
+ jQuery('.w3tcmaxcdn_error').addClass('w3tc_none');
7
+
8
+ jQuery.getJSON(ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
9
+ '&w3tc_action=cdn_maxcdn_widgetdata',
10
+ function(data) {
11
+ if (data && data.error) {
12
+ jQuery('.w3tcmaxcdn_error').removeClass('w3tc_none');
13
+ jQuery('.w3tcmaxcdn_error_details').html(data.error);
14
+ jQuery('.w3tcmaxcdn_loading').addClass('w3tc_hidden');
15
+ return;
16
+ }
17
+
18
+ for (p in data) {
19
+ var v = data[p];
20
+ if (p.substr(0, 4) == 'url_')
21
+ jQuery('.w3tcmaxcdn_href_' + p.substr(4)).attr('href', v);
22
+ else
23
+ jQuery('.w3tcmaxcdn_' + p).html(v);
24
+ }
25
+
26
+ var chart_data = google.visualization.arrayToDataTable(data.graph);
27
+
28
+ var chart = new google.visualization.PieChart(
29
+ document.getElementById('chart_div'));
30
+ var options = {colors: data.colors};
31
+ chart.draw(chart_data, options);
32
+
33
+ var popuplar_html = '';
34
+ if ( data.popular_files && data.popular_files.length > 0) {
35
+ var compare = data.popular_files[0]['hit'];
36
+ for ( var n = 0; n < data.popular_files.length; n++) {
37
+ var file = data.popular_files[n];
38
+ popuplar_html += '<li>' +
39
+ '<span style="display:inline-block; background-color: ' + file.color +
40
+ ';width: ' + (file.hit / compare * 100 * 0.9) + '%; ' +
41
+ 'min-width:60%" title="' +
42
+ file.title + ' / ' + file.group + ' / ' + file.file + '">' +
43
+ '</span> <span style="color:#000">' + file.hit +
44
+ '</span></li>';
45
+ }
46
+ jQuery('.w3tcmaxcdn_file_hits').html(popuplar_html);
47
+ }
48
+
49
+ jQuery('.w3tcmaxcdn_content').removeClass('w3tc_hidden');
50
+ jQuery('.w3tcmaxcdn_loading').addClass('w3tc_hidden');
51
+ }
52
+ ).fail(function() {
53
+ jQuery('.w3tcmaxcdn_error').removeClass('w3tc_none');
54
+ jQuery('.w3tcmaxcdn_content').addClass('w3tc_hidden');
55
+ jQuery('.w3tcmaxcdn_loading').addClass('w3tc_hidden');
56
+ });
57
+ }
58
+
59
+
60
+
61
+ google.load("visualization", "1", {packages:["corechart"]});
62
+ google.setOnLoadCallback(w3tcmaxcdn_load);
Cdn_Plugin_WidgetMaxCdn_View_Authorized.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ /**
8
+ *
9
+ *
10
+ * @var int $zone_id
11
+ * @var array $summary
12
+ * @var array $popular_files
13
+ * @var string $content_zone
14
+ * @var string $account_status
15
+ */
16
+
17
+ ?>
18
+ <div class="w3tcmaxcdn_loading w3tc_loading w3tc_hidden">Loading...</div>
19
+ <div class="w3tcmaxcdn_error w3tc_none">
20
+ An error occurred
21
+ <div class="w3tcmaxcdn_error_details"></div>
22
+ </div>
23
+
24
+ <div id="maxcdn-widget" class="maxcdn-netdna-widget-base w3tcmaxcdn_content w3tc_hidden">
25
+ <div class="w3tcmaxcdn_wrapper">
26
+ <div class="w3tcmaxcdn_status">
27
+ <p>
28
+ <span>
29
+ <?php _e( 'Status', 'w3-total-cache' ) ?>
30
+ <span class="w3tcmaxcdn_account_status"></span>
31
+ </span>
32
+ <span style="display:inline-block;float:right">
33
+ <?php _e( 'Content Zone:', 'w3-total-cache' ) ?>
34
+ <span class="w3tcmaxcdn_zone_name"></span>
35
+ </span>
36
+ </p>
37
+
38
+ </div>
39
+ <div class="w3tcmaxcdn_tools">
40
+ <ul class="w3tcmaxcdn_ul">
41
+ <li><a class="button w3tcmaxcdn_href_manage" href=""><?php _e( 'Manage', 'w3-total-cache' )?></a></li>
42
+ <li><a class="button w3tcmaxcdn_href_reports" href=""><?php _e( 'Reports', 'w3-total-cache' )?></a></li>
43
+ <li><a class="button" href="<?php echo wp_nonce_url( admin_url( 'admin.php?page=w3tc_cdn&amp;w3tc_cdn_purge' ) )?>" onclick="w3tc_popupadmin_bar(this.href); return false"><?php _e( 'Purge', 'w3-total-cache' )?></a></li>
44
+ </ul>
45
+ </div>
46
+ <div class="w3tcmaxcdn_summary">
47
+ <h4 class="w3tcmaxcdn_summary_h4"><?php _e( 'Report - 30 days', 'w3-total-cache' ) ?></h4>
48
+ </div>
49
+ <ul class="w3tcmaxcdn_ul">
50
+ <li>
51
+ <span class="w3tcmaxcdn_summary_col1"><?php _e('Transferred', 'w3-total-cache') ?>:</span>
52
+ <span class="w3tcmaxcdn_summary_col2 w3tcmaxcdn_summary_size"></span>
53
+ </li>
54
+ <li>
55
+ <span class="w3tcmaxcdn_summary_col1"><?php _e('Cache Hits', 'w3-total-cache' ) ?>:</span>
56
+ <span class="w3tcmaxcdn_summary_col2">
57
+ <span class="w3tcmaxcdn_summary_cache_hit"></span>
58
+ (<span class="w3tcmaxcdn_summary_cache_hit_percentage"></span>)
59
+ </span>
60
+ </li>
61
+ <li>
62
+ <span class="w3tcmaxcdn_summary_col1"><?php _e('Cache Misses', 'w3-total-cache') ?>:</span>
63
+ <span class="w3tcmaxcdn_summary_col2">
64
+ <span class="w3tcmaxcdn_summary_noncache_hit">
65
+ (<span class="w3tcmaxcdn_summary_noncache_hit_percentage"></span>)
66
+ </span>
67
+ </li>
68
+ </ul>
69
+ <div class="w3tcmaxcdn_chart charts w3tcmaxcdn_area">
70
+ <h4 class="w3tcmaxcdn_h4"><?php _e( 'Requests', 'w3-total-cache' ) ?></h4>
71
+ <div id="chart_div" style="width: 320px; height: 220px;margin-left: auto ; margin-right: auto ;"></div>
72
+ <h4 class="w3tcmaxcdn_h4"><?php _e( 'Content Breakdown', 'w3-total-cache' ) ?></h4>
73
+ <p>
74
+ <span><?php _e( 'File', 'w3-total-cache' )?></span>
75
+ <span style="display:inline-block;float:right"><?php _e( 'Hits', 'w3-total-cache' ) ?></span>
76
+ </p>
77
+ <ul class="w3tcmaxcdn_file_hits">
78
+ <li>A</li>
79
+ <li>A</li>
80
+ <li>A</li>
81
+ <li>A</li>
82
+ <li>A</li>
83
+ </ul>
84
+ </div>
85
+ </div>
86
+ </div>
Cdn_Plugin_WidgetMaxCdn_View_Unauthorized.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <div id="maxcdn-widget" class="w3tcmaxcdn_signup">
9
+ <p><?php _e( 'Dramatically increase website speeds in just a few clicks! Add the MaxCDN content delivery network service to your site.', 'w3-total-cache' )?></p>
10
+ <h4 class="w3tcmaxcdn_signup_h4"><?php _e( 'New customers', 'w3-total-cache' )?></h4>
11
+ <p><?php _e( 'MaxCDN works magically with W3 Total Cache.', 'w3-total-cache' )?></p>
12
+ <a class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_maxcdn_signup' ), 'w3tc' )?>" target="_blank"><?php _e( 'Sign Up Now and Save 25%', 'w3-total-cache' )?></a>
13
+ <p><span class="desc"><?php _e( '100% Money Back Guarantee (30 Days)', 'w3-total-cache' )?></span></p>
14
+ <h4 class="w3tcmaxcdn_signup_h4"><?php _e( 'Current customers', 'w3-total-cache' )?></h4>
15
+ <p><?php _e( "Existing MaxCDN customers, enable <acronym title='Content Delivery Network'>CDN</acronym> and:", 'w3-total-cache' )?></p>
16
+ <a class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_cdn' ), 'w3tc' )?>" target="_blank"><?php _e( 'Authorize', 'w3-total-cache' )?></a>
17
+ </div>
Cdn_StackPath_Api.php ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ require_once(W3TC_LIB_DIR . '/OAuth/W3tcOAuth.php');
5
+ require_once(W3TC_LIB_DIR . '/NetDNA/W3tcWpHttpException.php');
6
+
7
+ /**
8
+ * StackPath REST Client Library
9
+ */
10
+ class Cdn_StackPath_Api {
11
+ private $alias;
12
+ private $key;
13
+ private $secret;
14
+ private $netdnarws_url = 'https://api.stackpath.com/v1';
15
+
16
+
17
+
18
+ static public function create( $authorization_key ) {
19
+ $keys = explode( '+', $authorization_key );
20
+ $alias = '';
21
+ $consumerkey = '';
22
+ $consumersecret = '';
23
+
24
+ if ( sizeof( $keys ) == 3 ) {
25
+ list( $alias, $consumerkey, $consumersecret ) = $keys;
26
+ }
27
+
28
+ $api = new Cdn_StackPath_Api( $alias, $consumerkey, $consumersecret,
29
+ $endpoint );
30
+ return $api;
31
+ }
32
+
33
+ public function __construct( $alias, $key, $secret ) {
34
+ $this->alias = $alias;
35
+ $this->key = $key;
36
+ $this->secret = $secret;
37
+ }
38
+
39
+ public function is_valid() {
40
+ return !empty( $this->alias ) && !empty( $this->key ) &&
41
+ !empty( $this->secret );
42
+ }
43
+
44
+ private function execute( $selected_call, $method_type, $params ) {
45
+ //increase the http request timeout
46
+ add_filter( 'http_request_timeout', array( $this, 'filter_timeout_time' ) );
47
+ add_filter( 'https_ssl_verify', array( $this, 'https_ssl_verify' ) );
48
+
49
+ $consumer = new \W3tcOAuthConsumer( $this->key, $this->secret, NULL );
50
+
51
+ // the endpoint for your request
52
+ $endpoint = "$this->netdnarws_url/$this->alias$selected_call";
53
+
54
+ //parse endpoint before creating OAuth request
55
+ $parsed = parse_url( $endpoint );
56
+ if ( array_key_exists( "parsed", $parsed ) ) {
57
+ parse_str( $parsed['query'], $params );
58
+ }
59
+
60
+ //generate a request from your consumer
61
+ $req_req = \W3tcOAuthRequest::from_consumer_and_token(
62
+ $consumer, NULL, $method_type, $endpoint, $params );
63
+
64
+ //sign your OAuth request using hmac_sha1
65
+ $sig_method = new \W3tcOAuthSignatureMethod_HMAC_SHA1();
66
+ $req_req->sign_request( $sig_method, $consumer, NULL );
67
+
68
+ $request = array();
69
+ $request['sslverify'] = false;
70
+ $request['method'] = $method_type;
71
+
72
+ if ( $method_type == "POST" || $method_type == "PUT" ) {
73
+ $request['body'] = $req_req->to_postdata();
74
+ $request['headers']['Content-Type'] =
75
+ 'application/x-www-form-urlencoded; charset=' .
76
+ get_option('blog_charset');
77
+
78
+ $url = $req_req->get_normalized_http_url();
79
+ } else {
80
+ // notice GET, PUT and DELETE both needs to be passed in URL
81
+ $url = $req_req->to_url();
82
+ }
83
+
84
+ $response = wp_remote_request( $url, $request );
85
+
86
+ $json_output = '';
87
+ if ( !is_wp_error( $response ) ) {
88
+ // make call
89
+ $result = wp_remote_retrieve_body( $response );
90
+ $headers = wp_remote_retrieve_headers( $response );
91
+ $response_code = wp_remote_retrieve_response_code( $response );
92
+ // $json_output contains the output string
93
+ $json_output = $result;
94
+ } else {
95
+ $response_code = $response->get_error_code();
96
+ }
97
+
98
+ remove_filter( 'https_ssl_verify', array( $this, 'https_ssl_verify' ) );
99
+ remove_filter( 'http_request_timeout', array( $this, 'filter_timeout_time' ) );
100
+
101
+ // catch errors
102
+ if ( is_wp_error( $response ) ) {
103
+ throw new \W3tcWpHttpException(
104
+ "ERROR: {$response->get_error_message()}, Output: $json_output",
105
+ $response_code, null, $headers );
106
+ }
107
+
108
+ return $json_output;
109
+ }
110
+
111
+ /**
112
+ * Increase http request timeout to 60 seconds
113
+ */
114
+ public function filter_timeout_time($time) {
115
+ return 600;
116
+ }
117
+
118
+ /**
119
+ * Don't check certificate, some users have limited CA list
120
+ */
121
+ public function https_ssl_verify($v) {
122
+ return false;
123
+ }
124
+
125
+ private function execute_await_200( $selected_call, $method_type, $params ) {
126
+ $r = json_decode( $this->execute( $selected_call, $method_type, $params ),
127
+ true );
128
+ if ( !preg_match( '(200|201)', $r['code'] ) ) {
129
+ throw $this->to_exception( $r );
130
+ }
131
+ return $r;
132
+ }
133
+
134
+ private function get( $selected_call, $params = array() ) {
135
+ return $this->execute_await_200( $selected_call, 'GET', $params );
136
+ }
137
+
138
+ private function post( $selected_call, $params = array() ) {
139
+ return $this->execute_await_200( $selected_call, 'POST', $params );
140
+ }
141
+
142
+ private function put( $selected_call, $params = array() ) {
143
+ return $this->execute_await_200( $selected_call, 'PUT', $params );
144
+ }
145
+
146
+ private function delete( $selected_call, $params = array() ) {
147
+ return $this->execute_await_200( $selected_call, 'DELETE', $params );
148
+ }
149
+
150
+ private function to_exception($response) {
151
+ if ( isset( $response['error']['message'] ) ) {
152
+ $message = $response['error']['message'];
153
+ } else {
154
+ $message = 'Failed to communicate with StackPath';
155
+ }
156
+
157
+ if ( isset( $response['data'] ) && isset( $response['data']['errors'] ) ) {
158
+ foreach ( $response['data']['errors'] as $field => $error ) {
159
+ if ( isset( $error['error'] ) ) {
160
+ $message .= '. ' . $field . ': ' . $error['error'];
161
+ } else {
162
+ $message .= '. ' . $field . ': ' . $error;
163
+ }
164
+ }
165
+ }
166
+
167
+ return new \W3tcWpHttpException($message);
168
+ }
169
+
170
+ public function get_sites() {
171
+ $r = $this->get( '/sites' );
172
+ $zones = array();
173
+ foreach ( $r ['data']['zones'] as $zone ) {
174
+ $zones[] = $zone;
175
+ }
176
+
177
+ return $zones;
178
+ }
179
+
180
+ public function create_site($zone) {
181
+ $r = $this->post( '/sites', $zone );
182
+ return $r['data']['pullzone'];
183
+ }
184
+
185
+ public function update_site( $zone_id, $zone ) {
186
+ $r = $this->put( "/sites/$zone_id", $zone );
187
+ return $r['data']['pullzone'];
188
+ }
189
+
190
+ public function get_site( $zone_id ) {
191
+ $r = $this->get( "/sites/$zone_id" );
192
+ return $r['data']['pullzone'];
193
+ }
194
+
195
+ public function get_custom_domains($zone_id) {
196
+ $r = $this->get( "/sites/$zone_id/customdomains" );
197
+ $domains = array();
198
+ foreach ($r['data']['customdomains'] as $domain) {
199
+ $domains[] = $domain['custom_domain'];
200
+ }
201
+
202
+ return $domains;
203
+ }
204
+
205
+ public function delete_site_cache( $zone_id, $files_to_pass = null ) {
206
+ $params = array();
207
+ if ( !empty( $files_to_pass ) ) {
208
+ $params['files'] = $files_to_pass;
209
+ }
210
+
211
+ $r = $this->delete("/sites/$zone_id/cache", $params );
212
+ return true;
213
+ }
214
+
215
+ public function get_stats_per_zone($zone_id) {
216
+ $r = $this->get( "/reports/{$zone_id}/stats");
217
+ return $r['data']['summary'];
218
+ }
219
+
220
+ public function get_list_of_file_types_per_zone( $zone_id ) {
221
+ $r = $this->get( "/reports/{$zone_id}/filetypes" );
222
+ $stats = array(
223
+ 'total' => $r['data']['total'],
224
+ 'filetypes' => array()
225
+ );
226
+
227
+ foreach( $r['data']['filetypes'] as $filetyp ) {
228
+ $stats['filetypes'][] = $filetyp;
229
+ }
230
+ $stats['summary'] = $r['data']['summary'];
231
+ return $stats;
232
+ }
233
+
234
+ public function get_list_of_popularfiles_per_zone($zone_id) {
235
+ $r = $this->get( "/reports/{$zone_id}/popularfiles" );
236
+ return $r['data']['popularfiles'];
237
+ }
238
+
239
+ public function get_account() {
240
+ $r = $this->get( "/account" );
241
+ return $r['data']['account'];
242
+ }
243
+
244
+ public function create_custom_domain( $zone_id, $custom_domain ) {
245
+ $custom_domain = $this->post( "/sites/$zone_id/customdomains",
246
+ array( 'custom_domain' => $custom_domain) );
247
+ return $custom_domain;
248
+ }
249
+ }
Cdn_StackPath_Page.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdn_StackPath_Page {
7
+ // called from plugin-admin
8
+ static public function admin_print_scripts_w3tc_cdn() {
9
+ wp_enqueue_script( 'w3tc_cdn_stackpath',
10
+ plugins_url( 'Cdn_StackPath_Page_View.js', W3TC_FILE ),
11
+ array( 'jquery' ), '1.0' );
12
+ }
13
+
14
+
15
+
16
+ static public function w3tc_settings_cdn_boxarea_configuration() {
17
+ $config = Dispatcher::config();
18
+ $key = $config->get_string( 'cdn.stackpath.authorization_key' );
19
+ $zone = $config->get_string( 'cdn.stackpath.zone_id' );
20
+ $domains = $config->get_array( 'cdn.stackpath.domain' );
21
+
22
+ $authorized = !empty( $key ) && !empty( $zone );
23
+ $http_domain = isset( $domains['http_default'] ) ? $domains['http_default'] : null;
24
+ $https_domain = isset( $domains['https_default'] ) ? $domains['https_default'] : null;
25
+
26
+ include W3TC_DIR . '/Cdn_StackPath_Page_View.php';
27
+ }
28
+ }
Cdn_StackPath_Page_View.js ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ function w3tc_stackpath_resize(o) {
3
+ o.options.height = jQuery('.w3tc_cdn_stackpath_form').height();
4
+ o.resize();
5
+ }
6
+
7
+ $('body')
8
+ .on('click', '.w3tc_cdn_stackpath_authorize', function() {
9
+ W3tc_Lightbox.open({
10
+ id:'w3tc-overlay',
11
+ close: '',
12
+ width: 800,
13
+ height: 300,
14
+ url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
15
+ '&w3tc_action=cdn_stackpath_intro',
16
+ callback: w3tc_stackpath_resize
17
+ });
18
+ })
19
+
20
+
21
+
22
+ .on('click', '.w3tc_cdn_stackpath_list_zones', function() {
23
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
24
+ '&w3tc_action=cdn_stackpath_list_zones';
25
+
26
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_stackpath_form', w3tc_stackpath_resize);
27
+ })
28
+
29
+
30
+
31
+ .on('click', '.w3tc_cdn_stackpath_view_zone', function() {
32
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
33
+ '&w3tc_action=cdn_stackpath_view_zone';
34
+
35
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_stackpath_form', w3tc_stackpath_resize);
36
+ })
37
+
38
+
39
+
40
+ .on('click', '.w3tc_cdn_stackpath_configure_zone', function() {
41
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
42
+ '&w3tc_action=cdn_stackpath_configure_zone';
43
+
44
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_stackpath_form', w3tc_stackpath_resize);
45
+ })
46
+
47
+
48
+
49
+ .on('click', '.w3tc_cdn_stackpath_configure_zone_skip', function() {
50
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
51
+ '&w3tc_action=cdn_stackpath_configure_zone_skip';
52
+
53
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_stackpath_form', w3tc_stackpath_resize);
54
+ })
55
+
56
+
57
+
58
+ .on('click', '.w3tc_cdn_stackpath_done', function() {
59
+ // refresh page
60
+ window.location = window.location + '&';
61
+ })
62
+ });
Cdn_StackPath_Page_View.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <?php if ( !$authorized ): ?>
9
+ <tr>
10
+ <th style="width: 300px;"><label><?php _e( 'Create account:', 'w3-total-cache' )?></label></th>
11
+ <td>
12
+ <a href="<?php esc_attr_e( STACKPATH_SIGNUP_URL )?>" target="_blank" id="netdna-stackpath-create-account" class="button-primary"><?php _e( 'Sign Up Now and Save', 'w3-total-cache' ) ?></a>
13
+ <br />
14
+ <span class="description"><?php _e( 'StackPath is a service that lets you speed up your site even more with W3 Total Cache. 100% Money Back Guarantee (30 Days)!', 'w3-total-cache' )?></span>
15
+ </td>
16
+ </tr>
17
+ <?php endif ?>
18
+
19
+
20
+
21
+ <tr>
22
+ <th style="width: 300px;">
23
+ <label>
24
+ <?php _e( 'Specify account credentials:', 'w3-total-cache' ); ?>
25
+ </label>
26
+ </th>
27
+ <td>
28
+ <?php if ( $authorized ): ?>
29
+ <input class="w3tc_cdn_stackpath_authorize button-primary"
30
+ type="button"
31
+ value="<?php _e( 'Reauthorize', 'w3-total-cache' ); ?>"
32
+ />
33
+ <?php else: ?>
34
+ <input class="w3tc_cdn_stackpath_authorize button-primary"
35
+ type="button"
36
+ value="<?php _e( 'Authorize', 'w3-total-cache' ); ?>"
37
+ />
38
+ <?php endif ?>
39
+ </td>
40
+ </tr>
41
+
42
+ <?php if ( $authorized ): ?>
43
+ <?php if ( !is_null( $http_domain ) ): ?>
44
+ <tr>
45
+ <th>
46
+ <label><?php _e( '<acronym title="Content Delivery Network">CDN</acronym> HTTP CNAME:', 'w3-total-cache' ); ?></label>
47
+ </th>
48
+ <td class="w3tc_config_value_text">
49
+ <?php echo htmlspecialchars( $http_domain ) ?><br />
50
+ <span class="description">
51
+ This website domain has to be CNAME pointing to this
52
+ <acronym title="Content Delivery Network">CDN</acronym> domain for HTTP requests
53
+ </span>
54
+ </td>
55
+ </tr>
56
+ <?php endif ?>
57
+ <?php if ( !is_null( $https_domain ) ): ?>
58
+ <tr>
59
+ <th>
60
+ <label><?php _e( '<acronym title="Content Delivery Network">CDN</acronym> HTTPS CNAME:', 'w3-total-cache' ); ?></label>
61
+ </th>
62
+ <td class="w3tc_config_value_text">
63
+ <?php echo htmlspecialchars( $https_domain ) ?><br />
64
+ <span class="description">
65
+ This website domain has to be CNAME pointing to this
66
+ <acronym title="Content Delivery Network">CDN</acronym> domain for HTTPS requests
67
+ </span>
68
+ </td>
69
+ </tr>
70
+ <?php endif ?>
71
+
72
+ <tr>
73
+ <th><label for="cdn_stackpath_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support', 'w3-total-cache' )?>:</label></th>
74
+ <td>
75
+ <select id="cdn_stackpath_ssl" name="cdn__stackpath__ssl" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?>>
76
+ <option value="auto"<?php selected( $config->get_string( 'cdn.stackpath.ssl' ), 'auto' ); ?>><?php _e( 'Auto (determine connection type automatically)', 'w3-total-cache' )?></option>
77
+ <option value="enabled"<?php selected( $config->get_string( 'cdn.stackpath.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' )?></option>
78
+ <option value="disabled"<?php selected( $config->get_string( 'cdn.stackpath.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' )?></option>
79
+ </select>
80
+ <br /><span class="description"><?php _e( 'Some <acronym title="Content Delivery Network">CDN</acronym> providers may or may not support <acronym title="Secure Sockets Layer">SSL</acronym>, contact your vendor for more information.', 'w3-total-cache' )?></span>
81
+ </td>
82
+ </tr>
83
+ <tr>
84
+ <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' )?></th>
85
+ <td>
86
+ <?php $cnames = $config->get_array( 'cdn.stackpath.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
87
+ <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym title="Content Delivery Network">CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' )?></span>
88
+ </td>
89
+ </tr>
90
+ <tr>
91
+ <th colspan="2">
92
+ <input id="cdn_test" class="button {type: 'stackpath', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Test StackPath', 'w3-total-cache' )?>" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
93
+ </th>
94
+ </tr>
95
+
96
+ <?php endif ?>
Cdn_StackPath_Popup.php ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdn_StackPath_Popup {
7
+ static public function w3tc_ajax() {
8
+ $o = new Cdn_StackPath_Popup();
9
+
10
+ add_action( 'w3tc_ajax_cdn_stackpath_intro',
11
+ array( $o, 'w3tc_ajax_cdn_stackpath_intro' ) );
12
+ add_action( 'w3tc_ajax_cdn_stackpath_list_zones',
13
+ array( $o, 'w3tc_ajax_cdn_stackpath_list_zones' ) );
14
+ add_action( 'w3tc_ajax_cdn_stackpath_view_zone',
15
+ array( $o, 'w3tc_ajax_cdn_stackpath_view_zone' ) );
16
+ add_action( 'w3tc_ajax_cdn_stackpath_configure_zone',
17
+ array( $o, 'w3tc_ajax_cdn_stackpath_configure_zone' ) );
18
+ }
19
+
20
+
21
+
22
+ public function w3tc_ajax_cdn_stackpath_intro() {
23
+ $config = Dispatcher::config();
24
+
25
+ $this->render_intro( array(
26
+ 'api_key' => $config->get_string( 'cdn.stackpath.authorization_key' ) ) );
27
+ }
28
+
29
+
30
+
31
+ private function render_intro( $details ) {
32
+ $config = Dispatcher::config();
33
+ $url_obtain_key = STACKPATH_AUTHORIZE_URL;
34
+
35
+ include W3TC_DIR . '/Cdn_StackPath_Popup_View_Intro.php';
36
+ exit();
37
+ }
38
+
39
+
40
+
41
+ public function w3tc_ajax_cdn_stackpath_list_zones() {
42
+ $api_key = $_REQUEST['api_key'];
43
+
44
+ $api = Cdn_StackPath_Api::create( $api_key );
45
+ if ( !$api->is_valid() ) {
46
+ $this->render_intro( array(
47
+ 'api_key' => $api_key,
48
+ 'error_message' => 'Can\'t authenticate: API key not valid'
49
+ ) );
50
+ exit();
51
+ }
52
+
53
+ try {
54
+ $zones = $api->get_sites();
55
+ } catch ( \Exception $ex ) {
56
+ $error_message = 'Can\'t authenticate: ' . $ex->getMessage();
57
+
58
+ if ( strpos( $error_message, 'not whitelisted' ) > 0 ) {
59
+ $error_message .= '. You can whitelist IP ' .
60
+ '<a target="_blank" href="https://cp.maxcdn.com/account/api/whitelist">here</a>';
61
+ }
62
+ $this->render_intro( array(
63
+ 'api_key' => $api_key,
64
+ 'error_message' => $error_message
65
+ ) );
66
+ exit();
67
+ }
68
+
69
+ $details = array(
70
+ 'api_key' => $api_key,
71
+ 'zones' => $zones
72
+ );
73
+
74
+ include W3TC_DIR . '/Cdn_StackPath_Popup_View_Zones.php';
75
+ exit();
76
+ }
77
+
78
+
79
+
80
+ public function w3tc_ajax_cdn_StackPath_view_zone() {
81
+ $config = Dispatcher::config();
82
+ $api_key = $_REQUEST['api_key'];
83
+ $zone_id = Util_Request::get( 'zone_id', '' );
84
+
85
+ $details = array(
86
+ 'api_key' => $api_key,
87
+ 'zone_id' => $zone_id,
88
+ 'name' => '',
89
+ 'url' => array(
90
+ 'new' => get_home_url() ),
91
+ 'compress' => array(
92
+ 'new' => 1 ),
93
+ 'ssl' => array(
94
+ // off, dedicated, sni, shared
95
+ 'current' => null,
96
+ 'new' => null
97
+ ),
98
+ 'cors_headers' => array(
99
+ 'new' => ( $config->get_boolean( 'cdn.cors_header') ? 0 : 1 ) ),
100
+ 'domains' => array()
101
+ );
102
+
103
+ if ( empty( $zone_id ) ) {
104
+ // create new zone mode
105
+ $details['name'] = Util_Request::get( 'zone_new_name' );
106
+ $details['ssl']['new'] = 'new';
107
+ } else {
108
+ $api = Cdn_StackPath_Api::create( $api_key );
109
+ try {
110
+ $zone = $api->get_site( $zone_id );
111
+ $details['domains']['current'] = $api->get_custom_domains( $zone_id );
112
+ } catch ( \Exception $ex ) {
113
+ $this->render_intro( array(
114
+ 'api_key' => $api_key,
115
+ 'error_message' => 'Can\'t obtain zone: ' . $ex->getMessage()
116
+ ) );
117
+ exit();
118
+ }
119
+
120
+ $details['name'] = $zone['name'];
121
+ $details['compress']['current'] = $zone['compress'];
122
+ $details['cors_headers']['current'] = $zone['cors_headers'];
123
+ if ( $zone['ssl'] ) {
124
+ $details['ssl']['current'] = 'dedicated';
125
+ } elseif ( $zone['ssl_sni'] ) {
126
+ $details['ssl']['current'] = 'sni';
127
+ } elseif ( $zone['sslshared'] ) {
128
+ $details['ssl']['current'] = 'shared';
129
+ } else {
130
+ $details['ssl']['current'] = 'off';
131
+ }
132
+ $details['url']['current'] = $zone['url'];
133
+ }
134
+
135
+
136
+ // ssl is not enabled at maxcdn - offer it
137
+ if ( Util_Environment::is_https() &&
138
+ ( is_null( $details['ssl']['current'] ) ||
139
+ $details['ssl']['current'] == 'off' ) ) {
140
+ $details['ssl']['new'] = 'shared';
141
+ }
142
+
143
+ include W3TC_DIR . '/Cdn_StackPath_Popup_View_Zone.php';
144
+ exit();
145
+ }
146
+
147
+
148
+
149
+ public function w3tc_ajax_cdn_stackpath_configure_zone() {
150
+ $api_key = $_REQUEST['api_key'];
151
+ $zone_id = Util_Request::get( 'zone_id', '' );
152
+
153
+ if ( empty( $zone_id ) ) {
154
+ $zone = array(
155
+ 'name' => Util_Request::get( 'name' ),
156
+ 'label' => Util_Request::get( 'name' ),
157
+ 'url' => Util_Request::get( 'url' ),
158
+ 'use_stale' => 1,
159
+ 'queries' => 1,
160
+ 'compress' => 1,
161
+ 'backend_compress' => 1
162
+ );
163
+ } else {
164
+ $zone = array();
165
+
166
+ if ( isset( $_REQUEST['url_change'] ) ) {
167
+ $zone['url'] = Util_Request::get( 'url' );
168
+ }
169
+ if ( isset( $_REQUEST['compress_change'] ) ) {
170
+ $zone['compress'] = Util_Request::get( 'compress' );
171
+ }
172
+ if ( isset( $_REQUEST['cors_headers_change'] ) ) {
173
+ $zone['cors_headers'] = Util_Request::get( 'cors_headers' );
174
+ }
175
+ if ( Util_Request::get( 'ssl' ) == 'shared' ) {
176
+ $zone['sslshared'] = 1;
177
+ $zone['http2'] = 1;
178
+ }
179
+ }
180
+
181
+ $api = Cdn_StackPath_Api::create( $api_key );
182
+
183
+ try {
184
+ if ( empty( $zone_id ) ) {
185
+ $response = $api->create_site( $zone );
186
+ $zone_id = $response['id'];
187
+ } else {
188
+ if ( count( array_keys( $zone ) ) > 0 ) {
189
+ $response = $api->update_site( $zone_id, $zone );
190
+ }
191
+ }
192
+
193
+ $response = $api->get_site( $zone_id );
194
+ } catch ( \Exception $ex ) {
195
+ $this->render_intro( array(
196
+ 'api_key' => $api_key,
197
+ 'error_message' => 'Failed to configure zone: ' .
198
+ $ex->getMessage()
199
+ ) );
200
+ exit();
201
+ }
202
+
203
+ $c = Dispatcher::config();
204
+ $domains = $c->get( 'cdn.stackpath.domain' );
205
+ $domains['http_default'] = $response['cdn_url'];
206
+ $domains['https_default'] = $response['ssl_url'];
207
+
208
+ $c->set( 'cdn.stackpath.authorization_key', $api_key );
209
+ $c->set( 'cdn.stackpath.zone_id', $zone_id );
210
+ $c->set( 'cdn.stackpath.domain', $domains );
211
+ $c->save();
212
+
213
+ include W3TC_DIR . '/Cdn_StackPath_Popup_View_Success.php';
214
+ exit();
215
+ }
216
+
217
+
218
+
219
+ private function render_zone_textbox_change( $details, $field ) {
220
+ Util_Ui::hidden( '', $field, $details[$field]['new'] );
221
+
222
+ if ( !isset( $details[$field]['current'] ) ) {
223
+ echo 'will be set to <strong>';
224
+ echo htmlspecialchars( $details[$field]['new'] );
225
+ echo '</strong>';
226
+ } elseif ( $details[$field]['current'] == $details[$field]['new'] ) {
227
+ echo '<strong>';
228
+ echo htmlspecialchars( $details[$field]['new'] );
229
+ echo '</strong>';
230
+ } else {
231
+ echo 'currently set to <strong>';
232
+ echo htmlspecialchars( $details[$field]['current'] );
233
+ echo '</strong><br />';
234
+ echo '<label class="w3tc_change_label">';
235
+ echo '<input type="checkbox" name="' . $field . '_change" value="y"' .
236
+ ' checked="checked" /> ';
237
+ echo 'change to <strong>';
238
+ echo htmlspecialchars( $details[$field]['new'] );
239
+ echo '</strong></label><br />';
240
+ }
241
+ }
242
+
243
+
244
+ private function render_zone_boolean_change( $details, $field ) {
245
+ Util_Ui::hidden( '', $field, $details[$field]['new'] );
246
+
247
+ if ( !isset( $details[$field]['current'] ) ) {
248
+ echo 'will be set to <strong>';
249
+ $this->render_zone_boolean( $details[$field]['new'] );
250
+ echo '</strong>';
251
+ } elseif ( $details[$field]['current'] == $details[$field]['new'] ) {
252
+ echo '<strong>';
253
+ $this->render_zone_boolean( $details[$field]['new'] );
254
+ echo '</strong>';
255
+ } else {
256
+ echo 'currently set to <strong>';
257
+ $this->render_zone_boolean( $details[$field]['current'] );
258
+ echo '</strong><br />';
259
+ echo '<label class="w3tc_change_label">';
260
+ echo '<input type="checkbox" name="' . $field . '_change" value="y"' .
261
+ ' checked="checked" /> ';
262
+ echo 'change to <strong>';
263
+ $this->render_zone_boolean( $details[$field]['new'] );
264
+ echo '</strong></label><br />';
265
+ }
266
+ }
267
+
268
+
269
+
270
+ private function render_zone_boolean( $v ) {
271
+ if ( $v == 0 )
272
+ echo 'disabled';
273
+ else
274
+ echo 'enabled';
275
+ }
276
+ }
Cdn_StackPath_Popup_View_Intro.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_cdn_stackpath_form">
8
+ <?php
9
+ if ( isset( $details['error_message'] ) )
10
+ echo '<div class="error">' . $details['error_message'] . '</div>';
11
+ ?>
12
+ <div class="metabox-holder">
13
+ <?php Util_Ui::postbox_header(
14
+ __( 'Your StackPath Account credentials', 'w3-total-cache' ) ); ?>
15
+ <table class="form-table">
16
+ <tr>
17
+ <td>API Key:</td>
18
+ <td>
19
+ <input name="api_key" type="text" class="w3tc-ignore-change"
20
+ style="width: 550px"
21
+ value="<?php echo $details['api_key'] ?>" />
22
+ <br />
23
+ <span class="description">
24
+ To obtain API key you can
25
+ <a target="_blank" href="<?php echo $url_obtain_key ?>">click here</a>,
26
+ log in, and paste the key in above field.
27
+ </span>
28
+ </td>
29
+ </tr>
30
+ </table>
31
+
32
+ <p class="submit">
33
+ <input type="button"
34
+ class="w3tc_cdn_stackpath_list_zones w3tc-button-save button-primary"
35
+ value="<?php _e( 'Next', 'w3-total-cache' ); ?>" />
36
+ </p>
37
+ <?php Util_Ui::postbox_footer(); ?>
38
+ </div>
39
+ </form>
Cdn_StackPath_Popup_View_Success.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_cdn_stackpath_form">
8
+ <div class="metabox-holder">
9
+ <?php Util_Ui::postbox_header(
10
+ __( 'Succeeded', 'w3-total-cache' ) ); ?>
11
+
12
+ <div style="text-align: center">
13
+ Site was successfully configured.<br />
14
+ </div>
15
+
16
+ <p class="submit">
17
+ <input type="button"
18
+ class="w3tc_cdn_stackpath_done w3tc-button-save button-primary"
19
+ value="<?php _e( 'Done', 'w3-total-cache' ); ?>" />
20
+ </p>
21
+ <?php Util_Ui::postbox_footer(); ?>
22
+ </div>
23
+ </form>
Cdn_StackPath_Popup_View_Zone.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_cdn_stackpath_form" method="post">
8
+ <?php
9
+ Util_Ui::hidden( '', 'api_key', $details['api_key'] );
10
+ Util_Ui::hidden( '', 'zone_id', $details['zone_id'] );
11
+ Util_Ui::hidden( '', 'name', $details['name'] );
12
+ ?>
13
+
14
+ <div class="metabox-holder">
15
+ <?php Util_Ui::postbox_header( __( 'Configure zone', 'w3-total-cache' ) ); ?>
16
+ <table class="form-table">
17
+ <tr>
18
+ <th>Name:</th>
19
+ <td><?php echo $details['name'] ?></td>
20
+ </tr>
21
+ <tr>
22
+ <th>Origin URL:</th>
23
+ <td><?php $this->render_zone_textbox_change( $details, 'url' ) ?></td>
24
+ </tr>
25
+ <tr>
26
+ <th>Compress content:</th>
27
+ <td><?php $this->render_zone_boolean_change( $details, 'compress' ) ?></td>
28
+ </tr>
29
+ <tr>
30
+ <th>Add CORS header:</th>
31
+ <td><?php $this->render_zone_boolean_change( $details, 'cors_headers' ) ?></td>
32
+ </tr>
33
+ </table>
34
+
35
+ <p class="submit">
36
+ <input type="button"
37
+ class="w3tc_cdn_stackpath_configure_zone w3tc-button-save button-primary"
38
+ value="<?php _e( 'Apply', 'w3-total-cache' ); ?>" />
39
+ </p>
40
+ <?php Util_Ui::postbox_footer(); ?>
41
+ </div>
42
+ </form>
Cdn_StackPath_Popup_View_Zones.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_cdn_stackpath_form" method="post">
8
+ <?php
9
+ Util_Ui::hidden( '', 'api_key', $details['api_key'] );
10
+ ?>
11
+ <div class="metabox-holder">
12
+ <?php Util_Ui::postbox_header( __( 'Select zone to use', 'w3-total-cache' ) ); ?>
13
+ <table class="form-table">
14
+ <tr>
15
+ <td>Zone:</td>
16
+ <td>
17
+ <?php
18
+ if ( count( $details['zones'] ) > 15 )
19
+ echo '<div style="width: 100%; height: 300px; overflow-y: scroll">';
20
+ ?>
21
+
22
+ <?php foreach ( $details['zones'] as $zone ): ?>
23
+ <label>
24
+ <input name="zone_id" type="radio" class="w3tc-ignore-change"
25
+ value="<?php echo $zone['id'] ?>" />
26
+ <?php echo $zone['name'] ?>
27
+ (<?php echo $zone['cdn_url'] ?>)
28
+ </label><br />
29
+ <?php endforeach ?>
30
+
31
+ <label>
32
+ <input name="zone_id" type="radio" class="w3tc-ignore-change" value=""
33
+ />
34
+ Add new zone:
35
+ </label>
36
+ <input name="zone_new_name" type="text" class="w3tc-ignore-change" />
37
+
38
+ <?php
39
+ if ( count( $details['zones'] ) > 15 )
40
+ echo '</div>';
41
+ ?>
42
+ </td>
43
+ </tr>
44
+ </table>
45
+
46
+ <p class="submit">
47
+ <input type="button"
48
+ class="w3tc_cdn_stackpath_view_zone w3tc-button-save button-primary"
49
+ value="<?php _e( 'Apply', 'w3-total-cache' ); ?>" />
50
+ </p>
51
+ <?php Util_Ui::postbox_footer(); ?>
52
+ </div>
53
+ </form>
Cdn_StackPath_Widget.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class Cdn_StackPath_Widget {
5
+ static public function admin_init_w3tc_dashboard() {
6
+ $o = new Cdn_StackPath_Widget();
7
+ add_action( 'admin_print_styles',
8
+ array( $o, 'admin_print_styles' ) );
9
+ add_action( 'admin_print_scripts',
10
+ array( $o, 'admin_print_scripts' ) );
11
+ add_action( 'w3tc_widget_setup',
12
+ array( $o, 'w3tc_widget_setup' ) );
13
+ }
14
+
15
+
16
+
17
+ public function w3tc_widget_setup() {
18
+ Util_Widget::add( 'w3tc_stackpath',
19
+ '<div class="w3tc-widget-stackpath-logo"></div>',
20
+ array( $this, 'widget_form' ),
21
+ Util_Ui::admin_url( 'admin.php?page=w3tc_cdn' ),
22
+ 'normal' );
23
+ }
24
+
25
+ /**
26
+ * Runs plugin
27
+ */
28
+ function widget_form() {
29
+ $c = Dispatcher::config();
30
+
31
+ // Configure authorize and have_zone
32
+ $authorized = $c->get_string( 'cdn.stackpath.authorization_key' ) != '' &&
33
+ $c->get_string( 'cdn.engine' ) == 'stackpath';
34
+ $keys = explode( '+', $c->get_string( 'cdn.stackpath.authorization_key' ) );
35
+ $authorized = $authorized && sizeof( $keys ) == 3;
36
+ $have_zone = $c->get_string( 'cdn.stackpath.zone_id' ) != 0;
37
+
38
+ if ( $authorized && $have_zone ) {
39
+ include dirname( __FILE__ ) . DIRECTORY_SEPARATOR .
40
+ 'Cdn_StackPath_Widget_View_Authorized.php';
41
+ } else {
42
+ include dirname( __FILE__ ) . DIRECTORY_SEPARATOR .
43
+ 'Cdn_StackPath_Widget_View_Unauthorized.php';
44
+ }
45
+ }
46
+
47
+
48
+
49
+ function w3tc_ajax_cdn_stackpath_widgetdata() {
50
+ $c = Dispatcher::config();
51
+
52
+ require_once W3TC_LIB_NETDNA_DIR . '/NetDNAPresentation.php';
53
+ $api = Cdn_StackPath_Api::create(
54
+ $c->get_string( 'cdn.stackpath.authorization_key' ) );
55
+
56
+ $zone_id = $c->get_string( 'cdn.stackpath.zone_id' );
57
+ $response = array();
58
+
59
+ try {
60
+ $zone_info = $api->get_site( $zone_id );
61
+ if ( !$zone_info )
62
+ throw new \Exception("Zone not found");
63
+ $filetypes = $api->get_list_of_file_types_per_zone( $zone_id );
64
+
65
+ if ( !isset( $filetypes['filetypes'] ) )
66
+ $filetypes['filetypes'] = array();
67
+
68
+ $group_hits = \NetDNAPresentation::group_hits_per_filetype_group(
69
+ $filetypes['filetypes'] );
70
+
71
+ $graph = array( array('Filetype', 'Hits' ) );
72
+ $colors = array();
73
+ foreach ( $group_hits as $group => $hits ) {
74
+ $graph[] = array( $group, $hits );
75
+ $colors[] = \NetDNAPresentation::get_file_group_color( $group );
76
+ }
77
+
78
+ $response['graph'] = $graph;
79
+ $response['colors'] = $colors;
80
+
81
+ $summary = $api->get_stats_per_zone( $zone_id );
82
+
83
+ $response['zone_name'] = $zone_info['name'];
84
+ $response['summary'] = $summary;
85
+ $response['summary_size'] = Util_Ui::format_bytes( $summary['size'] );
86
+ $response['summary_cache_hit'] = $summary['cache_hit'];
87
+ $response['summary_cache_hit_percentage'] = $summary['hit'] ?
88
+ ( $summary['cache_hit'] / $summary['hit'] ) * 100 :
89
+ $summary['hit'];
90
+ $response['summary_noncache_hit'] = $summary['noncache_hit'];
91
+ $response['summary_noncache_hit_percentage'] = $summary['hit'] ?
92
+ ( $summary['noncache_hit'] / $summary['hit'] ) * 100 :
93
+ $summary['hit'];
94
+
95
+ $response['filetypes'] = $filetypes;
96
+ $popular_files = $api->get_list_of_popularfiles_per_zone( $zone_id );
97
+ $popular_files = \NetDNAPresentation::format_popular( $popular_files );
98
+ $response['popular_files'] = array_slice( $popular_files, 0 , 5 );
99
+ for ($n = 0; $n < count( $response['popular_files'] ); $n++) {
100
+ $response['popular_files'][$n]['color'] =
101
+ \NetDNAPresentation::get_file_group_color(
102
+ $response['popular_files'][$n]['group'] );
103
+ }
104
+
105
+ $account = $api->get_account();
106
+ $response['account_status'] = \NetDNAPresentation::get_account_status( $account['status'] );
107
+ $response['url_manage'] = 'https://app.stackpath.com/sites/' .
108
+ $zone_id . '/settings';
109
+ $response['url_reports'] = 'https://app.stackpath.com/reporting/files?zone_id=' .
110
+ $zone_id;
111
+ } catch ( \Exception $ex ) {
112
+ $response['error'] = $ex->getMessage();
113
+ }
114
+
115
+ echo json_encode( $response );
116
+ }
117
+
118
+
119
+
120
+
121
+
122
+ public function admin_print_styles() {
123
+ wp_enqueue_style( 'w3tc-widget' );
124
+ wp_enqueue_style( 'w3tc-stackpath-widget',
125
+ plugins_url( 'Cdn_StackPath_Widget_View.css', W3TC_FILE ),
126
+ array(), W3TC_VERSION );
127
+ }
128
+
129
+
130
+
131
+ public function admin_print_scripts() {
132
+ wp_enqueue_style( 'w3tc-widget' );
133
+ wp_enqueue_script( 'google-jsapi', 'https://www.google.com/jsapi');
134
+ wp_enqueue_script( 'w3tc-stackpath-widget',
135
+ plugins_url( 'Cdn_StackPath_Widget_View.js', W3TC_FILE ),
136
+ array( 'google-jsapi' ), W3TC_VERSION );
137
+ wp_enqueue_script( 'w3tc-metadata' );
138
+ wp_enqueue_script( 'w3tc-widget' );
139
+ }
140
+
141
+ }
Cdn_StackPath_Widget_View.css ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .w3tc-widget-stackpath-logo {
2
+ width: 150px;
3
+ height: 35px;
4
+ background: url("pub/img/w3tc_stackpath-logo.png") 0 5px no-repeat;
5
+ float: left;
6
+ }
7
+
8
+ .w3tcstackpath_h4 {
9
+ text-align: center;
10
+ }
11
+ .w3tcstackpath_summary_h4 {
12
+ text-align: center;
13
+ color: #8F8F8F;
14
+ text-align: left;
15
+ margin: 0;
16
+ }
17
+ .w3tcstackpath_status,
18
+ .w3tcstackpath_summary {
19
+ border-bottom: 1px solid #d2d2d2;
20
+ padding-left: 10px;
21
+ padding-right: 10px;
22
+ }
23
+ .w3tcstackpath_wrapper {
24
+ margin-left: -10px;
25
+ margin-right: -10px;
26
+ }
27
+ .w3tcstackpath_ul li {
28
+ margin-bottom: 3px;
29
+ padding: 0;
30
+ }
31
+ .w3tcstackpath_summary_col1 {
32
+ display: block;
33
+ font-weight: bold;
34
+ width: 90px;
35
+ float:left;
36
+ }
37
+ .w3tcstackpath_summary_col2 {
38
+ display: block;
39
+ font-weight: bold;
40
+ width: 80px;
41
+ float:left;
42
+ }
43
+ .w3tcstackpath_tools {
44
+ margin-top:15px;
45
+ padding-left: 10px;
46
+ padding-right: 10px;
47
+ }
48
+ .w3tcstackpath_tools li {
49
+ display:inline-block;
50
+ margin-right:10px;
51
+ }
52
+ ul.w3tcstackpath_file_hits li {
53
+ line-height: 12px;
54
+ font-size:10px;
55
+ }
56
+ ul.w3tcstackpath_file_hits li span {
57
+ color: #fff;
58
+ padding-top: 2px;
59
+ padding-left: 5px;
60
+ }
61
+ .w3tcstackpath_chart {
62
+ clear: both;
63
+ padding-left: 10px;
64
+ padding-right: 10px;
65
+ }
66
+ .w3tcstackpath_status p, .w3tcstackpath_chart p {
67
+ color:#8F8F8F;
68
+ margin:0;
69
+ }
70
+
71
+ .w3tcstackpath_account_status {
72
+ font-weight: bold;
73
+ color: #000;
74
+ }
75
+ .w3tcstackpath_zone_name {
76
+ color: #c0d9e4
77
+ }
78
+
79
+
80
+
81
+ .w3tcstackpath_wrapper .button-secondary{
82
+ margin-bottom: 3px;
83
+ }
84
+
85
+ .w3tcstackpath_signup_h4 {
86
+ text-align: left;
87
+ margin-bottom: 0;
88
+ padding-bottom: 0;
89
+ }
90
+
91
+ .w3tcstackpath_signup p{
92
+ margin-top: 4px;
93
+ padding-top: 0;
94
+
95
+ }
96
+ .w3tcstackpath_signup p span.desc {
97
+ color:#8F8F8F;
98
+ }
Cdn_StackPath_Widget_View.js ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var w3tcstackpath_graph_data;
2
+
3
+ function w3tcstackpath_load() {
4
+ jQuery('.w3tcstackpath_loading').removeClass('w3tc_hidden');
5
+ jQuery('.w3tcstackpath_content').addClass('w3tc_hidden');
6
+ jQuery('.w3tcstackpath_error').addClass('w3tc_none');
7
+
8
+ jQuery.getJSON(ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
9
+ '&w3tc_action=cdn_stackpath_widgetdata',
10
+ function(data) {
11
+ if (data && data.error) {
12
+ jQuery('.w3tcstackpath_error').removeClass('w3tc_none');
13
+ jQuery('.w3tcstackpath_error_details').html(data.error);
14
+ jQuery('.w3tcstackpath_loading').addClass('w3tc_hidden');
15
+ return;
16
+ }
17
+
18
+ for (p in data) {
19
+ var v = data[p];
20
+ if (p.substr(0, 4) == 'url_')
21
+ jQuery('.w3tcstackpath_href_' + p.substr(4)).attr('href', v);
22
+ else
23
+ jQuery('.w3tcstackpath_' + p).html(v);
24
+ }
25
+
26
+ var chart_data = google.visualization.arrayToDataTable(data.graph);
27
+
28
+ var chart = new google.visualization.PieChart(
29
+ document.getElementById('chart_div'));
30
+ var options = {colors: data.colors};
31
+ chart.draw(chart_data, options);
32
+
33
+ var popuplar_html = '';
34
+ if ( data.popular_files && data.popular_files.length > 0 ) {
35
+ var compare = data.popular_files[0]['hit'];
36
+ for ( var n = 0; n < data.popular_files.length; n++) {
37
+ var file = data.popular_files[n];
38
+ popuplar_html += '<li>' +
39
+ '<span style="display:inline-block; background-color: ' + file.color +
40
+ ';width: ' + (file.hit / compare * 100 * 0.9) + '%; ' +
41
+ 'min-width:60%" title="' +
42
+ file.title + ' / ' + file.group + ' / ' + file.file + '">' +
43
+ '</span> <span style="color:#000">' + file.hit +
44
+ '</span></li>';
45
+ }
46
+ jQuery('.w3tcstackpath_file_hits').html(popuplar_html);
47
+ }
48
+
49
+ jQuery('.w3tcstackpath_content').removeClass('w3tc_hidden');
50
+ jQuery('.w3tcstackpath_loading').addClass('w3tc_hidden');
51
+ }
52
+ ).fail(function() {
53
+ jQuery('.w3tcstackpath_error').removeClass('w3tc_none');
54
+ jQuery('.w3tcstackpath_content').addClass('w3tc_hidden');
55
+ jQuery('.w3tcstackpath_loading').addClass('w3tc_hidden');
56
+ });
57
+ }
58
+
59
+
60
+
61
+ google.load("visualization", "1", {packages:["corechart"]});
62
+ google.setOnLoadCallback(w3tcstackpath_load);
Cdn_StackPath_Widget_View_Authorized.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <div class="w3tcstackpath_loading w3tc_loading w3tc_hidden">Loading...</div>
8
+ <div class="w3tcstackpath_error w3tc_none">
9
+ An error occurred
10
+ <div class="w3tcstackpath_error_details"></div>
11
+ </div>
12
+
13
+ <div id="stackpath-widget" class="stackpath-netdna-widget-base w3tcstackpath_content w3tc_hidden">
14
+ <div class="w3tcstackpath_wrapper">
15
+ <div class="w3tcstackpath_status">
16
+ <p>
17
+ <span>
18
+ <?php _e( 'Status', 'w3-total-cache' ) ?>
19
+ <span class="w3tcstackpath_account_status"></span>
20
+ </span>
21
+ <span style="display:inline-block;float:right">
22
+ <?php _e( 'Content Zone:', 'w3-total-cache' ) ?>
23
+ <span class="w3tcstackpath_zone_name"></span>
24
+ </span>
25
+ </p>
26
+
27
+ </div>
28
+ <div class="w3tcstackpath_tools">
29
+ <ul class="w3tcstackpath_ul">
30
+ <li><a class="button w3tcstackpath_href_manage" href=""><?php _e( 'Manage', 'w3-total-cache' )?></a></li>
31
+ <li><a class="button w3tcstackpath_href_reports" href=""><?php _e( 'Reports', 'w3-total-cache' )?></a></li>
32
+ <li><a class="button" href="<?php echo wp_nonce_url( admin_url( 'admin.php?page=w3tc_cdn&amp;w3tc_cdn_purge' ) )?>" onclick="w3tc_popupadmin_bar(this.href); return false"><?php _e( 'Purge', 'w3-total-cache' )?></a></li>
33
+ </ul>
34
+ </div>
35
+ <div class="w3tcstackpath_summary">
36
+ <h4 class="w3tcstackpath_summary_h4"><?php _e( 'Report - 30 days', 'w3-total-cache' ) ?></h4>
37
+ </div>
38
+ <ul class="w3tcstackpath_ul">
39
+ <li>
40
+ <span class="w3tcstackpath_summary_col1"><?php _e('Transferred', 'w3-total-cache') ?>:</span>
41
+ <span class="w3tcstackpath_summary_col2 w3tcstackpath_summary_size"></span>
42
+ </li>
43
+ <li>
44
+ <span class="w3tcstackpath_summary_col1"><?php _e('Cache Hits', 'w3-total-cache' ) ?>:</span>
45
+ <span class="w3tcstackpath_summary_col2">
46
+ <span class="w3tcstackpath_summary_cache_hit"></span>
47
+ (<span class="w3tcstackpath_summary_cache_hit_percentage"></span>)
48
+ </span>
49
+ </li>
50
+ <li>
51
+ <span class="w3tcstackpath_summary_col1"><?php _e('Cache Misses', 'w3-total-cache') ?>:</span>
52
+ <span class="w3tcstackpath_summary_col2">
53
+ <span class="w3tcstackpath_summary_noncache_hit">
54
+ (<span class="w3tcstackpath_summary_noncache_hit_percentage"></span>)
55
+ </span>
56
+ </li>
57
+ </ul>
58
+ <div class="w3tcstackpath_chart charts w3tcstackpath_area">
59
+ <h4 class="w3tcstackpath_h4"><?php _e( 'Requests', 'w3-total-cache' ) ?></h4>
60
+ <div id="chart_div" style="width: 320px; height: 220px;margin-left: auto ; margin-right: auto ;"></div>
61
+ <h4 class="w3tcstackpath_h4"><?php _e( 'Content Breakdown', 'w3-total-cache' ) ?></h4>
62
+ <p>
63
+ <span><?php _e( 'File', 'w3-total-cache' )?></span>
64
+ <span style="display:inline-block;float:right"><?php _e( 'Hits', 'w3-total-cache' ) ?></span>
65
+ </p>
66
+ <ul class="w3tcstackpath_file_hits">
67
+ <li>A</li>
68
+ <li>A</li>
69
+ <li>A</li>
70
+ <li>A</li>
71
+ <li>A</li>
72
+ </ul>
73
+ </div>
74
+ </div>
75
+ </div>
Cdn_StackPath_Widget_View_Unauthorized.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <div id="stackpath-widget" class="w3tcstackpath_signup">
9
+ <p><?php _e( 'Dramatically increase website speeds in just a few clicks! Add the StackPath content delivery network service to your site.', 'w3-total-cache' )?></p>
10
+ <h4 class="w3tcstackpath_signup_h4"><?php _e( 'New customers', 'w3-total-cache' )?></h4>
11
+ <p><?php _e( 'StackPath works magically with W3 Total Cache.', 'w3-total-cache' )?></p>
12
+ <a class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_stackpath_signup' ), 'w3tc' )?>" target="_blank"><?php _e( 'Sign Up Now ', 'w3-total-cache' )?></a>
13
+ <p><!--span class="desc"><?php _e( '100% Money Back Guarantee (30 Days)', 'w3-total-cache' )?></span></p>-->
14
+ <h4 class="w3tcstackpath_signup_h4"><?php _e( 'Current customers', 'w3-total-cache' )?></h4>
15
+ <p><?php _e( "If you're an existing StackPath customer, enable <acronym title='Content Delivery Network'>CDN</acronym> and:", 'w3-total-cache' )?></p>
16
+ <a class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_cdn' ), 'w3tc' )?>" target="_blank"><?php _e( 'Authorize', 'w3-total-cache' )?></a>
17
+ </div>
Cdn_Util.php CHANGED
@@ -20,12 +20,14 @@ class Cdn_Util {
20
  'ftp',
21
  'google_drive',
22
  'highwinds',
 
23
  'maxcdn',
24
  'mirror',
25
  'rscf',
26
  'rackspace_cdn',
27
  's3',
28
  's3_compatible',
 
29
  ) );
30
  }
31
 
@@ -38,7 +40,8 @@ class Cdn_Util {
38
  static public function is_engine_mirror( $engine ) {
39
  return in_array( $engine, array(
40
  'mirror', 'maxcdn', 'cotendo', 'cf2', 'akamai',
41
- 'edgecast', 'att', 'highwinds', 'rackspace_cdn' ) );
 
42
  }
43
 
44
  static public function is_engine_push( $engine ) {
@@ -57,7 +60,9 @@ class Cdn_Util {
57
  'cotendo',
58
  'edgecast',
59
  'highwinds',
 
60
  'maxcdn',
 
61
  ) );
62
  }
63
 
@@ -78,10 +83,12 @@ class Cdn_Util {
78
  'edgecast',
79
  'ftp',
80
  'highwinds',
 
81
  'maxcdn',
82
  'rscf',
83
  's3',
84
  's3_compatible',
 
85
  ) );
86
  }
87
 
20
  'ftp',
21
  'google_drive',
22
  'highwinds',
23
+ 'limelight',
24
  'maxcdn',
25
  'mirror',
26
  'rscf',
27
  'rackspace_cdn',
28
  's3',
29
  's3_compatible',
30
+ 'stackpath',
31
  ) );
32
  }
33
 
40
  static public function is_engine_mirror( $engine ) {
41
  return in_array( $engine, array(
42
  'mirror', 'maxcdn', 'cotendo', 'cf2', 'akamai',
43
+ 'edgecast', 'att', 'highwinds', 'limelight', 'rackspace_cdn',
44
+ 'stackpath' ) );
45
  }
46
 
47
  static public function is_engine_push( $engine ) {
60
  'cotendo',
61
  'edgecast',
62
  'highwinds',
63
+ 'limelight',
64
  'maxcdn',
65
+ 'stackpath',
66
  ) );
67
  }
68
 
83
  'edgecast',
84
  'ftp',
85
  'highwinds',
86
+ 'limelight',
87
  'maxcdn',
88
  'rscf',
89
  's3',
90
  's3_compatible',
91
+ 'stackpath',
92
  ) );
93
  }
94
 
Cdnfsd_CacheFlush.php CHANGED
@@ -194,12 +194,18 @@ class Cdnfsd_CacheFlush {
194
  static public function w3tc_flush_execute_delayed_operations( $actions_made ) {
195
  $o = Dispatcher::component( 'Cdnfsd_CacheFlush' );
196
 
 
 
 
 
 
 
197
  if ( $o->flush_all_requested ) {
198
  $core = Dispatcher::component( 'Cdnfsd_Core' );
199
- $engine = $core->get_engine();
200
 
201
-
202
  try {
 
 
203
  if ( !is_null( $engine ) ) {
204
  $engine->flush_all();
205
  $actions_made[] = array( 'module' => 'cdn' );
@@ -219,8 +225,10 @@ class Cdnfsd_CacheFlush {
219
  $urls = array_keys( $o->queued_urls );
220
 
221
  $core = Dispatcher::component( 'Cdnfsd_Core' );
222
- $engine = $core->get_engine();
223
  try {
 
 
224
  if ( !is_null( $engine ) ) {
225
  $engine->flush_urls( $urls );
226
  $actions_made[] = array( 'module' => 'cdn' );
194
  static public function w3tc_flush_execute_delayed_operations( $actions_made ) {
195
  $o = Dispatcher::component( 'Cdnfsd_CacheFlush' );
196
 
197
+ // protection from incorrect w3tc upgrade operation when engine gets empty
198
+ $c = Dispatcher::config();
199
+ $engine = $c->get_string( 'cdnfsd.engine' );
200
+ if ( empty( $engine ) )
201
+ return $actions_made;
202
+
203
  if ( $o->flush_all_requested ) {
204
  $core = Dispatcher::component( 'Cdnfsd_Core' );
 
205
 
 
206
  try {
207
+ $engine = $core->get_engine();
208
+
209
  if ( !is_null( $engine ) ) {
210
  $engine->flush_all();
211
  $actions_made[] = array( 'module' => 'cdn' );
225
  $urls = array_keys( $o->queued_urls );
226
 
227
  $core = Dispatcher::component( 'Cdnfsd_Core' );
228
+
229
  try {
230
+ $engine = $core->get_engine();
231
+
232
  if ( !is_null( $engine ) ) {
233
  $engine->flush_urls( $urls );
234
  $actions_made[] = array( 'module' => 'cdn' );
Cdnfsd_Core.php CHANGED
@@ -19,7 +19,7 @@ class Cdnfsd_Core {
19
  case 'cloudflare':
20
  $engine_object = null; // extension handles everything
21
  break;
22
-
23
  case 'cloudfront':
24
  $engine_object = new Cdnfsd_CloudFront_Engine( array(
25
  'access_key' => $c->get_string( 'cdnfsd.cloudfront.access_key' ),
@@ -29,7 +29,7 @@ class Cdnfsd_Core {
29
  break;
30
 
31
  case 'limelight':
32
- $engine_object = new Cdnfsd_Limelight_Engine( array(
33
  'short_name' => $c->get_string( 'cdnfsd.limelight.short_name' ),
34
  'username' => $c->get_string( 'cdnfsd.limelight.username' ),
35
  'api_key' => $c->get_string( 'cdnfsd.limelight.api_key' ),
@@ -44,6 +44,13 @@ class Cdnfsd_Core {
44
  ) );
45
  break;
46
 
 
 
 
 
 
 
 
47
  default:
48
  throw new \Exception( 'unknown engine ' . $engine );
49
  }
19
  case 'cloudflare':
20
  $engine_object = null; // extension handles everything
21
  break;
22
+
23
  case 'cloudfront':
24
  $engine_object = new Cdnfsd_CloudFront_Engine( array(
25
  'access_key' => $c->get_string( 'cdnfsd.cloudfront.access_key' ),
29
  break;
30
 
31
  case 'limelight':
32
+ $engine_object = new Cdnfsd_LimeLight_Engine( array(
33
  'short_name' => $c->get_string( 'cdnfsd.limelight.short_name' ),
34
  'username' => $c->get_string( 'cdnfsd.limelight.username' ),
35
  'api_key' => $c->get_string( 'cdnfsd.limelight.api_key' ),
44
  ) );
45
  break;
46
 
47
+ case 'stackpath':
48
+ $engine_object = new Cdnfsd_StackPath_Engine( array(
49
+ 'api_key' => $c->get_string( 'cdnfsd.stackpath.api_key' ),
50
+ 'zone_id' => $c->get_integer( 'cdnfsd.stackpath.zone_id' )
51
+ ) );
52
+ break;
53
+
54
  default:
55
  throw new \Exception( 'unknown engine ' . $engine );
56
  }
Cdnfsd_Limelight_Api.php → Cdnfsd_LimeLight_Api.php RENAMED
@@ -3,7 +3,7 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Cdnfsd_Limelight_Api {
7
  private $url_base;
8
 
9
 
3
 
4
 
5
 
6
+ class Cdnfsd_LimeLight_Api {
7
  private $url_base;
8
 
9
 
Cdnfsd_Limelight_Engine.php → Cdnfsd_LimeLight_Engine.php RENAMED
@@ -3,7 +3,7 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Cdnfsd_Limelight_Engine {
7
  private $short_name;
8
  private $username;
9
  private $api_key;
@@ -25,7 +25,7 @@ class Cdnfsd_Limelight_Engine {
25
  empty( $this->api_key ) )
26
  throw new \Exception( __( 'Credentials are not specified.', 'w3-total-cache' ) );
27
 
28
- $api = new Cdnfsd_Limelight_Api( $this->short_name, $this->username, $this->api_key );
29
  $items = array();
30
 
31
  foreach ( $urls as $url ) {
@@ -64,7 +64,7 @@ class Cdnfsd_Limelight_Engine {
64
  empty( $this->api_key ) )
65
  throw new \Exception( __( 'Access key not specified.', 'w3-total-cache' ) );
66
 
67
- $api = new Cdnfsd_Limelight_Api( $this->short_name, $this->username, $this->api_key );
68
  $url = Util_Environment::home_domain_root_url() . '/*';
69
 
70
  $items = array(
3
 
4
 
5
 
6
+ class Cdnfsd_LimeLight_Engine {
7
  private $short_name;
8
  private $username;
9
  private $api_key;
25
  empty( $this->api_key ) )
26
  throw new \Exception( __( 'Credentials are not specified.', 'w3-total-cache' ) );
27
 
28
+ $api = new Cdnfsd_LimeLight_Api( $this->short_name, $this->username, $this->api_key );
29
  $items = array();
30
 
31
  foreach ( $urls as $url ) {
64
  empty( $this->api_key ) )
65
  throw new \Exception( __( 'Access key not specified.', 'w3-total-cache' ) );
66
 
67
+ $api = new Cdnfsd_LimeLight_Api( $this->short_name, $this->username, $this->api_key );
68
  $url = Util_Environment::home_domain_root_url() . '/*';
69
 
70
  $items = array(
Cdnfsd_Limelight_Page.php → Cdnfsd_LimeLight_Page.php RENAMED
@@ -1,11 +1,11 @@
1
  <?php
2
  namespace W3TC;
3
 
4
- class Cdnfsd_Limelight_Page {
5
  // called from plugin-admin
6
  static public function admin_print_scripts_performance_page_w3tc_cdn() {
7
  wp_enqueue_script( 'w3tc_cdnfsd_limelight',
8
- plugins_url( 'Cdnfsd_Limelight_Page_View.js', W3TC_FILE ),
9
  array( 'jquery' ), '1.0' );
10
  }
11
 
@@ -13,6 +13,6 @@ class Cdnfsd_Limelight_Page {
13
 
14
  static public function w3tc_settings_box_cdnfsd() {
15
  $config = Dispatcher::config();
16
- include W3TC_DIR . '/Cdnfsd_Limelight_Page_View.php';
17
  }
18
  }
1
  <?php
2
  namespace W3TC;
3
 
4
+ class Cdnfsd_LimeLight_Page {
5
  // called from plugin-admin
6
  static public function admin_print_scripts_performance_page_w3tc_cdn() {
7
  wp_enqueue_script( 'w3tc_cdnfsd_limelight',
8
+ plugins_url( 'Cdnfsd_LimeLight_Page_View.js', W3TC_FILE ),
9
  array( 'jquery' ), '1.0' );
10
  }
11
 
13
 
14
  static public function w3tc_settings_box_cdnfsd() {
15
  $config = Dispatcher::config();
16
+ include W3TC_DIR . '/Cdnfsd_LimeLight_Page_View.php';
17
  }
18
  }
Cdnfsd_Limelight_Page_View.js → Cdnfsd_LimeLight_Page_View.js RENAMED
File without changes
Cdnfsd_Limelight_Page_View.php → Cdnfsd_LimeLight_Page_View.php RENAMED
File without changes
Cdnfsd_Limelight_Popup.php → Cdnfsd_LimeLight_Popup.php RENAMED
@@ -3,9 +3,9 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Cdnfsd_Limelight_Popup {
7
  static public function w3tc_ajax() {
8
- $o = new Cdnfsd_Limelight_Popup();
9
 
10
  add_action( 'w3tc_ajax_cdnfsd_limelight_intro',
11
  array( $o, 'w3tc_ajax_cdnfsd_limelight_intro' ) );
@@ -24,7 +24,7 @@ class Cdnfsd_Limelight_Popup {
24
  private function render_intro( $details ) {
25
  $config = Dispatcher::config();
26
 
27
- include W3TC_DIR . '/Cdnfsd_Limelight_Popup_View_Intro.php';
28
  exit();
29
  }
30
 
@@ -36,7 +36,7 @@ class Cdnfsd_Limelight_Popup {
36
  $api_key = $_REQUEST['api_key'];
37
 
38
  try {
39
- $api = new Cdnfsd_Limelight_Api( $short_name, $username, $api_key );
40
  $url = Util_Environment::home_domain_root_url() . '/';
41
 
42
  $items = array(
@@ -62,7 +62,7 @@ class Cdnfsd_Limelight_Popup {
62
  $c->set( 'cdnfsd.limelight.api_key', $api_key );
63
  $c->save();
64
 
65
- include W3TC_DIR . '/Cdnfsd_Limelight_Popup_View_Success.php';
66
  exit();
67
  }
68
  }
3
 
4
 
5
 
6
+ class Cdnfsd_LimeLight_Popup {
7
  static public function w3tc_ajax() {
8
+ $o = new Cdnfsd_LimeLight_Popup();
9
 
10
  add_action( 'w3tc_ajax_cdnfsd_limelight_intro',
11
  array( $o, 'w3tc_ajax_cdnfsd_limelight_intro' ) );
24
  private function render_intro( $details ) {
25
  $config = Dispatcher::config();
26
 
27
+ include W3TC_DIR . '/Cdnfsd_LimeLight_Popup_View_Intro.php';
28
  exit();
29
  }
30
 
36
  $api_key = $_REQUEST['api_key'];
37
 
38
  try {
39
+ $api = new Cdnfsd_LimeLight_Api( $short_name, $username, $api_key );
40
  $url = Util_Environment::home_domain_root_url() . '/';
41
 
42
  $items = array(
62
  $c->set( 'cdnfsd.limelight.api_key', $api_key );
63
  $c->save();
64
 
65
+ include W3TC_DIR . '/Cdnfsd_LimeLight_Popup_View_Success.php';
66
  exit();
67
  }
68
  }
Cdnfsd_Limelight_Popup_View_Intro.php → Cdnfsd_LimeLight_Popup_View_Intro.php RENAMED
@@ -11,7 +11,7 @@ if ( isset( $details['error_message'] ) )
11
  ?>
12
  <div class="metabox-holder">
13
  <?php Util_Ui::postbox_header(
14
- __( 'Your Limelight Account credentials', 'w3-total-cache' ) ); ?>
15
  <table class="form-table">
16
  <tr>
17
  <td>Account Short Name:</td>
11
  ?>
12
  <div class="metabox-holder">
13
  <?php Util_Ui::postbox_header(
14
+ __( 'Your LimeLight Account credentials', 'w3-total-cache' ) ); ?>
15
  <table class="form-table">
16
  <tr>
17
  <td>Account Short Name:</td>
Cdnfsd_Limelight_Popup_View_Success.php → Cdnfsd_LimeLight_Popup_View_Success.php RENAMED
File without changes
Cdnfsd_MaxCdn_Popup.php CHANGED
@@ -15,7 +15,7 @@ class Cdnfsd_MaxCdn_Popup {
15
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_view_zone' ) );
16
  add_action( 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone',
17
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone' ) );
18
- add_action( 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone_skip',
19
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone_skip' ) );
20
  }
21
 
15
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_view_zone' ) );
16
  add_action( 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone',
17
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone' ) );
18
+ add_action( 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone_skip',
19
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_configure_zone_skip' ) );
20
  }
21
 
Cdnfsd_Plugin.php CHANGED
@@ -18,6 +18,12 @@ class Cdnfsd_Plugin {
18
  * Runs plugin
19
  */
20
  function run() {
 
 
 
 
 
 
21
  add_filter( 'w3tc_footer_comment', array(
22
  $this,
23
  'w3tc_footer_comment'
18
  * Runs plugin
19
  */
20
  function run() {
21
+ $engine = $this->_config->get_string( 'cdnfsd.engine' );
22
+
23
+ if ( !Util_Environment::is_w3tc_pro( $this->_config ) || empty( $engine ) ) {
24
+ return;
25
+ }
26
+
27
  add_filter( 'w3tc_footer_comment', array(
28
  $this,
29
  'w3tc_footer_comment'
Cdnfsd_Plugin_Admin.php CHANGED
@@ -17,6 +17,16 @@ class Cdnfsd_Plugin_Admin {
17
  add_action( 'w3tc_settings_box_cdnfsd', array(
18
  '\W3TC\Cdnfsd_CloudFront_Page',
19
  'w3tc_settings_box_cdnfsd' ) );
 
 
 
 
 
 
 
 
 
 
20
  } elseif ( $cdnfsd_engine == 'maxcdn' ) {
21
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
22
  '\W3TC\Cdnfsd_MaxCdn_Page',
@@ -27,15 +37,15 @@ class Cdnfsd_Plugin_Admin {
27
  add_action( 'w3tc_settings_box_cdnfsd', array(
28
  '\W3TC\Cdnfsd_MaxCdn_Page',
29
  'w3tc_settings_box_cdnfsd' ) );
30
- } elseif ( $cdnfsd_engine == 'limelight' ) {
31
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
32
- '\W3TC\Cdnfsd_Limelight_Page',
33
  'admin_print_scripts_performance_page_w3tc_cdn' ) );
34
  add_action( 'w3tc_ajax', array(
35
- '\W3TC\Cdnfsd_Limelight_Popup',
36
  'w3tc_ajax' ) );
37
  add_action( 'w3tc_settings_box_cdnfsd', array(
38
- '\W3TC\Cdnfsd_Limelight_Page',
39
  'w3tc_settings_box_cdnfsd' ) );
40
  }
41
 
@@ -55,7 +65,7 @@ class Cdnfsd_Plugin_Admin {
55
 
56
  $cdnfsd_engine_values = array();
57
  $cdnfsd_engine_values[''] = array(
58
- 'label' => __( 'Please select engine', 'w3-total-cache' )
59
  );
60
  $cdnfsd_engine_values['cloudfront'] = array(
61
  'label' => __( 'Amazon CloudFront', 'w3-total-cache' ),
@@ -70,12 +80,17 @@ class Cdnfsd_Plugin_Admin {
70
  $cdnfsd_engine_values['maxcdn'] = array(
71
  'label' => __( 'MaxCDN (recommended)', 'w3-total-cache' ),
72
  );
 
 
 
73
 
74
  $tag = '';
75
  if ( $cdnfsd_engine == 'cloudfront' ) {
76
  $tag = '#cdn-fsd-cloudfront';
77
  } elseif ( $cdnfsd_engine == 'maxcdn' ) {
78
  $tag = '#cdn-fsd-maxcdn';
 
 
79
  }
80
 
81
  if ( empty( $tag ) ) {
17
  add_action( 'w3tc_settings_box_cdnfsd', array(
18
  '\W3TC\Cdnfsd_CloudFront_Page',
19
  'w3tc_settings_box_cdnfsd' ) );
20
+ } elseif ( $cdnfsd_engine == 'limelight' ) {
21
+ add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
22
+ '\W3TC\Cdnfsd_LimeLight_Page',
23
+ 'admin_print_scripts_performance_page_w3tc_cdn' ) );
24
+ add_action( 'w3tc_ajax', array(
25
+ '\W3TC\Cdnfsd_LimeLight_Popup',
26
+ 'w3tc_ajax' ) );
27
+ add_action( 'w3tc_settings_box_cdnfsd', array(
28
+ '\W3TC\Cdnfsd_LimeLight_Page',
29
+ 'w3tc_settings_box_cdnfsd' ) );
30
  } elseif ( $cdnfsd_engine == 'maxcdn' ) {
31
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
32
  '\W3TC\Cdnfsd_MaxCdn_Page',
37
  add_action( 'w3tc_settings_box_cdnfsd', array(
38
  '\W3TC\Cdnfsd_MaxCdn_Page',
39
  'w3tc_settings_box_cdnfsd' ) );
40
+ } elseif ( $cdnfsd_engine == 'stackpath' ) {
41
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
42
+ '\W3TC\Cdnfsd_StackPath_Page',
43
  'admin_print_scripts_performance_page_w3tc_cdn' ) );
44
  add_action( 'w3tc_ajax', array(
45
+ '\W3TC\Cdnfsd_StackPath_Popup',
46
  'w3tc_ajax' ) );
47
  add_action( 'w3tc_settings_box_cdnfsd', array(
48
+ '\W3TC\Cdnfsd_StackPath_Page',
49
  'w3tc_settings_box_cdnfsd' ) );
50
  }
51
 
65
 
66
  $cdnfsd_engine_values = array();
67
  $cdnfsd_engine_values[''] = array(
68
+ 'label' => '',
69
  );
70
  $cdnfsd_engine_values['cloudfront'] = array(
71
  'label' => __( 'Amazon CloudFront', 'w3-total-cache' ),
80
  $cdnfsd_engine_values['maxcdn'] = array(
81
  'label' => __( 'MaxCDN (recommended)', 'w3-total-cache' ),
82
  );
83
+ $cdnfsd_engine_values['stackpath'] = array(
84
+ 'label' => __( 'StackPath', 'w3-total-cache' ),
85
+ );
86
 
87
  $tag = '';
88
  if ( $cdnfsd_engine == 'cloudfront' ) {
89
  $tag = '#cdn-fsd-cloudfront';
90
  } elseif ( $cdnfsd_engine == 'maxcdn' ) {
91
  $tag = '#cdn-fsd-maxcdn';
92
+ } elseif ( $cdnfsd_engine == 'stackpath' ) {
93
+ $tag = '#cdn-fsd-stackpath';
94
  }
95
 
96
  if ( empty( $tag ) ) {
Cdnfsd_StackPath_Engine.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdnfsd_StackPath_Engine {
7
+ private $api_key;
8
+ private $zone_id;
9
+
10
+
11
+
12
+ function __construct( $config = array() ) {
13
+ $this->api_key = $config['api_key'];
14
+ $this->zone_id = $config['zone_id'];
15
+ }
16
+
17
+
18
+
19
+ function flush_urls( $urls ) {
20
+ if ( empty( $this->api_key ) || empty( $this->zone_id ) )
21
+ throw new \Exception( __( 'API key not specified.', 'w3-total-cache' ) );
22
+
23
+ $api = Cdn_StackPath_Api::create( $this->api_key );
24
+
25
+ $files = array();
26
+ foreach ( $urls as $url ) {
27
+ $parsed = parse_url( $url );
28
+ $relative_url =
29
+ ( isset( $parsed['path'] ) ? $parsed['path'] : '/' ) .
30
+ ( isset( $parsed['query'] ) ? '?' . $parsed['query'] : '' );
31
+ $files[] = $relative_url;
32
+ }
33
+ $api->delete_site_cache( $this->zone_id, $files );
34
+ }
35
+
36
+
37
+
38
+ /**
39
+ * Flushes CDN completely
40
+ */
41
+ function flush_all() {
42
+ if ( empty( $this->api_key ) || empty( $this->zone_id ) )
43
+ throw new \Exception( __( 'API key not specified.', 'w3-total-cache' ) );
44
+
45
+ $api = Cdn_StackPath_Api::create( $this->api_key );
46
+ $api->delete_site_cache( $this->zone_id );
47
+ }
48
+ }
Cdnfsd_StackPath_Page.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdnfsd_StackPath_Page {
7
+ // called from plugin-admin
8
+ static public function admin_print_scripts_performance_page_w3tc_cdn() {
9
+ wp_enqueue_script( 'w3tc_cdn_stackpath_fsd',
10
+ plugins_url( 'Cdnfsd_StackPath_Page_View.js', W3TC_FILE ),
11
+ array( 'jquery' ), '1.0' );
12
+ }
13
+
14
+
15
+
16
+ static public function w3tc_settings_box_cdnfsd() {
17
+ $config = Dispatcher::config();
18
+ include W3TC_DIR . '/Cdnfsd_StackPath_Page_View.php';
19
+ }
20
+ }
Cdnfsd_StackPath_Page_View.js ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ function w3tc_stackpath_fsd_resize(o) {
3
+ o.options.height = jQuery('.w3tc_popup_form').height() + 30;
4
+ o.resize();
5
+ }
6
+
7
+ $('body')
8
+ .on('click', '.w3tc_cdn_stackpath_fsd_authorize', function() {
9
+ W3tc_Lightbox.open({
10
+ id:'w3tc-overlay',
11
+ close: '',
12
+ width: 800,
13
+ height: 300,
14
+ url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
15
+ '&w3tc_action=cdn_stackpath_fsd_intro',
16
+ callback: w3tc_stackpath_fsd_resize
17
+ });
18
+ })
19
+
20
+
21
+
22
+ .on('click', '.w3tc_cdn_stackpath_fsd_list_zones', function() {
23
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
24
+ '&w3tc_action=cdn_stackpath_fsd_list_zones';
25
+
26
+ var v = $('.w3tc_popup_form').find('input').each(function(i) {
27
+ var name = $(this).attr('name');
28
+ if (name)
29
+ url += '&' + encodeURIComponent(name) + '=' +
30
+ encodeURIComponent($(this).val());
31
+ });
32
+
33
+ W3tc_Lightbox.load(url, w3tc_stackpath_fsd_resize);
34
+ })
35
+
36
+
37
+
38
+ .on('click', '.w3tc_cdn_stackpath_fsd_view_zone', function() {
39
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
40
+ '&w3tc_action=cdn_stackpath_fsd_view_zone';
41
+
42
+ var v = $('.w3tc_popup_form').find('input').each(function(i) {
43
+ var name = $(this).attr('name');
44
+ var type = $(this).attr('type');
45
+ if (type == 'radio') {
46
+ if (!$(this).prop('checked'))
47
+ return;
48
+ }
49
+
50
+ if (name)
51
+ url += '&' + encodeURIComponent(name) + '=' +
52
+ encodeURIComponent($(this).val());
53
+ });
54
+
55
+ W3tc_Lightbox.load(url, w3tc_stackpath_fsd_resize);
56
+ })
57
+
58
+
59
+
60
+ .on('click', '.w3tc_cdn_stackpath_fsd_configure_zone', function() {
61
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
62
+ '&w3tc_action=cdn_stackpath_fsd_configure_zone';
63
+
64
+ var v = $('.w3tc_popup_form').find('input').each(function(i) {
65
+ var name = $(this).attr('name');
66
+ if (name)
67
+ url += '&' + encodeURIComponent(name) + '=' +
68
+ encodeURIComponent($(this).val());
69
+ });
70
+
71
+ W3tc_Lightbox.load(url, w3tc_stackpath_fsd_resize);
72
+ })
73
+
74
+
75
+
76
+ .on('click', '.w3tc_cdn_stackpath_fsd_configure_zone_skip', function() {
77
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
78
+ '&w3tc_action=cdn_stackpath_fsd_configure_zone_skip';
79
+
80
+ var v = $('.w3tc_popup_form').find('input').each(function(i) {
81
+ var name = $(this).attr('name');
82
+ if (name)
83
+ url += '&' + encodeURIComponent(name) + '=' +
84
+ encodeURIComponent($(this).val());
85
+ });
86
+
87
+ W3tc_Lightbox.load(url, w3tc_stackpath_fsd_resize);
88
+ })
89
+
90
+
91
+
92
+ .on('click', '.w3tc_cdn_stackpath_fsd_done', function() {
93
+ // refresh page
94
+ window.location = window.location + '&';
95
+ })
96
+
97
+
98
+
99
+ .on('size_change', '#cdn_cname_add', function() {
100
+ w3tc_stackpath_fsd_resize(W3tc_Lightbox);
101
+ })
102
+ });
Cdnfsd_StackPath_Page_View.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ $key = $config->get_string( 'cdnfsd.stackpath.api_key' );
8
+ $authorized = !empty( $key );
9
+
10
+ ?>
11
+ <form id="cdn_form" action="admin.php?page=w3tc_cdn" method="post">
12
+ <div class="metabox-holder">
13
+ <?php Util_Ui::postbox_header( __( 'Configuration: Full-Site Delivery', 'w3-total-cache' ),
14
+ '', 'configuration' ); ?>
15
+ <table class="form-table">
16
+ <tr>
17
+ <th style="width: 300px;">
18
+ <label>
19
+ <?php
20
+ _e( 'Specify account credentials:',
21
+ 'w3-total-cache' );
22
+ ?>
23
+ </label>
24
+ </th>
25
+ <td>
26
+ <?php if ( $authorized ): ?>
27
+ <input class="w3tc_cdn_stackpath_fsd_authorize button-primary"
28
+ type="button"
29
+ value="<?php _e( 'Reauthorize', 'w3-total-cache' ); ?>"
30
+ />
31
+ <?php else: ?>
32
+ <input class="w3tc_cdn_stackpath_fsd_authorize button-primary"
33
+ type="button"
34
+ value="<?php _e( 'Authorize', 'w3-total-cache' ); ?>"
35
+ />
36
+ <?php endif ?>
37
+ </td>
38
+ </tr>
39
+
40
+ <?php if ( $authorized ): ?>
41
+ <tr>
42
+ <th>
43
+ <label><?php _e( '<acronym title="Content Delivery Network">CDN</acronym> CNAME:', 'w3-total-cache' ); ?></label>
44
+ </th>
45
+ <td class="w3tc_config_value_text">
46
+ <?php
47
+ echo $config->get_string( 'cdnfsd.stackpath.zone_domain' )
48
+ ?><br />
49
+ <span class="description">
50
+ This website domain has to be CNAME pointing to this
51
+ <acronym title="Content Delivery Network">CDN</acronym> domain
52
+ </span>
53
+ </td>
54
+ </tr>
55
+ <?php endif ?>
56
+ </table>
57
+
58
+ <?php Util_Ui::button_config_save( 'cdn_configuration' ); ?>
59
+ <?php Util_Ui::postbox_footer(); ?>
60
+ </div>
61
+ </form>
Cdnfsd_StackPath_Popup.php ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdnfsd_StackPath_Popup {
7
+ static public function w3tc_ajax() {
8
+ $o = new Cdnfsd_StackPath_Popup();
9
+
10
+ add_action( 'w3tc_ajax_cdn_stackpath_fsd_intro',
11
+ array( $o, 'w3tc_ajax_cdn_stackpath_fsd_intro' ) );
12
+ add_action( 'w3tc_ajax_cdn_stackpath_fsd_list_zones',
13
+ array( $o, 'w3tc_ajax_cdn_stackpath_fsd_list_zones' ) );
14
+ add_action( 'w3tc_ajax_cdn_stackpath_fsd_view_zone',
15
+ array( $o, 'w3tc_ajax_cdn_stackpath_fsd_view_zone' ) );
16
+ add_action( 'w3tc_ajax_cdn_stackpath_fsd_configure_zone',
17
+ array( $o, 'w3tc_ajax_cdn_stackpath_fsd_configure_zone' ) );
18
+ add_action( 'w3tc_ajax_cdn_stackpath_fsd_configure_zone_skip',
19
+ array( $o, 'w3tc_ajax_cdn_stackpath_fsd_configure_zone_skip' ) );
20
+ }
21
+
22
+
23
+
24
+ public function w3tc_ajax_cdn_stackpath_fsd_intro() {
25
+ $config = Dispatcher::config();
26
+
27
+ $this->render_intro( array(
28
+ 'api_key' => $config->get_string( 'cdnfsd.stackpath.api_key' ) ) );
29
+ }
30
+
31
+
32
+
33
+ private function render_intro( $details ) {
34
+ $config = Dispatcher::config();
35
+ $url_obtain_key = STACKPATH_AUTHORIZE_URL;
36
+
37
+ include W3TC_DIR . '/Cdnfsd_StackPath_Popup_View_Intro.php';
38
+ exit();
39
+ }
40
+
41
+
42
+
43
+ public function w3tc_ajax_cdn_stackpath_fsd_list_zones() {
44
+ $api_key = $_REQUEST['api_key'];
45
+
46
+ $api = Cdn_StackPath_Api::create( $api_key );
47
+ if ( !$api->is_valid() ) {
48
+ $this->render_intro( array(
49
+ 'api_key' => $api_key,
50
+ 'error_message' => 'Can\'t authenticate: API key not valid'
51
+ ) );
52
+ exit();
53
+ }
54
+
55
+ try {
56
+ $zones = $api->get_sites();
57
+ } catch ( \Exception $ex ) {
58
+ $error_message = 'Can\'t authenticate: ' . $ex->getMessage();
59
+
60
+ if ( strpos( $error_message, 'not whitelisted' ) > 0 ) {
61
+ $error_message .= '. You can whitelist IP ' .
62
+ '<a target="_blank" href="https://app.stackpath.com/account/api/whitelist">here</a>';
63
+ }
64
+ $this->render_intro( array(
65
+ 'api_key' => $api_key,
66
+ 'error_message' => $error_message
67
+ ) );
68
+ exit();
69
+ }
70
+
71
+ $details = array(
72
+ 'api_key' => $api_key,
73
+ 'zones' => $zones
74
+ );
75
+
76
+ include W3TC_DIR . '/Cdnfsd_StackPath_Popup_View_Zones.php';
77
+ exit();
78
+ }
79
+
80
+
81
+
82
+ public function w3tc_ajax_cdn_stackpath_fsd_view_zone() {
83
+ $api_key = $_REQUEST['api_key'];
84
+ $zone_id = Util_Request::get( 'zone_id', '' );
85
+
86
+ $details = array(
87
+ 'api_key' => $api_key,
88
+ 'zone_id' => $zone_id,
89
+ 'name' => '',
90
+ 'url' => array(
91
+ 'new' => get_home_url() ),
92
+ 'ip' => array(),
93
+ // needs to be off since original DNS will be replaced with stackpath's
94
+ 'dns_check' => array(
95
+ 'new' => 0
96
+ ),
97
+ // needs to be off, since WP issues no-cache headers for wp-admin
98
+ // and logged-in users
99
+ 'ignore_cache_control' => array(
100
+ 'new' => 0
101
+ ),
102
+ 'custom_domain' => array(
103
+ 'new' => Util_Environment::home_url_host()
104
+ )
105
+ );
106
+
107
+ if ( empty( $zone_id ) ) {
108
+ // create new zone mode
109
+ $details['name'] = Util_Request::get( 'zone_new_name' );
110
+ $details['ip']['new'] = Cdnfsd_Util::get_suggested_home_ip();
111
+ } else {
112
+ $api = Cdn_StackPath_Api::create( $api_key );
113
+ try {
114
+ $zone = $api->get_site( $zone_id );
115
+ $custom_domains = $api->get_custom_domains( $zone_id );
116
+ } catch ( \Exception $ex ) {
117
+ $this->render_intro( array(
118
+ 'api_key' => $api_key,
119
+ 'error_message' => 'Can\'t obtain zone: ' . $ex->getMessage()
120
+ ) );
121
+ exit();
122
+ }
123
+
124
+ $details['custom_domain']['current'] = '';
125
+
126
+ foreach ( $custom_domains as $d ) {
127
+ $details['custom_domain']['current'] = $d;
128
+ if ( $d == Util_Environment::home_url_host() )
129
+ break;
130
+ }
131
+
132
+ $details['name'] = $zone['name'];
133
+ $details['dns_check']['current'] = $zone['dns_check'];
134
+ $details['ignore_cache_control'] = $zone['ignore_cache_control'];
135
+ $details['url']['current'] = $zone['url'];
136
+ $details['ip']['current'] = $zone['ip'];
137
+
138
+ $origin_ip = Cdnfsd_Util::get_suggested_home_ip();
139
+ $cdn_ip = gethostbyname( $zone['tmp_url'] );
140
+
141
+ if ( $origin_ip != $cdn_ip )
142
+ $details['ip']['new'] = $origin_ip;
143
+ }
144
+
145
+
146
+
147
+ include W3TC_DIR . '/Cdnfsd_StackPath_Popup_View_Zone.php';
148
+ exit();
149
+ }
150
+
151
+
152
+
153
+ private function render_zone_value_change( $details, $field ) {
154
+ Util_Ui::hidden( '', $field, $details[$field]['new'] );
155
+
156
+ if ( !isset( $details[$field]['current'] ) ||
157
+ $details[$field]['current'] == $details[$field]['new'] )
158
+ echo htmlspecialchars( $details[$field]['new'] );
159
+ else {
160
+ echo 'currently set to <strong>' .
161
+ htmlspecialchars( empty( $details[$field]['current'] ) ?
162
+ '<empty>' : $details[$field]['current'] ) .
163
+ '</strong><br />';
164
+ echo 'will be changed to <strong>' .
165
+ htmlspecialchars( $details[$field]['new'] ) . '</strong><br />';
166
+ }
167
+ }
168
+
169
+
170
+
171
+ private function render_zone_boolean_change( $details, $field ) {
172
+ Util_Ui::hidden( '', $field, $details[$field]['new'] );
173
+
174
+ if ( !isset( $details[$field]['current'] ) ) {
175
+ echo 'will be set to <strong>';
176
+ echo $this->render_zone_boolean( $details[$field]['new'] );
177
+ echo '</strong>';
178
+ } else if ( $details[$field]['current'] == $details[$field]['new'] ) {
179
+ echo '<strong>';
180
+ echo $this->render_zone_boolean( $details[$field]['new'] );
181
+ echo '</strong>';
182
+ } else {
183
+ echo 'currently set to <strong>';
184
+ $this->render_zone_boolean( $details[$field]['current'] );
185
+ echo '</strong><br />';
186
+ echo 'will be changed to <strong>';
187
+ $this->render_zone_boolean( $details[$field]['new'] );
188
+ echo '</strong><br />';
189
+ }
190
+ }
191
+
192
+
193
+
194
+ private function render_zone_boolean( $v ) {
195
+ if ( $v == 0 )
196
+ echo 'disabled';
197
+ else
198
+ echo 'enabled';
199
+ }
200
+
201
+
202
+
203
+ private function render_zone_ip_change( $details, $field ) {
204
+ Util_Ui::textbox( '', $field, $details[$field]['new'] );
205
+
206
+ if ( isset( $details[$field]['current'] ) &&
207
+ $details[$field]['current'] != $details[$field]['new'] ) {
208
+ echo '<br /><span class="description">currently set to <strong>' .
209
+ $details[$field]['current'] . '</strong></span>';
210
+ }
211
+ }
212
+
213
+
214
+
215
+ public function w3tc_ajax_cdn_stackpath_fsd_configure_zone() {
216
+ $api_key = $_REQUEST['api_key'];
217
+ $zone_id = Util_Request::get( 'zone_id', '' );
218
+
219
+ $zone = array(
220
+ 'name' => Util_Request::get( 'name' ),
221
+ 'label' => Util_Request::get( 'name' ),
222
+ 'url' => Util_Request::get( 'url' ),
223
+ 'use_stale' => 1,
224
+ 'queries' => 1,
225
+ 'compress' => 1,
226
+ 'backend_compress' => 1,
227
+ 'dns_check' => Util_Request::get( 'dns_check' ),
228
+ 'ip' => Util_Request::get( 'ip' )
229
+ );
230
+
231
+ if ( empty( $zone['ip'] ) ) {
232
+ unset( $zone['ip'] );
233
+ }
234
+
235
+ $api = Cdn_StackPath_Api::create( $api_key );
236
+
237
+ try {
238
+ if ( empty( $zone_id ) ) {
239
+ $response = $api->create_site( $zone );
240
+ $zone_id = $response['id'];
241
+ } else {
242
+ $response = $api->update_site( $zone_id, $zone );
243
+ }
244
+
245
+ $custom_domains = $api->get_custom_domains( $zone_id );
246
+ $custom_domain = Util_Request::get( 'custom_domain' );
247
+
248
+ $added = false;
249
+ foreach ( $custom_domains as $d ) {
250
+ if ( $d == $custom_domain ) {
251
+ $added = true;
252
+ break;
253
+ }
254
+ }
255
+ if ( !$added ) {
256
+ $api->create_custom_domain( $zone_id, $custom_domain );
257
+ }
258
+ } catch ( \Exception $ex ) {
259
+ $this->render_intro( array(
260
+ 'api_key' => $api_key,
261
+ 'error_message' => 'Failed to configure custom domain ' . $custom_domain . ': ' . $ex->getMessage()
262
+ ) );
263
+ exit();
264
+ }
265
+
266
+ $zone_domain = $response['tmp_url'];
267
+
268
+ $c = Dispatcher::config();
269
+ $c->set( 'cdnfsd.stackpath.api_key', $api_key );
270
+ $c->set( 'cdnfsd.stackpath.zone_id', $zone_id );
271
+ $c->set( 'cdnfsd.stackpath.zone_domain', $zone_domain );
272
+ $c->save();
273
+
274
+ $details = array(
275
+ 'name' => $zone['name'],
276
+ 'home_domain' => Util_Environment::home_url_host(),
277
+ 'dns_cname_target' => $zone_domain,
278
+ );
279
+
280
+ include W3TC_DIR . '/Cdnfsd_StackPath_Popup_View_Success.php';
281
+ exit();
282
+ }
283
+
284
+
285
+
286
+ public function w3tc_ajax_cdn_stackpath_fsd_configure_zone_skip() {
287
+ $api_key = $_REQUEST['api_key'];
288
+ $zone_id = Util_Request::get( 'zone_id', '' );
289
+
290
+ $api = Cdn_StackPath_Api::create( $api_key );
291
+
292
+ try {
293
+ $zone = $api->get_site( $zone_id );
294
+ } catch ( \Exception $ex ) {
295
+ $this->render_intro( array(
296
+ 'api_key' => $api_key,
297
+ 'error_message' => 'Failed to obtain custom domains: ' . $ex->getMessage()
298
+ ) );
299
+ exit();
300
+ }
301
+
302
+ $zone_domain = $zone['cdn_url'];
303
+
304
+ $c = Dispatcher::config();
305
+ $c->set( 'cdnfsd.stackpath.api_key', $api_key );
306
+ $c->set( 'cdnfsd.stackpath.zone_id', $zone_id );
307
+ $c->set( 'cdnfsd.stackpath.zone_domain', $zone_domain );
308
+ $c->save();
309
+
310
+ $details = array(
311
+ 'name' => $zone['name'],
312
+ 'home_domain' => Util_Environment::home_url_host(),
313
+ 'dns_cname_target' => $zone_domain,
314
+ );
315
+
316
+ include W3TC_DIR . '/Cdnfsd_StackPath_Popup_View_Success.php';
317
+ exit();
318
+ }
319
+ }
Cdnfsd_StackPath_Popup_View_Intro.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_popup_form">
8
+ <?php
9
+ if ( isset( $details['error_message'] ) )
10
+ echo '<div class="error">' . $details['error_message'] . '</div>';
11
+ ?>
12
+ <div class="metabox-holder">
13
+ <?php Util_Ui::postbox_header(
14
+ __( 'Your StackPath Account credentials', 'w3-total-cache' ) ); ?>
15
+ <table class="form-table">
16
+ <tr>
17
+ <td>API Key:</td>
18
+ <td>
19
+ <input name="api_key" type="text" class="w3tc-ignore-change"
20
+ style="width: 550px"
21
+ value="<?php echo $details['api_key'] ?>" />
22
+ <br />
23
+ <span class="description">
24
+ To obtain API key you can
25
+ <a target="_blank" href="<?php echo $url_obtain_key ?>">click here</a>,
26
+ log in, and paste the key in above field.
27
+ </span>
28
+ </td>
29
+ </tr>
30
+ </table>
31
+
32
+ <p class="submit">
33
+ <input type="button"
34
+ class="w3tc_cdn_stackpath_fsd_list_zones w3tc-button-save button-primary"
35
+ value="<?php _e( 'Next', 'w3-total-cache' ); ?>" />
36
+ </p>
37
+ <?php Util_Ui::postbox_footer(); ?>
38
+ </div>
39
+ </form>
Cdnfsd_StackPath_Popup_View_Success.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_popup_form">
8
+ <div class="metabox-holder">
9
+ <?php Util_Ui::postbox_header(
10
+ __( 'Succeeded', 'w3-total-cache' ) ); ?>
11
+
12
+ <div style="text-align: center">
13
+ Site <?php echo $details['name'] ?> was successfully configured.<br />
14
+ Next, update the domain <acronym title="Domain Name System">DNS</acronym> records
15
+ <strong><?php echo $details['home_domain'] ?></strong> and add <acronym title="Canonical Name">CNAME</acronym> alias to
16
+ <strong><?php echo $details['dns_cname_target'] ?></strong> to enable caching.
17
+ </div>
18
+
19
+ <p class="submit">
20
+ <input type="button"
21
+ class="w3tc_cdn_stackpath_fsd_done w3tc-button-save button-primary"
22
+ value="<?php _e( 'Done', 'w3-total-cache' ); ?>" />
23
+ </p>
24
+ <?php Util_Ui::postbox_footer(); ?>
25
+ </div>
26
+ </form>
Cdnfsd_StackPath_Popup_View_Zone.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_popup_form" method="post">
8
+ <?php
9
+ Util_Ui::hidden( '', 'api_key', $details['api_key'] );
10
+ Util_Ui::hidden( '', 'zone_id', $details['zone_id'] );
11
+ Util_Ui::hidden( '', 'name', $details['name'] );
12
+ ?>
13
+
14
+ <div class="metabox-holder">
15
+ <?php Util_Ui::postbox_header( __( 'Configure zone', 'w3-total-cache' ) ); ?>
16
+ <table class="form-table">
17
+ <tr>
18
+ <th>Name:</th>
19
+ <td><?php echo $details['name'] ?></td>
20
+ </tr>
21
+ <tr>
22
+ <th>Origin URL:</th>
23
+ <td><?php $this->render_zone_value_change( $details, 'url' ) ?></td>
24
+ </tr>
25
+ <tr>
26
+ <th>Origin IP:</th>
27
+ <td><?php $this->render_zone_ip_change( $details, 'ip' ) ?><br />
28
+ <span class="description">IP of your WordPress host</span>
29
+ </td>
30
+ </tr>
31
+ <tr>
32
+ <th>Origin IP Resolution:</th>
33
+ <td><?php $this->render_zone_boolean_change( $details, 'dns_check' ) ?></td>
34
+ </tr>
35
+ <tr>
36
+ <th>Ignore Cache Control:</th>
37
+ <td><?php $this->render_zone_boolean_change( $details, 'dns_check' ) ?></td>
38
+ </tr>
39
+ <tr>
40
+ <th><acronym title="Content Delivery Network">CDN</acronym> Domain:</th>
41
+ <td>
42
+ <?php $this->render_zone_value_change( $details, 'custom_domain' ) ?><br />
43
+ <span class="description">Domain <acronym title="Content Delivery Network">CDN</acronym> will handle</span>
44
+ </td>
45
+ </tr>
46
+ </table>
47
+
48
+ <p class="submit">
49
+ <input type="button"
50
+ class="w3tc_cdn_stackpath_fsd_configure_zone w3tc-button-save button-primary"
51
+ value="<?php _e( 'Apply', 'w3-total-cache' ); ?>" />
52
+ <input type="button"
53
+ class="w3tc_cdn_stackpath_fsd_configure_zone_skip w3tc-button-save button"
54
+ value="<?php _e( 'Don\'t reconfigure, I know what I\'m doing', 'w3-total-cache' ); ?>" />
55
+
56
+ </p>
57
+ <?php Util_Ui::postbox_footer(); ?>
58
+ </div>
59
+ </form>
Cdnfsd_StackPath_Popup_View_Zones.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_popup_form" method="post">
8
+ <?php
9
+ Util_Ui::hidden( '', 'api_key', $details['api_key'] );
10
+ ?>
11
+ <div class="metabox-holder">
12
+ <?php Util_Ui::postbox_header( __( 'Select zone to use', 'w3-total-cache' ) ); ?>
13
+ <table class="form-table">
14
+ <tr>
15
+ <td>Zone:</td>
16
+ <td>
17
+ <?php
18
+ if ( count( $details['zones'] ) > 15 )
19
+ echo '<div style="width: 100%; height: 300px; overflow-y: scroll">';
20
+ ?>
21
+
22
+ <?php foreach ( $details['zones'] as $zone ): ?>
23
+ <label>
24
+ <input name="zone_id" type="radio" class="w3tc-ignore-change"
25
+ value="<?php echo $zone['id'] ?>" />
26
+ <?php echo $zone['name'] ?>
27
+ (<?php echo $zone['cdn_url'] ?>)
28
+ </label><br />
29
+ <?php endforeach ?>
30
+
31
+ <label>
32
+ <input name="zone_id" type="radio" class="w3tc-ignore-change" value=""
33
+ />
34
+ Add new zone:
35
+ </label>
36
+ <input name="zone_new_name" type="text" class="w3tc-ignore-change" />
37
+
38
+ <?php
39
+ if ( count( $details['zones'] ) > 15 )
40
+ echo '</div>';
41
+ ?>
42
+ </td>
43
+ </tr>
44
+ </table>
45
+
46
+ <p class="submit">
47
+ <input type="button"
48
+ class="w3tc_cdn_stackpath_fsd_view_zone w3tc-button-save button-primary"
49
+ value="<?php _e( 'Apply', 'w3-total-cache' ); ?>" />
50
+ </p>
51
+ <?php Util_Ui::postbox_footer(); ?>
52
+ </div>
53
+ </form>
Cli.php CHANGED
@@ -450,19 +450,51 @@ class W3TotalCache_Command extends \WP_CLI_Command {
450
  }
451
 
452
  /**
453
- * Generally triggered from a cronjob, allows for manual Garbage collection of page cache to be triggered
454
  */
455
  function pgcache_cleanup() {
456
  try {
457
- $pgcache_cleanup = Dispatcher::component( 'PgCache_Plugin_Admin' );
458
- $pgcache_cleanup->cleanup();
459
  } catch ( \Exception $e ) {
460
- \WP_CLI::error( __( 'PageCache Garbage cleanup did not start with error %s',
461
- 'w3-total-cache' ), $e );
462
  }
463
 
464
  \WP_CLI::success( __( 'PageCache Garbage cleanup triggered successfully.',
465
- 'w3-total-cache' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  }
467
  }
468
 
450
  }
451
 
452
  /**
453
+ * Generally triggered from a cronjob, performs manual page cache Garbage collection
454
  */
455
  function pgcache_cleanup() {
456
  try {
457
+ $o = Dispatcher::component( 'PgCache_Plugin_Admin' );
458
+ $o->cleanup();
459
  } catch ( \Exception $e ) {
460
+ \WP_CLI::error( __( 'PageCache Garbage cleanup failed: %s',
461
+ 'w3-total-cache' ), $e );
462
  }
463
 
464
  \WP_CLI::success( __( 'PageCache Garbage cleanup triggered successfully.',
465
+ 'w3-total-cache' ) );
466
+ }
467
+
468
+
469
+
470
+ /**
471
+ * Generally triggered from a cronjob, performs manual page cache priming
472
+ * ## OPTIONS
473
+ * [--start=<start>]
474
+ * : Start since <start> entry of sitemap
475
+ *
476
+ * [--limit=<limit>]
477
+ * : load no more than <limit> pages
478
+ *
479
+ */
480
+ function pgcache_prime( $args = array(), $vars = array() ) {
481
+ try {
482
+ $log_callback = function($m) {
483
+ \WP_CLI::log($m);
484
+ };
485
+
486
+ $o = Dispatcher::component( 'PgCache_Plugin_Admin' );
487
+ $o->prime( ( isset( $vars['start'] ) ? $vars['start'] - 1 : null ),
488
+ ( isset( $vars['limit'] ) ? $vars['limit'] : null ),
489
+ $log_callback );
490
+
491
+ } catch ( \Exception $e ) {
492
+ \WP_CLI::error( __( 'PageCache Priming did failed: %s',
493
+ 'w3-total-cache' ), $e );
494
+ }
495
+
496
+ \WP_CLI::success( __( 'PageCache Priming triggered successfully.',
497
+ 'w3-total-cache' ) );
498
  }
499
  }
500
 
ConfigCompiler.php CHANGED
@@ -232,6 +232,15 @@ class ConfigCompiler {
232
  }
233
  }
234
 
 
 
 
 
 
 
 
 
 
235
  //
236
  // changes in 0.9.6
237
  //
232
  }
233
  }
234
 
235
+ //
236
+ // changes in 0.9.7
237
+ //
238
+ if ( isset( $file_data['cdnfsd.enabled'] ) &&
239
+ $file_data['cdnfsd.enabled'] == '1' &&
240
+ empty( $file_data['cdnfsd.engine'] ) ) {
241
+ $file_data['cdnfsd.enabled'] = '0';
242
+ }
243
+
244
  //
245
  // changes in 0.9.6
246
  //
ConfigKeys.php CHANGED
@@ -101,6 +101,10 @@ $keys = array(
101
  'type' => 'integer',
102
  'default' => 0
103
  ),
 
 
 
 
104
  'dbcache.reject.constants' => array(
105
  'type' => 'array',
106
  'default' => array(
@@ -549,6 +553,10 @@ $keys = array(
549
  'type' => 'boolean',
550
  'default' => false
551
  ),
 
 
 
 
552
  'pgcache.cookiegroups.enabled' => array(
553
  'type' => 'boolean',
554
  'default' => false
@@ -1047,9 +1055,9 @@ $keys = array(
1047
  'default' => false
1048
  ),
1049
  'cdn.admin.media_library' => array(
1050
- 'type' => 'boolean',
1051
- 'default' => false
1052
- ),
1053
  'cdn.cors_header' => array(
1054
  'type' => 'boolean',
1055
  'default' => true
@@ -1293,6 +1301,26 @@ $keys = array(
1293
  'type' => 'string',
1294
  'default' => 'auto'
1295
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1296
  'cdn.maxcdn.authorization_key' => array(
1297
  'type' => 'string',
1298
  'default' => ''
@@ -1389,6 +1417,22 @@ $keys = array(
1389
  'type' => 'string',
1390
  'default' => 'auto'
1391
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1392
  'cdn.reject.admins' => array(
1393
  'type' => 'boolean',
1394
  'default' => false
@@ -1433,6 +1477,46 @@ $keys = array(
1433
  'type' => 'boolean',
1434
  'default' => false
1435
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1436
 
1437
  'varnish.configuration_overloaded' => array(
1438
  'type' => 'boolean',
@@ -1463,10 +1547,6 @@ $keys = array(
1463
  'type' => 'boolean',
1464
  'default' => false
1465
  ),
1466
- 'browsercache.hsts' => array(
1467
- 'type' => 'boolean',
1468
- 'default' => false
1469
- ),
1470
  'browsercache.no404wp' => array(
1471
  'type' => 'boolean',
1472
  'default' => false
@@ -1606,6 +1686,144 @@ $keys = array(
1606
  'type' => 'array',
1607
  'default' => array()
1608
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1609
 
1610
  'mobile.configuration_overloaded' => array(
1611
  'type' => 'boolean',
101
  'type' => 'integer',
102
  'default' => 0
103
  ),
104
+ 'dbcache.use_filters' => array(
105
+ 'type' => 'boolean',
106
+ 'default' => false
107
+ ),
108
  'dbcache.reject.constants' => array(
109
  'type' => 'array',
110
  'default' => array(
553
  'type' => 'boolean',
554
  'default' => false
555
  ),
556
+ 'pgcache.rest' => array(
557
+ 'type' => 'string',
558
+ 'default' => ''
559
+ ),
560
  'pgcache.cookiegroups.enabled' => array(
561
  'type' => 'boolean',
562
  'default' => false
1055
  'default' => false
1056
  ),
1057
  'cdn.admin.media_library' => array(
1058
+ 'type' => 'boolean',
1059
+ 'default' => false
1060
+ ),
1061
  'cdn.cors_header' => array(
1062
  'type' => 'boolean',
1063
  'default' => true
1301
  'type' => 'string',
1302
  'default' => 'auto'
1303
  ),
1304
+ 'cdn.limelight.short_name' => array(
1305
+ 'type' => 'string',
1306
+ 'default' => ''
1307
+ ),
1308
+ 'cdn.limelight.username' => array(
1309
+ 'type' => 'string',
1310
+ 'default' => ''
1311
+ ),
1312
+ 'cdn.limelight.api_key' => array(
1313
+ 'type' => 'string',
1314
+ 'default' => ''
1315
+ ),
1316
+ 'cdn.limelight.host.domains' => array(
1317
+ 'type' => 'array',
1318
+ 'default' => array()
1319
+ ),
1320
+ 'cdn.limelight.ssl' => array(
1321
+ 'type' => 'string',
1322
+ 'default' => 'auto'
1323
+ ),
1324
  'cdn.maxcdn.authorization_key' => array(
1325
  'type' => 'string',
1326
  'default' => ''
1417
  'type' => 'string',
1418
  'default' => 'auto'
1419
  ),
1420
+ 'cdn.stackpath.authorization_key' => array(
1421
+ 'type' => 'string',
1422
+ 'default' => ''
1423
+ ),
1424
+ 'cdn.stackpath.domain' => array(
1425
+ 'type' => 'array',
1426
+ 'default' => array()
1427
+ ),
1428
+ 'cdn.stackpath.ssl' => array(
1429
+ 'type' => 'string',
1430
+ 'default' => 'auto'
1431
+ ),
1432
+ 'cdn.stackpath.zone_id' => array(
1433
+ 'type' => 'integer',
1434
+ 'default' => 0
1435
+ ),
1436
  'cdn.reject.admins' => array(
1437
  'type' => 'boolean',
1438
  'default' => false
1477
  'type' => 'boolean',
1478
  'default' => false
1479
  ),
1480
+ 'cdnfsd.cloudfront.access_key' => array(
1481
+ 'type' => 'string',
1482
+ 'default' => ''
1483
+ ),
1484
+ 'cdnfsd.cloudfront.secret_key' => array(
1485
+ 'type' => 'string',
1486
+ 'default' => ''
1487
+ ),
1488
+ 'cdnfsd.cloudfront.distribution_id' => array(
1489
+ 'type' => 'string',
1490
+ 'default' => ''
1491
+ ),
1492
+ 'cdnfsd.limelight.short_name' => array(
1493
+ 'type' => 'string',
1494
+ 'default' => ''
1495
+ ),
1496
+ 'cdnfsd.limelight.username' => array(
1497
+ 'type' => 'string',
1498
+ 'default' => ''
1499
+ ),
1500
+ 'cdnfsd.limelight.api_key' => array(
1501
+ 'type' => 'string',
1502
+ 'default' => ''
1503
+ ),
1504
+ 'cdnfsd.maxcdn.api_key' => array(
1505
+ 'type' => 'string',
1506
+ 'default' => ''
1507
+ ),
1508
+ 'cdnfsd.maxcdn.zone_id' => array(
1509
+ 'type' => 'integer',
1510
+ 'default' => 0
1511
+ ),
1512
+ 'cdnfsd.stackpath.api_key' => array(
1513
+ 'type' => 'string',
1514
+ 'default' => ''
1515
+ ),
1516
+ 'cdnfsd.stackpath.zone_id' => array(
1517
+ 'type' => 'integer',
1518
+ 'default' => 0
1519
+ ),
1520
 
1521
  'varnish.configuration_overloaded' => array(
1522
  'type' => 'boolean',
1547
  'type' => 'boolean',
1548
  'default' => false
1549
  ),
 
 
 
 
1550
  'browsercache.no404wp' => array(
1551
  'type' => 'boolean',
1552
  'default' => false
1686
  'type' => 'array',
1687
  'default' => array()
1688
  ),
1689
+ 'browsercache.security.session.cookie_httponly' => array(
1690
+ 'type' => 'string',
1691
+ 'default' => ''
1692
+ ),
1693
+ 'browsercache.security.session.cookie_secure' => array(
1694
+ 'type' => 'string',
1695
+ 'default' => ''
1696
+ ),
1697
+ 'browsercache.security.session.use_only_cookies' => array(
1698
+ 'type' => 'string',
1699
+ 'default' => ''
1700
+ ),
1701
+ 'browsercache.hsts' => array(
1702
+ 'type' => 'boolean',
1703
+ 'default' => false
1704
+ ),
1705
+ 'browsercache.security.hsts.directive' => array(
1706
+ 'type' => 'string',
1707
+ 'default' => 'maxage'
1708
+ ),
1709
+ 'browsercache.security.xfo' => array(
1710
+ 'type' => 'boolean',
1711
+ 'default' => false
1712
+ ),
1713
+ 'browsercache.security.xfo.directive' => array(
1714
+ 'type' => 'string',
1715
+ 'default' => 'same'
1716
+ ),
1717
+ 'browsercache.security.xfo.allow' => array(
1718
+ 'type' => 'string',
1719
+ 'default' => ''
1720
+ ),
1721
+ 'browsercache.security.xss' => array(
1722
+ 'type' => 'boolean',
1723
+ 'default' => false
1724
+ ),
1725
+ 'browsercache.security.xss.directive' => array(
1726
+ 'type' => 'string',
1727
+ 'default' => 'block'
1728
+ ),
1729
+ 'browsercache.security.xcto' => array(
1730
+ 'type' => 'boolean',
1731
+ 'default' => false
1732
+ ),
1733
+ 'browsercache.security.pkp' => array(
1734
+ 'type' => 'boolean',
1735
+ 'default' => false
1736
+ ),
1737
+ 'browsercache.security.pkp.pin' => array(
1738
+ 'type' => 'string',
1739
+ 'default' => ''
1740
+ ),
1741
+ 'browsercache.security.pkp.pin.backup' => array(
1742
+ 'type' => 'string',
1743
+ 'default' => ''
1744
+ ),
1745
+ 'browsercache.security.pkp.extra' => array(
1746
+ 'type' => 'string',
1747
+ 'default' => 'maxage'
1748
+ ),
1749
+ 'browsercache.security.pkp.report.url' => array(
1750
+ 'type' => 'string',
1751
+ 'default' => ''
1752
+ ),
1753
+ 'browsercache.security.pkp.report.only' => array(
1754
+ 'type' => 'string',
1755
+ 'default' => '0'
1756
+ ),
1757
+ 'browsercache.security.referrer.policy' => array(
1758
+ 'type' => 'boolean',
1759
+ 'default' => 'false'
1760
+ ),
1761
+ 'browsercache.security.referrer.policy.directive' => array(
1762
+ 'type' => 'string',
1763
+ 'default' => '0'
1764
+ ),
1765
+ 'browsercache.security.csp' => array(
1766
+ 'type' => 'boolean',
1767
+ 'default' => false
1768
+ ),
1769
+ 'browsercache.security.csp.base' => array(
1770
+ 'type' => 'string',
1771
+ 'default' => ''
1772
+ ),
1773
+ 'browsercache.security.csp.frame' => array(
1774
+ 'type' => 'string',
1775
+ 'default' => ''
1776
+ ),
1777
+ 'browsercache.security.csp.connect' => array(
1778
+ 'type' => 'string',
1779
+ 'default' => ''
1780
+ ),
1781
+ 'browsercache.security.csp.font' => array(
1782
+ 'type' => 'string',
1783
+ 'default' => ''
1784
+ ),
1785
+ 'browsercache.security.csp.script' => array(
1786
+ 'type' => 'string',
1787
+ 'default' => ''
1788
+ ),
1789
+ 'browsercache.security.csp.style' => array(
1790
+ 'type' => 'string',
1791
+ 'default' => ''
1792
+ ),
1793
+ 'browsercache.security.csp.img' => array(
1794
+ 'type' => 'string',
1795
+ 'default' => ''
1796
+ ),
1797
+ 'browsercache.security.csp.media' => array(
1798
+ 'type' => 'string',
1799
+ 'default' => ''
1800
+ ),
1801
+ 'browsercache.security.csp.object' => array(
1802
+ 'type' => 'string',
1803
+ 'default' => ''
1804
+ ),
1805
+ 'browsercache.security.csp.plugin' => array(
1806
+ 'type' => 'string',
1807
+ 'default' => ''
1808
+ ),
1809
+ 'browsercache.security.csp.form' => array(
1810
+ 'type' => 'string',
1811
+ 'default' => ''
1812
+ ),
1813
+ 'browsercache.security.csp.frame.ancestors' => array(
1814
+ 'type' => 'string',
1815
+ 'default' => ''
1816
+ ),
1817
+ 'browsercache.security.csp.sandbox' => array(
1818
+ 'type' => 'string',
1819
+ 'default' => ''
1820
+ ),
1821
+ 'browsercache.security.csp.default' => array(
1822
+ 'type' => 'string',
1823
+ 'default' => ''
1824
+ ),
1825
+
1826
+
1827
 
1828
  'mobile.configuration_overloaded' => array(
1829
  'type' => 'boolean',
DbCache_Wpdb.php CHANGED
@@ -129,11 +129,11 @@ class DbCache_Wpdb extends DbCache_WpdbBase {
129
  $processor->w3tc_usage_statistics_of_request( $storage );
130
  }
131
 
132
- function flush_cache() {
133
  $v = true;
134
 
135
  foreach ( $this->processors as $processor )
136
- $v &= $processor->flush_cache();
137
 
138
  return $v;
139
  }
129
  $processor->w3tc_usage_statistics_of_request( $storage );
130
  }
131
 
132
+ function flush_cache( $extras = array() ) {
133
  $v = true;
134
 
135
  foreach ( $this->processors as $processor )
136
+ $v &= $processor->flush_cache( $extras );
137
 
138
  return $v;
139
  }
DbCache_WpdbInjection.php CHANGED
@@ -149,7 +149,7 @@ class DbCache_WpdbInjection {
149
  public function w3tc_usage_statistics_of_request( $storage ) {
150
  }
151
 
152
- public function flush_cache() {
153
  return true;
154
  }
155
  }
149
  public function w3tc_usage_statistics_of_request( $storage ) {
150
  }
151
 
152
+ public function flush_cache( $extras = array() ) {
153
  return true;
154
  }
155
  }
DbCache_WpdbInjection_QueryCaching.php CHANGED
@@ -70,6 +70,7 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
70
  private $debug = false;
71
  private $reject_logged = false;
72
  private $reject_constants;
 
73
 
74
  /**
75
  * Result of check if caching is possible at the level of current http request
@@ -90,6 +91,7 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
90
  $this->debug = $c->get_boolean( 'dbcache.debug' );
91
  $this->reject_logged = $c->get_boolean( 'dbcache.reject.logged' );
92
  $this->reject_constants = $c->get_array( 'dbcache.reject.constants' );
 
93
  }
94
 
95
  /**
@@ -107,23 +109,30 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
107
  $cached = false;
108
  $data = false;
109
  $time_total = 0;
 
 
110
 
111
  $this->query_total++;
112
 
113
  $caching = $this->_can_cache( $query, $reason );
114
  if ( preg_match( '~^\s*start transaction\b~is', $query ) ) {
115
  $this->cache_reject_reason = 'transaction';
 
116
  $caching = false;
117
  }
118
 
119
  if ( preg_match( '~^\s*insert\b|^\s*delete\b|^\s*update\b|^\s*replace\b|^\s*commit\b|^\s*truncate\b|^\s*drop\b|^\s*create\b~is', $query ) ) {
120
- if ( $caching ) {
121
- $this->cache_reject_reason = 'modification query';
122
- $caching = false;
123
- }
 
124
 
125
- $group = $this->_get_group( $query );
126
- $this->_flush_cache_group( $group );
 
 
 
127
  }
128
 
129
  if ( $caching ) {
@@ -132,6 +141,7 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
132
  $cache = $this->_get_cache();
133
  $group = $this->_get_group( $query );
134
  $data = $cache->get( md5( $query ), $group );
 
135
  $time_total = $this->wpdb_mixin->timer_stop();
136
  }
137
 
@@ -153,6 +163,13 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
153
  $return_val = $this->next_injection->query( $query );
154
  $time_total = $this->wpdb_mixin->timer_stop();
155
 
 
 
 
 
 
 
 
156
  if ( $caching ) {
157
  $data = array(
158
  'last_error' => $this->wpdb_mixin->last_error,
@@ -165,13 +182,29 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
165
 
166
  $cache = $this->_get_cache();
167
  $group = $this->_get_group( $query );
168
- $cache->set( md5( $query ), $data, $this->_lifetime, $group );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  }
170
  }
171
 
172
  if ( $this->debug ) {
173
  $this->query_stats[] = array(
174
  'query' => $query,
 
175
  'caching' => $caching,
176
  'reason' => $reason,
177
  'cached' => $cached,
@@ -218,7 +251,8 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
218
  */
219
  function replace( $table, $data, $format = null ) {
220
  $group = $this->_get_group( $table );
221
- $this->_flush_cache_group( $group );
 
222
  return $this->next_injection->replace( $table, $data, $format );
223
  }
224
 
@@ -234,7 +268,7 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
234
  */
235
  function update( $table, $data, $where, $format = null, $where_format = null ) {
236
  $group = $this->_get_group( $table );
237
- $this->_flush_cache_group( $group );
238
  return $this->next_injection->update( $table, $data, $where, $format, $where_format );
239
  }
240
 
@@ -243,7 +277,7 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
243
  */
244
  function delete( $table, $where, $where_format = null ) {
245
  $group = $this->_get_group( $table );
246
- $this->_flush_cache_group( $group );
247
  return $this->next_injection->delete( $table, $where, $where_format );
248
  }
249
 
@@ -252,17 +286,27 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
252
  *
253
  * @return boolean
254
  */
255
- function flush_cache() {
256
- return $this->_flush_cache_group( 'all' );
257
  }
258
 
259
- private function _flush_cache_group( $group ) {
 
 
 
 
 
 
260
  $cache = $this->_get_cache();
261
- $flush_groups = $this->_get_flush_groups( $group );
262
  $v = true;
263
 
264
- foreach ( $flush_groups as $f_group )
 
 
 
265
  $v &= $cache->flush( $f_group );
 
266
 
267
  return $v;
268
  }
@@ -537,36 +581,82 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
537
 
538
  private function _get_group( $sql ) {
539
  $sql = strtolower( $sql );
540
- $matched = array();
541
- $options = false. $comments = false;
542
- $prefix = $this->wpdb_mixin->prefix;
543
- $options = preg_match( '~' . $prefix . 'options~i', $sql );
544
- $comments = preg_match( '~' . $prefix . '(comments|commentsmeta)~i', $sql );
545
-
546
- if ( $options && $comments )
547
- return 'options_comments';
548
- if ( $options )
549
- return 'options';
550
- if ( $comments )
551
- return 'comments';
552
- return 'all';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
553
  }
554
 
555
- private function _get_flush_groups( $group ) {
 
 
556
  switch ( $group ) {
557
- case 'all':
558
- return array( 'all', 'options_comments', 'options', 'comments' );
559
- case 'options_comments':
560
- return array( 'options_comments', 'options', 'comments' );
 
 
 
 
 
 
 
 
561
  case 'options':
562
- case 'comments':
563
- return array( 'options_comments', $group );
 
564
  break;
565
  default:
566
- return array( $group );
 
 
 
567
  }
568
- }
569
 
 
 
 
 
 
 
 
570
 
571
  public function get_reject_reason() {
572
  if ( is_null( $this->cache_reject_reason ) )
@@ -641,21 +731,23 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
641
 
642
  if ( count( $this->query_stats ) ) {
643
  $strings[] = "SQL info:";
644
- $strings[] = sprintf( "%s | %s | %s | % s | %s | %s",
645
  str_pad( '#', 5, ' ', STR_PAD_LEFT ), str_pad( 'Time (s)', 8, ' ', STR_PAD_LEFT ),
646
  str_pad( 'Caching (Reject reason)', 30, ' ', STR_PAD_BOTH ),
647
  str_pad( 'Status', 10, ' ', STR_PAD_BOTH ),
648
  str_pad( 'Data size (b)', 13, ' ', STR_PAD_LEFT ),
 
649
  'Query' );
650
 
651
  foreach ( $this->query_stats as $index => $query ) {
652
- $strings[] = sprintf( "%s | %s | %s | %s | %s | %s",
653
  str_pad( $index + 1, 5, ' ', STR_PAD_LEFT ),
654
  str_pad( round( $query['time_total'], 4 ), 8, ' ', STR_PAD_LEFT ),
655
  str_pad( ( $query['caching'] ? 'enabled'
656
  : sprintf( 'disabled (%s)', $query['reason'] ) ), 30, ' ', STR_PAD_BOTH ),
657
  str_pad( ( $query['cached'] ? 'cached' : 'not cached' ), 10, ' ', STR_PAD_BOTH ),
658
  str_pad( $query['data_size'], 13, ' ', STR_PAD_LEFT ),
 
659
  trim( $query['query'] ) );
660
  }
661
  }
70
  private $debug = false;
71
  private $reject_logged = false;
72
  private $reject_constants;
73
+ private $use_filters;
74
 
75
  /**
76
  * Result of check if caching is possible at the level of current http request
91
  $this->debug = $c->get_boolean( 'dbcache.debug' );
92
  $this->reject_logged = $c->get_boolean( 'dbcache.reject.logged' );
93
  $this->reject_constants = $c->get_array( 'dbcache.reject.constants' );
94
+ $this->use_filters = $this->_config->get_boolean( 'dbcache.use_filters' );
95
  }
96
 
97
  /**
109
  $cached = false;
110
  $data = false;
111
  $time_total = 0;
112
+ $group = '';
113
+ $flush_after_query = false;
114
 
115
  $this->query_total++;
116
 
117
  $caching = $this->_can_cache( $query, $reason );
118
  if ( preg_match( '~^\s*start transaction\b~is', $query ) ) {
119
  $this->cache_reject_reason = 'transaction';
120
+ $reason = $this->cache_reject_reason;
121
  $caching = false;
122
  }
123
 
124
  if ( preg_match( '~^\s*insert\b|^\s*delete\b|^\s*update\b|^\s*replace\b|^\s*commit\b|^\s*truncate\b|^\s*drop\b|^\s*create\b~is', $query ) ) {
125
+ $this->cache_reject_reason = 'modification query';
126
+ $reason = $this->cache_reject_reason;
127
+ $caching = false;
128
+ $flush_after_query = true;
129
+ }
130
 
131
+ if ( $this->use_filters && function_exists( 'apply_filters' ) ) {
132
+ $reason = apply_filters( 'w3tc_dbcache_can_cache_sql',
133
+ ( $caching ? '' : $reason ), $query );
134
+
135
+ $caching = empty( $reason );
136
  }
137
 
138
  if ( $caching ) {
141
  $cache = $this->_get_cache();
142
  $group = $this->_get_group( $query );
143
  $data = $cache->get( md5( $query ), $group );
144
+
145
  $time_total = $this->wpdb_mixin->timer_stop();
146
  }
147
 
163
  $return_val = $this->next_injection->query( $query );
164
  $time_total = $this->wpdb_mixin->timer_stop();
165
 
166
+ if ( $flush_after_query ) {
167
+ $group = $this->_get_group( $query );
168
+
169
+ $this->_flush_cache_for_sql_group( $group,
170
+ array( 'modification_query' => $query ) );
171
+ }
172
+
173
  if ( $caching ) {
174
  $data = array(
175
  'last_error' => $this->wpdb_mixin->last_error,
182
 
183
  $cache = $this->_get_cache();
184
  $group = $this->_get_group( $query );
185
+
186
+ $filter_data = array(
187
+ 'query' => $query,
188
+ 'group' => $group,
189
+ 'content' => $data,
190
+ 'expiration' => $this->_lifetime
191
+ );
192
+
193
+ if ( $this->use_filters && function_exists( 'apply_filters' ) ) {
194
+ $filter_data = apply_filters( 'w3tc_dbcache_cache_set', $filter_data );
195
+ }
196
+
197
+ $cache->set( md5( $filter_data['query'] ),
198
+ $filter_data['content'],
199
+ $filter_data['expiration'],
200
+ $filter_data['group'] );
201
  }
202
  }
203
 
204
  if ( $this->debug ) {
205
  $this->query_stats[] = array(
206
  'query' => $query,
207
+ 'group' => $group,
208
  'caching' => $caching,
209
  'reason' => $reason,
210
  'cached' => $cached,
251
  */
252
  function replace( $table, $data, $format = null ) {
253
  $group = $this->_get_group( $table );
254
+ $this->_flush_cache_for_sql_group( $group,
255
+ array( 'wpdb_replace' => $table ) );
256
  return $this->next_injection->replace( $table, $data, $format );
257
  }
258
 
268
  */
269
  function update( $table, $data, $where, $format = null, $where_format = null ) {
270
  $group = $this->_get_group( $table );
271
+ $this->_flush_cache_for_sql_group( $group, array( 'wpdb_update' => $table ) );
272
  return $this->next_injection->update( $table, $data, $where, $format, $where_format );
273
  }
274
 
277
  */
278
  function delete( $table, $where, $where_format = null ) {
279
  $group = $this->_get_group( $table );
280
+ $this->_flush_cache_for_sql_group( $group, array( 'wpdb_delete' => $table ) );
281
  return $this->next_injection->delete( $table, $where, $where_format );
282
  }
283
 
286
  *
287
  * @return boolean
288
  */
289
+ function flush_cache( $extras = array() ) {
290
+ return $this->_flush_cache_for_sql_group( 'remaining', $extras );
291
  }
292
 
293
+ private function _flush_cache_for_sql_group( $group, $extras = array() ) {
294
+ if ( $this->debug ) {
295
+ $filename = Util_Debug::log( 'dbcache',
296
+ 'flushing based on sqlquery group ' . $group .
297
+ ' with extras ' . json_encode( $extras ) );
298
+ }
299
+
300
  $cache = $this->_get_cache();
301
+ $flush_groups = $this->_get_flush_groups( $group, $extras );
302
  $v = true;
303
 
304
+ foreach ( $flush_groups as $f_group => $nothing ) {
305
+ if ( $this->debug ) {
306
+ $filename = Util_Debug::log( 'dbcache', 'flush group ' . $f_group );
307
+ }
308
  $v &= $cache->flush( $f_group );
309
+ }
310
 
311
  return $v;
312
  }
581
 
582
  private function _get_group( $sql ) {
583
  $sql = strtolower( $sql );
584
+
585
+ // collect list of tables used in query
586
+ if ( preg_match_all(
587
+ '~(^|[\s,`])' . $this->wpdb_mixin->prefix . '([0-9a-zA-Z_]+)~i', $sql, $m ) ) {
588
+ $tables = array_unique( $m[2] );
589
+ } else {
590
+ $tables = array();
591
+ }
592
+
593
+ if ( $this->contains_only_tables( $tables, array( 'options' => '*' ) ) ) {
594
+ $group = 'options';
595
+ } elseif ( $this->contains_only_tables( $tables, array(
596
+ 'comments' => '*', 'commentsmeta' => '*' ) ) ) {
597
+ $group = 'comments';
598
+ } elseif ( count( $tables ) <= 1 ) {
599
+ $group = 'singletables'; // request with single table affected
600
+ } else {
601
+ $group = 'remaining';
602
+ }
603
+
604
+ if ( $this->use_filters && function_exists( 'apply_filters' ) ) {
605
+ $group = apply_filters( 'w3tc_dbcache_get_sql_group', $group, $sql, $tables );
606
+ }
607
+
608
+ return $group;
609
+ }
610
+
611
+ private function contains_only_tables( $tables, $allowed ) {
612
+ if ( empty( $tables ) ) {
613
+ return false;
614
+ }
615
+
616
+ foreach ( $tables as $t ) {
617
+ if ( !isset( $allowed[$t] ) ) {
618
+ return false;
619
+ }
620
+ }
621
+
622
+ return true;
623
  }
624
 
625
+ private function _get_flush_groups( $group, $extras = array() ) {
626
+ $groups_to_flush = array();
627
+
628
  switch ( $group ) {
629
+ case 'remaining':
630
+ case 'singletables':
631
+ $groups_to_flush = array(
632
+ 'remaining' => '*',
633
+ 'options' => '*',
634
+ 'comments' => '*',
635
+ 'singletables' => '*' );
636
+ break;
637
+ // options are updated on each second request,
638
+ // ignore by default probability that SELECTs with joins with options
639
+ // are critical and don't flush "remaining".
640
+ // That can be changed by w3tc_dbcache_get_flush_groups filter
641
  case 'options':
642
+ $groups_to_flush = array(
643
+ $group => '*'
644
+ );
645
  break;
646
  default:
647
+ $groups_to_flush = array(
648
+ $group => '*',
649
+ 'remaining' => '*'
650
+ );
651
  }
 
652
 
653
+ if ( $this->use_filters && function_exists( 'apply_filters' ) ) {
654
+ $groups_to_flush = apply_filters( 'w3tc_dbcache_get_flush_groups',
655
+ $groups_to_flush, $group, $extras );
656
+ }
657
+
658
+ return $groups_to_flush;
659
+ }
660
 
661
  public function get_reject_reason() {
662
  if ( is_null( $this->cache_reject_reason ) )
731
 
732
  if ( count( $this->query_stats ) ) {
733
  $strings[] = "SQL info:";
734
+ $strings[] = sprintf( "%s | %s | %s | % s | %s | %s | %s",
735
  str_pad( '#', 5, ' ', STR_PAD_LEFT ), str_pad( 'Time (s)', 8, ' ', STR_PAD_LEFT ),
736
  str_pad( 'Caching (Reject reason)', 30, ' ', STR_PAD_BOTH ),
737
  str_pad( 'Status', 10, ' ', STR_PAD_BOTH ),
738
  str_pad( 'Data size (b)', 13, ' ', STR_PAD_LEFT ),
739
+ str_pad( 'Group', 10, ' ', STR_PAD_BOTH ),
740
  'Query' );
741
 
742
  foreach ( $this->query_stats as $index => $query ) {
743
+ $strings[] = sprintf( "%s | %s | %s | %s | %s | %s | %s",
744
  str_pad( $index + 1, 5, ' ', STR_PAD_LEFT ),
745
  str_pad( round( $query['time_total'], 4 ), 8, ' ', STR_PAD_LEFT ),
746
  str_pad( ( $query['caching'] ? 'enabled'
747
  : sprintf( 'disabled (%s)', $query['reason'] ) ), 30, ' ', STR_PAD_BOTH ),
748
  str_pad( ( $query['cached'] ? 'cached' : 'not cached' ), 10, ' ', STR_PAD_BOTH ),
749
  str_pad( $query['data_size'], 13, ' ', STR_PAD_LEFT ),
750
+ str_pad( $query['group'], 10, ' ', STR_PAD_LEFT ),
751
  trim( $query['query'] ) );
752
  }
753
  }
Enterprise_CacheFlush_MakeSnsEvent.php CHANGED
@@ -131,6 +131,15 @@ class Enterprise_CacheFlush_MakeSnsEvent extends Enterprise_SnsBase {
131
  ) );
132
  }
133
 
 
 
 
 
 
 
 
 
 
134
  /**
135
  * Purges/Flushes url
136
  *
131
  ) );
132
  }
133
 
134
+ function flush_group( $group, $extras ) {
135
+ return $this->_prepare_message( array(
136
+ 'action' => 'flush_group',
137
+ 'group' => $group,
138
+ 'extras' => $extras
139
+ ) );
140
+ }
141
+
142
+
143
  /**
144
  * Purges/Flushes url
145
  *
Enterprise_SnsServer.php CHANGED
@@ -125,6 +125,10 @@ class Enterprise_SnsServer extends Enterprise_SnsBase {
125
  elseif ( $action == 'flush_all' )
126
  $executor->flush_all(
127
  isset( $m['extras'] ) ? $m['extras'] : null );
 
 
 
 
128
  elseif ( $action == 'flush_post' )
129
  $executor->flush_post( $m['post_id'] );
130
  elseif ( $action == 'flush_posts' )
125
  elseif ( $action == 'flush_all' )
126
  $executor->flush_all(
127
  isset( $m['extras'] ) ? $m['extras'] : null );
128
+ elseif ( $action == 'flush_group' )
129
+ $executor->flush_group(
130
+ isset( $m['group'] ) ? $m['group'] : null,
131
+ isset( $m['extras'] ) ? $m['extras'] : null );
132
  elseif ( $action == 'flush_post' )
133
  $executor->flush_post( $m['post_id'] );
134
  elseif ( $action == 'flush_posts' )
Extension_Amp_Plugin.php CHANGED
@@ -25,8 +25,13 @@ class Extension_Amp_Plugin {
25
 
26
 
27
  private function is_amp_endpoint() {
28
- if ( is_null( $this->is_amp_endpoint ) && function_exists('is_amp_endpoint') ) {
29
- $this->is_amp_endpoint = is_amp_endpoint();
 
 
 
 
 
30
  }
31
 
32
  return $this->is_amp_endpoint;
25
 
26
 
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;
Extension_CloudFlare_AdminActions.php CHANGED
@@ -21,7 +21,7 @@ class Extension_CloudFlare_AdminActions {
21
  Util_Admin::redirect_with_custom_messages2( array(
22
  'errors' => array(
23
  'cloudflare_flush' =>
24
- __( 'Failed to flush CloudFlare cache: ', 'w3-total-cache' ) .
25
  $ex->getMessage()
26
  )
27
  ) );
21
  Util_Admin::redirect_with_custom_messages2( array(
22
  'errors' => array(
23
  'cloudflare_flush' =>
24
+ __( 'Failed to purge CloudFlare cache: ', 'w3-total-cache' ) .
25
  $ex->getMessage()
26
  )
27
  ) );
Extension_CloudFlare_Api.php CHANGED
@@ -163,6 +163,10 @@ class Extension_CloudFlare_Api {
163
 
164
 
165
  private function _wp_remote_request( $method, $url, $body = array() ) {
 
 
 
 
166
  $result = wp_remote_request( $url, array(
167
  'method' => $method,
168
  'headers' => array(
@@ -174,8 +178,9 @@ class Extension_CloudFlare_Api {
174
  'body' => $body
175
  ) );
176
 
177
- if ( is_wp_error( $result ) )
178
  throw new \Exception( 'Failed to reach API endpoint' );
 
179
 
180
  $response_json = @json_decode( $result['body'], true );
181
  if ( is_null( $response_json ) || !isset( $response_json['success'] ) ) {
163
 
164
 
165
  private function _wp_remote_request( $method, $url, $body = array() ) {
166
+ if ( empty( $this->_email ) || empty( $this->_key ) ) {
167
+ throw new \Exception('Not authenticated');
168
+ }
169
+
170
  $result = wp_remote_request( $url, array(
171
  'method' => $method,
172
  'headers' => array(
178
  'body' => $body
179
  ) );
180
 
181
+ if ( is_wp_error( $result ) ) {
182
  throw new \Exception( 'Failed to reach API endpoint' );
183
+ }
184
 
185
  $response_json = @json_decode( $result['body'], true );
186
  if ( is_null( $response_json ) || !isset( $response_json['success'] ) ) {
Extension_CloudFlare_Plugin.php CHANGED
@@ -103,7 +103,7 @@ class Extension_CloudFlare_Plugin {
103
  $api->purge();
104
  } catch ( \Exception $ex ) {
105
  $action_made['error'] =
106
- 'Failed to purge CloudFlare cache: ' . $ex->getMessage();
107
  }
108
 
109
  $this->flush_operation_requested = false;
103
  $api->purge();
104
  } catch ( \Exception $ex ) {
105
  $action_made['error'] =
106
+ 'CloudFlare cache: ' . $ex->getMessage();
107
  }
108
 
109
  $this->flush_operation_requested = false;
Extension_FragmentCache_WpObjectCache.php CHANGED
@@ -629,7 +629,7 @@ class Extension_FragmentCache_WpObjectCache {
629
  */
630
  private function _fragment_group( $id, $group ) {
631
  if ( empty( $id ) )
632
- return array( 'nogroup', 0 );
633
  $groups = $this->_core->get_registered_fragment_groups();
634
  $use_group = '';
635
  $length = 0;
629
  */
630
  private function _fragment_group( $id, $group ) {
631
  if ( empty( $id ) )
632
+ return array( 'nogroup', 0, false );
633
  $groups = $this->_core->get_registered_fragment_groups();
634
  $use_group = '';
635
  $length = 0;
Extension_NewRelic_Page_View_Apm.php CHANGED
@@ -135,7 +135,7 @@ _e( 'Use <acronym title="Real User Monitoring">RUM</acronym> only for following
135
  _e( 'Select user roles that <acronym title="Real User Monitoring">RUM</acronym> should be enabled for:', 'w3-total-cache' )
136
  ?></span>
137
 
138
- <div id="newrelic_accept_roles">
139
  <?php $saved_roles = $config->get_array( array( 'newrelic', 'accept.roles' ) ); ?>
140
  <input type="hidden" name="newrelic___accept__roles" value="" /><br />
141
  <?php foreach ( get_editable_roles() as $role_name => $role_data ) : ?>
135
  _e( 'Select user roles that <acronym title="Real User Monitoring">RUM</acronym> should be enabled for:', 'w3-total-cache' )
136
  ?></span>
137
 
138
+ <div id="newrelic_accept_roles" class="w3tc_reject_roles">
139
  <?php $saved_roles = $config->get_array( array( 'newrelic', 'accept.roles' ) ); ?>
140
  <input type="hidden" name="newrelic___accept__roles" value="" /><br />
141
  <?php foreach ( get_editable_roles() as $role_name => $role_data ) : ?>
Extension_NewRelic_Service.php CHANGED
@@ -41,15 +41,14 @@ class Extension_NewRelic_Service {
41
  $verified = array();
42
  $version = explode( '.', PHP_VERSION );
43
  $php_version = sprintf( '%s.%s.%s', $version[0], $version[1], $version[2] );
44
- $php_version_ok = ( version_compare( $php_version, '5.2', '>' ) &&
45
- version_compare( $php_version, '5.5', '<' ) );
46
 
47
  $supported_string = __( 'Supported', 'w3-total-cache' );
48
 
49
  $verified[__( 'PHP version', 'w3-total-cache' )] =
50
  ( $php_version_ok ? $supported_string :
51
- sprintf( __( 'Not supported: %s. Supported versions are %s.', 'w3-total-cache' ),
52
- $php_version, implode( ', ', $php_versions ) ) );
53
 
54
  $os_name = php_uname( 's' );
55
  switch ( $os_name ) {
@@ -119,7 +118,7 @@ class Extension_NewRelic_Service {
119
  switch ( true ) {
120
  case Util_Environment::is_apache():
121
  if ( $ws_version )
122
- $ws_check = version_compare( $ws_version, '2.2', '>=' ) || version_compare( $ws_version, '2.4', '>=' );
123
  break;
124
  case Util_Environment::is_nginx():
125
  $ws_check = php_sapi_name() == 'fpm-fcgi';
41
  $verified = array();
42
  $version = explode( '.', PHP_VERSION );
43
  $php_version = sprintf( '%s.%s.%s', $version[0], $version[1], $version[2] );
44
+ $php_version_ok = version_compare( $php_version, '5.2', '>' );
 
45
 
46
  $supported_string = __( 'Supported', 'w3-total-cache' );
47
 
48
  $verified[__( 'PHP version', 'w3-total-cache' )] =
49
  ( $php_version_ok ? $supported_string :
50
+ sprintf( __( 'Not supported: %s.', 'w3-total-cache' ),
51
+ $php_version ) );
52
 
53
  $os_name = php_uname( 's' );
54
  switch ( $os_name ) {
118
  switch ( true ) {
119
  case Util_Environment::is_apache():
120
  if ( $ws_version )
121
+ $ws_check = version_compare( $ws_version, '2.2', '>=' );
122
  break;
123
  case Util_Environment::is_nginx():
124
  $ws_check = php_sapi_name() == 'fpm-fcgi';
Extension_NewRelic_Widget_View.css CHANGED
@@ -1,8 +1,8 @@
1
- #new-relic-widget ul li, .maxcdn-netdna-widget-base ul li {
2
  margin-bottom: 3px;
3
  padding: 0;
4
  }
5
- #new-relic-widget ul li span, .maxcdn-netdna-widget-base .summary ul li span{
6
  display: block;
7
  font-weight: bold;
8
  width: 110px;
@@ -74,4 +74,4 @@
74
 
75
  .w3tcnr_topfive_message {
76
  padding: 10px;
77
- }
1
+ #new-relic-widget ul li {
2
  margin-bottom: 3px;
3
  padding: 0;
4
  }
5
+ #new-relic-widget ul li span {
6
  display: block;
7
  font-weight: bold;
8
  width: 110px;
74
 
75
  .w3tcnr_topfive_message {
76
  padding: 10px;
77
+ }
Extension_Swarmify_Plugin_Admin.php CHANGED
@@ -41,8 +41,6 @@ class Extension_Swarmify_Plugin_Admin {
41
  array( $this, 'w3tc_extension_page_swarmify' ) );
42
 
43
  add_filter( 'w3tc_admin_actions', array( $this, 'w3tc_admin_actions' ) );
44
-
45
- add_filter( 'w3tc_notes', array( $this, 'w3tc_notes' ) );
46
  }
47
 
48
 
@@ -61,29 +59,6 @@ class Extension_Swarmify_Plugin_Admin {
61
 
62
 
63
 
64
- public function w3tc_notes( $notes ) {
65
- $config = Dispatcher::config();
66
- $state = Dispatcher::config_state();
67
-
68
- $api_key = $config->get_string( array( 'swarmify', 'api_key' ) );
69
- $is_filled = !empty( $api_key );
70
-
71
- if ( !$is_filled && !$state->get_boolean( 'extension.swarmify.hide_note_activate_suggestion' ) ) {
72
- $notes['swarmify_activate_suggestion'] = sprintf(
73
- __( 'Just as the load time and overall performance of your website impacts user satisfaction, so does the performance of your online videos. Optimize your video performance by enabling the <a href="%s">Swarmify SmartVideo™ solution</a>. %s',
74
- 'w3-total-cache' ),
75
- esc_attr( Extension_Swarmify_Core::signup_url() ),
76
- Util_Ui::button_hide_note2( array(
77
- 'w3tc_default_config_state' => 'y',
78
- 'key' => 'extension.swarmify.hide_note_activate_suggestion',
79
- 'value' => 'true' ) ) );
80
- }
81
-
82
- return $notes;
83
- }
84
-
85
-
86
-
87
  public function w3tc_config_save( $config ) {
88
  // frontend activity
89
  $api_key = $config->get_string( array( 'swarmify', 'api_key' ) );
41
  array( $this, 'w3tc_extension_page_swarmify' ) );
42
 
43
  add_filter( 'w3tc_admin_actions', array( $this, 'w3tc_admin_actions' ) );
 
 
44
  }
45
 
46
 
59
 
60
 
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  public function w3tc_config_save( $config ) {
63
  // frontend activity
64
  $api_key = $config->get_string( array( 'swarmify', 'api_key' ) );
Generic_AdminActions_Default.php CHANGED
@@ -516,13 +516,16 @@ class Generic_AdminActions_Default {
516
  }
517
 
518
  switch ( $this->_config->get_string( 'cdn.engine' ) ) {
519
- case 'ftp':
520
- $config->set( 'cdn.ftp.domain', $cdn_domains );
521
  break;
522
 
523
- case 's3':
524
- case 's3_compatible':
525
- $config->set( 'cdn.s3.cname', $cdn_domains );
 
 
 
526
  break;
527
 
528
  case 'cf':
@@ -533,17 +536,26 @@ class Generic_AdminActions_Default {
533
  $config->set( 'cdn.cf2.cname', $cdn_domains );
534
  break;
535
 
536
- case 'rackspace_cdn':
537
- $config->set( 'cdn.rackspace_cdn.domains', $cdn_domains );
538
  break;
539
 
540
- case 'rscf':
541
- $config->set( 'cdn.rscf.cname', $cdn_domains );
542
  break;
543
 
544
- case 'azure':
545
- $config->set( 'cdn.azure.cname', $cdn_domains );
 
 
 
 
 
 
 
 
546
  break;
 
547
  case 'mirror':
548
  $config->set( 'cdn.mirror.domain', $cdn_domains );
549
  break;
@@ -558,24 +570,27 @@ class Generic_AdminActions_Default {
558
  $config->set( 'cdn.maxcdn.domain', $cdn_domains );
559
  break;
560
 
561
- case 'cotendo':
562
- $config->set( 'cdn.cotendo.domain', $cdn_domains );
563
  break;
564
 
565
- case 'edgecast':
566
- $config->set( 'cdn.edgecast.domain', $cdn_domains );
567
  break;
568
 
569
- case 'att':
570
- $config->set( 'cdn.att.domain', $cdn_domains );
 
571
  break;
572
 
573
- case 'akamai':
574
- $config->set( 'cdn.akamai.domain', $cdn_domains );
575
- break;
 
 
 
576
 
577
- case 'highwinds':
578
- $config->set( 'cdn.highwinds.host.domains', $cdn_domains );
579
  break;
580
  }
581
  }
516
  }
517
 
518
  switch ( $this->_config->get_string( 'cdn.engine' ) ) {
519
+ case 'akamai':
520
+ $config->set( 'cdn.akamai.domain', $cdn_domains );
521
  break;
522
 
523
+ case 'att':
524
+ $config->set( 'cdn.att.domain', $cdn_domains );
525
+ break;
526
+
527
+ case 'azure':
528
+ $config->set( 'cdn.azure.cname', $cdn_domains );
529
  break;
530
 
531
  case 'cf':
536
  $config->set( 'cdn.cf2.cname', $cdn_domains );
537
  break;
538
 
539
+ case 'cotendo':
540
+ $config->set( 'cdn.cotendo.domain', $cdn_domains );
541
  break;
542
 
543
+ case 'edgecast':
544
+ $config->set( 'cdn.edgecast.domain', $cdn_domains );
545
  break;
546
 
547
+ case 'ftp':
548
+ $config->set( 'cdn.ftp.domain', $cdn_domains );
549
+ break;
550
+
551
+ case 'highwinds':
552
+ $config->set( 'cdn.highwinds.host.domains', $cdn_domains );
553
+ break;
554
+
555
+ case 'limelight':
556
+ $config->set( 'cdn.limelight.host.domains', $cdn_domains );
557
  break;
558
+
559
  case 'mirror':
560
  $config->set( 'cdn.mirror.domain', $cdn_domains );
561
  break;
570
  $config->set( 'cdn.maxcdn.domain', $cdn_domains );
571
  break;
572
 
573
+ case 'rackspace_cdn':
574
+ $config->set( 'cdn.rackspace_cdn.domains', $cdn_domains );
575
  break;
576
 
577
+ case 'rscf':
578
+ $config->set( 'cdn.rscf.cname', $cdn_domains );
579
  break;
580
 
581
+ case 's3':
582
+ case 's3_compatible':
583
+ $config->set( 'cdn.s3.cname', $cdn_domains );
584
  break;
585
 
586
+ case 'stackpath':
587
+ $v = $config->get( 'cdn.stackpath.domain' );
588
+ if ( isset( $v['http_default'] ) )
589
+ $cdn_domains['http_default'] = $v['http_default'];
590
+ if ( isset( $v['https_default'] ) )
591
+ $cdn_domains['https_default'] = $v['https_default'];
592
 
593
+ $config->set( 'cdn.stackpath.domain', $cdn_domains );
 
594
  break;
595
  }
596
  }
Generic_AdminActions_Flush.php CHANGED
@@ -390,7 +390,7 @@ class Generic_AdminActions_Flush {
390
  ), true );
391
  } else {
392
  Util_Admin::redirect_with_custom_messages2( array(
393
- 'errors' => array( 'Failed to flush: ' .
394
  implode( ', ', $errors ) )
395
  ), true );
396
  }
390
  ), true );
391
  } else {
392
  Util_Admin::redirect_with_custom_messages2( array(
393
+ 'errors' => array( 'Failed to purge: ' .
394
  implode( ', ', $errors ) )
395
  ), true );
396
  }
Generic_Faq.php CHANGED
@@ -5,102 +5,62 @@ class Generic_Faq {
5
  static public function sections() {
6
  // name => column where to show
7
  return array(
8
- 'General' => 1,
9
- 'Usage' => 1,
10
- 'Compatibility' => 1,
11
- 'Minification' => 2,
12
- 'CDN' => 2,
13
- 'Browser Cache' => 3,
14
- 'Errors / Debugging' => 3,
15
- 'Requirements' => 3,
16
- 'Developers' => 3,
17
- 'Extensions' => 3
 
18
  );
19
  }
20
 
21
 
22
 
23
  /**
24
- * Parses FAQ XML file into array
25
- *
26
- * @return array
27
  */
28
- static public function parse() {
29
- $config = Dispatcher::config();
30
  $faq = array();
31
 
32
- self::parse_file( $faq, 'faq', '', '' );
33
-
34
- if ( Util_Environment::is_w3tc_pro( $config ) )
35
- self::parse_file( $faq, 'faq-pro', 'pro', '<b>Pro:</b> ' );
36
-
37
- return $faq;
38
- }
39
-
40
-
41
-
42
- static private function parse_file( &$entries, $filename_base, $flag,
43
- $question_prefix ) {
44
- $filename = W3TC_LANGUAGES_DIR . '/' . $filename_base . '-' .
45
- get_locale() . '.xml';
46
- if ( !file_exists( $filename ) )
47
- $filename = W3TC_LANGUAGES_DIR . '/' . $filename_base . '-en_US.xml';
48
-
49
- $xml = @file_get_contents( $filename );
50
- if ( empty( $xml ) )
51
- return;
52
-
53
- if ( !function_exists( 'xml_parser_create' ) )
54
- return;
55
-
56
- $parser = @xml_parser_create( 'UTF-8' );
57
-
58
- xml_parser_set_option( $parser, XML_OPTION_TARGET_ENCODING, 'UTF-8' );
59
- xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
60
- xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
61
-
62
- $values = null;
63
- $result = xml_parse_into_struct( $parser, $xml, $values );
64
- xml_parser_free( $parser );
65
 
66
- if ( !$result )
67
- return;
68
 
69
- $section = 'General';
70
- $entry = null;
71
 
72
- foreach ( $values as $value ) {
73
- switch ( $value['type'] ) {
74
- case 'open':
75
- if ( $value['tag'] === 'section' ) {
76
- $section = $value['attributes']['name'];
77
- if ( !isset( $entries[$section] ) )
78
- $entries[$section] = array();
79
- } else if ( $value['tag'] === 'entry' ) {
80
- $entry = array(
81
- 'flag' => $flag
82
- );
83
- }
84
- break;
85
 
86
- case 'complete':
87
- if ( $value['tag'] == 'question' )
88
- $entry['question'] = $question_prefix . $value['value'];
89
- else if ( $value['tag'] == 'answer' )
90
- $entry['answer'] = $value['value'];
91
- else if ( $value['tag'] == 'tag' )
92
- $entry['tag'] = $value['value'];
93
- break;
94
 
95
- case 'close':
96
- if ( $value['tag'] == 'entry' ) {
97
- if ( !isset( $entry['tag'] ) )
98
- $entry['tag'] = md5( $entry['answer'] );
 
 
 
 
99
 
100
- $entries[$section][] = $entry;
101
- }
102
- break;
 
 
 
103
  }
104
  }
 
 
105
  }
106
  }
5
  static public function sections() {
6
  // name => column where to show
7
  return array(
8
+ 'General' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-General',
9
+ 'Usage' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Usage',
10
+ 'Compatibility' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Compatibility',
11
+ 'Minification' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Minification',
12
+ 'CDN' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-CDN',
13
+ 'Browser Cache' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Browser-Cache',
14
+ 'Errors / Debugging' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Debugging',
15
+ 'Requirements' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Requirements',
16
+ 'Developers' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Developers',
17
+ 'Extensions' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Extensions',
18
+ 'Installation' => 'https://github.com/Auctollo/w3-total-cache/wiki/FAQ%3A-Installation'
19
  );
20
  }
21
 
22
 
23
 
24
  /**
25
+ * Returns list of questions for section
 
 
26
  */
27
+ static public function parse( $section ) {
 
28
  $faq = array();
29
 
30
+ $sections = self::sections();
31
+ if ( !isset( $sections[ $section ] ) ) {
32
+ return null;
33
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
+ $url = $sections[ $section ];
 
36
 
 
 
37
 
38
+ $response = wp_remote_get( $url );
39
+ if ( is_wp_error( $response ) ) {
40
+ return null;
41
+ }
 
 
 
 
 
 
 
 
 
42
 
43
+ $html = $response['body'];
44
+ $questions = array();
 
 
 
 
 
 
45
 
46
+ $m = array();
47
+ preg_match_all( '~<h1>\s*<a[^>]+href="(#[^"]+)[^>]+>.*?</a>([^<]+)</h1>~mi',
48
+ $html, $m );
49
+ if ( is_array( $m ) && count( $m ) > 1 ) {
50
+ for ( $n = 0; $n < count( $m[1] ); $n++ ) {
51
+ $questions[] = array('q' => $m[2][$n], 'a' => $url . $m[1][$n] );
52
+ }
53
+ }
54
 
55
+ $m = array();
56
+ preg_match_all( '~<li>\s*<a[^>]+href="([^"]+)[^>]+>(.*?)</a>\s*[.]s*</li>~mi',
57
+ $html, $m );
58
+ if ( is_array( $m ) && count( $m ) > 1 ) {
59
+ for ( $n = 0; $n < count( $m[1] ); $n++ ) {
60
+ $questions[] = array('q' => $m[2][$n], 'a' => $m[1][$n] );
61
  }
62
  }
63
+
64
+ return $questions;
65
  }
66
  }
Generic_Page_Faq.php DELETED
@@ -1,32 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
-
5
-
6
- class Generic_Page_Faq extends Base_Page_Settings {
7
- /**
8
- * Current page
9
- *
10
- * @var string
11
- */
12
- protected $_page = 'w3tc_faq';
13
-
14
- /**
15
- * FAQ tab
16
- *
17
- * @return void
18
- */
19
- function view() {
20
- $faq = Generic_Faq::parse();
21
- $sections = Generic_Faq::sections();
22
-
23
- $columns = array();
24
- foreach ( $sections as $section => $number ) {
25
- if ( !isset( $columns[$number] ) )
26
- $columns[$number] = array();
27
- $columns[$number][] = $section;
28
- }
29
-
30
- include W3TC_INC_DIR . '/options/faq.php';
31
- }
32
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Generic_Plugin.php CHANGED
@@ -489,6 +489,8 @@ class Generic_Plugin {
489
  if ( Util_Content::is_database_error( $buffer ) ) {
490
  status_header( 503 );
491
  } else {
 
 
492
  if ( Util_Content::can_print_comment( $buffer ) ) {
493
  /**
494
  * Add footer comment
@@ -518,13 +520,13 @@ class Generic_Plugin {
518
  Util_Content::escape_comment( implode( "\r\n", $strings ) ) .
519
  "\r\n-->";
520
  }
521
-
522
- $buffer = apply_filters( 'w3tc_process_content', $buffer );
523
  }
524
 
525
  $buffer = Util_Bus::do_ob_callbacks(
526
  array( 'swarmify', 'minify', 'newrelic', 'cdn', 'browsercache', 'pagecache' ),
527
  $buffer );
 
 
528
  }
529
 
530
  return $buffer;
489
  if ( Util_Content::is_database_error( $buffer ) ) {
490
  status_header( 503 );
491
  } else {
492
+ $buffer = apply_filters( 'w3tc_process_content', $buffer );
493
+
494
  if ( Util_Content::can_print_comment( $buffer ) ) {
495
  /**
496
  * Add footer comment
520
  Util_Content::escape_comment( implode( "\r\n", $strings ) ) .
521
  "\r\n-->";
522
  }
 
 
523
  }
524
 
525
  $buffer = Util_Bus::do_ob_callbacks(
526
  array( 'swarmify', 'minify', 'newrelic', 'cdn', 'browsercache', 'pagecache' ),
527
  $buffer );
528
+
529
+ $buffer = apply_filters( 'w3tc_processed_content', $buffer );
530
  }
531
 
532
  return $buffer;
Generic_Plugin_Admin.php CHANGED
@@ -372,7 +372,10 @@ class Generic_Plugin_Admin {
372
  }
373
 
374
  global $pagenow;
375
- if ( $pagenow == 'plugins.php' || $this->is_w3tc_page ) {
 
 
 
376
  /**
377
  * Only admin can see W3TC notices and errors
378
  */
@@ -473,8 +476,8 @@ class Generic_Plugin_Admin {
473
  $n = 0;
474
 
475
  foreach ( $sections as $section => $data ) {
476
- $content = '<div class="w3tchelp_content w3tchelp_section_' .
477
- md5( $section ) . '"></div>';
478
 
479
  $screen->add_help_tab( array(
480
  'id' => 'w3tc_faq_' . $n,
@@ -486,24 +489,17 @@ class Generic_Plugin_Admin {
486
  }
487
 
488
  public function w3tc_ajax_faq() {
489
- $sections = Generic_Faq::sections();
490
- $faq = Generic_Faq::parse();
491
 
 
492
  $response = array();
493
 
494
- foreach ( $sections as $section => $data ) {
495
- $entries = $faq[$section];
496
- $columns = array_chunk( $entries, ceil( count( $entries ) / 3 ) );
497
-
498
- ob_start();
499
- include W3TC_INC_OPTIONS_DIR . '/common/help.php';
500
- $content = ob_get_contents();
501
- ob_end_clean();
502
 
503
- $response[md5( $section )] = $content;
504
- }
505
-
506
- echo json_encode( $response );
507
  }
508
 
509
 
@@ -780,24 +776,22 @@ class Generic_Plugin_Admin {
780
  }
781
  }
782
 
783
- if ( Util_Admin::is_w3tc_admin_page() ) {
784
- $errors = apply_filters( 'w3tc_errors', $errors );
785
- $notes = apply_filters( 'w3tc_notes', $notes );
786
-
787
- /**
788
- * Show messages
789
- */
790
- foreach ( $notes as $key => $note ) {
791
- echo sprintf(
792
- '<div class="updated w3tc_note" id="%s"><p>%s</p></div>',
793
- $key,
794
- $note );
795
- }
796
 
797
- foreach ( $errors as $key => $error ) {
798
- echo sprintf( '<div class="error w3tc_error" id="%s"><p>%s</p></div>',
799
- $key, $error );
800
- }
801
  }
802
  }
803
  }
372
  }
373
 
374
  global $pagenow;
375
+ if ( $pagenow == 'plugins.php' || $this->is_w3tc_page ||
376
+ isset( $_REQUEST['w3tc_note'] ) ||
377
+ isset( $_REQUEST['w3tc_error'] ) ||
378
+ isset( $_REQUEST['w3tc_message'] ) ) {
379
  /**
380
  * Only admin can see W3TC notices and errors
381
  */
476
  $n = 0;
477
 
478
  foreach ( $sections as $section => $data ) {
479
+ $content = '<div class="w3tchelp_content" data-section="' .
480
+ $section . '"></div>';
481
 
482
  $screen->add_help_tab( array(
483
  'id' => 'w3tc_faq_' . $n,
489
  }
490
 
491
  public function w3tc_ajax_faq() {
492
+ $section = $_REQUEST['section'];
 
493
 
494
+ $entries = Generic_Faq::parse( $section );
495
  $response = array();
496
 
497
+ ob_start();
498
+ include W3TC_DIR . '/Generic_Plugin_Admin_View_Faq.php';
499
+ $content = ob_get_contents();
500
+ ob_end_clean();
 
 
 
 
501
 
502
+ echo json_encode( array( 'content' => $content ) );
 
 
 
503
  }
504
 
505
 
776
  }
777
  }
778
 
779
+ $errors = apply_filters( 'w3tc_errors', $errors );
780
+ $notes = apply_filters( 'w3tc_notes', $notes );
781
+
782
+ /**
783
+ * Show messages
784
+ */
785
+ foreach ( $notes as $key => $note ) {
786
+ echo sprintf(
787
+ '<div class="updated w3tc_note" id="%s"><p>%s</p></div>',
788
+ $key,
789
+ $note );
790
+ }
 
791
 
792
+ foreach ( $errors as $key => $error ) {
793
+ echo sprintf( '<div class="error w3tc_error" id="%s"><p>%s</p></div>',
794
+ $key, $error );
 
795
  }
796
  }
797
  }
Generic_Plugin_AdminNotifications.php CHANGED
@@ -53,20 +53,28 @@ class Generic_Plugin_AdminNotifications {
53
  $state = Dispatcher::config_state_master();
54
 
55
  // support us
 
56
  $support_reminder =
57
- $state->get_integer( 'common.support_us_invitations' ) < 3 &&
58
  ( $state->get_integer( 'common.install' ) <
59
- ( time() - W3TC_SUPPORT_US_TIMEOUT ) ) &&
60
  ( $state->get_integer( 'common.next_support_us_invitation' ) <
61
  time() ) &&
62
  $this->_config->get_string( 'common.support' ) == '' &&
63
  !$this->_config->get_boolean( 'common.tweeted' );
64
 
65
  if ( $support_reminder ) {
 
 
 
 
 
 
 
 
66
  $state->set( 'common.next_support_us_invitation',
67
- time() + W3TC_SUPPORT_US_TIMEOUT );
68
- $state->set( 'common.support_us_invitations',
69
- $state->get_integer( 'common.support_us_invitations' ) + 1 );
70
  $state->save();
71
 
72
  do_action( 'w3tc_message_action_generic_support_us' );
53
  $state = Dispatcher::config_state_master();
54
 
55
  // support us
56
+ $day7 = 604800;
57
  $support_reminder =
58
+ $state->get_integer( 'common.support_us_invitations' ) < 5 &&
59
  ( $state->get_integer( 'common.install' ) <
60
+ ( time() - $day7 ) ) &&
61
  ( $state->get_integer( 'common.next_support_us_invitation' ) <
62
  time() ) &&
63
  $this->_config->get_string( 'common.support' ) == '' &&
64
  !$this->_config->get_boolean( 'common.tweeted' );
65
 
66
  if ( $support_reminder ) {
67
+ $invitations = $state->get_integer( 'common.support_us_invitations' );
68
+
69
+ if ( $invitations <= 0 ) {
70
+ $delay = 259200; // delay 3 days to day10
71
+ } else {
72
+ $delay = 2592000;
73
+ }
74
+
75
  $state->set( 'common.next_support_us_invitation',
76
+ time() + $delay );
77
+ $state->set( 'common.support_us_invitations', $invitations + 1 );
 
78
  $state->save();
79
 
80
  do_action( 'w3tc_message_action_generic_support_us' );
inc/options/common/help.php → Generic_Plugin_Admin_View_Faq.php RENAMED
@@ -8,17 +8,15 @@ if ( !defined( 'W3TC' ) )
8
  <div id="w3tc-help">
9
  <p><?php _e( 'Request professional <a href="admin.php?page=w3tc_support" style="color: red;"><strong>support</strong></a> or troubleshoot issues using the common questions below:', 'w3-total-cache' ); ?></p>
10
 
11
- <?php foreach ( $columns as $entries ): ?>
12
  <ul>
13
  <?php foreach ( $entries as $entry ): ?>
14
  <li>
15
- <a href="admin.php?page=w3tc_faq#<?php echo $entry['tag']; ?>"><?php
16
- echo $entry['question'];
17
  ?></a>
18
  </li>
19
  <?php endforeach; ?>
20
  </ul>
21
- <?php endforeach; ?>
22
 
23
  <div style="clear: left;"></div>
24
  </div>
8
  <div id="w3tc-help">
9
  <p><?php _e( 'Request professional <a href="admin.php?page=w3tc_support" style="color: red;"><strong>support</strong></a> or troubleshoot issues using the common questions below:', 'w3-total-cache' ); ?></p>
10
 
 
11
  <ul>
12
  <?php foreach ( $entries as $entry ): ?>
13
  <li>
14
+ <a href="<?php echo htmlspecialchars($entry['a']) ?>" target="_blank"><?php
15
+ echo htmlspecialchars($entry['q'])
16
  ?></a>
17
  </li>
18
  <?php endforeach; ?>
19
  </ul>
 
20
 
21
  <div style="clear: left;"></div>
22
  </div>
Generic_WidgetSpreadTheWord.js CHANGED
@@ -1,4 +1,8 @@
1
  jQuery(function() {
 
 
 
 
2
  jQuery('.button-share').live('click', function() {
3
  window.open('https://plus.google.com/share?url=' +
4
  encodeURIComponent(w3tc_spread_the_word_product_url), '_blank');
1
  jQuery(function() {
2
+ jQuery('.button-vote').live('click', function() {
3
+ window.open('https://wordpress.org/support/plugin/w3-total-cache/reviews/#new-post');
4
+ });
5
+
6
  jQuery('.button-share').live('click', function() {
7
  window.open('https://plus.google.com/share?url=' +
8
  encodeURIComponent(w3tc_spread_the_word_product_url), '_blank');
Generic_WidgetSpreadTheWord_View.php CHANGED
@@ -5,9 +5,10 @@ if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
  ?>
8
- <p><?php _e( "We're working to make WordPress better. Please support us, here's how:", 'w3-total-cache' ) ?></p>
9
  <ul>
10
- <li><label>Share: </label><input type="button" class="button button-share" value="Share on Google+ Now" /></li>
 
11
  <li><label>Tweet: </label><input type="button" class="button button-tweet" value="Post to Twitter Now" /></li>
12
  <li><label>Like: </label><input type="button" class="button button-like" value="Like on Facebook Now" /></li>
13
  <li><label><?php _e( 'Rate:', 'w3-total-cache' )?> </label><input type="button" class="button button-rating" value="Vote &amp; Rate Now" /></li>
@@ -18,8 +19,9 @@ if ( !defined( 'W3TC' ) )
18
  <option value="<?php echo esc_attr( $support_id ); ?>" <?php selected( $support, $support_id ); ?>><?php echo esc_attr( $support_name ); ?></option>
19
  <?php endforeach; ?>
20
  </select>
21
- </li>
22
  </ul>
23
 
24
- <p><?php _e( 'Or manually place a link, here is the code:', 'w3-total-cache' ) ?></p>
25
- <div class="w3tc-manual-link widefat"><p><?php echo sprintf( __( 'Optimization %s by W3 EDGE', 'w3-total-cache' ), "&lt;a href=&quot;https://www.w3-edge.com/products/&quot; rel=&quot;nofollow&quot;&gt;WordPress Plugins&lt;/a&gt;" )?></p></div>
 
5
  die();
6
 
7
  ?>
8
+ <p><?php _e( "Enjoying W3TC? Please support us!", 'w3-total-cache' ) ?></p>
9
  <ul>
10
+ <li><label>Vote: </label><input type="button" class="button button-vote" value="Give us a 5 stars!" />
11
+ <!-- <li><label>Share: </label><input type="button" class="button button-share" value="Share on Google+ Now" /></li>
12
  <li><label>Tweet: </label><input type="button" class="button button-tweet" value="Post to Twitter Now" /></li>
13
  <li><label>Like: </label><input type="button" class="button button-like" value="Like on Facebook Now" /></li>
14
  <li><label><?php _e( 'Rate:', 'w3-total-cache' )?> </label><input type="button" class="button button-rating" value="Vote &amp; Rate Now" /></li>
19
  <option value="<?php echo esc_attr( $support_id ); ?>" <?php selected( $support, $support_id ); ?>><?php echo esc_attr( $support_name ); ?></option>
20
  <?php endforeach; ?>
21
  </select>
22
+ </li>-->
23
  </ul>
24
 
25
+ <p>Or please share <a href="admin.php?page=w3tc_support&amp;request_type=new_feature">your feedback</a> so that we can improve!</p>
26
+ <!--<p><?php _e( 'Or manually place a link, here is the code:', 'w3-total-cache' ) ?></p>
27
+ <div class="w3tc-manual-link widefat"><p><?php echo sprintf( __( 'Optimization %s by W3 EDGE', 'w3-total-cache' ), "&lt;a href=&quot;https://www.w3-edge.com/products/&quot; rel=&quot;nofollow&quot;&gt;WordPress Plugins&lt;/a&gt;" )?></p></div>-->
Minify_ContentMinifier.php CHANGED
@@ -246,7 +246,7 @@ class Minify_ContentMinifier {
246
  ) );
247
  }
248
 
249
- if ( $this->_config->get_boolean( 'cdn.enabled' ) && $this->_config->get_boolean( 'cdn.minify.enable' ) ) {
250
  $common = Dispatcher::component( 'Cdn_Core' );
251
  $cdn = $common->get_cdn();
252
 
246
  ) );
247
  }
248
 
249
+ if ( $this->_config->get_boolean( 'cdn.enabled' ) ) {
250
  $common = Dispatcher::component( 'Cdn_Core' );
251
  $cdn = $common->get_cdn();
252
 
Minify_MinifiedFileRequestHandler.php CHANGED
@@ -143,6 +143,7 @@ class Minify_MinifiedFileRequestHandler {
143
  'cacheheaders_enabled' => ( $browsercache && $this->_config->get_boolean( 'browsercache.cssjs.cache.control' ) ),
144
  'cacheheaders' => $this->_config->get_string( 'browsercache.cssjs.cache.policy' )
145
  ),
 
146
  'quiet' => $quiet
147
  ) );
148
 
@@ -366,13 +367,14 @@ class Minify_MinifiedFileRequestHandler {
366
 
367
  $file = Util_Environment::url_to_docroot_filename( $url );
368
 
369
- if ( Util_Environment::is_url( $file ) ) {
370
- $precached_file = $this->_precache_file( $file, $type );
 
371
 
372
  if ( $precached_file ) {
373
- $result[$location][$file] = $precached_file;
374
  } else {
375
- Minify_Core::debug_error( sprintf( 'Unable to cache remote file: "%s"', $file ) );
376
  }
377
  } else {
378
  $path = Util_Environment::document_root() . '/' . $file;
@@ -503,7 +505,10 @@ class Minify_MinifiedFileRequestHandler {
503
  $result = array();
504
  if ( is_array( $files ) && count( $files ) > 0 ) {
505
  foreach ( $files as $file ) {
506
- if ( Util_Environment::is_url( $file ) ) {
 
 
 
507
  $precached_file = $this->_precache_file( $file, $type );
508
 
509
  if ( $precached_file ) {
@@ -512,13 +517,12 @@ class Minify_MinifiedFileRequestHandler {
512
  Minify_Core::debug_error( sprintf( 'Unable to cache remote file: "%s"', $file ) );
513
  }
514
  } else {
515
- $file = Util_Environment::url_to_docroot_filename( $file );
516
- $path = Util_Environment::document_root() . '/' . $file;
517
 
518
  if ( file_exists( $path ) ) {
519
  $result[] = $file;
520
  } else {
521
- Minify_Core::debug_error( sprintf( 'File "%s" doesn\'t exist', $path ) );
522
  }
523
  }
524
  }
143
  'cacheheaders_enabled' => ( $browsercache && $this->_config->get_boolean( 'browsercache.cssjs.cache.control' ) ),
144
  'cacheheaders' => $this->_config->get_string( 'browsercache.cssjs.cache.policy' )
145
  ),
146
+ 'disable_304' => $quiet, // when requested for service needs - need content instead of 304
147
  'quiet' => $quiet
148
  ) );
149
 
367
 
368
  $file = Util_Environment::url_to_docroot_filename( $url );
369
 
370
+ if ( is_null( $file ) ) {
371
+ // it's external url
372
+ $precached_file = $this->_precache_file( $url, $type );
373
 
374
  if ( $precached_file ) {
375
+ $result[$location][$url] = $precached_file;
376
  } else {
377
+ Minify_Core::debug_error( sprintf( 'Unable to cache remote url: "%s"', $url ) );
378
  }
379
  } else {
380
  $path = Util_Environment::document_root() . '/' . $file;
505
  $result = array();
506
  if ( is_array( $files ) && count( $files ) > 0 ) {
507
  foreach ( $files as $file ) {
508
+ $docroot_filename = Util_Environment::url_to_docroot_filename( $file );
509
+
510
+ if ( Util_Environment::is_url( $file ) && is_null( $docroot_filename ) ) {
511
+ // it's external url
512
  $precached_file = $this->_precache_file( $file, $type );
513
 
514
  if ( $precached_file ) {
517
  Minify_Core::debug_error( sprintf( 'Unable to cache remote file: "%s"', $file ) );
518
  }
519
  } else {
520
+ $path = Util_Environment::docroot_to_full_filename( $docroot_filename );
 
521
 
522
  if ( file_exists( $path ) ) {
523
  $result[] = $file;
524
  } else {
525
+ Minify_Core::debug_error( sprintf( 'File "%s" doesn\'t exist', $file ) );
526
  }
527
  }
528
  }
Minify_Plugin.php CHANGED
@@ -92,7 +92,9 @@ class Minify_Plugin {
92
 
93
  if ( substr( $_SERVER['REQUEST_URI'], 0, strlen( $prefix ) ) == $prefix ) {
94
  $w3_minify = Dispatcher::component( 'Minify_MinifiedFileRequestHandler' );
95
- $w3_minify->process( substr( $_SERVER['REQUEST_URI'], strlen( $prefix ) ) );
 
 
96
  exit();
97
  }
98
 
@@ -1272,29 +1274,29 @@ class _W3_MinifyHelpers {
1272
  }
1273
 
1274
 
1275
- $file_normalized = Util_Environment::remove_query_all( $file );
1276
- $ext = strrchr( $file_normalized, '.' );
1277
-
1278
- if ( $ext != '.js' && $ext != '.css' ) {
1279
  if ( $this->debug ) {
1280
  Minify_Core::log(
1281
- 'is_file_for_minification: unknown extension ' . $ext .
1282
- ' for ' . $file );
1283
  }
1284
 
1285
  return '';
1286
  }
1287
 
1288
- if ( Util_Environment::is_url( $file_normalized ) ) {
 
 
 
1289
  if ( $this->debug ) {
1290
  Minify_Core::log(
1291
- 'is_file_for_minification: its url ' . $file . ' for url ' . $url );
 
1292
  }
1293
 
1294
  return '';
1295
  }
1296
 
1297
- $path = Util_Environment::document_root() . '/' . $file;
1298
 
1299
  if ( !file_exists( $path ) ) {
1300
  if ( $this->debug ) {
@@ -1533,7 +1535,11 @@ class _W3_MinifyJsAuto {
1533
  $script_src = Util_Environment::url_relative_to_full( $script_src );
1534
  $file = Util_Environment::url_to_docroot_filename( $script_src );
1535
 
1536
- $step1_result = $this->minify_helpers->is_file_for_minification( $script_src, $file );
 
 
 
 
1537
  $step1 = !empty( $step1_result );
1538
  $step2 = !in_array( $file, $this->ignore_js_files );
1539
 
92
 
93
  if ( substr( $_SERVER['REQUEST_URI'], 0, strlen( $prefix ) ) == $prefix ) {
94
  $w3_minify = Dispatcher::component( 'Minify_MinifiedFileRequestHandler' );
95
+ $filename = Util_Environment::remove_query_all(
96
+ substr( $_SERVER['REQUEST_URI'], strlen( $prefix ) ) );
97
+ $w3_minify->process( $filename );
98
  exit();
99
  }
100
 
1274
  }
1275
 
1276
 
1277
+ if ( is_null( $file ) ) {
 
 
 
1278
  if ( $this->debug ) {
1279
  Minify_Core::log(
1280
+ 'is_file_for_minification: external not whitelisted url ' . $url );
 
1281
  }
1282
 
1283
  return '';
1284
  }
1285
 
1286
+ $file_normalized = Util_Environment::remove_query_all( $file );
1287
+ $ext = strrchr( $file_normalized, '.' );
1288
+
1289
+ if ( $ext != '.js' && $ext != '.css' ) {
1290
  if ( $this->debug ) {
1291
  Minify_Core::log(
1292
+ 'is_file_for_minification: unknown extension ' . $ext .
1293
+ ' for ' . $file );
1294
  }
1295
 
1296
  return '';
1297
  }
1298
 
1299
+ $path = Util_Environment::docroot_to_full_filename( $file );
1300
 
1301
  if ( !file_exists( $path ) ) {
1302
  if ( $this->debug ) {
1535
  $script_src = Util_Environment::url_relative_to_full( $script_src );
1536
  $file = Util_Environment::url_to_docroot_filename( $script_src );
1537
 
1538
+ $step1_result = $this->minify_helpers->is_file_for_minification(
1539
+ $script_src, $file );
1540
+ if ( $step1_result == 'url' )
1541
+ $file = $script_src;
1542
+
1543
  $step1 = !empty( $step1_result );
1544
  $step2 = !in_array( $file, $this->ignore_js_files );
1545
 
ObjectCache_WpObjectCache_Regular.php CHANGED
@@ -164,12 +164,16 @@ class ObjectCache_WpObjectCache_Regular {
164
  json_encode($a);
165
  */
166
 
 
 
167
  if ( is_array( $v ) && isset( $v['content'] ) ) {
168
  $found = true;
169
  $value = $v['content'];
 
170
  } else {
171
  $found = false;
172
  $value = false;
 
173
  }
174
  } else {
175
  $found = false;
@@ -195,12 +199,7 @@ class ObjectCache_WpObjectCache_Regular {
195
  if ( $found ) {
196
  if ( !$in_incall_cache ) {
197
  $this->cache[$key] = $value;
198
- $this->cache_total++;
199
  }
200
-
201
- $this->cache_hits++;
202
- } else {
203
- $this->cache_misses++;
204
  }
205
 
206
  /**
@@ -230,14 +229,16 @@ class ObjectCache_WpObjectCache_Regular {
230
  }
231
  }
232
 
233
- $this->debug_info[] = array(
234
- 'id' => $id,
235
- 'group' => $group,
236
- 'operation' => 'get',
237
- 'returned' => $returned,
238
- 'data_size' => ( $value ? strlen( serialize( $value ) ) : '' ),
239
- 'time' => $time
240
- );
 
 
241
  }
242
 
243
  return $value;
164
  json_encode($a);
165
  */
166
 
167
+ $this->cache_total++;
168
+
169
  if ( is_array( $v ) && isset( $v['content'] ) ) {
170
  $found = true;
171
  $value = $v['content'];
172
+ $this->cache_hits++;
173
  } else {
174
  $found = false;
175
  $value = false;
176
+ $this->cache_misses++;
177
  }
178
  } else {
179
  $found = false;
199
  if ( $found ) {
200
  if ( !$in_incall_cache ) {
201
  $this->cache[$key] = $value;
 
202
  }
 
 
 
 
203
  }
204
 
205
  /**
229
  }
230
  }
231
 
232
+ if ( !$in_incall_cache ) {
233
+ $this->debug_info[] = array(
234
+ 'id' => $id,
235
+ 'group' => $group,
236
+ 'operation' => 'get',
237
+ 'returned' => $returned,
238
+ 'data_size' => ( $value ? strlen( serialize( $value ) ) : '' ),
239
+ 'time' => $time
240
+ );
241
+ }
242
  }
243
 
244
  return $value;
PgCache_ContentGrabber.php CHANGED
@@ -103,13 +103,6 @@ class PgCache_ContentGrabber {
103
  */
104
  var $cache_reject_reason = '';
105
 
106
- /**
107
- *
108
- *
109
- * @var If sitemap was matched
110
- */
111
- var $_sitemap_matched;
112
-
113
  /**
114
  *
115
  *
@@ -231,22 +224,13 @@ class PgCache_ContentGrabber {
231
  $encryption = $this->_page_key_extension['encryption'];
232
  $compression = $this->_page_key_extension['compression'];
233
 
234
- $group = '';
235
- $sitemap_regex = $this->_config->get_string( 'pgcache.purge.sitemap_regex' );
236
- if ( $sitemap_regex && preg_match( '/' . $sitemap_regex . '/', basename( $this->_request_uri ) ) ) {
237
- $group = 'sitemaps';
238
- $this->_sitemap_matched = true;
239
- } else {
240
- $this->_sitemap_matched = false;
241
- }
242
-
243
  /**
244
  * Check if page is cached
245
  */
246
  if ( !$this->_set_extract_page_key( $this->_page_key_extension, $with_filter ) ) {
247
  $data = null;
248
  } else {
249
- $data = $cache->get_with_old( $this->_page_key, $group );
250
  list( $data, $this->_old_exists ) = $data;
251
  }
252
 
@@ -259,7 +243,7 @@ class PgCache_ContentGrabber {
259
  array( 'compression' => '') ), $with_filter ) ) {
260
  $data = null;
261
  } else {
262
- $data = $cache->get_with_old( $this->_page_key, $group );
263
  list( $data, $this->_old_exists ) = $data;
264
  $compression = false;
265
  }
@@ -281,6 +265,18 @@ class PgCache_ContentGrabber {
281
 
282
 
283
  private function _set_extract_page_key( $page_key_extension, $with_filter ) {
 
 
 
 
 
 
 
 
 
 
 
 
284
  $this->_page_key = $this->_get_page_key( $page_key_extension );
285
 
286
  if ( $with_filter ) {
@@ -325,6 +321,13 @@ class PgCache_ContentGrabber {
325
  $has_dynamic = isset( $data['has_dynamic'] ) && $data['has_dynamic'];
326
  $etag = md5( $content );
327
 
 
 
 
 
 
 
 
328
  if ( $has_dynamic ) {
329
  // its last modification date is now, and any compression
330
  // browser wants cant be used, since its compressed now
@@ -503,13 +506,22 @@ class PgCache_ContentGrabber {
503
  /**
504
  * Skip if there is query in the request uri
505
  */
506
- if ( !$this->_check_query_string() &&
507
- ( !$this->_config->get_boolean( 'pgcache.cache.query' ) ||
508
- $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' ) &&
509
- strstr( $this->_request_uri, '?' ) !== false ) {
510
- $this->cache_reject_reason = 'Requested URI contains query';
 
 
 
 
 
511
 
512
- return false;
 
 
 
 
513
  }
514
 
515
  /**
@@ -588,6 +600,13 @@ class PgCache_ContentGrabber {
588
  return false;
589
  }
590
 
 
 
 
 
 
 
 
591
  /**
592
  * Don't cache 404 pages
593
  */
@@ -1053,6 +1072,7 @@ class PgCache_ContentGrabber {
1053
  'content_type' => '',
1054
  'cache' => true,
1055
  'cache_reject_reason' => '',
 
1056
  );
1057
 
1058
  if ( $this->_mobile )
@@ -1064,6 +1084,24 @@ class PgCache_ContentGrabber {
1064
 
1065
  $this->_fill_key_extension_cookie( $extension );
1066
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1067
  return $extension;
1068
  }
1069
 
@@ -1261,8 +1299,9 @@ class PgCache_ContentGrabber {
1261
  $key = $parts['host'] .
1262
  ( isset( $parts['path'] ) ? $parts['path'] : '' ) .
1263
  ( isset( $parts['query'] ) ? '?' . $parts['query'] : '' );
1264
- } else
1265
  $key = $this->_request_host . $this->_request_uri;
 
1266
 
1267
  // replace fragment
1268
  $key = preg_replace( '~#.*$~', '', $key );
@@ -1275,24 +1314,35 @@ class PgCache_ContentGrabber {
1275
  // replace double slashes
1276
  $key = preg_replace( '~[/\\\]+~', '/', $key );
1277
 
1278
- // replace query string
1279
- $key = preg_replace( '~\?.*$~', '', $key );
1280
-
1281
  // replace index.php
1282
  $key = str_replace( '/index.php', '/', $key );
1283
 
1284
- // trim slash
1285
- $key = ltrim( $key, '/' );
 
 
 
 
 
 
1286
 
 
 
 
 
1287
  if ( $key && substr( $key, -1 ) != '/' ) {
1288
  $key .= '/';
1289
  }
1290
 
1291
  $key .= '_index';
1292
  } else {
1293
- if ( $this->_check_query_string() )
 
 
 
1294
  // replace query string
1295
  $key = preg_replace( '~\?.*$~', '', $key );
 
1296
 
1297
  $key = md5( $key );
1298
  }
@@ -1324,7 +1374,7 @@ class PgCache_ContentGrabber {
1324
  }
1325
  }
1326
 
1327
- $key .= $key_postfix;
1328
  }
1329
 
1330
  /**
@@ -1748,7 +1798,7 @@ class PgCache_ContentGrabber {
1748
  return in_array( $content_type, $cache_headers );
1749
  }
1750
 
1751
- private function _check_query_string() {
1752
  $accept_qs = $this->_config->get_array( 'pgcache.accept.qs' );
1753
  Util_Rule::array_trim( $accept_qs );
1754
 
@@ -1872,16 +1922,6 @@ class PgCache_ContentGrabber {
1872
  * Store different versions of cache
1873
  */
1874
  $buffers = array();
1875
- $group = '';
1876
- if ( !isset( $this->_sitemap_matched ) ) {
1877
- $sitemap_regex =
1878
- $this->_config->get_string( 'pgcache.purge.sitemap_regex' );
1879
- if ( $sitemap_regex && preg_match( '/' . $sitemap_regex . '/', basename( $this->_request_uri ) ) ) {
1880
- $group = 'sitemaps';
1881
- $this->_sitemap_matched = true;
1882
- }
1883
- } elseif ( $this->_sitemap_matched )
1884
- $group = 'sitemaps';
1885
 
1886
  foreach ( $compressions_to_store as $_compression ) {
1887
  $this->_set_extract_page_key(
@@ -1905,10 +1945,11 @@ class PgCache_ContentGrabber {
1905
  if ( $has_dynamic )
1906
  $_data['has_dynamic'] = true;
1907
 
1908
- $_data = apply_filters( 'w3tc_pagecache_set', $_data, $this->_page_key );
 
1909
 
1910
  if ( !empty( $_data ) )
1911
- $cache->set( $this->_page_key, $_data, $this->_lifetime, $group );
1912
  }
1913
 
1914
  // Change buffer if using compression
@@ -1945,7 +1986,7 @@ class PgCache_ContentGrabber {
1945
  /**
1946
  * Log
1947
  */
1948
- static private function log( $msg ) {
1949
  $data = sprintf( "[%s] [%s] [%s] %s\n", date( 'r' ),
1950
  $_SERVER['REQUEST_URI'],
1951
  ( !empty( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '-' ),
103
  */
104
  var $cache_reject_reason = '';
105
 
 
 
 
 
 
 
 
106
  /**
107
  *
108
  *
224
  $encryption = $this->_page_key_extension['encryption'];
225
  $compression = $this->_page_key_extension['compression'];
226
 
 
 
 
 
 
 
 
 
 
227
  /**
228
  * Check if page is cached
229
  */
230
  if ( !$this->_set_extract_page_key( $this->_page_key_extension, $with_filter ) ) {
231
  $data = null;
232
  } else {
233
+ $data = $cache->get_with_old( $this->_page_key, $this->_page_group );
234
  list( $data, $this->_old_exists ) = $data;
235
  }
236
 
243
  array( 'compression' => '') ), $with_filter ) ) {
244
  $data = null;
245
  } else {
246
+ $data = $cache->get_with_old( $this->_page_key, $this->_page_group );
247
  list( $data, $this->_old_exists ) = $data;
248
  $compression = false;
249
  }
265
 
266
 
267
  private function _set_extract_page_key( $page_key_extension, $with_filter ) {
268
+ // set page group
269
+ $this->_page_group = $page_key_extension['group'];
270
+ if ( $with_filter ) {
271
+ // return empty value if caching should not happen
272
+ $this->_page_group = apply_filters( 'w3tc_page_extract_group',
273
+ $page_key_extension['group'],
274
+ $this->_request_host . $this->_request_uri,
275
+ $page_key_extension );
276
+ $page_key_extension['group'] = $this->_page_group;
277
+ }
278
+
279
+ // set page key
280
  $this->_page_key = $this->_get_page_key( $page_key_extension );
281
 
282
  if ( $with_filter ) {
321
  $has_dynamic = isset( $data['has_dynamic'] ) && $data['has_dynamic'];
322
  $etag = md5( $content );
323
 
324
+ // for REST under disk-enhanced - return json content type
325
+ if ( !empty( $this->_page_key_extension['content_type'] ) &&
326
+ !isset( $headers['Content-Type'] ) ) {
327
+ $headers['Content-Type'] = $this->_page_key_extension['content_type'];
328
+ }
329
+
330
+
331
  if ( $has_dynamic ) {
332
  // its last modification date is now, and any compression
333
  // browser wants cant be used, since its compressed now
506
  /**
507
  * Skip if there is query in the request uri
508
  */
509
+ if ( !$this->_is_whitelisted_query_string() ) {
510
+ $should_skip_qs =
511
+ ( !$this->_config->get_boolean( 'pgcache.cache.query' ) ||
512
+ $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' );
513
+
514
+ if ( $should_skip_qs &&
515
+ $this->_config->get_string( 'pgcache.rest' ) == 'cache' &&
516
+ Util_Environment::is_rest_request( $this->_request_uri ) ) {
517
+ $should_skip_qs = false;
518
+ }
519
 
520
+ if ( $should_skip_qs && strstr( $this->_request_uri, '?' ) !== false ) {
521
+ $this->cache_reject_reason = 'Requested URI contains query';
522
+
523
+ return false;
524
+ }
525
  }
526
 
527
  /**
600
  return false;
601
  }
602
 
603
+ if ( $this->_config->get_string( 'pgcache.rest' ) != 'cache' ) {
604
+ if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
605
+ $this->cache_reject_reason = 'REST request';
606
+ return false;
607
+ }
608
+ }
609
+
610
  /**
611
  * Don't cache 404 pages
612
  */
1072
  'content_type' => '',
1073
  'cache' => true,
1074
  'cache_reject_reason' => '',
1075
+ 'group' => ''
1076
  );
1077
 
1078
  if ( $this->_mobile )
1084
 
1085
  $this->_fill_key_extension_cookie( $extension );
1086
 
1087
+ // fill group
1088
+ $sitemap_regex = $this->_config->get_string(
1089
+ 'pgcache.purge.sitemap_regex' );
1090
+ if ( !$this->_enhanced_mode && $sitemap_regex &&
1091
+ preg_match( '~' . $sitemap_regex . '~',
1092
+ basename( $this->_request_uri ) ) ) {
1093
+ // dont store to separate group under disk-enhanced
1094
+ // so that rewrite rules still work.
1095
+ // flushing is handled by workaround in this case
1096
+ $extension['group'] = 'sitemaps';
1097
+ } elseif ( $this->_config->get_string( 'pgcache.rest' ) == 'cache' &&
1098
+ Util_Environment::is_rest_request( $this->_request_uri ) &&
1099
+ Util_Environment::is_w3tc_pro( $this->_config ) ) {
1100
+ $extension['group'] = 'rest';
1101
+ $extension['querystring.processing'] = 'include';
1102
+ $extension['content_type'] = 'application/json';
1103
+ }
1104
+
1105
  return $extension;
1106
  }
1107
 
1299
  $key = $parts['host'] .
1300
  ( isset( $parts['path'] ) ? $parts['path'] : '' ) .
1301
  ( isset( $parts['query'] ) ? '?' . $parts['query'] : '' );
1302
+ } else {
1303
  $key = $this->_request_host . $this->_request_uri;
1304
+ }
1305
 
1306
  // replace fragment
1307
  $key = preg_replace( '~#.*$~', '', $key );
1314
  // replace double slashes
1315
  $key = preg_replace( '~[/\\\]+~', '/', $key );
1316
 
 
 
 
1317
  // replace index.php
1318
  $key = str_replace( '/index.php', '/', $key );
1319
 
1320
+ $key_query = '';
1321
+ if ( isset( $page_key_extension['querystring.processing'] ) &&
1322
+ $page_key_extension['querystring.processing'] == 'include' ) {
1323
+
1324
+ if ( preg_match( '~\?.*$~', $key, $m ) ) {
1325
+ $key_query = '_' . md5( $m[0] );
1326
+ }
1327
+ }
1328
 
1329
+ $key = preg_replace( '~\?.*$~', '', $key );
1330
+
1331
+ // make sure one slash is at the end
1332
+ $key = ltrim( $key, '/' );
1333
  if ( $key && substr( $key, -1 ) != '/' ) {
1334
  $key .= '/';
1335
  }
1336
 
1337
  $key .= '_index';
1338
  } else {
1339
+ if ( isset( $page_key_extension['querystring.processing'] ) &&
1340
+ $page_key_extension['querystring.processing'] == 'include' ) {
1341
+ // include querystring in key
1342
+ } elseif ( $this->_is_whitelisted_query_string() ) {
1343
  // replace query string
1344
  $key = preg_replace( '~\?.*$~', '', $key );
1345
+ }
1346
 
1347
  $key = md5( $key );
1348
  }
1374
  }
1375
  }
1376
 
1377
+ $key .= $key_query . $key_postfix;
1378
  }
1379
 
1380
  /**
1798
  return in_array( $content_type, $cache_headers );
1799
  }
1800
 
1801
+ private function _is_whitelisted_query_string() {
1802
  $accept_qs = $this->_config->get_array( 'pgcache.accept.qs' );
1803
  Util_Rule::array_trim( $accept_qs );
1804
 
1922
  * Store different versions of cache
1923
  */
1924
  $buffers = array();
 
 
 
 
 
 
 
 
 
 
1925
 
1926
  foreach ( $compressions_to_store as $_compression ) {
1927
  $this->_set_extract_page_key(
1945
  if ( $has_dynamic )
1946
  $_data['has_dynamic'] = true;
1947
 
1948
+ $_data = apply_filters( 'w3tc_pagecache_set', $_data, $this->_page_key,
1949
+ $this->_page_group );
1950
 
1951
  if ( !empty( $_data ) )
1952
+ $cache->set( $this->_page_key, $_data, $this->_lifetime, $this->_page_group );
1953
  }
1954
 
1955
  // Change buffer if using compression
1986
  /**
1987
  * Log
1988
  */
1989
+ static protected function log( $msg ) {
1990
  $data = sprintf( "[%s] [%s] [%s] %s\n", date( 'r' ),
1991
  $_SERVER['REQUEST_URI'],
1992
  ( !empty( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '-' ),
PgCache_Environment.php CHANGED
@@ -1412,6 +1412,7 @@ class PgCache_Environment {
1412
  $lifetime = ( $browsercache ? $config->get_integer( 'browsercache.html.lifetime' ) : 0 );
1413
  $cache_control = ( $browsercache && $config->get_boolean( 'browsercache.html.cache.control' ) );
1414
  $w3tc = ( $browsercache && $config->get_integer( 'browsercache.html.w3tc' ) );
 
1415
 
1416
  $common_rules = '';
1417
 
@@ -1424,6 +1425,9 @@ class PgCache_Environment {
1424
  Util_Environment::w3tc_header() . "\";\n";
1425
  }
1426
 
 
 
 
1427
  if ( $expires ) {
1428
  $common_rules .= " add_header Vary \"Accept-Encoding, Cookie\";\n";
1429
  }
@@ -1477,7 +1481,7 @@ class PgCache_Environment {
1477
  $maybe_xml = '';
1478
  if ($config->get_boolean('pgcache.cache.nginx_handle_xml')) {
1479
  $maybe_xml = "\n" .
1480
- " text/xml xml_gzip\n" .
1481
  " ";
1482
  }
1483
 
1412
  $lifetime = ( $browsercache ? $config->get_integer( 'browsercache.html.lifetime' ) : 0 );
1413
  $cache_control = ( $browsercache && $config->get_boolean( 'browsercache.html.cache.control' ) );
1414
  $w3tc = ( $browsercache && $config->get_integer( 'browsercache.html.w3tc' ) );
1415
+ $hsts = ( $browsercache && $config->get_boolean( 'browsercache.hsts' ) );
1416
 
1417
  $common_rules = '';
1418
 
1425
  Util_Environment::w3tc_header() . "\";\n";
1426
  }
1427
 
1428
+ if ( $hsts ) {
1429
+ $common_rules .= " add_header Strict-Transport-Security \"max-age=31536000; preload\";\n";
1430
+ }
1431
  if ( $expires ) {
1432
  $common_rules .= " add_header Vary \"Accept-Encoding, Cookie\";\n";
1433
  }
1481
  $maybe_xml = '';
1482
  if ($config->get_boolean('pgcache.cache.nginx_handle_xml')) {
1483
  $maybe_xml = "\n" .
1484
+ " text/xml xml_gzip;\n" .
1485
  " ";
1486
  }
1487
 
PgCache_Flush.php CHANGED
@@ -11,7 +11,8 @@ class PgCache_Flush extends PgCache_ContentGrabber {
11
  * @var array
12
  */
13
  private $queued_urls = array();
14
- private $flush_operation_requested = false;
 
15
 
16
  /**
17
  * PHP5 Constructor
@@ -26,10 +27,14 @@ class PgCache_Flush extends PgCache_ContentGrabber {
26
  * @return boolean
27
  */
28
  function flush() {
29
- $this->flush_operation_requested = true;
30
  return true;
31
  }
32
 
 
 
 
 
33
  /**
34
  * Flushes post cache
35
  *
@@ -51,6 +56,10 @@ class PgCache_Flush extends PgCache_ContentGrabber {
51
  $feeds = $this->_config->get_array( 'pgcache.purge.feed.types' );
52
  $limit_post_pages = $this->_config->get_integer( 'pgcache.purge.postpages_limit' );
53
 
 
 
 
 
54
  if ( $this->_config->get_boolean( 'pgcache.purge.terms' ) ||
55
  $this->_config->get_boolean( 'pgcache.purge.feed.terms' ) ) {
56
  $taxonomies = get_post_taxonomies( $post_id );
@@ -140,15 +149,9 @@ class PgCache_Flush extends PgCache_ContentGrabber {
140
  /**
141
  * Feed URLs
142
  */
143
- if ( $this->_config->get_boolean( 'pgcache.purge.feed.blog' ) && $post ) {
144
- $post_type = null;
145
- if ( in_array( $post->post_type,
146
- array( 'post', 'page', 'attachment', 'revision' ) ) ) {
147
- $post_type = $post->post_type;
148
- }
149
-
150
  $full_urls = array_merge( $full_urls,
151
- Util_PageUrls::get_feed_urls( $feeds, $post_type ) );
152
  }
153
 
154
  if ( $this->_config->get_boolean( 'pgcache.purge.feed.comments' ) ) {
@@ -179,7 +182,6 @@ class PgCache_Flush extends PgCache_ContentGrabber {
179
  $full_urls = Util_PageUrls::complement_with_mirror_urls( $full_urls );
180
  $full_urls = apply_filters( 'pgcache_flush_post_queued_urls',
181
  $full_urls );
182
-
183
  /**
184
  * Queue flush
185
  */
@@ -254,17 +256,37 @@ class PgCache_Flush extends PgCache_ContentGrabber {
254
  * @return count of elements it has flushed
255
  */
256
  function flush_post_cleanup() {
257
- if ( $this->flush_operation_requested ) {
 
 
 
 
258
  $cache = $this->_get_cache();
259
  $cache->flush();
260
 
261
  $count = 999;
262
- $this->flush_operation_requested = false;
263
  $this->queued_urls = array();
264
  } else {
 
 
 
 
 
 
 
 
 
 
 
 
265
  $count = count( $this->queued_urls );
266
 
267
  if ( $count > 0 ) {
 
 
 
 
268
  $cache = $this->_get_cache();
269
  $mobile_groups = $this->_get_mobile_groups();
270
  $referrer_groups = $this->_get_referrer_groups();
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
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
+
38
  /**
39
  * Flushes post cache
40
  *
56
  $feeds = $this->_config->get_array( 'pgcache.purge.feed.types' );
57
  $limit_post_pages = $this->_config->get_integer( 'pgcache.purge.postpages_limit' );
58
 
59
+ if ( $this->_config->get_string( 'pgcache.rest' ) == 'cache' ) {
60
+ $this->flush_group( 'rest' );
61
+ }
62
+
63
  if ( $this->_config->get_boolean( 'pgcache.purge.terms' ) ||
64
  $this->_config->get_boolean( 'pgcache.purge.feed.terms' ) ) {
65
  $taxonomies = get_post_taxonomies( $post_id );
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 ) );
155
  }
156
 
157
  if ( $this->_config->get_boolean( 'pgcache.purge.feed.comments' ) ) {
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
  */
256
  * @return count of elements it has flushed
257
  */
258
  function flush_post_cleanup() {
259
+ if ( $this->flush_all_operation_requested ) {
260
+ if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
261
+ self::log( 'flush all' );
262
+ }
263
+
264
  $cache = $this->_get_cache();
265
  $cache->flush();
266
 
267
  $count = 999;
268
+ $this->flush_all_operation_requested = false;
269
  $this->queued_urls = array();
270
  } else {
271
+ if ( count( $this->queued_groups ) > 0 ) {
272
+ $cache = $this->_get_cache();
273
+
274
+ foreach ( $this->queued_groups as $group => $flag ) {
275
+ if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
276
+ self::log( 'pgcache flush "' . $group . '" group' );
277
+ }
278
+
279
+ $cache->flush( $group );
280
+ }
281
+ }
282
+
283
  $count = count( $this->queued_urls );
284
 
285
  if ( $count > 0 ) {
286
+ if ( $this->_config->get_boolean( 'pgcache.debug' ) ) {
287
+ self::log( 'pgcache flush ' . $count . ' urls' );
288
+ }
289
+
290
  $cache = $this->_get_cache();
291
  $mobile_groups = $this->_get_mobile_groups();
292
  $referrer_groups = $this->_get_referrer_groups();
PgCache_Plugin.php CHANGED
@@ -21,6 +21,9 @@ class PgCache_Plugin {
21
  add_action( 'w3tc_flush_all',
22
  array( $this, 'w3tc_flush_posts' ),
23
  1100, 1 );
 
 
 
24
  add_action( 'w3tc_flush_post',
25
  array( $this, 'w3tc_flush_post' ),
26
  1100, 1 );
@@ -94,8 +97,30 @@ class PgCache_Plugin {
94
  add_action( 'init',
95
  array( $this, 'redirect_on_foreign_domain' ) );
96
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
98
 
 
 
99
  /**
100
  * Does disk cache cleanup
101
  *
@@ -111,8 +136,8 @@ class PgCache_Plugin {
111
  * @param integer $start
112
  * @return void
113
  */
114
- function prime( $start = 0 ) {
115
- $this->_get_admin()->prime( $start );
116
  }
117
 
118
  /**
@@ -257,6 +282,16 @@ class PgCache_Plugin {
257
  return $menu_items;
258
  }
259
 
 
 
 
 
 
 
 
 
 
 
260
  /**
261
  * Flushes all caches
262
  *
21
  add_action( 'w3tc_flush_all',
22
  array( $this, 'w3tc_flush_posts' ),
23
  1100, 1 );
24
+ add_action( 'w3tc_flush_group',
25
+ array( $this, 'w3tc_flush_group' ),
26
+ 1100, 2 );
27
  add_action( 'w3tc_flush_post',
28
  array( $this, 'w3tc_flush_post' ),
29
  1100, 1 );
97
  add_action( 'init',
98
  array( $this, 'redirect_on_foreign_domain' ) );
99
  }
100
+ if ( $this->_config->get_string( 'pgcache.rest' ) == 'disable' ) {
101
+ // remove XMLRPC edit link
102
+ remove_action( 'xmlrpc_rsd_apis', 'rest_output_rsd' );
103
+ // remove wp-json in <head>
104
+ remove_action( 'wp_head', 'rest_output_link_wp_head', 10 );
105
+ // remove HTTP Header
106
+ remove_action( 'template_redirect', 'rest_output_link_header', 11 );
107
+
108
+ add_filter( 'rest_authentication_errors',
109
+ array( $this, 'rest_authentication_errors' ),
110
+ 100 );
111
+ }
112
+ }
113
+
114
+
115
+
116
+ public function rest_authentication_errors( $result ) {
117
+ $error_message = __( 'REST API disabled.', 'w3-total-cache' );
118
+
119
+ return new \WP_Error( 'rest_disabled', $error_message, array( 'status' => rest_authorization_required_code() ) );
120
  }
121
 
122
+
123
+
124
  /**
125
  * Does disk cache cleanup
126
  *
136
  * @param integer $start
137
  * @return void
138
  */
139
+ function prime() {
140
+ $this->_get_admin()->prime();
141
  }
142
 
143
  /**
282
  return $menu_items;
283
  }
284
 
285
+ function w3tc_flush_group( $group, $extras = array() ) {
286
+ if ( isset( $extras['only'] ) && $extras['only'] != 'pagecache' )
287
+ return;
288
+
289
+ $pgcacheflush = Dispatcher::component( 'PgCache_Flush' );
290
+ $v = $pgcacheflush->flush_group( $group );
291
+
292
+ return $v;
293
+ }
294
+
295
  /**
296
  * Flushes all caches
297
  *
PgCache_Plugin_Admin.php CHANGED
@@ -116,32 +116,29 @@ class PgCache_Plugin_Admin {
116
  * @param integer $start
117
  * @return void
118
  */
119
- function prime( $start = 0 ) {
120
- $start = (int) $start;
121
-
122
- /**
123
- * Don't start cache prime if queues are still scheduled
124
- */
125
- if ( $start == 0 ) {
126
- $crons = _get_cron_array();
127
-
128
- if ( is_array( $crons ) ) {
129
- foreach ( $crons as $timestamp => $hooks ) {
130
- foreach ( $hooks as $hook => $keys ) {
131
- foreach ( $keys as $key => $data ) {
132
- if ( $hook == 'w3_pgcache_prime' && count( $data['args'] ) ) {
133
- return;
134
- }
135
- }
136
- }
137
- }
138
- }
139
  }
140
 
141
  $interval = $this->_config->get_integer( 'pgcache.prime.interval' );
142
- $limit = $this->_config->get_integer( 'pgcache.prime.limit' );
 
 
 
 
 
 
143
  $sitemap = $this->_config->get_string( 'pgcache.prime.sitemap' );
144
 
 
 
 
 
 
145
  /**
146
  * Parse XML sitemap
147
  */
@@ -153,21 +150,26 @@ class PgCache_Plugin_Admin {
153
  $queue = array_slice( $urls, $start, $limit );
154
 
155
  if ( count( $urls ) > ( $start + $limit ) ) {
156
- wp_schedule_single_event( time() + $interval, 'w3_pgcache_prime', array(
157
- $start + $limit
158
- ) );
159
  }
160
 
 
 
161
  /**
162
  * Make HTTP requests and prime cache
163
  */
164
 
165
-
166
-
167
  // use 'WordPress' since by default we use W3TC-powered by
168
  // which blocks caching
169
- foreach ( $queue as $url )
170
  Util_Http::get( $url, array( 'user-agent' => 'WordPress' ) );
 
 
 
 
 
171
  }
172
 
173
  /**
116
  * @param integer $start
117
  * @return void
118
  */
119
+ function prime( $start = null, $limit = null, $log_callback = null ) {
120
+ if ( is_null( $start ) ) {
121
+ $start = get_option( 'w3tc_pgcache_prime_offset' );
122
+ }
123
+ if ( $start < 0 ) {
124
+ $start = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
 
127
  $interval = $this->_config->get_integer( 'pgcache.prime.interval' );
128
+ if ( is_null( $limit ) ) {
129
+ $limit = $this->_config->get_integer( 'pgcache.prime.limit' );
130
+ }
131
+ if ( $limit < 1 ) {
132
+ $limit = 1;
133
+ }
134
+
135
  $sitemap = $this->_config->get_string( 'pgcache.prime.sitemap' );
136
 
137
+ if ( !is_null( $log_callback ) ) {
138
+ $log_callback( 'Priming from sitemap ' . $sitemap .
139
+ ' entries ' . ( $start + 1 ) . '..' . ( $start + $limit ) );
140
+ }
141
+
142
  /**
143
  * Parse XML sitemap
144
  */
150
  $queue = array_slice( $urls, $start, $limit );
151
 
152
  if ( count( $urls ) > ( $start + $limit ) ) {
153
+ $next_offset = $start + $limit;
154
+ } else {
155
+ $next_offset = 0;
156
  }
157
 
158
+ update_option( 'w3tc_pgcache_prime_offset', $next_offset, false );
159
+
160
  /**
161
  * Make HTTP requests and prime cache
162
  */
163
 
 
 
164
  // use 'WordPress' since by default we use W3TC-powered by
165
  // which blocks caching
166
+ foreach ( $queue as $url ) {
167
  Util_Http::get( $url, array( 'user-agent' => 'WordPress' ) );
168
+
169
+ if ( !is_null( $log_callback ) ) {
170
+ $log_callback( 'Priming ' . $url );
171
+ }
172
+ }
173
  }
174
 
175
  /**
Root_AdminMenu.php CHANGED
@@ -86,7 +86,8 @@ class Root_AdminMenu {
86
  'page_title' => __( 'FAQ', 'w3-total-cache' ),
87
  'menu_text' => __( 'FAQ', 'w3-total-cache' ),
88
  'visible_always' => true,
89
- 'order' => 2000
 
90
  ),
91
  'w3tc_support' => array(
92
  'page_title' => __( 'Support', 'w3-total-cache' ),
@@ -132,7 +133,7 @@ class Root_AdminMenu {
132
 
133
  foreach ( $pages as $slug => $titles ) {
134
  if ( $is_master || $titles['visible_always'] || $remaining_visible ) {
135
- $submenu_pages[] = add_submenu_page( 'w3tc_dashboard',
136
  $titles['page_title'] . ' | W3 Total Cache',
137
  $titles['menu_text'],
138
  apply_filters( 'w3tc_capability_menu_' . $slug,
@@ -140,11 +141,20 @@ class Root_AdminMenu {
140
  $slug,
141
  array( $this, 'options' )
142
  );
 
 
 
 
 
143
  }
144
  }
145
  return $submenu_pages;
146
  }
147
 
 
 
 
 
148
 
149
  /**
150
  * Options page
@@ -218,11 +228,6 @@ class Root_AdminMenu {
218
  $options_cdn->options();
219
  break;
220
 
221
- case 'w3tc_faq':
222
- $options_faq = new Generic_Page_Faq();
223
- $options_faq->options();
224
- break;
225
-
226
  case 'w3tc_support':
227
  $options_support = new Support_Page();
228
  $options_support->options();
86
  'page_title' => __( 'FAQ', 'w3-total-cache' ),
87
  'menu_text' => __( 'FAQ', 'w3-total-cache' ),
88
  'visible_always' => true,
89
+ 'order' => 2000,
90
+ 'redirect_faq' => '*'
91
  ),
92
  'w3tc_support' => array(
93
  'page_title' => __( 'Support', 'w3-total-cache' ),
133
 
134
  foreach ( $pages as $slug => $titles ) {
135
  if ( $is_master || $titles['visible_always'] || $remaining_visible ) {
136
+ $hook = add_submenu_page( 'w3tc_dashboard',
137
  $titles['page_title'] . ' | W3 Total Cache',
138
  $titles['menu_text'],
139
  apply_filters( 'w3tc_capability_menu_' . $slug,
141
  $slug,
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
228
  $options_cdn->options();
229
  break;
230
 
 
 
 
 
 
231
  case 'w3tc_support':
232
  $options_support = new Support_Page();
233
  $options_support->options();
Root_Loader.php CHANGED
@@ -54,7 +54,8 @@ class Root_Loader {
54
 
55
  $plugins[] = new Cdn_Plugin_Admin();
56
  $plugins[] = new Cdnfsd_Plugin_Admin();
57
- if ( $c->get_string( 'cdn.engine' ) == 'highwinds' ) {
 
58
  } else {
59
  $plugins[] = new Cdn_Plugin_WidgetMaxCdn();
60
  }
54
 
55
  $plugins[] = new Cdn_Plugin_Admin();
56
  $plugins[] = new Cdnfsd_Plugin_Admin();
57
+ $cdn_engine = $c->get_string( 'cdn.engine' );
58
+ if ( $cdn_engine == 'highwinds' || $cdn_engine == 'stackpath' ) {
59
  } else {
60
  $plugins[] = new Cdn_Plugin_WidgetMaxCdn();
61
  }
Util_Environment.php CHANGED
@@ -796,35 +796,36 @@ class Util_Environment {
796
  if ( substr( $normalized_url, 0, strlen( $home_url ) ) != $home_url ) {
797
  // not a home url, return unchanged since cant be
798
  // converted to filename
799
- return $url;
800
- } else {
801
- $path_relative_to_home = str_replace( $home_url, '', $normalized_url );
802
-
803
- $home = set_url_scheme( get_option( 'home' ), 'http' );
804
- $siteurl = set_url_scheme( get_option( 'siteurl' ), 'http' );
805
-
806
- $home_path = rtrim( Util_Environment::site_path(), '/' );
807
- // adjust home_path if site is not is home
808
- if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
809
- // $siteurl - $home
810
- $wp_path_rel_to_home = rtrim( str_ireplace( $home, '', $siteurl ), '/' );
811
- if ( substr( $home_path, -strlen( $wp_path_rel_to_home ) ) ==
812
- $wp_path_rel_to_home ) {
813
- $home_path = substr( $home_path, 0, -strlen( $wp_path_rel_to_home ) );
814
- }
815
  }
 
816
 
817
- // common encoded characters
818
- $path_relative_to_home = str_replace( '%20', ' ', $path_relative_to_home );
819
 
820
- $full_filename = $home_path . DIRECTORY_SEPARATOR .
821
- trim( $path_relative_to_home, DIRECTORY_SEPARATOR );
822
 
823
- $docroot = Util_Environment::document_root();
824
- if ( substr( $full_filename, 0, strlen( $docroot ) ) == $docroot )
825
- $docroot_filename = substr( $full_filename, strlen( $docroot ) );
826
- else
827
- $docroot_filename = $path_relative_to_home;
828
  }
829
 
830
  // sometimes urls (coming from other plugins/themes)
@@ -835,6 +836,11 @@ class Util_Environment {
835
  return ltrim( $docroot_filename, DIRECTORY_SEPARATOR );
836
  }
837
 
 
 
 
 
 
838
  /**
839
  * Translates remote file to local file
840
  *
@@ -1207,4 +1213,16 @@ class Util_Environment {
1207
  $version = $temp[0];
1208
  return $version;
1209
  }
 
 
 
 
 
 
 
 
 
 
 
 
1210
  }
796
  if ( substr( $normalized_url, 0, strlen( $home_url ) ) != $home_url ) {
797
  // not a home url, return unchanged since cant be
798
  // converted to filename
799
+ return null;
800
+ }
801
+
802
+ $path_relative_to_home = str_replace( $home_url, '', $normalized_url );
803
+
804
+ $home = set_url_scheme( get_option( 'home' ), 'http' );
805
+ $siteurl = set_url_scheme( get_option( 'siteurl' ), 'http' );
806
+
807
+ $home_path = rtrim( Util_Environment::site_path(), '/' );
808
+ // adjust home_path if site is not is home
809
+ if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
810
+ // $siteurl - $home
811
+ $wp_path_rel_to_home = rtrim( str_ireplace( $home, '', $siteurl ), '/' );
812
+ if ( substr( $home_path, -strlen( $wp_path_rel_to_home ) ) ==
813
+ $wp_path_rel_to_home ) {
814
+ $home_path = substr( $home_path, 0, -strlen( $wp_path_rel_to_home ) );
815
  }
816
+ }
817
 
818
+ // common encoded characters
819
+ $path_relative_to_home = str_replace( '%20', ' ', $path_relative_to_home );
820
 
821
+ $full_filename = $home_path . DIRECTORY_SEPARATOR .
822
+ trim( $path_relative_to_home, DIRECTORY_SEPARATOR );
823
 
824
+ $docroot = Util_Environment::document_root();
825
+ if ( substr( $full_filename, 0, strlen( $docroot ) ) == $docroot ) {
826
+ $docroot_filename = substr( $full_filename, strlen( $docroot ) );
827
+ } else {
828
+ $docroot_filename = $path_relative_to_home;
829
  }
830
 
831
  // sometimes urls (coming from other plugins/themes)
836
  return ltrim( $docroot_filename, DIRECTORY_SEPARATOR );
837
  }
838
 
839
+ static public function docroot_to_full_filename( $docroot_filename ) {
840
+ return rtrim( Util_Environment::document_root(), DIRECTORY_SEPARATOR ) .
841
+ DIRECTORY_SEPARATOR . $docroot_filename;
842
+ }
843
+
844
  /**
845
  * Translates remote file to local file
846
  *
1213
  $version = $temp[0];
1214
  return $version;
1215
  }
1216
+
1217
+ /**
1218
+ * Checks if current request is REST REQUEST
1219
+ */
1220
+ static public function is_rest_request( $url ) {
1221
+ if ( defined( 'REST_REQUEST' ) && REST_REQUEST )
1222
+ return true;
1223
+
1224
+ // in case when called before constant is set
1225
+ // wp filters are not available in that case
1226
+ return preg_match( '~' . W3TC_WP_JSON_URI . '~', $url );
1227
+ }
1228
  }
Util_PageUrls.php CHANGED
@@ -732,6 +732,52 @@ class Util_PageUrls {
732
  return $link;
733
  }
734
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
735
  static public function complement_with_mirror_urls( $queued_urls ) {
736
  $config = Dispatcher::config();
737
 
732
  return $link;
733
  }
734
 
735
+ static public function get_rest_posts_urls() {
736
+ static $posts_urls = array();
737
+
738
+ if ( empty( $posts_urls ) ) {
739
+ $types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
740
+ $wp_json_base = self::wp_json_base();
741
+
742
+ foreach ( $types as $post_type ) {
743
+ $rest_base = ( !empty( $post_type->rest_base ) ?
744
+ $post_type->rest_base : $post_type->name );
745
+
746
+ $posts_urls[] = $wp_json_base . $rest_base;
747
+ }
748
+ }
749
+
750
+ return $posts_urls;
751
+ }
752
+
753
+ static public function get_rest_post_urls( $post_id ) {
754
+ static $post_urls = array();
755
+
756
+ if ( !isset( $post_urls[$post_id] ) ) {
757
+ $post = get_post( $post_id );
758
+ $urls = array();
759
+ $wp_json_base = self::wp_json_base();
760
+
761
+ if ( $post ) {
762
+ $post_type = get_post_type_object( $post->post_type );
763
+ $rest_base = ( !empty( $post_type->rest_base ) ?
764
+ $post_type->rest_base : $post_type->name );
765
+
766
+ $urls[] = $wp_json_base . $rest_base . '/' . $post->ID;
767
+ }
768
+
769
+ $post_urls[$post_id] = $urls;
770
+ }
771
+
772
+ return $post_urls[$post_id];
773
+ }
774
+
775
+ static private function wp_json_base() {
776
+ $wp_json_base = rtrim( get_home_url(), '/' ) . W3TC_WP_JSON_URI;
777
+ $wp_json_base = apply_filters( 'w3tc_pageurls_wp_json_base', $wp_json_base );
778
+ return $wp_json_base;
779
+ }
780
+
781
  static public function complement_with_mirror_urls( $queued_urls ) {
782
  $config = Dispatcher::config();
783
 
Util_Ui.php CHANGED
@@ -428,22 +428,38 @@ class Util_Ui {
428
 
429
  /**
430
  * Echos a group of radio elements
431
- *
432
- * @param string $id
433
- * @param string $name
434
- * @param bool $state whether checked or not
435
- * @param bool $disabled
436
  */
437
  static public function radiogroup( $name, $value, $values,
438
- $disabled = false ) {
439
- foreach ( $values as $key => $label ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  echo '<label><input type="radio" name="' . esc_attr( $name ) .
441
  '" value="' . esc_attr( $key ) . '"';
442
  checked( $value, $key );
443
- disabled( $disabled );
444
  echo ' />';
445
  echo $label;
446
- echo '</label>' . "\n";
447
  }
448
  }
449
 
@@ -558,7 +574,8 @@ class Util_Ui {
558
  elseif ( $key == 'html' )
559
  echo $e;
560
  elseif ( $key == 'radiogroup' )
561
- Util_Ui::radiogroup( $e['name'], $e['value'], $e['values'] );
 
562
  elseif ( $key == 'selectbox' )
563
  Util_Ui::selectbox( $id, $e['name'], $e['value'], $e['values'],
564
  ( isset( $e['disabled'] ) ? $e['disabled'] : false ),
@@ -642,7 +659,9 @@ class Util_Ui {
642
  'name' => Util_Ui::config_key_to_http_name( $a['key'] ),
643
  'value' => $a['value'],
644
  'disabled' => $disabled,
645
- 'values' => $a['radiogroup_values']
 
 
646
  );
647
  } else if ( $a['control'] == 'selectbox' ) {
648
  $table_tr['selectbox'] = array(
428
 
429
  /**
430
  * Echos a group of radio elements
431
+ * values: value => label pair or
432
+ * value => array(label, disabled, postfix)
 
 
 
433
  */
434
  static public function radiogroup( $name, $value, $values,
435
+ $disabled = false, $separator = '' ) {
436
+ $first = true;
437
+ foreach ( $values as $key => $label_or_array ) {
438
+ if ( $first ) {
439
+ $first = false;
440
+ } else {
441
+ echo $separator;
442
+ }
443
+
444
+ $label = '';
445
+ $item_disabled = false;
446
+ $postfix = '';
447
+
448
+ if ( !is_array( $label_or_array ) ) {
449
+ $label = $label_or_array;
450
+ } else {
451
+ $label = $label_or_array['label'];
452
+ $item_disabled = $label_or_array['disabled'];
453
+ $postfix = $label_or_array['postfix'];
454
+ }
455
+
456
  echo '<label><input type="radio" name="' . esc_attr( $name ) .
457
  '" value="' . esc_attr( $key ) . '"';
458
  checked( $value, $key );
459
+ disabled( $disabled || $item_disabled );
460
  echo ' />';
461
  echo $label;
462
+ echo '</label>' . $postfix . "\n";
463
  }
464
  }
465
 
574
  elseif ( $key == 'html' )
575
  echo $e;
576
  elseif ( $key == 'radiogroup' )
577
+ Util_Ui::radiogroup( $e['name'], $e['value'], $e['values'],
578
+ $e['disabled'], $e['separator'] );
579
  elseif ( $key == 'selectbox' )
580
  Util_Ui::selectbox( $id, $e['name'], $e['value'], $e['values'],
581
  ( isset( $e['disabled'] ) ? $e['disabled'] : false ),
659
  'name' => Util_Ui::config_key_to_http_name( $a['key'] ),
660
  'value' => $a['value'],
661
  'disabled' => $disabled,
662
+ 'values' => $a['radiogroup_values'],
663
+ 'separator' => isset( $a['radiogroup_separator'] ) ?
664
+ $a['radiogroup_separator'] : ''
665
  );
666
  } else if ( $a['control'] == 'selectbox' ) {
667
  $table_tr['selectbox'] = array(
inc/lightbox/self_test.php CHANGED
@@ -12,7 +12,7 @@ if ( !defined( 'W3TC' ) )
12
 
13
  <p>
14
  <?php _e( '<span style="background-color: #33cc33">Installed/Ok/Yes/True</span>: Functionality will work properly.', 'w3-total-cache' ); ?><br />
15
- <?php _e( '<span style="background-color: #FFFF00">Not detected/Not installed/Off</span>: May be installed, but cannot be automatically confirmed. Functionality will be limmited.', 'w3-total-cache' ); ?><br />
16
  <?php _e( '<span style="background-color: #FF0000">Not Installed/Error/No/False</span>: Plugin or some functions may not work.', 'w3-total-cache' ); ?><br />
17
  </p>
18
  </fieldset>
12
 
13
  <p>
14
  <?php _e( '<span style="background-color: #33cc33">Installed/Ok/Yes/True</span>: Functionality will work properly.', 'w3-total-cache' ); ?><br />
15
+ <?php _e( '<span style="background-color: #FFFF00">Not detected/Not installed/Off</span>: May be installed, but cannot be automatically confirmed. Functionality will be limited.', 'w3-total-cache' ); ?><br />
16
  <?php _e( '<span style="background-color: #FF0000">Not Installed/Error/No/False</span>: Plugin or some functions may not work.', 'w3-total-cache' ); ?><br />
17
  </p>
18
  </fieldset>
inc/lightbox/support_us.php CHANGED
@@ -37,52 +37,51 @@ if ( !defined( 'W3TC' ) )
37
  <form action="<?php echo Util_Ui::admin_url( 'admin.php?page=w3tc_general' ); ?>&amp;w3tc_config_save_support_us" method="post">
38
 
39
  <div class="content">
40
- <h3 class="font-palette-dark-skies"><?php _e( 'Support Us, It\'s Free!', 'w3-total-cache' ); ?></h3>
41
 
42
- <p><?php _e( 'We noticed you\'ve been using W3 Total Cache for 30 days or more, please help us improve WordPress by:', 'w3-total-cache' ); ?></p>
43
  <ul>
44
  <li>
45
  <label>
46
- Link to us: <br />
47
- <div class="styled-select">
48
- <select name="support" class="w3tc-size select">
49
- <option value=""><?php esc_attr_e( 'select location', 'w3-total-cache' ); ?></option>
50
- <?php foreach ( $supports as $support_id => $support_name ): ?>
51
- <option value="<?php echo esc_attr( $support_id ); ?>"<?php echo selected( $this->_config->get_string( 'common.support' ), $support_id ); ?>><?php echo htmlspecialchars( $support_name ); ?></option>
52
- <?php endforeach; ?>
53
- </select>
54
- </div>
55
  </label>
56
  </li>
57
  <li>
58
- <label>Send a tweet:<br />
59
  <?php
60
  $tweet_url = 'http://twitter.com/home/?status=' . urlencode( W3TC_SUPPORT_US_TWEET );
61
  echo Util_Ui::action_button(
62
- __( 'Tell Your Friends', 'w3-total-cache' ),
63
- $tweet_url,
64
- "btn w3tc-size image btn-default palette-twitter",
65
- true );
66
  echo Util_Ui::hidden(
67
- __( 'tweeted' ),
68
- __( 'tweeted' ),
69
- '0' ) ?>
70
  </label>
71
  </li>
72
  <li>
73
  <label>
74
- Login to wordpress.org to give us a great rating:<br>
75
- <?php
76
- echo Util_Ui::action_button(
77
- __( 'Login & Rate Us', 'w3-total-cache' ),
78
- W3TC_SUPPORT_US_RATE_URL,
79
- "btn w3tc-size image btn-default palette-wordpress",
80
- true ) ?>
 
 
81
  </label>
82
  </li>
83
  </ul>
84
  <p>
85
- <label class="w3tc_signup_email" for="email">You can also sign up for our newsletter:<br />
86
  <input id="email" name="email" type="text" class="form-control w3tc-size" value="<?php esc_attr_e( $email ) ?>"></label><br />
87
  <input type="checkbox" name="signmeup" id="signmeup" class="css-checkbox" value="1" checked="checked" /><label for="signmeup" class="css-label"> <?php _e( 'Yes, sign me up.', 'w3-total-cache' ) ?> </label>
88
  </p>
37
  <form action="<?php echo Util_Ui::admin_url( 'admin.php?page=w3tc_general' ); ?>&amp;w3tc_config_save_support_us" method="post">
38
 
39
  <div class="content">
40
+ <h3 class="font-palette-dark-skies"><?php _e( 'Thank you! You\'ve been using W3 Total Cache for seven days or so! Please support us:', 'w3-total-cache' ); ?></h3>
41
 
 
42
  <ul>
43
  <li>
44
  <label>
45
+ Please give us a five star rating:<br>
46
+ <?php
47
+ echo Util_Ui::action_button(
48
+ __( 'Login & Rate Us', 'w3-total-cache' ),
49
+ W3TC_SUPPORT_US_RATE_URL,
50
+ "btn w3tc-size image btn-default palette-wordpress",
51
+ true ) ?>
 
 
52
  </label>
53
  </li>
54
  <li>
55
+ <label>Post a tweet:<br />
56
  <?php
57
  $tweet_url = 'http://twitter.com/home/?status=' . urlencode( W3TC_SUPPORT_US_TWEET );
58
  echo Util_Ui::action_button(
59
+ __( 'Tell Your Friends', 'w3-total-cache' ),
60
+ $tweet_url,
61
+ "btn w3tc-size image btn-default palette-twitter",
62
+ true );
63
  echo Util_Ui::hidden(
64
+ __( 'tweeted' ),
65
+ __( 'tweeted' ),
66
+ '0' ) ?>
67
  </label>
68
  </li>
69
  <li>
70
  <label>
71
+ Link to us: <br />
72
+ <div class="styled-select">
73
+ <select name="support" class="w3tc-size select">
74
+ <option value=""><?php esc_attr_e( 'select location', 'w3-total-cache' ); ?></option>
75
+ <?php foreach ( $supports as $support_id => $support_name ): ?>
76
+ <option value="<?php echo esc_attr( $support_id ); ?>"<?php echo selected( $this->_config->get_string( 'common.support' ), $support_id ); ?>><?php echo htmlspecialchars( $support_name ); ?></option>
77
+ <?php endforeach; ?>
78
+ </select>
79
+ </div>
80
  </label>
81
  </li>
82
  </ul>
83
  <p>
84
+ <label class="w3tc_signup_email" for="email">Don't forget to join our newsletter:<br />
85
  <input id="email" name="email" type="text" class="form-control w3tc-size" value="<?php esc_attr_e( $email ) ?>"></label><br />
86
  <input type="checkbox" name="signmeup" id="signmeup" class="css-checkbox" value="1" checked="checked" /><label for="signmeup" class="css-label"> <?php _e( 'Yes, sign me up.', 'w3-total-cache' ) ?> </label>
87
  </p>
inc/lightbox/upgrade.php CHANGED
@@ -23,14 +23,17 @@ if ( !defined( 'W3TC' ) )
23
  </div>
24
  <div class="w3tc_overlay_upgrade_content_r">
25
  <ul>
 
 
 
26
  <li>
27
  <strong>Full Site Delivery (FSD)</strong><br>
28
  Provide the best user experience possible by enhancing by hosting HTML pages and RSS feeds with (supported) <acronym title="Content Delivery Network">CDN</acronym>'s high speed global networks.</li>
29
- <li><strong>Fragment Caching Module</strong><br>
30
- Unlocking the fragment caching module delivers enhanced performance for plugins and themes that use the WordPress Transient API. StudioPress' Genesis Framework is up to 60% faster with W3TC Pro.</li>
31
  <li>
32
- <strong>WPML Extension</strong><br>
33
- Improve the performance of your WPML-powered site by unlocking W3TC Pro.</li>
 
 
34
  </ul>
35
  </div>
36
  </div>
23
  </div>
24
  <div class="w3tc_overlay_upgrade_content_r">
25
  <ul>
26
+ <li>
27
+ <strong>Extension</strong><br>
28
+ Improve the performance of your Genesis, WPML-powered site, and much more by unlocking W3TC Pro.</li>
29
  <li>
30
  <strong>Full Site Delivery (FSD)</strong><br>
31
  Provide the best user experience possible by enhancing by hosting HTML pages and RSS feeds with (supported) <acronym title="Content Delivery Network">CDN</acronym>'s high speed global networks.</li>
 
 
32
  <li>
33
+ <strong>REST API Caching</strong><br>
34
+ Save resources or add scale and performance to the WordPress API with W3TC Pro.</li>
35
+ <li><strong>Fragment Caching</strong><br>
36
+ Unlocking the fragment caching module delivers enhanced performance for plugins and themes that use the WordPress Transient API. StudioPress' Genesis Framework is up to 60% faster with W3TC Pro.</li>
37
  </ul>
38
  </div>
39
  </div>
inc/options/browsercache.php CHANGED
@@ -4,6 +4,12 @@ namespace W3TC;
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
 
 
 
 
 
 
7
  ?>
8
  <?php include W3TC_INC_DIR . '/options/common/header.php'; ?>
9
 
@@ -98,7 +104,7 @@ if ( !defined( 'W3TC' ) )
98
  <textarea id="browsercache_replace_exceptions"
99
  <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
100
  name="browsercache__replace__exceptions" cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'browsercache.replace.exceptions' ) ) ); ?></textarea><br />
101
- <span class="description"><?php _e( 'Do not add the prevent caching query string to the specified URIs. Supports regular expressions.', 'w3-total-cache' ); ?></span>
102
  </td>
103
  </tr>
104
  <tr>
@@ -113,7 +119,7 @@ if ( !defined( 'W3TC' ) )
113
  <th colspan="2">
114
  <?php $this->checkbox( 'browsercache.no404wp', !Util_Rule::can_check_rules() ) ?> <?php Util_Ui::e_config_label( 'browsercache.no404wp' ) ?></label>
115
  <br /><span class="description"><?php _e( 'Reduce server load by allowing the web server to handle 404 (not found) errors for static files (images etc).', 'w3-total-cache' ); ?></span>
116
- <br /><span class="description"><?php _e( 'If enabled - you may get 404 File Not Found response for some files generated on-the-fly by WordPress plugins. You may add those file URIs to 404 error exception list below to avoid that.', 'w3-total-cache' ); ?></span>
117
  </th>
118
  </tr>
119
  <tr>
@@ -122,7 +128,7 @@ if ( !defined( 'W3TC' ) )
122
  <textarea id="browsercache_no404wp_exceptions"
123
  <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
124
  name="browsercache__no404wp__exceptions" cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'browsercache.no404wp.exceptions' ) ) ); ?></textarea><br />
125
- <span class="description"><?php _e( 'Never process 404 (not found) events for the specified URIs.', 'w3-total-cache' ); ?></span>
126
  </td>
127
  </tr>
128
  <?php
@@ -134,14 +140,6 @@ Util_Ui::config_item( array(
134
  'description' => __( 'Generate unique <acronym title="Universal Resource Indicator">URI</acronym> for each file protected from caching by browser.', 'w3-total-cache' ),
135
  'style' => '2'
136
  ) );
137
- Util_Ui::config_item( array(
138
- 'key' => 'browsercache.hsts',
139
- 'disabled' => Util_Ui::sealing_disabled( 'browsercache.' ),
140
- 'control' => 'checkbox',
141
- 'checkbox_label' => __( 'Apply <acronym title="Hypertext Transfer Protocol">HTTP</acronym> Strict Transport Security policy', 'w3-total-cache' ),
142
- 'description' => __( 'Set the <acronym title="HTTP Strict Transport Security">HSTS</acronym> header to maximize <acronym title="Secure Sockets Layer">SSL</acronym> security.', 'w3-total-cache' ),
143
- 'style' => '2'
144
- ) );
145
  ?>
146
  </table>
147
 
@@ -406,6 +404,356 @@ Util_Ui::config_item( array(
406
 
407
  <?php Util_Ui::button_config_save( 'browsercache_media' ); ?>
408
  <?php Util_Ui::postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
  </div>
410
  </form>
411
 
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
+ $security_session_values = array(
8
+ '' => 'Leave as is',
9
+ 'on' => 'Enable',
10
+ 'off' => 'Disable'
11
+ );
12
+
13
  ?>
14
  <?php include W3TC_INC_DIR . '/options/common/header.php'; ?>
15
 
104
  <textarea id="browsercache_replace_exceptions"
105
  <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
106
  name="browsercache__replace__exceptions" cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'browsercache.replace.exceptions' ) ) ); ?></textarea><br />
107
+ <span class="description"><?php _e( 'Do not add the prevent caching query string to the specified <acronym title="Uniform Resource Identifier">URI</acronym>s. Supports regular expressions.', 'w3-total-cache' ); ?></span>
108
  </td>
109
  </tr>
110
  <tr>
119
  <th colspan="2">
120
  <?php $this->checkbox( 'browsercache.no404wp', !Util_Rule::can_check_rules() ) ?> <?php Util_Ui::e_config_label( 'browsercache.no404wp' ) ?></label>
121
  <br /><span class="description"><?php _e( 'Reduce server load by allowing the web server to handle 404 (not found) errors for static files (images etc).', 'w3-total-cache' ); ?></span>
122
+ <br /><span class="description"><?php _e( 'If enabled - you may get 404 File Not Found response for some files generated on-the-fly by WordPress plugins. You may add those file <acronym title="Uniform Resource Identifier">URI</acronym>s to 404 error exception list below to avoid that.', 'w3-total-cache' ); ?></span>
123
  </th>
124
  </tr>
125
  <tr>
128
  <textarea id="browsercache_no404wp_exceptions"
129
  <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
130
  name="browsercache__no404wp__exceptions" cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'browsercache.no404wp.exceptions' ) ) ); ?></textarea><br />
131
+ <span class="description"><?php _e( 'Never process 404 (not found) events for the specified <acronym title="Uniform Resource Identifier">URI</acronym>s.', 'w3-total-cache' ); ?></span>
132
  </td>
133
  </tr>
134
  <?php
140
  'description' => __( 'Generate unique <acronym title="Universal Resource Indicator">URI</acronym> for each file protected from caching by browser.', 'w3-total-cache' ),
141
  'style' => '2'
142
  ) );
 
 
 
 
 
 
 
 
143
  ?>
144
  </table>
145
 
404
 
405
  <?php Util_Ui::button_config_save( 'browsercache_media' ); ?>
406
  <?php Util_Ui::postbox_footer(); ?>
407
+
408
+ <?php Util_Ui::postbox_header( __( 'Security Headers', 'w3-total-cache' ), '', 'security' ); ?>
409
+ <p><?php _e( '<acronym title="Hypertext Transfer Protocol">HTTP</acronym> security headers provide another layer of protection for your website by helping to mitigate attacks and security vulnerabilities.', 'w3-total-cache' ); ?></p>
410
+ <table class="form-table">
411
+ <?php
412
+ Util_Ui::config_item( array(
413
+ 'key' => 'browsercache.security.session.use_only_cookies',
414
+ 'control' => 'selectbox',
415
+ 'selectbox_values' => $security_session_values,
416
+ 'description' => __( 'This setting prevents attacks that are caused by passing session IDs in URLs.',
417
+ 'w3-total-cache' )
418
+ ) );
419
+ ?>
420
+ <?php
421
+ Util_Ui::config_item( array(
422
+ 'key' => 'browsercache.security.session.cookie_httponly',
423
+ 'control' => 'selectbox',
424
+ 'selectbox_values' => $security_session_values,
425
+ 'description' => __( 'This tells the user\'s browser not to make the session cookie accessible to client side scripting such as JavaScript. This makes it harder for an attacker to hijack the session ID and masquerade as the effected user.',
426
+ 'w3-total-cache' )
427
+ ) );
428
+ ?>
429
+ <?php
430
+ Util_Ui::config_item( array(
431
+ 'key' => 'browsercache.security.session.cookie_secure',
432
+ 'control' => 'selectbox',
433
+ 'selectbox_values' => $security_session_values,
434
+ 'description' => __( 'This will prevent the user\'s session ID from being transmitted in plain text, making it much harder to hijack the user\'s session.',
435
+ 'w3-total-cache' )
436
+ ) );
437
+ ?>
438
+ <tr>
439
+ <th colspan="2">
440
+ <?php $this->checkbox( 'browsercache.hsts' ) ?> <?php Util_Ui::e_config_label( 'browsercache.hsts' ) ?></label>
441
+ <br /><span class="description"><?php _e( '<acronym title="Hypertext Transfer Protocol">HTTP</acronym> Strict-Transport-Security (HSTS) enforces secure (<acronym title="Hypertext Transfer Protocol">HTTP</acronym> over <acronym title="Secure Sockets Layer">SSL</acronym>/<acronym title="Transport Layer Security">TLS</acronym>) connections to the server. This can help mitigate adverse effects caused by bugs and session leaks through cookies and links. It also helps defend against man-in-the-middle attacks. If there are <acronym title="Secure Sockets Layer">SSL</acronym> negotiation warnings then users will not be permitted to ignore them.', 'w3-total-cache' ); ?></span>
442
+ </th>
443
+ </tr>
444
+ <tr>
445
+ <th>
446
+ <label for="browsercache_security_hsts_directive"><?php Util_Ui::e_config_label( 'browsercache.security.hsts.directive' ) ?></label>
447
+ </th>
448
+ <td>
449
+ <select id="browsercache_security_hsts_directive"
450
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
451
+ name="browsercache__security__hsts__directive">
452
+ <?php $value = $this->_config->get_string( 'browsercache.security.hsts.directive' ); ?>
453
+ <option value="maxage"<?php selected( $value, 'maxage' ); ?>><?php _e( 'max-age=EXPIRES_SECONDS', 'w3-total-cache' ); ?></option>
454
+ <option value="maxagepre"<?php selected( $value, 'maxagepre' ); ?>><?php _e( 'max-age=EXPIRES_SECONDS; preload', 'w3-total-cache' ); ?></option>
455
+ <option value="maxageinc"<?php selected( $value, 'maxageinc' ); ?>><?php _e( 'max-age=EXPIRES_SECONDS; includeSubDomains', 'w3-total-cache' ); ?></option>
456
+ <option value="maxageincpre"<?php selected( $value, 'maxageincpre' ); ?>><?php _e( 'max-age=EXPIRES_SECONDS; includeSubDomains; preload', 'w3-total-cache' ); ?></option>
457
+ </select>
458
+ <div id="browsercache_security_hsts_directive_description"></div>
459
+ </td>
460
+ </tr>
461
+ <tr>
462
+ <th colspan="2">
463
+ <?php $this->checkbox( 'browsercache.security.xfo' ) ?> <?php Util_Ui::e_config_label( 'browsercache.security.xfo' ) ?></label>
464
+ <br /><span class="description"><?php _e( 'This tells the browser if it is permitted to render a page within a frame-like tag (i.e., &lt;frame&gt;, &lt;iframe&gt; or &lt;object&gt;). This is useful for preventing clickjacking attacks.', 'w3-total-cache' ); ?></span>
465
+ </th>
466
+ </tr>
467
+ <tr>
468
+ <th>
469
+ <label for="browsercache_security_xfo_directive"><?php Util_Ui::e_config_label( 'browsercache.security.xfo.directive' ) ?></label>
470
+ </th>
471
+ <td>
472
+ <select id="browsercache_security_xfo_directive"
473
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
474
+ name="browsercache__security__xfo__directive">
475
+ <?php $value = $this->_config->get_string( 'browsercache.security.xfo.directive' ); ?>
476
+ <option value="same"<?php selected( $value, 'same' ); ?>><?php _e( 'SameOrigin', 'w3-total-cache' ); ?></option>
477
+ <option value="deny"<?php selected( $value, 'deny' ); ?>><?php _e( 'Deny', 'w3-total-cache' ); ?></option>
478
+ <option value="allow"<?php selected( $value, 'allow' ); ?>><?php _e( 'Allow-From', 'w3-total-cache' ); ?></option>
479
+ </select>
480
+ <input id="browsercache_security_xfo_allow" type="text" name="browsercache__security__xfo__allow"
481
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.xfo.allow' ) ); ?>" size="50" placeholder="Enter URL" />
482
+ <div id="browsercache_security_xfo_directive_description"></div>
483
+ </td>
484
+ </tr>
485
+ <tr>
486
+ <th colspan="2">
487
+ <?php $this->checkbox( 'browsercache.security.xss' ) ?> <?php Util_Ui::e_config_label( 'browsercache.security.xss' ) ?></label>
488
+ <br /><span class="description"><?php _e( 'This header enables the Cross-Site Scripting (XSS) filter. It helps to stop malicious scripts from being injected into your website. Although this is already built into and enabled by default in most browsers today it is made available here to enforce its reactivation if it was disabled within the user\'s browser.', 'w3-total-cache' ); ?></span>
489
+ </th>
490
+ </tr>
491
+ <tr>
492
+ <th>
493
+ <label for="browsercache_security_xss_directive"><?php Util_Ui::e_config_label( 'browsercache.security.xss.directive' ) ?></label>
494
+ </th>
495
+ <td>
496
+ <select id="browsercache_security_xss_directive"
497
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
498
+ name="browsercache__security__xss__directive">
499
+ <?php $value = $this->_config->get_string( 'browsercache.security.xss.directive' ); ?>
500
+ <option value="0"<?php selected( $value, '0' ); ?>><?php _e( '0', 'w3-total-cache' ); ?></option>
501
+ <option value="1"<?php selected( $value, '1' ); ?>><?php _e( '1', 'w3-total-cache' ); ?></option>
502
+ <option value="block"<?php selected( $value, 'block' ); ?>><?php _e( '1; mode=block', 'w3-total-cache' ); ?></option>
503
+ </select>
504
+ <div id="browsercache_security_xss_directive_description"></div>
505
+ </td>
506
+ </tr>
507
+ <tr>
508
+ <th colspan="2">
509
+ <?php $this->checkbox( 'browsercache.security.xcto' ) ?> <?php Util_Ui::e_config_label( 'browsercache.security.xcto' ) ?></label>
510
+ <br /><span class="description"><?php _e( 'This instructs the browser to not MIME-sniff a response outside its declared content-type. It helps to reduce drive-by download attacks and stops sites from serving malevolent content that could masquerade as an executable or dynamic HTML file.', 'w3-total-cache' ); ?></span>
511
+ </th>
512
+ </tr>
513
+ <tr>
514
+ <th colspan="2">
515
+ <?php $this->checkbox( 'browsercache.security.pkp' ) ?> <?php Util_Ui::e_config_label( 'browsercache.security.pkp' ) ?></label>
516
+ <br /><span class="description"><?php _e( '<acronym title="Hypertext Transfer Protocol">HTTP</acronym> Public Key Pinning (<acronym title="HTTP Public Key Pinning">HPKP</acronym>) is a security feature for <acronym title="Hypertext Transfer Protocol">HTTP</acronym>S websites that can prevent fraudulently issued certificates from being used to impersonate existing secure websites.' ); ?></span>
517
+ </th>
518
+ </tr>
519
+ <tr>
520
+ <th>
521
+ <label for="browsercache_security_pkp_pin"><?php Util_Ui::e_config_label( 'browsercache.security.pkp.pin' ) ?></label>
522
+ </th>
523
+ <td>
524
+ <input id="browsercache_security_pkp_pin" type="text" name="browsercache__security__pkp__pin"
525
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.pkp.pin' ) ); ?>" size="50" placeholder="Enter the Base64-Encode of the SHA256 Hash" />
526
+ <div><i><?php _e( 'This field is <b>required</b> and represents a <acronym title="Subject Public Key Information">SPKI</acronym> fingerprint. This pin is any public key within your current certificate chain.' ); ?></i></div>
527
+ </td>
528
+ </tr>
529
+ <tr>
530
+ <th>
531
+ <label for="browsercache_security_pkp_pin_backup"><?php Util_Ui::e_config_label( 'browsercache.security.pkp.pin.backup' ) ?></label>
532
+ </th>
533
+ <td>
534
+ <input id="browsercache_security_pkp_pin_backup" type="text" name="browsercache__security__pkp__pin__backup"
535
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.pkp.pin.backup' ) ); ?>" size="50" placeholder="Enter the Base64-Encode of the SHA256 Hash" />
536
+ <div><i><?php _e( 'This field is <b>also required</b> and represents your backup <acronym title="Subject Public Key Information">SPKI</acronym> fingerprint. This pin is any public key not in your current certificate chain and serves as a backup in case your certificate expires or has to be revoked.' ); ?></i></div>
537
+ </td>
538
+ </tr>
539
+ <tr>
540
+ <th>
541
+ <label for="browsercache_security_pkp_extra"><?php Util_Ui::e_config_label( 'browsercache.security.pkp.extra' ) ?></label>
542
+ </th>
543
+ <td>
544
+ <select id="browsercache_security_pkp_extra"
545
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
546
+ name="browsercache__security__pkp__extra">
547
+ <?php $value = $this->_config->get_string( 'browsercache.security.pkp.extra' ); ?>
548
+ <option value="maxage"<?php selected( $value, 'maxage' ); ?>><?php _e( 'max-age=EXPIRES_SECONDS', 'w3-total-cache' ); ?></option>
549
+ <option value="maxageinc"<?php selected( $value, 'maxageinc' ); ?>><?php _e( 'max-age=EXPIRES_SECONDS; includeSubDomains', 'w3-total-cache' ); ?></option>
550
+ </select>
551
+ <div id="browsercache_security_pkp_extra_description"></div>
552
+ </td>
553
+ </tr>
554
+ <tr>
555
+ <th>
556
+ <label for="browsercache_security_pkp_report_url"><?php Util_Ui::e_config_label( 'browsercache.security.pkp.report.url' ) ?></label>
557
+ </th>
558
+ <td>
559
+ <input id="browsercache_security_pkp_report_url" type="text" name="browsercache__security__pkp__report__url"
560
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.pkp.report.url' ) ); ?>" size="50" placeholder="Enter URL" />
561
+ <div><i><?php _e( 'This optional field can be used to specify a URL that clients will send reports to if pin validation failures occur. The report is sent as a POST request with a JSON body.' ); ?></i></div>
562
+ </td>
563
+ </tr>
564
+ <tr>
565
+ <th>
566
+ <label for="browsercache_security_pkp_report_only"><?php Util_Ui::e_config_label( 'browsercache.security.pkp.report.only' ) ?></label>
567
+ </th>
568
+ <td>
569
+ <select id="browsercache_security_pkp_report_only"
570
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
571
+ name="browsercache__security__pkp__report__only">
572
+ <?php $value = $this->_config->get_string( 'browsercache.security.pkp.report.only' ); ?>
573
+ <option value="0"<?php selected( $value, '0' ); ?>><?php _e( 'No = Enforce HPKP', 'w3-total-cache' ); ?></option>
574
+ <option value="1"<?php selected( $value, '1' ); ?>><?php _e( 'Yes = Don\'t Enforce HPKP', 'w3-total-cache' ); ?></option>
575
+ </select>
576
+ <div id="browsercache_security_pkp_report_only_description"></div>
577
+ </td>
578
+ </tr>
579
+ <tr>
580
+ <th colspan="2">
581
+ <?php $this->checkbox( 'browsercache.security.referrer.policy' ) ?> <?php Util_Ui::e_config_label( 'browsercache.security.referrer.policy' ) ?></label>
582
+ <br /><span class="description"><?php _e( 'This header restricts the values of the referer header in outbound links.' ); ?></span>
583
+ </th>
584
+ </tr>
585
+ <tr>
586
+ <th>
587
+ <label for="browsercache_security_referrer_policy_directive"><?php Util_Ui::e_config_label( 'browsercache.security.referrer.policy.directive' ) ?></label>
588
+ </th>
589
+ <td>
590
+ <select id="browsercache_security_referrer_policy_directive"
591
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?>
592
+ name="browsercache__security__referrer__policy__directive">
593
+ <?php $value = $this->_config->get_string( 'browsercache.security.referrer.policy.directive' ); ?>
594
+ <option value="0"<?php selected( $value, '0' ); ?>><?php _e( '""', 'w3-total-cache' ); ?></option>
595
+ <option value="no-referrer"<?php selected( $value, 'no-referrer' ); ?>><?php _e( 'no-referrer', 'w3-total-cache' ); ?></option>
596
+ <option value="no-referrer-when-downgrade"<?php selected( $value, 'no-referrer-when-downgrade' ); ?>><?php _e( 'no-referrer-when-downgrade', 'w3-total-cache' ); ?></option>
597
+ <option value="same-origin"<?php selected( $value, 'same-origin' ); ?>><?php _e( 'same-origin', 'w3-total-cache' ); ?></option>
598
+ <option value="origin"<?php selected( $value, 'origin' ); ?>><?php _e( 'origin', 'w3-total-cache' ); ?></option>
599
+ <option value="strict-origin"<?php selected( $value, 'strict-origin' ); ?>><?php _e( 'strict-origin', 'w3-total-cache' ); ?></option>
600
+ <option value="origin-when-cross-origin"<?php selected( $value, 'origin-when-cross-origin' ); ?>><?php _e( 'origin-when-cross-origin', 'w3-total-cache' ); ?></option>
601
+ <option value="unsafe-url"<?php selected( $value, 'unsafe-url' ); ?>><?php _e( 'unsafe-url', 'w3-total-cache' ); ?></option>
602
+ </select>
603
+ <div id="browsercache_security_referrer_policy_directive_description"></div>
604
+ </td>
605
+ </tr>
606
+ <tr>
607
+ <th colspan="2">
608
+ <?php $this->checkbox( 'browsercache.security.csp' ) ?> <?php Util_Ui::e_config_label( 'browsercache.security.csp' ) ?></label>
609
+ <br /><span class="description"><?php _e( 'The Content Security Policy (<acronym title="Content Security Policy">CSP</acronym>) header reduces the risk of <acronym title="Cross-Site Scripting">XSS</acronym> attacks by allowing you to define where resources can be retrieved from, preventing browsers from loading data from any other locations. This makes it harder for an attacker to inject malicious code into your site.' ); ?></span>
610
+ <p><a onclick="w3tc_csp_reference()" href="javascript:void(0);">Quick Reference Chart</a></p>
611
+ </th>
612
+ </tr>
613
+ <tr>
614
+ <th>
615
+ <label for="browsercache_security_csp_base"><?php Util_Ui::e_config_label( 'browsercache.security.csp.base' ) ?></label>
616
+ </th>
617
+ <td>
618
+ <input id="browsercache_security_csp_base" type="text" name="browsercache__security__csp__base"
619
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.base' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
620
+ <div><i><?php _e( 'Restricts the URLs which can be used in a document\'s &lt;base&gt; element.' ); ?></i></div>
621
+ </td>
622
+ </tr>
623
+ <tr>
624
+ <th>
625
+ <label for="browsercache_security_csp_connect"><?php Util_Ui::e_config_label( 'browsercache.security.csp.connect' ) ?></label>
626
+ </th>
627
+ <td>
628
+ <input id="browsercache_security_csp_connect" type="text" name="browsercache__security__csp__connect"
629
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.connect' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
630
+ <div><i><?php _e( 'Limits the origins to which you can connect via XMLHttpRequest, WebSockets, and EventSource.' ); ?></i></div>
631
+ </td>
632
+ </tr>
633
+ <tr>
634
+ <th>
635
+ <label for="browsercache_security_csp_font"><?php Util_Ui::e_config_label( 'browsercache.security.csp.font' ) ?></label>
636
+ </th>
637
+ <td>
638
+ <input id="browsercache_security_csp_font" type="text" name="browsercache__security__csp__font"
639
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.font' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
640
+ <div><i><?php _e( 'Specifies the origins that can serve web fonts.' ); ?></i></div>
641
+ </td>
642
+ </tr>
643
+ <tr>
644
+ <th>
645
+ <label for="browsercache_security_csp_frame"><?php Util_Ui::e_config_label( 'browsercache.security.csp.frame' ) ?></label>
646
+ </th>
647
+ <td>
648
+ <input id="browsercache_security_csp_frame" type="text" name="browsercache__security__csp__frame"
649
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.frame' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
650
+ <div><i><?php _e( 'Restricts from where the protected resource can embed frames.' ); ?></i></div>
651
+ </td>
652
+ </tr>
653
+ <tr>
654
+ <th>
655
+ <label for="browsercache_security_csp_img"><?php Util_Ui::e_config_label( 'browsercache.security.csp.img' ) ?></label>
656
+ </th>
657
+ <td>
658
+ <input id="browsercache_security_csp_img" type="text" name="browsercache__security__csp__img"
659
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.img' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
660
+ <div><i><?php _e( 'Specifies valid sources for images and favicons.' ); ?></i></div>
661
+ </td>
662
+ </tr>
663
+ <tr>
664
+ <th>
665
+ <label for="browsercache_security_csp_media"><?php Util_Ui::e_config_label( 'browsercache.security.csp.media' ) ?></label>
666
+ </th>
667
+ <td>
668
+ <input id="browsercache_security_csp_media" type="text" name="browsercache__security__csp__media"
669
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.media' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
670
+ <div><i><?php _e( 'Specifies valid sources for loading media using the &lt;audio&gt; and &lt;video&gt; elements.' ); ?></i></div>
671
+ </td>
672
+ </tr>
673
+ <tr>
674
+ <th>
675
+ <label for="browsercache_security_csp_object"><?php Util_Ui::e_config_label( 'browsercache.security.csp.object' ) ?></label>
676
+ </th>
677
+ <td>
678
+ <input id="browsercache_security_csp_object" type="text" name="browsercache__security__csp__object"
679
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.object' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
680
+ <div><i><?php _e( 'Allows control over the &lt;object&gt;, &lt;embed&gt;, and &lt;applet&gt; elements used by Flash and other plugins.' ); ?></i></div>
681
+ </td>
682
+ </tr>
683
+ <tr>
684
+ <th>
685
+ <label for="browsercache_security_csp_script"><?php Util_Ui::e_config_label( 'browsercache.security.csp.script' ) ?></label>
686
+ </th>
687
+ <td>
688
+ <input id="browsercache_security_csp_script" type="text" name="browsercache__security__csp__script"
689
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.script' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
690
+ <div><i><?php _e( 'Specifies valid sources for JavaScript.' ); ?></i></div>
691
+ </td>
692
+ </tr>
693
+ <tr>
694
+ <th>
695
+ <label for="browsercache_security_csp_style"><?php Util_Ui::e_config_label( 'browsercache.security.csp.style' ) ?></label>
696
+ </th>
697
+ <td>
698
+ <input id="browsercache_security_csp_style" type="text" name="browsercache__security__csp__style"
699
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.style' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
700
+ <div><i><?php _e( 'Specifies valid sources for CSS stylesheets.' ); ?></i></div>
701
+ </td>
702
+ </tr>
703
+ <tr>
704
+ <th>
705
+ <label for="browsercache_security_csp_form"><?php Util_Ui::e_config_label( 'browsercache.security.csp.form' ) ?></label>
706
+ </th>
707
+ <td>
708
+ <input id="browsercache_security_csp_form" type="text" name="browsercache__security__csp__form"
709
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.form' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
710
+ <div><i><?php _e( 'Restricts the URLs which can be used as the target of form submissions from a given context.' ); ?></i></div>
711
+ </td>
712
+ </tr>
713
+ <tr>
714
+ <th>
715
+ <label for="browsercache_security_csp_frame_ancestors"><?php Util_Ui::e_config_label( 'browsercache.security.csp.frame.ancestors' ) ?></label>
716
+ </th>
717
+ <td>
718
+ <input id="browsercache_security_csp_frame_ancestors" type="text" name="browsercache__security__csp__frame__ancestors"
719
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.frame' ) ); ?>" size="50" placeholder="Example: 'none'" />
720
+ <div><i><?php _e( 'Specifies valid parents that may embed a page using &lt;frame&gt;, &lt;iframe&gt;, &lt;object&gt;, &lt;embed&gt;, or &lt;applet&gt;.' ); ?></i></div>
721
+ </td>
722
+ </tr>
723
+ <tr>
724
+ <th>
725
+ <label for="browsercache_security_csp_plugin"><?php Util_Ui::e_config_label( 'browsercache.security.csp.plugin' ) ?></label>
726
+ </th>
727
+ <td>
728
+ <input id="browsercache_security_csp_plugin" type="text" name="browsercache__security__csp__plugin"
729
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.plugin' ) ); ?>" size="50" placeholder="Example: application/x-shockwave-flash" />
730
+ <div><i><?php _e( 'Restricts the set of plugins that can be embedded into a document by limiting the types of resources which can be loaded.' ); ?></i></div>
731
+ </td>
732
+ </tr>
733
+ <tr>
734
+ <th>
735
+ <label for="browsercache_security_csp_sandbox"><?php Util_Ui::e_config_label( 'browsercache.security.csp.sandbox' ) ?></label>
736
+ </th>
737
+ <td>
738
+ <input id="browsercache_security_csp_sandbox" type="text" name="browsercache__security__csp__sandbox"
739
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.sandbox' ) ); ?>" size="50" placeholder="Example: allow-popups" />
740
+ <div><i><?php _e( 'This directive operates similarly to the &lt;iframe&gt; sandbox attribute by applying restrictions to a page\'s actions, including preventing popups, preventing the execution of plugins and scripts, and enforcing a same-origin policy.' ); ?></i></div>
741
+ </td>
742
+ </tr>
743
+ <tr>
744
+ <th>
745
+ <label for="browsercache_security_csp_default"><?php Util_Ui::e_config_label( 'browsercache.security.csp.default' ) ?></label>
746
+ </th>
747
+ <td>
748
+ <input id="browsercache_security_csp_default" type="text" name="browsercache__security__csp__default"
749
+ <?php Util_Ui::sealing_disabled( 'browsercache.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'browsercache.security.csp.default' ) ); ?>" size="50" placeholder="Example: 'self' 'unsafe-inline' *.domain.com" />
750
+ <div><i><?php _e( 'Defines the defaults for directives you leave unspecified. Generally, this applies to any directive that ends with -src.' ); ?></i></div>
751
+ </td>
752
+ </tr>
753
+ </table>
754
+
755
+ <?php Util_Ui::button_config_save( 'browsercache_security' ); ?>
756
+ <?php Util_Ui::postbox_footer(); ?>
757
  </div>
758
  </form>
759
 
inc/options/cdn.php CHANGED
@@ -160,8 +160,9 @@ if ( !$upload_blogfiles_enabled )
160
  <table class="form-table">
161
  <?php
162
  if ( $cdn_engine == 'google_drive' || $cdn_engine == 'highwinds' ||
163
- $cdn_engine == 'maxcdn' ||
164
- $cdn_engine == 'rackspace_cdn' || $cdn_engine == 'rscf' ) {
 
165
  do_action( 'w3tc_settings_cdn_boxarea_configuration' );
166
  } else if ( Cdn_Util::is_engine( $cdn_engine ) ) {
167
  include W3TC_INC_DIR . '/options/cdn/' . $cdn_engine . '.php';
@@ -185,7 +186,7 @@ if ( $cdn_engine == 'google_drive' || $cdn_engine == 'highwinds' ||
185
  <tr>
186
  <th colspan="2">
187
  <?php $this->checkbox( 'cdn.admin.media_library' ) ?> <?php Util_Ui::e_config_label( 'cdn.admin.media_library' ) ?></label><br />
188
- <span class="description">All Media Library content will use CDN links on administration pages.</span>
189
  </th>
190
  </tr>
191
  <tr>
@@ -200,7 +201,7 @@ if ( $cdn_engine == 'google_drive' || $cdn_engine == 'highwinds' ||
200
  <?php $this->checkbox( 'cdn.reject.logged_roles' ) ?> <?php Util_Ui::e_config_label( 'cdn.reject.logged_roles' ) ?></label><br />
201
  <span class="description"><?php _e( 'Select user roles that will use the origin server exclusively:', 'w3-total-cache' ) ?></span>
202
 
203
- <div id="cdn_reject_roles">
204
  <?php $saved_roles = $this->_config->get_array( 'cdn.reject.roles' ); ?>
205
  <input type="hidden" name="cdn__reject__roles" value="" /><br />
206
  <?php foreach ( get_editable_roles() as $role_name => $role_data ) : ?>
160
  <table class="form-table">
161
  <?php
162
  if ( $cdn_engine == 'google_drive' || $cdn_engine == 'highwinds' ||
163
+ $cdn_engine == 'limelight' ||
164
+ $cdn_engine == 'maxcdn' || $cdn_engine == 'rackspace_cdn' ||
165
+ $cdn_engine == 'rscf' || $cdn_engine == 'stackpath' ) {
166
  do_action( 'w3tc_settings_cdn_boxarea_configuration' );
167
  } else if ( Cdn_Util::is_engine( $cdn_engine ) ) {
168
  include W3TC_INC_DIR . '/options/cdn/' . $cdn_engine . '.php';
186
  <tr>
187
  <th colspan="2">
188
  <?php $this->checkbox( 'cdn.admin.media_library' ) ?> <?php Util_Ui::e_config_label( 'cdn.admin.media_library' ) ?></label><br />
189
+ <span class="description">All Media Library content will use <acronym title="Content Delivery Network">CDN</acronym> links on administration pages.</span>
190
  </th>
191
  </tr>
192
  <tr>
201
  <?php $this->checkbox( 'cdn.reject.logged_roles' ) ?> <?php Util_Ui::e_config_label( 'cdn.reject.logged_roles' ) ?></label><br />
202
  <span class="description"><?php _e( 'Select user roles that will use the origin server exclusively:', 'w3-total-cache' ) ?></span>
203
 
204
+ <div id="cdn_reject_roles" class="w3tc_reject_roles">
205
  <?php $saved_roles = $this->_config->get_array( 'cdn.reject.roles' ); ?>
206
  <input type="hidden" name="cdn__reject__roles" value="" /><br />
207
  <?php foreach ( get_editable_roles() as $role_name => $role_data ) : ?>
inc/options/common/header.php CHANGED
@@ -123,7 +123,8 @@ $licensing_visible = ( ( !Util_Environment::is_wpmu() || is_network_admin() ) &&
123
  <a href="#general"><?php _e( 'General', 'w3-total-cache' ); ?></a> |
124
  <a href="#css_js"><?php _e( '<acronym title="Cascading Style Sheet">CSS</acronym> &amp; <acronym title="JavaScript">JS</acronym>', 'w3-total-cache' ); ?></a> |
125
  <a href="#html_xml"><?php _e( '<acronym title="Hypertext Markup Language">HTML</acronym> &amp; <acronym title="eXtensible Markup Language">XML</acronym>', 'w3-total-cache' ); ?></a> |
126
- <a href="#media"><?php _e( 'Media', 'w3-total-cache' ); ?></a>
 
127
  </p>
128
  <?php
129
  break;
123
  <a href="#general"><?php _e( 'General', 'w3-total-cache' ); ?></a> |
124
  <a href="#css_js"><?php _e( '<acronym title="Cascading Style Sheet">CSS</acronym> &amp; <acronym title="JavaScript">JS</acronym>', 'w3-total-cache' ); ?></a> |
125
  <a href="#html_xml"><?php _e( '<acronym title="Hypertext Markup Language">HTML</acronym> &amp; <acronym title="eXtensible Markup Language">XML</acronym>', 'w3-total-cache' ); ?></a> |
126
+ <a href="#media"><?php _e( 'Media', 'w3-total-cache' ); ?></a> |
127
+ <a href="#security"><?php _e( 'Security Headers', 'w3-total-cache' ); ?></a>
128
  </p>
129
  <?php
130
  break;
inc/options/dashboard.php CHANGED
@@ -40,7 +40,7 @@ echo implode( " $string ", apply_filters( 'w3tc_dashboard_actions', array() ) )
40
  <div class="content">
41
  <div id="dashboard-text" style="display:inline-block;">
42
  <h1><?php _e( 'Dashboard', 'w3-total-cache' )?></h1>
43
- <p>Thanks for choosing W3TC as your Web Performance Optimization (<acronym title="Web Performance Optimization">WPO</acronym>) framework. Please share <a href="admin.php?page=w3tc_support&amp;request_type=new_feature">your suggestions</a> about the statistics and reporting you would like to see!</p>
44
  </div>
45
  <div id="widgets-container">
46
  <?php do_meta_boxes( $screen->id, 'normal', '' ); ?>
40
  <div class="content">
41
  <div id="dashboard-text" style="display:inline-block;">
42
  <h1><?php _e( 'Dashboard', 'w3-total-cache' )?></h1>
43
+ <p>Thanks for choosing W3TC as your Web Performance Optimization (<acronym title="Web Performance Optimization">WPO</acronym>) framework!
44
  </div>
45
  <div id="widgets-container">
46
  <?php do_meta_boxes( $screen->id, 'normal', '' ); ?>
inc/options/faq.php DELETED
@@ -1,40 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- if ( !defined( 'W3TC' ) )
5
- die();
6
-
7
- include W3TC_INC_DIR . '/options/common/header.php';
8
- ?>
9
-
10
- <h4 id="toc"><?php _e( 'Table of Contents', 'w3-total-cache' ); ?></h4>
11
-
12
- <?php foreach ( $columns as $number => $sections ): ?>
13
- <div style="float: left; width: 29%; margin-left: 30px">
14
- <?php foreach ( $sections as $section ): ?>
15
- <?php if ( isset( $faq[$section] ) ): ?>
16
- <div style="margin-bottom: 20px">
17
- <h5><?php echo strtoupper( $section ); ?>:</h5>
18
- <ul>
19
- <?php foreach ( $faq[$section] as $entry ): ?>
20
- <li><a href="#<?php echo $entry['tag']; ?>"><?php echo $entry['question']; ?></a></li>
21
- <?php endforeach; ?>
22
- </ul>
23
- </div>
24
- <?php endif; ?>
25
- <?php endforeach; ?>
26
- </div>
27
- <?php endforeach; ?>
28
-
29
- <div id="qa">
30
- <hr />
31
- <?php foreach ( $faq as $section => $entries ): ?>
32
- <?php foreach ( $entries as $entry ): ?>
33
- <p id="<?php echo $entry['tag']; ?>"><strong><?php echo $entry['question']; ?></strong></p>
34
- <?php echo $entry['answer']; ?>
35
- <p align="right"><a href="#toc">back to top</a></p>
36
- <?php endforeach; ?>
37
- <?php endforeach; ?>
38
- </div>
39
-
40
- <?php include W3TC_INC_DIR . '/options/common/footer.php'; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/general.php CHANGED
@@ -419,8 +419,7 @@ Util_Ui::config_item( array(
419
  <th><label for="widget_pagespeed_key"><?php Util_Ui::e_config_label( 'widget.pagespeed.key' ) ?></label></th>
420
  <td>
421
  <input id="widget_pagespeed_key" type="text" name="widget__pagespeed__key" value="<?php echo esc_attr( $this->_config->get_string( 'widget.pagespeed.key' ) ); ?>" <?php Util_Ui::sealing_disabled( 'common.' ) ?> size="60" /><br />
422
- <span class="description"><?php _e( 'To acquire an <acronym title="Application Programming Interface">API</acronym> key, visit the <a href="https://code.google.com/apis/console" target="_blank"><acronym title="Application Programming Interface">API</acronym>s Console</a>. Go to the Project Home tab, activate the PageSpeed Insights <acronym title="Application Programming Interface">API</acronym>, and accept the Terms of Service.
423
- Then go to the <acronym title="Application Programming Interface">API</acronym> Access tab. The <acronym title="Application Programming Interface">API</acronym> key is in the Simple <acronym title="Application Programming Interface">API</acronym> Access section.', 'w3-total-cache' ); ?></span>
424
  </td>
425
  </tr>
426
  <tr>
419
  <th><label for="widget_pagespeed_key"><?php Util_Ui::e_config_label( 'widget.pagespeed.key' ) ?></label></th>
420
  <td>
421
  <input id="widget_pagespeed_key" type="text" name="widget__pagespeed__key" value="<?php echo esc_attr( $this->_config->get_string( 'widget.pagespeed.key' ) ); ?>" <?php Util_Ui::sealing_disabled( 'common.' ) ?> size="60" /><br />
422
+ <span class="description"><?php _e( 'Learn more about obtaining a <a href="https://support.google.com/cloud/answer/6158862" target="_blank"><acronym title="Application Programming Interface">API</acronym> key here</a>.', 'w3-total-cache' ); ?></span>
 
423
  </td>
424
  </tr>
425
  <tr>
inc/options/pgcache.php CHANGED
@@ -80,7 +80,7 @@ echo sprintf( __( 'To rebuild the page cache use the %s operation', 'w3-total-ca
80
  <?php $this->checkbox( 'pgcache.reject.logged_roles' ) ?> <?php Util_Ui::e_config_label( 'pgcache.reject.logged_roles' ) ?></label><br />
81
  <span class="description"><?php _e( 'Select user roles that should not receive cached pages:', 'w3-total-cache' ); ?></span>
82
 
83
- <div id="pgcache_reject_roles">
84
  <?php $saved_roles = $this->_config->get_array( 'pgcache.reject.roles' ); ?>
85
  <input type="hidden" name="pgcache__reject__roles" value="" /><br />
86
  <?php foreach ( get_editable_roles() as $role_name => $role_data ) : ?>
@@ -183,6 +183,7 @@ Util_Ui::postbox_header( __( 'Purge Policy: ', 'w3-total-cache' ) . implode( ',
183
  <?php $this->checkbox( 'pgcache.purge.home' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.home' ) ?></label><br />
184
  <?php $this->checkbox( 'pgcache.purge.post' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.post' ) ?></label><br />
185
  <?php $this->checkbox( 'pgcache.purge.feed.blog' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.feed.blog' ) ?></label><br />
 
186
  </th>
187
  <th>
188
  <?php $this->checkbox( 'pgcache.purge.comments' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.comments' ) ?></label><br />
@@ -247,6 +248,32 @@ Util_Ui::postbox_header( __( 'Purge Policy: ', 'w3-total-cache' ) . implode( ',
247
  <?php echo Util_Ui::button_config_save( 'pagecache_purge_policy' ); ?>
248
  <?php Util_Ui::postbox_footer(); ?>
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  <?php Util_Ui::postbox_header( __( 'Advanced', 'w3-total-cache' ), '', 'advanced' ); ?>
251
  <table class="form-table">
252
  <tr>
@@ -303,7 +330,7 @@ if ( $this->_config->get_string( 'pgcache.engine' ) == 'memcached' ) {
303
  </td>
304
  </tr>
305
  <?php endif; ?>
306
- <?php if ( $this->_config->get_string( 'pgcache.engine' ) != 'file' && $this->_config->get_string( 'pgcache.engine' ) != 'file_generic' ): ?>
307
  <tr>
308
  <th><label for="pgcache_lifetime"><?php Util_Ui::e_config_label( 'pgcache.lifetime' ) ?></label></th>
309
  <td>
80
  <?php $this->checkbox( 'pgcache.reject.logged_roles' ) ?> <?php Util_Ui::e_config_label( 'pgcache.reject.logged_roles' ) ?></label><br />
81
  <span class="description"><?php _e( 'Select user roles that should not receive cached pages:', 'w3-total-cache' ); ?></span>
82
 
83
+ <div id="pgcache_reject_roles" class="w3tc_reject_roles">
84
  <?php $saved_roles = $this->_config->get_array( 'pgcache.reject.roles' ); ?>
85
  <input type="hidden" name="pgcache__reject__roles" value="" /><br />
86
  <?php foreach ( get_editable_roles() as $role_name => $role_data ) : ?>
183
  <?php $this->checkbox( 'pgcache.purge.home' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.home' ) ?></label><br />
184
  <?php $this->checkbox( 'pgcache.purge.post' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.post' ) ?></label><br />
185
  <?php $this->checkbox( 'pgcache.purge.feed.blog' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.feed.blog' ) ?></label><br />
186
+
187
  </th>
188
  <th>
189
  <?php $this->checkbox( 'pgcache.purge.comments' ) ?> <?php Util_Ui::e_config_label( 'pgcache.purge.comments' ) ?></label><br />
248
  <?php echo Util_Ui::button_config_save( 'pagecache_purge_policy' ); ?>
249
  <?php Util_Ui::postbox_footer(); ?>
250
 
251
+ <?php Util_Ui::postbox_header( __( '<acronym title="REpresentational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym>', 'w3-total-cache' ), '', 'rest' ); ?>
252
+ <table class="form-table">
253
+ <?php
254
+ Util_Ui::config_item( array(
255
+ 'key' => 'pgcache.rest',
256
+ 'label' => '<acronym title="REpresentational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym>',
257
+ 'control' => 'radiogroup',
258
+ 'radiogroup_values' => array(
259
+ '' => "Don't cache",
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">Upgrade</a> now to enable)')
265
+ ),
266
+ 'disable' => 'Disable <acronym title="REpresentational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym>',
267
+ ),
268
+ 'radiogroup_separator' => '<br />',
269
+ 'description' => __( 'Controls WordPress <acronym title="REpresentational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym> functionality.', 'w3-total-cache' )
270
+ ) );
271
+ ?>
272
+ </table>
273
+ <?php echo Util_Ui::button_config_save( 'rest' ); ?>
274
+ <?php Util_Ui::postbox_footer(); ?>
275
+
276
+
277
  <?php Util_Ui::postbox_header( __( 'Advanced', 'w3-total-cache' ), '', 'advanced' ); ?>
278
  <table class="form-table">
279
  <tr>
330
  </td>
331
  </tr>
332
  <?php endif; ?>
333
+ <?php if ( $this->_config->get_string( 'pgcache.engine' ) != 'file_generic' ): ?>
334
  <tr>
335
  <th><label for="pgcache_lifetime"><?php Util_Ui::e_config_label( 'pgcache.lifetime' ) ?></label></th>
336
  <td>
inc/widget/maxcdn.php DELETED
@@ -1,64 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- if ( !defined( 'W3TC' ) )
5
- die();
6
-
7
- /**
8
- *
9
- *
10
- * @var int $zone_id
11
- * @var array $summary
12
- * @var array $popular_files
13
- * @var string $content_zone
14
- * @var string $account_status
15
- */
16
-
17
- ?>
18
- <div id="maxcdn-widget" class="maxcdn-netdna-widget-base">
19
- <div class="wrapper">
20
- <div class="status area">
21
- <p>
22
- <span><?php echo sprintf( __( 'Status: %s', 'w3-total-cache' ), '<span class="account_status">' . $account_status. '</span>' ) ?></span>
23
- <span style="display:inline-block;float:right"><?php echo sprintf( __( 'Content Zone: %s', 'w3-total-cache' ), '<span class="content-zone">' . $content_zone . '</span>' ) ?></span>
24
- </p>
25
-
26
- </div>
27
- <div class="tools area">
28
- <ul>
29
- <li><a class="button" href="<?php echo "https://cp.maxcdn.com/zones/pull/{$zone_id}"?>"><?php _e( 'Manage', 'w3-total-cache' )?></a></li>
30
- <li><a class="button" href="<?php echo "https://cp.maxcdn.com/reporting/{$zone_id}"?>"><?php _e( 'Reports', 'w3-total-cache' )?></a></li>
31
- <li><a class="button" href="<?php echo wp_nonce_url( admin_url( 'admin.php?page=w3tc_cdn&amp;w3tc_cdn_purge' ) )?>" onclick="w3tc_popupadmin_bar(this.href); return false"><?php _e( 'Purge', 'w3-total-cache' )?></a></li>
32
- </ul>
33
- </div>
34
- <div class="summary area">
35
- <h4><?php _e( 'Report - 30 days', 'w3-total-cache' ) ?></h4>
36
- <ul>
37
- <li><?php echo sprintf( __( '<span>Transferred:</span> %s', 'w3-total-cache' ), Util_Ui::format_bytes( $summary['size'] ) ) ?></li>
38
- <li><?php echo sprintf( __( '<span>Cache Hits:</span> %d (%d%%)', 'w3-total-cache' ),
39
- $summary['cache_hit'], $summary['hit'] ? ( $summary['cache_hit']/$summary['hit'] )*100:$summary['hit'] ) ?></li>
40
- <li class="large"><?php echo sprintf( __( '<span>Cache Misses (non-cache hits):</span> %d (%d%%)', 'w3-total-cache' ),
41
- $summary['noncache_hit'], $summary['hit']?( $summary['noncache_hit']/$summary['hit'] )*100:$summary['hit'] ) ?></li>
42
- </ul>
43
- </div>
44
- <div class="charts area">
45
- <h4><?php _e( 'Requests', 'w3-total-cache' ) ?></h4>
46
- <div id="chart_div" style="width: 320px; height: 220px;margin-left: auto ; margin-right: auto ;"></div>
47
- <h4><?php _e( 'Content Breakdown', 'w3-total-cache' ) ?></h4>
48
- <p>
49
- <span><?php _e( 'File', 'w3-total-cache' )?></span>
50
- <span style="display:inline-block;float:right"><?php _e( 'Hits', 'w3-total-cache' ) ?></span>
51
- </p>
52
- <ul class="file_hits">
53
- <?php
54
- if ( $popular_files ) :
55
- $compare = $popular_files[0]['hit'];
56
- foreach ( $popular_files as $file ): ?>
57
- <li><span style="display:inline-block; background-color: <?php echo \NetDNAPresentation::get_file_group_color( $file['group'] )?>;width: <?php echo $file['hit']/$compare*100*0.9?>%; min-width:60%" title="<?php echo $file['title'] ?>"><?php echo '/', $file['group'], '/', $file['file']?></span> <span style="color:#000"><?php echo $file['hit']?></span></li>
58
- <?php endforeach;
59
- endif;
60
- ?>
61
- </ul>
62
- </div>
63
- </div>
64
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/widget/maxcdn_signup.php DELETED
@@ -1,22 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- if ( !defined( 'W3TC' ) )
5
- die();
6
-
7
- ?>
8
- <div id="maxcdn-widget" class="sign-up maxcdn-netdna-widget-base">
9
- <?php if ( $error ): ?>
10
- <?php Util_Ui::error_box( '<p>' . sprintf( __( 'MaxCDN encountered an error trying to retrieve data, make sure your host support cURL and outgoing requests: %s', 'w3-total-cache' ), $error ) . '</p>' ) ?>
11
- <?php endif; ?>
12
- <?php if ( !$authorized ): ?>
13
- <p><?php _e( 'Add the MaxCDN content delivery network to increase website speeds dramatically in just a few minutes!', 'w3-total-cache' )?></p>
14
- <h4><?php _e( 'New customers', 'w3-total-cache' )?></h4>
15
- <p><?php _e( 'MaxCDN is a service that lets you speed up your site even more with W3 Total Cache.', 'w3-total-cache' )?></p>
16
- <a class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_maxcdn_signup' ), 'w3tc' )?>" target="_blank"><?php _e( 'Sign Up Now and Save 25%', 'w3-total-cache' )?></a>
17
- <p><span class="desc"><?php _e( '100% Money Back Guarantee (30 Days)', 'w3-total-cache' )?></span></p>
18
- <?php endif ?>
19
- <h4><?php _e( 'Current customers', 'w3-total-cache' )?></h4>
20
- <p><?php _e( "Once you've signed up or if you're an existing MaxCDN customer, to enable CDN:", 'w3-total-cache' )?></p>
21
- <a class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_cdn' ), 'w3tc' )?>" target="_blank"><?php _e( 'Authorize', 'w3-total-cache' )?></a>
22
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ini/apache_conf/mod_deflate.conf ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ----------------------------------------------------------------------
2
+ # Gzip compression
3
+ # Compress content before it is delivered to the client
4
+ # http://httpd.apache.org/docs/2.0/mod/mod_deflate.html
5
+ # ----------------------------------------------------------------------
6
+
7
+ <ifmodule mod_deflate.c="">
8
+ # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
9
+ <ifmodule mod_setenvif.c="">
10
+ <ifmodule mod_headers.c="">
11
+ SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
12
+ RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
13
+ </ifmodule>
14
+ </ifmodule>
15
+
16
+ <ifmodule filter_module="">
17
+ # HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
18
+ FilterDeclare COMPRESS
19
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$text/html'"
20
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$text/css'"
21
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$text/plain'"
22
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$text/xml'"
23
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$text/x-component'"
24
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/javascript'"
25
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/json'"
26
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/xml'"
27
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/xhtml+xml'"
28
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/rss+xml'"
29
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/atom+xml'"
30
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/vnd.ms-fontobject'"
31
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$image/svg+xml'"
32
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$image/x-icon'"
33
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$application/x-font-ttf'"
34
+ FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} = '$font/opentype'"
35
+ FilterChain COMPRESS
36
+ FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
37
+ </ifmodule>
38
+
39
+ <ifmodule mod_filter.c="">
40
+ # Legacy versions of Apache
41
+ AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
42
+ AddOutputFilterByType DEFLATE application/javascript
43
+ AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
44
+ AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
45
+ AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
46
+ </ifmodule>
47
+
48
+ </ifmodule>
ini/apache_conf/mod_expires.conf ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ----------------------------------------------------------------------
2
+ # Cache Control via HTTP Headers + Expires
3
+ # Generation of Expires and Cache-Control HTTP headers according to user-specified criteria
4
+ # http://httpd.apache.org/docs/2.0/mod/mod_headers.html
5
+ # ----------------------------------------------------------------------
6
+
7
+ # Expires Defaults
8
+ <ifmodule mod_expires.c="">
9
+ ExpiresActive On
10
+ # Set default expires to 2 days
11
+ ExpiresDefault A172800
12
+ ExpiresByType text/css A31536000
13
+ ExpiresByType application/x-javascript A31536000
14
+ ExpiresByType text/x-component A31536000
15
+ ExpiresByType text/html A3600
16
+ ExpiresByType text/richtext A3600
17
+ ExpiresByType image/svg+xml A3600
18
+ ExpiresByType text/plain A3600
19
+ ExpiresByType text/xsd A3600
20
+ ExpiresByType text/xsl A3600
21
+ ExpiresByType text/xml A3600
22
+ ExpiresByType video/asf A31536000
23
+ ExpiresByType video/avi A31536000
24
+ ExpiresByType image/bmp A31536000
25
+ ExpiresByType application/java A31536000
26
+ ExpiresByType video/divx A31536000
27
+ ExpiresByType application/msword A31536000
28
+ ExpiresByType application/vnd.ms-fontobject A31536000
29
+ ExpiresByType application/x-msdownload A31536000
30
+ ExpiresByType image/gif A31536000
31
+ ExpiresByType application/x-gzip A31536000
32
+ ExpiresByType image/x-icon A31536000
33
+ ExpiresByType image/jpeg A31536000
34
+ ExpiresByType application/vnd.ms-access A31536000
35
+ ExpiresByType audio/midi A31536000
36
+ ExpiresByType video/quicktime A31536000
37
+ ExpiresByType audio/mpeg A31536000
38
+ ExpiresByType video/mp4 A31536000
39
+ ExpiresByType video/mpeg A31536000
40
+ ExpiresByType application/vnd.ms-project A31536000
41
+ ExpiresByType application/x-font-otf A31536000
42
+ ExpiresByType application/vnd.oasis.opendocument.database A31536000
43
+ ExpiresByType application/vnd.oasis.opendocument.chart A31536000
44
+ ExpiresByType application/vnd.oasis.opendocument.formula A31536000
45
+ ExpiresByType application/vnd.oasis.opendocument.graphics A31536000
46
+ ExpiresByType application/vnd.oasis.opendocument.presentation A31536000
47
+ ExpiresByType application/vnd.oasis.opendocument.spreadsheet A31536000
48
+ ExpiresByType application/vnd.oasis.opendocument.text A31536000
49
+ ExpiresByType audio/ogg A31536000
50
+ ExpiresByType application/pdf A31536000
51
+ ExpiresByType image/png A31536000
52
+ ExpiresByType application/vnd.ms-powerpoint A31536000
53
+ ExpiresByType audio/x-realaudio A31536000
54
+ ExpiresByType image/svg+xml A31536000
55
+ ExpiresByType application/x-shockwave-flash A31536000
56
+ ExpiresByType application/x-tar A31536000
57
+ ExpiresByType image/tiff A31536000
58
+ ExpiresByType application/x-font-ttf A31536000
59
+ ExpiresByType audio/wav A31536000
60
+ ExpiresByType audio/wma A31536000
61
+ ExpiresByType application/vnd.ms-write A31536000
62
+ ExpiresByType application/vnd.ms-excel A31536000
63
+ ExpiresByType application/zip A31536000
64
+ </ifmodule>
65
+
66
+ # No caching for dynamic files
67
+ <filesmatch>
68
+ ExpiresDefault A0
69
+ Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
70
+ Header set Pragma "no-cache"
71
+ </filesmatch>
72
+
73
+ # 1 MIN
74
+ <filesmatch>
75
+ ExpiresDefault A60
76
+ Header set Cache-Control "max-age=60, must-revalidate"
77
+ </filesmatch>
78
+
79
+ # 2 DAYS
80
+ <filesmatch>
81
+ ExpiresDefault A172800
82
+ Header set Cache-Control "max-age=172800, must-revalidate"
83
+ </filesmatch>
84
+
85
+ # 1 WEEK
86
+ <filesmatch>
87
+ ExpiresDefault A604800
88
+ Header set Cache-Control "max-age=604800, must-revalidate"
89
+ </filesmatch>
90
+
91
+ # 1 MONTH
92
+ <filesmatch>
93
+ ExpiresDefault A2419200
94
+ Header set Cache-Control "max-age=2419200, must-revalidate"
95
+ </filesmatch>
ini/apache_conf/mod_mime.conf ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ----------------------------------------------------------------------
2
+ # Mime Types
3
+ # Mime Associates the requested filename's extensions with the file's behavior and content
4
+ # http://httpd.apache.org/docs/2.0/mod/mod_mime.html
5
+ # ----------------------------------------------------------------------
6
+
7
+ <ifmodule mod_mime.c="">
8
+ AddType text/css .css
9
+ AddType application/x-javascript .js
10
+ AddType text/x-component .htc
11
+ AddType text/html .html .htm
12
+ AddType text/richtext .rtf .rtx
13
+ AddType image/svg+xml .svg .svgz
14
+ AddType text/plain .txt
15
+ AddType text/xsd .xsd
16
+ AddType text/xsl .xsl
17
+ AddType text/xml .xml
18
+ AddType video/asf .asf .asx .wax .wmv .wmx
19
+ AddType video/avi .avi
20
+ AddType image/bmp .bmp
21
+ AddType application/java .class
22
+ AddType video/divx .divx
23
+ AddType application/msword .doc .docx
24
+ AddType application/vnd.ms-fontobject .eot
25
+ AddType application/x-msdownload .exe
26
+ AddType image/gif .gif
27
+ AddType application/x-gzip .gz .gzip
28
+ AddType image/x-icon .ico
29
+ AddType image/jpeg .jpg .jpeg .jpe
30
+ AddType application/vnd.ms-access .mdb
31
+ AddType audio/midi .mid .midi
32
+ AddType video/quicktime .mov .qt
33
+ AddType audio/mpeg .mp3 .m4a
34
+ AddType video/mp4 .mp4 .m4v
35
+ AddType video/mpeg .mpeg .mpg .mpe
36
+ AddType application/vnd.ms-project .mpp
37
+ AddType application/x-font-otf .otf
38
+ AddType application/vnd.oasis.opendocument.database .odb
39
+ AddType application/vnd.oasis.opendocument.chart .odc
40
+ AddType application/vnd.oasis.opendocument.formula .odf
41
+ AddType application/vnd.oasis.opendocument.graphics .odg
42
+ AddType application/vnd.oasis.opendocument.presentation .odp
43
+ AddType application/vnd.oasis.opendocument.spreadsheet .ods
44
+ AddType application/vnd.oasis.opendocument.text .odt
45
+ AddType audio/ogg .ogg
46
+ AddType application/pdf .pdf
47
+ AddType image/png .png
48
+ AddType application/vnd.ms-powerpoint .pot .pps .ppt .pptx
49
+ AddType audio/x-realaudio .ra .ram
50
+ AddType application/x-shockwave-flash .swf
51
+ AddType application/x-tar .tar
52
+ AddType image/tiff .tif .tiff
53
+ AddType application/x-font-ttf .ttf .ttc
54
+ AddType audio/wav .wav
55
+ AddType audio/wma .wma
56
+ AddType application/vnd.ms-write .wri
57
+ AddType application/vnd.ms-excel .xla .xls .xlsx .xlt .xlw
58
+ AddType application/zip .zip
59
+ </ifmodule>
ini/apache_conf/mod_rewrite.conf ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ----------------------------------------------------------------------
2
+ # Start rewrite engine
3
+ # Provides a rule-based rewriting engine to rewrite requested URLs on the fly
4
+ # http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
5
+ # ----------------------------------------------------------------------
6
+
7
+ # FollowSymLinks must be enabled for this to work
8
+ <ifmodule mod_rewrite.c="">
9
+ Options +FollowSymlinks
10
+ RewriteEngine On
11
+ </ifmodule>
12
+
13
+ # Block access to "hidden" directories whose names begin with a period
14
+ <ifmodule mod_rewrite.c="">
15
+ RewriteCond %{SCRIPT_FILENAME} -d
16
+ RewriteCond %{SCRIPT_FILENAME} -f
17
+ RewriteRule "(^|/)\." - [F]
18
+ </ifmodule>
languages/faq-en_US.xml DELETED
@@ -1,826 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <faqs>
3
- <section name="General">
4
- <entry>
5
- <question><![CDATA[ Who is this plugin for? ]]></question>
6
- <answer><![CDATA[ <p>Anyone that wants to provide an optimal user experience to their readers.</p> ]]></answer>
7
- </entry>
8
- <entry>
9
- <question><![CDATA[ Umm, why? ]]></question>
10
- <answer><![CDATA[
11
- <p>We needed an elegant remedy to common performance issues we spent countless hours addressing on various blogs we work with. They all suffered from similar issues and we found that same remedies would sort all of them. Issues like <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transaction reduction, object size reduction and blocking objects are performance killers and have been remedied with this plugin. Rather than release our various plugins individually (and support them independently) we saw an opportunity to demonstrate how all of this functionality is intertwined and combines to realize far more than the sum of its parts.</p>
12
- <p>One of the WordPress community's strengths is also its weakness; we found that numerous plugins are very handy and save some development time in a pinch, but the maintenance and performance penalties blogs suffer from as a result contribute to a poor user experience, which is never acceptable.</p>
13
- <p>Experience has shown that fast loading web sites have (at least) the following characteristics:</p>
14
- <ul>
15
- <li>Reduced <a href="http://en.wikipedia.org/wiki/Customer_attrition" target="_blank">attrition</a></li>
16
- <li>Higher conversion rates for e-commerce / affiliate etc sites</li>
17
- <li>Increased time on site / more page views per visitor</li>
18
- </ul>
19
- <p><em>In fact, if wordpress.com (for example) applied some of the techniques used in this plugin, we imagine they'd realize ~10% performance improvement on the <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> and <acronym title="Hypertext Markup Language">HTML</acronym> (respectively) on the millions of blogs they host.</em></p>
20
- <p>As a practical matter, Akamai and JupiterResearch did a study on <a href="http://www.akamai.com/html/about/press/releases/2006/press_110606.html" target="_blank">acceptable wait time for retail web sites</a> to load back in late 2006 concluding that users may leave after 4 seconds of waiting. That was several years ago now, even before 3G was available for mobile devices, what do you think web users expect today? <a href="http://blogs.zdnet.com/BTL/?p=3925" target="_blank">According to Marissa Mayer</a> of Google, as she stated the same year as Akamai, improving the speed of sites/applications reduces the learning curve for applications and contributes to higher use. It's time to bring the performance major corporations enjoy to the blogosphere.</p>
21
- <p>As an aside, don't you think your site's <acronym title="Key Performance Indicators">KPI</acronym> would be more meaningful if you could be confident that all users were having the exact same performance experience with your site? It's too early to say for sure, but we feel that the statistics and metrics we all use to track our progress and results will be more realistic when W3 Total Cache is actively removing bottlenecks from our blogs.</p>
22
- <p><a href="mailto:wordpressexperts@w3-edge.com">Please let us know</a> what kind of mileage you have.</p>
23
- ]]></answer>
24
- </entry>
25
- <entry>
26
- <question><![CDATA[ So give me the skinny, what are the highlights? ]]></question>
27
- <answer><![CDATA[
28
- <p>W3 Total Cache is a suite of functionality designed to optimize the performance of all WordPress blogs. Features and benefits include:</p>
29
- <ul>
30
- <li>Improved progressive render (non-blocking <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> embedding)</li>
31
- <li>Reduced <acronym title="Hypertext Transfer Protocol">HTTP</acronym> Transactions, <acronym title="Domain Name System">DNS</acronym> lookups, reduced document load time</li>
32
- <li>Transparent content delivery network (<acronym title="Content Delivery Network">CDN</acronym>) support with automated media library import</li>
33
- <li>Bandwidth savings via <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym>) for <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym></li>
34
- <li>Minification (concatenation, white space removal) of inline, external or 3rd party <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> with scheduled updates</li>
35
- <li>Optional embedding of <acronym title="JavaScript">JS</acronym> just above &lt;/body&gt;</li>
36
- <li>Support for caching pages, posts, feeds, database objects, <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> in memory with an opcode cache or memcached or both</li>
37
- <li>Caching of feeds (comments, page and site), <acronym title="Uniform Resource Indicator">URL</acronym>s with query string variables (like search result pages), Database queries, Pages, Posts, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym></li>
38
- <li>Complete header management including ETags</li>
39
- <li>Increased web server concurrency and reduced resource consumption, increased scale</li>
40
- </ul>
41
- <p>In essence, anything that can be automated to squeeze out every bit of server performance and minimize bandwidth utilization has been done, leaving your readers with an optimized user experience.</p> ]]></answer>
42
- </entry>
43
- <entry>
44
- <question><![CDATA[ I don't have time to deal with this, but I know I need it. Will you help me? ]]></question>
45
- <answer><![CDATA[ <p>Yes! Please <a href="mailto:wordpressexperts@w3-edge.com">reach out to us</a> and we'll get you acclimated so you can "set it and forget it."</p> ]]></answer>
46
- </entry>
47
- <entry>
48
- <question><![CDATA[ I've never heard of any of this stuff; my blog is fine, no one complains about the speed. Why should I install this? ]]></question>
49
- <answer><![CDATA[ <p>Rarely do readers take the time to complain. They typically just stop browsing earlier than you'd prefer and may not return altogether. It's in every web site owner's best interest is to make sure that the performance of your blog is not hindering its success.</p> ]]></answer>
50
- </entry>
51
- <entry>
52
- <question><![CDATA[ But even Matt Mullenweg doesn't agree that additional caching is so important, why bother? ]]></question>
53
- <answer><![CDATA[ <p>You're right, <a href="http://ma.tt/2008/03/wordpress-is-open-source/#comment-439787" target="_blank">Matt did say that</a>. However, this plugin provides more than just "caching". Because he is correct, the web is dynamic and must remain so. But as we explain throughout this FAQ, our goal is to improve the performance of any blog. Furthermore, some techniques we use are well documented from past <a href="http://www.slideshare.net/bazza/high-performance-wordpress" target="_blank">WordCamp presentations</a>; we combined them in a way that we have found stands up to the highest traffic spikes.</p> ]]></answer>
54
- </entry>
55
- <entry>
56
- <question><![CDATA[ And how many years of university do I need to use this thing? ]]></question>
57
- <answer><![CDATA[ <p>-4 &mdash; That's right; a youngster in junior high school can get started with this plugin. Seriously, if you did your own WordPress install or have ever installed a plugin before you're in good shape. If you need help, <a href="mailto:wordpressexperts@w3-edge.com">let us know</a> or perhaps we'll make some videos or the like.</p> ]]></answer>
58
- </entry>
59
- <entry>
60
- <question><![CDATA[ Ok, so the benefits are clear. What exactly is so special about *how* this plugin works? ]]></question>
61
- <answer><![CDATA[ <p>Thanks for asking. We just decided not try to use the typical WordPress hooks and methodologies to implement our features, instead we take the normal output and perform optimizations to it before we send it to the user agent using a method they support and then cache the result afterwards. This concept is applied to objects you decide to cache.</p> ]]></answer>
62
- </entry>
63
- <entry>
64
- <question><![CDATA[ So let me get this straight; you're telling me this plugin is designed to improve performance of any WordPress blog? ]]></question>
65
- <answer><![CDATA[ <p>Precisely, that is unless you don't write any posts in your blog nor have any readers. If you're someone that's always into the latest web development technique or plugin, now you can "have it all" without making your readers suffer.</p> ]]></answer>
66
- </entry>
67
- <entry>
68
- <question><![CDATA[ This is too good to be true, how can I test the results? ]]></question>
69
- <answer><![CDATA[
70
- <p>You will be able to see it instantly on each page load, but for tangible metrics, consider the following tools:</p>
71
- <ul>
72
- <li><a href="https://developers.google.com/speed/pagespeed/" target="_blank">Google Page Speed</a></li>
73
- <li><a href="https://www.webpagetest.org/test" target="_blank">WebPagetest</a></li>
74
- <li><a href="https://tools.pingdom.com/" target="_blank">Pingdom</a></li>
75
- <li><a href="https://www.dynatrace.com/en_us/application-performance-management/products/performance-center.html" target="_blank">DynaTrace (formerly Gomez) Performance Test</a></li>
76
- </ul>
77
- ]]></answer>
78
- </entry>
79
- <entry>
80
- <question><![CDATA[ I understand the database caching and the page caching, but what's minify all about? ]]></question>
81
- <answer><![CDATA[
82
- <p>We'll just quote the fine folks at yahoo on this one:</p>
83
- <blockquote>
84
- <p>"Minification is the practice of removing unnecessary characters from code to reduce its size thereby improving load times. When code is minified all comments are removed, as well as unneeded white space characters (space, newline, and tab). In the case of JavaScript, this improves response time performance because the size of the downloaded file is reduced. Two popular tools for minifying JavaScript code are <a href="http://www.crockford.com/javascript/jsmin.html" target="_blank"><acronym title="JavaScript">JS</acronym>Min</a> and <a href="http://developer.yahoo.com/yui/compressor/" target="_blank"><acronym title="Yahoo! User Interface">YUI</acronym> Compressor</a>. The <acronym title="Yahoo! User Interface">YUI</acronym> compressor can also minify <acronym title="Cascading Style Sheet">CSS</acronym>.</p>
85
- <p>Obfuscation is an alternative optimization that can be applied to source code. It's more complex than minification and thus more likely to generate bugs as a result of the obfuscation step itself. In a survey of ten top U.S. web sites, minification achieved a 21% size reduction versus 25% for obfuscation. Although obfuscation has a higher size reduction, minifying JavaScript is less risky.</p>
86
- <p>In addition to minifying external scripts and styles, inline &lt;script&gt; and &lt;style&gt; blocks can and should also be minified. Even if you <acronym title="GNU zip">gzip</acronym> your scripts and styles, minifying them will still reduce the size by 5% or more. As the use and size of JavaScript and <acronym title="Cascading Style Sheet">CSS</acronym> increases so will the savings gained by minifying your code."</p>
87
- <cite><a href="http://developer.yahoo.com/performance/rules.html#minify" target="_blank">developer.yahoo.com</a></cite>
88
- </blockquote>
89
- ]]></answer>
90
- </entry>
91
- <entry>
92
- <question><![CDATA[ What do you use to minify? ]]></question>
93
- <answer><![CDATA[ <p> We use: <a href="http://code.google.com/p/minify/" target="_blank">minify</a> but may support various engines in the future. Based on <a href="http://ejohn.org/" target="_blank">John Resig's</a> suggestion we're currently looking at <a href="http://yuilibrary.com/projects/yuicompressor/wiki" target="_blank"><acronym title="Yahoo! User Interface">YUI</acronym> Compressor</a> and <a href="http://code.google.com/closure/compiler/" target="_blank">Google Closure Compiler</a> (for JavaScript) also.</p> ]]></answer>
94
- </entry>
95
- <entry>
96
- <question><![CDATA[ Will this speed up <acronym title="WordPress">WP</acronym> Admin? ]]></question>
97
- <answer><![CDATA[ <p>Yes, indirectly &mdash; if you have a lot of bloggers working with you, you will find that it feels like you have a server dedicated only to <acronym title="WordPress">WP</acronym> Admin once this plugin is enabled; the result, increased productivity.</p> ]]></answer>
98
- </entry>
99
- <entry>
100
- <question><![CDATA[ Does this plugin modify how the WordPress core works? ]]></question>
101
- <answer><![CDATA[ <p>No. No theme changes, special files, WordPress core file modifications or special permissions need to be set.</p> ]]></answer>
102
- </entry>
103
- <entry>
104
- <question><![CDATA[ Seriously, tell me what the downside is, there must be something? ]]></question>
105
- <answer><![CDATA[ <p>Well, no there isn't. Installing the server side software might be challenging for some, but <a href="mailto:wordpressexperts@w3-edge.com">we can assist</a> with that if you ask. Other than that, unless you enjoy frequently upgrading your server plan or buying more servers and paying for bandwidth overages or wincing every time you add another "must have" plugin to your blog, we cannot find any reason to deter you from the use of this one.</p> ]]></answer>
106
- </entry>
107
- <entry>
108
- <question><![CDATA[ If this plugin does everything you claim, why would you give it away free? Cui Bono? ]]></question>
109
- <answer><![CDATA[
110
- <p>Who benefits? Everyone. Of the numerous, here are the three the most important reasons we share with the WordPress community:</p>
111
- <ul>
112
- <li>WordPress is free and high quality, plugins should be too.</li>
113
- <li>There's no reason your blog shouldn't be able to perform as well as well as any major corporation's web site/application.</li>
114
- <li><a href="http://code.google.com/speed/articles/" target="_blank">Google</a> and <a href="http://developer.yahoo.com/yui/" target="_blank">Yahoo</a> offer quite a bit, but they did not offer a WordPress solution yet. This is our contribution to speeding up the web (starting with the blogosphere).</li>
115
- </ul>
116
- ]]></answer>
117
- </entry>
118
- <entry>
119
- <question><![CDATA[ We run many blogs on many servers here at my company, is this plugin still for me? ]]></question>
120
- <answer><![CDATA[ <p> Yes, especially if you have a cluster and many WordPress installations or a WordPress <acronym title="Multi-User">MU</acronym> installation, then plugin is for you. It will allow you to move easily from multiple installations to WordPress <acronym title="Multi-User">MU</acronym> and continue to use multiple <acronym title="Hypertext Transfer Protocol">HTTP</acronym>, Database, Network Attached Storage etc servers in any configuration you wish. You can also specify as many memcached servers as you wish, although you cannot yet delegate a memcached server to a specific type of caching, i.e. there's no pool management yet.</p> ]]></answer>
121
- </entry>
122
- <entry>
123
- <question><![CDATA[ So you appear to know what you're talking about, will there be any negative effect on my SEO rankings? ]]></question>
124
- <answer><![CDATA[
125
- <p>To answer, first we must assume that you're using all of the options we offer: <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression, minify etc. Having said that, we are only sending compressed data to user agents that support it; even <a href="http://www.google.com/search?q=search+engine+crawler+http+compression" target="_blank">most search engine crawlers do</a>. As for minified <acronym title="Hypertext Markup Language">HTML</acronym>, this is essentially how crawlers see your page anyway when they download it. So no, there's no penalty or compromise.</p>
126
- <p>Fact of the matter, there was a time when the semantics and size of your <acronym title="Hypertext Markup Language">HTML</acronym> file (code-to-content ratio), was a factor in a more favorable ranking. <a href="http://microformats.org/wiki/posh" target="_blank"><acronym title="Plain Old Semantic HTML">POSH</acronym></a> <acronym title="Hypertext Markup Language">HTML</acronym> has always been preferred by search engines. In some markets this may still be true, so give the search engines what they want.</p>
127
- ]]></answer>
128
- </entry>
129
- <entry>
130
- <question><![CDATA[ What about my robots.txt, sitemap.xml and all my site verification files etc, what happens with those? ]]></question>
131
- <answer><![CDATA[ <p>If you're concerned about what happens with these when the <acronym title="Content Delivery Network">CDN</acronym> functionality is active, nothing does. You do not want or need these files moved from their original locations and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (or minification for that matter) is of no consequence in most cases.</p> ]]></answer>
132
- </entry>
133
- <entry>
134
- <question><![CDATA[ Do you have any tricks for "post-loading", "lazy-loading" and other render optimizations in this plugin? ]]></question>
135
- <answer><![CDATA[ <p>Yes we do, we're currently evaluating if they are best introduced into this plugin or as standalones. Feel free to <a href="mailto:wordpressexperts@w3-edge.com">chime in</a>.</p> ]]></answer>
136
- </entry>
137
- <entry>
138
- <question><![CDATA[ I want to obfuscate my <acronym title="JavaScript">JS</acronym>, does the plugin do that? Will it ever? ]]></question>
139
- <answer><![CDATA[ <p>No the plugin will not do that and it's unlikely that we'll support that.</p> ]]></answer>
140
- </entry>
141
- <entry>
142
- <question><![CDATA[ I have some ideas for more features, can I write my own add-ons for your plugin? ]]></question>
143
- <answer><![CDATA[ <p>Not yet, we are considering support for add-ons. Meanwhile, please <a href="mailto:wordpressexperts@w3-edge.com">reach out to us</a> and let us know what you think would benefit the community.</p> ]]></answer>
144
- </entry>
145
- <entry>
146
- <question><![CDATA[ Who do I thank for all of this? ]]></question>
147
- <answer><![CDATA[
148
- <p>It's quite difficult to recall all of the innovators that have shared their thoughts, code and experiences in the blogosphere over the years, but here are some names to get you started:</p>
149
- <ul>
150
- <li><a href="http://stevesouders.com/" target="_blank">Steve Souders</a></li>
151
- <li><a href="http://mrclay.org/" target="_blank">Steve Clay</a></li>
152
- <li><a href="http://wonko.com/" target="_blank">Ryan Grove</a></li>
153
- <li><a href="http://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/" target="_blank">Nicholas Zakas</a> </li>
154
- <li><a href="http://rtdean.livejournal.com/" target="_blank">Ryan Dean</a></li>
155
- <li><a href="http://gravitonic.com/" target="_blank">Andrei Zmievski</a></li>
156
- <li>George Schlossnagle</li>
157
- <li>Daniel Cowgill</li>
158
- <li><a href="http://toys.lerdorf.com/" target="_blank">Rasmus Lerdorf</a></li>
159
- <li><a href="http://notmysock.org/" target="_blank">Gopal Vijayaraghavan</a></li>
160
- <li><a href="http://eaccelerator.net/" target="_blank">Bart Vanbraban</a></li>
161
- <li><a href="http://xcache.lighttpd.net/" target="_blank">mOo</a></li>
162
- </ul>
163
- <p>Please reach out to all of these people and support their projects if you're so inclined.</p> ]]></answer>
164
- </entry>
165
- </section>
166
- <section name="Usage">
167
- <entry>
168
- <question><![CDATA[ In the past, I always had to modify my theme to run dynamic code. Don't I need to do that again for this plugin? ]]></question>
169
- <answer><![CDATA[ <p>For now no; there are some special cases that we will address with an upcoming release for highly dynamic sites.</p> ]]></answer>
170
- </entry>
171
- <entry>
172
- <question><![CDATA[ How can I tell if it's working? Aren't there any statistics at all? ]]></question>
173
- <answer><![CDATA[ <p>Well yes actually there are, simply enable debug mode on the "General" tab to have details appended to the bottom of your <acronym title="Hypertext Markup Language">HTML</acronym> source. Remember that when enabled all visitors to your blog can see these statistics if they view source. Using debug mode does slow the performance of your site so use sparingly.</p> ]]></answer>
174
- </entry>
175
- <entry>
176
- <question><![CDATA[ I'm not a hardcore developer, can you explain to me how this // and / stuff works and how I should specify the paths for <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files? ]]></question>
177
- <answer><![CDATA[
178
- <p>You mean on the minify settings page right? Ok, it's simple:<br />
179
- // tells the plugin to search for the file with the provided path from the document root, e.g.: ///JS/jquery/jquery.<acronym title="JavaScript">JS</acronym><br />
180
- / tells the plugin to search for the file with the provided path from the server root, e.g. //JS/jquery/jquery.<acronym title="JavaScript">JS</acronym></p>
181
- <p>In most cases providing an absolute path is sufficient and most reliable. You can of course use relative paths, but we discourage it unless you really know what you are doing.</p>
182
- ]]></answer>
183
- </entry>
184
- <entry>
185
- <question><![CDATA[ Which features can I use if I haven't yet installed an opcode cache or memcached? ]]></question>
186
- <answer><![CDATA[ <p>Memory caching will not be possible. However you will be able to use both the page cache and minify in "disk" mode, as well <acronym title="Content Delivery Network">CDN</acronym> functionality without issue.</p> ]]></answer>
187
- </entry>
188
- <entry>
189
- <question><![CDATA[ Which textareas for file entries support regular expressions? ]]></question>
190
- <answer><![CDATA[
191
- <ul>
192
- <li>Page Cache: Never cache the following pages, Cache exception list, Non-trailing slash pages</li>
193
- <li>Database Cache: Never cache the following pages</li>
194
- <li><acronym title="Content Delivery Network">CDN</acronym>: Custom file list, Rejected files <br />The <acronym title="Content Delivery Network">CDN</acronym> fields only support regular expression on the filename.</li>
195
- </ul>
196
- <p>Examples (Never cache the following pages):</p>
197
- <ul>
198
- <li>Do not cache page/directory and sub pages
199
- /directory*</li>
200
- <li>Do not cache pages under a directory
201
- /directory/.+</li>
202
- <li>Do not cache pages that contain specific text<br />
203
- /.*text.*</li>
204
- <li>Do not cache pages that is named child in directories<br />
205
- .+/child</li>
206
- <li>Do not cache any pages named child<br />
207
- */child</li>
208
- </ul>
209
- <p>
210
- Note: To disable page caching of specific theme templates or plugin files you need to add define('DONOTCACHEPAGE', true); to it.</p>
211
- </p>
212
- ]]></answer>
213
- </entry>
214
- <entry>
215
- <question><![CDATA[ How fast will the cache be updated? ]]></question>
216
- <answer><![CDATA[ <p>Items expire from the cache at a rate that you specify. As far as how fast changes appear to your visitors, they appear instantly in most cases and if you're an administrator who's logged in they will always be immediately visible.</p> ]]></answer>
217
- </entry>
218
- <entry>
219
- <question><![CDATA[ My server has state of the art file storage, why do I need to cache anything in memory? ]]></question>
220
- <answer><![CDATA[ <p>Even if your server was using an array of solid state disks (SSD), your server's <acronym title="Random Access Memory">RAM</acronym> is still going to be faster and introduce less overhead to access than even the fastest solid state drives on a PCIe bus. If you didn't invest in solid state disks for your server, then even worse off - at least an order of magnitude speed difference in read operations in <acronym title="Random Access Memory">RAM</acronym> versus HDD. For write operations delta the latency differences is even more pronounced. <acronym title="Random Access Memory">RAM</acronym> is the winner hands down. We won't even discuss the blocking and arbitration issues that happen with disk arrays under certain circumstances.</p> ]]></answer>
221
- </entry>
222
- <entry>
223
- <question><![CDATA[ Why would I choose opcode caching over memcached or vice versa? ]]></question>
224
- <answer><![CDATA[
225
- <p>There's no straight answer for this one. Since WordPress is a PHP-based application, we encourage everyone to install an opcode cache and realize a minimum of 10x performance gain. It will obviously make our plugin faster as well, so again please check out the installation instructions if you do not already use an opcode cache. Once installed, you can select an opcode cache as the method and get back to blogging.</p>
226
- <p>Opcode caching does have a couple weaknesses:</p>
227
- <ul>
228
- <li>If you frequently restart your web server (e.g. apache) especially during high traffic periods, you will lose your cache and your site will slow down as it rebuilds the cache (which happens very quickly). However if you use memcached you would not lose your cache if your web server is restarted.</li>
229
- <li>More importantly, opcode caching is best suited for single server environments because the cache is only accessible to the local server, it cannot be shared with other servers in a multi-server (cluster) environment.</li>
230
- </ul>
231
- <p>It would appear that using <acronym title="Alternative PHP Cache">APC</acronym> database caching may be best, but your mileage may vary. So depending on what software you install and how you manage your server, you can choose the options to fit your needs. If you need help with the install on your dedicated or virtual dedicated linux-based server ask us!</p>
232
- ]]></answer>
233
- </entry>
234
- <entry>
235
- <question><![CDATA[ I already use <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression on my server, why does it matter if I minify my code? ]]></question>
236
- <answer><![CDATA[ <p>Let's say you had a file of 10240 bytes, which becomes 2048 bytes when compressed, savings of ~80% (typical for <acronym title="Cascading Style Sheet">CSS</acronym> files). That same file will now have an <strong>additional</strong> ~3x-10x transfer speed improvement when minified. That's a big return from a small operation. The larger your files, the more significant the proportional performance gains.</p> ]]></answer>
237
- </entry>
238
- <entry>
239
- <question><![CDATA[ How do I make some specific pages stay dynamic? ]]></question>
240
- <answer><![CDATA[ <p>They never stop being dynamic, we just don't create pages that have not been changed. If you have a page that updated frequently in your blog before, it will still remain up-to-date at all times.</p> ]]></answer>
241
- </entry>
242
- <entry>
243
- <question><![CDATA[ Why would I want to cache my feeds? ]]></question>
244
- <answer><![CDATA[ <p>We feel that caching objects after the first request and checking for updates before responding subsequent requests (which is kind of how web browsers work too) creates more opportunities for interesting applications and mashups where the blogosphere doesn't require institutional investment to be able to handle developers making hundreds of requests every day the same way we use Google, Twitter and Facebook (for example) <acronym title="Application Programming Interface">API</acronym>s today. Think about it, even when major search engines crawl your site, they have to be "gentle" so they don't bring it down, let's turn the paradigm around so that every blog can deliver content in real-time in various formats.</p> ]]></answer>
245
- </entry>
246
- <entry>
247
- <question><![CDATA[ How do I cache only the home page? ]]></question>
248
- <answer><![CDATA[ <p>Add "/.+" (without the quotes) to page cache "Never cache the following pages" option on the page cache settings tab.</p> ]]></answer>
249
- </entry>
250
- <entry>
251
- <question><![CDATA[ Sitemaps are not being cached. How do I resolve this? ]]></question>
252
- <answer><![CDATA[ <p>Enable "Cache feeds: site, categories, tags, comments" on the "Page Cache" settings tab. Some sitemap implementations are considered by WordPress to be "feeds."</p> ]]></answer>
253
- </entry>
254
- <entry>
255
- <question><![CDATA[ Is it possible to store plugin configuration in a database instead of file? ]]></question>
256
- <answer><![CDATA[ <p>Yes, but you should note that many types of requests can be made prior to the initialization of the database, so switching to database-stored configuration will increase request response time. This functionality should be used only when you have no other option. To enable database-stored setting, add define( 'W3TC_CONFIG_DATABASE', true ); to your wp-config.php and the plugin will immediately begin to use options table for configuration storage via wp-options table. Alternatively, W3TC_CONFIG_DATABASE_TABLE constant can be defined to specify a table you created specifically for this use case.</p><p>Note: If you customized your settings prior to switching to the database storage setting, you will lose your configuration settings. Be sure to export settings beforehand, then import afterward. You can then remove configuration file from your source control if it was there and delete it. Ideally, defining the W3TC_CONFIG_DATABASE constant prior plugin activation allows you to skip all of these steps.</p> ]]></answer>
257
-
258
- </entry>
259
- </section>
260
- <section name="Minification">
261
- <entry>
262
- <question><![CDATA[ How do I find the <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> to optimize (manually minify) them with this plugin? ]]></question>
263
- <answer><![CDATA[
264
- <p>View your page source in your browser and search for any &lt;style&gt;, &lt;link&gt; or &lt;script&gt; tags that contain external <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> files and one by one add them to the minify settings page. Do not include any <acronym title="Cascading Style Sheet">CSS</acronym> in conditional statements (unless you know what you are doing) like:</p>
265
- <p>&lt;!--[if lte IE 8]&gt;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;/wp-content/themes/default/lte.css&quot; media=&quot;screen,projection&quot; /&gt;&lt;![endif]--&gt; Or simply use the "Help" tool available on the minify settings page which will identify <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files used in the templates of your theme and properly assign them to the same. Simply tick the checkbox for files you wish to minify, click "Apply &amp; close", then save your settings.</p>
266
- <p>The plugin will combine, minify, <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compress and check for updates to these files automatically from now on. If you have any <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> that are inline consider making them external files so that you can use them with minify.</p>
267
- ]]></answer>
268
- </entry>
269
- <entry>
270
- <question><![CDATA[ I've used the plugin to optimize all my theme's <acronym title="JavaScript">JS</acronym> and plugins <acronym title="JavaScript">JS</acronym>, but there are some function calls, where do those go? ]]></question>
271
- <answer><![CDATA[ <p>Just place them above &lt;/head&gt; if that's where your embed is done or above &lt;/body&gt; if that's where you need them. Wherever they need to be to be called after the <acronym title="JavaScript">JS</acronym> that needs them, it'll be fine.</p> ]]></answer>
272
- </entry>
273
- <entry>
274
- <question><![CDATA[ Can I use scripts that generate <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> with this plugin?]]></question>
275
- <answer><![CDATA[ <p>Yes you can, but since there are numerous ways to do so, so be sure to test your results carefully. Having said that we do encourage it as it will mean that less processing has to be done to deliver your pages.</p> ]]></answer>
276
- </entry>
277
- <entry>
278
- <question><![CDATA[ Why would I want to put my <acronym title="JavaScript">JS</acronym> at the bottom of the page? ]]></question>
279
- <answer><![CDATA[ <p>First let me point out that in many cases we suggest putting all the <acronym title="JavaScript">JS</acronym> that's not required for interactivity with your site at the bottom of the document. Anything <acronym title="JavaScript">JS</acronym> that makes the site work as intended we suggested embedding in the &lt;head&gt;. Depending on your specific situation, having the majority of your <acronym title="JavaScript">JS</acronym> at the bottom of the document will mean that your visitors won't have to download things they don't want to begin interacting with your site or reading it's content. Quite often the additional <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transaction is worthwhile.</p> ]]></answer>
280
- </entry>
281
- <entry>
282
- <question><![CDATA[ Does it really matter if I remove the line breaks from my code? ]]></question>
283
- <answer><![CDATA[ <p>Definitely. Removing white space from your files make <acronym title="GNU zip">gzip</acronym> (<acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression) more effective.</p> ]]></answer>
284
- </entry>
285
- <entry>
286
- <question><![CDATA[ What's the benefit of removing <acronym title="Hypertext Markup Language">HTML</acronym> comments from my code? ]]></question>
287
- <answer><![CDATA[ <p>Many developers like to have comments in the code for various reasons, however these comments add no value from the blog readers (or search engine for that matter) point of view and only contribute to increased load time and wasted bandwidth as a result. Now only you can use them and view them in your site (as a logged in administrator viewing the page source), which is really what (we assume) you intended.</p> ]]></answer>
288
- </entry>
289
- <entry>
290
- <question><![CDATA[ Why is &lt;link&gt; used to embed <acronym title="Cascading Style Sheet">CSS</acronym> instead of &lt;style&gt;? ]]></question>
291
- <answer><![CDATA[ <p>&lt;link&gt; is a non-blocking method to embed <acronym title="Cascading Style Sheet">CSS</acronym> into a document. We recommend this approach for optimal performance.</p> ]]></answer>
292
- </entry>
293
- <entry>
294
- <question><![CDATA[ Why do I care of <acronym title="JavaScript">JS</acronym> or <acronym title="Cascading Style Sheet">CSS</acronym> is "blocking" or not? ]]></question>
295
- <answer><![CDATA[ <p>In the case of objects (files) you don't host yourself, this could add several seconds to your page's load time as the <acronym title="Domain Name System">DNS</acronym> lookups, <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transaction roundtrip times and wait times add up. Even when all the scripts are hosted locally, the same adversities exist. Since all objects in the &lt;head&gt; of a document have to be ready before the page can be rendered, having them load in a parallel fashion as opposed to linear (or near linear) gives night and day results.</p> ]]></answer>
296
- </entry>
297
- <entry>
298
- <question><![CDATA[ What does this plugin do to inline <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym>? ]]></question>
299
- <answer><![CDATA[ <p>Nothing yet. We're evaluating use cases to deal with common issues (like inline <acronym title="Cascading Style Sheet">CSS</acronym> for tag clouds for example).</p> ]]></answer>
300
- </entry>
301
- <entry>
302
- <question><![CDATA[ Ok I get it, this all sounds nice and everything, but is this perfect? ]]></question>
303
- <answer><![CDATA[ <p>Pretty much. If you monetize your blog with ads you will want to spend some time making sure that the ad code works well with your optimization settings. There are also the occasional pieces of code that conflict with the others and have to be in a specific order to work well, but that's not a problem that this plugin introduces.</p> ]]></answer>
304
- </entry>
305
- <entry>
306
- <question><![CDATA[ Will this plugin break my theme by changing the order of conditional statements or the like? ]]></question>
307
- <answer><![CDATA[ <p>No, the plugin looks for conditional statements in your markup used for <acronym title="Cascading Style Sheet">CSS</acronym> (and sometimes <acronym title="JavaScript">JS</acronym>) and makes sure that the minified files precede it, so keep that in mind.</p> ]]></answer>
308
- </entry>
309
- <entry>
310
- <question><![CDATA[ Can I use packed or obfuscated <acronym title="JavaScript">JS</acronym> with this plugin? ]]></question>
311
- <answer><![CDATA[ <p> Yes and no. In general, packed <acronym title="JavaScript">JS</acronym> cannot be minified reliably. Obfuscated <acronym title="JavaScript">JS</acronym> also is hit or miss. A minified and <acronym title="GNU zip">gzip</acronym>ped <acronym title="JavaScript">JS</acronym> file will be smaller than a packed file in any case, so using the (uncompressed, unpacked or un obfuscated) developer versions of your plugins is no longer a concern when using this plugin. Alternatively, you can use the non-blocking embed option to continue to use your packed or obfuscated file without minification.</p> ]]></answer>
312
- </entry>
313
- <entry>
314
- <question><![CDATA[ What about comments? Does the plugin slow down the rate at which comments appear? ]]></question>
315
- <answer><![CDATA[ <p>On the contrary, as with any other action a user can perform on a site, faster performance will encourage more of it. The cache is so quickly rebuilt in memory that it's no trouble to show visitors the most current version of a post that's experiencing Digg, Slashdot, Drudge Report, Yahoo Buzz or Twitter effect.</p> ]]></answer>
316
- </entry>
317
- <entry>
318
- <question><![CDATA[ What if I accidentally specify an incorrect path to a <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> file? ]]></question>
319
- <answer><![CDATA[ <p>Unfortunately a 400 bad request error may be generated. So use the "Check <acronym title="Uniform Resource Indicator">URI</acronym>" button to make sure that you have entered the correct <acronym title="Uniform Resource Indicator">URL</acronym> or path to the file.</p> ]]></answer>
320
- </entry>
321
- <entry>
322
- <question><![CDATA[ Does the plugin automatically remove duplicate <acronym title="JavaScript">JS</acronym>? ]]></question>
323
- <answer><![CDATA[ <p>No. If you include a script in the minfy settings twice or it already exists in your theme we do not automatically remove the extra code. That's tricky business and it's better for us to just let you make the decisions conscientiously.</p> ]]></answer>
324
- </entry>
325
- <entry>
326
- <question><![CDATA[ I have some <acronym title="Cascading Style Sheet">CSS</acronym> classes with declarations being overwritten or <acronym title="JavaScript">JS</acronym> with dependencies, do I really have to copy and paste all my <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> file settings around?</strong> ]]></question>
327
- <answer><![CDATA[ <p>No, you can drag and drop them into the desired order on the minify settings page.</p> ]]></answer>
328
- </entry>
329
- <entry>
330
- <question><![CDATA[ Why does your plugin change the order of my &lt;script&gt; and &lt;link&gt; tags (in the &lt;head&gt;)? ]]></question>
331
- <answer><![CDATA[ <p>Steve Souders <a href="http://www.youtube.com/watch?v=oaxZtKAlLRk" target="_blank">identified</a> that placing inline scripts between <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> embeds creates a blocking situation, so we're try to help you avoid that. If you'd like to experiment with various scenarios related specifically to your blog, we recommend Steve's tool, <a href="http://stevesouders.com/cuzillion/" target="_blank">Cuzillion</a>. Have some beneficial input on other common cases for WordPress users? <a href="mailto:wordpressexperts@w3-edge.com">Reach out to us</a>.</p> ]]></answer>
332
- </entry>
333
- <entry>
334
- <question><![CDATA[ I can't read this minified <acronym title="Hypertext Markup Language">HTML</acronym>; can you give me a break please? ]]></question>
335
- <answer><![CDATA[ <p>Happy to! Login as an administrator, go to the Minify Settings page and check off "Show un-minified pages to administrators" and save the changes. Now stay logged in as an administrator in the same browser you used to change the settings and now when you view the source of a given page in the site, the source will not be minified.</p> ]]></answer>
336
- </entry>
337
- <entry>
338
- <question><![CDATA[ I'm an advanced theme developer and I want to have different combinations of <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> files on different types of pages in my theme; how is this done? ]]></question>
339
- <answer><![CDATA[ <p>On the minify settings tab, use the drop-down selection menu to define the <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> files that appear on all pages using the "Default" group first. Then specify unie files for the other pages.</p> ]]></answer>
340
- </entry>
341
- <entry>
342
- <question><![CDATA[ Why do you set the value of the media attribute of &lt;link&gt; to all? ]]></question>
343
- <answer><![CDATA[ <p>In case you were using @media declarations in your document, we'd have you covered. We will likely allow you to modify this attribute as subsequent features are finalized.</p> ]]></answer>
344
- </entry>
345
- <entry>
346
- <question><![CDATA[ Some WordPress caching plugins fail when markup is not well-formed, is this plugin similar? ]]></question>
347
- <answer><![CDATA[ <p>No, this plugin is not similar. While valid <acronym title="Hypertext Markup Language">HTML</acronym> and <acronym title="World Wide Web Consortium">W3C</acronym> standards ensure consistent behavior across user agents and promote accessibility, any invalidity that exist in the code is not going to bring your site to its knees.</p> ]]></answer>
348
- </entry>
349
- <entry>
350
- <question><![CDATA[ Won't various 3rd parties who's <acronym title="JavaScript">JS</acronym> I download and cache be concerned? ]]></question>
351
- <answer><![CDATA[ <p>Unlikely, you're saving them bandwidth and using their applications, so they will probably appreciate it as long as their application still works as intended and you're using their software in an authorized manner. Look at it this way, even before this plugin, you and thousands of other people were still downloading it, now you're just downloading it first.</p> ]]></answer>
352
- </entry>
353
- <entry>
354
- <question><![CDATA[
355
- Google already minified and
356
- <acronym title="Hypertext Transfer Protocol">HTTP</acronym>
357
- compressed jQuery (and other libraries ) for me, why can't I just
358
- use their bandwidth and embed other code after it?
359
- ]]></question>
360
- <answer><![CDATA[ <p>You can! Just add Google's script to your minify settings use non-blocking mode and your visitors will download jQuery directly from them as you wish. And the same is obviously true for any other library you wish. Remember you are creating additional <acronym title="Domain Name System">DNS</acronym> Lookups and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transactions when you do this.</p> ]]></answer>
361
- </entry>
362
- <entry>
363
- <question><![CDATA[ I wanted to use a different version jQuery with my theme,
364
- how do I replace WordPress' jQuery with Google's minified version
365
- using your plugin? ]]></question>
366
- <answer><![CDATA[ <p>Currently you cannot, replacement is not yet supported.</p> ]]></answer>
367
- </entry>
368
- <entry>
369
- <question><![CDATA[ What about query string variables on <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym>, do they matter? ]]></question>
370
- <answer><![CDATA[ <p>This is definitely a special case. Files like "http://domain.com/wp-content/themes/default/js/script.js?ver=20090102" etc need to be specified with the full <acronym title="Uniform Resource Locator">URL</acronym>. This is an exception to the general rule of specifying a local path to file like: "wp-content/themes/default/js/script.js", which should also work fine. Be sure to click the "Verify <acronym title="Uniform Resource Indicator">URL</acronym>" button to be sure that everything is ok before saving changes.</p> ]]></answer>
371
- </entry>
372
- <entry>
373
- <question><![CDATA[ How can I embed the CSS or JS file at the location I choose? ]]></question>
374
- <answer><![CDATA[
375
- <p>When using Minify and JS/CSS placement, custom placement, the following tags are available:</p>
376
- <ul>
377
- <li>&lt;!-- W3TC-include-css --&gt;<br / >Used with "Auto" and "Manual". Inserts the minified/combined <acronym title="Cascading Style Sheet">CSS</acronym> files at the location you choose.</li>
378
- <li>&lt;!-- W3TC-include-js-head --&gt;<br / >Used with "Manual". Inserts the minified/combined <acronym title="JavaScript">JS</acronym> files. Embed location "in &lt;head&gt;" in "Manual" mode.</li>
379
- <li>&lt;!-- W3TC-include-js-body-start --&gt;<br / >Used with "Manual". Inserts the minified/combined <acronym title="JavaScript">JS</acronym> files. Embed location "after &lt;body&gt;" in "Manual" mode.</li>
380
- <li>&lt;!-- W3TC-include-js-body-end --&gt;<br / >Used with "Manual". Inserts the minified/combined <acronym title="JavaScript">JS</acronym> files. Embed location "before &lt;/body&gt;" in "Manual" mode.</li>
381
- </ul>
382
- ]]></answer>
383
- </entry>
384
- <entry>
385
- <question><![CDATA[ What's the point of downloading and caching 3rd party files (e.g. <acronym title="JavaScript">JS</acronym>)? ]]></question>
386
- <answer><![CDATA[ <p>With the various hosted 3rd party applications available (from web site statistics to social media sharing widgets), the problems we've noticed are: additional <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transactions, <acronym title="Domain Name System">DNS</acronym> lookups and latencies from busy servers that we can't control and often un-minified files with no <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression all add up to a very slow page load and poor user experience. With your own copy of external files, updated as frequently as you wish, none of these problems exist.</p> ]]></answer>
387
- </entry>
388
- </section>
389
- <section name="CDN">
390
- <entry>
391
- <question><![CDATA[ I don't understand what a <acronym title="Content Delivery Network">CDN</acronym> has to do with caching, that's completely different, no? ]]></question>
392
- <answer><![CDATA[ <p>Technically no, a <acronym title="Content Delivery Network">CDN</acronym> is a high performance cache that stores static assets (your theme files, media library etc) in various locations throughout the world in order to provide low latency access to them by readers in those regions.</p> ]]></answer>
393
- </entry>
394
- <entry>
395
- <question><![CDATA[ How do I configure Amazon Simple Storage Service (Amazon <acronym title="Simple Storage Service">S3</acronym>) or Amazon CloudFront as my <acronym title="Content Delivery Network">CDN</acronym>? ]]></question>
396
- <answer><![CDATA[
397
- <p>First <a href="http://aws.amazon.com/" target="_blank">create an S3 account</a> (unless using origin pull); it may take several hours for your account credentials to be functional. Next, you need to obtain your "Access key ID" and "Secret key" from the "Access Credentials" section of the "<a href="http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key" target="_blank">Security Credentials</a>" page of "My Account." Make sure the status is "active." Next, make sure that "Amazon Simple Storage Service (Amazon S3)" is the selected "<acronym title="Content Delivery Network">CDN</acronym> type" on the "General Settings" tab, then save the changes. Now on the "Content Delivery Network Settings" tab enter your "Access key," "Secret key" and enter a name (avoid special characters and spaces) for your bucket in the "Create a bucket" field by clicking the button of the same name. If using an existing bucket simply specify the bucket name in the "Bucket" field. Click the "Test <acronym title="Simple Storage Service">S3</acronym> Upload" button and make sure that the test is successful, if not check your settings and try again. Save your settings.</p>
398
- <p>Unless you wish to use CloudFront, you're almost done, skip to the next paragraph if you're using CloudFront. Go to the "General Settings" tab and click the "Enable" checkbox and save the settings to enable <acronym title="Content Delivery Network">CDN</acronym> functionality. Empty the cache for the changes to take effect. If preview mode is active you will need to "deploy" your changes for them to take effect.</p>
399
- <p>To use CloudFront, perform all of the steps above, except select the "Amazon CloudFront" "<acronym title="Content Delivery Network">CDN</acronym> type" in the "Content Delivery Network" section of the "General Settings" tab. When creating a new bucket, the distribution ID will automatically be populated. Otherwise, proceed to the <a href="https://console.aws.amazon.com/cloudfront/" target="_blank"><acronym title="Amazon Web Services">AWS</acronym> Management Console</a> and create a new distribution: select the S3 Bucket you created earlier as the "Origin," enter a <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?CNAMEs.html" target="_blank"><acronym title="Canonical Name">CNAME</acronym></a> if you wish to add one or more to your DNS Zone. Make sure that "Distribution Status" is deployed and "State" is enabled. Now on "Content Delivery Network" tab of the plugin, copy the subdomain found in the <acronym title="Amazon Web Services">AWS</acronym> Management Console and enter the <acronym title="Canonical Name">CNAME</acronym> used for the distribution in the "<acronym title="Canonical Name">CNAME</acronym>" field.</p>
400
- <p>You may optionally, specify up to 10 hostnames to use rather than the default hostname, doing so will improve the render performance of your site's pages. Additional hostnames should also be specified in the settings for the distribution you're using in the <acronym title="Amazon Web Services">AWS</acronym> Management Console.</p>
401
- <p>Now go to the General tab and click the "Enable" checkbox and save the settings to enable <acronym title="Content Delivery Network">CDN</acronym> functionality and empty the cache for the changes to take effect. If preview mode is active you will need to "deploy" your changes for them to take effect.</p>
402
- ]]></answer>
403
- </entry>
404
- <entry>
405
- <question><![CDATA[ Anything I need to do when using Amazon Web Services with limited permissions (<acronym title="Simple Storage Service">S3</acronym>, CloudFront, <acronym title="Simple Notification Service">SNS</acronym>)? ]]></question>
406
- <answer><![CDATA[
407
- <p>We recommend that you use <a href="http://docs.amazonwebservices.com/IAM/latest/UserGuide/AccessPolicyLanguage_KeyConcepts.html" target="_blank"><acronym title="AWS Identity and Access Management">IAM</acronym></a> to create a new policy for <acronym title="Amazon Web Services">AWS</acronym> services that have limited permissions. A helpful tool: <a href="http://awspolicygen.s3.amazonaws.com/policygen.html" target="_blank">AWS Policy Generator</a></p>
408
- <p>You also find a <acronym title="Simple Storage Service">S3</acronym> configuration sample in the "ini" folder in the plugins directory.</p>
409
- ]]>
410
- </answer>
411
- </entry>
412
- <entry>
413
- <question><![CDATA[ How do I configure Rackspace Cloud Files as my <acronym title="Content Delivery Network">CDN</acronym>? ]]></question>
414
- <answer><![CDATA[
415
- <p>First <a href="http://www.rackspacecloud.com/cloud_hosting_products/files" target="_blank">create an account</a>. Next, in the "Content Delivery Network" section of the "General Settings" tab, select Rackspace Cloud Files as the "<acronym title="Content Delivery Network">CDN</acronym> Type." Now, in the "Configuration" section of the "Content Delivery Network" tab, enter the "Username" and "<acronym title="Application Programming Interface">API</acronym> key" associated with your account (found in the <acronym title="Application Programming Interface">API</acronym> Access section of the <a href="https://manage.rackspacecloud.com/APIAccess.do" target="_blank">rackspace cloud control panel</a>) in the respective fields. Next enter a name for the container to use (avoid special characters and spaces). If the operation is successful, the container's ID will automatically appear in the "Replace site's hostname with" field. You may optionally, specify the container name and container ID of an <a href="https://manage.rackspacecloud.com/CloudFiles.do" target="_blank">existing container</a> if you wish. Click the "Test Cloud Files Upload" button and make sure that the test is successful, if not check your settings and try again. Save your settings. You're now ready to export your media library, theme and any other files to the <acronym title="Content Delivery Network">CDN</acronym>.</p>
416
- <p>You may optionally, specify up to 10 hostnames to use rather than the default hostname, doing so will improve the render performance of your site's pages.</p>
417
- <p>Now go to the General tab and click the "Enable" checkbox and save the settings to enable <acronym title="Content Delivery Network">CDN</acronym> functionality and empty the cache for the changes to take effect. If preview mode is active you will need to "deploy" your changes for them to take effect.</p>
418
- ]]></answer>
419
- </entry>
420
- <entry>
421
- <question><![CDATA[ How do I use an Origin Pull (Mirror) <acronym title="Content Delivery Network">CDN</acronym>? ]]></question>
422
- <answer><![CDATA[
423
- <p>Login to your <acronym title="Content Delivery Network">CDN</acronym> providers control panel or account management area. Following any set up steps they provide, create a new "pull zone" or "bucket" for your site's domain name. If there's a set up wizard or any troubleshooting tips your provider offers, be sure to review them. In the "Content Delivery Network" tab of the plugin, enter the hostname your <acronym title="Content Delivery Network">CDN</acronym> provider provided in the "replace site's hostname with" field. You should always do a quick check by opening a test file from the <acronym title="Content Delivery Network">CDN</acronym> hostname, e.g. http://cdn.domain.com/favicon.ico. Troubleshoot with yoru <acronym title="Content Delivery Network">CDN</acronym> provider until this test is successful.</p>
424
- <p>Now go to the "General" tab and click the checkbox and save the settings to enable <acronym title="Content Delivery Network">CDN</acronym> functionality and empty the cache for the changes to take effect.</p> ]]>
425
- </answer>
426
- </entry>
427
- <entry>
428
- <question><![CDATA[ How can I host my favicon with my (origin push) <acronym title="Content Delivery Network">CDN</acronym>? ]]></question>
429
- <answer><![CDATA[ <p>If the file exists in your document root (i.e. http://domain.com/favicon.ico), the plugin can take care of that for you using custom upload options. If the file is in your theme directory you can also have the plugin uploaded from there.</p> ]]></answer>
430
- </entry>
431
- <entry>
432
- <question><![CDATA[ What about the wp-includes files, can those be served from the <acronym title="Content Delivery Network">CDN</acronym>? ]]></question>
433
- <answer><![CDATA[ <p>Yes, you can specify which file types you would like served by <acronym title="Content Delivery Network">CDN</acronym> and they will be uploaded and always downloaded from that location. This includes the smilies, JavaScript files et al. By default we take care of them all.</p> ]]></answer>
434
- </entry>
435
- <entry>
436
- <question><![CDATA[ Are minified files uploaded to my <acronym title="Content Delivery Network">CDN</acronym> provider? ]]></question>
437
- <answer><![CDATA[ <p>Yes, any <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> you manage with the plugin are minified before being uploaded to your <acronym title="Content Delivery Network">CDN</acronym>. You don't have to make any special changes to your theme. We encourage you to make sure that your provider supports <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression as the benefit of having your static assets available from more than one <acronym title="Point of Presence">POP</acronym> alone is not enough.</p> ]]></answer>
438
- </entry>
439
- <entry>
440
- <question><![CDATA[ Who do you recommend as a <acronym title="Content Delivery Network">CDN</acronym> provider? ]]></question>
441
- <answer><![CDATA[
442
- <p>That depends on how you use your blog and where most of your readers read your blog (regionally). Here's a short list:</p>
443
- <ul>
444
- <li><a href="http://bit.ly/acaXXt" target="_blank">MaxCDN</a></li>
445
- <li><a href="http://bit.ly/ao1sGt" target="_blank">Amazon Cloudfront</a></li>
446
- <li><a href="http://bit.ly/9hpX8T" target="_blank">Rackspace Cloud Files</a></li>
447
- <li><a href="http://bit.ly/aCW04j" target="_blank">Limelight Networks</a></li>
448
- </ul>
449
- ]]></answer>
450
- </entry>
451
- <entry>
452
- <question><![CDATA[ Hang on, don't I need to modify my <acronym title="Cascading Style Sheet">CSS</acronym> files so they'll work on the <acronym title="Content Delivery Network">CDN</acronym>? ]]></question>
453
- <answer><![CDATA[ <p>No, that is taken care of for you. Your <acronym title="Cascading Style Sheet">CSS</acronym> files will originate from your <acronym title="Content Delivery Network">CDN</acronym> provider and all paths to any images in your <acronym title="Cascading Style Sheet">CSS</acronym> will be changed from relative to absolute, making sure that they load just fine. Do nothing differently, yet reap all the benefits.</p> ]]></answer>
454
- </entry>
455
- <entry>
456
- <question><![CDATA[ What is the purpose of the "Media Library Import" tool and how do I use it? ]]></question>
457
- <answer><![CDATA[
458
- <p>The media library import tool is for old or "messy" WordPress installations that have attachments (images etc in posts or pages) scattered about the web server or "hot linked" to 3rd party sites instead of properly using the media library.</p>
459
- <p>The tool will scan your posts and pages for the cases above and copy them to your media library, update your posts to use the link addresses and produce a .htaccess file containing the list of of permanent redirects, so search engines can find the files in their new location.</p>
460
- <p>You should backup your database before performing this operation.</p>
461
- ]]></answer>
462
- </entry>
463
- <entry>
464
- <question><![CDATA[ What is the purpose of the "modify attachment <acronym title="Uniform Resource Indicator">URL</acronym>s" button? ]]></question>
465
- <answer><![CDATA[
466
- <p>If the domain name of your site has changed, this tool is useful in updating your posts and pages to use the current addresses. For example, if your site used to be www.domain.com, and you decided to change it to domain.com, the result would either be many "broken" images or many unnecessary redirects (which slow down the visitor's browsing experience). You can use this tool to correct this and similar cases. Correcting the <acronym title="Uniform Resource Indicator">URL</acronym>s of your images also allows the plugin to do a better job of determining which images are actually hosted with the <acronym title="Content Delivery Network">CDN</acronym></p>
467
- <p>As always, it never hurts to back up your database first.</p>
468
- ]]></answer>
469
- </entry>
470
- </section>
471
- <section name="Browser Cache">
472
- <entry>
473
- <question><![CDATA[ What's an ETag and why do I need one? ]]></question>
474
- <answer><![CDATA[ <p>Entity tags were created to add more reliability to client side caching my providing a simple method for a browser to verify that a file had not changed since last it was downloaded. Using them helps enables your server return 304 or "not modified" responses instead of a 200 "ok" response which are much much slower (because the file is sent). The result is a visitor viewing multiple pages of your site would have that "instant loading" experience that we all definitely enjoy. Don't worry we don't use inodes to create our ETags so this solution is reliable for multi server hosting solutions.</p> ]]></answer>
475
- </entry>
476
- <entry>
477
- <question><![CDATA[ What about ETags? ]]></question>
478
- <answer><![CDATA[ <p>Yes, we have ETags covered. Even if you have a clustered hosting environment, your <a href="http://en.wikipedia.org/wiki/HTTP_ETag" target="_blank">Etags</a> will be consistent (across multiple servers in your cluster) so you don't have to worry about using special session cookies when you introduce our plugin. If you would like to specify headers for various reasons, you can do that as well.</p> ]]></answer>
479
- </entry>
480
- <entry>
481
- <question><![CDATA[ Which encodings do you support? ]]></question>
482
- <answer><![CDATA[ <p>We recommend UTF-8, but we do not modify the encoding in any files, instead we simply return the code as it is provided.</p> ]]></answer>
483
- </entry>
484
- </section>
485
- <section name="Compatibility">
486
- <entry>
487
- <question><![CDATA[ Does this plugin work with WordPress <acronym title="Multi-User">MU</acronym>? ]]></question>
488
- <answer><![CDATA[ <p>Indeed it does.</p> ]]></answer>
489
- </entry>
490
- <entry>
491
- <question><![CDATA[ Does this plugin work with BuddyPress (bbPress)? ]]></question>
492
- <answer><![CDATA[ <p>Yes.</p> ]]></answer>
493
- </entry>
494
- <entry>
495
- <question><![CDATA[ Which WordPress versions are supported? ]]></question>
496
- <answer><![CDATA[ <p>To use all features in the suite, a minimum version of 2.8 is required. Earlier versions will benefit from our Media Library Importer to get them back on the upgrade path and into a <acronym title="Content Delivery Network">CDN</acronym> of their choosing.</p> ]]></answer>
497
- </entry>
498
- <entry>
499
- <question><![CDATA[ Will the plugin interfere with other plugins or widgets? ]]></question>
500
- <answer><![CDATA[ <p>No, on the contrary if you use the minify settings you will improve their performance by several times.</p> ]]></answer>
501
- </entry>
502
- <entry>
503
- <question><![CDATA[ Is this plugin compatible with other popular caching plugins? ]]></question>
504
- <answer><![CDATA[ <p>No. Any disk based page caching plugin you're currently using would need to be completely uninstalled (not just disabled) in order to use this plugin. So if you have a development environment where you can try this out or testing during low traffic periods to get your preferences set, that is recommended. You can always backup your full WordPress installation before testing pretty quickly if you skip the /uploads/ (media library) directory.</p> ]]></answer>
505
- </entry>
506
- <entry>
507
- <question><![CDATA[ Is this plugin comptatible with GD Star Rating? ]]></question>
508
- <answer><![CDATA[
509
- <p>Yes. Follow these steps:</p>
510
- <ol>
511
- <li>Enable dynamic loading of ratings by checking GD Star Rating -> Settings -> Features "Cache support option"</li>
512
- <li>If Database cache enabled in W3 Total Cache add "wp_gdsr" to "Ignored query stems" field in the Database Cache settings tab, otherwise ratings will not updated after voting</li>
513
- <li>Empty all caches</li>
514
- </ol>
515
- ]]></answer>
516
- </entry>
517
- <entry>
518
- <question><![CDATA[ How do I get WPTouch to work properly together with W3 Total Cache? ]]></question>
519
- <answer><![CDATA[ <p>You need to enable "User Agent Groups" high and low and add any user agents you think are missing.</p>]]></answer>
520
- </entry>
521
- <entry>
522
- <question><![CDATA[ Is this plugin comptatible with TDO Mini Forms? ]]></question>
523
- <answer><![CDATA[ <p>Captcha and recaptcha will work fine, however you will need to prevent any pages with forms from being cached. Add the page's URI to the "Never cache the following pages" box on the Page Cache Settings tab.</p> ]]></answer>
524
- </entry>
525
- <entry>
526
- <question><![CDATA[ Is this plugin compatible with varnish or squid? ]]></question>
527
- <answer><![CDATA[ <p>It is compatible with <a href="http://varnish.projects.linpro.no/" target="_blank">varnish</a>.</p> ]]></answer>
528
- </entry>
529
- </section>
530
- <section name="Errors / Debugging">
531
- <entry>
532
- <question><![CDATA[ I've been using the plugin for some time, I updated one of my other plugins and now it doesn't work anymore. What's up? ]]></question>
533
- <answer><![CDATA[ <p>It's likely the plugin author modified their <acronym title="JavaScript">JS</acronym> or <acronym title="Cascading Style Sheet">CSS</acronym> in the new release and any old <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> you optimized with our plugin has introduced duplicate code as a result (creating a conflict). Simply check out the source code, identify any new <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> and update your <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> optimizations our plugin and you're good to go.</p> ]]></answer>
534
- </entry>
535
- <entry>
536
- <question><![CDATA[ I see garbage characters instead of the normal web site, what's going on here? ]]></question>
537
- <answer><![CDATA[ <p>If a theme or it's files use the call php_flush() or function flush() that will interfere with the plugins normal operation; making the plugin send cached files before essential operations have finished. The flush() call is no longer necessary and should be removed.</p> ]]></answer>
538
- </entry>
539
- <entry>
540
- <question><![CDATA[ I'm getting blank pages or 500 error codes when trying to upgrade on WordPress MU ]]></question>
541
- <answer><![CDATA[ <p>First, make sure the plugin is not active (disabled) network-wide. Then make sure it's deactivated network-wide. Now you should be able to successful upgrade without breaking your site.</p> ]]></answer>
542
- </entry>
543
- <entry>
544
- <question><![CDATA[ When I post / like my posts on Facebook the wrong text or no images are shown on Facebook.]]></question>
545
- <answer><![CDATA[ <p>If this happens you need to add the following user agents to the textarea "Rejected user agents" the Page Cache settings page:</p>
546
- <pre>facebookexternalhit
547
- FacebookExternalHit/1.1
548
- FacebookExternalHit/1.0</pre>
549
- <p>Also make sure you have the correct xmlns:og /xmlns:fb tags in your opening HTML tag.</p>
550
- ]]></answer>
551
- </entry>
552
- <entry>
553
- <question><![CDATA[ Why doesn't minify work for me? ]]></question>
554
- <answer> <![CDATA[
555
- <p>Great question. W3 Total Cache uses several open source tools to attempt to combine and optimize <acronym title="Cascading Style Sheet">CSS</acronym>, JavaScript and <acronym title="Hypertext Markup Language">HTML</acronym> etc. Unfortunately some trial and error is required on the part of developers is required to make sure that their code can be successfully minified with the various libraries W3 Total Cache supports. Even still, if developers do test their code thoroughly, they cannot be sure that interoperability with other code your site may have. This fault does not lie with any single party here, because there are thousands of plugins and theme combinations that a given site can have, there are millions of possible combinations of <acronym title="Cascading Style Sheet">CSS</acronym>, JavaScript etc.</p>
556
- <p>A good rule of thumb is to try auto mode, work with a developer to identify the code that is not compatible and start with combine only mode (the safest optimization) and increase the optimization to the point just before functionality (JavaScript) or user interface / layout (<acronym title="Cascading Style Sheet">CSS</acronym>) breaks in your site.</p>
557
- <p>We're always working to make this more simple and straight forward in future releases, but this is not an undertaking we can realize on our own. When you find a plugin, theme or file that is not compatible with minification reach out to the developer and ask them either to provide a minified version with their distribution or otherwise make sure their code is minification-friendly.</p>
558
- ]]></answer>
559
- </entry>
560
- <entry>
561
- <question><![CDATA[ A notification about file owner appears along with a <acronym title="File Transfer Protocol">FTP</acronym> form, how can I resolve this? ]]></question>
562
- <answer><![CDATA[ <p>The plugin uses WordPress FileSystem functionality to write to files. It verifies that file owner, file owner group of created files match process owner. If this is not the case it cannot write or modify files.</[>
563
- <p>Typically, you should ask your web host about the permissions issue and they should be able to resolve it.
564
- You can however try adding <em>define('FS_METHOD', 'direct');</em> to wp-config.php to circumvent the file and folder checks.</p>
565
- ]]></answer>
566
- </entry>
567
- <entry>
568
- <question><![CDATA[ I get an CloudFlare error message similar too <em>"certificate verify locations: CAfile: /etc/path/certs/ca-bundle.crt CApath: none "</em> ]]></question>
569
- <answer>
570
- <![CDATA[ <p>
571
- This is happens when CURL cannot find the proper location of certificates or the certificates have incorrect permissions. Ask your web host for help addressing this issue.
572
- </p>
573
- ]]>
574
- </answer>
575
- </entry>
576
- </section>
577
- <section name="Requirements">
578
- <entry>
579
- <question><![CDATA[ Which web servers do you support? ]]></question>
580
- <answer><![CDATA[ <p>We are aware of no incompatibilities with <a href="http://httpd.apache.org/" target="_blank">apache</a> 1.3+, <a href="[nginx](https://www.nginx.com/solutions/web-server/) 0.7+" target="_blank">nginx 0.7+</a>, , <a href="http://www.iis.net/" target="_blank">IIS</a> 5+ or <a href="http://litespeedtech.com/products/webserver/overview/" target="_blank">litespeed</a> 4.0.2+. If there's a web server you feel we should be actively testing (e.g. <a href="http://www.lighttpd.net/" target="_blank">lighttpd</a>), we're <a href="mailto:wordpressexperts@w3-edge.com">interested in hearing</a>.</p> ]]></answer>
581
- </entry>
582
- <entry>
583
- <question><![CDATA[ Do I need to enable mod_gzip, mod_rewrite or install any <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression software on my server? ]]></question>
584
- <answer><![CDATA[
585
- <p>Not when the option is enabled for page caching or minfiied files, however you do need either module to compress files that are not handled by W3 Total Cache.</p>
586
- <p>If you're larger organization or a web hosting company, consider looking into solutions that exist like <a href="http://www.gear6.com/">Gear6</a> which could be useful now that you have a plugin that makes management memcached pain free.</p>
587
- ]]></answer>
588
- </entry>
589
- <entry>
590
- <question><![CDATA[ How much memory (<acronym title="Random Access Memory">RAM</acronym>) do I need to delegate to caching? ]]></question>
591
- <answer><![CDATA[
592
- <p>Probably the hardest question of all. At the time of this writing the default WordPress install and theme will consume about 50MB of memory in an opcode cache while running our plugin. Keep in mind that the following factors will determine the minimum size of your cache beyond this noted 50MB:</p>
593
- <ul>
594
- <li>Number of typically requested pages per day (if your blog is popular this number is quite large)</li>
595
- <li>Size of minified <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> and <acronym title="Hypertext Markup Language">HTML</acronym> pages (smaller is better)</li>
596
- <li>Number and complexity of plugins active on your blog (fewer is better)</li>
597
- <li>Expiry time of the cache (larger expiry time, larger cache)</li>
598
- </ul>
599
- <p>So we recommend an absolute minimum of 128MB for a typical blog; this figure is greater than some defaults, so keep that in mind. With statistics you'll be able to react accordingly and make adjustments.</p>
600
- <p>For those that don't want or have time to learn anything new to get started, sample configuration files are included with the plugin containing inline comments for you.</p>
601
- ]]></answer>
602
- </entry>
603
- <entry>
604
- <question><![CDATA[ What version of <acronym title="Hypertext Preprocessor">PHP</acronym> do I need for this thing? ]]></question>
605
- <answer><![CDATA[ <p> Version 5.3+ </p> ]]></answer>
606
- </entry>
607
- <entry>
608
- <question><![CDATA[ What version of mySQL is needed? ]]></question>
609
- <answer><![CDATA[ <p>If your WordPress installation works, you're all set.</p> ]]></answer>
610
- </entry>
611
- <entry>
612
- <question><![CDATA[ And I need mod_rewrite (or equivalent for my web server) installed too, no? ]]></question>
613
- <answer><![CDATA[ <p>That's correct; everything you need for WordPress (i.e. fancy <acronym title="Uniform Resource Locator">URL</acronym>s) will get you started with this plugin also.</p> ]]></answer>
614
- </entry>
615
- <entry>
616
- <question><![CDATA[ How much hardware do I have to throw at something like this before I see a benefit? ]]></question>
617
- <answer><![CDATA[ <p>This plugin was actually designed with virtual dedicated servers in mind. As long as your server has at least 256M of <acronym title="Random Access Memory">RAM</acronym>, you can get started with the advanced optimizations.</p> ]]></answer>
618
- </entry>
619
- <entry>
620
- <question><![CDATA[ Is this plugin server cluster and load balancer friendly? ]]></question>
621
- <answer><![CDATA[ <p>Yes, built from the ground up with scale and current hosting paradigms in mind.</p> ]]></answer>
622
- </entry>
623
- <entry>
624
- <question><![CDATA[ I'm a web hosting provider and I heard about this plugin from my clients, is this plugin safe for a shared hosting environment? ]]></question>
625
- <answer><![CDATA[ <p>Yes.</p> ]]></answer>
626
- </entry>
627
- <entry>
628
- <question><![CDATA[ What is the intended impact of this plugin on the web hosting landscape? ]]></question>
629
- <answer><![CDATA[ <p>We feel that shared or virtual hosting providers will begin offering secure containers (similar to what <a href="http://mediatemple.net/" target="_blank">mediatemple.net</a> does for mySQL and Ruby etc) for opcode caching and memcached. Whoever brings this offering to market first will lower the bar for more web sites/applications (and startups) to build better performing applications with greater ease. The same hosting provider would also possess a new value added service, thereby realizing a competitive advantage in a highly competitive marketplace. Not to mention be able to increase the density of domains per server (or cluster) without shortchanging customers.</p> <p>One day hopefully this plugin will contribute to making web servers greener and reduce the ecological footprint of the web by reducing the computational effort required to deliver high performance rich user experiences.</p> ]]></answer>
630
- </entry>
631
- </section>
632
- <section name="Developers">
633
- <entry>
634
- <question><![CDATA[ When are you going to translate this plugin into more languages? ]]></question>
635
- <answer><![CDATA[ <p>When you help us! :-) Localization is tricky and we're happy to work with those willing to support the WordPress community. We will most likely follow the <a href="http://en.wordpress.com/stats/" target="_blank">trends of WordPress</a> itself to determine which languages are addressed first.</p> ]]></answer>
636
- </entry>
637
- <entry>
638
- <question><![CDATA[ How do I implement page fragment caching? ]]></question>
639
- <answer><![CDATA[
640
- <p>First you need to define W3TC_DYNAMIC_SECURITY in your wp-config.php file.</p>
641
- <pre>
642
- define('W3TC_DYNAMIC_SECURITY', 'somesecurestring');
643
- </pre>
644
- <p>Edit your templates with the following syntax to ensure that dynamic features remain so. Replace W3TC_DYNAMIC_SECURITY with content of the constant or use echo to print constant:</p>
645
- <ul>
646
- <li>Example 1:<br />&lt;!-- mfunc W3TC_DYNAMIC_SECURITY any PHP code --&gt;&lt;!-- /mfunc W3TC_DYNAMIC_SECURITY --&gt;</li>
647
- <li>Example 2:<br />&lt;!-- mfunc W3TC_DYNAMIC_SECURITY --&gt;any PHP code&lt;!-- /mfunc W3TC_DYNAMIC_SECURITY --&gt;</li>
648
- <li>Example 3:<br />&lt;!--MFUNC W3TC_DYNAMIC_SECURITY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo rand();<br />&lt;!--/mfunc W3TC_DYNAMIC_SECURITY --&gt;</li>
649
- <li>Example 4:<br />&lt;!-- mclude W3TC_DYNAMIC_SECURITY path/to/file.php --&gt;&lt;!-- /mclude W3TC_DYNAMIC_SECURITY --&gt;</li>
650
- <li>Example 5:<br />&lt;!-- mclude W3TC_DYNAMIC_SECURITY --&gt;path/to/file.php&lt;!-- /mclude W3TC_DYNAMIC_SECURITY --&gt;</li>
651
- </ul>
652
- <p>Be aware that WordPress functions will not be available.</p>
653
- ]]></answer>
654
- </entry>
655
- <entry>
656
- <question><![CDATA[ How can I prevent caching directly in my templates etc? ]]></question>
657
- <answer><![CDATA[
658
- <p>Several constants are available for these purposes:</p>
659
- <ul>
660
- <li>define('DONOTCACHEPAGE', true);<br />Disables page caching for a given page.</li>
661
- <li>define('DONOTCACHEDB', true);<br />Disables database caching for given page.</li>
662
- <li>define('DONOTMINIFY', true);<br />Disables minify for a given page.</li>
663
- <li>define('DONOTCDN', true);<br />Disables content delivery network for a given page.</li>
664
- <li>define('DONOTCACHEOBJECT', true);<br />Disables object cache for a given page.</li>
665
- </ul>
666
- ]]></answer>
667
- </entry>
668
- <entry>
669
- <question><![CDATA[ How can I flush the cache without using the WP Admin interface? ]]></question>
670
- <answer><![CDATA[
671
- <p>It's possible to empty the entire cache or simply purge the cache of a single post / page:</p>
672
- <ul>
673
- <li>Purge the entire cache of html content:<br />
674
- if (function_exists('w3tc_flush_posts')) {<br />
675
- w3tc_flush_posts();<br />
676
- }
677
- </li>
678
- <li>Purge a single post / page by passing it's ID:<br />
679
- if (function_exists('w3tc_flush_post')) {<br />
680
- w3tc_flush_post($post_id);<br />
681
- }
682
- </li>
683
- </ul>
684
- ]]></answer>
685
- </entry>
686
- <entry>
687
- <question><![CDATA[ How do I programmatically modify user agent groups? ]]></question>
688
- <answer><![CDATA[
689
- <p>There are two ways change user agent groups, functions or filter.</p>
690
- <p><strong>Using functions:</strong></p>
691
- <pre>
692
- $group_config = w3tc_get_user_agent_group($group_name); //name of the group
693
- $group_config['theme'] = 'newtheme';
694
- $group_config['redirect'] = '';
695
- $group_config['agents'] = array(escaped_string, [...]);
696
- $group_config['enabled'] = true;
697
-
698
- w3tc_save_user_agent_group($group_name, $group_config['theme'], $group_config['redirect'], $group_config['agents'], $group_config['enabled']);
699
-
700
- </pre>
701
- <p><strong>Using filter: </strong></p>
702
- <pre>
703
- function my_w3tc_mobile_groups($w3tc_groups) {
704
- // any operations
705
- // clear all groups example
706
- $w3tc_groups = array();
707
- // delete all groups and add new example
708
- $w3tc_groups = array(....);
709
- // merge groups example:
710
- $w3tc_groups = array_merge($w3tc_groups, array(
711
- 'good_browsers' =&gt; array(
712
- 'theme' =&gt; 'good_theme/good_theme',
713
- 'enabled' =&gt; true,
714
- 'redirect' =&gt; '',
715
- 'agents' =&gt; array('firefox', 'chrome')
716
- ),
717
- 'bad_browsers' =&gt; array(
718
- 'theme' =&gt; 'bad_theme/bad_theme',
719
- 'enabled' =&gt; true,
720
- 'redirect' =&gt; '',
721
- 'agents' =&gt; array('msie', 'opera')
722
- )
723
- ));
724
- return $w3tc_groups;
725
- }
726
- add_filter('w3tc_mobile_groups', 'my_w3tc_mobile_groups');
727
- </pre>
728
- ]]></answer>
729
- </entry>
730
- <entry>
731
- <question><![CDATA[ How do I programmatically modify referrer groups? ]]></question>
732
- <answer><![CDATA[
733
- <p>There are two ways change referrer groups, functions or filter.</p>
734
- <p><strong>Using functions:</strong></p>
735
- <pre>
736
- $group_config = w3tc_get_referrer_group($group_name); //name of the group
737
- $group_config['theme'] = 'newtheme';
738
- $group_config['redirect'] = '';
739
- $group_config['referrers'] = array(escaped_string, [...]);
740
- $group_config['enabled'] = true;
741
- w3tc_save_referrer_group($group_name, $group_config['theme'], $group_config['referrer'], $group_config['referrers'], $group_config['enabled']);
742
- </pre>
743
- <p><strong>Using filters: </strong></p>
744
- <pre>
745
- function my_w3tc_referrer_groups($w3tc_groups) {<br />
746
- // any operations
747
- // clear all groups example
748
- $w3tc_groups = array();
749
-
750
- // delete all groups and add new example
751
- $w3tc_groups = array(....);
752
-
753
- // merge groups example:
754
- $w3tc_groups = array_merge($w3tc_groups, array(
755
- 'search_referrers' =&gt; array(
756
- 'theme' =&gt; 'search_theme',
757
- 'enabled' =&gt; true,<br />
758
- 'redirect' =&gt; '',<br />
759
- 'referrers' =&gt; array('google\.com')
760
- ),
761
-
762
- 'other_referrers' =&gt; array(
763
- 'theme' =&gt; 'video_theme',
764
- 'enabled' =&gt; true,
765
- 'redirect' =&gt; '',
766
- 'referrers' =&gt; array('youtube\.com')
767
- )
768
- ));
769
-
770
- return $w3tc_groups;
771
- }
772
- add_filter('w3tc_referrer_groups', 'my_w3tc_referrer_groups');</pre>
773
- ]]></answer>
774
- </entry>
775
- <entry>
776
- <question><![CDATA[ How do I remove the W3 Total Cache <acronym title="Hypertext Markup Language">HTML</acronym> comment? ]]></question>
777
- <answer> <![CDATA[
778
- <p>Define APP_REQUEST in wp-config.php for example:<br /><br />
779
- if ($_SERVER['REQUEST_URI'] == '/my-specific-page/') {<br />
780
- &nbsp;&nbsp;&nbsp;&nbsp;define('APP_REQUEST', 'true');<br />
781
- }
782
- </p>
783
- ]]></answer>
784
- </entry>
785
- <entry>
786
- <question><![CDATA[ How can I issue delete and reload APC commands over <acronym title="Hypertext Transfer Protocol">HTTP</acronym>/WP-CLI? ]]></question>
787
- <answer> <![CDATA[
788
- <p>Functions required for deleting and reloading over <acronym title="Hypertext Transfer Protocol">HTTP</acronym> is found in inc/w3-total-cache-api.php.<br />
789
- Call <em>w3tc_opcache_flush_file(,true)</em> to reload file.<br />
790
- Call <em>w3tc_opcache_flush(true)</em> to flush all files.</p>
791
- <p>
792
- <p>To do it locally with <em>WP-CLI</em>:<br />
793
- Call <em>wp w3-total-cache opcache_flush_file local file1</em><br />
794
- Call <em>wp w3-total-cache opcache_flush local</em><br />
795
- </p>
796
- ]]></answer>
797
- </entry>
798
- <entry>
799
- <question><![CDATA[ How do I add new extensions? ]]></question>
800
- <answer><![CDATA[
801
- <p>
802
- Refer to w3-total-cache/extensions/GenesisAdmin.php to see how to create an extension by example.
803
- </p>
804
- <pre>
805
- // Adding a basic function. See GenesisAdmin.php for how to setup settings screen.
806
- add_filter('w3tc_extensions', 'custom_extension');
807
- function custom_extension($extensions) {
808
- $extensions['some.theme'] = array (
809
- 'name' => 'Custpom Framework Extension',
810
- 'author' => 'Bluw Widgets',
811
- 'description' => 'Adds specific caching capabilities.',
812
- 'author_uri' => 'http://example.com',
813
- 'extension_uri' => 'http://example.com',
814
- 'extension_id' => 'some.theme',
815
- 'settings_exists' => false,
816
- 'version' => '0.1',
817
- 'enabled' => true,
818
- 'requirements' => array(),
819
- 'path' => 'your-plugin-folder/extensions/CustomExtension.php'
820
- );
821
- }
822
- </pre>
823
- ]]></answer>
824
- </entry>
825
- </section>
826
- </faqs>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/faq-enterprise-en_US.xml DELETED
@@ -1,61 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <faqs>
3
- <section name="General">
4
- <entry>
5
- <question>
6
- <![CDATA[ Which Enterprise features are currently available? ]]>
7
- </question>
8
- <answer>
9
- <![CDATA[ <p>Enterprise features available:</p>
10
- <ul>
11
- <li>Database cluster</li>
12
- <li>Amazon <acronym title="Simple Notification Service">SNS</acronym></li>
13
- </ul>
14
- ]]>
15
- </answer>
16
- </entry>
17
- <entry>
18
- <question><![CDATA[ When should I use Amazon <acronym title="Simple Notification Service">SNS</acronym>? ]]></question>
19
- <answer><![CDATA[ It should be used when you use load balancing with multiple servers. Using Amazon <acronym title="Simple Notification Service">SNS</acronym> will make sure that the W3 Total Cache caches for each server is purged when required. ]]></answer>
20
- </entry>
21
- </section>
22
- <section name="Usage">
23
- <entry>
24
- <question><![CDATA[ How do I enable Database Cluster support? ]]></question>
25
- <answer><![CDATA[
26
- <p>In order to use Database Cluster you need use WordPress in network mode and enable Enterprise mode for W3 Total Cache.</p>
27
- <p>After enabling Enterprise mode you will find a area inside Database Cache box on the General Settings page. Click 'Enable database cluster' to enable the functionality.</p>
28
- ]]></answer>
29
- </entry>
30
- <entry>
31
- <question><![CDATA[ How do I configure Amazon <acronym title="Simple Notification Service">SNS</acronym>?]]>
32
- </question>
33
- <answer><![CDATA[
34
- <ol>
35
- <li>You need to visit <a href="https://console.aws.amazon.com/sns/"><acronym title="Simple Notification Service">SNS</acronym></a> and sign in /create account.</li>
36
- <li>Create a new topic.</li>
37
- <li>Copy paste the Topic ARN into correspongding field on the General Settings page. </li>
38
- <li>Enter the corrent <a href="http://docs.aws.amazon.com/general/latest/gr/rande.html#sns_region">SNS region</a> in the corresponding textfield on General Settings page.</li>
39
- <li>Enter your API key and API secret. You find your API key and API secret under Security Credentials in your Amazon account.</li>
40
- <li>Click subscribe.</li>
41
- <li>Save settings</li>
42
- </ol>
43
- ]]>
44
- </answer>
45
- </entry>
46
- </section>
47
- <section name="Requirements">
48
- <entry>
49
- <question>
50
- <![CDATA[ What is required to use Amazon <acronym title="Simple Notification Service">SNS</acronym>?]]>
51
- </question>
52
- <answer>
53
- <![CDATA[
54
- <p>
55
- You need to sign up for a <a href="http://aws.amazon.com/sns/" target="_blank">Amazon Web Services account</a>.
56
- </p>
57
- ]]>
58
- </answer>
59
- </entry>
60
- </section>
61
- </faqs>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/faq-pro-en_US.xml DELETED
@@ -1,221 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <faqs>
3
- <section name="General">
4
- <entry>
5
- <question>
6
- <![CDATA[ Which Pro features are currently available? ]]>
7
- </question>
8
- <answer>
9
- <![CDATA[ <p>Pro features available:</p>
10
- <ul>
11
- <li>Fragment Cache Extension</li>
12
- <li>Genesis Extension</li>
13
- <li>WPML Extension</li>
14
- <li>Full Site Delivery (FSD)</li>
15
- <li>Cache Statistics</li>
16
- </ul>
17
- ]]>
18
- </answer>
19
- </entry>
20
- <entry>
21
- <question><![CDATA[ How do I enable Pro mode on a site that is not registered, i.e a site that was not used for purchase such as local development site?]]></question>
22
- <answer><![CDATA[
23
- <p>Add define('W3TC_PRO_DEV_MODE', true) to wp-config.php and resave the license key.</p>
24
- ]]></answer>
25
- </entry>
26
- </section>
27
- <section name="Usage">
28
- <section name="CDN">
29
- <entry>
30
- <tag>cdn-fsd-maxcdn</tag>
31
- <question><![CDATA[ How do I set up Full Site Delivery (FSD) with MaxCDN? ]]></question>
32
- <answer><![CDATA[
33
- <p>
34
- <ol>
35
- <li>Select <acronym title="Content Delivery Network">CDN</acronym> provider of your choice in a "Full site mirroring" group of "CDN type" dropdown on "General Settings" page, select MaxCDN there.</li>
36
- <li>Go to "CDN" page.</li>
37
- <li>Click "Authorize" button</li>
38
- <li>Type in API key of your account. You can obtain by following a link in a popup. Opening that link will you will be prompted for your MaxCDN login and password.
39
- Select Zone from the list or choose "Add new" to create new zone (type in some friendly name of zone in that case)</li>
40
- <li>In a zone setup form you will be notified with the settings required for zone. Tou have only 1 editable field is IP address of your WordPress host. W3 Total Cache tries to guess it, but its not possible to know that in all possible cases.</li>
41
- <li>You get success page with information about DNS changes. Now you need to change record of your wordpress host from IP address and replace it to CNAME to specified hostname.</li>
42
- <li>It works</li>
43
- </ol>
44
- </p>
45
- ]]></answer>
46
- </entry>
47
- <entry>
48
- <tag>cdn-fsd-cloudfront</tag>
49
- <question><![CDATA[ How do I set up Full Site Delivery (FSD) with CloudFront? ]]></question>
50
- <answer><![CDATA[
51
- <p>
52
- <ol>
53
- <li>Select <acronym title="Content Delivery Network">CDN</acronym> provider of your choice in a "Full site mirroring" group of "CDN type" dropdown on "General Settings" page, select CloudFront there.</li>
54
- <li>Go to "CDN" page.</li>
55
- <li>Click "Authorize" button</li>
56
- <li>Type in Access Key and Secret Key of your account.</li>
57
- <li>Select Distribution from the list or choose "Add new" to create new zone (type in some friendly name of zone in that case - that will not be visible anywhere except your AWS control panel)</li>
58
- <li>In a distribution setup form you will be notified with the settings required. Tou have only 1 editable field is alternative hostname of your WordPress host. For example if your have myblog.com website with A record pointint to 1.2.3.4 IP, create another one origin.myblog.com DNS record with A record pointint to 1.2.3.4 IP and type in "origin.myblog.com" in this form.</li>
59
- <li>You get success page with information about DNS changes. Now you need to change record of your wordpress host from IP address and replace it to CNAME to specified hostname.</li>
60
- <li>It works</li>
61
- </ol>
62
- </p>
63
- ]]></answer>
64
- </entry>
65
- <entry>
66
- <question><![CDATA[ How do I get CloudFront Dynamic Caching to work with full site delivery (FSD)? ]]></question>
67
- <answer><![CDATA[
68
- <p>
69
- First enable Browser Cache and disable "Expires" header. This is because CloudFront does not cache properly
70
- when "Expires" headers are set. When using CloudFront and full page caching there are no purging of cached pages when posting
71
- new posts etc. Cache invalidations in CF is limited per month and also takes up to 15 minutes to complete. </p>
72
- <p>Since there is no purging and you want to people to be able to comment it is recommended to use a hosted
73
- commenting software, such as FaceBook Comments or Disqus. If you do not use this comments are not
74
- shown after they been posted or approved.
75
- </p>
76
- <p>
77
- Main step to get CloudFront full page caching working is to have your site on a different domain than the
78
- one you want your visitors to see. So you should install or configure your site so its on a separate domain,
79
- for example wp.example.com. You will then later configure example.com so its used by CloudFront.
80
- </p>
81
- <p>How to configure CloudFront on AWS:</p>
82
- <ol>
83
- <li>Go to <a href="https://console.aws.amazon.com/cloudfront/home">AWS Console</a></li>
84
- <li>Click "Create Distribution"</li>
85
- <li>Select "Web"</li>
86
- <li>Click "Continue"</li>
87
- <li>Enter wp.example.com into "Origin Domain Name"</li>
88
- <li>Enter CustomWWW-example.com into "Origin ID"</li>
89
- <li>Set Origin Protocol Policy to HTTP Only (CloudFront will connect to my origin using only HTTP).</li>
90
- <li>Select "Allow HTTP Methods" - GET, HEAD, PUT, PATCH, DELETE, OPTIONS</li>
91
- <li>Select "Forward Query Strings" - Yes</li>
92
- <li>Enter example.com (the domain that your visitors will type into their browser) into
93
- Alternate Domain Names(CNAMESs)</li>
94
- <li>Set logging to "On"</li>
95
- <li>Enter "webserverlog-example.com" into "Bucket for logs"</li>
96
- <li>Enter "stats-logs/" into Log Prefix</li>
97
- <li>Enter "CDN for example.com" into Comment.</li>
98
- <li>Click "Create Distribution"</li>
99
- </ol>
100
- <p>Configure DNS</p>
101
- <ol>
102
- <li>Add new CNAME recored for example.com that points to the Domain Name that belongs to the distribution you created previously.
103
- </ol>
104
- <p>How to configure W3 Total Cache:</p>
105
- <p>There are two methods to configure W3 Total Cache <acronym title="Content Delivery Network">CDN</acronym>. Origin Pull "CloudFront" or "Generic mirror". If you want to be able to invalidate URLs from within WordPress you need to use the CloudFront option.
106
- If you do not configure an <acronym title="Content Delivery Network">CDN</acronym> the wrong URLs will be used when linking to CSS, JS and other files.
107
- </p>
108
- <p>Configure CloudFront:</p>
109
- <ol>
110
- <li>Select Origin Pull (Mirror) Amazon CloudPront on General Page</li>
111
- <li>Go to the CDN page.</li>
112
- <li>Enter your AWS credentials</li>
113
- <li>Enter example.com as an CNAME</li>
114
- <li>Save Settings</li>
115
- </ol>
116
- <p>Configure Generic Mirror:</p>
117
- <ol>
118
- <li>Enter example.com into "Replace site's hostname with:"</li>
119
- <li>Save Settings</li>
120
- </ol>
121
- ]]>
122
- </answer>
123
- </entry>
124
- </section>
125
- <section name="Extensions">
126
- <entry>
127
- <question><![CDATA[ What is required for the Genesis Extension to work? ]]></question>
128
- <answer><![CDATA[ <p>You need to enable Fragment Caching and use a theme based on Genesis.</p> ]]></answer>
129
- </entry>
130
-
131
- <entry>
132
- <question><![CDATA[ When I enabled Genesis Extension with EDD, WooCommerce or other similar plugins, my cart,
133
- checkout and/or other dynamic elements no longer get updated. How do I fix that? ]]></question>
134
- <answer><![CDATA[
135
- <p>You need to go the Genesis Extension settings page.
136
- There you will a textbox called "Excluded single pages / posts:" there you need to enter the pages
137
- that should not be cached by the fragment caching. The exclude textareas support regular expressions
138
- so if the pages that are to be excluded are similar you can most likely enter one
139
- expression that covers all your pages. For information on regular expression you need to search.</p>
140
- <p>
141
- If you have anything dynamic in your widgets area, the sidebar, then you'll need to disable the sidebar caching, or enter pages that should not have their sidedar cached.
142
- </p>
143
- ]]></answer>
144
- </entry>
145
- </section>
146
- </section>
147
- <section name="Developers">
148
- <entry>
149
- <question><![CDATA[ How do I implement fragment caching? ]]></question>
150
- <answer><![CDATA[
151
- <p>Fragment caching adds new functionality to the WordPress <a href="http://codex.wordpress.org/Transients_API">Transients <acronym title="Application Programming Interface">API</acronym></a>:</p>
152
- <ul>
153
- <li>Adds support for grouping transients both per blog and site wide</li>
154
- <li>Adds support for manual flushing of registered transient groups</li>
155
- <li>Adds support for action based flushing of registered transient groups</li>
156
- <li>Adds support for caching filters and actions</li>
157
- </ul>
158
- <p>To make the plugin aware that you group transients see code examples below:</p>
159
- <pre>
160
- add_action('w3tc_register_fragment_groups', 'my_plugin_register_groups');
161
-
162
- function my_plugin_register_groups() {
163
- //blog specific group and an array of actions that will trigger a flush of the group
164
- w3tc_register_fragment_group('my_plugin_', array('publish_post'), 3600);
165
- //If using MultiSite Network/site wide specific group and an array of actions that will trigger a flush of the group
166
- w3tc_register_fragment_group_global('my_plugin_global_', array('edit_site'), 3600);
167
- }
168
- function my_plugin_flush_group() {
169
- //manually flush group.
170
- w3tc_fragmentcache_flush_group('my_plugin_');
171
- }
172
-
173
- //Set transients
174
- function on_some_event() {
175
- if (false === get_transient('my_plugin_some_key'))
176
- //my_plugin_ prefix is the group name we registered earlier
177
- set_transient('my_plugin_some_key', 'blog specific value');
178
- if (false === get_site_transient('my_plugin_some_key'))
179
- //my_plugin_site_ prefix is the group name we registered earlier
180
- set_site_transient('my_plugin_site_some_key', 'site wide specific value');
181
- }
182
-
183
- // Cache action example
184
- add_action('theme_post_loop', 'cache_theme_post_loop_start',-999999999);
185
- add_action('theme_post_loop', 'cache_theme_post_loop_end', 999999999);
186
-
187
- /**
188
- * Start outputbuffering
189
- */
190
- function cache_theme_post_loop_start() {
191
- w3tc_fragmentcache_start('example1', 'examples', 'theme_post_loop');
192
- }
193
-
194
- /**
195
- * Store the output buffer .
196
- */
197
- function cache_theme_post_loop_end() {
198
- w3tc_fragmentcache_end('example1', 'examples', false);
199
- }
200
-
201
- // Cache filter example
202
- add_filter('theme_filter', 'cache_theme_filter_start',-999999999);
203
- add_filter('theme_filter', 'cache_theme_filter_end', 999999999);
204
- /**
205
- * Start filter buffering and return filter result
206
- */
207
- function cache_theme_filter_start($data) {
208
- return w3tc_fragmentcache_filter_start('example_filter1', 'examples', $hook, $data);
209
- }
210
-
211
- /**
212
- * Store the filter result and return filter result.
213
- */
214
- function cache_theme_filter_end($data) {
215
- return w3tc_fragmentcache_filter_end('example_filter1', 'examples', $data);
216
- }
217
- </pre>
218
- ]]></answer>
219
- </entry>
220
- </section>
221
- </faqs>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Minify/Minify.php CHANGED
@@ -241,7 +241,8 @@ class Minify0_Minify {
241
  }
242
 
243
  $cg = new HTTP_ConditionalGet($cgOptions);
244
- if ( $cg->cacheIsValid && !defined( 'W3TC_MINIFY_CONDITIONAL_OFF' ) ) {
 
245
  // client's cache is valid
246
  if (! self::$_options['quiet']) {
247
  self::$lastServed = array(
241
  }
242
 
243
  $cg = new HTTP_ConditionalGet($cgOptions);
244
+ if ( $cg->cacheIsValid && !self::$_options['disable_304'] &&
245
+ !defined( 'W3TC_MINIFY_CONDITIONAL_OFF' ) ) {
246
  // client's cache is valid
247
  if (! self::$_options['quiet']) {
248
  self::$lastServed = array(
lib/Minify/Minify/HTML.php CHANGED
@@ -274,11 +274,12 @@ class Minify_HTML {
274
  {
275
  if (false !== strpos($str, '<![CDATA[')) {
276
  $str = str_replace('//<![CDATA[', '', $str);
277
- $str = str_replace('/*<![CDATA[*/', '', $str);
 
278
  $str = str_replace('<![CDATA[', '', $str);
279
 
280
  $str = str_replace('//]]>', '', $str);
281
- $str = str_replace('/*]]>*/', '', $str);
282
  $str = str_replace(']]>', '', $str);
283
  }
284
 
274
  {
275
  if (false !== strpos($str, '<![CDATA[')) {
276
  $str = str_replace('//<![CDATA[', '', $str);
277
+
278
+ $str = preg_replace('~/\*\s*<!\[CDATA\[\s*\*/~', '', $str);
279
  $str = str_replace('<![CDATA[', '', $str);
280
 
281
  $str = str_replace('//]]>', '', $str);
282
+ $str = preg_replace('~/\*\s*\]\]>\s*\*/~', '', $str);
283
  $str = str_replace(']]>', '', $str);
284
  }
285
 
lib/NetDNA/NetDNA.php CHANGED
@@ -299,29 +299,6 @@ class NetDNA {
299
  return $m;
300
  }
301
 
302
- /**
303
- * Returns all zones connected to an url
304
- * @param $url
305
- * @throws Exception
306
- * @return array|null
307
- */
308
- public function get_zones_by_url($url) {
309
- $zone_id = null;
310
- $pull_zones = json_decode($this->get('/zones/pull.json'), true);
311
- $zones = array();
312
- if (preg_match("(200|201)", $pull_zones['code'])) {
313
- foreach ($pull_zones ['data']['pullzones'] as $zone) {
314
- if (trim($zone['url'], '/') != trim($url, '/'))
315
- continue;
316
- else {
317
- $zones[] = $zone;
318
- }
319
- }
320
- } else
321
- throw new Exception($this->error_message($pull_zones));
322
- return $zones;
323
- }
324
-
325
  /**
326
  * Retrieves pull zones
327
  * @throws Exception
@@ -372,49 +349,6 @@ class NetDNA {
372
  }
373
  }
374
 
375
- /**
376
- * Creates a new pull zone with default settings
377
- * @param string $url the sites url 4-100 chars; only valid URLs accepted
378
- * @param null|string $name 3-32 chars; only letters, digits, and dash (-)accepted
379
- * @param null|string $label length: 1-255 chars
380
- * @param array $zone_settings custom settings
381
- * @return string
382
- */
383
- public function create_default_pull_zone($url, $name = null, $label = null, $zone_settings=array()) {
384
- $zone_defaults = array();
385
- if (is_null($name)) {
386
- $name = md5($url);
387
- $len = strlen($name)>24 ? 24 : strlen($name);
388
- $name = substr($name, 0, $len);
389
- }
390
- if (is_null($label))
391
- $label = sprintf(__('Zone for %s was created by W3 Total Cache', 'w3-total-cache'), $url);
392
- $zone_defaults['name'] = $name;
393
- $zone_defaults['label'] = $label;
394
- $zone_defaults['url'] = $url;
395
- $zone_defaults['use_stale'] = 0;
396
- $zone_defaults['queries'] = 1;
397
- $zone_defaults['compress'] = 1;
398
- $zone_defaults['backend_compress'] = 1;
399
- $zone_defaults['disallow_robots'] = 1;
400
- $zone_defaults = array_merge( $zone_defaults, $zone_settings);
401
- $response = $this->create_pull_zone($zone_defaults);
402
- return $response;
403
- }
404
-
405
- /**
406
- * Returns number of zones
407
- * @throws Exception
408
- * @return array
409
- */
410
- public function get_zone_count() {
411
- $pull_zones = json_decode($this->get('/zones.json/count'), true);
412
- if (preg_match("(200|201)", $pull_zones['code'])) {
413
- return intval($pull_zones ['data']['count']);
414
- } else
415
- throw new Exception($this->error_message($pull_zones));
416
- }
417
-
418
  /**
419
  * Creates custom domains
420
  * @param $zone_id
299
  return $m;
300
  }
301
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  /**
303
  * Retrieves pull zones
304
  * @throws Exception
349
  }
350
  }
351
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  /**
353
  * Creates custom domains
354
  * @param $zone_id
lib/OAuth/W3tcOAuth.php CHANGED
@@ -107,9 +107,9 @@ abstract class W3tcOAuthSignatureMethod {
107
  }
108
 
109
  /**
110
- * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
111
- * where the Signature Base String is the text and the key is the concatenated values (each first
112
- * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
113
  * character (ASCII code 38) even if empty.
114
  * - Chapter 9.2 ("HMAC-SHA1")
115
  */
@@ -135,7 +135,7 @@ class W3tcOAuthSignatureMethod_HMAC_SHA1 extends W3tcOAuthSignatureMethod {
135
  }
136
 
137
  /**
138
- * The PLAINTEXT method does not provide any security protection and SHOULD only be used
139
  * over a secure channel such as HTTPS. It does not use the Signature Base String.
140
  * - Chapter 9.4 ("PLAINTEXT")
141
  */
@@ -145,8 +145,8 @@ class W3tcOAuthSignatureMethod_PLAINTEXT extends W3tcOAuthSignatureMethod {
145
  }
146
 
147
  /**
148
- * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
149
- * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
150
  * empty. The result MUST be encoded again.
151
  * - Chapter 9.4.1 ("Generating Signatures")
152
  *
@@ -168,10 +168,10 @@ class W3tcOAuthSignatureMethod_PLAINTEXT extends W3tcOAuthSignatureMethod {
168
  }
169
 
170
  /**
171
- * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
172
- * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
173
- * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
174
- * verified way to the Service Provider, in a manner which is beyond the scope of this
175
  * specification.
176
  * - Chapter 9.3 ("RSA-SHA1")
177
  */
@@ -635,7 +635,10 @@ class W3tcOAuthUtil {
635
  // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
636
  sort($value, SORT_STRING);
637
  foreach ($value as $duplicate_value) {
638
- $pairs[] = $parameter . '=' . $duplicate_value;
 
 
 
639
  }
640
  } else {
641
  $pairs[] = $parameter . '=' . $value;
107
  }
108
 
109
  /**
110
+ * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104]
111
+ * where the Signature Base String is the text and the key is the concatenated values (each first
112
+ * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&'
113
  * character (ASCII code 38) even if empty.
114
  * - Chapter 9.2 ("HMAC-SHA1")
115
  */
135
  }
136
 
137
  /**
138
+ * The PLAINTEXT method does not provide any security protection and SHOULD only be used
139
  * over a secure channel such as HTTPS. It does not use the Signature Base String.
140
  * - Chapter 9.4 ("PLAINTEXT")
141
  */
145
  }
146
 
147
  /**
148
+ * oauth_signature is set to the concatenated encoded values of the Consumer Secret and
149
+ * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is
150
  * empty. The result MUST be encoded again.
151
  * - Chapter 9.4.1 ("Generating Signatures")
152
  *
168
  }
169
 
170
  /**
171
+ * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in
172
+ * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for
173
+ * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a
174
+ * verified way to the Service Provider, in a manner which is beyond the scope of this
175
  * specification.
176
  * - Chapter 9.3 ("RSA-SHA1")
177
  */
635
  // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
636
  sort($value, SORT_STRING);
637
  foreach ($value as $duplicate_value) {
638
+ $pairs[] = $parameter . '=' .
639
+ ( is_array( $duplicate_value ) ?
640
+ implode( ',', $duplicate_value ) :
641
+ $duplicate_value );
642
  }
643
  } else {
644
  $pairs[] = $parameter . '=' . $value;
pub/css/lightbox.css CHANGED
@@ -475,3 +475,24 @@ padding: 10px 20px 20px 20px;
475
  .w3tc_overlay_upgrade_right_text {
476
  font-weight: normal;
477
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  .w3tc_overlay_upgrade_right_text {
476
  font-weight: normal;
477
  }
478
+
479
+ .w3tc_change_label {
480
+ color:black;
481
+ font-weight:inherit;
482
+ }
483
+
484
+ @media only screen and (max-device-width: 480px) {
485
+ .w3tc_overlay_upgrade_content_l {
486
+ display: none;
487
+ }
488
+ .w3tc_overlay_upgrade_content_r {
489
+ width: inherit;
490
+ padding: none;
491
+ float: none;
492
+ }
493
+
494
+ .w3tc-overlay #w3tc-upgrade ul {
495
+ width: inherit;
496
+ float: none;
497
+ }
498
+ }
pub/css/options.css CHANGED
@@ -47,16 +47,11 @@ input.w3tc-error, textarea.w3tc-error {
47
  }
48
 
49
  #w3tc-help ul {
50
- float: left;
51
- width: 29%;
52
  list-style-type: disc;
53
  margin: 1em 2% 1em 2%;
54
  }
55
 
56
- #w3tc-help li {
57
- margin: 0;
58
- }
59
-
60
  #w3tc-help a {
61
  text-decoration: none;
62
  }
@@ -369,7 +364,7 @@ input.w3tc-error, textarea.w3tc-error {
369
  display:none;
370
  }
371
 
372
- #cdn_netdna_authorization_key, #cdn_maxcdn_authorization_key, .maxcdn-netdna-widget-base .button-secondary{
373
  margin-bottom: 3px;
374
  }
375
 
@@ -441,6 +436,9 @@ td.w3tc_config_value_text {
441
  padding: 20px;
442
  }
443
 
 
 
 
444
 
445
  /*---*/
446
  /* js bound to id */
@@ -450,3 +448,14 @@ th.w3tc_extensions_manage_column_check {
450
  vertical-align: middle;
451
  width: 2.2em;
452
  }
 
 
 
 
 
 
 
 
 
 
 
47
  }
48
 
49
  #w3tc-help ul {
50
+ columns: 2;
 
51
  list-style-type: disc;
52
  margin: 1em 2% 1em 2%;
53
  }
54
 
 
 
 
 
55
  #w3tc-help a {
56
  text-decoration: none;
57
  }
364
  display:none;
365
  }
366
 
367
+ #cdn_netdna_authorization_key, #cdn_maxcdn_authorization_key, {
368
  margin-bottom: 3px;
369
  }
370
 
436
  padding: 20px;
437
  }
438
 
439
+ .w3tc_reject_roles label {
440
+ font-weight: normal;
441
+ }
442
 
443
  /*---*/
444
  /* js bound to id */
448
  vertical-align: middle;
449
  width: 2.2em;
450
  }
451
+
452
+ #browsercache_security_xfo_allow {
453
+ padding-top:0;
454
+ padding-bottom:4px;
455
+ }
456
+ #w3tc_csp {
457
+ width: 872px;
458
+ height: 654px;
459
+ background: url("../img/cspref.png") center center no-repeat;
460
+ margin: auto;
461
+ }
pub/css/widget.css CHANGED
@@ -82,66 +82,3 @@
82
  #normal-sortables #w3tc_new_relic {
83
  width: 360px;
84
  }
85
- .maxcdn-netdna-widget-base h4 {
86
- text-align: center;
87
- }
88
- .maxcdn-netdna-widget-base .summary h4 {
89
- color: #8F8F8F;
90
- text-align: left;
91
- }
92
- .maxcdn-netdna-widget-base .status,.maxcdn-netdna-widget-base .summary {
93
- border-bottom: 1px solid #d2d2d2;
94
- }
95
-
96
- .maxcdn-netdna-widget-base .wrapper {
97
- margin-left: -10px;
98
- margin-right: -10px;
99
- }
100
- .maxcdn-netdna-widget-base .area {
101
- padding-left: 10px;
102
- padding-right: 10px;
103
- }
104
-
105
-
106
- .maxcdn-netdna-widget-base .tools {
107
- margin-top:15px;
108
- }
109
- .maxcdn-netdna-widget-base .tools li {
110
- display:inline-block;
111
- margin-right:10px;
112
- }
113
- .maxcdn-netdna-widget-base .summary li.large span {
114
- width: 210px;
115
- }
116
- .maxcdn-netdna-widget-base ul.file_hits li {
117
- line-height: 12px;
118
- font-size:10px;
119
- }
120
- .maxcdn-netdna-widget-base ul.file_hits li span{
121
- color: #fff;
122
- padding-top: 2px;
123
- padding-left: 5px;
124
- }
125
- .maxcdn-netdna-widget-base .status p, .maxcdn-netdna-widget-base .charts p{
126
- color:#8F8F8F
127
- }
128
- .maxcdn-netdna-widget-base .account_status {
129
- font-weight: bold;
130
- color: #000;
131
- }
132
- .maxcdn-netdna-widget-base .content-zone {
133
- color: #c0d9e4
134
- }
135
- .maxcdn-netdna-widget-base.sign-up h4 {
136
- text-align: left;
137
- margin-bottom: 0;
138
- padding-bottom: 0;
139
- }
140
- .maxcdn-netdna-widget-base.sign-up p{
141
- margin-top: 4px;
142
- padding-top: 0;
143
-
144
- }
145
- .maxcdn-netdna-widget-base.sign-up p span.desc {
146
- color:#8F8F8F;
147
- }
82
  #normal-sortables #w3tc_new_relic {
83
  width: 360px;
84
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pub/img/cspref.png ADDED
Binary file
pub/img/w3tc_stackpath-logo-retina.png ADDED
Binary file
pub/img/w3tc_stackpath-logo.png ADDED
Binary file
pub/js/lightbox.js CHANGED
@@ -90,6 +90,11 @@ var W3tc_Lightbox = {
90
  var width = (this.options.width ? this.options.width : this.window.width() * this.options.widthPercent);
91
  var height = (this.options.height ? this.options.height : this.window.height() * this.options.heightPercent);
92
 
 
 
 
 
 
93
  if (this.options.maxWidth && width > this.options.maxWidth) {
94
  width = this.options.maxWidth;
95
  } else if (width < this.options.minWidth) {
@@ -400,6 +405,8 @@ function w3tc_lightbox_buy_plugin(nonce) {
400
  W3tc_Lightbox.open({
401
  width: 800,
402
  minHeight: 350,
 
 
403
  url: 'admin.php?page=w3tc_dashboard&w3tc_licensing_buy_plugin&_wpnonce=' + nonce,
404
  callback: function(lightbox) {
405
  var w3tc_license_listener = function(event) {
90
  var width = (this.options.width ? this.options.width : this.window.width() * this.options.widthPercent);
91
  var height = (this.options.height ? this.options.height : this.window.height() * this.options.heightPercent);
92
 
93
+ if (!this.options.maxWidth)
94
+ this.options.maxWidth = this.window.width();
95
+ if (!this.options.maxHeight)
96
+ this.options.maxHeight = this.window.height();
97
+
98
  if (this.options.maxWidth && width > this.options.maxWidth) {
99
  width = this.options.maxWidth;
100
  } else if (width < this.options.minWidth) {
405
  W3tc_Lightbox.open({
406
  width: 800,
407
  minHeight: 350,
408
+ maxWidth: jQuery(window).width() - 40,
409
+ maxHeight: jQuery(window).height() - 40,
410
  url: 'admin.php?page=w3tc_dashboard&w3tc_licensing_buy_plugin&_wpnonce=' + nonce,
411
  callback: function(lightbox) {
412
  var w3tc_license_listener = function(event) {
pub/js/options.js CHANGED
@@ -1,1422 +1,1502 @@
1
  function w3tc_popup(url, name, width, height) {
2
- if (width === undefined) {
3
- width = 800;
4
- }
5
- if (height === undefined) {
6
- height = 600;
7
- }
8
-
9
- return window.open(url, name, 'width=' + width + ',height=' + height + ',status=no,toolbar=no,menubar=no,scrollbars=yes');
10
  }
11
 
12
  function w3tc_input_enable(input, enabled) {
13
- jQuery(input).each(function() {
14
- var me = jQuery(this);
15
- if (enabled) {
16
- me.removeAttr('disabled');
17
- } else {
18
- me.attr('disabled', 'disabled');
19
- }
20
-
21
- if (enabled) {
22
- me.next('[type=hidden]').remove();
23
- } else {
24
- var t = me.attr('type');
25
- if ((t != 'radio' && t != 'checkbox') || me.is(':checked')) {
26
- me.after(jQuery('<input />').attr({
27
- type: 'hidden',
28
- name: me.attr('name')
29
- }).val(me.val()));
30
- }
31
- }
32
- });
33
  }
34
 
35
  function w3tc_minify_js_file_clear() {
36
- if (!jQuery('#js_files :visible').size()) {
37
- jQuery('#js_files_empty').show();
38
- } else {
39
- jQuery('#js_files_empty').hide();
40
- }
41
  }
42
 
43
  function w3tc_minify_css_file_clear() {
44
- if (!jQuery('#css_files :visible').size()) {
45
- jQuery('#css_files_empty').show();
46
- } else {
47
- jQuery('#css_files_empty').hide();
48
- }
49
  }
50
 
51
  function w3tc_mobile_groups_clear() {
52
- if (!jQuery('#mobile_groups li').size()) {
53
- jQuery('#mobile_groups_empty').show();
54
- } else {
55
- jQuery('#mobile_groups_empty').hide();
56
- }
57
  }
58
 
59
  function w3tc_referrer_groups_clear() {
60
- if (!jQuery('#referrer_groups li').size()) {
61
- jQuery('#referrer_groups_empty').show();
62
- } else {
63
- jQuery('#referrer_groups_empty').hide();
64
- }
65
  }
66
 
67
  function w3tc_minify_js_file_add(theme, template, location, file) {
68
- var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th>Template:</th><th colspan="3">Embed Location:</th></tr><tr><td>' + (jQuery('#js_files li').size() + 1) + '.</td><td><input class="js_enabled" type="text" name="js_files[' + theme + '][' + template + '][' + location + '][]" value="" size="70" \/></td><td><select class="js_file_template js_enabled"></select></td><td><select class="js_file_location js_enabled"><option value="include">Embed in &lt;head&gt;</option><option value="include-body">Embed after &lt;body&gt;</option><option value="include-footer">Embed before &lt;/body&gt;</option></select></td><td><input class="js_file_delete js_enabled button" type="button" value="Delete" /> <input class="js_file_verify js_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
69
- append.find('input:text').val(file);
70
- var select = append.find('.js_file_template');
71
- for (var i in minify_templates[theme]) {
72
- select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
73
- }
74
- select.val(template);
75
- jQuery(append).find('.js_file_location').val(location);
76
- jQuery('#js_files').append(append).find('li:last input:first').focus();
77
- w3tc_minify_js_file_clear();
78
  }
79
 
80
  function w3tc_minify_css_file_add(theme, template, file) {
81
- var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th colspan="2">Template:</th></tr><tr><td>' + (jQuery('#css_files li').size() + 1) + '.</td><td><input class="css_enabled" type="text" name="css_files[' + theme + '][' + template + '][include][]" value="" size="70" \/></td><td><select class="css_file_template css_enabled"></select></td><td><input class="css_file_delete css_enabled button" type="button" value="Delete" /></td><td><input class="css_file_verify css_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
82
- append.find('input:text').val(file);
83
- var select = append.find('.css_file_template');
84
- for (var i in minify_templates[theme]) {
85
- select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
86
- }
87
- select.val(template);
88
- jQuery('#css_files').append(append).find('li:last input:first').focus();
89
- w3tc_minify_css_file_clear();
90
  }
91
 
92
  function w3tc_minify_js_theme(theme) {
93
- jQuery('#js_themes').val(theme);
94
- jQuery('#js_files :text').each(function() {
95
- var input = jQuery(this);
96
- if (input.attr('name').indexOf('js_files[' + theme + ']') != 0) {
97
- input.parents('li').hide();
98
- } else {
99
- input.parents('li').show();
100
- }
101
- });
102
- w3tc_minify_js_file_clear();
103
  }
104
 
105
  function w3tc_minify_css_theme(theme) {
106
- jQuery('#css_themes').val(theme);
107
- jQuery('#css_files :text').each(function() {
108
- var input = jQuery(this);
109
- if (input.attr('name').indexOf('css_files[' + theme + ']') != 0) {
110
- input.parents('li').hide();
111
- } else {
112
- input.parents('li').show();
113
- }
114
- });
115
- w3tc_minify_css_file_clear();
116
  }
117
 
118
  function w3tc_cdn_get_cnames() {
119
- var cnames = [];
120
 
121
- jQuery('#cdn_cnames input[type=text]').each(function() {
122
- var cname = jQuery(this).val();
123
 
124
- if (cname) {
125
- var match = /^\*\.(.*)$/.exec(cname);
126
 
127
- if (match) {
128
- cnames = [];
129
- for (var i = 1; i <= 10; i++) {
130
- cnames.push('cdn' + i + '.' + match[1]);
131
- }
132
- return false;
133
- }
134
 
135
- cnames.push(cname);
136
- }
137
- });
138
 
139
- return cnames;
140
  }
141
 
142
  function w3tc_cdn_cnames_assign() {
143
- var li = jQuery('#cdn_cnames li'), size = li.size();
144
-
145
- if (size > 1) {
146
- li.eq(0).find('.cdn_cname_delete').show();
147
- } else {
148
- li.eq(0).find('.cdn_cname_delete').hide();
149
- }
150
-
151
- jQuery(li).each(function(index) {
152
- var label = '';
153
-
154
- if (size > 1) {
155
- switch (index) {
156
- case 0:
157
- label = '(reserved for CSS)';
158
- break;
159
-
160
- case 1:
161
- label = '(reserved for JS in <head>)';
162
- break;
163
-
164
- case 2:
165
- label = '(reserved for JS after <body>)';
166
- break;
167
-
168
- case 3:
169
- label = '(reserved for JS before </body>)';
170
- break;
171
- }
172
- }
173
-
174
- jQuery(this).find('span').text(label);
175
- });
176
  }
177
 
178
  function w3tc_toggle(name, check) {
179
- if (check === undefined) {
180
- check = true;
181
- }
182
-
183
- var id = '#' + name, cls = '.' + name;
184
-
185
- jQuery(cls).click(function() {
186
- var checked = check;
187
-
188
- jQuery(cls).each(function() {
189
- var _checked = jQuery(this).is(':checked');
190
-
191
- if ((check && !_checked) || (!check && _checked)) {
192
- checked = !check;
193
-
194
- return false;
195
- }
196
- });
197
-
198
- if (checked) {
199
- jQuery(id).attr('checked', 'checked');
200
- } else {
201
- jQuery(id).removeAttr('checked');
202
- }
203
- });
204
-
205
- jQuery(id).click(function() {
206
- var checked = jQuery(this).is(':checked');
207
- jQuery(cls).each(function() {
208
- if (checked) {
209
- jQuery(this).attr('checked', 'checked');
210
- } else {
211
- jQuery(this).removeAttr('checked');
212
- }
213
- });
214
- });
215
  }
216
 
217
  function w3tc_toggle2(name, dependent_ids) {
218
- var id = '#' + name, dependants = '', n;
219
- for (n = 0; n < dependent_ids.length; n++)
220
- dependants += (n > 0 ? ',' : '') + '#' + dependent_ids[n];
221
-
222
- jQuery(dependants).click(function() {
223
- var total_checked = true;
224
-
225
- jQuery(dependants).each(function() {
226
- var current_checked = jQuery(this).is(':checked');
227
-
228
- if (!current_checked)
229
- total_checked = false;
230
- });
231
-
232
- if (total_checked) {
233
- jQuery(id).attr('checked', 'checked');
234
- } else {
235
- jQuery(id).removeAttr('checked');
236
- }
237
- });
238
-
239
- jQuery(id).click(function() {
240
- var checked = jQuery(this).is(':checked');
241
- jQuery(dependants).each(function() {
242
- if (checked) {
243
- jQuery(this).attr('checked', 'checked');
244
- } else {
245
- jQuery(this).removeAttr('checked');
246
- }
247
- });
248
- });
249
  }
250
 
251
  function w3tc_beforeupload_bind() {
252
- jQuery(window).bind('beforeunload', w3tc_beforeunload);
253
  }
254
 
255
  function w3tc_beforeupload_unbind() {
256
- jQuery(window).unbind('beforeunload', w3tc_beforeunload);
257
  }
258
 
259
  function w3tc_beforeunload() {
260
- return 'Navigate away from this page without saving your changes?';
261
  }
262
 
263
-
264
  function w3tc_starts_with(s, starts_with) {
265
  s = s.replace(/\n/g, '');
266
  s = s.replace(/\s/g, '');
267
- return s.substr(0, starts_with.length) == starts_with;
268
  }
269
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
 
 
 
 
 
 
 
 
 
 
 
 
271
 
272
  jQuery(function() {
273
- // general page
274
- jQuery('.w3tc_read_technical_info').click(function() {
275
- jQuery('.w3tc_technical_info').toggle();
276
- });
277
-
278
- jQuery('#plugin_license_key_verify').click(function() {
279
- jQuery('.w3tc_license_verification').html("Checking...");
280
-
281
- var license_key = jQuery('#plugin_license_key').val();
282
-
283
- if (!license_key) {
284
- jQuery('.w3tc_license_verification').html('Please enter an license key and try again.');
285
- return;
286
- }
287
- var params = {
288
- action: 'w3tc_verify_plugin_license_key',
289
- license_key: license_key
290
- };
291
-
292
- jQuery.get(ajaxurl, params, function(data) {
293
- if (w3tc_starts_with(data + '.', 'inactive.expired.')) {
294
- jQuery('.w3tc_license_verification').html('The license key has expired. Please renew it.');
295
- } else if (w3tc_starts_with(data + '.', 'active.')) {
296
- jQuery('.w3tc_license_verification').html('License key is correct.');
297
- } else if (w3tc_starts_with(data + '.', 'inactive.by_rooturi.activations_limit_not_reached.')) {
298
- jQuery('.w3tc_license_verification').html('License key is correct and can be activated now.');
299
- } else if (w3tc_starts_with(data + '.', 'inactive.by_rooturi.')) {
300
- jQuery('.w3tc_license_verification').html('License key is correct but already in use on another site. See the FAQ for how to enable Pro version in development mode.');
301
- } else {
302
- jQuery('.w3tc_license_verification').html('The license key is not valid. Please check it and try again.');
303
- }
304
- }).fail(function() {
305
- jQuery('.w3tc_license_verification').html('Check failed');
306
- })
307
- });
308
-
309
- // pagecache page
310
- w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').size());
311
- jQuery('#pgcache__reject__logged_roles').live('click', function(){
312
- w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').size());
313
- });
314
-
315
- if(jQuery('#pgcache__cache__nginx_handle_xml').is('*'))
316
- jQuery('#pgcache__cache__nginx_handle_xml').attr('checked',jQuery('#pgcache__cache__feed').is(':checked'));
317
-
318
- jQuery('#pgcache__cache__feed').change(function(){
319
- if(jQuery('#pgcache__cache__nginx_handle_xml').is('*'))
320
- jQuery('#pgcache__cache__nginx_handle_xml').attr('checked',this.checked);
321
- });
322
-
323
- // browsercache page
324
- w3tc_toggle2('browsercache_last_modified',
325
- ['browsercache__cssjs__last_modified', 'browsercache__html__last_modified',
326
- 'browsercache__other__last_modified']);
327
- w3tc_toggle2('browsercache_expires',
328
- ['browsercache__cssjs__expires', 'browsercache__html__expires',
329
- 'browsercache__other__expires']);
330
- w3tc_toggle2('browsercache_cache_control',
331
- ['browsercache__cssjs__cache__control', 'browsercache__html__cache__control',
332
- 'browsercache__other__cache__control']);
333
- w3tc_toggle2('browsercache_etag',
334
- ['browsercache__cssjs__etag', 'browsercache__html__etag',
335
- 'browsercache__other__etag']);
336
- w3tc_toggle2('browsercache_w3tc',
337
- ['browsercache__cssjs__w3tc', 'browsercache__html__w3tc',
338
- 'browsercache__other__w3tc']);
339
- w3tc_toggle2('browsercache_compression',
340
- ['browsercache__cssjs__compression', 'browsercache__html__compression',
341
- 'browsercache__other__compression']);
342
- w3tc_toggle2('browsercache_replace',
343
- ['browsercache__cssjs__replace', 'browsercache__other__replace']);
344
- w3tc_toggle2('browsercache_querystring',
345
- ['browsercache__cssjs__querystring', 'browsercache__other__querystring']);
346
- w3tc_toggle2('browsercache_nocookies',
347
- ['browsercache__cssjs__nocookies', 'browsercache__other__nocookies']);
348
-
349
- // minify page
350
- w3tc_input_enable('.html_enabled', jQuery('#minify__html__enable:checked').size());
351
- w3tc_input_enable('.js_enabled', jQuery('#minify__js__enable:checked').size());
352
- w3tc_input_enable('.css_enabled', jQuery('#minify__css__enable:checked').size());
353
-
354
- w3tc_minify_js_theme(jQuery('#js_themes').val());
355
- w3tc_minify_css_theme(jQuery('#css_themes').val());
356
-
357
- jQuery('#minify__html__enable').click(function() {
358
- w3tc_input_enable('.html_enabled', this.checked);
359
- });
360
-
361
- jQuery('#minify__js__enable').click(function() {
362
- w3tc_input_enable('.js_enabled', jQuery(this).is(':checked'));
363
- });
364
-
365
- jQuery('#minify__css__enable').click(function() {
366
- w3tc_input_enable('.css_enabled', jQuery(this).is(':checked'));
367
- });
368
-
369
- jQuery('.js_file_verify,.css_file_verify').live('click', function() {
370
- var file = jQuery(this).parents('li').find(':text').val();
371
- if (file == '') {
372
- alert('Empty URI');
373
- } else {
374
- var url = '';
375
- if (/^https?:\/\//.test(file)) {
376
- url = file;
377
- } else {
378
- url = '/' + file;
379
- }
380
- w3tc_popup(url, 'file_verify');
381
- }
382
- });
383
-
384
- jQuery('.js_file_template').live('change', function() {
385
- jQuery(this).parents('li').find(':text').attr('name', 'js_files[' + jQuery('#js_themes').val() + '][' + jQuery(this).val() + '][' + jQuery(this).parents('li').find('.js_file_location').val() + '][]');
386
- });
387
-
388
- jQuery('.css_file_template').live('change', function() {
389
- jQuery(this).parents('li').find(':text').attr('name', 'css_files[' + jQuery('#css_themes').val() + '][' + jQuery(this).val() + '][include][]');
390
- });
391
-
392
- jQuery('.js_file_location').live('change', function() {
393
- jQuery(this).parents('li').find(':text').attr('name', 'js_files[' + jQuery('#js_themes').val() + '][' + jQuery(this).parents('li').find('.js_file_template').val() + '][' + jQuery(this).val() + '][]');
394
- });
395
-
396
- jQuery('.js_file_delete').live('click', function() {
397
- var parent = jQuery(this).parents('li');
398
- if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this JS file?')) {
399
- parent.remove();
400
- w3tc_minify_js_file_clear();
401
- w3tc_beforeupload_bind();
402
- }
403
-
404
- return false;
405
- });
406
-
407
- jQuery('.css_file_delete').live('click', function() {
408
- var parent = jQuery(this).parents('li');
409
- if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this CSS file?')) {
410
- parent.remove();
411
- w3tc_minify_css_file_clear();
412
- w3tc_beforeupload_bind();
413
- }
414
-
415
- return false;
416
- });
417
-
418
- jQuery('#js_file_add').click(function() {
419
- w3tc_minify_js_file_add(jQuery('#js_themes').val(), 'default', 'include', '');
420
- });
421
-
422
- jQuery('#css_file_add').click(function() {
423
- w3tc_minify_css_file_add(jQuery('#css_themes').val(), 'default', '');
424
- });
425
-
426
- jQuery('#js_themes').change(function() {
427
- w3tc_minify_js_theme(jQuery(this).val());
428
- });
429
-
430
- jQuery('#css_themes').change(function() {
431
- w3tc_minify_css_theme(jQuery(this).val());
432
- });
433
-
434
- jQuery('#minify_form').submit(function() {
435
- var js = [], css = [], invalid_js = [], invalid_css = [], duplicate = false, query_js = [], query_css = [];
436
-
437
- jQuery('#js_files :text').each(function() {
438
- var v = jQuery(this).val(), n = jQuery(this).attr('name'), c = v + n, g = '';
439
- var match = /js_files\[([a-z0-9_\/]+)\]/.exec(n);
440
- if (match) {
441
- g = '[' + jQuery('#js_themes option[value=' + match[1] + ']').text() + '] ' + v;
442
- }
443
- if (v != '') {
444
- for (var i = 0; i < js.length; i++) {
445
- if (js[i] == c) {
446
- duplicate = true;
447
- break;
448
- }
449
- }
450
-
451
- js.push(c);
452
-
453
- var qindex = v.indexOf('?');
454
- if (qindex != -1) {
455
- if (!/^(https?:)?\/\//.test(v)) {
456
- query_js.push(g);
457
- }
458
- v = v.substr(0, qindex);
459
- } else if (!/\.js$/.test(v)) {
460
- invalid_js.push(g);
461
- }
462
- }
463
- });
464
-
465
- jQuery('#css_files :text').each(function() {
466
- var v = jQuery(this).val(), n = jQuery(this).attr('name'), c = v + n, g = '';
467
- var match = /css_files\[([a-z0-9_\/]+)\]/.exec(n);
468
- if (match) {
469
- g = '[' + jQuery('#css_themes option[value=' + match[1] + ']').text() + '] ' + v;
470
- }
471
- if (v != '') {
472
- for (var i = 0; i < css.length; i++) {
473
- if (css[i] == c) {
474
- duplicate = true;
475
- break;
476
- }
477
- }
478
-
479
- css.push(c);
480
-
481
- var qindex = v.indexOf('?');
482
- if (qindex != -1) {
483
- if (!/^(https?:)?\/\//.test(v)) {
484
- query_css.push(g);
485
- }
486
- v = v.substr(0, qindex);
487
- } else if (!/\.css$/.test(v)) {
488
- invalid_css.push(g);
489
- }
490
- }
491
- });
492
-
493
- if (jQuery('#js_enabled:checked').size()) {
494
- if (invalid_js.length && !confirm('The following files have invalid JS file extension:\r\n\r\n' + invalid_js.join('\r\n') + '\r\n\r\nAre you confident these files contain valid JS code?')) {
495
- return false;
496
- }
497
-
498
- if (query_js.length) {
499
- alert('We recommend using the entire URI for files with query string (GET) variables. You entered:\r\n\r\n' + query_js.join('\r\n'));
500
- return false;
501
- }
502
- }
503
-
504
- if (jQuery('#css_enabled:checked').size()) {
505
- if (invalid_css.length && !confirm('The following files have invalid CSS file extension:\r\n\r\n' + invalid_css.join('\r\n') + '\r\n\r\nAre you confident these files contain valid CSS code?')) {
506
- return false;
507
- }
508
-
509
- if (query_css.length) {
510
- alert('We recommend using the entire URI for files with query string (GET) variables. You entered:\r\n\r\n' + query_css.join('\r\n'));
511
- return false;
512
- }
513
- }
514
-
515
- if (duplicate) {
516
- alert('Duplicate files have been found in your minify settings, please check your settings and re-save.');
517
- return false;
518
- }
519
-
520
- return true;
521
- });
522
-
523
- // CDN
524
- jQuery('.w3tc-tab').click(function() {
525
- jQuery('.w3tc-tab-content').hide();
526
- jQuery(this.rel).show();
527
- });
528
-
529
- w3tc_input_enable('#cdn_reject_roles input[type=checkbox]', jQuery('#cdn__reject__logged_roles:checked').size());
530
- jQuery('#cdn__reject__logged_roles').live('click', function() {
531
- w3tc_input_enable('#cdn_reject_roles input[type=checkbox]', jQuery('#cdn__reject__logged_roles:checked').size());
532
- });
533
-
534
- jQuery('#cdn_export_library').click(function() {
535
- w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_export_library&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_export_library');
536
- });
537
-
538
- jQuery('#cdn_import_library').click(function() {
539
- w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_import_library&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_import_library');
540
- });
541
-
542
- jQuery('#cdn_queue').click(function() {
543
- w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_queue&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_queue');
544
- });
545
-
546
- jQuery('#cdn_rename_domain').click(function() {
547
- w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_rename_domain&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_rename_domain');
548
- });
549
-
550
- jQuery('#cdn_purge').click(function() {
551
- w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_purge&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_purge');
552
- });
553
-
554
- jQuery('.cdn_export').click(function() {
555
- var metadata = jQuery(this).metadata();
556
- w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_export&cdn_export_type=' + metadata.type + '&_wpnonce=' + metadata.nonce, 'cdn_export_' + metadata.type);
557
- });
558
-
559
- jQuery('#validate_cdn_key').click(function() {
560
- var me = jQuery(this);
561
- var metadata = me.metadata();
562
- w3tc_validate_cdn_key_result(metadata.type, metadata.nonce);
563
- });
564
-
565
- jQuery('#use_poll_zone').click(function() {
566
- var me = jQuery(this);
567
- var metadata = me.metadata();
568
- w3tc_use_poll_zone(metadata.type, metadata.nonce);
569
- });
570
-
571
- jQuery('#cdn_test').click(function() {
572
- var me = jQuery(this);
573
- var metadata = me.metadata();
574
- var cnames = w3tc_cdn_get_cnames();
575
- var params = {
576
- w3tc_cdn_test: 1,
577
- _wpnonce: metadata.nonce
578
- };
579
-
580
- switch (metadata.type) {
581
- case 'ftp':
582
- jQuery.extend(params, {
583
- engine: 'ftp',
584
- 'config[host]': jQuery('#cdn_ftp_host').val(),
585
- 'config[type]': jQuery('#cdn_ftp_type').val(),
586
- 'config[user]': jQuery('#cdn_ftp_user').val(),
587
- 'config[path]': jQuery('#cdn_ftp_path').val(),
588
- 'config[pass]': jQuery('#cdn_ftp_pass').val(),
589
- 'config[pasv]': jQuery('#cdn_ftp_pasv:checked').size()
590
- });
591
-
592
- if (cnames.length) {
593
- params['config[domain][]'] = cnames;
594
- }
595
- break;
596
-
597
- case 's3':
598
- jQuery.extend(params, {
599
- engine: 's3',
600
- 'config[key]': jQuery('#cdn_s3_key').val(),
601
- 'config[secret]': jQuery('#cdn_s3_secret').val(),
602
- 'config[bucket]': jQuery('#cdn_s3_bucket').val(),
603
- 'config[bucket_location]': jQuery('#cdn_s3_bucket_location').val()
604
- });
605
-
606
- if (cnames.length) {
607
- params['config[cname][]'] = cnames;
608
- }
609
- break;
610
-
611
- case 'cf':
612
- jQuery.extend(params, {
613
- engine: 'cf',
614
- 'config[key]': jQuery('#cdn_cf_key').val(),
615
- 'config[secret]': jQuery('#cdn_cf_secret').val(),
616
- 'config[bucket]': jQuery('#cdn_cf_bucket').val(),
617
- 'config[bucket_location]': jQuery('#cdn_cf_bucket_location').val(),
618
- 'config[id]': jQuery('#cdn_cf_id').val()
619
- });
620
-
621
- if (cnames.length) {
622
- params['config[cname][]'] = cnames;
623
- }
624
- break;
625
-
626
- case 'cf2':
627
- jQuery.extend(params, {
628
- engine: 'cf2',
629
- 'config[key]': jQuery('#cdn_cf2_key').val(),
630
- 'config[secret]': jQuery('#cdn_cf2_secret').val(),
631
- 'config[origin]': jQuery('#cdn_cf2_origin').val(),
632
- 'config[id]': jQuery('#cdn_cf2_id').val()
633
- });
634
-
635
- if (cnames.length) {
636
- params['config[cname][]'] = cnames;
637
- }
638
- break;
639
-
640
- case 'rscf':
641
- jQuery.extend(params, {
642
- engine: 'rscf',
643
- 'config[user]': jQuery('#cdn_rscf_user').val(),
644
- 'config[key]': jQuery('#cdn_rscf_key').val(),
645
- 'config[location]': jQuery('#cdn_rscf_location').val(),
646
- 'config[container]': jQuery('#cdn_rscf_container').val(),
647
- 'config[id]': jQuery('#cdn_rscf_id').val()
648
- });
649
-
650
- if (cnames.length) {
651
- params['config[cname][]'] = cnames;
652
- }
653
- break;
654
-
655
- case 'azure':
656
- jQuery.extend(params, {
657
- engine: 'azure',
658
- 'config[user]': jQuery('#cdn_azure_user').val(),
659
- 'config[key]': jQuery('#cdn_azure_key').val(),
660
- 'config[container]': jQuery('#cdn_azure_container').val()
661
- });
662
-
663
- if (cnames.length) {
664
- params['config[cname][]'] = cnames;
665
- }
666
- break;
667
-
668
- case 'mirror':
669
- jQuery.extend(params, {
670
- engine: 'mirror'
671
- });
672
-
673
- if (cnames.length) {
674
- params['config[domain][]'] = cnames;
675
- }
676
- break;
677
-
678
- case 'cotendo':
679
- var zones = [], zones_val = jQuery('#cdn_cotendo_zones').val();
680
-
681
- if (zones_val) {
682
- zones = zones_val.split(/[\r\n,;]+/);
683
- }
684
-
685
- jQuery.extend(params, {
686
- engine: 'cotendo',
687
- 'config[username]': jQuery('#cdn_cotendo_username').val(),
688
- 'config[password]': jQuery('#cdn_cotendo_password').val()
689
- });
690
-
691
- if (zones.length) {
692
- params['config[zones][]'] = zones;
693
- }
694
-
695
- if (cnames.length) {
696
- params['config[domain][]'] = cnames;
697
- }
698
- break;
699
- case 'akamai':
700
- var emails = [], emails_val = jQuery('#cdn_akamai_email_notification').val();
701
-
702
- if (emails_val) {
703
- emails = emails_val.split(/[\r\n,;]+/);
704
- }
705
-
706
- jQuery.extend(params, {
707
- engine: 'akamai',
708
- 'config[username]': jQuery('#cdn_akamai_username').val(),
709
- 'config[password]': jQuery('#cdn_akamai_password').val(),
710
- 'config[zone]': jQuery('#cdn_akamai_zone').val()
711
- });
712
-
713
- if (emails.length) {
714
- params['config[email_notification][]'] = emails;
715
- }
716
-
717
- if (cnames.length) {
718
- params['config[domain][]'] = cnames;
719
- }
720
- break;
721
-
722
- case 'edgecast':
723
- jQuery.extend(params, {
724
- engine: 'edgecast',
725
- 'config[account]': jQuery('#cdn_edgecast_account').val(),
726
- 'config[token]': jQuery('#cdn_edgecast_token').val()
727
- });
728
-
729
- if (cnames.length) {
730
- params['config[domain][]'] = cnames;
731
- }
732
- break;
733
-
734
- case 'att':
735
- jQuery.extend(params, {
736
- engine: 'att',
737
- 'config[account]': jQuery('#cdn_att_account').val(),
738
- 'config[token]': jQuery('#cdn_att_token').val()
739
- });
740
-
741
- if (cnames.length) {
742
- params['config[domain][]'] = cnames;
743
- }
744
- break;
745
- default:
746
- jQuery.extend(params, {
747
- engine: metadata.type
748
- });
749
- }
750
-
751
- var status = jQuery('#cdn_test_status');
752
- status.removeClass('w3tc-error');
753
- status.removeClass('w3tc-success');
754
- status.addClass('w3tc-process');
755
-
756
- var status2 = jQuery('#cdn_create_container_status');
757
- status2.removeClass('w3tc-error');
758
- status2.removeClass('w3tc-success');
759
- status2.html('');
760
-
761
- status.html('Testing...');
762
-
763
- jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
764
- status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
765
- status.html(data.error);
766
- }, 'json').fail(function() {
767
- status.addClass('w3tc-error');
768
- status.html('Test failed');
769
- });
770
- });
771
-
772
- jQuery('#cdn_create_container').live('click', function() {
773
- var me = jQuery(this);
774
- var metadata = me.metadata();
775
- var cnames = w3tc_cdn_get_cnames();
776
- var container_id = null;
777
- var params = {
778
- w3tc_cdn_create_container: 1,
779
- _wpnonce: metadata.nonce
780
- };
781
-
782
- switch (metadata.type) {
783
- case 's3':
784
- jQuery.extend(params, {
785
- engine: 's3',
786
- 'config[key]': jQuery('#cdn_s3_key').val(),
787
- 'config[secret]': jQuery('#cdn_s3_secret').val(),
788
- 'config[bucket]': jQuery('#cdn_s3_bucket').val(),
789
- 'config[bucket_location]': jQuery('#cdn_s3_bucket_location').val()
790
- });
791
-
792
- if (cnames.length) {
793
- params['config[cname][]'] = cnames;
794
- }
795
- break;
796
-
797
- case 'cf':
798
- container_id = jQuery('#cdn_cf_id');
799
-
800
- jQuery.extend(params, {
801
- engine: 'cf',
802
- 'config[key]': jQuery('#cdn_cf_key').val(),
803
- 'config[secret]': jQuery('#cdn_cf_secret').val(),
804
- 'config[bucket]': jQuery('#cdn_cf_bucket').val(),
805
- 'config[bucket_location]': jQuery('#cdn_cf_bucket_location').val()
806
- });
807
-
808
- if (cnames.length) {
809
- params['config[cname][]'] = cnames;
810
- }
811
- break;
812
-
813
- case 'cf2':
814
- container_id = jQuery('#cdn_cf2_id');
815
-
816
- jQuery.extend(params, {
817
- engine: 'cf2',
818
- 'config[key]': jQuery('#cdn_cf2_key').val(),
819
- 'config[secret]': jQuery('#cdn_cf2_secret').val(),
820
- 'config[origin]': jQuery('#cdn_cf2_origin').val(),
821
- 'config[bucket_location]': jQuery('#cdn_cf2_bucket_location').val()
822
- });
823
-
824
- if (cnames.length) {
825
- params['config[cname][]'] = cnames;
826
- }
827
- break;
828
-
829
- case 'rscf':
830
- container_id = jQuery('#cdn_cnames input[type=text]:first');
831
-
832
- jQuery.extend(params, {
833
- engine: 'rscf',
834
- 'config[user]': jQuery('#cdn_rscf_user').val(),
835
- 'config[key]': jQuery('#cdn_rscf_key').val(),
836
- 'config[location]': jQuery('#cdn_rscf_location').val(),
837
- 'config[container]': jQuery('#cdn_rscf_container').val()
838
- });
839
-
840
- if (cnames.length) {
841
- params['config[cname][]'] = cnames;
842
- }
843
- break;
844
-
845
- case 'azure':
846
- jQuery.extend(params, {
847
- engine: 'azure',
848
- 'config[user]': jQuery('#cdn_azure_user').val(),
849
- 'config[key]': jQuery('#cdn_azure_key').val(),
850
- 'config[container]': jQuery('#cdn_azure_container').val()
851
- });
852
-
853
- if (cnames.length) {
854
- params['config[cname][]'] = cnames;
855
- }
856
- break;
857
- }
858
-
859
- var status = jQuery('#cdn_create_container_status');
860
- status.removeClass('w3tc-error');
861
- status.removeClass('w3tc-success');
862
- status.addClass('w3tc-process');
 
 
863
 
864
  var status2 = jQuery('#cdn_test_status');
865
- status2.removeClass('w3tc-error');
866
- status2.removeClass('w3tc-success');
867
- status2.html('');
868
-
869
- status.html('Creating...');
870
-
871
- jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
872
- status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
873
- status.html(data.error);
874
-
875
- if (container_id && container_id.size() && data.container_id) {
876
- container_id.val(data.container_id);
877
- }
878
- }, 'json').fail(function() {
879
- status.addClass('w3tc-error');
880
- status.html('failed');
881
- });
882
- });
883
-
884
- jQuery('#memcached_test').click(function() {
885
- var status = jQuery('#memcached_test_status');
886
- status.removeClass('w3tc-error');
887
- status.removeClass('w3tc-success');
888
- status.addClass('w3tc-process');
889
- status.html('Testing...');
890
- jQuery.post('admin.php?page=w3tc_dashboard', {
891
- w3tc_test_memcached: 1,
892
- servers: jQuery('#memcached_servers').val(),
893
- _wpnonce: jQuery(this).metadata().nonce
894
- }, function(data) {
895
- status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
896
- status.html(data.error);
897
- }, 'json')
898
- .fail(function() {
899
- status.addClass('w3tc-error');
900
- status.html('Request failed');
901
- });
902
- });
903
-
904
- jQuery('.w3tc_common_redis_test').click(function() {
905
- var status = jQuery('.w3tc_common_redis_test_result');
906
- status.removeClass('w3tc-error');
907
- status.removeClass('w3tc-success');
908
- status.addClass('w3tc-process');
909
- status.html('Testing...');
910
- jQuery.post('admin.php?page=w3tc_dashboard', {
911
- w3tc_test_redis: 1,
912
- servers: jQuery('#redis_servers').val(),
913
- dbid : jQuery('#redis_dbid').val(),
914
- password : jQuery('#redis_password').val(),
915
- _wpnonce: jQuery(this).metadata().nonce
916
- }, function(data) {
917
- status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
918
- status.html(data.error);
919
- }, 'json')
920
- .fail(function() {
921
- status.addClass('w3tc-error');
922
- status.html('Request failed');
923
- });
924
- });
925
-
926
- jQuery('.minifier_test').click(function() {
927
- var me = jQuery(this);
928
- var metadata = me.metadata();
929
- var params = {
930
- w3tc_test_minifier: 1,
931
- _wpnonce: metadata.nonce
932
- };
933
-
934
- switch (metadata.type) {
935
- case 'yuijs':
936
- jQuery.extend(params, {
937
- engine: 'yuijs',
938
- path_java: jQuery('#minify__yuijs__path__java').val(),
939
- path_jar: jQuery('#minify__yuijs__path__jar').val()
940
- });
941
- break;
942
-
943
- case 'yuicss':
944
- jQuery.extend(params, {
945
- engine: 'yuicss',
946
- path_java: jQuery('#minify__yuicss__path__java').val(),
947
- path_jar: jQuery('#minify__yuicss__path__jar').val()
948
- });
949
- break;
950
-
951
- case 'ccjs':
952
- jQuery.extend(params, {
953
- engine: 'ccjs',
954
- path_java: jQuery('#minify__ccjs__path__java').val(),
955
- path_jar: jQuery('#minify__ccjs__path__jar').val()
956
- });
957
- break;
958
- case 'googleccjs':
959
- jQuery.extend(params, {
960
- engine: 'googleccjs'
961
- });
962
- break;
963
- }
964
-
965
- var status = me.next();
966
- status.removeClass('w3tc-error');
967
- status.removeClass('w3tc-success');
968
- status.addClass('w3tc-process');
969
- status.html('Testing...');
970
-
971
- jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
972
- status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
973
- status.html(data.error);
974
- }, 'json');
975
- });
976
-
977
- // CDN cnames
978
- jQuery('body').on('click', '#cdn_cname_add', function() {
979
- jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
980
- w3tc_cdn_cnames_assign();
981
- jQuery(this).trigger("size_change");
982
- });
983
-
984
- jQuery('.cdn_cname_delete').live('click', function() {
985
- var p = jQuery(this).parent();
986
- if (p.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this CNAME?')) {
987
- p.remove();
988
- w3tc_cdn_cnames_assign();
989
- w3tc_beforeupload_bind();
990
- }
991
- });
992
-
993
- jQuery('#cdn_form').submit(function() {
994
- var cnames = [], ret = true;
995
-
996
- jQuery('#cdn_cnames input[type=text]').each(function() {
997
- var cname = jQuery(this).val();
998
-
999
- if (cname) {
1000
- if (jQuery.inArray(cname, cnames) != -1) {
1001
- alert('CNAME "' + cname + '" already exists.');
1002
- ret = false;
1003
-
1004
- return false;
1005
- } else {
1006
- cnames.push(cname);
1007
- }
1008
- }
1009
- });
1010
-
1011
- return ret;
1012
- });
1013
-
1014
-
1015
- // mobile tab
1016
- jQuery('#mobile_form').submit(function() {
1017
- var error = false;
1018
-
1019
- jQuery('#mobile_groups li').each(function() {
1020
- if (jQuery(this).find(':checked').size()) {
1021
- var group = jQuery(this).find('.mobile_group').text();
1022
- var theme = jQuery(this).find(':selected').val();
1023
- var redirect = jQuery(this).find('input[type=text]').val();
1024
- var agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1025
-
1026
- jQuery('#mobile_groups li').each(function() {
1027
- if (jQuery(this).find(':checked').size()) {
1028
- var compare_group = jQuery(this).find('.mobile_group').text();
1029
- if (compare_group != group) {
1030
- var compare_theme = jQuery(this).find(':selected').val();
1031
- var compare_redirect = jQuery(this).find('input[type=text]').val();
1032
- var compare_agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1033
-
1034
- if (compare_redirect == '' && redirect == '' && compare_theme != '' && compare_theme == theme) {
1035
- alert('Duplicate theme "' + compare_theme + '" found in the group "' + group + '".');
1036
- error = true;
1037
- return false;
1038
- }
1039
-
1040
- if (compare_redirect != '' && compare_redirect == redirect) {
1041
- alert('Duplicate redirect "' + compare_redirect + '" found in the group "' + group + '".');
1042
- error = true;
1043
- return false;
1044
- }
1045
-
1046
- jQuery.each(compare_agents, function(index, value) {
1047
- if (jQuery.inArray(value, agents) != -1) {
1048
- alert('Duplicate stem "' + value + '" found in the group "' + compare_group + '".');
1049
- error = true;
1050
- return false;
1051
- }
1052
- });
1053
- }
1054
- }
1055
- });
1056
-
1057
- if (error) {
1058
- return false;
1059
- }
1060
- }
1061
- });
1062
-
1063
- if (error) {
1064
- return false;
1065
- }
1066
- });
1067
-
1068
- jQuery('#mobile_add').click(function() {
1069
- var group = prompt('Enter group name (only "0-9", "a-z", "_" symbols are allowed).');
1070
-
1071
- if (group !== null) {
1072
- group = group.toLowerCase();
1073
- group = group.replace(/[^0-9a-z_]+/g, '_');
1074
- group = group.replace(/^_+/, '');
1075
- group = group.replace(/_+$/, '');
1076
-
1077
- if (group) {
1078
- var exists = false;
1079
-
1080
- jQuery('.mobile_group').each(function() {
1081
- if (jQuery(this).html() == group) {
1082
- alert('Group already exists!');
1083
- exists = true;
1084
- return false;
1085
- }
1086
- });
1087
-
1088
- if (!exists) {
1089
- var li = jQuery('<li id="mobile_group_' + group + '"><table class="form-table"><tr><th>Group name:</th><td><span class="mobile_group_number">' + (jQuery('#mobile_groups li').size() + 1) + '.</span> <span class="mobile_group">' + group + '</span> <input type="button" class="button mobile_delete" value="Delete group" /></td></tr><tr><th><label for="mobile_groups_' + group + '_enabled">Enabled:</label></th><td><input type="hidden" name="mobile_groups[' + group + '][enabled]" value="0" /><input id="mobile_groups_' + group + '_enabled" type="checkbox" name="mobile_groups[' + group + '][enabled]" value="1" checked="checked" /></td></tr><tr><th><label for="mobile_groups_' + group + '_theme">Theme:</label></th><td><select id="mobile_groups_' + group + '_theme" name="mobile_groups[' + group + '][theme]"><option value="">-- Pass-through --</option></select><br /><span class="description">Assign this group of user agents to a specific them. Leaving this option "Active Theme" allows any plugins you have (e.g. mobile plugins) to properly handle requests for these user agents. If the "redirect users to" field is not empty, this setting is ignored.</span></td></tr><tr><th><label for="mobile_groups_' + group + '_redirect">Redirect users to:</label></th><td><input id="mobile_groups_' + group + '_redirect" type="text" name="mobile_groups[' + group + '][redirect]" value="" size="60" /><br /><span class="description">A 302 redirect is used to send this group of users to another hostname (domain); recommended if a 3rd party service provides a mobile version of your site.</span></td></tr><tr><th><label for="mobile_groups_' + group + '_agents">User agents:</label></th><td><textarea id="mobile_groups_' + group + '_agents" name="mobile_groups[' + group + '][agents]" rows="10" cols="50"></textarea><br /><span class="description">Specify the user agents for this group.</span></td></tr></table></li>');
1090
- var select = li.find('select');
1091
-
1092
- jQuery.each(mobile_themes, function(index, value) {
1093
- select.append(jQuery('<option />').val(index).html(value));
1094
- });
1095
-
1096
- jQuery('#mobile_groups').append(li);
1097
- w3tc_mobile_groups_clear();
1098
- window.location.hash = '#mobile_group_' + group;
1099
- li.find('textarea').focus();
1100
- }
1101
- } else {
1102
- alert('Empty group name!');
1103
- }
1104
- }
1105
- });
1106
-
1107
- jQuery('.mobile_delete').live('click', function() {
1108
- if (confirm('Are you sure want to delete this group?')) {
1109
- jQuery(this).parents('#mobile_groups li').remove();
1110
- w3tc_mobile_groups_clear();
1111
- w3tc_beforeupload_bind();
1112
- }
1113
- });
1114
-
1115
- w3tc_mobile_groups_clear();
1116
-
1117
- // referrer tab
1118
- jQuery('#referrer_form').submit(function() {
1119
- var error = false;
1120
-
1121
- jQuery('#referrer_groups li').each(function() {
1122
- if (jQuery(this).find(':checked').size()) {
1123
- var group = jQuery(this).find('.referrer_group').text();
1124
- var theme = jQuery(this).find(':selected').val();
1125
- var redirect = jQuery(this).find('input[type=text]').val();
1126
- var agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1127
-
1128
- jQuery('#referrer_groups li').each(function() {
1129
- if (jQuery(this).find(':checked').size()) {
1130
- var compare_group = jQuery(this).find('.referrer_group').text();
1131
- if (compare_group != group) {
1132
- var compare_theme = jQuery(this).find(':selected').val();
1133
- var compare_redirect = jQuery(this).find('input[type=text]').val();
1134
- var compare_agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1135
-
1136
- if (compare_redirect == '' && redirect == '' && compare_theme != '' && compare_theme == theme) {
1137
- alert('Duplicate theme "' + compare_theme + '" found in the group "' + group + '".');
1138
- error = true;
1139
- return false;
1140
- }
1141
-
1142
- if (compare_redirect != '' && compare_redirect == redirect) {
1143
- alert('Duplicate redirect "' + compare_redirect + '" found in the group "' + group + '".');
1144
- error = true;
1145
- return false;
1146
- }
1147
-
1148
- jQuery.each(compare_agents, function(index, value) {
1149
- if (jQuery.inArray(value, agents) != -1) {
1150
- alert('Duplicate stem "' + value + '" found in the group "' + compare_group + '".');
1151
- error = true;
1152
- return false;
1153
- }
1154
- });
1155
- }
1156
- }
1157
- });
1158
-
1159
- if (error) {
1160
- return false;
1161
- }
1162
- }
1163
- });
1164
-
1165
- if (error) {
1166
- return false;
1167
- }
1168
- });
1169
-
1170
- jQuery('#referrer_add').click(function() {
1171
- var group = prompt('Enter group name (only "0-9", "a-z", "_" symbols are allowed).');
1172
-
1173
- if (group !== null) {
1174
- group = group.toLowerCase();
1175
- group = group.replace(/[^0-9a-z_]+/g, '_');
1176
- group = group.replace(/^_+/, '');
1177
- group = group.replace(/_+$/, '');
1178
-
1179
- if (group) {
1180
- var exists = false;
1181
-
1182
- jQuery('.referrer_group').each(function() {
1183
- if (jQuery(this).html() == group) {
1184
- alert('Group already exists!');
1185
- exists = true;
1186
- return false;
1187
- }
1188
- });
1189
-
1190
- if (!exists) {
1191
- var li = jQuery('<li id="referrer_group_' + group + '"><table class="form-table"><tr><th>Group name:</th><td><span class="referrer_group_number">' + (jQuery('#referrer_groups li').size() + 1) + '.</span> <span class="referrer_group">' + group + '</span> <input type="button" class="button referrer_delete" value="Delete group" /></td></tr><tr><th><label for="referrer_groups_' + group + '_enabled">Enabled:</label></th><td><input type="hidden" name="referrer_groups[' + group + '][enabled]" value="0" /><input id="referrer_groups_' + group + '_enabled" type="checkbox" name="referrer_groups[' + group + '][enabled]" value="1" checked="checked" /></td></tr><tr><th><label for="referrer_groups_' + group + '_theme">Theme:</label></th><td><select id="referrer_groups_' + group + '_theme" name="referrer_groups[' + group + '][theme]"><option value="">-- Pass-through --</option></select><br /><span class="description">Assign this group of referrers to a specific them. Leaving this option "Active Theme" allows any plugins you have (e.g. referrer plugins) to properly handle requests for these referrers. If the "redirect users to" field is not empty, this setting is ignored.</span></td></tr><tr><th><label for="referrer_groups_' + group + '_redirect">Redirect users to:</label></th><td><input id="referrer_groups_' + group + '_redirect" type="text" name="referrer_groups[' + group + '][redirect]" value="" size="60" /><br /><span class="description">A 302 redirect is used to send this group of users to another hostname (domain); recommended if a 3rd party service provides a referrer version of your site.</span></td></tr><tr><th><label for="referrer_groups_' + group + '_referrers">Referrers:</label></th><td><textarea id="referrer_groups_' + group + '_referrers" name="referrer_groups[' + group + '][referrers]" rows="10" cols="50"></textarea><br /><span class="description">Specify the referrers for this group.</span></td></tr></table></li>');
1192
- var select = li.find('select');
1193
-
1194
- jQuery.each(referrer_themes, function(index, value) {
1195
- select.append(jQuery('<option />').val(index).html(value));
1196
- });
1197
-
1198
- jQuery('#referrer_groups').append(li);
1199
- w3tc_referrer_groups_clear();
1200
- window.location.hash = '#referrer_group_' + group;
1201
- li.find('textarea').focus();
1202
- }
1203
- } else {
1204
- alert('Empty group name!');
1205
- }
1206
- }
1207
- });
1208
-
1209
- jQuery('.referrer_delete').live('click', function() {
1210
- if (confirm('Are you sure want to delete this group?')) {
1211
- jQuery(this).parents('#referrer_groups li').remove();
1212
- w3tc_referrer_groups_clear();
1213
- w3tc_beforeupload_bind();
1214
- }
1215
- });
1216
-
1217
- w3tc_referrer_groups_clear();
1218
-
1219
- // add sortable
1220
- if (jQuery.ui && jQuery.ui.sortable) {
1221
- jQuery('#js_files,#css_files').sortable({
1222
- axis: 'y',
1223
- stop: function() {
1224
- jQuery(this).find('li').each(function(index) {
1225
- jQuery(this).find('td:eq(0)').html((index + 1) + '.');
1226
- });
1227
- }
1228
- });
1229
-
1230
- jQuery('#cdn_cnames').sortable({
1231
- axis: 'y',
1232
- stop: w3tc_cdn_cnames_assign
1233
- });
1234
-
1235
- jQuery('#mobile_groups').sortable({
1236
- axis: 'y',
1237
- stop: function() {
1238
- jQuery('#mobile_groups').find('.mobile_group_number').each(function(index) {
1239
- jQuery(this).html((index + 1) + '.');
1240
- });
1241
- }
1242
- });
1243
-
1244
- jQuery('#referrer_groups').sortable({
1245
- axis: 'y',
1246
- stop: function() {
1247
- jQuery('#referrer_groups').find('.referrer_group_number').each(function(index) {
1248
- jQuery(this).html((index + 1) + '.');
1249
- });
1250
- }
1251
- });
1252
- }
1253
-
1254
- // show hide rules
1255
- jQuery('.w3tc-show-rules').click(function() {
1256
- var btn = jQuery(this), rules = btn.parent().find('.w3tc-rules');
1257
-
1258
- if (rules.is(':visible')) {
1259
- rules.css('display', 'none');
1260
- btn.val('view code');
1261
- } else {
1262
- rules.css('display', 'block');
1263
- btn.val('hide code');
1264
- }
1265
- });
1266
-
1267
-
1268
- // show hide missing files
1269
- jQuery('.w3tc-show-required-changes').click(function() {
1270
- var btn = jQuery(this), rules = jQuery('.w3tc-required-changes');
1271
-
1272
- if (rules.is(':visible')) {
1273
- rules.css('display', 'none');
1274
- btn.val('View required changes');
1275
- } else {
1276
- rules.css('display', 'block');
1277
- btn.val('Hide required changes');
1278
- }
1279
- });
1280
-
1281
- // show hide missing files
1282
- jQuery('.w3tc-show-ftp-form').click(function() {
1283
- var btn = jQuery(this), rules = jQuery('.w3tc-ftp-form');
1284
-
1285
- if (rules.is(':visible')) {
1286
- rules.css('display', 'none');
1287
- btn.val('Update via FTP');
1288
- } else {
1289
- rules.css('display', 'block');
1290
- btn.val('Cancel FTP Update');
1291
- }
1292
- });
1293
-
1294
- // show hide missing files
1295
- jQuery('.w3tc-show-technical-info').click(function() {
1296
- var btn = jQuery(this), info = jQuery('.w3tc-technical-info');
1297
-
1298
- if (info.is(':visible')) {
1299
- info.css('display', 'none');
1300
- btn.val('Technical Information');
1301
- } else {
1302
- info.css('display', 'block');
1303
- btn.val('Hide technical information');
1304
- }
1305
- });
1306
-
1307
- // add ignore class to the ftp form elements
1308
- jQuery('#ftp_upload_form').find('input').each(function() {
1309
- jQuery(this).addClass('w3tc-ignore-change');
1310
- });
1311
-
1312
- // toggle hiddent content
1313
- jQuery('.w3tc_link_more').click(function() {
1314
- var target_class = jQuery(this).metadata().for_class;
1315
- jQuery('.' + target_class).slideToggle();
1316
- });
1317
-
1318
- // check for unsaved changes
1319
- jQuery('#w3tc input,#w3tc select,#w3tc textarea').live('change', function() {
1320
- var ignore = false;
1321
- jQuery(this).parents().andSelf().each(function() {
1322
- if (jQuery(this).hasClass('w3tc-ignore-change') || jQuery(this).hasClass('lightbox')) {
1323
- ignore = true;
1324
- return false;
1325
- }
1326
- });
1327
-
1328
- if (!ignore) {
1329
- w3tc_beforeupload_bind();
1330
- }
1331
- });
1332
-
1333
- jQuery('body').on('click', '.w3tc-button-save', w3tc_beforeupload_unbind);
1334
-
1335
-
1336
- var w3tchelp_loaded = false;
1337
- jQuery('#contextual-help-link').click(function() {
1338
- if (w3tchelp_loaded)
1339
- return;
1340
-
1341
- jQuery('.w3tchelp_content').html('<div class="w3tchelp_loading_outer">' +
1342
- '<div class="w3tc-loading w3tchelp_loading_inner"></div></div>');
1343
-
1344
- w3tchelp_loaded = true;
1345
-
1346
- jQuery.getJSON(ajaxurl, {
1347
- action: 'w3tc_ajax',
1348
- _wpnonce: w3tc_nonce,
1349
- w3tc_action: 'faq'
1350
- }, function(data) {
1351
- for (var section_id in data) {
1352
- jQuery('.w3tchelp_section_' + section_id).html(data[section_id]);
1353
- }
1354
- }).fail(function() {
1355
- jQuery('.w3tchelp_content').html('Failed to obtain data');
1356
- });
1357
- });
1358
-
1359
- // extensions page
1360
- jQuery('.w3tc_extensions_manage_input_checkall').click(function(v) {
1361
- var c = jQuery(this).is(':checked');
1362
-
1363
- jQuery('.w3tc_extensions_manage_input_checkall').prop('checked', c);
1364
- jQuery('.w3tc_extensions_input_active').each(function(index) {
1365
- if (!jQuery(this).is(':disabled'))
1366
- jQuery(this).prop('checked', c);
1367
- });
1368
- });
1369
-
1370
- // google analytics events
1371
- if (typeof ga != 'undefined') {
1372
- jQuery('.w3tc_error').each(function() {
1373
- var id = jQuery(this).attr('id');
1374
- var text = jQuery(this).text();
1375
- if (id)
1376
- ga('send', 'event', 'w3tc_error', id, text);
1377
- });
1378
- jQuery('.w3tc_note').each(function() {
1379
- var id = jQuery(this).attr('id');
1380
- var text = jQuery(this).text();
1381
- if (id)
1382
- ga('send', 'event', 'w3tc_note', id, text);
1383
- });
1384
-
1385
- jQuery('body').on('click', 'a', function() {
1386
- var url = jQuery(this).attr('href');
1387
- if (url)
1388
- ga('send', 'event', 'anchor', 'click', url, {useBeacon: true});
1389
- });
1390
-
1391
- jQuery('body').on('click', 'input[type="button"]', function() {
1392
- var name = jQuery(this).attr('name');
1393
- if (name)
1394
- ga('send', 'event', 'button', 'click', name, {useBeacon: true});
1395
- });
1396
- jQuery('body').on('click', 'input[type="submit"]', function() {
1397
- var name = jQuery(this).attr('name');
1398
- var id = jQuery(this).attr('id');
1399
- if (!id)
1400
- id = name;
1401
-
1402
- if (name)
1403
- ga('send', 'event', 'button', id, name, {useBeacon: true});
1404
- });
1405
-
1406
- jQuery('body').on('click', 'input[type="checkbox"]', function() {
1407
- var name = jQuery(this).attr('name');
1408
- var action = jQuery(this).is(':checked') ? 'check' : 'uncheck';
1409
-
1410
- if (name)
1411
- ga('send', 'event', 'checkbox', action, name);
1412
- });
1413
-
1414
- jQuery('body').on('change', 'select', function() {
1415
- var name = jQuery(this).attr('name');
1416
- var value = jQuery(this).val();
1417
-
1418
- if (name && value)
1419
- ga('send', 'event', 'select', value, name);
1420
- });
1421
- }
 
 
 
 
 
 
 
 
 
 
 
1422
  });
 
1
  function w3tc_popup(url, name, width, height) {
2
+ if (width === undefined) {
3
+ width = 800;
4
+ }
5
+ if (height === undefined) {
6
+ height = 600;
7
+ }
8
+
9
+ return window.open(url, name, 'width=' + width + ',height=' + height + ',status=no,toolbar=no,menubar=no,scrollbars=yes');
10
  }
11
 
12
  function w3tc_input_enable(input, enabled) {
13
+ jQuery(input).each(function() {
14
+ var me = jQuery(this);
15
+ if (enabled) {
16
+ me.removeAttr('disabled');
17
+ } else {
18
+ me.attr('disabled', 'disabled');
19
+ }
20
+
21
+ if (enabled) {
22
+ me.next('[type=hidden]').remove();
23
+ } else {
24
+ var t = me.attr('type');
25
+ if ((t != 'radio' && t != 'checkbox') || me.is(':checked')) {
26
+ me.after(jQuery('<input />').attr({
27
+ type: 'hidden',
28
+ name: me.attr('name')
29
+ }).val(me.val()));
30
+ }
31
+ }
32
+ });
33
  }
34
 
35
  function w3tc_minify_js_file_clear() {
36
+ if (!jQuery('#js_files :visible').size()) {
37
+ jQuery('#js_files_empty').show();
38
+ } else {
39
+ jQuery('#js_files_empty').hide();
40
+ }
41
  }
42
 
43
  function w3tc_minify_css_file_clear() {
44
+ if (!jQuery('#css_files :visible').size()) {
45
+ jQuery('#css_files_empty').show();
46
+ } else {
47
+ jQuery('#css_files_empty').hide();
48
+ }
49
  }
50
 
51
  function w3tc_mobile_groups_clear() {
52
+ if (!jQuery('#mobile_groups li').size()) {
53
+ jQuery('#mobile_groups_empty').show();
54
+ } else {
55
+ jQuery('#mobile_groups_empty').hide();
56
+ }
57
  }
58
 
59
  function w3tc_referrer_groups_clear() {
60
+ if (!jQuery('#referrer_groups li').size()) {
61
+ jQuery('#referrer_groups_empty').show();
62
+ } else {
63
+ jQuery('#referrer_groups_empty').hide();
64
+ }
65
  }
66
 
67
  function w3tc_minify_js_file_add(theme, template, location, file) {
68
+ var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th>Template:</th><th colspan="3">Embed Location:</th></tr><tr><td>' + (jQuery('#js_files li').size() + 1) + '.</td><td><input class="js_enabled" type="text" name="js_files[' + theme + '][' + template + '][' + location + '][]" value="" size="70" \/></td><td><select class="js_file_template js_enabled"></select></td><td><select class="js_file_location js_enabled"><option value="include">Embed in &lt;head&gt;</option><option value="include-body">Embed after &lt;body&gt;</option><option value="include-footer">Embed before &lt;/body&gt;</option></select></td><td><input class="js_file_delete js_enabled button" type="button" value="Delete" /> <input class="js_file_verify js_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
69
+ append.find('input:text').val(file);
70
+ var select = append.find('.js_file_template');
71
+ for (var i in minify_templates[theme]) {
72
+ select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
73
+ }
74
+ select.val(template);
75
+ jQuery(append).find('.js_file_location').val(location);
76
+ jQuery('#js_files').append(append).find('li:last input:first').focus();
77
+ w3tc_minify_js_file_clear();
78
  }
79
 
80
  function w3tc_minify_css_file_add(theme, template, file) {
81
+ var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th colspan="2">Template:</th></tr><tr><td>' + (jQuery('#css_files li').size() + 1) + '.</td><td><input class="css_enabled" type="text" name="css_files[' + theme + '][' + template + '][include][]" value="" size="70" \/></td><td><select class="css_file_template css_enabled"></select></td><td><input class="css_file_delete css_enabled button" type="button" value="Delete" /></td><td><input class="css_file_verify css_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
82
+ append.find('input:text').val(file);
83
+ var select = append.find('.css_file_template');
84
+ for (var i in minify_templates[theme]) {
85
+ select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
86
+ }
87
+ select.val(template);
88
+ jQuery('#css_files').append(append).find('li:last input:first').focus();
89
+ w3tc_minify_css_file_clear();
90
  }
91
 
92
  function w3tc_minify_js_theme(theme) {
93
+ jQuery('#js_themes').val(theme);
94
+ jQuery('#js_files :text').each(function() {
95
+ var input = jQuery(this);
96
+ if (input.attr('name').indexOf('js_files[' + theme + ']') != 0) {
97
+ input.parents('li').hide();
98
+ } else {
99
+ input.parents('li').show();
100
+ }
101
+ });
102
+ w3tc_minify_js_file_clear();
103
  }
104
 
105
  function w3tc_minify_css_theme(theme) {
106
+ jQuery('#css_themes').val(theme);
107
+ jQuery('#css_files :text').each(function() {
108
+ var input = jQuery(this);
109
+ if (input.attr('name').indexOf('css_files[' + theme + ']') != 0) {
110
+ input.parents('li').hide();
111
+ } else {
112
+ input.parents('li').show();
113
+ }
114
+ });
115
+ w3tc_minify_css_file_clear();
116
  }
117
 
118
  function w3tc_cdn_get_cnames() {
119
+ var cnames = [];
120
 
121
+ jQuery('#cdn_cnames input[type=text]').each(function() {
122
+ var cname = jQuery(this).val();
123
 
124
+ if (cname) {
125
+ var match = /^\*\.(.*)$/.exec(cname);
126
 
127
+ if (match) {
128
+ cnames = [];
129
+ for (var i = 1; i <= 10; i++) {
130
+ cnames.push('cdn' + i + '.' + match[1]);
131
+ }
132
+ return false;
133
+ }
134
 
135
+ cnames.push(cname);
136
+ }
137
+ });
138
 
139
+ return cnames;
140
  }
141
 
142
  function w3tc_cdn_cnames_assign() {
143
+ var li = jQuery('#cdn_cnames li'), size = li.size();
144
+
145
+ if (size > 1) {
146
+ li.eq(0).find('.cdn_cname_delete').show();
147
+ } else {
148
+ li.eq(0).find('.cdn_cname_delete').hide();
149
+ }
150
+
151
+ jQuery(li).each(function(index) {
152
+ var label = '';
153
+
154
+ if (size > 1) {
155
+ switch (index) {
156
+ case 0:
157
+ label = '(reserved for CSS)';
158
+ break;
159
+
160
+ case 1:
161
+ label = '(reserved for JS in <head>)';
162
+ break;
163
+
164
+ case 2:
165
+ label = '(reserved for JS after <body>)';
166
+ break;
167
+
168
+ case 3:
169
+ label = '(reserved for JS before </body>)';
170
+ break;
171
+ }
172
+ }
173
+
174
+ jQuery(this).find('span').text(label);
175
+ });
176
  }
177
 
178
  function w3tc_toggle(name, check) {
179
+ if (check === undefined) {
180
+ check = true;
181
+ }
182
+
183
+ var id = '#' + name, cls = '.' + name;
184
+
185
+ jQuery(cls).click(function() {
186
+ var checked = check;
187
+
188
+ jQuery(cls).each(function() {
189
+ var _checked = jQuery(this).is(':checked');
190
+
191
+ if ((check && !_checked) || (!check && _checked)) {
192
+ checked = !check;
193
+
194
+ return false;
195
+ }
196
+ });
197
+
198
+ if (checked) {
199
+ jQuery(id).attr('checked', 'checked');
200
+ } else {
201
+ jQuery(id).removeAttr('checked');
202
+ }
203
+ });
204
+
205
+ jQuery(id).click(function() {
206
+ var checked = jQuery(this).is(':checked');
207
+ jQuery(cls).each(function() {
208
+ if (checked) {
209
+ jQuery(this).attr('checked', 'checked');
210
+ } else {
211
+ jQuery(this).removeAttr('checked');
212
+ }
213
+ });
214
+ });
215
  }
216
 
217
  function w3tc_toggle2(name, dependent_ids) {
218
+ var id = '#' + name, dependants = '', n;
219
+ for (n = 0; n < dependent_ids.length; n++)
220
+ dependants += (n > 0 ? ',' : '') + '#' + dependent_ids[n];
221
+
222
+ jQuery(dependants).click(function() {
223
+ var total_checked = true;
224
+
225
+ jQuery(dependants).each(function() {
226
+ var current_checked = jQuery(this).is(':checked');
227
+
228
+ if (!current_checked)
229
+ total_checked = false;
230
+ });
231
+
232
+ if (total_checked) {
233
+ jQuery(id).attr('checked', 'checked');
234
+ } else {
235
+ jQuery(id).removeAttr('checked');
236
+ }
237
+ });
238
+
239
+ jQuery(id).click(function() {
240
+ var checked = jQuery(this).is(':checked');
241
+ jQuery(dependants).each(function() {
242
+ if (checked) {
243
+ jQuery(this).attr('checked', 'checked');
244
+ } else {
245
+ jQuery(this).removeAttr('checked');
246
+ }
247
+ });
248
+ });
249
  }
250
 
251
  function w3tc_beforeupload_bind() {
252
+ jQuery(window).bind('beforeunload', w3tc_beforeunload);
253
  }
254
 
255
  function w3tc_beforeupload_unbind() {
256
+ jQuery(window).unbind('beforeunload', w3tc_beforeunload);
257
  }
258
 
259
  function w3tc_beforeunload() {
260
+ return 'Navigate away from this page without saving your changes?';
261
  }
262
 
 
263
  function w3tc_starts_with(s, starts_with) {
264
  s = s.replace(/\n/g, '');
265
  s = s.replace(/\s/g, '');
266
+ return s.substr(0, starts_with.length) == starts_with;
267
  }
268
 
269
+ function w3tc_security_headers() {
270
+ var directive_description =
271
+ {
272
+ browsercache_security_hsts_directive:
273
+ {
274
+ maxage: 'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using HTTPS. This only affects the site\'s main domain.',
275
+ maxagepre: 'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using HTTPS with a request to be included in Chrome\'s HSTS preload list - a list of sites that are hardcoded into Chrome as being HTTPS only. This only affects the site\'s main domain.',
276
+ maxageinc: 'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using HTTPS. This affects the site\'s subdomains as well.',
277
+ maxageincpre: 'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using HTTPS with a request to be included in Chrome\'s HSTS preload list - a list of sites that are hardcoded into Chrome as being HTTPS only. This affects the site\'s subdomains as well.'
278
+ },
279
+ browsercache_security_xfo_directive:
280
+ {
281
+ same: "The page can only be displayed in a frame on the same origin as the page itself.",
282
+ deny: "The page cannot be displayed in a frame, regardless of the site attempting to do so.",
283
+ allow: "The page can only be displayed in a frame on the specified URL."
284
+ },
285
+ browsercache_security_xss_directive:
286
+ {
287
+ 0: "Disables XSS filtering.",
288
+ 1: "Enables XSS filtering (usually default in browsers). If a cross-site scripting attack is detected, the browser will sanitize the page (remove the unsafe parts).",
289
+ block: "Enables XSS filtering. Rather than sanitizing the page, the browser will prevent rendering of the page if an attack is detected."
290
+ },
291
+ browsercache_security_pkp_extra:
292
+ {
293
+ maxage: 'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using one of the defined keys. This only affects the site\'s main domain.',
294
+ maxageinc: 'The time, in seconds (as defined under the "Expires Header Lifetime" box of "Media & Other Files"), that the browser should remember that this site is only to be accessed using one of the defined keys. This affects the site\'s subdomains as well.'
295
+ },
296
+ browsercache_security_pkp_report_only:
297
+ {
298
+ 0: 'This instructs the browser to enforce the HPKP policy.',
299
+ 1: 'This sets up HPKP without enforcement allowing you to use pinning to test its impact without the risk of a failed connection caused by your site being unreachable or HPKP being misconfigured.'
300
+ }
301
+ };
302
+
303
+ jQuery('#browsercache_security_hsts_directive,#browsercache_security_xfo_directive,#browsercache_security_xss_directive,#browsercache_security_pkp_extra,#browsercache_security_pkp_report_only').change(
304
+ function() {
305
+ jQuery('#' + jQuery(this).attr('id') + '_description').html('<i>' + directive_description[jQuery(this).attr('id')][jQuery(this).val()] + '</i>');
306
+ if (jQuery(this).attr('id') == 'browsercache_security_xfo_directive') {
307
+ if (jQuery(this).val() == 'allow') {
308
+ jQuery('#browsercache_security_xfo_allow').show();
309
+ }else {
310
+ jQuery('#browsercache_security_xfo_allow').hide();
311
+ }
312
+ }
313
+ });
314
+
315
+ if(jQuery('#browsercache_security_xfo_allow').length) {
316
+ if (jQuery('#browsercache_security_xfo_directive').val() == 'allow') {
317
+ jQuery('#browsercache_security_xfo_allow').show();
318
+ } else {
319
+ jQuery('#browsercache_security_xfo_allow').hide();
320
+ }
321
+ jQuery('#browsercache_security_hsts_directive,#browsercache_security_xfo_directive,#browsercache_security_xss_directive,#browsercache_security_pkp_extra,#browsercache_security_pkp_report_only').change();
322
+ }
323
+ }
324
 
325
+ function w3tc_csp_reference() {
326
+ W3tc_Lightbox.open({
327
+ id: 'w3tc-overlay',
328
+ close: '',
329
+ width: 890,
330
+ height: 660,
331
+ content: '<div id="w3tc_csp"></div>'
332
+ });
333
+ jQuery('div#overlay,.lightbox-content').click(function() {
334
+ W3tc_Lightbox.close();
335
+ });
336
+ }
337
 
338
  jQuery(function() {
339
+ // general page
340
+ jQuery('.w3tc_read_technical_info').click(function() {
341
+ jQuery('.w3tc_technical_info').toggle();
342
+ });
343
+
344
+ jQuery('#plugin_license_key_verify').click(function() {
345
+ jQuery('.w3tc_license_verification').html("Checking...");
346
+
347
+ var license_key = jQuery('#plugin_license_key').val();
348
+
349
+ if (!license_key) {
350
+ jQuery('.w3tc_license_verification').html('Please enter an license key and try again.');
351
+ return;
352
+ }
353
+ var params = {
354
+ action: 'w3tc_verify_plugin_license_key',
355
+ license_key: license_key
356
+ };
357
+
358
+ jQuery.get(ajaxurl, params, function(data) {
359
+ if (w3tc_starts_with(data + '.', 'inactive.expired.')) {
360
+ jQuery('.w3tc_license_verification').html('The license key has expired. Please renew it.');
361
+ } else if (w3tc_starts_with(data + '.', 'active.')) {
362
+ jQuery('.w3tc_license_verification').html('License key is correct.');
363
+ } else if (w3tc_starts_with(data + '.', 'inactive.by_rooturi.activations_limit_not_reached.')) {
364
+ jQuery('.w3tc_license_verification').html('License key is correct and can be activated now.');
365
+ } else if (w3tc_starts_with(data + '.', 'inactive.by_rooturi.')) {
366
+ jQuery('.w3tc_license_verification').html('License key is correct but already in use on another site. See the FAQ for how to enable Pro version in development mode.');
367
+ } else {
368
+ jQuery('.w3tc_license_verification').html('The license key is not valid. Please check it and try again.');
369
+ }
370
+ }).fail(function() {
371
+ jQuery('.w3tc_license_verification').html('Check failed');
372
+ })
373
+ });
374
+
375
+ // pagecache page
376
+ w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').size());
377
+ jQuery('#pgcache__reject__logged_roles').live('click', function(){
378
+ w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').size());
379
+ });
380
+
381
+ if(jQuery('#pgcache__cache__nginx_handle_xml').is('*'))
382
+ jQuery('#pgcache__cache__nginx_handle_xml').attr('checked',jQuery('#pgcache__cache__feed').is(':checked'));
383
+
384
+ jQuery('#pgcache__cache__feed').change(function(){
385
+ if(jQuery('#pgcache__cache__nginx_handle_xml').is('*'))
386
+ jQuery('#pgcache__cache__nginx_handle_xml').attr('checked',this.checked);
387
+ });
388
+
389
+ // browsercache page
390
+ w3tc_toggle2('browsercache_last_modified',
391
+ ['browsercache__cssjs__last_modified', 'browsercache__html__last_modified',
392
+ 'browsercache__other__last_modified']);
393
+ w3tc_toggle2('browsercache_expires',
394
+ ['browsercache__cssjs__expires', 'browsercache__html__expires',
395
+ 'browsercache__other__expires']);
396
+ w3tc_toggle2('browsercache_cache_control',
397
+ ['browsercache__cssjs__cache__control', 'browsercache__html__cache__control',
398
+ 'browsercache__other__cache__control']);
399
+ w3tc_toggle2('browsercache_etag',
400
+ ['browsercache__cssjs__etag', 'browsercache__html__etag',
401
+ 'browsercache__other__etag']);
402
+ w3tc_toggle2('browsercache_w3tc',
403
+ ['browsercache__cssjs__w3tc', 'browsercache__html__w3tc',
404
+ 'browsercache__other__w3tc']);
405
+ w3tc_toggle2('browsercache_compression',
406
+ ['browsercache__cssjs__compression', 'browsercache__html__compression',
407
+ 'browsercache__other__compression']);
408
+ w3tc_toggle2('browsercache_replace',
409
+ ['browsercache__cssjs__replace', 'browsercache__other__replace']);
410
+ w3tc_toggle2('browsercache_querystring',
411
+ ['browsercache__cssjs__querystring', 'browsercache__other__querystring']);
412
+ w3tc_toggle2('browsercache_nocookies',
413
+ ['browsercache__cssjs__nocookies', 'browsercache__other__nocookies']);
414
+
415
+ w3tc_security_headers();
416
+
417
+ // minify page
418
+ w3tc_input_enable('.html_enabled', jQuery('#minify__html__enable:checked').size());
419
+ w3tc_input_enable('.js_enabled', jQuery('#minify__js__enable:checked').size());
420
+ w3tc_input_enable('.css_enabled', jQuery('#minify__css__enable:checked').size());
421
+
422
+ w3tc_minify_js_theme(jQuery('#js_themes').val());
423
+ w3tc_minify_css_theme(jQuery('#css_themes').val());
424
+
425
+ jQuery('#minify__html__enable').click(function() {
426
+ w3tc_input_enable('.html_enabled', this.checked);
427
+ });
428
+
429
+ jQuery('#minify__js__enable').click(function() {
430
+ w3tc_input_enable('.js_enabled', jQuery(this).is(':checked'));
431
+ });
432
+
433
+ jQuery('#minify__css__enable').click(function() {
434
+ w3tc_input_enable('.css_enabled', jQuery(this).is(':checked'));
435
+ });
436
+
437
+ jQuery('.js_file_verify,.css_file_verify').live('click', function() {
438
+ var file = jQuery(this).parents('li').find(':text').val();
439
+ if (file == '') {
440
+ alert('Empty URI');
441
+ } else {
442
+ var url = '';
443
+ if (/^https?:\/\//.test(file)) {
444
+ url = file;
445
+ } else {
446
+ url = '/' + file;
447
+ }
448
+ w3tc_popup(url, 'file_verify');
449
+ }
450
+ });
451
+
452
+ jQuery('.js_file_template').live('change', function() {
453
+ jQuery(this).parents('li').find(':text').attr('name', 'js_files[' + jQuery('#js_themes').val() + '][' + jQuery(this).val() + '][' + jQuery(this).parents('li').find('.js_file_location').val() + '][]');
454
+ });
455
+
456
+ jQuery('.css_file_template').live('change', function() {
457
+ jQuery(this).parents('li').find(':text').attr('name', 'css_files[' + jQuery('#css_themes').val() + '][' + jQuery(this).val() + '][include][]');
458
+ });
459
+
460
+ jQuery('.js_file_location').live('change', function() {
461
+ jQuery(this).parents('li').find(':text').attr('name', 'js_files[' + jQuery('#js_themes').val() + '][' + jQuery(this).parents('li').find('.js_file_template').val() + '][' + jQuery(this).val() + '][]');
462
+ });
463
+
464
+ jQuery('.js_file_delete').live('click', function() {
465
+ var parent = jQuery(this).parents('li');
466
+ if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this JS file?')) {
467
+ parent.remove();
468
+ w3tc_minify_js_file_clear();
469
+ w3tc_beforeupload_bind();
470
+ }
471
+
472
+ return false;
473
+ });
474
+
475
+ jQuery('.css_file_delete').live('click', function() {
476
+ var parent = jQuery(this).parents('li');
477
+ if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this CSS file?')) {
478
+ parent.remove();
479
+ w3tc_minify_css_file_clear();
480
+ w3tc_beforeupload_bind();
481
+ }
482
+
483
+ return false;
484
+ });
485
+
486
+ jQuery('#js_file_add').click(function() {
487
+ w3tc_minify_js_file_add(jQuery('#js_themes').val(), 'default', 'include', '');
488
+ });
489
+
490
+ jQuery('#css_file_add').click(function() {
491
+ w3tc_minify_css_file_add(jQuery('#css_themes').val(), 'default', '');
492
+ });
493
+
494
+ jQuery('#js_themes').change(function() {
495
+ w3tc_minify_js_theme(jQuery(this).val());
496
+ });
497
+
498
+ jQuery('#css_themes').change(function() {
499
+ w3tc_minify_css_theme(jQuery(this).val());
500
+ });
501
+
502
+ jQuery('#minify_form').submit(function() {
503
+ var js = [], css = [], invalid_js = [], invalid_css = [], duplicate = false, query_js = [], query_css = [];
504
+
505
+ jQuery('#js_files :text').each(function() {
506
+ var v = jQuery(this).val(), n = jQuery(this).attr('name'), c = v + n, g = '';
507
+ var match = /js_files\[([a-z0-9_\/]+)\]/.exec(n);
508
+ if (match) {
509
+ g = '[' + jQuery('#js_themes option[value=' + match[1] + ']').text() + '] ' + v;
510
+ }
511
+ if (v != '') {
512
+ for (var i = 0; i < js.length; i++) {
513
+ if (js[i] == c) {
514
+ duplicate = true;
515
+ break;
516
+ }
517
+ }
518
+
519
+ js.push(c);
520
+
521
+ var qindex = v.indexOf('?');
522
+ if (qindex != -1) {
523
+ if (!/^(https?:)?\/\//.test(v)) {
524
+ query_js.push(g);
525
+ }
526
+ v = v.substr(0, qindex);
527
+ } else if (!/\.js$/.test(v)) {
528
+ invalid_js.push(g);
529
+ }
530
+ }
531
+ });
532
+
533
+ jQuery('#css_files :text').each(function() {
534
+ var v = jQuery(this).val(), n = jQuery(this).attr('name'), c = v + n, g = '';
535
+ var match = /css_files\[([a-z0-9_\/]+)\]/.exec(n);
536
+ if (match) {
537
+ g = '[' + jQuery('#css_themes option[value=' + match[1] + ']').text() + '] ' + v;
538
+ }
539
+ if (v != '') {
540
+ for (var i = 0; i < css.length; i++) {
541
+ if (css[i] == c) {
542
+ duplicate = true;
543
+ break;
544
+ }
545
+ }
546
+
547
+ css.push(c);
548
+
549
+ var qindex = v.indexOf('?');
550
+ if (qindex != -1) {
551
+ if (!/^(https?:)?\/\//.test(v)) {
552
+ query_css.push(g);
553
+ }
554
+ v = v.substr(0, qindex);
555
+ } else if (!/\.css$/.test(v)) {
556
+ invalid_css.push(g);
557
+ }
558
+ }
559
+ });
560
+
561
+ if (jQuery('#js_enabled:checked').size()) {
562
+ if (invalid_js.length && !confirm('The following files have invalid JS file extension:\r\n\r\n' + invalid_js.join('\r\n') + '\r\n\r\nAre you confident these files contain valid JS code?')) {
563
+ return false;
564
+ }
565
+
566
+ if (query_js.length) {
567
+ alert('We recommend using the entire URI for files with query string (GET) variables. You entered:\r\n\r\n' + query_js.join('\r\n'));
568
+ return false;
569
+ }
570
+ }
571
+
572
+ if (jQuery('#css_enabled:checked').size()) {
573
+ if (invalid_css.length && !confirm('The following files have invalid CSS file extension:\r\n\r\n' + invalid_css.join('\r\n') + '\r\n\r\nAre you confident these files contain valid CSS code?')) {
574
+ return false;
575
+ }
576
+
577
+ if (query_css.length) {
578
+ alert('We recommend using the entire URI for files with query string (GET) variables. You entered:\r\n\r\n' + query_css.join('\r\n'));
579
+ return false;
580
+ }
581
+ }
582
+
583
+ if (duplicate) {
584
+ alert('Duplicate files have been found in your minify settings, please check your settings and re-save.');
585
+ return false;
586
+ }
587
+
588
+ return true;
589
+ });
590
+
591
+ // CDN
592
+ jQuery('.w3tc-tab').click(function() {
593
+ jQuery('.w3tc-tab-content').hide();
594
+ jQuery(this.rel).show();
595
+ });
596
+
597
+ w3tc_input_enable('#cdn_reject_roles input[type=checkbox]', jQuery('#cdn__reject__logged_roles:checked').size());
598
+ jQuery('#cdn__reject__logged_roles').live('click', function() {
599
+ w3tc_input_enable('#cdn_reject_roles input[type=checkbox]', jQuery('#cdn__reject__logged_roles:checked').size());
600
+ });
601
+
602
+ jQuery('#cdn_export_library').click(function() {
603
+ w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_export_library&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_export_library');
604
+ });
605
+
606
+ jQuery('#cdn_import_library').click(function() {
607
+ w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_import_library&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_import_library');
608
+ });
609
+
610
+ jQuery('#cdn_queue').click(function() {
611
+ w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_queue&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_queue');
612
+ });
613
+
614
+ jQuery('#cdn_rename_domain').click(function() {
615
+ w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_rename_domain&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_rename_domain');
616
+ });
617
+
618
+ jQuery('#cdn_purge').click(function() {
619
+ w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_purge&_wpnonce=' + jQuery(this).metadata().nonce, 'cdn_purge');
620
+ });
621
+
622
+ jQuery('.cdn_export').click(function() {
623
+ var metadata = jQuery(this).metadata();
624
+ w3tc_popup('admin.php?page=w3tc_cdn&w3tc_cdn_export&cdn_export_type=' + metadata.type + '&_wpnonce=' + metadata.nonce, 'cdn_export_' + metadata.type);
625
+ });
626
+
627
+ jQuery('#validate_cdn_key').click(function() {
628
+ var me = jQuery(this);
629
+ var metadata = me.metadata();
630
+ w3tc_validate_cdn_key_result(metadata.type, metadata.nonce);
631
+ });
632
+
633
+ jQuery('#use_poll_zone').click(function() {
634
+ var me = jQuery(this);
635
+ var metadata = me.metadata();
636
+ w3tc_use_poll_zone(metadata.type, metadata.nonce);
637
+ });
638
+
639
+ jQuery('#cdn_test').click(function() {
640
+ var me = jQuery(this);
641
+ var metadata = me.metadata();
642
+ var cnames = w3tc_cdn_get_cnames();
643
+ var params = {
644
+ w3tc_cdn_test: 1,
645
+ _wpnonce: metadata.nonce
646
+ };
647
+
648
+ switch (metadata.type) {
649
+ case 'ftp':
650
+ jQuery.extend(params, {
651
+ engine: 'ftp',
652
+ 'config[host]': jQuery('#cdn_ftp_host').val(),
653
+ 'config[type]': jQuery('#cdn_ftp_type').val(),
654
+ 'config[user]': jQuery('#cdn_ftp_user').val(),
655
+ 'config[path]': jQuery('#cdn_ftp_path').val(),
656
+ 'config[pass]': jQuery('#cdn_ftp_pass').val(),
657
+ 'config[pasv]': jQuery('#cdn_ftp_pasv:checked').size()
658
+ });
659
+
660
+ if (cnames.length) {
661
+ params['config[domain][]'] = cnames;
662
+ }
663
+ break;
664
+
665
+ case 's3':
666
+ jQuery.extend(params, {
667
+ engine: 's3',
668
+ 'config[key]': jQuery('#cdn_s3_key').val(),
669
+ 'config[secret]': jQuery('#cdn_s3_secret').val(),
670
+ 'config[bucket]': jQuery('#cdn_s3_bucket').val(),
671
+ 'config[bucket_location]': jQuery('#cdn_s3_bucket_location').val()
672
+ });
673
+
674
+ if (cnames.length) {
675
+ params['config[cname][]'] = cnames;
676
+ }
677
+ break;
678
+
679
+ case 'cf':
680
+ jQuery.extend(params, {
681
+ engine: 'cf',
682
+ 'config[key]': jQuery('#cdn_cf_key').val(),
683
+ 'config[secret]': jQuery('#cdn_cf_secret').val(),
684
+ 'config[bucket]': jQuery('#cdn_cf_bucket').val(),
685
+ 'config[bucket_location]': jQuery('#cdn_cf_bucket_location').val(),
686
+ 'config[id]': jQuery('#cdn_cf_id').val()
687
+ });
688
+
689
+ if (cnames.length) {
690
+ params['config[cname][]'] = cnames;
691
+ }
692
+ break;
693
+
694
+ case 'cf2':
695
+ jQuery.extend(params, {
696
+ engine: 'cf2',
697
+ 'config[key]': jQuery('#cdn_cf2_key').val(),
698
+ 'config[secret]': jQuery('#cdn_cf2_secret').val(),
699
+ 'config[origin]': jQuery('#cdn_cf2_origin').val(),
700
+ 'config[id]': jQuery('#cdn_cf2_id').val()
701
+ });
702
+
703
+ if (cnames.length) {
704
+ params['config[cname][]'] = cnames;
705
+ }
706
+ break;
707
+
708
+ case 'rscf':
709
+ jQuery.extend(params, {
710
+ engine: 'rscf',
711
+ 'config[user]': jQuery('#cdn_rscf_user').val(),
712
+ 'config[key]': jQuery('#cdn_rscf_key').val(),
713
+ 'config[location]': jQuery('#cdn_rscf_location').val(),
714
+ 'config[container]': jQuery('#cdn_rscf_container').val(),
715
+ 'config[id]': jQuery('#cdn_rscf_id').val()
716
+ });
717
+
718
+ if (cnames.length) {
719
+ params['config[cname][]'] = cnames;
720
+ }
721
+ break;
722
+
723
+ case 'azure':
724
+ jQuery.extend(params, {
725
+ engine: 'azure',
726
+ 'config[user]': jQuery('#cdn_azure_user').val(),
727
+ 'config[key]': jQuery('#cdn_azure_key').val(),
728
+ 'config[container]': jQuery('#cdn_azure_container').val()
729
+ });
730
+
731
+ if (cnames.length) {
732
+ params['config[cname][]'] = cnames;
733
+ }
734
+ break;
735
+
736
+ case 'mirror':
737
+ jQuery.extend(params, {
738
+ engine: 'mirror'
739
+ });
740
+
741
+ if (cnames.length) {
742
+ params['config[domain][]'] = cnames;
743
+ }
744
+ break;
745
+
746
+ case 'cotendo':
747
+ var zones = [], zones_val = jQuery('#cdn_cotendo_zones').val();
748
+
749
+ if (zones_val) {
750
+ zones = zones_val.split(/[\r\n,;]+/);
751
+ }
752
+
753
+ jQuery.extend(params, {
754
+ engine: 'cotendo',
755
+ 'config[username]': jQuery('#cdn_cotendo_username').val(),
756
+ 'config[password]': jQuery('#cdn_cotendo_password').val()
757
+ });
758
+
759
+ if (zones.length) {
760
+ params['config[zones][]'] = zones;
761
+ }
762
+
763
+ if (cnames.length) {
764
+ params['config[domain][]'] = cnames;
765
+ }
766
+ break;
767
+ case 'akamai':
768
+ var emails = [], emails_val = jQuery('#cdn_akamai_email_notification').val();
769
+
770
+ if (emails_val) {
771
+ emails = emails_val.split(/[\r\n,;]+/);
772
+ }
773
+
774
+ jQuery.extend(params, {
775
+ engine: 'akamai',
776
+ 'config[username]': jQuery('#cdn_akamai_username').val(),
777
+ 'config[password]': jQuery('#cdn_akamai_password').val(),
778
+ 'config[zone]': jQuery('#cdn_akamai_zone').val()
779
+ });
780
+
781
+ if (emails.length) {
782
+ params['config[email_notification][]'] = emails;
783
+ }
784
+
785
+ if (cnames.length) {
786
+ params['config[domain][]'] = cnames;
787
+ }
788
+ break;
789
+
790
+ case 'edgecast':
791
+ jQuery.extend(params, {
792
+ engine: 'edgecast',
793
+ 'config[account]': jQuery('#cdn_edgecast_account').val(),
794
+ 'config[token]': jQuery('#cdn_edgecast_token').val()
795
+ });
796
+
797
+ if (cnames.length) {
798
+ params['config[domain][]'] = cnames;
799
+ }
800
+ break;
801
+
802
+ case 'att':
803
+ jQuery.extend(params, {
804
+ engine: 'att',
805
+ 'config[account]': jQuery('#cdn_att_account').val(),
806
+ 'config[token]': jQuery('#cdn_att_token').val()
807
+ });
808
+
809
+ if (cnames.length) {
810
+ params['config[domain][]'] = cnames;
811
+ }
812
+ break;
813
+ default:
814
+ jQuery.extend(params, {
815
+ engine: metadata.type
816
+ });
817
+ }
818
+
819
+ var status = jQuery('#cdn_test_status');
820
+ status.removeClass('w3tc-error');
821
+ status.removeClass('w3tc-success');
822
+ status.addClass('w3tc-process');
823
+
824
+ var status2 = jQuery('#cdn_create_container_status');
825
+ status2.removeClass('w3tc-error');
826
+ status2.removeClass('w3tc-success');
827
+ status2.html('');
828
+
829
+ status.html('Testing...');
830
+
831
+ jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
832
+ status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
833
+ status.html(data.error);
834
+ }, 'json').fail(function() {
835
+ status.addClass('w3tc-error');
836
+ status.html('Test failed');
837
+ });
838
+ });
839
+
840
+ jQuery('#cdn_create_container').live('click', function() {
841
+ var me = jQuery(this);
842
+ var metadata = me.metadata();
843
+ var cnames = w3tc_cdn_get_cnames();
844
+ var container_id = null;
845
+ var params = {
846
+ w3tc_cdn_create_container: 1,
847
+ _wpnonce: metadata.nonce
848
+ };
849
+
850
+ switch (metadata.type) {
851
+ case 's3':
852
+ jQuery.extend(params, {
853
+ engine: 's3',
854
+ 'config[key]': jQuery('#cdn_s3_key').val(),
855
+ 'config[secret]': jQuery('#cdn_s3_secret').val(),
856
+ 'config[bucket]': jQuery('#cdn_s3_bucket').val(),
857
+ 'config[bucket_location]': jQuery('#cdn_s3_bucket_location').val()
858
+ });
859
+
860
+ if (cnames.length) {
861
+ params['config[cname][]'] = cnames;
862
+ }
863
+ break;
864
+
865
+ case 'cf':
866
+ container_id = jQuery('#cdn_cf_id');
867
+
868
+ jQuery.extend(params, {
869
+ engine: 'cf',
870
+ 'config[key]': jQuery('#cdn_cf_key').val(),
871
+ 'config[secret]': jQuery('#cdn_cf_secret').val(),
872
+ 'config[bucket]': jQuery('#cdn_cf_bucket').val(),
873
+ 'config[bucket_location]': jQuery('#cdn_cf_bucket_location').val()
874
+ });
875
+
876
+ if (cnames.length) {
877
+ params['config[cname][]'] = cnames;
878
+ }
879
+ break;
880
+
881
+ case 'cf2':
882
+ container_id = jQuery('#cdn_cf2_id');
883
+
884
+ jQuery.extend(params, {
885
+ engine: 'cf2',
886
+ 'config[key]': jQuery('#cdn_cf2_key').val(),
887
+ 'config[secret]': jQuery('#cdn_cf2_secret').val(),
888
+ 'config[origin]': jQuery('#cdn_cf2_origin').val(),
889
+ 'config[bucket_location]': jQuery('#cdn_cf2_bucket_location').val()
890
+ });
891
+
892
+ if (cnames.length) {
893
+ params['config[cname][]'] = cnames;
894
+ }
895
+ break;
896
+
897
+ case 'rscf':
898
+ container_id = jQuery('#cdn_cnames input[type=text]:first');
899
+
900
+ jQuery.extend(params, {
901
+ engine: 'rscf',
902
+ 'config[user]': jQuery('#cdn_rscf_user').val(),
903
+ 'config[key]': jQuery('#cdn_rscf_key').val(),
904
+ 'config[location]': jQuery('#cdn_rscf_location').val(),
905
+ 'config[container]': jQuery('#cdn_rscf_container').val()
906
+ });
907
+
908
+ if (cnames.length) {
909
+ params['config[cname][]'] = cnames;
910
+ }
911
+ break;
912
+
913
+ case 'azure':
914
+ jQuery.extend(params, {
915
+ engine: 'azure',
916
+ 'config[user]': jQuery('#cdn_azure_user').val(),
917
+ 'config[key]': jQuery('#cdn_azure_key').val(),
918
+ 'config[container]': jQuery('#cdn_azure_container').val()
919
+ });
920
+
921
+ if (cnames.length) {
922
+ params['config[cname][]'] = cnames;
923
+ }
924
+ break;
925
+ }
926
+
927
+ var status = jQuery('#cdn_create_container_status');
928
+ status.removeClass('w3tc-error');
929
+ status.removeClass('w3tc-success');
930
+ status.addClass('w3tc-process');
931
 
932
  var status2 = jQuery('#cdn_test_status');
933
+ status2.removeClass('w3tc-error');
934
+ status2.removeClass('w3tc-success');
935
+ status2.html('');
936
+
937
+ status.html('Creating...');
938
+
939
+ jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
940
+ status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
941
+ status.html(data.error);
942
+
943
+ if (container_id && container_id.size() && data.container_id) {
944
+ container_id.val(data.container_id);
945
+ }
946
+ }, 'json').fail(function() {
947
+ status.addClass('w3tc-error');
948
+ status.html('failed');
949
+ });
950
+ });
951
+
952
+ jQuery('#memcached_test').click(function() {
953
+ var status = jQuery('#memcached_test_status');
954
+ status.removeClass('w3tc-error');
955
+ status.removeClass('w3tc-success');
956
+ status.addClass('w3tc-process');
957
+ status.html('Testing...');
958
+ jQuery.post('admin.php?page=w3tc_dashboard', {
959
+ w3tc_test_memcached: 1,
960
+ servers: jQuery('#memcached_servers').val(),
961
+ _wpnonce: jQuery(this).metadata().nonce
962
+ }, function(data) {
963
+ status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
964
+ status.html(data.error);
965
+ }, 'json')
966
+ .fail(function() {
967
+ status.addClass('w3tc-error');
968
+ status.html('Request failed');
969
+ });
970
+ });
971
+
972
+ jQuery('.w3tc_common_redis_test').click(function() {
973
+ var status = jQuery('.w3tc_common_redis_test_result');
974
+ status.removeClass('w3tc-error');
975
+ status.removeClass('w3tc-success');
976
+ status.addClass('w3tc-process');
977
+ status.html('Testing...');
978
+ jQuery.post('admin.php?page=w3tc_dashboard', {
979
+ w3tc_test_redis: 1,
980
+ servers: jQuery('#redis_servers').val(),
981
+ dbid : jQuery('#redis_dbid').val(),
982
+ password : jQuery('#redis_password').val(),
983
+ _wpnonce: jQuery(this).metadata().nonce
984
+ }, function(data) {
985
+ status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
986
+ status.html(data.error);
987
+ }, 'json')
988
+ .fail(function() {
989
+ status.addClass('w3tc-error');
990
+ status.html('Request failed');
991
+ });
992
+ });
993
+
994
+ jQuery('.minifier_test').click(function() {
995
+ var me = jQuery(this);
996
+ var metadata = me.metadata();
997
+ var params = {
998
+ w3tc_test_minifier: 1,
999
+ _wpnonce: metadata.nonce
1000
+ };
1001
+
1002
+ switch (metadata.type) {
1003
+ case 'yuijs':
1004
+ jQuery.extend(params, {
1005
+ engine: 'yuijs',
1006
+ path_java: jQuery('#minify__yuijs__path__java').val(),
1007
+ path_jar: jQuery('#minify__yuijs__path__jar').val()
1008
+ });
1009
+ break;
1010
+
1011
+ case 'yuicss':
1012
+ jQuery.extend(params, {
1013
+ engine: 'yuicss',
1014
+ path_java: jQuery('#minify__yuicss__path__java').val(),
1015
+ path_jar: jQuery('#minify__yuicss__path__jar').val()
1016
+ });
1017
+ break;
1018
+
1019
+ case 'ccjs':
1020
+ jQuery.extend(params, {
1021
+ engine: 'ccjs',
1022
+ path_java: jQuery('#minify__ccjs__path__java').val(),
1023
+ path_jar: jQuery('#minify__ccjs__path__jar').val()
1024
+ });
1025
+ break;
1026
+ case 'googleccjs':
1027
+ jQuery.extend(params, {
1028
+ engine: 'googleccjs'
1029
+ });
1030
+ break;
1031
+ }
1032
+
1033
+ var status = me.next();
1034
+ status.removeClass('w3tc-error');
1035
+ status.removeClass('w3tc-success');
1036
+ status.addClass('w3tc-process');
1037
+ status.html('Testing...');
1038
+
1039
+ jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
1040
+ status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
1041
+ status.html(data.error);
1042
+ }, 'json');
1043
+ });
1044
+
1045
+ // CDN cnames
1046
+ jQuery('body').on('click', '#cdn_cname_add', function() {
1047
+ jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
1048
+ w3tc_cdn_cnames_assign();
1049
+ jQuery(this).trigger("size_change");
1050
+ });
1051
+
1052
+ jQuery('.cdn_cname_delete').live('click', function() {
1053
+ var p = jQuery(this).parent();
1054
+ if (p.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this CNAME?')) {
1055
+ p.remove();
1056
+ w3tc_cdn_cnames_assign();
1057
+ w3tc_beforeupload_bind();
1058
+ }
1059
+ });
1060
+
1061
+ jQuery('#cdn_form').submit(function() {
1062
+ var cnames = [], ret = true;
1063
+
1064
+ jQuery('#cdn_cnames input[type=text]').each(function() {
1065
+ var cname = jQuery(this).val();
1066
+
1067
+ if (cname) {
1068
+ if (jQuery.inArray(cname, cnames) != -1) {
1069
+ alert('CNAME "' + cname + '" already exists.');
1070
+ ret = false;
1071
+
1072
+ return false;
1073
+ } else {
1074
+ cnames.push(cname);
1075
+ }
1076
+ }
1077
+ });
1078
+
1079
+ return ret;
1080
+ });
1081
+
1082
+ // mobile tab
1083
+ jQuery('#mobile_form').submit(function() {
1084
+ var error = false;
1085
+
1086
+ jQuery('#mobile_groups li').each(function() {
1087
+ if (jQuery(this).find(':checked').size()) {
1088
+ var group = jQuery(this).find('.mobile_group').text();
1089
+ var theme = jQuery(this).find(':selected').val();
1090
+ var redirect = jQuery(this).find('input[type=text]').val();
1091
+ var agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1092
+
1093
+ jQuery('#mobile_groups li').each(function() {
1094
+ if (jQuery(this).find(':checked').size()) {
1095
+ var compare_group = jQuery(this).find('.mobile_group').text();
1096
+ if (compare_group != group) {
1097
+ var compare_theme = jQuery(this).find(':selected').val();
1098
+ var compare_redirect = jQuery(this).find('input[type=text]').val();
1099
+ var compare_agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1100
+
1101
+ if (compare_redirect == '' && redirect == '' && compare_theme != '' && compare_theme == theme) {
1102
+ alert('Duplicate theme "' + compare_theme + '" found in the group "' + group + '".');
1103
+ error = true;
1104
+ return false;
1105
+ }
1106
+
1107
+ if (compare_redirect != '' && compare_redirect == redirect) {
1108
+ alert('Duplicate redirect "' + compare_redirect + '" found in the group "' + group + '".');
1109
+ error = true;
1110
+ return false;
1111
+ }
1112
+
1113
+ jQuery.each(compare_agents, function(index, value) {
1114
+ if (jQuery.inArray(value, agents) != -1) {
1115
+ alert('Duplicate stem "' + value + '" found in the group "' + compare_group + '".');
1116
+ error = true;
1117
+ return false;
1118
+ }
1119
+ });
1120
+ }
1121
+ }
1122
+ });
1123
+
1124
+ if (error) {
1125
+ return false;
1126
+ }
1127
+ }
1128
+ });
1129
+
1130
+ if (error) {
1131
+ return false;
1132
+ }
1133
+ });
1134
+
1135
+ jQuery('#mobile_add').click(function() {
1136
+ var group = prompt('Enter group name (only "0-9", "a-z", "_" symbols are allowed).');
1137
+
1138
+ if (group !== null) {
1139
+ group = group.toLowerCase();
1140
+ group = group.replace(/[^0-9a-z_]+/g, '_');
1141
+ group = group.replace(/^_+/, '');
1142
+ group = group.replace(/_+$/, '');
1143
+
1144
+ if (group) {
1145
+ var exists = false;
1146
+
1147
+ jQuery('.mobile_group').each(function() {
1148
+ if (jQuery(this).html() == group) {
1149
+ alert('Group already exists!');
1150
+ exists = true;
1151
+ return false;
1152
+ }
1153
+ });
1154
+
1155
+ if (!exists) {
1156
+ var li = jQuery('<li id="mobile_group_' + group + '"><table class="form-table"><tr><th>Group name:</th><td><span class="mobile_group_number">' + (jQuery('#mobile_groups li').size() + 1) + '.</span> <span class="mobile_group">' + group + '</span> <input type="button" class="button mobile_delete" value="Delete group" /></td></tr><tr><th><label for="mobile_groups_' + group + '_enabled">Enabled:</label></th><td><input type="hidden" name="mobile_groups[' + group + '][enabled]" value="0" /><input id="mobile_groups_' + group + '_enabled" type="checkbox" name="mobile_groups[' + group + '][enabled]" value="1" checked="checked" /></td></tr><tr><th><label for="mobile_groups_' + group + '_theme">Theme:</label></th><td><select id="mobile_groups_' + group + '_theme" name="mobile_groups[' + group + '][theme]"><option value="">-- Pass-through --</option></select><br /><span class="description">Assign this group of user agents to a specific them. Leaving this option "Active Theme" allows any plugins you have (e.g. mobile plugins) to properly handle requests for these user agents. If the "redirect users to" field is not empty, this setting is ignored.</span></td></tr><tr><th><label for="mobile_groups_' + group + '_redirect">Redirect users to:</label></th><td><input id="mobile_groups_' + group + '_redirect" type="text" name="mobile_groups[' + group + '][redirect]" value="" size="60" /><br /><span class="description">A 302 redirect is used to send this group of users to another hostname (domain); recommended if a 3rd party service provides a mobile version of your site.</span></td></tr><tr><th><label for="mobile_groups_' + group + '_agents">User agents:</label></th><td><textarea id="mobile_groups_' + group + '_agents" name="mobile_groups[' + group + '][agents]" rows="10" cols="50"></textarea><br /><span class="description">Specify the user agents for this group.</span></td></tr></table></li>');
1157
+ var select = li.find('select');
1158
+
1159
+ jQuery.each(mobile_themes, function(index, value) {
1160
+ select.append(jQuery('<option />').val(index).html(value));
1161
+ });
1162
+
1163
+ jQuery('#mobile_groups').append(li);
1164
+ w3tc_mobile_groups_clear();
1165
+ window.location.hash = '#mobile_group_' + group;
1166
+ li.find('textarea').focus();
1167
+ }
1168
+ } else {
1169
+ alert('Empty group name!');
1170
+ }
1171
+ }
1172
+ });
1173
+
1174
+ jQuery('.mobile_delete').live('click', function() {
1175
+ if (confirm('Are you sure want to delete this group?')) {
1176
+ jQuery(this).parents('#mobile_groups li').remove();
1177
+ w3tc_mobile_groups_clear();
1178
+ w3tc_beforeupload_bind();
1179
+ }
1180
+ });
1181
+
1182
+ w3tc_mobile_groups_clear();
1183
+
1184
+ // referrer tab
1185
+ jQuery('#referrer_form').submit(function() {
1186
+ var error = false;
1187
+
1188
+ jQuery('#referrer_groups li').each(function() {
1189
+ if (jQuery(this).find(':checked').size()) {
1190
+ var group = jQuery(this).find('.referrer_group').text();
1191
+ var theme = jQuery(this).find(':selected').val();
1192
+ var redirect = jQuery(this).find('input[type=text]').val();
1193
+ var agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1194
+
1195
+ jQuery('#referrer_groups li').each(function() {
1196
+ if (jQuery(this).find(':checked').size()) {
1197
+ var compare_group = jQuery(this).find('.referrer_group').text();
1198
+ if (compare_group != group) {
1199
+ var compare_theme = jQuery(this).find(':selected').val();
1200
+ var compare_redirect = jQuery(this).find('input[type=text]').val();
1201
+ var compare_agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1202
+
1203
+ if (compare_redirect == '' && redirect == '' && compare_theme != '' && compare_theme == theme) {
1204
+ alert('Duplicate theme "' + compare_theme + '" found in the group "' + group + '".');
1205
+ error = true;
1206
+ return false;
1207
+ }
1208
+
1209
+ if (compare_redirect != '' && compare_redirect == redirect) {
1210
+ alert('Duplicate redirect "' + compare_redirect + '" found in the group "' + group + '".');
1211
+ error = true;
1212
+ return false;
1213
+ }
1214
+
1215
+ jQuery.each(compare_agents, function(index, value) {
1216
+ if (jQuery.inArray(value, agents) != -1) {
1217
+ alert('Duplicate stem "' + value + '" found in the group "' + compare_group + '".');
1218
+ error = true;
1219
+ return false;
1220
+ }
1221
+ });
1222
+ }
1223
+ }
1224
+ });
1225
+
1226
+ if (error) {
1227
+ return false;
1228
+ }
1229
+ }
1230
+ });
1231
+
1232
+ if (error) {
1233
+ return false;
1234
+ }
1235
+ });
1236
+
1237
+ jQuery('#referrer_add').click(function() {
1238
+ var group = prompt('Enter group name (only "0-9", "a-z", "_" symbols are allowed).');
1239
+
1240
+ if (group !== null) {
1241
+ group = group.toLowerCase();
1242
+ group = group.replace(/[^0-9a-z_]+/g, '_');
1243
+ group = group.replace(/^_+/, '');
1244
+ group = group.replace(/_+$/, '');
1245
+
1246
+ if (group) {
1247
+ var exists = false;
1248
+
1249
+ jQuery('.referrer_group').each(function() {
1250
+ if (jQuery(this).html() == group) {
1251
+ alert('Group already exists!');
1252
+ exists = true;
1253
+ return false;
1254
+ }
1255
+ });
1256
+
1257
+ if (!exists) {
1258
+ var li = jQuery('<li id="referrer_group_' + group + '"><table class="form-table"><tr><th>Group name:</th><td><span class="referrer_group_number">' + (jQuery('#referrer_groups li').size() + 1) + '.</span> <span class="referrer_group">' + group + '</span> <input type="button" class="button referrer_delete" value="Delete group" /></td></tr><tr><th><label for="referrer_groups_' + group + '_enabled">Enabled:</label></th><td><input type="hidden" name="referrer_groups[' + group + '][enabled]" value="0" /><input id="referrer_groups_' + group + '_enabled" type="checkbox" name="referrer_groups[' + group + '][enabled]" value="1" checked="checked" /></td></tr><tr><th><label for="referrer_groups_' + group + '_theme">Theme:</label></th><td><select id="referrer_groups_' + group + '_theme" name="referrer_groups[' + group + '][theme]"><option value="">-- Pass-through --</option></select><br /><span class="description">Assign this group of referrers to a specific them. Leaving this option "Active Theme" allows any plugins you have (e.g. referrer plugins) to properly handle requests for these referrers. If the "redirect users to" field is not empty, this setting is ignored.</span></td></tr><tr><th><label for="referrer_groups_' + group + '_redirect">Redirect users to:</label></th><td><input id="referrer_groups_' + group + '_redirect" type="text" name="referrer_groups[' + group + '][redirect]" value="" size="60" /><br /><span class="description">A 302 redirect is used to send this group of users to another hostname (domain); recommended if a 3rd party service provides a referrer version of your site.</span></td></tr><tr><th><label for="referrer_groups_' + group + '_referrers">Referrers:</label></th><td><textarea id="referrer_groups_' + group + '_referrers" name="referrer_groups[' + group + '][referrers]" rows="10" cols="50"></textarea><br /><span class="description">Specify the referrers for this group.</span></td></tr></table></li>');
1259
+ var select = li.find('select');
1260
+
1261
+ jQuery.each(referrer_themes, function(index, value) {
1262
+ select.append(jQuery('<option />').val(index).html(value));
1263
+ });
1264
+
1265
+ jQuery('#referrer_groups').append(li);
1266
+ w3tc_referrer_groups_clear();
1267
+ window.location.hash = '#referrer_group_' + group;
1268
+ li.find('textarea').focus();
1269
+ }
1270
+ } else {
1271
+ alert('Empty group name!');
1272
+ }
1273
+ }
1274
+ });
1275
+
1276
+ jQuery('.referrer_delete').live('click', function() {
1277
+ if (confirm('Are you sure want to delete this group?')) {
1278
+ jQuery(this).parents('#referrer_groups li').remove();
1279
+ w3tc_referrer_groups_clear();
1280
+ w3tc_beforeupload_bind();
1281
+ }
1282
+ });
1283
+
1284
+ w3tc_referrer_groups_clear();
1285
+
1286
+ // add sortable
1287
+ if (jQuery.ui && jQuery.ui.sortable) {
1288
+ jQuery('#js_files,#css_files').sortable({
1289
+ axis: 'y',
1290
+ stop: function() {
1291
+ jQuery(this).find('li').each(function(index) {
1292
+ jQuery(this).find('td:eq(0)').html((index + 1) + '.');
1293
+ });
1294
+ }
1295
+ });
1296
+
1297
+ jQuery('#cdn_cnames').sortable({
1298
+ axis: 'y',
1299
+ stop: w3tc_cdn_cnames_assign
1300
+ });
1301
+
1302
+ jQuery('#mobile_groups').sortable({
1303
+ axis: 'y',
1304
+ stop: function() {
1305
+ jQuery('#mobile_groups').find('.mobile_group_number').each(function(index) {
1306
+ jQuery(this).html((index + 1) + '.');
1307
+ });
1308
+ }
1309
+ });
1310
+
1311
+ jQuery('#referrer_groups').sortable({
1312
+ axis: 'y',
1313
+ stop: function() {
1314
+ jQuery('#referrer_groups').find('.referrer_group_number').each(function(index) {
1315
+ jQuery(this).html((index + 1) + '.');
1316
+ });
1317
+ }
1318
+ });
1319
+ }
1320
+
1321
+ // show hide rules
1322
+ jQuery('.w3tc-show-rules').click(function() {
1323
+ var btn = jQuery(this), rules = btn.parent().find('.w3tc-rules');
1324
+
1325
+ if (rules.is(':visible')) {
1326
+ rules.css('display', 'none');
1327
+ btn.val('view code');
1328
+ } else {
1329
+ rules.css('display', 'block');
1330
+ btn.val('hide code');
1331
+ }
1332
+ });
1333
+
1334
+
1335
+ // show hide missing files
1336
+ jQuery('.w3tc-show-required-changes').click(function() {
1337
+ var btn = jQuery(this), rules = jQuery('.w3tc-required-changes');
1338
+
1339
+ if (rules.is(':visible')) {
1340
+ rules.css('display', 'none');
1341
+ btn.val('View required changes');
1342
+ } else {
1343
+ rules.css('display', 'block');
1344
+ btn.val('Hide required changes');
1345
+ }
1346
+ });
1347
+
1348
+ // show hide missing files
1349
+ jQuery('.w3tc-show-ftp-form').click(function() {
1350
+ var btn = jQuery(this), rules = jQuery('.w3tc-ftp-form');
1351
+
1352
+ if (rules.is(':visible')) {
1353
+ rules.css('display', 'none');
1354
+ btn.val('Update via FTP');
1355
+ } else {
1356
+ rules.css('display', 'block');
1357
+ btn.val('Cancel FTP Update');
1358
+ }
1359
+ });
1360
+
1361
+ // show hide missing files
1362
+ jQuery('.w3tc-show-technical-info').click(function() {
1363
+ var btn = jQuery(this), info = jQuery('.w3tc-technical-info');
1364
+
1365
+ if (info.is(':visible')) {
1366
+ info.css('display', 'none');
1367
+ btn.val('Technical Information');
1368
+ } else {
1369
+ info.css('display', 'block');
1370
+ btn.val('Hide technical information');
1371
+ }
1372
+ });
1373
+
1374
+ // add ignore class to the ftp form elements
1375
+ jQuery('#ftp_upload_form').find('input').each(function() {
1376
+ jQuery(this).addClass('w3tc-ignore-change');
1377
+ });
1378
+
1379
+ // toggle hiddent content
1380
+ jQuery('.w3tc_link_more').click(function() {
1381
+ var target_class = jQuery(this).metadata().for_class;
1382
+ jQuery('.' + target_class).slideToggle();
1383
+ });
1384
+
1385
+ // check for unsaved changes
1386
+ jQuery('#w3tc input,#w3tc select,#w3tc textarea').live('change', function() {
1387
+ var ignore = false;
1388
+ jQuery(this).parents().andSelf().each(function() {
1389
+ if (jQuery(this).hasClass('w3tc-ignore-change') || jQuery(this).hasClass('lightbox')) {
1390
+ ignore = true;
1391
+ return false;
1392
+ }
1393
+ });
1394
+
1395
+ if (!ignore) {
1396
+ w3tc_beforeupload_bind();
1397
+ }
1398
+ });
1399
+
1400
+ jQuery('body').on('click', '.w3tc-button-save', w3tc_beforeupload_unbind);
1401
+
1402
+
1403
+ jQuery('.contextual-help-tabs ul li a').click(function() {
1404
+ var id = jQuery(this).attr('aria-controls');
1405
+ var i = jQuery('#' + id + ' .w3tchelp_content');
1406
+ w3tc_load_faq_section(i);
1407
+ });
1408
+
1409
+ jQuery('#contextual-help-link').click(function() {
1410
+ var i = jQuery('.w3tchelp_content').first();
1411
+ w3tc_load_faq_section(i);
1412
+ });
1413
+
1414
+ var w3tchelp_loaded = {};
1415
+ function w3tc_load_faq_section(i) {
1416
+ var section = i.attr('data-section');
1417
+
1418
+ if (w3tchelp_loaded[section])
1419
+ return;
1420
+
1421
+ i.html('<div class="w3tchelp_loading_outer">' +
1422
+ '<div class="w3tc-loading w3tchelp_loading_inner"></div></div>');
1423
+
1424
+ w3tchelp_loaded[section] = true;
1425
+
1426
+ jQuery.getJSON(ajaxurl, {
1427
+ action: 'w3tc_ajax',
1428
+ _wpnonce: w3tc_nonce,
1429
+ w3tc_action: 'faq',
1430
+ section: section
1431
+ }, function(data) {
1432
+ i.html(data.content)
1433
+ }).fail(function() {
1434
+ i.html('Failed to obtain data');
1435
+ });
1436
+ }
1437
+
1438
+ // extensions page
1439
+ jQuery('.w3tc_extensions_manage_input_checkall').click(function(v) {
1440
+ var c = jQuery(this).is(':checked');
1441
+
1442
+ jQuery('.w3tc_extensions_manage_input_checkall').prop('checked', c);
1443
+ jQuery('.w3tc_extensions_input_active').each(function(index) {
1444
+ if (!jQuery(this).is(':disabled'))
1445
+ jQuery(this).prop('checked', c);
1446
+ });
1447
+ });
1448
+
1449
+ // google analytics events
1450
+ if (typeof ga != 'undefined') {
1451
+ jQuery('.w3tc_error').each(function() {
1452
+ var id = jQuery(this).attr('id');
1453
+ var text = jQuery(this).text();
1454
+ if (id)
1455
+ ga('send', 'event', 'w3tc_error', id, text);
1456
+ });
1457
+ jQuery('.w3tc_note').each(function() {
1458
+ var id = jQuery(this).attr('id');
1459
+ var text = jQuery(this).text();
1460
+ if (id)
1461
+ ga('send', 'event', 'w3tc_note', id, text);
1462
+ });
1463
+
1464
+ jQuery('body').on('click', 'a', function() {
1465
+ var url = jQuery(this).attr('href');
1466
+ if (url)
1467
+ ga('send', 'event', 'anchor', 'click', url, {useBeacon: true});
1468
+ });
1469
+
1470
+ jQuery('body').on('click', 'input[type="button"]', function() {
1471
+ var name = jQuery(this).attr('name');
1472
+ if (name)
1473
+ ga('send', 'event', 'button', 'click', name, {useBeacon: true});
1474
+ });
1475
+ jQuery('body').on('click', 'input[type="submit"]', function() {
1476
+ var name = jQuery(this).attr('name');
1477
+ var id = jQuery(this).attr('id');
1478
+ if (!id)
1479
+ id = name;
1480
+
1481
+ if (name)
1482
+ ga('send', 'event', 'button', id, name, {useBeacon: true});
1483
+ });
1484
+
1485
+ jQuery('body').on('click', 'input[type="checkbox"]', function() {
1486
+ var name = jQuery(this).attr('name');
1487
+ var action = jQuery(this).is(':checked') ? 'check' : 'uncheck';
1488
+
1489
+ if (name)
1490
+ ga('send', 'event', 'checkbox', action, name);
1491
+ });
1492
+
1493
+ jQuery('body').on('change', 'select', function() {
1494
+ var name = jQuery(this).attr('name');
1495
+ var value = jQuery(this).val();
1496
+
1497
+ if (name && value)
1498
+ ga('send', 'event', 'select', value, name);
1499
+ });
1500
+ }
1501
  });
1502
+
readme.txt CHANGED
@@ -2,8 +2,8 @@
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: 4.9.1
6
- Stable tag: 0.9.6
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -283,19 +283,48 @@ Please reach out to all of these people and support their projects if you're so
283
 
284
  == Changelog ==
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  = 0.9.6 =
287
  * Fixed anonymous usage tracking, default to disabled
288
  * Fixed incorrect minify cache data written if target directory missing
289
  * Fixed empty minify cache file written when file locking enabled
290
- * Fixed missing commas in CSS (@nigrosimone)
291
- * Fixed typo in object cache engine (@Furniel)
292
  * Fixed incorrect reuse of redis connections when persistent connections option enabled
293
  * Fixed reliability of Google Drive (via jikamens)
294
  * Fixed handling of UTF-8 encoded files by writing them in binary (via jikamens)
295
  * Improved Full Site Delivery configuration user flow on the General and CDN settings screens
296
  * Improved content type matching and cache hits as a result
297
  * Improved minify file locking logic
298
- * Improved visual langage of the compatibility test (@Furniel)
299
  * Improved configuration file management
300
  * Improved MaxCDN set up wizard
301
  * Improved page cache's accepted query string handling to handle optional values and add support for disk enhanced mode (via amiga-500, nigrosimone)
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: 4.9.5
6
+ Stable tag: 0.9.7
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
283
 
284
  == Changelog ==
285
 
286
+ = 0.9.7 =
287
+ * Fixed minified files not being hosted by CDN when enabled if "host minified files" is disabled
288
+ * Fixed warning thrown when purge all was selected (via nigrosimone)
289
+ * Fixed undefined offset error in fragment cache
290
+ * Fixed MaxCDN test button failure when debug mode is enabled
291
+ * Fixed purging of feeds when cache feeds option is enabeld
292
+ * Improved handling of errors when full site delivery isn't set
293
+ * Improved nginx.conf to support xml caching
294
+ * Improved nginx.conf to support HSTS for static files
295
+ * Improved minify's handling of query strings
296
+ * Improved database caching, frequent wp_options no longer flush posts or comments data
297
+ * Improved Limelight Networks CDN integration
298
+ * Improved FAQ, they're now hosted in the GitHub public repository
299
+ * Improved handling for /*<![CDATA[*/ in HTML minify engine
300
+ * Imporved garbage collection for basic disk caching
301
+ * Improved HSTS support (via Dave Welsh)
302
+ * Improved reliabilty of CSS embed options
303
+ * Improved New Relic requirements in compatibility test
304
+ * Added StackPath CDN integration (including full site delivery)
305
+ * Added support for page cache priming via WP-CLI via prime function
306
+ * Added filter support for managing cache groups
307
+ * Added API for flushing individual cache groups via flush_group function
308
+ * Added purge support for JSON cache e.g. cached REST API requests
309
+ * Added filter support for managing database cache settings
310
+ * Added filter support before (w3tc_process_content) and after (w3tc_processed_content) a cache object is created
311
+ * Added compatibility for AMPforWP plugin
312
+ * Added JSON caching support for Pro subscribers
313
+ * Added additional security headers (via amiga-500)
314
+
315
  = 0.9.6 =
316
  * Fixed anonymous usage tracking, default to disabled
317
  * Fixed incorrect minify cache data written if target directory missing
318
  * Fixed empty minify cache file written when file locking enabled
319
+ * Fixed missing commas in CSS (via nigrosimone)
320
+ * Fixed typo in object cache engine (via Furniel)
321
  * Fixed incorrect reuse of redis connections when persistent connections option enabled
322
  * Fixed reliability of Google Drive (via jikamens)
323
  * Fixed handling of UTF-8 encoded files by writing them in binary (via jikamens)
324
  * Improved Full Site Delivery configuration user flow on the General and CDN settings screens
325
  * Improved content type matching and cache hits as a result
326
  * Improved minify file locking logic
327
+ * Improved visual langage of the compatibility test (via Furniel)
328
  * Improved configuration file management
329
  * Improved MaxCDN set up wizard
330
  * Improved page cache's accepted query string handling to handle optional values and add support for disk enhanced mode (via amiga-500, nigrosimone)
w3-total-cache-api.php CHANGED
@@ -5,7 +5,7 @@ if ( !defined( 'ABSPATH' ) ) {
5
  }
6
 
7
  define( 'W3TC', true );
8
- define( 'W3TC_VERSION', '0.9.6' );
9
  define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
10
  define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
11
  define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
@@ -15,18 +15,20 @@ define( 'W3TC_FEED_URL', 'http://feeds.feedburner.com/W3TOTALCACHE' );
15
  define( 'W3TC_NEWS_FEED_URL', 'http://feeds.feedburner.com/W3EDGE' );
16
  define( 'W3TC_README_URL', 'http://plugins.svn.wordpress.org/w3-total-cache/trunk/readme.txt' );
17
  define( 'W3TC_SUPPORT_US_PRODUCT_URL', 'https://www.w3-edge.com/products/w3-total-cache/' );
18
- define( 'W3TC_SUPPORT_US_RATE_URL', 'http://wordpress.org/support/view/plugin-reviews/w3-total-cache?rate=5#postform' );
19
- define( 'W3TC_SUPPORT_US_TIMEOUT', 2592000 ); // 30 days
20
  define( 'W3TC_SUPPORT_US_TWEET', 'YES! I optimized the user experience of my website with the W3 Total Cache #WordPress #plugin by @w3edge! http://bit.ly/TeSBL3' );
21
  define( 'W3TC_EDGE_TIMEOUT', 7 * 24 * 60 * 60 );
22
  define( 'W3TC_SUPPORT_REQUEST_URL', 'https://www.w3-edge.com/w3tc-support/extra' );
23
  define( 'W3TC_SUPPORT_SERVICES_URL', 'https://www.w3-edge.com/w3tc/premium-widget.json' );
 
24
  define( 'W3TC_TRACK_URL', 'https://www.w3-edge.com/w3tc/track/' );
25
  define( 'W3TC_MAILLINGLIST_SIGNUP_URL', 'https://www.w3-edge.com/w3tc/emailsignup/' );
26
  define( 'NEWRELIC_SIGNUP_URL', 'http://bit.ly/w3tc-partner-newrelic-signup' );
27
  define( 'MAXCDN_SIGNUP_URL', 'http://bit.ly/w3tc-cdn-maxcdn-create-account' );
28
  define( 'MAXCDN_AUTHORIZE_URL', 'http://bit.ly/w3tc-cdn-maxcdn-authorize' );
29
  define( 'NETDNA_AUTHORIZE_URL', 'https://cp.netdna.com/i/w3tc' );
 
 
30
  define( 'GOOGLE_DRIVE_AUTHORIZE_URL', 'https://www.w3-edge.com/w3tcoa/google-drive/' );
31
 
32
  // this is the URL our updater / license checker pings. This should be the URL of the site with EDD installed
@@ -113,8 +115,13 @@ define( 'W3TC_MARKER_END_CDN', '# END W3TC CDN' );
113
  define( 'W3TC_MARKER_END_NEW_RELIC_CORE', '# END W3TC New Relic core' );
114
 
115
 
116
- if ( !defined( 'W3TC_EXTENSION_DIR' ) )
117
  define( 'W3TC_EXTENSION_DIR', ( defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins' ) );
 
 
 
 
 
118
 
119
  @ini_set( 'pcre.backtrack_limit', 4194304 );
120
  @ini_set( 'pcre.recursion_limit', 4194304 );
@@ -212,7 +219,7 @@ function w3tc_config() {
212
  }
213
 
214
  /**
215
- * Shortcut for url varnish flush
216
  */
217
  function w3tc_flush_all( $extras = null ) {
218
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
@@ -243,6 +250,14 @@ function w3tc_flush_url( $url, $extras = null ) {
243
  $o->flush_url( $url, $extras );
244
  }
245
 
 
 
 
 
 
 
 
 
246
 
247
 
248
  /**
5
  }
6
 
7
  define( 'W3TC', true );
8
+ define( 'W3TC_VERSION', '0.9.7' );
9
  define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
10
  define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
11
  define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
15
  define( 'W3TC_NEWS_FEED_URL', 'http://feeds.feedburner.com/W3EDGE' );
16
  define( 'W3TC_README_URL', 'http://plugins.svn.wordpress.org/w3-total-cache/trunk/readme.txt' );
17
  define( 'W3TC_SUPPORT_US_PRODUCT_URL', 'https://www.w3-edge.com/products/w3-total-cache/' );
18
+ define( 'W3TC_SUPPORT_US_RATE_URL', 'https://wordpress.org/support/plugin/w3-total-cache/reviews/#new-post' );
 
19
  define( 'W3TC_SUPPORT_US_TWEET', 'YES! I optimized the user experience of my website with the W3 Total Cache #WordPress #plugin by @w3edge! http://bit.ly/TeSBL3' );
20
  define( 'W3TC_EDGE_TIMEOUT', 7 * 24 * 60 * 60 );
21
  define( 'W3TC_SUPPORT_REQUEST_URL', 'https://www.w3-edge.com/w3tc-support/extra' );
22
  define( 'W3TC_SUPPORT_SERVICES_URL', 'https://www.w3-edge.com/w3tc/premium-widget.json' );
23
+ define( 'W3TC_FAQ_URL', 'https://github.com/Auctollo/w3-total-cache-public/wiki/FAQ' );
24
  define( 'W3TC_TRACK_URL', 'https://www.w3-edge.com/w3tc/track/' );
25
  define( 'W3TC_MAILLINGLIST_SIGNUP_URL', 'https://www.w3-edge.com/w3tc/emailsignup/' );
26
  define( 'NEWRELIC_SIGNUP_URL', 'http://bit.ly/w3tc-partner-newrelic-signup' );
27
  define( 'MAXCDN_SIGNUP_URL', 'http://bit.ly/w3tc-cdn-maxcdn-create-account' );
28
  define( 'MAXCDN_AUTHORIZE_URL', 'http://bit.ly/w3tc-cdn-maxcdn-authorize' );
29
  define( 'NETDNA_AUTHORIZE_URL', 'https://cp.netdna.com/i/w3tc' );
30
+ define( 'STACKPATH_SIGNUP_URL', 'http://bit.ly/w3tc-cdn-stackpath-create-account' );
31
+ define( 'STACKPATH_AUTHORIZE_URL', 'http://bit.ly/w3tc-cdn-stackpath-authorize' );
32
  define( 'GOOGLE_DRIVE_AUTHORIZE_URL', 'https://www.w3-edge.com/w3tcoa/google-drive/' );
33
 
34
  // this is the URL our updater / license checker pings. This should be the URL of the site with EDD installed
115
  define( 'W3TC_MARKER_END_NEW_RELIC_CORE', '# END W3TC New Relic core' );
116
 
117
 
118
+ if ( !defined( 'W3TC_EXTENSION_DIR' ) ) {
119
  define( 'W3TC_EXTENSION_DIR', ( defined( 'WP_PLUGIN_DIR' ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins' ) );
120
+ }
121
+
122
+ if ( !defined( 'W3TC_WP_JSON_URI' ) ) {
123
+ define( 'W3TC_WP_JSON_URI', '/wp-json/' );
124
+ }
125
 
126
  @ini_set( 'pcre.backtrack_limit', 4194304 );
127
  @ini_set( 'pcre.recursion_limit', 4194304 );
219
  }
220
 
221
  /**
222
+ * Purges/Flushes everything
223
  */
224
  function w3tc_flush_all( $extras = null ) {
225
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
250
  $o->flush_url( $url, $extras );
251
  }
252
 
253
+ /**
254
+ * Purges/Flushes separate cache group
255
+ */
256
+ function w3tc_flush_group( $group, $extras = null ) {
257
+ $o = \W3TC\Dispatcher::component( 'CacheFlush' );
258
+ $o->flush_group( $group, $extras );
259
+ }
260
+
261
 
262
 
263
  /**
w3-total-cache.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: W3 Total Cache
4
  Description: The highest rated and most complete WordPress performance plugin. Dramatically improve the speed and user experience of your site. Add browser, page, object and database caching as well as minify and content delivery network (CDN) to WordPress.
5
- Version: 0.9.6
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
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.9.7
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