W3 Total Cache - Version 0.9.6

Version Description

  • Fixed anonymous usage tracking, default to disabled
  • Fixed incorrect minify cache data written if target directory missing
  • Fixed empty minify cache file written when file locking enabled
  • Fixed missing commas in CSS (@nigrosimone)
  • Fixed typo in object cache engine (@Furniel)
  • Fixed incorrect reuse of redis connections when persistent connections option enabled
  • Fixed reliability of Google Drive (via jikamens)
  • Fixed handling of UTF-8 encoded files by writing them in binary (via jikamens)
  • Improved Full Site Delivery configuration user flow on the General and CDN settings screens
  • Improved content type matching and cache hits as a result
  • Improved minify file locking logic
  • Improved visual langage of the compatibility test (@Furniel)
  • Improved configuration file management
  • Improved MaxCDN set up wizard
  • Improved page cache's accepted query string handling to handle optional values and add support for disk enhanced mode (via amiga-500, nigrosimone)
  • Improved handling of timeouts to origin push CDN proviers
  • Added HTTP/2 push headers for disk enhanced page caching (via nigrosimone)
  • Added X-Forwarded-Proto header for use cases like HTTPS recognition behind proxies or load balancers
  • Added multiple CDN support i.e. static file objects and pages, posts, feeds, API responses etc to use different respective CDN providers
  • Added page caching by cookie name or value (sponsored by SQweb)
  • Added toggle for CORS header to improve inter-operatbility with various CDN providers
  • Added support for CDN hosted media to media library (inspired by amiga-500)
  • Added object caching of AJAX calls (via andyexeter)
  • Enterprise features are now available to Pro subscribers! Including reading from multiple databases concurrently and purging caches across multiple hosts via a Message Bus
Download this release

Release Info

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

Code changes from version 0.9.5.4 to 0.9.6

Files changed (221) hide show
  1. BrowserCache_Environment.php +17 -15
  2. Cache.php +0 -4
  3. CacheFlush.php +4 -4
  4. CacheFlush_Locally.php +15 -7
  5. Cache_File_Generic.php +40 -19
  6. Cache_Memcache.php +8 -0
  7. Cache_Memcached.php +8 -0
  8. Cache_Redis.php +12 -2
  9. CdnEngine.php +0 -4
  10. CdnEngine_Azure.php +8 -3
  11. CdnEngine_Base.php +13 -1
  12. CdnEngine_Ftp.php +7 -3
  13. CdnEngine_GoogleDrive.php +146 -47
  14. CdnEngine_Mirror_Akamai.php +0 -4
  15. CdnEngine_Mirror_Cotendo.php +0 -4
  16. CdnEngine_Mirror_Edgecast.php +0 -4
  17. CdnEngine_Mirror_MaxCdn.php +168 -4
  18. CdnEngine_Mirror_Netdna.php +0 -178
  19. CdnEngine_RackSpaceCloudFiles.php +7 -3
  20. CdnEngine_S3.php +40 -11
  21. CdnEngine_S3_Cf.php +16 -3
  22. CdnEngine_S3_Compatible.php +9 -3
  23. Cdn_AdminActions.php +20 -337
  24. Cdn_AdminNotes.php +1 -21
  25. Cdn_CloudFrontFsd_Page.php +0 -18
  26. Cdn_ConfigLabels.php +2 -0
  27. Cdn_Core.php +21 -10
  28. Cdn_Core_Admin.php +7 -7
  29. Cdn_Environment.php +66 -32
  30. Cdn_Fsd_Core.php +0 -41
  31. Cdn_GeneralPage_View.php +3 -1
  32. Cdn_Highwinds_Page_View.js +1 -1
  33. Cdn_Highwinds_Page_View.php +3 -3
  34. Cdn_Highwinds_Popup_View_ConfigureCnamesForm.php +1 -1
  35. Cdn_MaxCdnFsd_Page.php +0 -18
  36. Cdn_MaxCdn_Page.php +28 -0
  37. Cdn_MaxCdn_Page_View.js +68 -0
  38. Cdn_MaxCdn_Page_View.php +96 -0
  39. Cdn_MaxCdn_Popup.php +282 -0
  40. Cdn_MaxCdn_Popup_View_Intro.php +39 -0
  41. Cdn_MaxCdn_Popup_View_Success.php +23 -0
  42. Cdn_MaxCdn_Popup_View_Zone.php +74 -0
  43. Cdn_MaxCdn_Popup_View_Zones.php +53 -0
  44. Cdn_Page.php +0 -32
  45. Cdn_Page_View_Fsd_HeaderActions.php +1 -1
  46. Cdn_Plugin.php +67 -31
  47. Cdn_Plugin_Admin.php +55 -56
  48. Cdn_Plugin_WidgetMaxCdn.php +0 -9
  49. Cdn_Plugin_WidgetNetDna.php +0 -191
  50. Cdn_RackSpaceCdn_Page_View.js +1 -1
  51. Cdn_RackSpaceCdn_Page_View.php +3 -3
  52. Cdn_RackSpaceCdn_Popup_View_ConfigureDomains.php +1 -1
  53. Cdn_RackSpaceCloudFiles_Page_View.php +3 -3
  54. Cdn_Util.php +2 -23
  55. Cdn_Fsd_CacheFlush.php → Cdnfsd_CacheFlush.php +17 -11
  56. Cdn_CloudFrontFsd_Api.php → Cdnfsd_CloudFront_Api.php +1 -1
  57. Cdn_CloudFrontFsd_Engine.php → Cdnfsd_CloudFront_Engine.php +3 -3
  58. Cdnfsd_CloudFront_Page.php +18 -0
  59. Cdn_CloudFrontFsd_Page_View.js → Cdnfsd_CloudFront_Page_View.js +1 -1
  60. Cdn_CloudFrontFsd_Page_View.php → Cdnfsd_CloudFront_Page_View.php +5 -13
  61. Cdn_CloudFrontFsd_Popup.php → Cdnfsd_CloudFront_Popup.php +19 -19
  62. Cdn_CloudFrontFsd_Popup_View_Distribution.php → Cdnfsd_CloudFront_Popup_View_Distribution.php +0 -0
  63. Cdn_CloudFrontFsd_Popup_View_Distributions.php → Cdnfsd_CloudFront_Popup_View_Distributions.php +0 -0
  64. Cdn_CloudFrontFsd_Popup_View_Intro.php → Cdnfsd_CloudFront_Popup_View_Intro.php +2 -2
  65. Cdn_CloudFrontFsd_Popup_View_Success.php → Cdnfsd_CloudFront_Popup_View_Success.php +0 -0
  66. Cdnfsd_Core.php +54 -0
  67. Cdnfsd_GeneralPage_View.php +37 -0
  68. Cdnfsd_Limelight_Api.php +101 -0
  69. Cdnfsd_Limelight_Engine.php +85 -0
  70. Cdnfsd_Limelight_Page.php +18 -0
  71. Cdnfsd_Limelight_Page_View.js +42 -0
  72. Cdnfsd_Limelight_Page_View.php +43 -0
  73. Cdnfsd_Limelight_Popup.php +68 -0
  74. Cdnfsd_Limelight_Popup_View_Intro.php +49 -0
  75. Cdnfsd_Limelight_Popup_View_Success.php +22 -0
  76. Cdn_MaxCdnFsd_Engine.php → Cdnfsd_MaxCdn_Engine.php +1 -1
  77. Cdnfsd_MaxCdn_Page.php +20 -0
  78. Cdn_MaxCdnFsd_Page_View.js → Cdnfsd_MaxCdn_Page_View.js +17 -1
  79. Cdn_MaxCdnFsd_Page_View.php → Cdnfsd_MaxCdn_Page_View.php +5 -16
  80. Cdn_MaxCdnFsd_Popup.php → Cdnfsd_MaxCdn_Popup.php +53 -15
  81. Cdn_MaxCdnFsd_Popup_View_Intro.php → Cdnfsd_MaxCdn_Popup_View_Intro.php +0 -0
  82. Cdn_MaxCdnFsd_Popup_View_Success.php → Cdnfsd_MaxCdn_Popup_View_Success.php +0 -0
  83. Cdn_MaxCdnFsd_Popup_View_Zone.php → Cdnfsd_MaxCdn_Popup_View_Zone.php +6 -2
  84. Cdn_MaxCdnFsd_Popup_View_Zones.php → Cdnfsd_MaxCdn_Popup_View_Zones.php +0 -0
  85. Cdnfsd_Page_View_Header.php +15 -0
  86. Cdnfsd_Plugin.php +61 -0
  87. Cdnfsd_Plugin_Admin.php +91 -0
  88. Cdn_Fsd_Util.php → Cdnfsd_Util.php +9 -1
  89. Cli.php +26 -0
  90. Config.php +49 -24
  91. ConfigCache.php +108 -0
  92. ConfigCompiler.php +56 -52
  93. ConfigDbStorage.php +390 -0
  94. ConfigKeys.php +91 -41
  95. ConfigState.php +0 -2
  96. ConfigUtil.php +81 -0
  97. DbCache_Environment.php +7 -1
  98. DbCache_Wpdb.php +42 -2
  99. DbCache_WpdbInjection.php +8 -0
  100. DbCache_WpdbInjection_QueryCaching.php +23 -17
  101. Dispatcher.php +1 -14
  102. Enterprise_CacheFlush_MakeSnsEvent.php +10 -4
  103. Enterprise_Dbcache_WpdbInjection_Cluster.php +116 -43
  104. Extension_Amp_Plugin.php +3 -7
  105. Extension_CloudFlare_Api.php +1 -1
  106. Extension_CloudFlare_Cdn_Page_View.php +31 -0
  107. Extension_CloudFlare_Page.php +10 -2
  108. Extension_CloudFlare_Plugin_Admin.php +58 -6
  109. Extension_CloudFlare_Popup_View_Zones.php +41 -39
  110. Extension_CloudFlare_SettingsForUi.php +2 -2
  111. Extension_FragmentCache_Plugin_Admin.php +7 -8
  112. Extension_FragmentCache_WpObjectCache.php +12 -15
  113. Extension_NewRelic_Plugin.php +30 -13
  114. Extension_NewRelic_Plugin_Admin.php +6 -7
  115. Extension_NewRelic_Popup_View.js +8 -8
  116. Extension_Swarmify_Page.php +1 -8
  117. Extension_WordPressSeo_Plugin_Admin.php +0 -12
  118. Extensions_Plugin_Admin.php +7 -7
  119. Generic_AdminActions_Config.php +6 -36
  120. Generic_AdminActions_Default.php +9 -6
  121. Generic_AdminActions_EdgeMode.php +0 -28
  122. Generic_AdminActions_Flush.php +1 -1
  123. Generic_AdminActions_Test.php +8 -2
  124. Generic_ConfigLabels.php +1 -0
  125. Generic_Environment.php +8 -27
  126. Generic_Faq.php +0 -2
  127. Generic_GeneralPage_View_ShowEdge.js +3 -3
  128. Generic_GeneralPage_View_ShowSupportUs.js +6 -3
  129. Generic_Page_Dashboard_View.css +33 -20
  130. Generic_Page_General.php +0 -1
  131. Generic_Plugin.php +19 -18
  132. Generic_Plugin_Admin.php +13 -4
  133. Generic_Plugin_AdminCompatibility.php +0 -27
  134. Generic_Plugin_AdminNotifications.php +0 -29
  135. Minify_ContentMinifier.php +1 -1
  136. Minify_Plugin.php +25 -23
  137. Minify_Plugin_Admin.php +1 -3
  138. ModuleStatus.php +0 -16
  139. ObjectCache_Environment.php +7 -1
  140. ObjectCache_WpObjectCache_Regular.php +43 -36
  141. PageSpeed_Api.php +13 -5
  142. PageSpeed_Plugin_Widget.php +4 -2
  143. PgCache_ConfigLabels.php +4 -0
  144. PgCache_ContentGrabber.php +302 -134
  145. PgCache_Environment.php +166 -16
  146. PgCache_Flush.php +14 -8
  147. PgCache_Page.php +1 -3
  148. PgCache_Page_CookieGroups.php +78 -0
  149. PgCache_Page_CookieGroups_View.js +96 -0
  150. PgCache_Page_CookieGroups_View.php +113 -0
  151. PgCache_Plugin_Admin.php +43 -0
  152. Root_AdminActions.php +0 -1
  153. Root_AdminActivation.php +1 -1
  154. Root_AdminMenu.php +51 -36
  155. Root_Loader.php +10 -8
  156. Support_AdminActions.php +0 -2
  157. Util_Admin.php +3 -25
  158. Util_AttachToActions.php +12 -0
  159. Util_Debug.php +9 -0
  160. Util_Environment.php +26 -34
  161. Util_PageUrls.php +3 -1
  162. Util_Rule.php +9 -3
  163. Util_RuleSnippet.php +10 -33
  164. Util_Ui.php +1 -1
  165. inc/lightbox/edge.php +0 -24
  166. inc/lightbox/self_test.php +61 -60
  167. inc/lightbox/support_us.php +5 -1
  168. inc/lightbox/upgrade.php +2 -2
  169. inc/options/about.php +1 -1
  170. inc/options/cdn.php +17 -1
  171. inc/options/cdn/akamai.php +1 -1
  172. inc/options/cdn/att.php +2 -2
  173. inc/options/cdn/azure.php +1 -1
  174. inc/options/cdn/cf.php +24 -7
  175. inc/options/cdn/cf2.php +1 -1
  176. inc/options/cdn/common/cnames.php +13 -4
  177. inc/options/cdn/cotendo.php +2 -2
  178. inc/options/cdn/edgecast.php +2 -2
  179. inc/options/cdn/ftp.php +1 -1
  180. inc/options/cdn/maxcdn.php +0 -89
  181. inc/options/cdn/mirror.php +2 -2
  182. inc/options/cdn/netdna.php +0 -89
  183. inc/options/cdn/rscf.php +1 -1
  184. inc/options/cdn/s3.php +24 -6
  185. inc/options/cdn/s3_compatible.php +1 -1
  186. inc/options/common/header.php +1 -1
  187. inc/options/dashboard.php +2 -2
  188. inc/options/general.php +11 -32
  189. inc/options/minify.php +2 -2
  190. inc/options/minify/yuijs2.php +6 -6
  191. inc/options/pgcache.php +42 -6
  192. inc/popup/cdn_purge.php +1 -1
  193. inc/widget/maxcdn_signup.php +1 -30
  194. inc/widget/netdna.php +0 -64
  195. inc/widget/netdna_signup.php +0 -53
  196. ini/config-db-sample.php +34 -0
  197. ini/dbcluster-config-sample.php +175 -149
  198. ini/web.config +28 -3
  199. languages/faq-en_US.xml +6 -1
  200. languages/faq-pro-en_US.xml +4 -4
  201. languages/w3-total-cache.pot +1 -26
  202. lib/Minify/CSSmin.php +0 -758
  203. lib/Minify/Minify/CSS/UriRewriter.php +1 -2
  204. lib/Minify/Minify/Cache/File.php +3 -2
  205. lib/Minify/Minify/ClosureCompiler.php +8 -1
  206. lib/Minify/Minify/HTML.php +1 -1
  207. lib/Minify/Minify/YUICompressor.php +30 -24
  208. lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Colors.php +155 -0
  209. lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Command.php +223 -0
  210. lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Minifier.php +862 -0
  211. lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Utils.php +149 -0
  212. lib/NetDNA/NetDNA.php +424 -407
  213. lib/S3.php +1927 -429
  214. pub/css/lightbox.css +9 -0
  215. pub/css/options.css +185 -178
  216. pub/js/lightbox.js +3 -91
  217. pub/js/options.js +17 -280
  218. pub/opcache.php +1 -1
  219. readme.txt +29 -2
  220. w3-total-cache-api.php +20 -15
  221. w3-total-cache.php +1 -1
BrowserCache_Environment.php CHANGED
@@ -316,7 +316,7 @@ class BrowserCache_Environment {
316
  $rules .= " BrowserMatch \\bMSI[E] !no-gzip !gzip-only-text/html\n";
317
  $rules .= " </IfModule>\n";
318
  }
319
- if ( version_compare( $this->_get_server_version(), '2.3.7', '>=' ) ) {
320
  $rules .= " <IfModule mod_filter.c>\n";
321
  }
322
  $rules .= " AddOutputFilterByType DEFLATE " . implode( ' ', $compression_types ) . "\n";
@@ -325,7 +325,7 @@ class BrowserCache_Environment {
325
  $rules .= " AddOutputFilter DEFLATE js css htm html xml\n";
326
  $rules .= " </IfModule>\n";
327
 
328
- if ( version_compare( $this->_get_server_version(), '2.3.7', '>=' ) ) {
329
  $rules .= " </IfModule>\n";
330
  }
331
  $rules .= "</IfModule>\n";
@@ -585,10 +585,12 @@ class BrowserCache_Environment {
585
  $mime_types, $section ) {
586
 
587
  $expires = $config->get_boolean( 'browsercache.' . $section . '.expires' );
 
588
  $cache_control = $config->get_boolean( 'browsercache.' . $section . '.cache.control' );
589
  $w3tc = $config->get_boolean( 'browsercache.' . $section . '.w3tc' );
 
590
 
591
- if ( $expires || $cache_control || $w3tc ) {
592
  $lifetime = $config->get_integer( 'browsercache.' . $section . '.lifetime' );
593
 
594
  $extensions = array_keys( $mime_types );
@@ -604,6 +606,18 @@ class BrowserCache_Environment {
604
  if ( $expires ) {
605
  $rules .= " expires " . $lifetime . "s;\n";
606
  }
 
 
 
 
 
 
 
 
 
 
 
 
607
 
608
  $add_header_rules = '';
609
 
@@ -794,18 +808,6 @@ class BrowserCache_Environment {
794
  return $rules;
795
  }
796
 
797
- /**
798
- * Returns the apache, nginx version
799
- *
800
- * @return string
801
- */
802
- private function _get_server_version() {
803
- $sig= explode( '/', $_SERVER['SERVER_SOFTWARE'] );
804
- $temp = isset( $sig[1] ) ? explode( ' ', $sig[1] ) : array( '0' );
805
- $version = $temp[0];
806
- return $version;
807
- }
808
-
809
  /**
810
  * Takes an array of extensions single per row and/or extensions delimited by |
811
  *
316
  $rules .= " BrowserMatch \\bMSI[E] !no-gzip !gzip-only-text/html\n";
317
  $rules .= " </IfModule>\n";
318
  }
319
+ if ( version_compare( Util_Environment::get_server_version(), '2.3.7', '>=' ) ) {
320
  $rules .= " <IfModule mod_filter.c>\n";
321
  }
322
  $rules .= " AddOutputFilterByType DEFLATE " . implode( ' ', $compression_types ) . "\n";
325
  $rules .= " AddOutputFilter DEFLATE js css htm html xml\n";
326
  $rules .= " </IfModule>\n";
327
 
328
+ if ( version_compare( Util_Environment::get_server_version(), '2.3.7', '>=' ) ) {
329
  $rules .= " </IfModule>\n";
330
  }
331
  $rules .= "</IfModule>\n";
585
  $mime_types, $section ) {
586
 
587
  $expires = $config->get_boolean( 'browsercache.' . $section . '.expires' );
588
+ $etag = $config->get_boolean( 'browsercache.' . $section . '.etag' );
589
  $cache_control = $config->get_boolean( 'browsercache.' . $section . '.cache.control' );
590
  $w3tc = $config->get_boolean( 'browsercache.' . $section . '.w3tc' );
591
+ $last_modified = $config->get_boolean( 'browsercache.' . $section . '.last_modified' );
592
 
593
+ if ( $etag || $expires || $cache_control || $w3tc || !$last_modified ) {
594
  $lifetime = $config->get_integer( 'browsercache.' . $section . '.lifetime' );
595
 
596
  $extensions = array_keys( $mime_types );
606
  if ( $expires ) {
607
  $rules .= " expires " . $lifetime . "s;\n";
608
  }
609
+ if ( version_compare( Util_Environment::get_server_version(), '1.3.3', '>=' ) ) {
610
+ if ( $etag ) {
611
+ $rules .= " etag on;\n";
612
+ } else {
613
+ $rules .= " etag off;\n";
614
+ }
615
+ }
616
+ if ( $last_modified ) {
617
+ $rules .= " if_modified_since exact;\n";
618
+ } else {
619
+ $rules .= " if_modified_since off;\n";
620
+ }
621
 
622
  $add_header_rules = '';
623
 
808
  return $rules;
809
  }
810
 
 
 
 
 
 
 
 
 
 
 
 
 
811
  /**
812
  * Takes an array of extensions single per row and/or extensions delimited by |
813
  *
Cache.php CHANGED
@@ -166,10 +166,6 @@ class Cache {
166
  $engine_name = 'mirror';
167
  break;
168
 
169
- case 'netdna':
170
- $engine_name = 'netdna';
171
- break;
172
-
173
  case 'maxcdn':
174
  $engine_name = 'maxcdn';
175
  break;
166
  $engine_name = 'mirror';
167
  break;
168
 
 
 
 
 
169
  case 'maxcdn':
170
  $engine_name = 'maxcdn';
171
  break;
CacheFlush.php CHANGED
@@ -128,8 +128,8 @@ class CacheFlush {
128
  /**
129
  * Purges/Flushes post page
130
  */
131
- function flush_post( $post_id ) {
132
- return $this->_executor->flush_post( $post_id );
133
  }
134
 
135
  /**
@@ -162,12 +162,12 @@ class CacheFlush {
162
  /**
163
  * Purges/Flushes url
164
  */
165
- function flush_url( $url ) {
166
  static $flushed_urls = array();
167
 
168
  if ( !in_array( $url, $flushed_urls ) ) {
169
  $flushed_urls[] = $url;
170
- return $this->_executor->flush_url( $url );
171
  }
172
  return true;
173
  }
128
  /**
129
  * Purges/Flushes post page
130
  */
131
+ function flush_post( $post_id, $extras = null ) {
132
+ return $this->_executor->flush_post( $post_id, $extras );
133
  }
134
 
135
  /**
162
  /**
163
  * Purges/Flushes url
164
  */
165
+ function flush_url( $url, $extras = null ) {
166
  static $flushed_urls = array();
167
 
168
  if ( !in_array( $url, $flushed_urls ) ) {
169
  $flushed_urls[] = $url;
170
+ return $this->_executor->flush_url( $url, $extras );
171
  }
172
  return true;
173
  }
CacheFlush_Locally.php CHANGED
@@ -83,7 +83,7 @@ class CacheFlush_Locally {
83
  function minifycache_flush_all( $extras = array() ) {
84
  if ( $extras['minify'] == 'purge_map' )
85
  delete_option( 'w3tc_minify' );
86
-
87
  $this->minifycache_flush( $extras );
88
  }
89
 
@@ -156,8 +156,10 @@ class CacheFlush_Locally {
156
  /**
157
  * Purges/Flushes post from page cache, varnish and cdn cache
158
  */
159
- function flush_post( $post_id ) {
160
- do_action( 'w3tc_flush_post', $post_id );
 
 
161
  }
162
 
163
  /**
@@ -165,7 +167,9 @@ class CacheFlush_Locally {
165
  * When global changes affect whole content but not internal data structures
166
  */
167
  function flush_posts( $extras = null ) {
168
- do_action( 'w3tc_flush_posts', $extras );
 
 
169
  }
170
 
171
  /**
@@ -198,14 +202,18 @@ class CacheFlush_Locally {
198
  $default_actions_added = true;
199
  }
200
 
201
- do_action( 'w3tc_flush_all', $extras );
 
 
202
  }
203
 
204
  /**
205
  * Purges/Flushes url from page cache, varnish and cdn cache
206
  */
207
- function flush_url( $url ) {
208
- do_action( 'w3tc_flush_url', $url );
 
 
209
  }
210
 
211
  /**
83
  function minifycache_flush_all( $extras = array() ) {
84
  if ( $extras['minify'] == 'purge_map' )
85
  delete_option( 'w3tc_minify' );
86
+
87
  $this->minifycache_flush( $extras );
88
  }
89
 
156
  /**
157
  * Purges/Flushes post from page cache, varnish and cdn cache
158
  */
159
+ function flush_post( $post_id, $extras = null ) {
160
+ $do_flush = apply_filters( 'w3tc_preflush_post', true, $extras );
161
+ if ( $do_flush )
162
+ do_action( 'w3tc_flush_post', $post_id );
163
  }
164
 
165
  /**
167
  * When global changes affect whole content but not internal data structures
168
  */
169
  function flush_posts( $extras = null ) {
170
+ $do_flush = apply_filters( 'w3tc_preflush_posts', true, $extras );
171
+ if ( $do_flush )
172
+ do_action( 'w3tc_flush_posts', $extras );
173
  }
174
 
175
  /**
202
  $default_actions_added = true;
203
  }
204
 
205
+ $do_flush = apply_filters( 'w3tc_preflush_all', true, $extras );
206
+ if ( $do_flush )
207
+ do_action( 'w3tc_flush_all', $extras );
208
  }
209
 
210
  /**
211
  * Purges/Flushes url from page cache, varnish and cdn cache
212
  */
213
+ function flush_url( $url, $extras = null ) {
214
+ $do_flush = apply_filters( 'w3tc_preflush_url', true, $extras );
215
+ if ( $do_flush )
216
+ do_action( 'w3tc_flush_url', $url );
217
  }
218
 
219
  /**
Cache_File_Generic.php CHANGED
@@ -2,13 +2,7 @@
2
  namespace W3TC;
3
 
4
  /**
5
- * Generic file cache
6
- */
7
-
8
-
9
-
10
- /**
11
- * class Cache_File_Generic
12
  */
13
  class Cache_File_Generic extends Cache_File {
14
  /**
@@ -56,7 +50,7 @@ class Cache_File_Generic extends Cache_File {
56
 
57
  $tmppath = $path . '.' . getmypid();
58
 
59
- $fp = @fopen( $tmppath, 'w' );
60
  if ( !$fp )
61
  return false;
62
 
@@ -83,16 +77,43 @@ class Cache_File_Generic extends Cache_File {
83
  $old_entry_path = $path . '_old';
84
  @unlink( $old_entry_path );
85
 
86
- if ( Util_Environment::is_apache() && isset( $var['headers'] ) &&
87
- isset( $var['headers']['Content-Type'] ) &&
88
- substr( $var['headers']['Content-Type'], 0, 8 ) == 'text/xml' ) {
89
- file_put_contents( dirname( $path ) . '/.htaccess',
90
- "<IfModule mod_mime.c>\n" .
91
- " RemoveType .html_gzip\n" .
92
- " AddType text/xml .html_gzip\n" .
93
- " RemoveType .html\n" .
94
- " AddType text/xml .html\n".
95
- "</IfModule>" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
 
98
  return true;
@@ -147,7 +168,7 @@ class Cache_File_Generic extends Cache_File {
147
  if ( !is_readable( $path ) )
148
  return null;
149
 
150
- $fp = @fopen( $path, 'r' );
151
  if ( !$fp )
152
  return null;
153
 
2
  namespace W3TC;
3
 
4
  /**
5
+ * Disk:Enhanced file cache
 
 
 
 
 
 
6
  */
7
  class Cache_File_Generic extends Cache_File {
8
  /**
50
 
51
  $tmppath = $path . '.' . getmypid();
52
 
53
+ $fp = @fopen( $tmppath, 'wb' );
54
  if ( !$fp )
55
  return false;
56
 
77
  $old_entry_path = $path . '_old';
78
  @unlink( $old_entry_path );
79
 
80
+ if ( Util_Environment::is_apache() && isset( $var['headers'] ) ) {
81
+ $rules = '';
82
+
83
+ if ( isset( $var['headers']['Content-Type'] ) &&
84
+ substr( $var['headers']['Content-Type'], 0, 8 ) == 'text/xml' ) {
85
+
86
+ $rules .= "<IfModule mod_mime.c>\n";
87
+ $rules .= " RemoveType .html_gzip\n";
88
+ $rules .= " AddType text/xml .html_gzip\n";
89
+ $rules .= " RemoveType .html\n";
90
+ $rules .= " AddType text/xml .html\n";
91
+ $rules .= "</IfModule>\n";
92
+ }
93
+
94
+ if ( isset( $var['headers'] ) ) {
95
+ $links = '';
96
+
97
+ foreach ( $var['headers'] as $h ) {
98
+ if ( isset($h['n']) && isset($h['v']) && $h['n'] == 'Link' ) {
99
+ $value = $h['v'];
100
+ if ( false !== strpos( $value, 'rel=preload' ) ) {
101
+ $links .= " Header add Link '" . trim($value) . "'\n";
102
+ }
103
+ }
104
+ }
105
+
106
+ if ( !empty( $links) ) {
107
+ $rules .= "<IfModule mod_headers.c>\n";
108
+ $rules .= " Header unset Link\n";
109
+ $rules .= $links;
110
+ $rules .= "</IfModule>\n";
111
+ }
112
+ }
113
+
114
+ if ( !empty($rules) ) {
115
+ @file_put_contents( dirname( $path ) . '/.htaccess', $rules );
116
+ }
117
  }
118
 
119
  return true;
168
  if ( !is_readable( $path ) )
169
  return null;
170
 
171
+ $fp = @fopen( $path, 'rb' );
172
  if ( !$fp )
173
  return null;
174
 
Cache_Memcache.php CHANGED
@@ -44,6 +44,14 @@ class Cache_Memcache extends Cache_Base {
44
  return false;
45
  }
46
 
 
 
 
 
 
 
 
 
47
  return true;
48
  }
49
 
44
  return false;
45
  }
46
 
47
+ // when disabled - no extra requests are made to obtain key version,
48
+ // but flush operations not supported as a result
49
+ // group should be always empty
50
+ if ( isset( $config['key_version_mode'] ) &&
51
+ $config['key_version_mode'] == 'disabled' ) {
52
+ $this->_key_version[''] = 1;
53
+ }
54
+
55
  return true;
56
  }
57
 
Cache_Memcached.php CHANGED
@@ -82,6 +82,14 @@ class Cache_Memcached extends Cache_Base {
82
  $this->_memcache->setSaslAuthData( $config['username'],
83
  $config['password'] );
84
 
 
 
 
 
 
 
 
 
85
  return true;
86
  }
87
 
82
  $this->_memcache->setSaslAuthData( $config['username'],
83
  $config['password'] );
84
 
85
+ // when disabled - no extra requests are made to obtain key version,
86
+ // but flush operations not supported as a result
87
+ // group should be always empty
88
+ if ( isset( $config['key_version_mode'] ) &&
89
+ $config['key_version_mode'] == 'disabled' ) {
90
+ $this->_key_version[''] = 1;
91
+ }
92
+
93
  return true;
94
  }
95
 
Cache_Redis.php CHANGED
@@ -25,6 +25,14 @@ class Cache_Redis extends Cache_Base {
25
  $this->_servers = (array)$config['servers'];
26
  $this->_password = $config['password'];
27
  $this->_dbid = $config['dbid'];
 
 
 
 
 
 
 
 
28
  }
29
 
30
  /**
@@ -325,14 +333,16 @@ class Cache_Redis extends Cache_Base {
325
 
326
  if ( substr( $server, 0, 5 ) == 'unix:' ) {
327
  if ( $this->_persistent )
328
- $accessor->pconnect( trim( substr( $server, 5 ) ) );
 
329
  else
330
  $accessor->connect( trim( substr( $server, 5 ) ) );
331
  } else {
332
  list( $ip, $port ) = explode( ':', $server );
333
 
334
  if ( $this->_persistent )
335
- $accessor->pconnect( trim( $ip ), (integer) trim( $port ) );
 
336
  else
337
  $accessor->connect( trim( $ip ), (integer) trim( $port ) );
338
  }
25
  $this->_servers = (array)$config['servers'];
26
  $this->_password = $config['password'];
27
  $this->_dbid = $config['dbid'];
28
+
29
+ // when disabled - no extra requests are made to obtain key version,
30
+ // but flush operations not supported as a result
31
+ // group should be always empty
32
+ if ( isset( $config['key_version_mode'] ) &&
33
+ $config['key_version_mode'] == 'disabled' ) {
34
+ $this->_key_version[''] = 1;
35
+ }
36
  }
37
 
38
  /**
333
 
334
  if ( substr( $server, 0, 5 ) == 'unix:' ) {
335
  if ( $this->_persistent )
336
+ $accessor->pconnect( trim( substr( $server, 5 ) ),
337
+ null, null, $this->_instance_id . '_' . $this->_dbid );
338
  else
339
  $accessor->connect( trim( substr( $server, 5 ) ) );
340
  } else {
341
  list( $ip, $port ) = explode( ':', $server );
342
 
343
  if ( $this->_persistent )
344
+ $accessor->pconnect( trim( $ip ), (integer) trim( $port ),
345
+ null, $this->_instance_id . '_' . $this->_dbid );
346
  else
347
  $accessor->connect( trim( $ip ), (integer) trim( $port ) );
348
  }
CdnEngine.php CHANGED
@@ -67,10 +67,6 @@ class CdnEngine {
67
  $instances[$instance_key] = new CdnEngine_Mirror( $config );
68
  break;
69
 
70
- case 'netdna':
71
- $instances[$instance_key] = new CdnEngine_Mirror_Netdna( $config );
72
- break;
73
-
74
  case 'rackspace_cdn':
75
  $instances[$instance_key] = new CdnEngine_Mirror_RackSpaceCdn( $config );
76
  break;
67
  $instances[$instance_key] = new CdnEngine_Mirror( $config );
68
  break;
69
 
 
 
 
 
70
  case 'rackspace_cdn':
71
  $instances[$instance_key] = new CdnEngine_Mirror_RackSpaceCdn( $config );
72
  break;
CdnEngine_Azure.php CHANGED
@@ -90,10 +90,15 @@ class CdnEngine_Azure extends CdnEngine_Base {
90
  }
91
 
92
  foreach ( $files as $file ) {
93
- if ( !is_null( $timeout_time ) && time() > $timeout_time )
94
- break;
95
-
96
  $remote_path = $file['remote_path'];
 
 
 
 
 
 
 
 
97
 
98
  $results[] = $this->_upload( $file, $force_rewrite );
99
  }
90
  }
91
 
92
  foreach ( $files as $file ) {
 
 
 
93
  $remote_path = $file['remote_path'];
94
+ $local_path = $file['local_path'];
95
+
96
+ // process at least one item before timeout so that progress goes on
97
+ if ( !empty( $results ) ) {
98
+ if ( !is_null( $timeout_time ) && time() > $timeout_time ) {
99
+ return 'timeout';
100
+ }
101
+ }
102
 
103
  $results[] = $this->_upload( $file, $force_rewrite );
104
  }
CdnEngine_Base.php CHANGED
@@ -179,7 +179,15 @@ class CdnEngine_Base {
179
  break;
180
 
181
  default:
182
- if ( $count > 4 ) {
 
 
 
 
 
 
 
 
183
  $domain = $this->_get_domain( array_slice( $domains, 4 ),
184
  $path );
185
  } else {
@@ -579,6 +587,10 @@ class CdnEngine_Base {
579
  */
580
  function _get_domain( $domains, $path ) {
581
  $count = count( $domains );
 
 
 
 
582
 
583
  if ( $count ) {
584
  /**
179
  break;
180
 
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'] :
188
+ $domains['https_default'];
189
+ }
190
+ } elseif ( $count > 4 ) {
191
  $domain = $this->_get_domain( array_slice( $domains, 4 ),
192
  $path );
193
  } else {
587
  */
588
  function _get_domain( $domains, $path ) {
589
  $count = count( $domains );
590
+ if ( isset( $domains['http_default'] ) )
591
+ $count--;
592
+ if ( isset( $domains['https_default'] ) )
593
+ $count--;
594
 
595
  if ( $count ) {
596
  /**
CdnEngine_Ftp.php CHANGED
@@ -164,12 +164,16 @@ class CdnEngine_Ftp extends CdnEngine_Base {
164
  }
165
 
166
  foreach ( $files as $file ) {
167
- if ( !is_null( $timeout_time ) && time() > $timeout_time )
168
- break;
169
-
170
  $local_path = $file['local_path'];
171
  $remote_path = $file['remote_path'];
172
 
 
 
 
 
 
 
 
173
  if ( !file_exists( $local_path ) ) {
174
  $results[] = $this->_get_result( $local_path, $remote_path,
175
  W3TC_CDN_RESULT_ERROR, 'Source file not found.', $file );
164
  }
165
 
166
  foreach ( $files as $file ) {
 
 
 
167
  $local_path = $file['local_path'];
168
  $remote_path = $file['remote_path'];
169
 
170
+ // process at least one item before timeout so that progress goes on
171
+ if ( !empty( $results ) ) {
172
+ if ( !is_null( $timeout_time ) && time() > $timeout_time ) {
173
+ return 'timeout';
174
+ }
175
+ }
176
+
177
  if ( !file_exists( $local_path ) ) {
178
  $results[] = $this->_get_result( $local_path, $remote_path,
179
  W3TC_CDN_RESULT_ERROR, 'Source file not found.', $file );
CdnEngine_GoogleDrive.php CHANGED
@@ -11,6 +11,7 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
11
  private $_root_url;
12
 
13
  private $_service;
 
14
 
15
 
16
 
@@ -28,6 +29,9 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
28
  $this->_root_url = rtrim( $config['root_url'], '/' ) . '/';
29
  $this->_new_access_token_callback = $config['new_access_token_callback'];
30
 
 
 
 
31
  try {
32
  $this->_init_service( $config['access_token'] );
33
  } catch ( \Exception $e ) {
@@ -79,7 +83,7 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
79
  function upload( $files, &$results, $force_rewrite = false, $timeout_time = NULL ) {
80
  if ( is_null( $this->_service ) )
81
  return false;
82
-
83
  $allow_refresh_token = true;
84
  $result = true;
85
 
@@ -96,8 +100,10 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
96
  }
97
  if ( $r != 'success' )
98
  $result = false;
99
- if ( $r == 'timeout' )
100
- break;
 
 
101
  }
102
 
103
  return $result;
@@ -105,6 +111,45 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
105
 
106
 
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  private function _upload_chunk( $files, &$results, $force_rewrite,
109
  $timeout_time, $allow_refresh_token ) {
110
  list( $result, $listed_files ) = $this->list_files_chunk( $files,
@@ -112,45 +157,28 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
112
  if ( $result != 'success' )
113
  return $result;
114
 
115
- // remove dups
116
- $files_by_title = array();
117
-
118
- for ( $n = 0; $n < count( $listed_files ); $n++ ) {
119
- $title_to_search = $listed_files[$n]->title;
120
- $files_by_title[$title_to_search] = $listed_files[$n];
121
-
122
- for ( $m = $n + 1; $m < count( $listed_files ); $m++ ) {
123
- if ( $listed_files[$m]->title == $title_to_search ) {
124
- try {
125
- $this->_service->files->delete( $listed_files[$m]->id );
126
- } catch ( \W3TCG_Google_Service_Exception $e ) {
127
- $errors = $e->getErrors();
128
- $details = '';
129
- if ( count( $errors ) >= 1 ) {
130
- if ( $errors[0]['reason'] == 'notFound' ) {
131
- continue;
132
- } else
133
- $details = $errors[0]['reason'];
134
- }
135
 
136
- $results[] = $this->_get_result( '',
137
- '', W3TC_CDN_RESULT_ERROR,
138
- 'Failed to delete dup file ' . $title_to_search . ' ' . $details );
139
- $result = 'with_errors';
140
- }
141
- }
142
  }
143
  }
144
 
145
  // check update date and upload
146
  foreach ( $files as $file_descriptor ) {
147
- if ( !is_null( $timeout_time ) && time() > $timeout_time )
148
- return 'timeout';
 
 
 
 
 
149
 
150
  list( $parent_id, $title ) = $this->remote_path_to_title(
151
  $file_descriptor['remote_path'] );
152
- $properties = array();
153
-
154
  if ( isset( $file_descriptor['content'] ) ) {
155
  // when content specified - just upload
156
  $content = $file_descriptor['content'];
@@ -158,7 +186,7 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
158
  $local_path = $file_descriptor['local_path'];
159
  if ( !file_exists( $local_path ) ) {
160
  $results[] = $this->_get_result( $local_path,
161
- $file_descriptor['remote_path'],
162
  W3TC_CDN_RESULT_ERROR, 'Source file not found.',
163
  $file_descriptor );
164
  continue;
@@ -171,8 +199,8 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
171
  $p->value = $mtime;
172
  $properties[] = $p;
173
 
174
- if ( !$force_rewrite && isset( $files_by_title[$title] ) ) {
175
- $existing_file = $files_by_title[$title];
176
  $existing_size = $existing_file->fileSize;
177
  $existing_mtime = 0;
178
  if ( is_array( $existing_file->properties ) ) {
@@ -185,7 +213,7 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
185
  $size = @filesize( $local_path );
186
  if ( $mtime == $existing_mtime && $size == $existing_size ) {
187
  $results[] = $this->_get_result( $file_descriptor['local_path'],
188
- $file_descriptor['remote_path'], W3TC_CDN_RESULT_OK,
189
  'File up-to-date.', $file_descriptor );
190
  continue;
191
  }
@@ -205,8 +233,8 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
205
  try {
206
  try {
207
  // update file if there's one already or insert
208
- if ( isset( $files_by_title[$title] ) ) {
209
- $existing_file = $files_by_title[$title];
210
 
211
  $created_file = $this->_service->files->update(
212
  $existing_file->id, $file, array(
@@ -235,20 +263,21 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
235
  }
236
 
237
  $results[] = $this->_get_result( $file_descriptor['local_path'],
238
- $file_descriptor['remote_path'], W3TC_CDN_RESULT_OK,
239
  'OK', $file_descriptor );
 
240
  } catch ( \W3TCG_Google_Service_Exception $e ) {
241
  $errors = $e->getErrors();
242
  $details = '';
243
  if ( count( $errors ) >= 1 ) {
244
- $details = $errors[0]['reason'];
245
  }
246
 
247
  delete_transient( 'w3tc_cdn_google_drive_folder_ids' );
248
 
249
  $results[] = $this->_get_result( $file_descriptor['local_path'],
250
- $file_descriptor['remote_path'], W3TC_CDN_RESULT_ERROR,
251
- 'Failed to upload file ' . $file_descriptor['remote_path'] .
252
  ' ' . $details, $file_descriptor );
253
  $result = 'with_errors';
254
  continue;
@@ -256,8 +285,8 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
256
  delete_transient( 'w3tc_cdn_google_drive_folder_ids' );
257
 
258
  $results[] = $this->_get_result( $file_descriptor['local_path'],
259
- $file_descriptor['remote_path'], W3TC_CDN_RESULT_ERROR,
260
- 'Failed to upload file ' . $file_descriptor['remote_path'],
261
  $file_descriptor );
262
  $result = 'with_errors';
263
  continue;
@@ -516,7 +545,77 @@ class CdnEngine_GoogleDrive extends CdnEngine_Base {
516
  }
517
 
518
 
519
- function format_url( $path ) {
520
- return $this->_root_url . ltrim( $path, '/' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
  }
522
  }
11
  private $_root_url;
12
 
13
  private $_service;
14
+ private $_tablename_pathmap;
15
 
16
 
17
 
29
  $this->_root_url = rtrim( $config['root_url'], '/' ) . '/';
30
  $this->_new_access_token_callback = $config['new_access_token_callback'];
31
 
32
+ global $wpdb;
33
+ $this->_tablename_pathmap = $wpdb->base_prefix . W3TC_CDN_TABLE_PATHMAP;
34
+
35
  try {
36
  $this->_init_service( $config['access_token'] );
37
  } catch ( \Exception $e ) {
83
  function upload( $files, &$results, $force_rewrite = false, $timeout_time = NULL ) {
84
  if ( is_null( $this->_service ) )
85
  return false;
86
+
87
  $allow_refresh_token = true;
88
  $result = true;
89
 
100
  }
101
  if ( $r != 'success' )
102
  $result = false;
103
+ if ( $r == 'timeout' ) {
104
+ return 'timeout';
105
+ }
106
+
107
  }
108
 
109
  return $result;
111
 
112
 
113
 
114
+ private function _properties_to_path( $file ) {
115
+ $path_pieces = array();
116
+ foreach ( $file->properties as $p ) {
117
+ $k = ($p->key == 'path') ? 'path1' : $p->key;
118
+ if ( !preg_match( '/^path[0-9]+$/', $k ) )
119
+ continue;
120
+ $path_pieces[$k] = $p->value;
121
+ }
122
+ if ( count( $path_pieces ) == 0 )
123
+ return NULL;
124
+ ksort($path_pieces);
125
+ return join( $path_pieces );
126
+ }
127
+
128
+
129
+
130
+ private function _path_to_properties( $path ) {
131
+ // from google drive api docs:
132
+ // Maximum of 124 bytes size per property
133
+ // (including both key and value) string in UTF-8 encoding.
134
+ // Maximum of 30 private properties per file from any one application.
135
+ $chunks = str_split( $path, 55 );
136
+ $properties = array();
137
+ $i = 1;
138
+
139
+ foreach ( $chunks as $chunk ) {
140
+ $p = new \W3TCG_Google_Service_Drive_Property();
141
+ $p->key = 'path' . $i;
142
+ $p->value = $chunk;
143
+ $properties[] = $p;
144
+
145
+ $i++;
146
+ }
147
+
148
+ return $properties;
149
+ }
150
+
151
+
152
+
153
  private function _upload_chunk( $files, &$results, $force_rewrite,
154
  $timeout_time, $allow_refresh_token ) {
155
  list( $result, $listed_files ) = $this->list_files_chunk( $files,
157
  if ( $result != 'success' )
158
  return $result;
159
 
160
+ $files_by_path = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
+ foreach ( $listed_files as $existing_file ) {
163
+ $path = $this->_properties_to_path( $existing_file );
164
+ if ( $path ) {
165
+ $files_by_path[$path] = $existing_file;
 
 
166
  }
167
  }
168
 
169
  // check update date and upload
170
  foreach ( $files as $file_descriptor ) {
171
+ $remote_path = $file_descriptor['remote_path'];
172
+
173
+ // process at least one item before timeout so that progress goes on
174
+ if ( !empty( $results ) ) {
175
+ if ( !is_null( $timeout_time ) && time() > $timeout_time )
176
+ return 'timeout';
177
+ }
178
 
179
  list( $parent_id, $title ) = $this->remote_path_to_title(
180
  $file_descriptor['remote_path'] );
181
+ $properties = $this->_path_to_properties( $remote_path );
 
182
  if ( isset( $file_descriptor['content'] ) ) {
183
  // when content specified - just upload
184
  $content = $file_descriptor['content'];
186
  $local_path = $file_descriptor['local_path'];
187
  if ( !file_exists( $local_path ) ) {
188
  $results[] = $this->_get_result( $local_path,
189
+ $remote_path,
190
  W3TC_CDN_RESULT_ERROR, 'Source file not found.',
191
  $file_descriptor );
192
  continue;
199
  $p->value = $mtime;
200
  $properties[] = $p;
201
 
202
+ if ( !$force_rewrite && isset( $files_by_path[$remote_path] ) ) {
203
+ $existing_file = $files_by_path[$remote_path];
204
  $existing_size = $existing_file->fileSize;
205
  $existing_mtime = 0;
206
  if ( is_array( $existing_file->properties ) ) {
213
  $size = @filesize( $local_path );
214
  if ( $mtime == $existing_mtime && $size == $existing_size ) {
215
  $results[] = $this->_get_result( $file_descriptor['local_path'],
216
+ $remote_path, W3TC_CDN_RESULT_OK,
217
  'File up-to-date.', $file_descriptor );
218
  continue;
219
  }
233
  try {
234
  try {
235
  // update file if there's one already or insert
236
+ if ( isset( $files_by_path[$remote_path] ) ) {
237
+ $existing_file = $files_by_path[$remote_path];
238
 
239
  $created_file = $this->_service->files->update(
240
  $existing_file->id, $file, array(
263
  }
264
 
265
  $results[] = $this->_get_result( $file_descriptor['local_path'],
266
+ $remote_path, W3TC_CDN_RESULT_OK,
267
  'OK', $file_descriptor );
268
+ $this->path_set_id( $remote_path, $created_file->id );
269
  } catch ( \W3TCG_Google_Service_Exception $e ) {
270
  $errors = $e->getErrors();
271
  $details = '';
272
  if ( count( $errors ) >= 1 ) {
273
+ $details = json_encode($errors);
274
  }
275
 
276
  delete_transient( 'w3tc_cdn_google_drive_folder_ids' );
277
 
278
  $results[] = $this->_get_result( $file_descriptor['local_path'],
279
+ $remote_path, W3TC_CDN_RESULT_ERROR,
280
+ 'Failed to upload file ' . $remote_path .
281
  ' ' . $details, $file_descriptor );
282
  $result = 'with_errors';
283
  continue;
285
  delete_transient( 'w3tc_cdn_google_drive_folder_ids' );
286
 
287
  $results[] = $this->_get_result( $file_descriptor['local_path'],
288
+ $remote_path, W3TC_CDN_RESULT_ERROR,
289
+ 'Failed to upload file ' . $remote_path,
290
  $file_descriptor );
291
  $result = 'with_errors';
292
  continue;
545
  }
546
 
547
 
548
+
549
+ function purge_all( &$results ) {
550
+ return false;
551
+ }
552
+
553
+
554
+
555
+ private function path_set_id( $path, $id ) {
556
+ global $wpdb;
557
+ $md5 = md5( $path );
558
+ if ( !$id ) {
559
+ $sql = "
560
+ INSERT INTO $this->_tablename_pathmap (path, path_hash, remote_id)
561
+ VALUES (%s, %s, NULL)
562
+ ON DUPLICATE KEY UPDATE remote_id = NULL";
563
+ $wpdb->query($wpdb->prepare($sql, $path, $md5));
564
+ } else {
565
+ $sql = "
566
+ INSERT INTO $this->_tablename_pathmap (path, path_hash, remote_id)
567
+ VALUES (%s, %s, %s)
568
+ ON DUPLICATE KEY UPDATE remote_id = %s";
569
+ $wpdb->query($wpdb->prepare(
570
+ $sql, $path, $md5, $id, $id));
571
+ }
572
+ }
573
+
574
+
575
+
576
+ private function path_get_id( $path, $allow_refresh_token = true ) {
577
+ global $wpdb;
578
+ $md5 = md5($path);
579
+ $sql = "SELECT remote_id FROM $this->_tablename_pathmap WHERE path_hash = %s";
580
+ $query = $wpdb->prepare( $sql, $md5 );
581
+ $results = $wpdb->get_results( $query );
582
+ if ( count( $results ) > 0 ) {
583
+ return $results[0]->remote_id;
584
+ }
585
+ $props = $this->_path_to_properties( $path );
586
+ $q = 'trashed = false';
587
+ foreach ( $props as $prop ) {
588
+ $key = $prop->key;
589
+ $value = str_replace( "'", "\\'", $prop->value );
590
+ $q .= " and properties has { key='$key' and " .
591
+ " value='$value' and visibility='PRIVATE' }";
592
+ }
593
+
594
+ try {
595
+ $items = $this->_service->files->listFiles(
596
+ array( 'q' => $q ) );
597
+ } catch ( \W3TCG_Google_Auth_Exception $e ) {
598
+ if ( $allow_refresh_token ) {
599
+ $this->_refresh_token();
600
+ return $this->path_get_id( $path, false );
601
+ }
602
+
603
+ throw $e;
604
+ }
605
+
606
+ $id = ( count( $items ) == 0 ) ? NULL : $items[0]->id;
607
+ $this->path_set_id( $path, $id );
608
+
609
+ return $id;
610
+ }
611
+
612
+
613
+
614
+ function format_url( $path, $allow_refresh_token = true ) {
615
+ $id = $this->path_get_id( Util_Environment::remove_query( $path ) );
616
+ if ( is_null( $id ) )
617
+ return NULL;
618
+
619
+ return 'https://drive.google.com/uc?id=' . $id;
620
  }
621
  }
CdnEngine_Mirror_Akamai.php CHANGED
@@ -1,10 +1,6 @@
1
  <?php
2
  namespace W3TC;
3
 
4
- /**
5
- * W3 CDN Netdna Class
6
- */
7
-
8
  define( 'W3TC_CDN_MIRROR_AKAMAI_WSDL', 'https://ccuapi.akamai.com/ccuapi-axis.wsdl' );
9
  define( 'W3TC_CDN_MIRROR_AKAMAI_NAMESPACE', 'http://www.akamai.com/purge' );
10
 
1
  <?php
2
  namespace W3TC;
3
 
 
 
 
 
4
  define( 'W3TC_CDN_MIRROR_AKAMAI_WSDL', 'https://ccuapi.akamai.com/ccuapi-axis.wsdl' );
5
  define( 'W3TC_CDN_MIRROR_AKAMAI_NAMESPACE', 'http://www.akamai.com/purge' );
6
 
CdnEngine_Mirror_Cotendo.php CHANGED
@@ -1,10 +1,6 @@
1
  <?php
2
  namespace W3TC;
3
 
4
- /**
5
- * W3 CDN Netdna Class
6
- */
7
-
8
  define( 'W3TC_CDN_MIRROR_COTENDO_WSDL', 'https://api.cotendo.net/cws?wsdl' );
9
  define( 'W3TC_CDN_MIRROR_COTENDO_ENDPOINT', 'http://api.cotendo.net/cws?ver=1.0' );
10
  define( 'W3TC_CDN_MIRROR_COTENDO_NAMESPACE', 'http://api.cotendo.net/' );
1
  <?php
2
  namespace W3TC;
3
 
 
 
 
 
4
  define( 'W3TC_CDN_MIRROR_COTENDO_WSDL', 'https://api.cotendo.net/cws?wsdl' );
5
  define( 'W3TC_CDN_MIRROR_COTENDO_ENDPOINT', 'http://api.cotendo.net/cws?ver=1.0' );
6
  define( 'W3TC_CDN_MIRROR_COTENDO_NAMESPACE', 'http://api.cotendo.net/' );
CdnEngine_Mirror_Edgecast.php CHANGED
@@ -1,10 +1,6 @@
1
  <?php
2
  namespace W3TC;
3
 
4
- /**
5
- * W3 CDN Netdna Class
6
- */
7
-
8
  if ( !defined( 'W3TC_CDN_EDGECAST_PURGE_URL' ) ) define( 'W3TC_CDN_EDGECAST_PURGE_URL', 'http://api.edgecast.com/v2/mcc/customers/%s/edge/purge' );
9
  define( 'W3TC_CDN_EDGECAST_MEDIATYPE_WINDOWS_MEDIA_STREAMING', 1 );
10
  define( 'W3TC_CDN_EDGECAST_MEDIATYPE_FLASH_MEDIA_STREAMING', 2 );
1
  <?php
2
  namespace W3TC;
3
 
 
 
 
 
4
  if ( !defined( 'W3TC_CDN_EDGECAST_PURGE_URL' ) ) define( 'W3TC_CDN_EDGECAST_PURGE_URL', 'http://api.edgecast.com/v2/mcc/customers/%s/edge/purge' );
5
  define( 'W3TC_CDN_EDGECAST_MEDIATYPE_WINDOWS_MEDIA_STREAMING', 1 );
6
  define( 'W3TC_CDN_EDGECAST_MEDIATYPE_FLASH_MEDIA_STREAMING', 2 );
CdnEngine_Mirror_MaxCdn.php CHANGED
@@ -1,7 +1,171 @@
1
  <?php
2
  namespace W3TC;
3
 
4
- /**
5
- * W3 CDN MaxCDN Class
6
- */
7
- class CdnEngine_Mirror_MaxCdn extends CdnEngine_Mirror_Netdna {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
  namespace W3TC;
3
 
4
+ define( 'W3TC_CDN_NETDNA_URL', 'netdna-cdn.com' );
5
+
6
+ class CdnEngine_Mirror_MaxCdn extends CdnEngine_Mirror {
7
+ /**
8
+ * PHP5 Constructor
9
+ *
10
+ * @param array $config
11
+ */
12
+ function __construct( $config = array() ) {
13
+ $config = array_merge( array(
14
+ 'authorization_key' => '',
15
+ 'alias' => '',
16
+ 'consumerkey' => '',
17
+ 'consumersecret' => '',
18
+ 'zone_id' => 0
19
+ ), $config );
20
+ $split_keys = explode( '+', $config['authorization_key'] );
21
+ if ( sizeof( $split_keys )==3 )
22
+ list( $config['alias'], $config['consumerkey'], $config['consumersecret'] ) = $split_keys;
23
+ parent::__construct( $config );
24
+ }
25
+
26
+ /**
27
+ * Purges remote files
28
+ *
29
+ * @param array $files
30
+ * @param array $results
31
+ * @return boolean
32
+ */
33
+ function purge( $files, &$results ) {
34
+ if ( empty( $this->_config['authorization_key'] ) ) {
35
+ $results = $this->_get_results( $files, W3TC_CDN_RESULT_HALT, __( 'Empty Authorization Key.', 'w3-total-cache' ) );
36
+
37
+ return false;
38
+ }
39
+
40
+ if ( empty( $this->_config['alias'] ) || empty( $this->_config['consumerkey'] ) || 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
+ if ( !class_exists( 'NetDNA' ) ) {
47
+ require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
48
+ }
49
+
50
+ $api = new \NetDNA( $this->_config['alias'],
51
+ $this->_config['consumerkey'], $this->_config['consumersecret'] );
52
+ $results = array();
53
+
54
+ try {
55
+ if ( $this->_config['zone_id'] != 0 )
56
+ $zone_id = $this->_config['zone_id'];
57
+ else {
58
+ $zone_id = $api->get_zone_id( get_home_url() );
59
+ }
60
+
61
+ if ( $zone_id == 0 ) {
62
+ $zone_id = $api->get_zone_id( Util_Environment::home_domain_root_url() );
63
+ }
64
+
65
+ if ( $zone_id == 0 ) {
66
+ $zone_id = $api->get_zone_id( str_replace( '://', '://www.', Util_Environment::home_domain_root_url() ) );
67
+ }
68
+
69
+ if ( $zone_id == 0 || is_null( $zone_id ) ) {
70
+ if ( Util_Environment::home_domain_root_url() == get_home_url() )
71
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ) ) );
72
+ else
73
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s or %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ), trim( Util_Environment::home_domain_root_url(), '/' ) ) );
74
+ return !$this->_is_error( $results );
75
+ }
76
+
77
+
78
+ $files_to_pass = array();
79
+ foreach ( $files as $file )
80
+ $files_to_pass[] = '/' . $file['remote_path'];
81
+ $params = array( 'files' => $files_to_pass );
82
+ $file_purge = json_decode( $api->delete(
83
+ '/zones/pull.json/' . $zone_id . '/cache',
84
+ $params ) );
85
+
86
+ if ( preg_match( "(200|201)", $file_purge->code ) ) {
87
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, 'OK' );
88
+ } else {
89
+ if ( preg_match( "(401|500)", $file_purge->code ) ) {
90
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'Failed with error code %s Please check your alias, consumer key, and private key.', 'w3-total-cache' ), $file_purge->code ) );
91
+ } else {
92
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, __( 'Failed with error code ', 'w3-total-cache' ) . $file_purge->code );
93
+ }
94
+ }
95
+ } catch ( W3tcWpHttpException $e ) {
96
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, __( 'Failure to pull zone: ', 'w3-total-cache' ) . $e->getMessage() );
97
+ }
98
+
99
+ return !$this->_is_error( $results );
100
+ }
101
+
102
+ /**
103
+ * Purge CDN completely
104
+ *
105
+ * @param unknown $results
106
+ * @return bool
107
+ */
108
+ function purge_all( &$results ) {
109
+ if ( empty( $this->_config['authorization_key'] ) ) {
110
+ $results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Empty Authorization Key.', 'w3-total-cache' ) );
111
+
112
+ return false;
113
+ }
114
+
115
+ if ( empty( $this->_config['alias'] ) || empty( $this->_config['consumerkey'] ) || empty( $this->_config['consumersecret'] ) ) {
116
+ $results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Malformed Authorization Key.', 'w3-total-cache' ) );
117
+
118
+ return false;
119
+ }
120
+
121
+ if ( !class_exists( 'NetDNA' ) ) {
122
+ require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
123
+ }
124
+
125
+ $api = new \NetDNA( $this->_config['alias'], $this->_config['consumerkey'], $this->_config['consumersecret'] );
126
+
127
+ $results = array();
128
+
129
+ try {
130
+ if ( $this->_config['zone_id'] != 0 )
131
+ $zone_id = $this->_config['zone_id'];
132
+ else {
133
+ $zone_id = $api->get_zone_id( get_home_url() );
134
+ }
135
+
136
+ if ( $zone_id == 0 ) {
137
+ $zone_id = $api->get_zone_id( Util_Environment::home_domain_root_url() );
138
+ }
139
+
140
+
141
+ if ( $zone_id == 0 ) {
142
+ $zone_id = $api->get_zone_id( str_replace( '://', '://www.', Util_Environment::home_domain_root_url() ) );
143
+ }
144
+
145
+ if ( $zone_id == 0 || is_null( $zone_id ) ) {
146
+ if ( Util_Environment::home_domain_root_url() == get_home_url() )
147
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ) ) );
148
+ else
149
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s or %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ), trim( Util_Environment::home_domain_root_url(), '/' ) ) );
150
+ return !$this->_is_error( $results );
151
+ }
152
+
153
+ $file_purge = json_decode( $api->delete( '/zones/pull.json/' . $zone_id . '/cache' ) );
154
+
155
+ if ( preg_match( "(200|201)", $file_purge->code ) ) {
156
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, __( 'OK', 'w3-total-cache' ) );
157
+ } else {
158
+ if ( preg_match( "(401|500)", $file_purge->code ) ) {
159
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'Failed with error code %s. Please check your alias, consumer key, and private key.', 'w3-total-cache' ), $file_purge->code ) );
160
+ } else {
161
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, __( 'Failed with error code ', 'w3-total-cache' ) . $file_purge->code );
162
+ }
163
+ }
164
+
165
+ } catch ( W3tcWpHttpException $e ) {
166
+ $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, __( 'Failure to pull zone: ', 'w3-total-cache' ) . $e->getMessage() );
167
+ }
168
+
169
+ return !$this->_is_error( $results );
170
+ }
171
+ }
CdnEngine_Mirror_Netdna.php DELETED
@@ -1,178 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- /**
5
- * W3 CDN Netdna Class
6
- */
7
-
8
- define( 'W3TC_CDN_NETDNA_URL', 'netdna-cdn.com' );
9
-
10
- /**
11
- * class CdnEngine_Mirror_Netdna
12
- */
13
- class CdnEngine_Mirror_Netdna extends CdnEngine_Mirror {
14
- /**
15
- * PHP5 Constructor
16
- *
17
- * @param array $config
18
- */
19
- function __construct( $config = array() ) {
20
- $config = array_merge( array(
21
- 'authorization_key' => '',
22
- 'alias' => '',
23
- 'consumerkey' => '',
24
- 'consumersecret' => '',
25
- 'zone_id' => 0
26
- ), $config );
27
- $split_keys = explode( '+', $config['authorization_key'] );
28
- if ( sizeof( $split_keys )==3 )
29
- list( $config['alias'], $config['consumerkey'], $config['consumersecret'] ) = $split_keys;
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->_config['authorization_key'] ) ) {
42
- $results = $this->_get_results( $files, W3TC_CDN_RESULT_HALT, __( 'Empty Authorization Key.', 'w3-total-cache' ) );
43
-
44
- return false;
45
- }
46
-
47
- if ( empty( $this->_config['alias'] ) || empty( $this->_config['consumerkey'] ) || empty( $this->_config['consumersecret'] ) ) {
48
- $results = $this->_get_results( $files, W3TC_CDN_RESULT_HALT, __( 'Malformed Authorization Key.', 'w3-total-cache' ) );
49
-
50
- return false;
51
- }
52
-
53
- if ( !class_exists( 'NetDNA' ) ) {
54
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
55
- }
56
-
57
- $api = new \NetDNA( $this->_config['alias'],
58
- $this->_config['consumerkey'], $this->_config['consumersecret'] );
59
- $results = array();
60
-
61
- try {
62
- if ( $this->_config['zone_id'] != 0 )
63
- $zone_id = $this->_config['zone_id'];
64
- else {
65
- $zone_id = $api->get_zone_id( get_home_url() );
66
- }
67
-
68
- if ( $zone_id == 0 ) {
69
- $zone_id = $api->get_zone_id( Util_Environment::home_domain_root_url() );
70
- }
71
-
72
- if ( $zone_id == 0 ) {
73
- $zone_id = $api->get_zone_id( str_replace( '://', '://www.', Util_Environment::home_domain_root_url() ) );
74
- }
75
-
76
- if ( $zone_id == 0 || is_null( $zone_id ) ) {
77
- if ( Util_Environment::home_domain_root_url() == get_home_url() )
78
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ) ) );
79
- else
80
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s or %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ), trim( Util_Environment::home_domain_root_url(), '/' ) ) );
81
- return !$this->_is_error( $results );
82
- }
83
-
84
-
85
- $files_to_pass = array();
86
- foreach ( $files as $file )
87
- $files_to_pass[] = '/' . $file['remote_path'];
88
- $params = array( 'files' => $files_to_pass );
89
- $file_purge = json_decode( $api->delete(
90
- '/zones/pull.json/' . $zone_id . '/cache',
91
- $params ) );
92
-
93
- if ( preg_match( "(200|201)", $file_purge->code ) ) {
94
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, 'OK' );
95
- } else {
96
- if ( preg_match( "(401|500)", $file_purge->code ) ) {
97
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'Failed with error code %s Please check your alias, consumer key, and private key.', 'w3-total-cache' ), $file_purge->code ) );
98
- } else {
99
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, __( 'Failed with error code ', 'w3-total-cache' ) . $file_purge->code );
100
- }
101
- }
102
- } catch ( W3tcWpHttpException $e ) {
103
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, __( 'Failure to pull zone: ', 'w3-total-cache' ) . $e->getMessage() );
104
- }
105
-
106
- return !$this->_is_error( $results );
107
- }
108
-
109
- /**
110
- * Purge CDN completely
111
- *
112
- * @param unknown $results
113
- * @return bool
114
- */
115
- function purge_all( &$results ) {
116
- if ( empty( $this->_config['authorization_key'] ) ) {
117
- $results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Empty Authorization Key.', 'w3-total-cache' ) );
118
-
119
- return false;
120
- }
121
-
122
- if ( empty( $this->_config['alias'] ) || empty( $this->_config['consumerkey'] ) || empty( $this->_config['consumersecret'] ) ) {
123
- $results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Malformed Authorization Key.', 'w3-total-cache' ) );
124
-
125
- return false;
126
- }
127
-
128
- if ( !class_exists( 'NetDNA' ) ) {
129
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
130
- }
131
-
132
- $api = new \NetDNA( $this->_config['alias'], $this->_config['consumerkey'], $this->_config['consumersecret'] );
133
-
134
- $results = array();
135
-
136
- try {
137
- if ( $this->_config['zone_id'] != 0 )
138
- $zone_id = $this->_config['zone_id'];
139
- else {
140
- $zone_id = $api->get_zone_id( get_home_url() );
141
- }
142
-
143
- if ( $zone_id == 0 ) {
144
- $zone_id = $api->get_zone_id( Util_Environment::home_domain_root_url() );
145
- }
146
-
147
-
148
- if ( $zone_id == 0 ) {
149
- $zone_id = $api->get_zone_id( str_replace( '://', '://www.', Util_Environment::home_domain_root_url() ) );
150
- }
151
-
152
- if ( $zone_id == 0 || is_null( $zone_id ) ) {
153
- if ( Util_Environment::home_domain_root_url() == get_home_url() )
154
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ) ) );
155
- else
156
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'No zones match site: %s or %s.', 'w3-total-cache' ), trim( get_home_url(), '/' ), trim( Util_Environment::home_domain_root_url(), '/' ) ) );
157
- return !$this->_is_error( $results );
158
- }
159
-
160
- $file_purge = json_decode( $api->delete( '/zones/pull.json/' . $zone_id . '/cache' ) );
161
-
162
- if ( preg_match( "(200|201)", $file_purge->code ) ) {
163
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, __( 'OK', 'w3-total-cache' ) );
164
- } else {
165
- if ( preg_match( "(401|500)", $file_purge->code ) ) {
166
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, sprintf( __( 'Failed with error code %s. Please check your alias, consumer key, and private key.', 'w3-total-cache' ), $file_purge->code ) );
167
- } else {
168
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_ERROR, __( 'Failed with error code ', 'w3-total-cache' ) . $file_purge->code );
169
- }
170
- }
171
-
172
- } catch ( W3tcWpHttpException $e ) {
173
- $results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, __( 'Failure to pull zone: ', 'w3-total-cache' ) . $e->getMessage() );
174
- }
175
-
176
- return !$this->_is_error( $results );
177
- }
178
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
CdnEngine_RackSpaceCloudFiles.php CHANGED
@@ -145,12 +145,16 @@ class CdnEngine_RackSpaceCloudFiles extends CdnEngine_Base {
145
  function upload( $files, &$results, $force_rewrite = false,
146
  $timeout_time = NULL ) {
147
  foreach ( $files as $file ) {
148
- if ( !is_null( $timeout_time ) && time() > $timeout_time )
149
- break;
150
-
151
  $local_path = $file['local_path'];
152
  $remote_path = $file['remote_path'];
153
 
 
 
 
 
 
 
 
154
  if ( !file_exists( $local_path ) ) {
155
  $results[] = $this->_get_result( $local_path, $remote_path,
156
  W3TC_CDN_RESULT_ERROR, 'Source file not found.', $file );
145
  function upload( $files, &$results, $force_rewrite = false,
146
  $timeout_time = NULL ) {
147
  foreach ( $files as $file ) {
 
 
 
148
  $local_path = $file['local_path'];
149
  $remote_path = $file['remote_path'];
150
 
151
+ // process at least one item before timeout so that progress goes on
152
+ if ( !empty( $results ) ) {
153
+ if ( !is_null( $timeout_time ) && time() > $timeout_time ) {
154
+ return 'timeout';
155
+ }
156
+ }
157
+
158
  if ( !file_exists( $local_path ) ) {
159
  $results[] = $this->_get_result( $local_path, $remote_path,
160
  W3TC_CDN_RESULT_ERROR, 'Source file not found.', $file );
CdnEngine_S3.php CHANGED
@@ -30,6 +30,7 @@ class CdnEngine_S3 extends CdnEngine_Base {
30
  'key' => '',
31
  'secret' => '',
32
  'bucket' => '',
 
33
  'cname' => array(),
34
  ), $config );
35
 
@@ -83,7 +84,19 @@ class CdnEngine_S3 extends CdnEngine_Base {
83
  return false;
84
  }
85
 
86
- $this->_s3 = new \S3( $this->_config['key'], $this->_config['secret'], false );
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  return true;
89
  }
@@ -107,12 +120,16 @@ class CdnEngine_S3 extends CdnEngine_Base {
107
  }
108
 
109
  foreach ( $files as $file ) {
110
- if ( !is_null( $timeout_time ) && time() > $timeout_time )
111
- break;
112
-
113
  $local_path = $file['local_path'];
114
  $remote_path = $file['remote_path'];
115
 
 
 
 
 
 
 
 
116
  $results[] = $this->_upload( $file, $force_rewrite );
117
 
118
  if ( $this->_config['compression'] && $this->_may_gzip( $remote_path ) ) {
@@ -167,10 +184,14 @@ class CdnEngine_S3 extends CdnEngine_Base {
167
  W3TC_CDN_RESULT_OK, 'OK', $file );
168
  }
169
 
 
 
 
 
 
 
170
  return $this->_get_result( $local_path, $remote_path,
171
- W3TC_CDN_RESULT_ERROR,
172
- sprintf( 'Unable to put object (%s).', $this->_get_last_error() ),
173
- $file );
174
  }
175
 
176
  /**
@@ -235,10 +256,14 @@ class CdnEngine_S3 extends CdnEngine_Base {
235
  W3TC_CDN_RESULT_OK, 'OK', $file );
236
  }
237
 
 
 
 
 
 
 
238
  return $this->_get_result( $local_path, $remote_path,
239
- W3TC_CDN_RESULT_ERROR,
240
- sprintf( 'Unable to put object (%s).', $this->_get_last_error() ),
241
- $file );
242
  }
243
 
244
  /**
@@ -337,7 +362,11 @@ class CdnEngine_S3 extends CdnEngine_Base {
337
  }
338
 
339
  if ( !@$this->_s3->putObjectString( $string, $this->_config['bucket'], $string, \S3::ACL_PUBLIC_READ ) ) {
340
- $error = sprintf( 'Unable to put object (%s).', $this->_get_last_error() );
 
 
 
 
341
 
342
  $this->_restore_error_handler();
343
 
30
  'key' => '',
31
  'secret' => '',
32
  'bucket' => '',
33
+ 'bucket_location' => '',
34
  'cname' => array(),
35
  ), $config );
36
 
84
  return false;
85
  }
86
 
87
+ if ( empty( $this->_config['bucket_location'] ) ) {
88
+ $region = '';
89
+ $endpoint = 's3.amazonaws.com';
90
+ } else {
91
+ $region = $this->_config['bucket_location'];
92
+ $endpoint = 's3.dualstack.' . $region . '.amazonaws.com';
93
+ }
94
+
95
+ $this->_s3 = new \S3( $this->_config['key'], $this->_config['secret'],
96
+ false, $endpoint, $region );
97
+ if ( empty( $region ) ) {
98
+ $this->_s3->setSignatureVersion( 'v2' );
99
+ }
100
 
101
  return true;
102
  }
120
  }
121
 
122
  foreach ( $files as $file ) {
 
 
 
123
  $local_path = $file['local_path'];
124
  $remote_path = $file['remote_path'];
125
 
126
+ // process at least one item before timeout so that progress goes on
127
+ if ( !empty( $results ) ) {
128
+ if ( !is_null( $timeout_time ) && time() > $timeout_time ) {
129
+ return 'timeout';
130
+ }
131
+ }
132
+
133
  $results[] = $this->_upload( $file, $force_rewrite );
134
 
135
  if ( $this->_config['compression'] && $this->_may_gzip( $remote_path ) ) {
184
  W3TC_CDN_RESULT_OK, 'OK', $file );
185
  }
186
 
187
+ if ( strpos( $this->_get_last_error(), 'AWS4-HMAC-SHA256' ) !== false ) {
188
+ $error = "Bucket location region is incorrect. Please select the right one.";
189
+ } else {
190
+ $error = sprintf( 'Unable to put object (%s).', $this->_get_last_error() );
191
+ }
192
+
193
  return $this->_get_result( $local_path, $remote_path,
194
+ W3TC_CDN_RESULT_ERROR, $error, $file );
 
 
195
  }
196
 
197
  /**
256
  W3TC_CDN_RESULT_OK, 'OK', $file );
257
  }
258
 
259
+ if ( strpos( $this->_get_last_error(), 'AWS4-HMAC-SHA256' ) !== false ) {
260
+ $error = "Bucket location region is incorrect. Please select the right one.";
261
+ } else {
262
+ $error = sprintf( 'Unable to put object (%s).', $this->_get_last_error() );
263
+ }
264
+
265
  return $this->_get_result( $local_path, $remote_path,
266
+ W3TC_CDN_RESULT_ERROR, $error, $file );
 
 
267
  }
268
 
269
  /**
362
  }
363
 
364
  if ( !@$this->_s3->putObjectString( $string, $this->_config['bucket'], $string, \S3::ACL_PUBLIC_READ ) ) {
365
+ if ( strpos( $this->_get_last_error(), 'AWS4-HMAC-SHA256' ) !== false ) {
366
+ $error = "Bucket location region is incorrect. Please select the right one.";
367
+ } else {
368
+ $error = sprintf( 'Unable to put object (%s).', $this->_get_last_error() );
369
+ }
370
 
371
  $this->_restore_error_handler();
372
 
CdnEngine_S3_Cf.php CHANGED
@@ -67,7 +67,20 @@ class CdnEngine_S3_Cf extends CdnEngine_S3 {
67
  return false;
68
  }
69
 
70
- $this->_s3 = new \S3( $this->_config['key'], $this->_config['secret'], false );
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  return true;
73
  }
@@ -193,7 +206,7 @@ class CdnEngine_S3_Cf extends CdnEngine_S3 {
193
  }
194
 
195
  $this->_set_error_handler();
196
- $invalidation = @$this->_s3->createInvalidation( $dist['id'], $paths );
197
  $this->_restore_error_handler();
198
 
199
  if ( !$invalidation ) {
@@ -358,7 +371,7 @@ class CdnEngine_S3_Cf extends CdnEngine_S3 {
358
 
359
  $matches = null;
360
 
361
- if ( preg_match( '~^(.+)\.cloudfront\.net$~', $dist['domain'], $matches ) ) {
362
  $container_id = $matches[1];
363
  }
364
 
67
  return false;
68
  }
69
 
70
+ if ( empty( $this->_config['bucket_location'] ) ) {
71
+ $region = '';
72
+ $endpoint = 's3.amazonaws.com';
73
+ } else {
74
+ $region = $this->_config['bucket_location'];
75
+ $endpoint = 's3.dualstack.'.$region.'.amazonaws.com';
76
+ }
77
+
78
+ $this->_s3 = new \S3( $this->_config['key'], $this->_config['secret'],
79
+ false, $endpoint, $region );
80
+
81
+ if ( empty( $region ) ) {
82
+ $this->_s3->setSignatureVersion( 'v2' );
83
+ }
84
 
85
  return true;
86
  }
206
  }
207
 
208
  $this->_set_error_handler();
209
+ $invalidation = @$this->_s3->invalidateDistribution( $dist['id'], $paths );
210
  $this->_restore_error_handler();
211
 
212
  if ( !$invalidation ) {
371
 
372
  $matches = null;
373
 
374
+ if ( !empty( $dist['domain'] ) && preg_match( '~^(.+)\.cloudfront\.net$~', $dist['domain'], $matches ) ) {
375
  $container_id = $matches[1];
376
  }
377
 
CdnEngine_S3_Compatible.php CHANGED
@@ -33,6 +33,8 @@ class CdnEngine_S3_Compatible extends CdnEngine_Base {
33
 
34
  $this->_s3 = new \S3( $config['key'], $config['secret'], false,
35
  $config['api_host'] );
 
 
36
  parent::__construct( $config );
37
  }
38
 
@@ -72,12 +74,16 @@ class CdnEngine_S3_Compatible extends CdnEngine_Base {
72
  $error = null;
73
 
74
  foreach ( $files as $file ) {
75
- if ( !is_null( $timeout_time ) && time() > $timeout_time )
76
- break;
77
-
78
  $local_path = $file['local_path'];
79
  $remote_path = $file['remote_path'];
80
 
 
 
 
 
 
 
 
81
  $results[] = $this->_upload( $file, $force_rewrite );
82
 
83
  if ( $this->_config['compression'] && $this->_may_gzip( $remote_path ) ) {
33
 
34
  $this->_s3 = new \S3( $config['key'], $config['secret'], false,
35
  $config['api_host'] );
36
+ $this->_s3->setSignatureVersion( 'v2' );
37
+
38
  parent::__construct( $config );
39
  }
40
 
74
  $error = null;
75
 
76
  foreach ( $files as $file ) {
 
 
 
77
  $local_path = $file['local_path'];
78
  $remote_path = $file['remote_path'];
79
 
80
+ // process at least one item before timeout so that progress goes on
81
+ if ( !empty( $results ) ) {
82
+ if ( !is_null( $timeout_time ) && time() > $timeout_time ) {
83
+ return 'timeout';
84
+ }
85
+ }
86
+
87
  $results[] = $this->_upload( $file, $force_rewrite );
88
 
89
  if ( $this->_config['compression'] && $this->_may_gzip( $remote_path ) ) {
Cdn_AdminActions.php CHANGED
@@ -118,12 +118,12 @@ class Cdn_AdminActions {
118
  $results = array();
119
 
120
  $w3_plugin_cdn->export_library( $limit, $offset, $count, $total,
121
- $results, time() + 5 );
122
 
123
  $response = array(
124
  'limit' => $limit,
125
  'offset' => $offset,
126
- 'count' => count( $results ),
127
  'total' => $total,
128
  'results' => $results
129
  );
@@ -493,265 +493,26 @@ class Cdn_AdminActions {
493
  $type = Util_Request::get_string( 'type', 's3' );
494
 
495
  $locations = array(
496
- '' => 'US (Default)',
497
- 'us-west-1' => __( 'US-West (Northern California)', 'w3-total-cache' ),
498
- 'EU' => 'Europe',
499
- 'ap-southeast-1' => __( 'AP-SouthEast (Singapore)', 'w3-total-cache' ),
 
 
 
 
 
 
 
 
 
 
500
  );
501
 
502
  include W3TC_INC_DIR . '/lightbox/cdn_s3_bucket_location.php';
503
  }
504
 
505
 
506
- /**
507
- * Includes the manual create pull zone form.
508
- */
509
- function w3tc_cdn_create_netdna_maxcdn_pull_zone_form() {
510
- $type = Util_Request::get_string( 'type', 'maxcdn' );
511
- include W3TC_INC_DIR . '/lightbox/create_netdna_maxcdn_pull_zone.php';
512
- }
513
-
514
-
515
- /**
516
- * Create NetDNA/MaxCDN pullzone
517
- */
518
- function w3tc_cdn_create_netdna_maxcdn_pull_zone() {
519
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
520
- $type = Util_Request::get_string( 'type' );
521
- $name = Util_Request::get_string( 'name' );
522
- $label = Util_Request::get_string( 'label' );
523
- $cdn_engine= $type;
524
-
525
- $authorization_key = $this->_config->get_string( "cdn.$cdn_engine.authorization_key" );
526
- $alias = $consumerkey = $consumersecret = '';
527
-
528
- if ( $authorization_key ) {
529
- $keys = explode( '+', $authorization_key );
530
- if ( sizeof( $keys ) == 3 ) {
531
- list( $alias, $consumerkey, $consumersecret ) = $keys;
532
- }
533
- }
534
- $api = new \NetDNA( $alias, $consumerkey, $consumersecret );
535
- $url = get_home_url();
536
- $zone = array();
537
- $zone['name'] = $name;
538
- $zone['label'] = $label;
539
- $zone['url'] = $url;
540
- $zone['use_stale'] = 1;
541
- $zone['queries'] = 1;
542
- $zone['compress'] = 1;
543
- $zone['backend_compress'] = 1;
544
- try {
545
- $response = $api->create_pull_zone( $zone );
546
- try {
547
- $temporary_url = "$name.$alias.netdna-cdn.com";
548
- $test_result = -1;
549
- if ( !$this->_config->get_array( "cdn.$cdn_engine.domain" ) ) {
550
- $test_result = $this->test_cdn_url( $temporary_url ) ? 1 : 0;
551
- $this->_config->set( "cdn.$cdn_engine.domain", array( $temporary_url ) );
552
- if ( $test_result )
553
- $this->_config->set( "cdn.enabled", true );
554
- }
555
- $this->_config->save();
556
- $state = Dispatcher::config_state();
557
- $zones = $api->get_pull_zones();
558
- $zone_count = sizeof( $zones );
559
- Util_Admin::make_track_call( array( 'type'=>'cdn',
560
- 'data'=>array(
561
- 'cdn' => $type, 'action' => 'zonecreation', 'creation' => 'manual', 'creationtime' => time()
562
- , 'signupclick' => $state->get_integer( 'track.maxcdn_signup' )
563
- , 'authorizeclick' => $state->get_integer( 'track.maxcdn_authorize' )
564
- , 'validationclick' => $state->get_integer( 'track.maxcdn_validation' )
565
- , 'total_zones' => $zone_count
566
- , 'test' => $test_result
567
- ) ) );
568
- } catch ( \Exception $ex ) {}
569
- echo json_encode( array( 'status' => 'success', 'message' => 'Pull Zone created.', 'temporary_url' => "$name.$alias.netdna-cdn.com", 'data' => $response ) );
570
- } catch ( \Exception $ex ) {
571
- echo json_encode( array( 'status' => 'error', 'message' => $ex->getMessage() ) );
572
- }
573
- }
574
-
575
- /**
576
- * Validates the authorization key and echos json encoded data connected with the key.
577
- */
578
- function w3tc_cdn_validate_authorization_key() {
579
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
580
-
581
- $cdn_engine = Util_Request::get_string( 'type' );
582
- $this->validate_cdnengine_is_netdna_maxcdn( $cdn_engine );
583
- $authorization_key = Util_Request::get_string( 'authorization_key' );
584
- $this->validate_authorization_key( $authorization_key );
585
- $keys = explode( '+', $authorization_key );
586
- list( $alias, $consumer_key, $consumer_secret ) = $keys;
587
- $api = new \NetDNA( $alias, $consumer_key, $consumer_secret );
588
- $this->validate_account( $api );
589
- try {
590
- $pull_zones = $api->get_zones_by_url( get_home_url() );
591
- if ( sizeof( $pull_zones ) == 0 ) {
592
- $result = array( 'result' => 'create' );
593
- try {
594
- $this->_config->set( "cdn.$cdn_engine.authorization_key", $authorization_key );
595
- $this->_config->save();
596
- } catch ( \Exception $ex ) {}
597
- } elseif ( sizeof( $pull_zones ) == 1 ) {
598
- $custom_domains = $api->get_custom_domains( $pull_zones[0]['id'] );
599
- if ( sizeof( $custom_domains ) > 0 ) {
600
- $result = array( 'result' => 'single', 'cnames' => array( $custom_domains ) );
601
- $this->_config->set( "cdn.$cdn_engine.domain", $custom_domains );
602
- $this->_config->set( "cdn.enabled", true );
603
- } else {
604
- $name = $pull_zones[0]['name'];
605
- $result = array( 'result' => 'single', 'cnames' => array( "$name.$alias.netdna-cdn.com" ) );
606
- }
607
- $this->_config->set( "cdn.$cdn_engine.zone_id", $pull_zones[0]['id'] );
608
- $this->_config->set( "cdn.$cdn_engine.authorization_key", $authorization_key );
609
- $this->_config->set( "cdn.$cdn_engine.domain", $result['cnames'] );
610
- $this->_config->save();
611
- } else {
612
- $zones = array();
613
- $data = array();
614
- foreach ( $pull_zones as $zone ) {
615
- if ( empty( $data ) ) {
616
- $domains = $this->test_cdn_pull_zone( $api, $zone['id'], $zone['name'], $alias );
617
- if ( $domains ) {
618
- $data = array( 'id' => $zone['id'], 'domains' => $domains );
619
- $this->_config->set( "cdn.$cdn_engine.zone_id", $zone['id'] );
620
- $this->_config->set( "cdn.$cdn_engine.domain", $domains );
621
- }
622
- }
623
- $zones[] = array( 'id' => $zone['id'], 'name' => $zone['name'] );
624
- }
625
- $result = array( 'result' => 'many', 'zones' => $zones, 'data' => $data );
626
- $this->_config->set( "cdn.$cdn_engine.authorization_key", $authorization_key );
627
- $this->_config->save();
628
- }
629
- try {
630
- $state = Dispatcher::config_state();
631
- if ( $state->get_integer( 'track.maxcdn_validation', 0 ) == 0 ) {
632
- $state->set( 'track.maxcdn_validation', time() );
633
- $state->save();
634
- }
635
- } catch ( \Exception $ex ) {}
636
- } catch ( \Exception $ex ) {
637
- $result = array( 'result' => 'error', 'message' => $ex->getMessage() );
638
- }
639
- echo json_encode( $result );
640
- exit();
641
- }
642
-
643
- /**
644
- *
645
- *
646
- * @param NetDNA $api
647
- * @param int $id
648
- * @param string $name
649
- * @param string $alias
650
- * @return array|null
651
- */
652
- private function test_cdn_pull_zone( $api, $id, $name, $alias ) {
653
- try {
654
- $domains = $api->get_custom_domains( $id );
655
- if ( $domains ) {
656
- $test = true;
657
- foreach ( $domains as $domain )
658
- $test = $test && $this->test_cdn_url( $domain );
659
- } else {
660
- $url = "$name.$alias.netdna-cdn.com";
661
- $test = $this->test_cdn_url( $url );
662
- $domains = array( $url );
663
- }
664
- if ( $test )
665
- return $domains;
666
- } catch ( \Exception $ex ) {}
667
- return array();
668
- }
669
- /**
670
- * Validates key and echos encoded message on failure.
671
- *
672
- * @param unknown $authorization_key
673
- */
674
- private function validate_authorization_key( $authorization_key ) {
675
- if ( empty( $authorization_key ) ) {
676
- $result = array( 'result' => 'error', 'message' => __( 'An authorization key was not provided.', 'w3-total-cache' ) );
677
- echo json_encode( $result );
678
- exit();
679
- }
680
- $keys = explode( '+', $authorization_key );
681
- if ( sizeof( $keys ) != 3 ) {
682
- $result = array( 'result' => 'error', 'message' => sprintf( __( 'The provided authorization key is
683
- not in the correct format: %s.', 'w3-total-cache' ), $authorization_key ) );
684
- echo json_encode( $result );
685
- exit();
686
-
687
- }
688
- }
689
-
690
- /**
691
- * Validates that the API works and echos message and exists if it fails
692
- *
693
- * @param NetDNA $api
694
- * @return null|array
695
- */
696
- private function validate_account( $api ) {
697
- try {
698
- return $api->get_account();
699
- } catch ( \Exception $ex ) {
700
- $result = array( 'result' => 'error', 'message' => $ex->getMessage() );
701
- echo json_encode( $result );
702
- exit();
703
- }
704
- }
705
-
706
- /**
707
- * Create a NetDNA or MaxCDN pull zone automatically
708
- */
709
- function w3tc_cdn_auto_create_netdna_maxcdn_pull_zone() {
710
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
711
-
712
- $cdn_engine = Util_Request::get_string( 'type' );
713
- $this->validate_cdnengine_is_netdna_maxcdn( $cdn_engine );
714
- $authorization_key = Util_Request::get_string( 'authorization_key' );
715
- $this->validate_authorization_key( $authorization_key );
716
- $keys = explode( '+', $authorization_key );
717
- list( $alias, $consumerkey, $consumersecret ) = $keys;
718
- $url = get_home_url();
719
- try {
720
- $api = new \NetDNA( $alias, $consumerkey, $consumersecret );
721
- $disable_cooker_header = $this->_config->get_boolean( 'browsercache.other.nocookies' ) ||
722
- $this->_config->get_boolean( 'browsercache.cssjs.nocookies' );
723
- $zone = $api->create_default_pull_zone( $url, null, null,
724
- array( 'ignore_setcookie_header' => $disable_cooker_header ) );
725
- $name = $zone['name'];
726
- $temporary_url = "$name.$alias.netdna-cdn.com";
727
- $test_result = -1;
728
- if ( !$this->_config->get_array( "cdn.$cdn_engine.domain" ) ) {
729
- $test_result = $this->test_cdn_url( $temporary_url ) ? 1 : 0;
730
- $this->_config->set( "cdn.$cdn_engine.zone_id", $zone['id'] );
731
- if ( $test_result )
732
- $this->_config->set( "cdn.enabled", true );
733
- $this->_config->set( "cdn.$cdn_engine.domain", array( $temporary_url ) );
734
- }
735
- $this->_config->save();
736
- $state = Dispatcher::config_state();
737
- $zones = $api->get_pull_zones();
738
- $zone_count = sizeof( $zones );
739
- Util_Admin::make_track_call( array( 'type'=>'cdn',
740
- 'data'=>array(
741
- 'cdn' => $cdn_engine, 'action' => 'zonecreation'
742
- , 'creation' => 'manual', 'creationtime' => time()
743
- , 'signupclick' => $state->get_integer( 'track.maxcdn_signup' )
744
- , 'authorizeclick' => $state->get_integer( 'track.maxcdn_authorize' )
745
- , 'validationclick' => $state->get_integer( 'track.maxcdn_validation' )
746
- , 'total_zones' => $zone_count
747
- , 'test' => $test_result ) ) );
748
- $result = array( 'result' => 'single', 'cnames' => array( $temporary_url ) );
749
- } catch ( \Exception $ex ) {
750
- $result = array( 'result' => 'error', 'message' => sprintf( __( 'Could not create default zone.' . $ex->getMessage(), 'w3-total-cache' ) ) );
751
- }
752
- echo json_encode( $result );
753
- exit();
754
- }
755
 
756
  private function test_cdn_url( $url ) {
757
  $response = wp_remote_get( $url );
@@ -762,70 +523,8 @@ class Cdn_AdminActions {
762
  return 200 == $code;
763
  }
764
  }
765
- /**
766
- * Configures the plugin to use the zone id provided in request
767
- */
768
- function w3tc_cdn_use_netdna_maxcdn_pull_zone() {
769
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
770
-
771
- $cdn_engine = Util_Request::get_string( 'type' );
772
- $this->validate_cdnengine_is_netdna_maxcdn( $cdn_engine );
773
- $authorization_key = Util_Request::get_string( 'authorization_key' );
774
- $this->validate_authorization_key( $authorization_key );
775
- $zone_id = Util_Request::get_integer( 'zone_id' );
776
- $keys = explode( '+', $authorization_key );
777
- list( $alias, $consumer_key, $consumer_secret ) = $keys;
778
- $api = new \NetDNA( $alias, $consumer_key, $consumer_secret );
779
- $this->validate_account( $api );
780
- try {
781
- $pull_zone = $api->get_zone( $zone_id );
782
- if ( $pull_zone ) {
783
- $custom_domains = $api->get_custom_domains( $pull_zone['id'] );
784
- if ( sizeof( $custom_domains ) > 0 ) {
785
- $result = array( 'result' => 'valid', 'cnames' => array( $custom_domains ) );
786
- $test = true;
787
- foreach ( $custom_domains as $url )
788
- $test = $test && $this->test_cdn_url( $url );
789
- if ( $test )
790
- $this->_config->set( "cdn.enabled", true );
791
- } else {
792
- $name = $pull_zone['name'];
793
- $result = array( 'result' => 'valid', 'cnames' => array( "$name.$alias.netdna-cdn.com" ) );
794
- $test = $this->test_cdn_url( "$name.$alias.netdna-cdn.com" );
795
- if ( $test )
796
- $this->_config->set( "cdn.enabled", true );
797
- }
798
- $this->_config->set( "cdn.enabled", true );
799
- $this->_config->set( "cdn.$cdn_engine.zone_id", $pull_zone['id'] );
800
- $this->_config->set( "cdn.$cdn_engine.domain", $result['cnames'] );
801
- $this->_config->save();
802
- } else {
803
- $result = array( 'result' => 'error', 'message' => sprintf( __( 'The provided zone id was not connected to the provided authorization key.', 'w3-total-cache' ) ) );
804
- }
805
- } catch ( \Exception $ex ) {
806
- $result = array( 'result' => 'error', 'message' => $ex->getMessage() );
807
- }
808
 
809
- echo json_encode( $result );
810
- exit();
811
- }
812
 
813
- function w3tc_cdn_save_activate() {
814
- try {
815
- $this->_config->set( 'cdn.enabled', true );
816
- $this->_config->save();
817
- } catch ( \Exception $ex ) {}
818
- Util_Environment::redirect( Util_Ui::admin_url( sprintf( 'admin.php?page=w3tc_cdn#configuration' ) ) );
819
- }
820
-
821
- function w3tc_cdn_maxcdn_signup() {
822
- try {
823
- $state = Dispatcher::config_state();
824
- $state->set( 'track.maxcdn_signup', time() );
825
- $state->save();
826
- } catch ( \Exception $ex ) {}
827
- Util_Environment::redirect( MAXCDN_SIGNUP_URL );
828
- }
829
 
830
  function w3tc_cdn_maxcdn_authorize() {
831
  try {
@@ -838,28 +537,12 @@ class Cdn_AdminActions {
838
  Util_Environment::redirect( MAXCDN_AUTHORIZE_URL );
839
  }
840
 
841
- function w3tc_cdn_netdna_authorize() {
842
  try {
843
  $state = Dispatcher::config_state();
844
- if ( $state->get_integer( 'track.maxcdn_authorize', 0 ) == 0 ) {
845
- $state->set( 'track.maxcdn_authorize', time() );
846
- $state->save();
847
- }
848
  } catch ( \Exception $ex ) {}
849
- Util_Environment::redirect( NETDNA_AUTHORIZE_URL );
850
- }
851
-
852
- /**
853
- * Validates cdn engine and echos message and exists if it fails
854
- *
855
- * @param unknown $cdn_engine
856
- */
857
- private function validate_cdnengine_is_netdna_maxcdn( $cdn_engine ) {
858
- if ( !in_array( $cdn_engine, array( 'netdna', 'maxcdn' ) ) ) {
859
- $result = array( 'result' => 'notsupported', 'message' => sprintf( __( '%s is not supported for Pull Zone
860
- selection.', 'w3-total-cache' ), $cdn_engine ) );
861
- echo json_encode( $result );
862
- exit();
863
- }
864
  }
865
  }
118
  $results = array();
119
 
120
  $w3_plugin_cdn->export_library( $limit, $offset, $count, $total,
121
+ $results, time() + 120 );
122
 
123
  $response = array(
124
  'limit' => $limit,
125
  'offset' => $offset,
126
+ 'count' => $count,
127
  'total' => $total,
128
  'results' => $results
129
  );
493
  $type = Util_Request::get_string( 'type', 's3' );
494
 
495
  $locations = array(
496
+ 'us-east-1' => __( 'US East (N. Virginia)', 'w3-total-cache' ),
497
+ 'us-east-2' => __( 'US East (Ohio)', 'w3-total-cache' ),
498
+ 'us-west-1' => __( 'US-West (N. California)', 'w3-total-cache' ),
499
+ 'us-west-2' => __( 'US-West (Oregon)', 'w3-total-cache' ),
500
+ 'ca-central-1' => __( 'Canada (Montreal)', 'w3-total-cache' ),
501
+ 'ap-south-1' => __( 'Asia Pacific (Mumbai)', 'w3-total-cache' ),
502
+ 'ap-northeast-2'=> __( 'Asia Pacific (Seoul)', 'w3-total-cache' ),
503
+ 'ap-southeast-1'=> __( 'Asia Pacific (Singapore)', 'w3-total-cache' ),
504
+ 'ap-southeast-2'=> __( 'Asia Pacific (Sydney)', 'w3-total-cache' ),
505
+ 'ap-northeast-1'=> __( 'Asia Pacific (Tokyo)', 'w3-total-cache' ),
506
+ 'eu-central-1' => __( 'EU (Frankfurt)', 'w3-total-cache' ),
507
+ 'eu-west-1' => __( 'EU (Ireland)', 'w3-total-cache' ),
508
+ 'eu-west-2' => __( 'EU (London)', 'w3-total-cache' ),
509
+ 'sa-east-1' => __( 'South America (S&atilde;o Paulo)', 'w3-total-cache' ),
510
  );
511
 
512
  include W3TC_INC_DIR . '/lightbox/cdn_s3_bucket_location.php';
513
  }
514
 
515
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
516
 
517
  private function test_cdn_url( $url ) {
518
  $response = wp_remote_get( $url );
523
  return 200 == $code;
524
  }
525
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
 
 
 
527
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
528
 
529
  function w3tc_cdn_maxcdn_authorize() {
530
  try {
537
  Util_Environment::redirect( MAXCDN_AUTHORIZE_URL );
538
  }
539
 
540
+ function w3tc_cdn_maxcdn_signup() {
541
  try {
542
  $state = Dispatcher::config_state();
543
+ $state->set( 'track.maxcdn_signup', time() );
544
+ $state->save();
 
 
545
  } catch ( \Exception $ex ) {}
546
+ Util_Environment::redirect( MAXCDN_SIGNUP_URL );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  }
548
  }
Cdn_AdminNotes.php CHANGED
@@ -108,7 +108,7 @@ class Cdn_AdminNotes {
108
  }
109
  }
110
 
111
- if ( in_array( $config->get_string( 'cdn.engine' ), array( 'netdna', 'maxcdn' ) ) &&
112
  !$state->get_boolean( 'cdn.hide_note_maxcdn_whitelist_ip' ) &&
113
  $state->get_integer( 'track.maxcdn_authorize' ) == 0 &&
114
  $config->get_string( 'cdn.' . $config->get_string( 'cdn.engine' ) .'.authorization_key' ) ) {
@@ -233,26 +233,6 @@ class Cdn_AdminNotes {
233
  $error = __( 'The <strong>"Replace default hostname with"</strong> field cannot be empty.', 'w3-total-cache' );
234
  break;
235
 
236
- case ( $cdn_engine == 'netdna' ):
237
- $fields = array();
238
- if ( $c->get_string( 'cdn.netdna.authorization_key' ) == '' )
239
- $fields[] = '"' . __( 'Authorization key', 'w3-total-cache' ) . '"';
240
-
241
- if ( !count( $c->get_array( 'cdn.netdna.domain' ) ) )
242
- $fields[] = '"' . __( 'Replace default hostname with', 'w3-total-cache' ) . '"';
243
-
244
- if ( $fields ) {
245
- $error = sprintf( __( 'The <strong>%s</strong> field(s) cannot be empty.', 'w3-total-cache' ),
246
- implode( __( ' and ', 'w3-total-cache' ), $fields ) );
247
- }
248
-
249
- if ( $c->get_string( 'cdn.netdna.authorization_key' ) != '' &&
250
- sizeof( explode( '+', $c->get_string( 'cdn.netdna.authorization_key' ) ) ) != 3 )
251
- $error .= __( 'The <strong>"Authorization key"</strong> is not correct.', 'w3-total-cache' );
252
- elseif ( $c->get_integer( 'cdn.netdna.zone_id', 0 ) <= 0 )
253
- $error .= __( 'You need to select / create a pull zone.', 'w3-total-cache' );
254
- break;
255
-
256
  case ( $cdn_engine == 'maxcdn' ):
257
  $fields = array();
258
  if ( $c->get_string( 'cdn.maxcdn.authorization_key' ) == '' )
108
  }
109
  }
110
 
111
+ if ( $config->get_string( 'cdn.engine' ) == 'maxcdn' &&
112
  !$state->get_boolean( 'cdn.hide_note_maxcdn_whitelist_ip' ) &&
113
  $state->get_integer( 'track.maxcdn_authorize' ) == 0 &&
114
  $config->get_string( 'cdn.' . $config->get_string( 'cdn.engine' ) .'.authorization_key' ) ) {
233
  $error = __( 'The <strong>"Replace default hostname with"</strong> field cannot be empty.', 'w3-total-cache' );
234
  break;
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  case ( $cdn_engine == 'maxcdn' ):
237
  $fields = array();
238
  if ( $c->get_string( 'cdn.maxcdn.authorization_key' ) == '' )
Cdn_CloudFrontFsd_Page.php DELETED
@@ -1,18 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- class Cdn_CloudFrontFsd_Page {
5
- // called from plugin-admin
6
- static public function admin_print_scripts_w3tc_cdn() {
7
- wp_enqueue_script( 'w3tc_cdn_cloudfront_fsd',
8
- plugins_url( 'Cdn_CloudFrontFsd_Page_View.js', W3TC_FILE ),
9
- array( 'jquery' ), '1.0' );
10
- }
11
-
12
-
13
-
14
- static public function w3tc_settings_cdn() {
15
- $config = Dispatcher::config();
16
- include W3TC_DIR . '/Cdn_CloudFrontFsd_Page_View.php';
17
- }
18
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Cdn_ConfigLabels.php CHANGED
@@ -7,6 +7,7 @@ class Cdn_ConfigLabels {
7
  'cdn.enabled' => __( '<acronym title="Content Delivery Network">CDN</acronym>:', 'w3-total-cache' ),
8
  'cdn.engine' => __( '<acronym title="Content Delivery Network">CDN</acronym> Type:', 'w3-total-cache' ),
9
  'cdn.debug' => __( '<acronym title="Content Delivery Network">CDN</acronym>', 'w3-total-cache' ),
 
10
  'cdn.uploads.enable' => __( 'Host attachments', 'w3-total-cache' ),
11
  'cdn.includes.enable' => __( 'Host wp-includes/ files', 'w3-total-cache' ),
12
  'cdn.theme.enable' => __( 'Host theme files', 'w3-total-cache' ),
@@ -16,6 +17,7 @@ class Cdn_ConfigLabels {
16
  'cdn.import.external' => __( 'Import external media library attachments', 'w3-total-cache' ),
17
  'cdn.canonical_header' => __( 'Add canonical header', 'w3-total-cache' ),
18
  'cdn.reject.ssl' => __( 'Disable <acronym title="Content Delivery Network">CDN</acronym> on <acronym title="Secure Sockets Layer">SSL</acronym> pages', 'w3-total-cache' ),
 
19
  'cdn.reject.logged_roles' => __( 'Disable <acronym title="Content Delivery Network">CDN</acronym> for the following roles', 'w3-total-cache' ),
20
  'cdn.reject.uri' => __( 'Disable <acronym title="Content Delivery Network">CDN</acronym> on the following pages:', 'w3-total-cache' ),
21
  'cdn.autoupload.enabled' => __( 'Export changed files automatically', 'w3-total-cache' ),
7
  'cdn.enabled' => __( '<acronym title="Content Delivery Network">CDN</acronym>:', 'w3-total-cache' ),
8
  'cdn.engine' => __( '<acronym title="Content Delivery Network">CDN</acronym> Type:', 'w3-total-cache' ),
9
  'cdn.debug' => __( '<acronym title="Content Delivery Network">CDN</acronym>', 'w3-total-cache' ),
10
+ 'cdnfsd.debug' => __( '<acronym title="Full Site Delivery">FSD</acronym> <acronym title="Content Delivery Network">CDN</acronym>', 'w3-total-cache' ),
11
  'cdn.uploads.enable' => __( 'Host attachments', 'w3-total-cache' ),
12
  'cdn.includes.enable' => __( 'Host wp-includes/ files', 'w3-total-cache' ),
13
  'cdn.theme.enable' => __( 'Host theme files', 'w3-total-cache' ),
17
  'cdn.import.external' => __( 'Import external media library attachments', 'w3-total-cache' ),
18
  'cdn.canonical_header' => __( 'Add canonical header', 'w3-total-cache' ),
19
  'cdn.reject.ssl' => __( 'Disable <acronym title="Content Delivery Network">CDN</acronym> on <acronym title="Secure Sockets Layer">SSL</acronym> pages', 'w3-total-cache' ),
20
+ 'cdn.admin.media_library' => __( 'Use CDN links for the Media Library on admin pages', 'w3-total-cache' ),
21
  'cdn.reject.logged_roles' => __( 'Disable <acronym title="Content Delivery Network">CDN</acronym> for the following roles', 'w3-total-cache' ),
22
  'cdn.reject.uri' => __( 'Disable <acronym title="Content Delivery Network">CDN</acronym> on the following pages:', 'w3-total-cache' ),
23
  'cdn.autoupload.enabled' => __( 'Export changed files automatically', 'w3-total-cache' ),
Cdn_Core.php CHANGED
@@ -367,6 +367,7 @@ class Cdn_Core {
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
  'id' => $this->_config->get_string( 'cdn.cf.id' ),
371
  'cname' => $this->_config->get_array( 'cdn.cf.cname' ),
372
  'ssl' => $this->_config->get_string( 'cdn.cf.ssl' ),
@@ -477,16 +478,6 @@ class Cdn_Core {
477
  );
478
  break;
479
 
480
- case 'netdna':
481
- $engine_config = array(
482
- 'authorization_key' => $this->_config->get_string( 'cdn.netdna.authorization_key' ),
483
- 'zone_id' => $this->_config->get_integer( 'cdn.netdna.zone_id' ),
484
- 'domain' => $this->_config->get_array( 'cdn.netdna.domain' ),
485
- 'ssl' => $this->_config->get_string( 'cdn.netdna.ssl' ),
486
- 'compression' => false
487
- );
488
- break;
489
-
490
  case 'rackspace_cdn':
491
  $state = Dispatcher::config_state();
492
 
@@ -533,6 +524,7 @@ class Cdn_Core {
533
  'key' => $this->_config->get_string( 'cdn.s3.key' ),
534
  'secret' => $this->_config->get_string( 'cdn.s3.secret' ),
535
  'bucket' => $this->_config->get_string( 'cdn.s3.bucket' ),
 
536
  'cname' => $this->_config->get_array( 'cdn.s3.cname' ),
537
  'ssl' => $this->_config->get_string( 'cdn.s3.ssl' ),
538
  'compression' => $compression
@@ -669,6 +661,25 @@ class Cdn_Core {
669
  return ltrim( $remote_uri, '/' );
670
  }
671
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  /**
673
  * Returns the sitepath for multisite subfolder or subdomain path for multisite subdomain
674
  *
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' ),
478
  );
479
  break;
480
 
 
 
 
 
 
 
 
 
 
 
481
  case 'rackspace_cdn':
482
  $state = Dispatcher::config_state();
483
 
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
661
  return ltrim( $remote_uri, '/' );
662
  }
663
 
664
+ /**
665
+ * Need to pass full URL and it's URI
666
+ * URI passed to prevent redundant parsing, normally it's available for caller
667
+ **/
668
+ function url_to_cdn_url( $url, $path ) {
669
+ $cdn = $this->get_cdn();
670
+ $remote_path = $this->uri_to_cdn_uri( $path );
671
+ $new_url = $cdn->format_url( $remote_path );
672
+ if ( !$new_url ) {
673
+ return null;
674
+ }
675
+ $is_engine_mirror = Cdn_Util::is_engine_mirror(
676
+ $this->_config->get_string( 'cdn.engine' ) );
677
+
678
+ $new_url = apply_filters( 'w3tc_cdn_url', $new_url, $url,
679
+ $is_engine_mirror );
680
+ return $new_url;
681
+ }
682
+
683
  /**
684
  * Returns the sitepath for multisite subfolder or subdomain path for multisite subdomain
685
  *
Cdn_Core_Admin.php CHANGED
@@ -209,7 +209,9 @@ class Cdn_Core_Admin {
209
  WHERE
210
  p.post_type = "attachment" AND (pm.meta_value IS NOT NULL OR pm2.meta_value IS NOT NULL)
211
  GROUP BY
212
- p.ID', $wpdb->prefix, $wpdb->prefix, $wpdb->prefix );
 
 
213
 
214
  if ( $limit ) {
215
  $sql .= sprintf( ' LIMIT %d', $limit );
@@ -715,10 +717,12 @@ WHERE p.post_type = "attachment" AND (pm.meta_value IS NOT NULL OR pm2.meta_valu
715
  }
716
 
717
  /**
718
- * Changes settings on MaxCDN/NetDNA site
719
  */
720
  function change_canonical_header() {
721
- if ( in_array( $cdn_engine = $this->_config->get_string( 'cdn.engine' ), array( 'maxcdn', 'netdna' ) ) ) {
 
 
722
  require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
723
  $authorization_key = $this->_config->get_string( "cdn.$cdn_engine.authorization_key" );
724
  if ( $authorization_key ) {
@@ -776,10 +780,6 @@ WHERE p.post_type = "attachment" AND (pm.meta_value IS NOT NULL OR pm2.meta_valu
776
  $running = false;
777
  break;
778
 
779
- case ( $cdn_engine == 'netdna' ):
780
- $running = false;
781
- break;
782
-
783
  case ( $cdn_engine == 'maxcdn' ):
784
  $running = false;
785
  break;
209
  WHERE
210
  p.post_type = "attachment" AND (pm.meta_value IS NOT NULL OR pm2.meta_value IS NOT NULL)
211
  GROUP BY
212
+ p.ID
213
+ ORDER BY
214
+ p.ID', $wpdb->prefix, $wpdb->prefix, $wpdb->prefix );
215
 
216
  if ( $limit ) {
217
  $sql .= sprintf( ' LIMIT %d', $limit );
717
  }
718
 
719
  /**
720
+ * Changes settings on MaxCDN site
721
  */
722
  function change_canonical_header() {
723
+ $cdn_engine = $this->_config->get_string( 'cdn.engine' );
724
+
725
+ if ( $cdn_engine == 'maxcdn' ) {
726
  require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
727
  $authorization_key = $this->_config->get_string( "cdn.$cdn_engine.authorization_key" );
728
  if ( $authorization_key ) {
780
  $running = false;
781
  break;
782
 
 
 
 
 
783
  case ( $cdn_engine == 'maxcdn' ):
784
  $running = false;
785
  break;
Cdn_Environment.php CHANGED
@@ -1,11 +1,6 @@
1
  <?php
2
  namespace W3TC;
3
 
4
-
5
-
6
-
7
-
8
-
9
  /**
10
  * class Cdn_Environment
11
  */
@@ -79,7 +74,9 @@ class Cdn_Environment {
79
 
80
  if ( $config->get_boolean( 'cdn.enabled' ) ) {
81
  try {
82
- $this->table_create( $event == 'activate' );
 
 
83
  } catch ( \Exception $ex ) {
84
  $exs->push( $ex );
85
  }
@@ -96,7 +93,7 @@ class Cdn_Environment {
96
  $exs = new Util_Environment_Exceptions();
97
 
98
  $this->rules_remove( $exs );
99
- $this->table_delete();
100
 
101
  if ( count( $exs->exceptions() ) > 0 )
102
  throw $exs;
@@ -162,33 +159,36 @@ class Cdn_Environment {
162
 
163
 
164
 
165
- /*
166
- * table operations
167
- */
168
-
169
  /**
170
- * Create queue table
171
  *
172
  * @param bool $drop
173
  * @throws Util_Environment_Exception
174
  */
175
- private function table_create( $drop = false ) {
176
  global $wpdb;
177
 
178
- if ( $drop ) {
179
- $sql = sprintf( 'DROP TABLE IF EXISTS `%s%s`;', $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE );
180
 
 
 
 
 
181
  $wpdb->query( $sql );
182
  }
183
 
184
- $charset_collate = '';
 
 
185
 
 
186
  if ( ! empty( $wpdb->charset ) )
187
  $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
188
  if ( ! empty( $wpdb->collate ) )
189
  $charset_collate .= " COLLATE $wpdb->collate";
190
 
191
- $sql = sprintf( "CREATE TABLE IF NOT EXISTS `%s%s` (
192
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
193
  `local_path` varchar(500) NOT NULL DEFAULT '',
194
  `remote_path` varchar(500) NOT NULL DEFAULT '',
@@ -197,26 +197,34 @@ class Cdn_Environment {
197
  `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
198
  PRIMARY KEY (`id`),
199
  KEY `date` (`date`)
200
- ) $charset_collate;", $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE );
201
 
202
  $wpdb->query( $sql );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
 
204
  if ( !$wpdb->result )
205
  throw new Util_Environment_Exception( 'Can\'t create table ' .
206
- $wpdb->base_prefix . W3TC_CDN_TABLE_QUEUE );
207
  }
208
 
209
- /**
210
- * Delete queue table
211
- *
212
- * @return void
213
- */
214
- private function table_delete() {
215
- global $wpdb;
216
 
217
- $sql = sprintf( 'DROP TABLE IF EXISTS `%s%s`', $wpdb->base_prefix, W3TC_CDN_TABLE_QUEUE );
218
- $wpdb->query( $sql );
219
- }
220
 
221
  private function generate_table_sql() {
222
  global $wpdb;
@@ -317,9 +325,12 @@ class Cdn_Environment {
317
  private function rules_generate( $config, $cdnftp = false ) {
318
  $rules = '';
319
  if ( Dispatcher::canonical_generated_by( $config, $cdnftp ) == 'cdn' )
320
- $rules .= Util_RuleSnippet::canonical( $config, $cdnftp );
321
- if ( Dispatcher::allow_origin_generated_by( $config ) == 'cdn' )
322
- $rules .= Util_RuleSnippet::allow_origin( $config, $cdnftp );
 
 
 
323
 
324
  if ( strlen( $rules ) > 0 )
325
  $rules =
@@ -329,4 +340,27 @@ class Cdn_Environment {
329
 
330
  return $rules;
331
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  }
1
  <?php
2
  namespace W3TC;
3
 
 
 
 
 
 
4
  /**
5
  * class Cdn_Environment
6
  */
74
 
75
  if ( $config->get_boolean( 'cdn.enabled' ) ) {
76
  try {
77
+ $this->handle_tables(
78
+ $event == 'activate' /* drop state on activation */,
79
+ true );
80
  } catch ( \Exception $ex ) {
81
  $exs->push( $ex );
82
  }
93
  $exs = new Util_Environment_Exceptions();
94
 
95
  $this->rules_remove( $exs );
96
+ $this->handle_tables( true, false );
97
 
98
  if ( count( $exs->exceptions() ) > 0 )
99
  throw $exs;
159
 
160
 
161
 
 
 
 
 
162
  /**
163
+ * Create tables
164
  *
165
  * @param bool $drop
166
  * @throws Util_Environment_Exception
167
  */
168
+ private function handle_tables( $drop, $create ) {
169
  global $wpdb;
170
 
171
+ $tablename_queue = $wpdb->base_prefix . W3TC_CDN_TABLE_QUEUE;
172
+ $tablename_map = $wpdb->base_prefix . W3TC_CDN_TABLE_PATHMAP;
173
 
174
+ if ( $drop ) {
175
+ $sql = "DROP TABLE IF EXISTS `$tablename_queue`;";
176
+ $wpdb->query( $sql );
177
+ $sql = "DROP TABLE IF EXISTS `$tablename_map`;";
178
  $wpdb->query( $sql );
179
  }
180
 
181
+ if ( !$create ) {
182
+ return;
183
+ }
184
 
185
+ $charset_collate = '';
186
  if ( ! empty( $wpdb->charset ) )
187
  $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
188
  if ( ! empty( $wpdb->collate ) )
189
  $charset_collate .= " COLLATE $wpdb->collate";
190
 
191
+ $sql = "CREATE TABLE IF NOT EXISTS `$tablename_queue` (
192
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
193
  `local_path` varchar(500) NOT NULL DEFAULT '',
194
  `remote_path` varchar(500) NOT NULL DEFAULT '',
197
  `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
198
  PRIMARY KEY (`id`),
199
  KEY `date` (`date`)
200
+ ) $charset_collate;";
201
 
202
  $wpdb->query( $sql );
203
+ if ( !$wpdb->result )
204
+ throw new Util_Environment_Exception( 'Can\'t create table ' .
205
+ $tablename_queue );
206
+
207
+ $sql = "
208
+ CREATE TABLE IF NOT EXISTS `$tablename_map` (
209
+ -- Relative file path.
210
+ -- For reference, not actually used for finding files.
211
+ path TEXT NOT NULL,
212
+ -- MD5 hash of remote path, used for finding files.
213
+ path_hash VARCHAR(32) CHARACTER SET ascii NOT NULL,
214
+ type tinyint(1) NOT NULL DEFAULT '0',
215
+ -- Google Drive: document identifier
216
+ remote_id VARCHAR(200) CHARACTER SET ascii,
217
+ PRIMARY KEY (path_hash),
218
+ KEY `remote_id` (`remote_id`)
219
+ ) $charset_collate";
220
 
221
+ $wpdb->query( $sql );
222
  if ( !$wpdb->result )
223
  throw new Util_Environment_Exception( 'Can\'t create table ' .
224
+ $tablename_map );
225
  }
226
 
 
 
 
 
 
 
 
227
 
 
 
 
228
 
229
  private function generate_table_sql() {
230
  global $wpdb;
325
  private function rules_generate( $config, $cdnftp = false ) {
326
  $rules = '';
327
  if ( Dispatcher::canonical_generated_by( $config, $cdnftp ) == 'cdn' )
328
+ $rules .= Util_RuleSnippet::canonical( $cdnftp,
329
+ $config->get_boolean( 'cdn.cors_header') );
330
+
331
+ if ( $config->get_boolean( 'cdn.cors_header') ) {
332
+ $rules .= $this->allow_origin( $cdnftp );
333
+ }
334
 
335
  if ( strlen( $rules ) > 0 )
336
  $rules =
340
 
341
  return $rules;
342
  }
343
+
344
+ /**
345
+ * Returns allow-origin rules
346
+ */
347
+ private function allow_origin( $cdnftp = false ) {
348
+ switch ( true ) {
349
+ case Util_Environment::is_apache():
350
+ case Util_Environment::is_litespeed():
351
+ $r = "<IfModule mod_headers.c>\n";
352
+ $r .= " Header set Access-Control-Allow-Origin \"*\"\n";
353
+ $r .= "</IfModule>\n";
354
+
355
+ if ( !$cdnftp )
356
+ return $r;
357
+ else
358
+ return
359
+ "<FilesMatch \"\.(ttf|ttc|otf|eot|woff|woff2|font.css)$\">\n" .
360
+ $r .
361
+ "</FilesMatch>\n";
362
+ }
363
+
364
+ return '';
365
+ }
366
  }
Cdn_Fsd_Core.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- /**
5
- * Core for FSD CDN
6
- */
7
- class Cdn_Fsd_Core {
8
- /**
9
- * Returns CDN object
10
- */
11
- function get_engine() {
12
- static $engine_object = null;
13
-
14
- if ( is_null( $engine_object ) ) {
15
- $c = Dispatcher::config();
16
- $engine = $c->get_string( 'cdn.engine' );
17
-
18
- switch ( $engine ) {
19
- case 'cloudfront_fsd':
20
- $engine_object = new Cdn_CloudFrontFsd_Engine( array(
21
- 'access_key' => $c->get_string( 'cdn.cloudfront_fsd.access_key' ),
22
- 'secret_key' => $c->get_string( 'cdn.cloudfront_fsd.secret_key' ),
23
- 'distribution_id' => $c->get_string( 'cdn.cloudfront_fsd.distribution_id' )
24
- ) );
25
- break;
26
-
27
- case 'maxcdn_fsd':
28
- $engine_object = new Cdn_MaxCdnFsd_Engine( array(
29
- 'api_key' => $c->get_string( 'cdn.maxcdn_fsd.api_key' ),
30
- 'zone_id' => $c->get_integer( 'cdn.maxcdn_fsd.zone_id' )
31
- ) );
32
- break;
33
-
34
- default:
35
- throw new \Exception( 'unknown engine ' . $engine );
36
- }
37
- }
38
-
39
- return $engine_object;
40
- }
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Cdn_GeneralPage_View.php CHANGED
@@ -30,12 +30,14 @@ Util_Ui::config_item( array(
30
  'selectbox_values' => $engine_values,
31
  'selectbox_optgroups' => $engine_optgroups,
32
  'description' => __( 'Select the <acronym title="Content Delivery Network">CDN</acronym> type you wish to use.',
33
- 'w3-total-cache' ) . $cdn_engine_extra_description
34
  ) );
35
  ?>
36
  </table>
37
 
38
  <?php
 
 
39
  Util_Ui::button_config_save( 'general_cdn',
40
  '<input id="cdn_purge" type="button" value="'.
41
  __( 'Empty cache', 'w3-total-cache' ) . '" ' .
30
  'selectbox_values' => $engine_values,
31
  'selectbox_optgroups' => $engine_optgroups,
32
  'description' => __( 'Select the <acronym title="Content Delivery Network">CDN</acronym> type you wish to use.',
33
+ 'w3-total-cache' )
34
  ) );
35
  ?>
36
  </table>
37
 
38
  <?php
39
+ do_action( 'w3tc_settings_general_boxarea_cdn_footer' );
40
+
41
  Util_Ui::button_config_save( 'general_cdn',
42
  '<input id="cdn_purge" type="button" value="'.
43
  __( 'Empty cache', 'w3-total-cache' ) . '" ' .
Cdn_Highwinds_Page_View.js CHANGED
@@ -43,7 +43,7 @@ jQuery(function($) {
43
  var name = $(this).attr('name');
44
  var type = $(this).attr('type');
45
  if (type == 'radio') {
46
- if (!$(this).attr('checked'))
47
  return;
48
  }
49
 
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
 
Cdn_Highwinds_Page_View.php CHANGED
@@ -21,7 +21,7 @@ $hash_code = $config->get_string( 'cdn.highwinds.host.hash_code' );
21
 
22
  <?php if ( !empty( $hash_code ) ): ?>
23
  <tr>
24
- <th><label><?php _e( 'CDN host (CNAME target):', 'w3-total-cache' ); ?></label></th>
25
  <td class="w3tc_config_value_text">
26
  cds.<?php echo $config->get_string( 'cdn.highwinds.host.hash_code' ) ?>.hwcdn.net
27
  </td>
@@ -34,7 +34,7 @@ $hash_code = $config->get_string( 'cdn.highwinds.host.hash_code' );
34
  <option value="enabled"<?php selected( $config->get_string( 'cdn.highwinds.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
35
  <option value="disabled"<?php selected( $config->get_string( 'cdn.highwinds.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
36
  </select>
37
- <br /><span class="description"><?php _e( 'Some <acronym>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>
38
  </td>
39
  </tr>
40
  <tr>
@@ -44,7 +44,7 @@ $hash_code = $config->get_string( 'cdn.highwinds.host.hash_code' );
44
  <input class="w3tc_cdn_highwinds_configure_cnames_form button" type="button"
45
  value="<?php _e( 'Configure CNAMEs', 'w3-total-cache' ); ?>" />
46
  <br />
47
- <span class="description"><?php _e( 'Hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
48
  </td>
49
  </tr>
50
  <tr>
21
 
22
  <?php if ( !empty( $hash_code ) ): ?>
23
  <tr>
24
+ <th><label><?php _e( '<acronym title="Content Delivery Network">CDN</acronym> host (CNAME target):', 'w3-total-cache' ); ?></label></th>
25
  <td class="w3tc_config_value_text">
26
  cds.<?php echo $config->get_string( 'cdn.highwinds.host.hash_code' ) ?>.hwcdn.net
27
  </td>
34
  <option value="enabled"<?php selected( $config->get_string( 'cdn.highwinds.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
35
  <option value="disabled"<?php selected( $config->get_string( 'cdn.highwinds.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
36
  </select>
37
+ <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>
38
  </td>
39
  </tr>
40
  <tr>
44
  <input class="w3tc_cdn_highwinds_configure_cnames_form button" type="button"
45
  value="<?php _e( 'Configure CNAMEs', 'w3-total-cache' ); ?>" />
46
  <br />
47
+ <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>
48
  </td>
49
  </tr>
50
  <tr>
Cdn_Highwinds_Popup_View_ConfigureCnamesForm.php CHANGED
@@ -13,7 +13,7 @@ if ( !empty( $details['error_message'] ) )
13
  <?php Util_Ui::postbox_header( __( 'CNAMEs to use', 'w3-total-cache' ) ); ?>
14
  <?php $cname_class = 'w3tc-ignore-change'; include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
15
  <br />
16
- <span class="description"><?php _e( 'Enter hostname mapped to <acronym>CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
17
 
18
  <p class="submit">
19
  <input type="button"
13
  <?php Util_Ui::postbox_header( __( 'CNAMEs to use', 'w3-total-cache' ) ); ?>
14
  <?php $cname_class = 'w3tc-ignore-change'; include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
15
  <br />
16
+ <span class="description"><?php _e( 'Enter hostname mapped to <acronym title="Content Delivery Network">CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
17
 
18
  <p class="submit">
19
  <input type="button"
Cdn_MaxCdnFsd_Page.php DELETED
@@ -1,18 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- class Cdn_MaxCdnFsd_Page {
5
- // called from plugin-admin
6
- static public function admin_print_scripts_w3tc_cdn() {
7
- wp_enqueue_script( 'w3tc_cdn_maxcdn_fsd',
8
- plugins_url( 'Cdn_MaxCdnFsd_Page_View.js', W3TC_FILE ),
9
- array( 'jquery' ), '1.0' );
10
- }
11
-
12
-
13
-
14
- static public function w3tc_settings_cdn() {
15
- $config = Dispatcher::config();
16
- include W3TC_DIR . '/Cdn_MaxCdnFsd_Page_View.php';
17
- }
18
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Cdn_MaxCdn_Page.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdn_MaxCdn_Page {
7
+ // called from plugin-admin
8
+ static public function admin_print_scripts_w3tc_cdn() {
9
+ wp_enqueue_script( 'w3tc_cdn_maxcdn',
10
+ plugins_url( 'Cdn_MaxCdn_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.maxcdn.authorization_key' );
19
+ $zone = $config->get_string( 'cdn.maxcdn.zone_id' );
20
+ $domains = $config->get_array( 'cdn.maxcdn.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_MaxCdn_Page_View.php';
27
+ }
28
+ }
Cdn_MaxCdn_Page_View.js ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ function w3tc_maxcdn_resize(o) {
3
+ o.options.height = jQuery('.w3tc_cdn_maxcdn_form').height();
4
+ o.resize();
5
+ }
6
+
7
+ $('body')
8
+ .on('click', '.w3tc_cdn_maxcdn_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_maxcdn_intro',
16
+ callback: w3tc_maxcdn_resize
17
+ });
18
+ })
19
+
20
+
21
+
22
+ .on('click', '.w3tc_cdn_maxcdn_list_zones', function() {
23
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
24
+ '&w3tc_action=cdn_maxcdn_list_zones';
25
+
26
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_maxcdn_form', w3tc_maxcdn_resize);
27
+ })
28
+
29
+
30
+
31
+ .on('click', '.w3tc_cdn_maxcdn_view_zone', function() {
32
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
33
+ '&w3tc_action=cdn_maxcdn_view_zone';
34
+
35
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_maxcdn_form', w3tc_maxcdn_resize);
36
+ })
37
+
38
+
39
+
40
+ .on('click', '.w3tc_cdn_maxcdn_configure_zone', function() {
41
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
42
+ '&w3tc_action=cdn_maxcdn_configure_zone';
43
+
44
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_maxcdn_form', w3tc_maxcdn_resize);
45
+ })
46
+
47
+
48
+
49
+ .on('click', '.w3tc_cdn_maxcdn_configure_zone_skip', function() {
50
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
51
+ '&w3tc_action=cdn_maxcdn_configure_zone_skip';
52
+
53
+ W3tc_Lightbox.load_form(url, '.w3tc_cdn_maxcdn_form', w3tc_maxcdn_resize);
54
+ })
55
+
56
+
57
+
58
+ .on('click', '.w3tc_cdn_maxcdn_done', 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
+ });
Cdn_MaxCdn_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( wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_maxcdn_signup' ), 'w3tc' ) )?>" target="_blank" id="netdna-maxcdn-create-account" class="button-primary"><?php _e( 'Sign Up Now and Save 25%', 'w3-total-cache' ) ?></a>
13
+ <br />
14
+ <span class="description"><?php _e( 'MaxCDN 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_maxcdn_authorize button-primary"
30
+ type="button"
31
+ value="<?php _e( 'Reauthorize', 'w3-total-cache' ); ?>"
32
+ />
33
+ <?php else: ?>
34
+ <input class="w3tc_cdn_maxcdn_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_maxcdn_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support', 'w3-total-cache' )?>:</label></th>
74
+ <td>
75
+ <select id="cdn_maxcdn_ssl" name="cdn__maxcdn__ssl" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?>>
76
+ <option value="auto"<?php selected( $config->get_string( 'cdn.maxcdn.ssl' ), 'auto' ); ?>><?php _e( 'Auto (determine connection type automatically)', 'w3-total-cache' )?></option>
77
+ <option value="enabled"<?php selected( $config->get_string( 'cdn.maxcdn.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' )?></option>
78
+ <option value="disabled"<?php selected( $config->get_string( 'cdn.maxcdn.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.maxcdn.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: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Test MaxCDN', 'w3-total-cache' )?>" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
93
+ </th>
94
+ </tr>
95
+
96
+ <?php endif ?>
Cdn_MaxCdn_Popup.php ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdn_MaxCdn_Popup {
7
+ static public function w3tc_ajax() {
8
+ $o = new Cdn_MaxCdn_Popup();
9
+
10
+ add_action( 'w3tc_ajax_cdn_maxcdn_intro',
11
+ array( $o, 'w3tc_ajax_cdn_maxcdn_intro' ) );
12
+ add_action( 'w3tc_ajax_cdn_maxcdn_list_zones',
13
+ array( $o, 'w3tc_ajax_cdn_maxcdn_list_zones' ) );
14
+ add_action( 'w3tc_ajax_cdn_maxcdn_view_zone',
15
+ array( $o, 'w3tc_ajax_cdn_maxcdn_view_zone' ) );
16
+ add_action( 'w3tc_ajax_cdn_maxcdn_configure_zone',
17
+ array( $o, 'w3tc_ajax_cdn_maxcdn_configure_zone' ) );
18
+ }
19
+
20
+
21
+
22
+ public function __construct() {
23
+ if ( !class_exists( 'NetDNA' ) )
24
+ require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
25
+ }
26
+
27
+
28
+
29
+ public function w3tc_ajax_cdn_maxcdn_intro() {
30
+ $config = Dispatcher::config();
31
+
32
+ $this->render_intro( array(
33
+ 'api_key' => $config->get_string( 'cdn.maxcdn.authorization_key' ) ) );
34
+ }
35
+
36
+
37
+
38
+ private function render_intro( $details ) {
39
+ $config = Dispatcher::config();
40
+ $url_obtain_key = Util_Ui::url( array(
41
+ 'page' => 'w3tc_dashboard',
42
+ 'w3tc_cdn_maxcdn_authorize' => 'y'
43
+ ) );
44
+
45
+ include W3TC_DIR . '/Cdn_MaxCdn_Popup_View_Intro.php';
46
+ exit();
47
+ }
48
+
49
+
50
+
51
+ public function w3tc_ajax_cdn_maxcdn_list_zones() {
52
+ $api_key = $_REQUEST['api_key'];
53
+
54
+ $api = \NetDNA::create( $api_key );
55
+ if ( !$api->is_valid() ) {
56
+ $this->render_intro( array(
57
+ 'api_key' => $api_key,
58
+ 'error_message' => 'Can\'t authenticate: API key not valid'
59
+ ) );
60
+ exit();
61
+ }
62
+
63
+ try {
64
+ $zones = $api->get_pull_zones();
65
+ } catch ( \Exception $ex ) {
66
+ $error_message = 'Can\'t authenticate: ' . $ex->getMessage();
67
+
68
+ if ( strpos( $error_message, 'not whitelisted' ) > 0 ) {
69
+ $error_message .= '. You can whitelist IP ' .
70
+ '<a target="_blank" href="https://cp.maxcdn.com/account/api/whitelist">here</a>';
71
+ }
72
+ $this->render_intro( array(
73
+ 'api_key' => $api_key,
74
+ 'error_message' => $error_message
75
+ ) );
76
+ exit();
77
+ }
78
+
79
+ $details = array(
80
+ 'api_key' => $api_key,
81
+ 'zones' => $zones
82
+ );
83
+
84
+ include W3TC_DIR . '/Cdn_MaxCdn_Popup_View_Zones.php';
85
+ exit();
86
+ }
87
+
88
+
89
+
90
+ public function w3tc_ajax_cdn_maxcdn_view_zone() {
91
+ $config = Dispatcher::config();
92
+ $api_key = $_REQUEST['api_key'];
93
+ $zone_id = Util_Request::get( 'zone_id', '' );
94
+
95
+ $details = array(
96
+ 'api_key' => $api_key,
97
+ 'zone_id' => $zone_id,
98
+ 'name' => '',
99
+ 'url' => array(
100
+ 'new' => get_home_url() ),
101
+ 'compress' => array(
102
+ 'new' => 1 ),
103
+ 'ssl' => array(
104
+ // off, dedicated, sni, shared
105
+ 'current' => null,
106
+ 'new' => null
107
+ ),
108
+ 'cors_headers' => array(
109
+ 'new' => ( $config->get_boolean( 'cdn.cors_header') ? 0 : 1 ) ),
110
+ 'domains' => array()
111
+ );
112
+
113
+ if ( empty( $zone_id ) ) {
114
+ // create new zone mode
115
+ $details['name'] = Util_Request::get( 'zone_new_name' );
116
+ } else {
117
+ $api = \NetDNA::create( $api_key );
118
+ try {
119
+ $zone = $api->get_zone( $zone_id );
120
+ $details['domains']['current'] = $api->get_custom_domains( $zone_id );
121
+ } catch ( \Exception $ex ) {
122
+ $this->render_intro( array(
123
+ 'api_key' => $api_key,
124
+ 'error_message' => 'Can\'t obtain zone: ' . $ex->getMessage()
125
+ ) );
126
+ exit();
127
+ }
128
+
129
+ $details['name'] = $zone['name'];
130
+ $details['compress']['current'] = $zone['compress'];
131
+ $details['cors_headers']['current'] = $zone['cors_headers'];
132
+ if ( $zone['ssl'] ) {
133
+ $details['ssl']['current'] = 'dedicated';
134
+ } elseif ( $zone['ssl_sni'] ) {
135
+ $details['ssl']['current'] = 'sni';
136
+ } elseif ( $zone['sslshared'] ) {
137
+ $details['ssl']['current'] = 'shared';
138
+ } else {
139
+ $details['ssl']['current'] = 'off';
140
+ }
141
+ $details['url']['current'] = $zone['url'];
142
+ }
143
+
144
+
145
+ if ( Util_Environment::is_https() &&
146
+ ( is_null( $details['ssl']['current'] ) ||
147
+ $details['ssl']['current'] == 'off' ) ) {
148
+ $details['ssl']['new'] = 'shared';
149
+ }
150
+
151
+ include W3TC_DIR . '/Cdn_MaxCdn_Popup_View_Zone.php';
152
+ exit();
153
+ }
154
+
155
+
156
+
157
+ public function w3tc_ajax_cdn_maxcdn_configure_zone() {
158
+ $api_key = $_REQUEST['api_key'];
159
+ $zone_id = Util_Request::get( 'zone_id', '' );
160
+
161
+ if ( empty( $zone_id ) ) {
162
+ $zone = array(
163
+ 'name' => Util_Request::get( 'name' ),
164
+ 'label' => Util_Request::get( 'name' ),
165
+ 'url' => Util_Request::get( 'url' ),
166
+ 'use_stale' => 1,
167
+ 'queries' => 1,
168
+ 'compress' => 1,
169
+ 'backend_compress' => 1
170
+ );
171
+ } else {
172
+ $zone = array();
173
+
174
+ if ( isset( $_REQUEST['url_change'] ) ) {
175
+ $zone['url'] = Util_Request::get( 'url' );
176
+ }
177
+ if ( isset( $_REQUEST['compress_change'] ) ) {
178
+ $zone['compress'] = Util_Request::get( 'compress' );
179
+ }
180
+ if ( isset( $_REQUEST['cors_headers_change'] ) ) {
181
+ $zone['cors_headers'] = Util_Request::get( 'cors_headers' );
182
+ }
183
+ if ( Util_Request::get( 'ssl' ) == 'shared' ) {
184
+ $zone['sslshared'] = 1;
185
+ $zone['http2'] = 1;
186
+ }
187
+ }
188
+
189
+ $api = \NetDNA::create( $api_key );
190
+
191
+ try {
192
+ if ( empty( $zone_id ) ) {
193
+ $response = $api->create_pull_zone( $zone );
194
+ $zone_id = $response['id'];
195
+ } else {
196
+ if ( count( array_keys( $zone ) ) > 0 ) {
197
+ $response = $api->update_pull_zone( $zone_id, $zone );
198
+ }
199
+ }
200
+
201
+ $response = $api->get_zone( $zone_id );
202
+ } catch ( \Exception $ex ) {
203
+ $this->render_intro( array(
204
+ 'api_key' => $api_key,
205
+ 'error_message' => 'Failed to configure zone: ' .
206
+ $ex->getMessage()
207
+ ) );
208
+ exit();
209
+ }
210
+
211
+ $c = Dispatcher::config();
212
+ $domains = $c->get( 'cdn.maxcdn.domain' );
213
+ $domains['http_default'] = $response['cdn_url'];
214
+ $domains['https_default'] = $response['ssl_url'];
215
+
216
+ $c->set( 'cdn.maxcdn.authorization_key', $api_key );
217
+ $c->set( 'cdn.maxcdn.zone_id', $zone_id );
218
+ $c->set( 'cdn.maxcdn.domain', $domains );
219
+ $c->save();
220
+
221
+ include W3TC_DIR . '/Cdn_MaxCdn_Popup_View_Success.php';
222
+ exit();
223
+ }
224
+
225
+
226
+
227
+ private function render_zone_textbox_change( $details, $field ) {
228
+ Util_Ui::hidden( '', $field, $details[$field]['new'] );
229
+
230
+ if ( !isset( $details[$field]['current'] ) ) {
231
+ echo 'will be set to <strong>';
232
+ echo htmlspecialchars( $details[$field]['new'] );
233
+ echo '</strong>';
234
+ } elseif ( $details[$field]['current'] == $details[$field]['new'] ) {
235
+ echo '<strong>';
236
+ echo htmlspecialchars( $details[$field]['new'] );
237
+ echo '</strong>';
238
+ } else {
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
+
250
+
251
+ private function render_zone_boolean_change( $details, $field ) {
252
+ Util_Ui::hidden( '', $field, $details[$field]['new'] );
253
+
254
+ if ( !isset( $details[$field]['current'] ) ) {
255
+ echo 'will be set to <strong>';
256
+ $this->render_zone_boolean( $details[$field]['new'] );
257
+ echo '</strong>';
258
+ } elseif ( $details[$field]['current'] == $details[$field]['new'] ) {
259
+ echo '<strong>';
260
+ $this->render_zone_boolean( $details[$field]['new'] );
261
+ echo '</strong>';
262
+ } else {
263
+ echo 'currently set to <strong>';
264
+ $this->render_zone_boolean( $details[$field]['current'] );
265
+ echo '</strong><br />';
266
+ echo '<input type="checkbox" name="' . $field . '_change" value="y"' .
267
+ ' checked="checked" /> ';
268
+ echo 'change to <strong>';
269
+ $this->render_zone_boolean( $details[$field]['new'] );
270
+ echo '</strong><br />';
271
+ }
272
+ }
273
+
274
+
275
+
276
+ private function render_zone_boolean( $v ) {
277
+ if ( $v == 0 )
278
+ echo 'disabled';
279
+ else
280
+ echo 'enabled';
281
+ }
282
+ }
Cdn_MaxCdn_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_maxcdn_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 MaxCDN 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_maxcdn_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_MaxCdn_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_maxcdn_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
+ Pull Zone was successfully configured.<br />
14
+ </div>
15
+
16
+ <p class="submit">
17
+ <input type="button"
18
+ class="w3tc_cdn_maxcdn_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_MaxCdn_Popup_View_Zone.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+ ?>
7
+ <form class="w3tc_cdn_maxcdn_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
+ <tr>
34
+ <th>HTTPS support:</th>
35
+ <td>
36
+ <?php if ( !is_null( $details['ssl']['current'] ) ): ?>
37
+ <strong>
38
+ <?php
39
+ $v = $details['ssl']['current'];
40
+ if ( $v == 'dedicated' )
41
+ echo 'Dedicated';
42
+ elseif ( $v == 'sni' )
43
+ echo 'SNI';
44
+ elseif ( $v == 'shared' )
45
+ echo 'Shared';
46
+ else
47
+ echo 'Not active';
48
+ ?>
49
+ </strong><br />
50
+ <?php endif ?>
51
+ <?php if ( !is_null( $details['ssl']['new'] ) ): ?>
52
+ <?php Util_Ui::hidden( '', 'ssl', $details['ssl']['new'] ); ?>
53
+ <label>
54
+ <input type="radio" name="ssl" value="" checked="" /> Leave as is
55
+ </label>
56
+ <br />
57
+ <label>
58
+ <input type="radio" name="ssl" value="shared" checked="checked" />
59
+ Enable Shared HTTPS
60
+ </label>
61
+ <br />
62
+ <?php endif ?>
63
+ </td>
64
+ </tr>
65
+ </table>
66
+
67
+ <p class="submit">
68
+ <input type="button"
69
+ class="w3tc_cdn_maxcdn_configure_zone w3tc-button-save button-primary"
70
+ value="<?php _e( 'Apply', 'w3-total-cache' ); ?>" />
71
+ </p>
72
+ <?php Util_Ui::postbox_footer(); ?>
73
+ </div>
74
+ </form>
Cdn_MaxCdn_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_maxcdn_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_maxcdn_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_Page.php CHANGED
@@ -20,11 +20,6 @@ class Cdn_Page extends Base_Page_Settings {
20
  $config = Dispatcher::config();
21
  $cdn_engine = $config->get_string( 'cdn.engine' );
22
 
23
- if ( Cdn_Util::is_engine_fsd( $cdn_engine ) ) {
24
- do_action( 'w3tc_settings_cdn' );
25
- return;
26
- }
27
-
28
  $cdn_enabled = $config->get_boolean( 'cdn.enabled' );
29
  $cdn_mirror = Cdn_Util::is_engine_mirror( $cdn_engine );
30
  $cdn_mirror_purge_all = Cdn_Util::can_purge_all( $cdn_engine );
@@ -45,33 +40,6 @@ class Cdn_Page extends Base_Page_Settings {
45
  // Required for Update Media Query String button
46
  $browsercache_enabled = $config->get_boolean( 'browsercache.enabled' );
47
  $browsercache_update_media_qs = ( $config->get_boolean( 'browsercache.cssjs.replace' ) || $config->get_boolean( 'browsercache.other.replace' ) );
48
- if ( in_array( $cdn_engine, array( 'netdna', 'maxcdn' ) ) ) {
49
- $pull_zones = array();
50
- $authorization_key = $config->get_string( "cdn.$cdn_engine.authorization_key" );
51
- $zone_id = $config->get_integer( "cdn.$cdn_engine.zone_id" );
52
- $alias = $consumerkey = $consumersecret = '';
53
-
54
- if ( $authorization_key ) {
55
- $keys = explode( '+', $authorization_key );
56
- if ( sizeof( $keys ) == 3 ) {
57
- list( $alias, $consumerkey, $consumersecret ) = $keys;
58
- }
59
- }
60
-
61
- $authorized = $authorization_key != '' && $alias && $consumerkey && $consumersecret;
62
- $have_zone = $zone_id != 0;
63
- if ( $authorized ) {
64
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
65
- try {
66
- $api = new \NetDNA( $alias, $consumerkey, $consumersecret );
67
- $pull_zones = $api->get_zones_by_url( get_home_url() );
68
- } catch ( \Exception $ex ) {
69
-
70
-
71
- Util_Ui::error_box( '<p>There is an error with your CDN settings: ' . $ex->getMessage() . '</p>' );
72
- }
73
- }
74
- }
75
  include W3TC_INC_DIR . '/options/cdn.php';
76
  }
77
 
20
  $config = Dispatcher::config();
21
  $cdn_engine = $config->get_string( 'cdn.engine' );
22
 
 
 
 
 
 
23
  $cdn_enabled = $config->get_boolean( 'cdn.enabled' );
24
  $cdn_mirror = Cdn_Util::is_engine_mirror( $cdn_engine );
25
  $cdn_mirror_purge_all = Cdn_Util::can_purge_all( $cdn_engine );
40
  // Required for Update Media Query String button
41
  $browsercache_enabled = $config->get_boolean( 'browsercache.enabled' );
42
  $browsercache_update_media_qs = ( $config->get_boolean( 'browsercache.cssjs.replace' ) || $config->get_boolean( 'browsercache.other.replace' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  include W3TC_INC_DIR . '/options/cdn.php';
44
  }
45
 
Cdn_Page_View_Fsd_HeaderActions.php CHANGED
@@ -8,7 +8,7 @@ if ( !defined( 'W3TC' ) )
8
  <p>
9
  <?php
10
  echo Util_Ui::button_link(
11
- __( 'Purge CDN completely', 'w3-total-cache' ),
12
  Util_Ui::url( array( 'w3tc_cdn_flush' => 'y' ) ) );
13
  ?>
14
  </p>
8
  <p>
9
  <?php
10
  echo Util_Ui::button_link(
11
+ __( 'Purge <acronym title="Content Delivery Network">CDN</acronym> completely', 'w3-total-cache' ),
12
  Util_Ui::url( array( 'w3tc_cdn_flush' => 'y' ) ) );
13
  ?>
14
  </p>
Cdn_Plugin.php CHANGED
@@ -29,21 +29,16 @@ class Cdn_Plugin {
29
  */
30
  function run() {
31
  $cdn_engine = $this->_config->get_string( 'cdn.engine' );
32
- if ( Cdn_Util::is_engine_fsd( $cdn_engine ) ) {
33
- $this->run_fsd();
34
- return;
35
- }
36
 
37
  add_filter( 'cron_schedules', array(
38
  $this,
39
  'cron_schedules'
40
  ) );
41
 
42
- if ( !$this->_config->get_boolean( 'cdn.debug' ) )
43
- add_filter( 'w3tc_footer_comment', array(
44
- $this,
45
- 'w3tc_footer_comment'
46
- ) );
47
 
48
  if ( !Cdn_Util::is_engine_mirror( $cdn_engine ) ) {
49
  add_action( 'delete_attachment', array(
@@ -80,6 +75,11 @@ class Cdn_Plugin {
80
  $this,
81
  'update_feedback'
82
  ) );
 
 
 
 
 
83
  }
84
 
85
  add_filter( 'w3tc_admin_bar_menu',
@@ -111,24 +111,24 @@ class Cdn_Plugin {
111
  */
112
  private function run_fsd() {
113
  add_action( 'w3tc_flush_all', array(
114
- '\W3TC\Cdn_Fsd_CacheFlush',
115
  'w3tc_flush_all'
116
  ), 3000, 1 );
117
  add_action( 'w3tc_flush_post', array(
118
- '\W3TC\Cdn_Fsd_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\Cdn_Fsd_CacheFlush',
124
  'w3tc_flush_all'
125
  ), 3000 );
126
  add_action( 'w3tc_flush_url', array(
127
- '\W3TC\Cdn_Fsd_CacheFlush',
128
  'w3tc_flush_url'
129
  ), 3000, 1 );
130
  add_filter( 'w3tc_flush_execute_delayed_operations', array(
131
- '\W3TC\Cdn_Fsd_CacheFlush',
132
  'w3tc_flush_execute_delayed_operations'
133
  ), 3000 );
134
 
@@ -685,6 +685,54 @@ class Cdn_Plugin {
685
  $admin->change_canonical_header();
686
  }
687
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
688
  public function w3tc_admin_bar_menu( $menu_items ) {
689
  $cdn_engine = $this->_config->get_string( 'cdn.engine' );
690
 
@@ -724,14 +772,8 @@ class Cdn_Plugin {
724
  sprintf( ' (%s)', $this->cdn_reject_reason ) ) );
725
 
726
  if ( $this->_config->get_boolean( 'cdn.debug' ) ) {
727
- $strings[] = "CDN debug info:";
728
- $strings[] = sprintf( "%s%s", str_pad( 'Engine: ', 20 ),
729
- $this->_config->get_string( 'cdn.engine' ) );
730
-
731
- if ( $this->cdn_reject_reason ) {
732
- $strings[] = sprintf( "%s%s", str_pad( 'Reject reason: ', 20 ),
733
- $this->cdn_reject_reason );
734
- }
735
 
736
  if ( count( $this->_replaced_urls ) ) {
737
  $strings[] = "Replaced URLs:";
@@ -742,6 +784,7 @@ class Cdn_Plugin {
742
  Util_Content::escape_comment( $new_url ) );
743
  }
744
  }
 
745
  }
746
 
747
  return $strings;
@@ -1130,15 +1173,8 @@ class _Cdn_Plugin_ContentFilter {
1130
  */
1131
  function _link_replace_callback_ask_cdn( $match, $quote, $url, $path ) {
1132
  $common = Dispatcher::component( 'Cdn_Core' );
1133
- $cdn = $common->get_cdn();
1134
- $remote_path = $common->uri_to_cdn_uri( $path );
1135
- $new_url = $cdn->format_url( $remote_path );
1136
- if ( $new_url ) {
1137
- $is_engine_mirror = Cdn_Util::is_engine_mirror(
1138
- $this->_config->get_string( 'cdn.engine' ) );
1139
-
1140
- $new_url = apply_filters( 'w3tc_cdn_url', $new_url, $url,
1141
- $is_engine_mirror );
1142
  $this->replaced_urls[$url] = $new_url;
1143
  return $quote . $new_url;
1144
  }
29
  */
30
  function run() {
31
  $cdn_engine = $this->_config->get_string( 'cdn.engine' );
 
 
 
 
32
 
33
  add_filter( 'cron_schedules', array(
34
  $this,
35
  'cron_schedules'
36
  ) );
37
 
38
+ add_filter( 'w3tc_footer_comment', array(
39
+ $this,
40
+ 'w3tc_footer_comment'
41
+ ) );
 
42
 
43
  if ( !Cdn_Util::is_engine_mirror( $cdn_engine ) ) {
44
  add_action( 'delete_attachment', array(
75
  $this,
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',
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
 
685
  $admin->change_canonical_header();
686
  }
687
 
688
+ /**
689
+ * Adjusts attachment urls to cdn. This is for those who rely on
690
+ * wp_prepare_attachment_for_js()
691
+ *
692
+ * @param array $response Mixed collection of data about the attachment object
693
+ * @return array
694
+ */
695
+ public function wp_prepare_attachment_for_js( $response ) {
696
+ $response['url'] = $this->wp_prepare_attachment_for_js_url( $response['url'] );
697
+ $response['link'] = $this->wp_prepare_attachment_for_js_url( $response['link'] );
698
+
699
+ if ( !empty( $response['sizes'] ) ) {
700
+ foreach( $response['sizes'] as $size => &$data ) {
701
+ $data['url'] = $this->wp_prepare_attachment_for_js_url( $data['url'] );
702
+ }
703
+ }
704
+
705
+ return $response;
706
+ }
707
+
708
+ /**
709
+ * An attachment's local url to modify into a cdn url
710
+ *
711
+ * @param string $url the local url to modify
712
+ * @return string
713
+ */
714
+ private function wp_prepare_attachment_for_js_url( $url ) {
715
+ $url = trim( $url );
716
+ if ( !empty( $url ) ) {
717
+ $parsed = parse_url( $url );
718
+ $uri = ( isset( $parsed['path'] ) ? $parsed['path'] : '/' ) .
719
+ ( isset( $parsed['query'] ) ? '?' . $parsed['query'] : '' );
720
+
721
+ $wp_upload_dir = wp_upload_dir();
722
+ $upload_base_url = $wp_upload_dir['baseurl'];
723
+
724
+ if ( substr($url, 0, strlen( $upload_base_url ) ) == $upload_base_url ) {
725
+ $common = Dispatcher::component( 'Cdn_Core' );
726
+ $new_url = $common->url_to_cdn_url( $url, $uri );
727
+ if ( !is_null( $new_url ) ) {
728
+ $url = $new_url;
729
+ }
730
+ }
731
+ }
732
+
733
+ return $url;
734
+ }
735
+
736
  public function w3tc_admin_bar_menu( $menu_items ) {
737
  $cdn_engine = $this->_config->get_string( 'cdn.engine' );
738
 
772
  sprintf( ' (%s)', $this->cdn_reject_reason ) ) );
773
 
774
  if ( $this->_config->get_boolean( 'cdn.debug' ) ) {
775
+ $strings[] = '';
776
+ $strings[] = 'CDN debug info:';
 
 
 
 
 
 
777
 
778
  if ( count( $this->_replaced_urls ) ) {
779
  $strings[] = "Replaced URLs:";
784
  Util_Content::escape_comment( $new_url ) );
785
  }
786
  }
787
+ $strings[] = '';
788
  }
789
 
790
  return $strings;
1173
  */
1174
  function _link_replace_callback_ask_cdn( $match, $quote, $url, $path ) {
1175
  $common = Dispatcher::component( 'Cdn_Core' );
1176
+ $new_url = $common->url_to_cdn_url( $url, $path );
1177
+ if ( !is_null( $new_url ) ) {
 
 
 
 
 
 
 
1178
  $this->replaced_urls[$url] = $new_url;
1179
  return $quote . $new_url;
1180
  }
Cdn_Plugin_Admin.php CHANGED
@@ -9,26 +9,25 @@ class Cdn_Plugin_Admin {
9
  $c = Dispatcher::config();
10
  $cdn_engine = $c->get_string( 'cdn.engine' );
11
 
12
- if ( $c->get_boolean( 'cdn.enabled' ) &&
13
- !Cdn_Util::is_engine_fsd( $cdn_engine ) ) {
14
  $admin_notes = new Cdn_AdminNotes();
15
  add_filter( 'w3tc_notes', array( $admin_notes, 'w3tc_notes' ) );
16
  add_filter( 'w3tc_errors', array( $admin_notes, 'w3tc_errors' ) );
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
 
20
  // attach to actions without firing class loading at all without need
21
- if ( $cdn_engine == 'cloudfront_fsd' ) {
22
- add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
23
- '\W3TC\Cdn_CloudFrontFsd_Page',
24
- 'admin_print_scripts_w3tc_cdn' ) );
25
- add_action( 'w3tc_ajax', array(
26
- '\W3TC\Cdn_CloudFrontFsd_Popup',
27
- 'w3tc_ajax' ) );
28
- add_action( 'w3tc_settings_cdn', array(
29
- '\W3TC\Cdn_CloudFrontFsd_Page',
30
- 'w3tc_settings_cdn' ) );
31
- } elseif ( $cdn_engine == 'google_drive' ) {
32
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
33
  '\W3TC\Cdn_GoogleDrive_Page',
34
  'admin_print_scripts_w3tc_cdn' ) );
@@ -52,16 +51,17 @@ class Cdn_Plugin_Admin {
52
  add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
53
  '\W3TC\Cdn_Highwinds_Page',
54
  'w3tc_settings_cdn_boxarea_configuration' ) );
55
- } elseif ( $cdn_engine == 'maxcdn_fsd' ) {
56
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
57
- '\W3TC\Cdn_MaxCdnFsd_Page',
58
  'admin_print_scripts_w3tc_cdn' ) );
59
  add_action( 'w3tc_ajax', array(
60
- '\W3TC\Cdn_MaxCdnFsd_Popup',
61
  'w3tc_ajax' ) );
62
- add_action( 'w3tc_settings_cdn', array(
63
- '\W3TC\Cdn_MaxCdnFsd_Page',
64
- 'w3tc_settings_cdn' ) );
 
65
  } elseif ( $cdn_engine == 'rackspace_cdn' ) {
66
  add_filter( 'w3tc_admin_actions', array(
67
  '\W3TC\Cdn_RackSpaceCdn_Page',
@@ -101,25 +101,8 @@ class Cdn_Plugin_Admin {
101
  $engine_optgroups = array();
102
  $engine_values = array();
103
 
104
- $is_fsd = Util_Environment::is_w3tc_pro( $config );
105
-
106
- if ( $is_fsd ) {
107
- $engine_optgroups[] = __( 'Full Site Delivery:', 'w3-total-cache' );
108
- $engine_values['cloudfront_fsd'] = array(
109
- 'label' => __( 'Amazon CloudFront', 'w3-total-cache' ),
110
- 'optgroup' => 0
111
- );
112
- $engine_values['maxcdn_fsd'] = array(
113
- 'label' => __( 'MaxCDN (recommended)', 'w3-total-cache' ),
114
- 'optgroup' => 0
115
- );
116
-
117
- $optgroup_pull = count( $engine_optgroups );
118
- $engine_optgroups[] = __( 'Origin Pull / Mirror:', 'w3-total-cache' );
119
- } else {
120
- $optgroup_pull = count( $engine_optgroups );
121
- $engine_optgroups[] = __( 'Origin Pull / Mirror:', 'w3-total-cache' );
122
- }
123
 
124
  $optgroup_push = count( $engine_optgroups );
125
  $engine_optgroups[] = __( 'Origin Push:', 'w3-total-cache' );
@@ -154,10 +137,6 @@ class Cdn_Plugin_Admin {
154
  'label' => __( 'MaxCDN', 'w3-total-cache' ),
155
  'optgroup' => $optgroup_pull
156
  );
157
- $engine_values['netdna'] = array(
158
- 'label' => __( 'MaxCDN Enterprise (NetDNA)', 'w3-total-cache' ),
159
- 'optgroup' => $optgroup_pull
160
- );
161
  $engine_values['rackspace_cdn'] = array(
162
  'label' => __( 'RackSpace CDN', 'w3-total-cache' ),
163
  'optgroup' => $optgroup_pull
@@ -201,22 +180,42 @@ class Cdn_Plugin_Admin {
201
  );
202
 
203
  $cdn_enabled = $config->get_boolean( 'cdn.enabled' );
204
-
205
  $cdn_engine = $config->get_string( 'cdn.engine' );
206
 
207
- $tag = '';
208
- if ( $cdn_engine == 'cloudfront_fsd' )
209
- $tag = '#cdn-fsd-cloudfront';
210
- elseif ( $cdn_engine == 'maxcdn_fsd' )
211
- $tag = '#cdn-fsd-maxcdn';
212
-
213
- if ( empty( $tag ) )
214
- $cdn_engine_extra_description = '';
215
- else
216
- $cdn_engine_extra_description =
217
- ' See <a href="admin.php?page=w3tc_faq' . $tag .
218
- '">setup instructions</a>';
219
-
220
  include W3TC_DIR . '/Cdn_GeneralPage_View.php';
221
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  }
9
  $c = Dispatcher::config();
10
  $cdn_engine = $c->get_string( 'cdn.engine' );
11
 
12
+ if ( $c->get_boolean( 'cdn.enabled' ) ) {
 
13
  $admin_notes = new Cdn_AdminNotes();
14
  add_filter( 'w3tc_notes', array( $admin_notes, 'w3tc_notes' ) );
15
  add_filter( 'w3tc_errors', array( $admin_notes, 'w3tc_errors' ) );
16
+
17
+ if ( $c->get_boolean( 'cdn.admin.media_library' ) &&
18
+ $c->get_boolean( 'cdn.uploads.enable' ) ) {
19
+
20
+ add_filter( 'wp_get_attachment_url',
21
+ array( $this, 'wp_get_attachment_url' ), 0 );
22
+
23
+ add_filter( 'attachment_link',
24
+ array( $this, 'wp_get_attachment_url' ), 0 );
25
+ }
26
  }
27
 
28
 
29
  // attach to actions without firing class loading at all without need
30
+ if ( $cdn_engine == 'google_drive' ) {
 
 
 
 
 
 
 
 
 
 
31
  add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
32
  '\W3TC\Cdn_GoogleDrive_Page',
33
  'admin_print_scripts_w3tc_cdn' ) );
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',
57
  'admin_print_scripts_w3tc_cdn' ) );
58
  add_action( 'w3tc_ajax', array(
59
+ '\W3TC\Cdn_MaxCdn_Popup',
60
  'w3tc_ajax' ) );
61
+ add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
62
+ '\W3TC\Cdn_MaxCdn_Page',
63
+ 'w3tc_settings_cdn_boxarea_configuration'
64
+ ) );
65
  } elseif ( $cdn_engine == 'rackspace_cdn' ) {
66
  add_filter( 'w3tc_admin_actions', array(
67
  '\W3TC\Cdn_RackSpaceCdn_Page',
101
  $engine_optgroups = array();
102
  $engine_values = array();
103
 
104
+ $optgroup_pull = count( $engine_optgroups );
105
+ $engine_optgroups[] = __( 'Origin Pull / Mirror:', 'w3-total-cache' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
  $optgroup_push = count( $engine_optgroups );
108
  $engine_optgroups[] = __( 'Origin Push:', 'w3-total-cache' );
137
  'label' => __( 'MaxCDN', 'w3-total-cache' ),
138
  'optgroup' => $optgroup_pull
139
  );
 
 
 
 
140
  $engine_values['rackspace_cdn'] = array(
141
  'label' => __( 'RackSpace CDN', 'w3-total-cache' ),
142
  'optgroup' => $optgroup_pull
180
  );
181
 
182
  $cdn_enabled = $config->get_boolean( 'cdn.enabled' );
 
183
  $cdn_engine = $config->get_string( 'cdn.engine' );
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  include W3TC_DIR . '/Cdn_GeneralPage_View.php';
186
  }
187
+
188
+
189
+
190
+ /**
191
+ * Adjusts attachment urls to cdn. This is for those who rely on
192
+ * wp_get_attachment_url()
193
+ *
194
+ * @param string $url the local url to modify
195
+ * @return string
196
+ */
197
+ function wp_get_attachment_url( $url ) {
198
+ if ( defined( 'WP_ADMIN' ) ) {
199
+ $url = trim( $url );
200
+
201
+ if ( !empty( $url ) ) {
202
+ $parsed = parse_url( $url );
203
+ $uri = ( isset( $parsed['path'] ) ? $parsed['path'] : '/' ) .
204
+ ( isset( $parsed['query'] ) ? '?' . $parsed['query'] : '' );
205
+
206
+ $wp_upload_dir = wp_upload_dir();
207
+ $upload_base_url = $wp_upload_dir['baseurl'];
208
+
209
+ if ( substr($url, 0, strlen( $upload_base_url ) ) == $upload_base_url ) {
210
+ $common = Dispatcher::component( 'Cdn_Core' );
211
+ $new_url = $common->url_to_cdn_url( $url, $uri );
212
+ if ( !is_null( $new_url ) ) {
213
+ $url = $new_url;
214
+ }
215
+ }
216
+ }
217
+ }
218
+
219
+ return $url;
220
+ }
221
  }
Cdn_Plugin_WidgetMaxCdn.php CHANGED
@@ -9,16 +9,7 @@ class Cdn_Plugin_WidgetMaxCdn {
9
  private $have_zone;
10
  private $_sealed;
11
 
12
- /**
13
- *
14
- *
15
- * @var NetDNA
16
- */
17
  private $api;
18
-
19
- /**
20
- * Config
21
- */
22
  private $_config = null;
23
 
24
  function __construct() {
9
  private $have_zone;
10
  private $_sealed;
11
 
 
 
 
 
 
12
  private $api;
 
 
 
 
13
  private $_config = null;
14
 
15
  function __construct() {
Cdn_Plugin_WidgetNetDna.php DELETED
@@ -1,191 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
- /**
4
- * W3 NetDNA Widget
5
- */
6
-
7
-
8
-
9
- /**
10
- * Class Cdn_Plugin_WidgetNetDna
11
- */
12
- class Cdn_Plugin_WidgetNetDna {
13
- private $authorized;
14
- private $have_zone;
15
- private $_sealed;
16
-
17
- /**
18
- *
19
- *
20
- * @var NetDNA
21
- */
22
- private $api;
23
-
24
- /**
25
- * Config
26
- */
27
- private $_config = null;
28
-
29
- function __construct() {
30
- $this->_config = Dispatcher::config();
31
- }
32
-
33
- /**
34
- * Runs plugin
35
- */
36
- function run() {
37
- if ( Util_Admin::get_current_wp_page() == 'w3tc_dashboard' )
38
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
39
- add_action( 'w3tc_widget_setup', array(
40
- $this,
41
- 'wp_dashboard_setup'
42
- ) );
43
- add_action( 'w3tc_network_dashboard_setup', array(
44
- $this,
45
- 'wp_dashboard_setup'
46
- ) );
47
-
48
- // Configure authorize and have_zone
49
- $this->_setup( $this->_config );
50
-
51
- if ( $this->have_zone && $this->authorized && isset( $_GET['page'] ) && strpos( $_GET['page'], 'w3tc_dashboard' ) !== false ) {
52
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
53
- require_once W3TC_LIB_NETDNA_DIR . '/NetDNAPresentation.php';
54
- $authorization_key = $this->_config->get_string( 'cdn.netdna.authorization_key' );
55
- $alias = $consumerkey = $consumersecret = '';
56
-
57
- $keys = explode( '+', $authorization_key );
58
- if ( sizeof( $keys ) == 3 )
59
- list( $alias, $consumerkey, $consumersecret ) = $keys;
60
-
61
- $this->api = new \NetDNA( $alias, $consumerkey, $consumersecret );
62
- add_action( 'admin_head', array( $this, 'admin_head' ) );
63
- }
64
- }
65
-
66
- function admin_head() {
67
- $zone_id = $this->_config->get_string( 'cdn.netdna.zone_id' );
68
- try {
69
- $zone_info = $this->api->get_pull_zone( $zone_id );
70
-
71
- if ( !$zone_info )
72
- return;
73
- $filetypes = $this->api->get_list_of_file_types_per_zone( $zone_id );
74
-
75
- if ( !isset( $filetypes['filetypes'] ) )
76
- return;
77
- } catch ( \Exception $ex ) {
78
- return;
79
- }
80
-
81
- $filetypes = $filetypes['filetypes'];
82
- $group_hits = \NetDNAPresentation::group_hits_per_filetype_group( $filetypes );
83
-
84
- $list = array();
85
- $colors = array();
86
- foreach ( $group_hits as $group => $hits ) {
87
- $list[] = sprintf( "['%s', %d]", $group, $hits );
88
- $colors[] = '\'' . \NetDNAPresentation::get_file_group_color( $group ) . '\'';
89
- }
90
- ?>
91
- <script type="text/javascript" src="https://www.google.com/jsapi"></script>
92
- <script type="text/javascript">
93
- google.load("visualization", "1", {packages:["corechart"]});
94
- google.setOnLoadCallback(drawChart);
95
- function drawChart() {
96
- var data = google.visualization.arrayToDataTable([
97
- ['Filetype', 'Hits'],<?php
98
- echo " ", implode( ',', $list );
99
- ?>
100
- ]);
101
- var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
102
- var options = {colors: [<?php echo implode( ',', $colors ) ?>]};
103
- chart.draw(data, options);
104
- }
105
- </script>
106
- <?php
107
- }
108
-
109
- /**
110
- * Dashboard setup action
111
- *
112
- * @return void
113
- */
114
- function wp_dashboard_setup() {
115
- Util_Widget::add( 'w3tc_netdna',
116
- '<div class="w3tc-widget-netdna-logo"></div>',
117
- array( $this, 'widget_netdna' ),
118
- Util_Ui::admin_url( 'admin.php?page=w3tc_cdn' ),
119
- 'normal' );
120
- }
121
-
122
- /**
123
- * Loads and configures NetDNA widget to be used in WP Dashboards.
124
- *
125
- * @param unknown $widget_id
126
- * @param array $form_inputs
127
- */
128
- function widget_netdna( $widget_id, $form_inputs = array() ) {
129
- $authorized = $this->authorized;
130
- $have_zone = $this->have_zone;
131
- $is_sealed = $this->_sealed;
132
- $error = '';
133
- $pull_zones = array();
134
- $zone_info = false;
135
- if ( $authorized && $have_zone ) {
136
- $zone_id = $this->_config->get_integer( 'cdn.netdna.zone_id' );
137
- try{
138
- $zone_info = $this->api->get_pull_zone( $zone_id );
139
- } catch ( \Exception $ex ) {
140
- $error = $ex->getMessage();
141
- $zone_info = false;
142
- }
143
- if ( $zone_info ) {
144
- $content_zone = $zone_info['name'];
145
- try{
146
- $summary = $this->api->get_stats_per_zone( $zone_id );
147
- $filetypes = $this->api->get_list_of_file_types_per_zone( $zone_id );
148
- $popular_files = $this->api->get_list_of_popularfiles_per_zone( $zone_id );
149
- $popular_files = \NetDNAPresentation::format_popular( $popular_files );
150
- $popular_files = array_slice( $popular_files, 0 , 5 );
151
- $account = $this->api->get_account();
152
- $account_status = \NetDNAPresentation::get_account_status( $account['status'] );
153
- include W3TC_INC_WIDGET_DIR . '/netdna.php';
154
- } catch ( \Exception $ex ) {
155
- try {
156
- $pull_zones = $this->api->get_zones_by_url( home_url() );
157
- } catch ( \Exception $ex ) {}
158
- $error = $ex->getMessage();
159
- include W3TC_INC_WIDGET_DIR . '/netdna_signup.php';
160
- }
161
- } else {
162
- try {
163
- $pull_zones = $this->api->get_zones_by_url( home_url() );
164
- } catch ( \Exception $ex ) {}
165
- include W3TC_INC_WIDGET_DIR . '/netdna_signup.php';
166
- }
167
- } else {
168
- include W3TC_INC_WIDGET_DIR . '/netdna_signup.php';
169
- }
170
- }
171
-
172
- /**
173
- *
174
- *
175
- * @param Config $config
176
- */
177
- private function _setup( $config ) {
178
- $this->authorized = $config->get_string( 'cdn.netdna.authorization_key' ) != '' &&
179
- $config->get_string( 'cdn.engine' ) == 'netdna';
180
- $keys = explode( '+', $config->get_string( 'cdn.netdna.authorization_key' ) );
181
- $this->authorized = $this->authorized && sizeof( $keys ) == 3;
182
-
183
- $this->have_zone = $config->get_string( 'cdn.netdna.zone_id' ) != 0;
184
- }
185
-
186
- public function enqueue() {
187
- wp_enqueue_style( 'w3tc-widget' );
188
- wp_enqueue_script( 'w3tc-metadata' );
189
- wp_enqueue_script( 'w3tc-widget' );
190
- }
191
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Cdn_RackSpaceCdn_Page_View.js CHANGED
@@ -97,7 +97,7 @@ jQuery(function($) {
97
  var protocol = '';
98
 
99
  $('body').find('.w3tc_cdn_rackspace_protocol').each(function(i) {
100
- if (!jQuery(this).attr('checked'))
101
  return;
102
 
103
  protocol = $(this).val();
97
  var protocol = '';
98
 
99
  $('body').find('.w3tc_cdn_rackspace_protocol').each(function(i) {
100
+ if (!jQuery(this).prop('checked'))
101
  return;
102
 
103
  protocol = $(this).val();
Cdn_RackSpaceCdn_Page_View.php CHANGED
@@ -38,7 +38,7 @@ if ( !defined( 'W3TC' ) )
38
  </td>
39
  </tr>
40
  <tr>
41
- <th><label><?php _e( 'CDN host (CNAME target):', 'w3-total-cache' ); ?></label></th>
42
  <td class="w3tc_config_value_text">
43
  <?php echo $access_url_full ?>
44
  </td>
@@ -52,7 +52,7 @@ if ( !defined( 'W3TC' ) )
52
  value="<?php _e( 'Configure CNAMEs', 'w3-total-cache' ); ?>" />
53
  <br />
54
  <span class="description">
55
- <?php _e( 'Enter hostname mapped to <acronym>CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?>
56
  </span>
57
  </td>
58
  </tr>
@@ -66,7 +66,7 @@ if ( !defined( 'W3TC' ) )
66
  value="<?php _e( 'Reload CNAMEs from RackSpace', 'w3-total-cache' ); ?>" />
67
  <br />
68
  <span class="description">
69
- <?php _e( 'Hostname(s) mapped to <acronym>CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>. You can manage them from RackSpace management console and load here afterwards.', 'w3-total-cache' ); ?>
70
  </span>
71
  </td>
72
  </tr>
38
  </td>
39
  </tr>
40
  <tr>
41
+ <th><label><?php _e( '<acronym title="Content Delivery Network">CDN</acronym> host (CNAME target):', 'w3-total-cache' ); ?></label></th>
42
  <td class="w3tc_config_value_text">
43
  <?php echo $access_url_full ?>
44
  </td>
52
  value="<?php _e( 'Configure CNAMEs', 'w3-total-cache' ); ?>" />
53
  <br />
54
  <span class="description">
55
+ <?php _e( 'Enter hostname mapped to <acronym title="Content Delivery Network">CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?>
56
  </span>
57
  </td>
58
  </tr>
66
  value="<?php _e( 'Reload CNAMEs from RackSpace', 'w3-total-cache' ); ?>" />
67
  <br />
68
  <span class="description">
69
+ <?php _e( 'Hostname(s) mapped to <acronym title="Content Delivery Network">CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>. You can manage them from RackSpace management console and load here afterwards.', 'w3-total-cache' ); ?>
70
  </span>
71
  </td>
72
  </tr>
Cdn_RackSpaceCdn_Popup_View_ConfigureDomains.php CHANGED
@@ -13,7 +13,7 @@ if ( !empty( $details['error_message'] ) )
13
  <?php Util_Ui::postbox_header( __( 'CNAMEs to use', 'w3-total-cache' ) ); ?>
14
  <?php $cname_class = 'w3tc-ignore-change'; include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
15
  <br />
16
- <span class="description"><?php _e( 'Enter hostname mapped to <acronym>CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
17
 
18
  <p class="submit">
19
  <input type="button"
13
  <?php Util_Ui::postbox_header( __( 'CNAMEs to use', 'w3-total-cache' ) ); ?>
14
  <?php $cname_class = 'w3tc-ignore-change'; include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
15
  <br />
16
+ <span class="description"><?php _e( 'Enter hostname mapped to <acronym title="Content Delivery Network">CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
17
 
18
  <p class="submit">
19
  <input type="button"
Cdn_RackSpaceCloudFiles_Page_View.php CHANGED
@@ -38,7 +38,7 @@ if ( !defined( 'W3TC' ) )
38
  </td>
39
  </tr>
40
  <tr>
41
- <th><label><?php _e( 'CDN host (CNAME target):', 'w3-total-cache' ); ?></label></th>
42
  <td class="w3tc_config_value_text">
43
  http: <?php echo $cdn_host_http ?><br />
44
  https: <?php echo $cdn_host_https ?>
@@ -52,7 +52,7 @@ if ( !defined( 'W3TC' ) )
52
  <option value="enabled"<?php selected( $config->get_string( 'cdn.rscf.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
53
  <option value="disabled"<?php selected( $config->get_string( 'cdn.rscf.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
54
  </select>
55
- <br /><span class="description"><?php _e( 'Some <acronym>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>
56
  </td>
57
  </tr>
58
  <tr>
@@ -61,7 +61,7 @@ if ( !defined( 'W3TC' ) )
61
  <?php $cnames = $config->get_array( 'cdn.rscf.cname' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
62
  <br />
63
  <span class="description">
64
- <?php _e( 'Enter hostname mapped to <acronym>CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?>
65
  </span>
66
  </td>
67
  </tr>
38
  </td>
39
  </tr>
40
  <tr>
41
+ <th><label><?php _e( '<acronym title="Content Delivery Network">CDN</acronym> host (CNAME target):', 'w3-total-cache' ); ?></label></th>
42
  <td class="w3tc_config_value_text">
43
  http: <?php echo $cdn_host_http ?><br />
44
  https: <?php echo $cdn_host_https ?>
52
  <option value="enabled"<?php selected( $config->get_string( 'cdn.rscf.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
53
  <option value="disabled"<?php selected( $config->get_string( 'cdn.rscf.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
54
  </select>
55
+ <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>
56
  </td>
57
  </tr>
58
  <tr>
61
  <?php $cnames = $config->get_array( 'cdn.rscf.cname' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
62
  <br />
63
  <span class="description">
64
+ <?php _e( 'Enter hostname mapped to <acronym title="Content Delivery Network">CDN</acronym> host, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?>
65
  </span>
66
  </td>
67
  </tr>
Cdn_Util.php CHANGED
@@ -14,17 +14,14 @@ class Cdn_Util {
14
  'att',
15
  'azure',
16
  'cf',
17
- 'cloudfront_fsd',
18
  'cf2',
19
  'cotendo',
20
  'edgecast',
21
- 'maxcdn_fsd',
22
  'ftp',
23
  'google_drive',
24
  'highwinds',
25
  'maxcdn',
26
  'mirror',
27
- 'netdna',
28
  'rscf',
29
  'rackspace_cdn',
30
  's3',
@@ -40,25 +37,12 @@ class Cdn_Util {
40
  */
41
  static public function is_engine_mirror( $engine ) {
42
  return in_array( $engine, array(
43
- 'mirror', 'netdna', 'maxcdn', 'cotendo', 'cf2', 'akamai',
44
  'edgecast', 'att', 'highwinds', 'rackspace_cdn' ) );
45
  }
46
 
47
- /**
48
- * Returns true if CDN engine is mirror
49
- *
50
- * @param string $engine
51
- * @return bool
52
- */
53
- static public function is_engine_fsd( $engine ) {
54
- return in_array( $engine, array(
55
- 'cloudfront_fsd',
56
- 'maxcdn_fsd'
57
- ) );
58
- }
59
-
60
  static public function is_engine_push( $engine ) {
61
- return !self::is_engine_mirror( $engine ) && !self::is_engine_fsd( $engine );
62
  }
63
 
64
  /**
@@ -72,10 +56,8 @@ class Cdn_Util {
72
  'att',
73
  'cotendo',
74
  'edgecast',
75
- 'maxcdn_fsd',
76
  'highwinds',
77
  'maxcdn',
78
- 'netdna',
79
  ) );
80
  }
81
 
@@ -92,14 +74,11 @@ class Cdn_Util {
92
  'azure',
93
  'cf',
94
  'cf2',
95
- 'cloudfront_fsd',
96
  'cotendo',
97
  'edgecast',
98
- 'maxcdn_fsd',
99
  'ftp',
100
  'highwinds',
101
  'maxcdn',
102
- 'netdna',
103
  'rscf',
104
  's3',
105
  's3_compatible',
14
  'att',
15
  'azure',
16
  'cf',
 
17
  'cf2',
18
  'cotendo',
19
  'edgecast',
 
20
  'ftp',
21
  'google_drive',
22
  'highwinds',
23
  'maxcdn',
24
  'mirror',
 
25
  'rscf',
26
  'rackspace_cdn',
27
  's3',
37
  */
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 ) {
45
+ return !self::is_engine_mirror( $engine );
46
  }
47
 
48
  /**
56
  'att',
57
  'cotendo',
58
  'edgecast',
 
59
  'highwinds',
60
  'maxcdn',
 
61
  ) );
62
  }
63
 
74
  'azure',
75
  'cf',
76
  'cf2',
 
77
  'cotendo',
78
  'edgecast',
 
79
  'ftp',
80
  'highwinds',
81
  'maxcdn',
 
82
  'rscf',
83
  's3',
84
  's3_compatible',
Cdn_Fsd_CacheFlush.php → Cdnfsd_CacheFlush.php RENAMED
@@ -4,7 +4,7 @@ namespace W3TC;
4
  /**
5
  * CDN cache flusher
6
  */
7
- class Cdn_Fsd_CacheFlush {
8
  /**
9
  * Array of urls to flush
10
  *
@@ -22,7 +22,7 @@ class Cdn_Fsd_CacheFlush {
22
  if ( isset( $extras['only'] ) && $extras['only'] != 'cdn' )
23
  return;
24
 
25
- $o = Dispatcher::component( 'Cdn_Fsd_CacheFlush' );
26
 
27
  $o->flush_all_requested = true;
28
  return true;
@@ -167,7 +167,7 @@ class Cdn_Fsd_CacheFlush {
167
  * Queue flush
168
  */
169
  if ( count( $full_urls ) ) {
170
- $o = Dispatcher::component( 'Cdn_Fsd_CacheFlush' );
171
 
172
  foreach ( $full_urls as $url )
173
  $o->queued_urls[$url] = '*';
@@ -182,7 +182,7 @@ class Cdn_Fsd_CacheFlush {
182
  * @param unknown $url
183
  */
184
  static public function w3tc_flush_url( $url ) {
185
- $o = Dispatcher::component( 'Cdn_Fsd_CacheFlush' );
186
  $o->queued_urls[$url] = '*';
187
 
188
  return true;
@@ -192,14 +192,18 @@ class Cdn_Fsd_CacheFlush {
192
  * Clears global and repeated urls
193
  */
194
  static public function w3tc_flush_execute_delayed_operations( $actions_made ) {
195
- $o = Dispatcher::component( 'Cdn_Fsd_CacheFlush' );
196
 
197
  if ( $o->flush_all_requested ) {
198
- $core = Dispatcher::component( 'Cdn_Fsd_Core' );
199
  $engine = $core->get_engine();
 
 
200
  try {
201
- $engine->flush_all();
202
- $actions_made[] = array( 'module' => 'cdn' );
 
 
203
  } catch ( \Exception $ex ) {
204
  $actions_made[] = array(
205
  'module' => 'cdn',
@@ -214,11 +218,13 @@ class Cdn_Fsd_CacheFlush {
214
  if ( $count > 0 ) {
215
  $urls = array_keys( $o->queued_urls );
216
 
217
- $core = Dispatcher::component( 'Cdn_Fsd_Core' );
218
  $engine = $core->get_engine();
219
  try {
220
- $engine->flush_urls( $urls );
221
- $actions_made[] = array( 'module' => 'cdn' );
 
 
222
  } catch ( \Exception $ex ) {
223
  $actions_made[] = array(
224
  'module' => 'cdn',
4
  /**
5
  * CDN cache flusher
6
  */
7
+ class Cdnfsd_CacheFlush {
8
  /**
9
  * Array of urls to flush
10
  *
22
  if ( isset( $extras['only'] ) && $extras['only'] != 'cdn' )
23
  return;
24
 
25
+ $o = Dispatcher::component( 'Cdnfsd_CacheFlush' );
26
 
27
  $o->flush_all_requested = true;
28
  return true;
167
  * Queue flush
168
  */
169
  if ( count( $full_urls ) ) {
170
+ $o = Dispatcher::component( 'Cdnfsd_CacheFlush' );
171
 
172
  foreach ( $full_urls as $url )
173
  $o->queued_urls[$url] = '*';
182
  * @param unknown $url
183
  */
184
  static public function w3tc_flush_url( $url ) {
185
+ $o = Dispatcher::component( 'Cdnfsd_CacheFlush' );
186
  $o->queued_urls[$url] = '*';
187
 
188
  return true;
192
  * Clears global and repeated urls
193
  */
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' );
206
+ }
207
  } catch ( \Exception $ex ) {
208
  $actions_made[] = array(
209
  'module' => 'cdn',
218
  if ( $count > 0 ) {
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' );
227
+ }
228
  } catch ( \Exception $ex ) {
229
  $actions_made[] = array(
230
  'module' => 'cdn',
Cdn_CloudFrontFsd_Api.php → Cdnfsd_CloudFront_Api.php RENAMED
@@ -1,7 +1,7 @@
1
  <?php
2
  namespace W3TC;
3
 
4
- class Cdn_CloudFrontFsd_Api {
5
  private $access_key; // AWS Access key
6
  private $secret_Key; // AWS Secret key
7
  private $api_host; // AWS host where API is located
1
  <?php
2
  namespace W3TC;
3
 
4
+ class Cdnfsd_CloudFront_Api {
5
  private $access_key; // AWS Access key
6
  private $secret_Key; // AWS Secret key
7
  private $api_host; // AWS host where API is located
Cdn_CloudFrontFsd_Engine.php → Cdnfsd_CloudFront_Engine.php RENAMED
@@ -3,7 +3,7 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Cdn_CloudFrontFsd_Engine {
7
  private $access_key;
8
  private $secret_key;
9
  private $distribution_id;
@@ -23,7 +23,7 @@ class Cdn_CloudFrontFsd_Engine {
23
  empty( $this->distribution_id ) )
24
  throw new \Exception( __( 'Access key not specified.', 'w3-total-cache' ) );
25
 
26
- $api = new Cdn_CloudFrontFsd_Api( $this->access_key, $this->secret_key );
27
  $uris = array();
28
  foreach ( $urls as $url ) {
29
  $parsed = parse_url( $url );
@@ -46,7 +46,7 @@ class Cdn_CloudFrontFsd_Engine {
46
  empty( $this->distribution_id ) )
47
  throw new \Exception( __( 'Access key not specified.', 'w3-total-cache' ) );
48
 
49
- $api = new Cdn_CloudFrontFsd_Api( $this->access_key, $this->secret_key );
50
  $uris = array( '/*' );
51
 
52
  $api->invalidation_create( $this->distribution_id, $uris );
3
 
4
 
5
 
6
+ class Cdnfsd_CloudFront_Engine {
7
  private $access_key;
8
  private $secret_key;
9
  private $distribution_id;
23
  empty( $this->distribution_id ) )
24
  throw new \Exception( __( 'Access key not specified.', 'w3-total-cache' ) );
25
 
26
+ $api = new Cdnfsd_CloudFront_Api( $this->access_key, $this->secret_key );
27
  $uris = array();
28
  foreach ( $urls as $url ) {
29
  $parsed = parse_url( $url );
46
  empty( $this->distribution_id ) )
47
  throw new \Exception( __( 'Access key not specified.', 'w3-total-cache' ) );
48
 
49
+ $api = new Cdnfsd_CloudFront_Api( $this->access_key, $this->secret_key );
50
  $uris = array( '/*' );
51
 
52
  $api->invalidation_create( $this->distribution_id, $uris );
Cdnfsd_CloudFront_Page.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class Cdnfsd_CloudFront_Page {
5
+ // called from plugin-admin
6
+ static public function admin_print_scripts_performance_page_w3tc_cdn() {
7
+ wp_enqueue_script( 'w3tc_cdn_cloudfront_fsd',
8
+ plugins_url( 'Cdnfsd_CloudFront_Page_View.js', W3TC_FILE ),
9
+ array( 'jquery' ), '1.0' );
10
+ }
11
+
12
+
13
+
14
+ static public function w3tc_settings_box_cdnfsd() {
15
+ $config = Dispatcher::config();
16
+ include W3TC_DIR . '/Cdnfsd_CloudFront_Page_View.php';
17
+ }
18
+ }
Cdn_CloudFrontFsd_Page_View.js → Cdnfsd_CloudFront_Page_View.js RENAMED
@@ -43,7 +43,7 @@ jQuery(function($) {
43
  var name = $(this).attr('name');
44
  var type = $(this).attr('type');
45
  if (type == 'radio') {
46
- if (!$(this).attr('checked'))
47
  return;
48
  }
49
 
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
 
Cdn_CloudFrontFsd_Page_View.php → Cdnfsd_CloudFront_Page_View.php RENAMED
@@ -4,18 +4,13 @@ namespace W3TC;
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
- $key = $config->get_string( 'cdn.cloudfront_fsd.access_key' );
8
  $authorized = !empty( $key );
9
 
10
- include W3TC_DIR . '/Cdn_Page_View_Header.php';
11
  ?>
12
- <p id="w3tc-options-menu">
13
- <?php _e( 'Jump to:', 'w3-total-cache' ); ?>
14
- <a href="?page=w3tc_general"><?php _e( 'Main Menu', 'w3-total-cache' ); ?></a>
15
- </p>
16
  <form id="cdn_form" action="admin.php?page=w3tc_cdn" method="post">
17
  <div class="metabox-holder">
18
- <?php Util_Ui::postbox_header( __( 'Configuration', 'w3-total-cache' ),
19
  '', 'configuration' ); ?>
20
  <table class="form-table">
21
  <tr>
@@ -45,15 +40,15 @@ _e( 'Specify account credentials:',
45
  <?php if ( $authorized ): ?>
46
  <tr>
47
  <th>
48
- <label><?php _e( 'CDN CNAME:', 'w3-total-cache' ); ?></label>
49
  </th>
50
  <td class="w3tc_config_value_text">
51
  <?php
52
- echo $config->get_string( 'cdn.cloudfront_fsd.distribution_domain' )
53
  ?><br />
54
  <span class="description">
55
  This website domain has to be CNAME pointing to this
56
- CDN domain
57
  </span>
58
  </td>
59
  </tr>
@@ -64,6 +59,3 @@ echo $config->get_string( 'cdn.cloudfront_fsd.distribution_domain' )
64
  <?php Util_Ui::postbox_footer(); ?>
65
  </div>
66
  </form>
67
-
68
- <?php
69
- include W3TC_INC_DIR . '/options/common/footer.php';
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
+ $key = $config->get_string( 'cdnfsd.cloudfront.access_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>
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.cloudfront.distribution_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>
59
  <?php Util_Ui::postbox_footer(); ?>
60
  </div>
61
  </form>
 
 
 
Cdn_CloudFrontFsd_Popup.php → Cdnfsd_CloudFront_Popup.php RENAMED
@@ -3,9 +3,9 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Cdn_CloudFrontFsd_Popup {
7
  static public function w3tc_ajax() {
8
- $o = new Cdn_CloudFrontFsd_Popup();
9
 
10
  add_action( 'w3tc_ajax_cdn_cloudfront_fsd_intro',
11
  array( $o, 'w3tc_ajax_cdn_cloudfront_fsd_intro' ) );
@@ -34,7 +34,7 @@ class Cdn_CloudFrontFsd_Popup {
34
  'w3tc_cdn_maxcdn_authorize' => 'y'
35
  ) );
36
 
37
- include W3TC_DIR . '/Cdn_CloudFrontFsd_Popup_View_Intro.php';
38
  exit();
39
  }
40
 
@@ -44,7 +44,7 @@ class Cdn_CloudFrontFsd_Popup {
44
  $access_key = $_REQUEST['access_key'];
45
  $secret_key = $_REQUEST['secret_key'];
46
 
47
- $api = new Cdn_CloudFrontFsd_Api( $access_key, $secret_key );
48
  if ( empty( $access_key ) || empty( $secret_key ) ) {
49
  $this->render_intro( array(
50
  'error_message' => 'Can\'t authenticate: Access Key or Secret not valid'
@@ -82,7 +82,7 @@ class Cdn_CloudFrontFsd_Popup {
82
  'distributions' => $items
83
  );
84
 
85
- include W3TC_DIR . '/Cdn_CloudFrontFsd_Popup_View_Distributions.php';
86
  exit();
87
  }
88
 
@@ -119,7 +119,7 @@ class Cdn_CloudFrontFsd_Popup {
119
  // create new zone mode
120
  $details['distribution_comment'] = Util_Request::get( 'comment_new' );
121
  } else {
122
- $api = new Cdn_CloudFrontFsd_Api( $access_key, $secret_key );
123
 
124
  try {
125
  $distribution = $api->distribution_get( $distribution_id );
@@ -171,7 +171,7 @@ class Cdn_CloudFrontFsd_Popup {
171
 
172
 
173
 
174
- include W3TC_DIR . '/Cdn_CloudFrontFsd_Popup_View_Distribution.php';
175
  exit();
176
  }
177
 
@@ -305,7 +305,7 @@ class Cdn_CloudFrontFsd_Popup {
305
  );
306
 
307
  try {
308
- $api = new Cdn_CloudFrontFsd_Api( $access_key, $secret_key );
309
  if ( empty( $distribution_id ) ) {
310
  $distribution['DefaultCacheBehavior']['TrustedSigners'] = array(
311
  'Enabled' => 'false',
@@ -329,10 +329,10 @@ class Cdn_CloudFrontFsd_Popup {
329
  $distribution_domain = $response['DomainName'];
330
 
331
  $c = Dispatcher::config();
332
- $c->set( 'cdn.cloudfront_fsd.access_key', $access_key );
333
- $c->set( 'cdn.cloudfront_fsd.secret_key', $secret_key );
334
- $c->set( 'cdn.cloudfront_fsd.distribution_id', $distribution_id );
335
- $c->set( 'cdn.cloudfront_fsd.distribution_domain', $distribution_domain );
336
  $c->save();
337
 
338
  $details = array(
@@ -341,7 +341,7 @@ class Cdn_CloudFrontFsd_Popup {
341
  'dns_cname_target' => $distribution_domain,
342
  );
343
 
344
- include W3TC_DIR . '/Cdn_CloudFrontFsd_Popup_View_Success.php';
345
  exit();
346
  }
347
 
@@ -355,7 +355,7 @@ class Cdn_CloudFrontFsd_Popup {
355
  $origin_id = rand();
356
 
357
  try {
358
- $api = new Cdn_CloudFrontFsd_Api( $access_key, $secret_key );
359
  $distribution = $api->distribution_get( $distribution_id );
360
  } catch ( \Exception $ex ) {
361
  $this->render_intro( array(
@@ -370,10 +370,10 @@ class Cdn_CloudFrontFsd_Popup {
370
  $distribution_domain = 'n/a';
371
 
372
  $c = Dispatcher::config();
373
- $c->set( 'cdn.cloudfront_fsd.access_key', $access_key );
374
- $c->set( 'cdn.cloudfront_fsd.secret_key', $secret_key );
375
- $c->set( 'cdn.cloudfront_fsd.distribution_id', $distribution_id );
376
- $c->set( 'cdn.cloudfront_fsd.distribution_domain', $distribution_domain );
377
  $c->save();
378
 
379
  $details = array(
@@ -382,7 +382,7 @@ class Cdn_CloudFrontFsd_Popup {
382
  'dns_cname_target' => $distribution_domain,
383
  );
384
 
385
- include W3TC_DIR . '/Cdn_CloudFrontFsd_Popup_View_Success.php';
386
  exit();
387
  }
388
  }
3
 
4
 
5
 
6
+ class Cdnfsd_CloudFront_Popup {
7
  static public function w3tc_ajax() {
8
+ $o = new Cdnfsd_CloudFront_Popup();
9
 
10
  add_action( 'w3tc_ajax_cdn_cloudfront_fsd_intro',
11
  array( $o, 'w3tc_ajax_cdn_cloudfront_fsd_intro' ) );
34
  'w3tc_cdn_maxcdn_authorize' => 'y'
35
  ) );
36
 
37
+ include W3TC_DIR . '/Cdnfsd_CloudFront_Popup_View_Intro.php';
38
  exit();
39
  }
40
 
44
  $access_key = $_REQUEST['access_key'];
45
  $secret_key = $_REQUEST['secret_key'];
46
 
47
+ $api = new Cdnfsd_CloudFront_Api( $access_key, $secret_key );
48
  if ( empty( $access_key ) || empty( $secret_key ) ) {
49
  $this->render_intro( array(
50
  'error_message' => 'Can\'t authenticate: Access Key or Secret not valid'
82
  'distributions' => $items
83
  );
84
 
85
+ include W3TC_DIR . '/Cdnfsd_CloudFront_Popup_View_Distributions.php';
86
  exit();
87
  }
88
 
119
  // create new zone mode
120
  $details['distribution_comment'] = Util_Request::get( 'comment_new' );
121
  } else {
122
+ $api = new Cdnfsd_CloudFront_Api( $access_key, $secret_key );
123
 
124
  try {
125
  $distribution = $api->distribution_get( $distribution_id );
171
 
172
 
173
 
174
+ include W3TC_DIR . '/Cdnfsd_CloudFront_Popup_View_Distribution.php';
175
  exit();
176
  }
177
 
305
  );
306
 
307
  try {
308
+ $api = new Cdnfsd_CloudFront_Api( $access_key, $secret_key );
309
  if ( empty( $distribution_id ) ) {
310
  $distribution['DefaultCacheBehavior']['TrustedSigners'] = array(
311
  'Enabled' => 'false',
329
  $distribution_domain = $response['DomainName'];
330
 
331
  $c = Dispatcher::config();
332
+ $c->set( 'cdnfsd.cloudfront.access_key', $access_key );
333
+ $c->set( 'cdnfsd.cloudfront.secret_key', $secret_key );
334
+ $c->set( 'cdnfsd.cloudfront.distribution_id', $distribution_id );
335
+ $c->set( 'cdnfsd.cloudfront.distribution_domain', $distribution_domain );
336
  $c->save();
337
 
338
  $details = array(
341
  'dns_cname_target' => $distribution_domain,
342
  );
343
 
344
+ include W3TC_DIR . '/Cdnfsd_CloudFront_Popup_View_Success.php';
345
  exit();
346
  }
347
 
355
  $origin_id = rand();
356
 
357
  try {
358
+ $api = new Cdnfsd_CloudFront_Api( $access_key, $secret_key );
359
  $distribution = $api->distribution_get( $distribution_id );
360
  } catch ( \Exception $ex ) {
361
  $this->render_intro( array(
370
  $distribution_domain = 'n/a';
371
 
372
  $c = Dispatcher::config();
373
+ $c->set( 'cdnfsd.cloudfront.access_key', $access_key );
374
+ $c->set( 'cdnfsd.cloudfront.secret_key', $secret_key );
375
+ $c->set( 'cdnfsd.cloudfront.distribution_id', $distribution_id );
376
+ $c->set( 'cdnfsd.cloudfront.distribution_domain', $distribution_domain );
377
  $c->save();
378
 
379
  $details = array(
382
  'dns_cname_target' => $distribution_domain,
383
  );
384
 
385
+ include W3TC_DIR . '/Cdnfsd_CloudFront_Popup_View_Success.php';
386
  exit();
387
  }
388
  }
Cdn_CloudFrontFsd_Popup_View_Distribution.php → Cdnfsd_CloudFront_Popup_View_Distribution.php RENAMED
File without changes
Cdn_CloudFrontFsd_Popup_View_Distributions.php → Cdnfsd_CloudFront_Popup_View_Distributions.php RENAMED
File without changes
Cdn_CloudFrontFsd_Popup_View_Intro.php → Cdnfsd_CloudFront_Popup_View_Intro.php RENAMED
@@ -18,7 +18,7 @@ if ( isset( $details['error_message'] ) )
18
  <td>
19
  <input name="access_key" type="text" class="w3tc-ignore-change"
20
  style="width: 550px"
21
- value="<?php echo $config->get_string( 'cdn.cloudfront_fsd.access_key' ) ?>" />
22
  </td>
23
  </tr>
24
  <tr>
@@ -26,7 +26,7 @@ if ( isset( $details['error_message'] ) )
26
  <td>
27
  <input name="secret_key" type="text" class="w3tc-ignore-change"
28
  style="width: 550px"
29
- value="<?php echo $config->get_string( 'cdn.cloudfront_fsd.secret_key' ) ?>" />
30
  </td>
31
  </tr>
32
  </table>
18
  <td>
19
  <input name="access_key" type="text" class="w3tc-ignore-change"
20
  style="width: 550px"
21
+ value="<?php echo $config->get_string( 'cdnfsd.cloudfront.access_key' ) ?>" />
22
  </td>
23
  </tr>
24
  <tr>
26
  <td>
27
  <input name="secret_key" type="text" class="w3tc-ignore-change"
28
  style="width: 550px"
29
+ value="<?php echo $config->get_string( 'cdnfsd.cloudfront.secret_key' ) ?>" />
30
  </td>
31
  </tr>
32
  </table>
Cdn_CloudFrontFsd_Popup_View_Success.php → Cdnfsd_CloudFront_Popup_View_Success.php RENAMED
File without changes
Cdnfsd_Core.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * Core for FSD CDN
6
+ */
7
+ class Cdnfsd_Core {
8
+ /**
9
+ * Returns CDN object
10
+ */
11
+ function get_engine() {
12
+ static $engine_object = null;
13
+
14
+ if ( is_null( $engine_object ) ) {
15
+ $c = Dispatcher::config();
16
+ $engine = $c->get_string( 'cdnfsd.engine' );
17
+
18
+ switch ( $engine ) {
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' ),
26
+ 'secret_key' => $c->get_string( 'cdnfsd.cloudfront.secret_key' ),
27
+ 'distribution_id' => $c->get_string( 'cdnfsd.cloudfront.distribution_id' )
28
+ ) );
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' ),
36
+ 'debug' => $c->get_string( 'cdnfsd.debug' )
37
+ ) );
38
+ break;
39
+
40
+ case 'maxcdn':
41
+ $engine_object = new Cdnfsd_MaxCdn_Engine( array(
42
+ 'api_key' => $c->get_string( 'cdnfsd.maxcdn.api_key' ),
43
+ 'zone_id' => $c->get_integer( 'cdnfsd.maxcdn.zone_id' )
44
+ ) );
45
+ break;
46
+
47
+ default:
48
+ throw new \Exception( 'unknown engine ' . $engine );
49
+ }
50
+ }
51
+
52
+ return $engine_object;
53
+ }
54
+ }
Cdnfsd_GeneralPage_View.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <p><?php _e( 'Host whole website with your full site content delivery network provider to reduce page load time.', 'w3-total-cache' ); ?>
9
+ <?php if ( !$cdnfsd_enabled ): ?>
10
+ <?php printf( __( ' If you do not have a <acronym title="Content Delivery Network">CDN</acronym> provider try MaxCDN. <a href="%s" target="_blank">Sign up and save 25&#37;</a>.', 'w3-total-cache' ), wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_maxcdn_signup' ), 'w3tc' ) ); ?>
11
+ <?php endif ?>
12
+ </p>
13
+ <table class="form-table">
14
+ <?php
15
+ Util_Ui::config_item( array(
16
+ 'key' => 'cdnfsd.enabled',
17
+ 'label' => __( '<acronym title="Full Site Delivery">FSD</acronym> <acronym title="Content Delivery Network">CDN</acronym>:', 'w3-total-cache' ),
18
+ 'control' => 'checkbox',
19
+ 'checkbox_label' => __( 'Enable', 'w3-total-cache' ),
20
+ 'disabled' => ( $is_pro ? null : true ),
21
+ 'description' => __( 'Whole website will appear to load instantly for site visitors.',
22
+ 'w3-total-cache' ) .
23
+ ( $is_pro ? '' : __( ' <strong>Available after upgrade.</strong>', 'w3-total-cache' ) )
24
+ ) );
25
+
26
+ Util_Ui::config_item( array(
27
+ 'key' => 'cdnfsd.engine',
28
+ 'label' => __( '<acronym title="Full Site Delivery">FSD</acronym> <acronym title="Content Delivery Network">CDN</acronym> Type:', 'w3-total-cache' ),
29
+ 'control' => 'selectbox',
30
+ 'selectbox_values' => $cdnfsd_engine_values,
31
+ 'value' => $cdnfsd_engine,
32
+ 'disabled' => ( $is_pro ? null : true ),
33
+ 'description' => __( 'Select the <acronym title="Content Delivery Network">CDN</acronym> type you wish to use.',
34
+ 'w3-total-cache' ) . $cdnfsd_engine_extra_description
35
+ ) );
36
+ ?>
37
+ </table>
Cdnfsd_Limelight_Api.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdnfsd_Limelight_Api {
7
+ private $url_base;
8
+
9
+
10
+
11
+ public function __construct( $short_name, $username, $api_key ) {
12
+ $this->url_base = 'https://purge.llnw.com/purge/v1/account/' .
13
+ $short_name . '/requests';
14
+ $this->username = $username;
15
+ $this->api_key = $api_key;
16
+ }
17
+
18
+
19
+
20
+ public function purge( $items ) {
21
+ $body = json_encode( array( 'patterns' => $items ) );
22
+ return $this->_wp_remote_post( '', $body );
23
+ }
24
+
25
+
26
+
27
+ public function get( $uri ) {
28
+ return $this->_wp_remote_get( $uri );
29
+ }
30
+
31
+
32
+
33
+ private function _wp_remote_get( $uri, $body = '', $headers = array() ) {
34
+ $url = $this->url_base . $uri;
35
+ $headers = $this->_add_headers( $headers, $url, 'GET', $body );
36
+
37
+ $result = wp_remote_get( $url, array(
38
+ 'headers' => $headers,
39
+ 'body' => $body
40
+ ) );
41
+
42
+ return $this->_decode_response( $result );
43
+ }
44
+
45
+
46
+
47
+ private function _wp_remote_post( $uri, $body, $headers = array() ) {
48
+ $url = $this->url_base . $uri;
49
+ $headers = $this->_add_headers( $headers, $url, 'POST', $body );
50
+
51
+ $result = wp_remote_post( $url, array(
52
+ 'headers' => $headers,
53
+ 'body' => $body
54
+ ) );
55
+
56
+ return $this->_decode_response( $result );
57
+ }
58
+
59
+
60
+
61
+ private function _add_headers( $headers, $url, $method, $body ) {
62
+ $timestamp = '' . ( time() * 1000 );
63
+
64
+ $headers['Content-Type'] = 'application/json';
65
+ $headers['X-LLNW-Security-Principal'] = $this->username;
66
+ $headers['X-LLNW-Security-Timestamp'] = $timestamp;
67
+ $headers['X-LLNW-Security-Token'] = hash_hmac( 'sha256',
68
+ $method . $url . $timestamp . $body, pack( 'H*', $this->api_key ) );
69
+
70
+ return $headers;
71
+ }
72
+
73
+
74
+
75
+ private function _decode_response( $result ) {
76
+ if ( is_wp_error( $result ) )
77
+ throw new \Exception( 'Failed to reach API endpoint' );
78
+
79
+ $response_json = @json_decode( $result['body'], true );
80
+ if ( is_null( $response_json ) ) {
81
+ throw new \Exception(
82
+ 'Failed to reach API endpoint, got unexpected response ' .
83
+ $result['body'] );
84
+ }
85
+
86
+ if ( $result['response']['code'] != '200' &&
87
+ $result['response']['code'] != '201' &&
88
+ $result['response']['code'] != '202' &&
89
+ $result['response']['code'] != '204' ) {
90
+ if ( isset( $response_json['errors'] ) &&
91
+ isset( $response_json['errors'][0]['description'] ) ) {
92
+ throw new \Exception( $response_json['errors'][0]['description'] );
93
+ }
94
+
95
+ throw new \Exception( $result['body'] );
96
+ }
97
+
98
+
99
+ return $response_json;
100
+ }
101
+ }
Cdnfsd_Limelight_Engine.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdnfsd_Limelight_Engine {
7
+ private $short_name;
8
+ private $username;
9
+ private $api_key;
10
+ private $debug;
11
+
12
+
13
+
14
+ function __construct( $config = array() ) {
15
+ $this->short_name = $config['short_name'];
16
+ $this->username = $config['username'];
17
+ $this->api_key = $config['api_key'];
18
+ $this->debug = $config['debug'];
19
+ }
20
+
21
+
22
+
23
+ function flush_urls( $urls ) {
24
+ if ( empty( $this->short_name ) || empty( $this->username ) ||
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 ) {
32
+ $items[] = array(
33
+ 'pattern' => $url,
34
+ 'exact' => true,
35
+ 'evict' => false,
36
+ 'incqs' => false
37
+ );
38
+
39
+ // max number of items per request based on API docs
40
+ if ( count( $items ) >= 100 ) {
41
+ if ( $this->debug ) {
42
+ Util_Debug::log( 'cdnfsd', json_encode( $items, JSON_PRETTY_PRINT ) );
43
+ }
44
+
45
+ $api->purge( $items );
46
+ $items = array();
47
+ }
48
+ }
49
+
50
+ if ( $this->debug ) {
51
+ Util_Debug::log( 'cdnfsd', json_encode( $items, JSON_PRETTY_PRINT ) );
52
+ }
53
+
54
+ $api->purge( $items );
55
+ }
56
+
57
+
58
+
59
+ /**
60
+ * Flushes CDN completely
61
+ */
62
+ function flush_all() {
63
+ if ( empty( $this->short_name ) || empty( $this->username ) ||
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(
71
+ array(
72
+ 'pattern' => $url,
73
+ 'exact' => false,
74
+ 'evict' => false,
75
+ 'incqs' => false
76
+ )
77
+ );
78
+
79
+ if ( $this->debug ) {
80
+ Util_Debug::log( 'cdnfsd', json_encode( $items, JSON_PRETTY_PRINT ) );
81
+ }
82
+
83
+ $api->purge( $items );
84
+ }
85
+ }
Cdnfsd_Limelight_Page.php ADDED
@@ -0,0 +1,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
+
12
+
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 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_cdnfsd_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=cdnfsd_limelight_intro',
16
+ callback: w3tc_popup_resize
17
+ });
18
+ })
19
+
20
+
21
+
22
+ .on('click', '.w3tc_cdnfsd_limelight_save', function() {
23
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
24
+ '&w3tc_action=cdnfsd_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_cdnfsd_limelight_done', function() {
39
+ // refresh page
40
+ window.location = window.location + '&';
41
+ })
42
+ });
Cdnfsd_Limelight_Page_View.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ $key = $config->get_string( 'cdnfsd.limelight.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_cdnfsd_limelight_authorize button-primary"
28
+ type="button"
29
+ value="<?php _e( 'Reauthorize', 'w3-total-cache' ); ?>"
30
+ />
31
+ <?php else: ?>
32
+ <input class="w3tc_cdnfsd_limelight_authorize button-primary"
33
+ type="button"
34
+ value="<?php _e( 'Authorize', 'w3-total-cache' ); ?>"
35
+ />
36
+ <?php endif ?>
37
+ </td>
38
+ </tr>
39
+ </table>
40
+
41
+ <?php Util_Ui::postbox_footer(); ?>
42
+ </div>
43
+ </form>
Cdnfsd_Limelight_Popup.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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_cdnfsd_limelight_intro',
11
+ array( $o, 'w3tc_ajax_cdnfsd_limelight_intro' ) );
12
+ add_action( 'w3tc_ajax_cdnfsd_limelight_save',
13
+ array( $o, 'w3tc_ajax_cdnfsd_limelight_save' ) );
14
+ }
15
+
16
+
17
+
18
+ public function w3tc_ajax_cdnfsd_limelight_intro() {
19
+ $this->render_intro( array() );
20
+ }
21
+
22
+
23
+
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
+
31
+
32
+
33
+ public function w3tc_ajax_cdnfsd_limelight_save() {
34
+ $short_name = $_REQUEST['short_name'];
35
+ $username = $_REQUEST['username'];
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(
43
+ array(
44
+ 'pattern' => $url,
45
+ 'exact' => true,
46
+ 'evict' => false,
47
+ 'incqs' => false
48
+ )
49
+ );
50
+
51
+ $api->purge( $items );
52
+ } catch ( \Exception $ex ) {
53
+ $this->render_intro( array(
54
+ 'error_message' => 'Failed to make test purge request: ' . $ex->getMessage()
55
+ ) );
56
+ exit();
57
+ }
58
+
59
+ $c = Dispatcher::config();
60
+ $c->set( 'cdnfsd.limelight.short_name', $short_name );
61
+ $c->set( 'cdnfsd.limelight.username', $username );
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 ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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( 'cdnfsd.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( 'cdnfsd.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( 'cdnfsd.limelight.api_key' ) ?>" />
38
+ </td>
39
+ </tr>
40
+ </table>
41
+
42
+ <p class="submit">
43
+ <input type="button"
44
+ class="w3tc_cdnfsd_limelight_save w3tc-button-save button-primary"
45
+ value="<?php _e( 'Next', 'w3-total-cache' ); ?>" />
46
+ </p>
47
+ <?php Util_Ui::postbox_footer(); ?>
48
+ </div>
49
+ </form>
Cdnfsd_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_cdnfsd_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_MaxCdnFsd_Engine.php → Cdnfsd_MaxCdn_Engine.php RENAMED
@@ -3,7 +3,7 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Cdn_MaxCdnFsd_Engine {
7
  private $api_key;
8
  private $zone_id;
9
 
3
 
4
 
5
 
6
+ class Cdnfsd_MaxCdn_Engine {
7
  private $api_key;
8
  private $zone_id;
9
 
Cdnfsd_MaxCdn_Page.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class Cdnfsd_MaxCdn_Page {
7
+ // called from plugin-admin
8
+ static public function admin_print_scripts_performance_page_w3tc_cdn() {
9
+ wp_enqueue_script( 'w3tc_cdn_maxcdn_fsd',
10
+ plugins_url( 'Cdnfsd_MaxCdn_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_MaxCdn_Page_View.php';
19
+ }
20
+ }
Cdn_MaxCdnFsd_Page_View.js → Cdnfsd_MaxCdn_Page_View.js RENAMED
@@ -43,7 +43,7 @@ jQuery(function($) {
43
  var name = $(this).attr('name');
44
  var type = $(this).attr('type');
45
  if (type == 'radio') {
46
- if (!$(this).attr('checked'))
47
  return;
48
  }
49
 
@@ -73,6 +73,22 @@ jQuery(function($) {
73
 
74
 
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  .on('click', '.w3tc_cdn_maxcdn_fsd_done', function() {
77
  // refresh page
78
  window.location = window.location + '&';
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
 
73
 
74
 
75
 
76
+ .on('click', '.w3tc_cdn_maxcdn_fsd_configure_zone_skip', function() {
77
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
78
+ '&w3tc_action=cdn_maxcdn_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_maxcdn_fsd_resize);
88
+ })
89
+
90
+
91
+
92
  .on('click', '.w3tc_cdn_maxcdn_fsd_done', function() {
93
  // refresh page
94
  window.location = window.location + '&';
Cdn_MaxCdnFsd_Page_View.php → Cdnfsd_MaxCdn_Page_View.php RENAMED
@@ -4,21 +4,13 @@ namespace W3TC;
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
- $key = $config->get_string( 'cdn.maxcdn_fsd.api_key' );
8
  $authorized = !empty( $key );
9
 
10
- include W3TC_DIR . '/Cdn_Page_View_Header.php';
11
- ?>
12
- <p id="w3tc-options-menu">
13
- <?php _e( 'Jump to:', 'w3-total-cache' ); ?>
14
- <a href="?page=w3tc_general"><?php _e( 'Main Menu', 'w3-total-cache' ); ?></a>
15
- </p>
16
- <?php
17
- include W3TC_DIR . '/Cdn_Page_View_Fsd_HeaderActions.php';
18
  ?>
19
  <form id="cdn_form" action="admin.php?page=w3tc_cdn" method="post">
20
  <div class="metabox-holder">
21
- <?php Util_Ui::postbox_header( __( 'Configuration', 'w3-total-cache' ),
22
  '', 'configuration' ); ?>
23
  <table class="form-table">
24
  <tr>
@@ -48,15 +40,15 @@ _e( 'Specify account credentials:',
48
  <?php if ( $authorized ): ?>
49
  <tr>
50
  <th>
51
- <label><?php _e( 'CDN CNAME:', 'w3-total-cache' ); ?></label>
52
  </th>
53
  <td class="w3tc_config_value_text">
54
  <?php
55
- echo $config->get_string( 'cdn.maxcdn_fsd.zone_domain' )
56
  ?><br />
57
  <span class="description">
58
  This website domain has to be CNAME pointing to this
59
- CDN domain
60
  </span>
61
  </td>
62
  </tr>
@@ -67,6 +59,3 @@ echo $config->get_string( 'cdn.maxcdn_fsd.zone_domain' )
67
  <?php Util_Ui::postbox_footer(); ?>
68
  </div>
69
  </form>
70
-
71
- <?php
72
- include W3TC_INC_DIR . '/options/common/footer.php';
4
  if ( !defined( 'W3TC' ) )
5
  die();
6
 
7
+ $key = $config->get_string( 'cdnfsd.maxcdn.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>
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.maxcdn.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>
59
  <?php Util_Ui::postbox_footer(); ?>
60
  </div>
61
  </form>
 
 
 
Cdn_MaxCdnFsd_Popup.php → Cdnfsd_MaxCdn_Popup.php RENAMED
@@ -3,9 +3,9 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Cdn_MaxCdnFsd_Popup {
7
  static public function w3tc_ajax() {
8
- $o = new Cdn_MaxCdnFsd_Popup();
9
 
10
  add_action( 'w3tc_ajax_cdn_maxcdn_fsd_intro',
11
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_intro' ) );
@@ -15,6 +15,8 @@ class Cdn_MaxCdnFsd_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
  }
19
 
20
 
@@ -30,7 +32,7 @@ class Cdn_MaxCdnFsd_Popup {
30
  $config = Dispatcher::config();
31
 
32
  $this->render_intro( array(
33
- 'api_key' => $config->get_string( 'cdn.maxcdn_fsd.api_key' ) ) );
34
  }
35
 
36
 
@@ -42,7 +44,7 @@ class Cdn_MaxCdnFsd_Popup {
42
  'w3tc_cdn_maxcdn_authorize' => 'y'
43
  ) );
44
 
45
- include W3TC_DIR . '/Cdn_MaxCdnFsd_Popup_View_Intro.php';
46
  exit();
47
  }
48
 
@@ -81,7 +83,7 @@ class Cdn_MaxCdnFsd_Popup {
81
  'zones' => $zones
82
  );
83
 
84
- include W3TC_DIR . '/Cdn_MaxCdnFsd_Popup_View_Zones.php';
85
  exit();
86
  }
87
 
@@ -115,7 +117,7 @@ class Cdn_MaxCdnFsd_Popup {
115
  if ( empty( $zone_id ) ) {
116
  // create new zone mode
117
  $details['name'] = Util_Request::get( 'zone_new_name' );
118
- $details['ip']['new'] = Cdn_Fsd_Util::get_suggested_home_ip();
119
  } else {
120
  $api = \NetDNA::create( $api_key );
121
  try {
@@ -132,8 +134,8 @@ class Cdn_MaxCdnFsd_Popup {
132
  $details['custom_domain']['current'] = '';
133
 
134
  foreach ( $custom_domains as $d ) {
135
- $details['custom_domain']['current'] = $d['custom_domain'];
136
- if ( $d['custom_domain'] == Util_Environment::home_url_host() )
137
  break;
138
  }
139
 
@@ -143,7 +145,7 @@ class Cdn_MaxCdnFsd_Popup {
143
  $details['url']['current'] = $zone['url'];
144
  $details['ip']['current'] = $zone['ip'];
145
 
146
- $origin_ip = Cdn_Fsd_Util::get_suggested_home_ip();
147
  $cdn_ip = gethostbyname( $zone['tmp_url'] );
148
 
149
  if ( $origin_ip != $cdn_ip )
@@ -152,7 +154,7 @@ class Cdn_MaxCdnFsd_Popup {
152
 
153
 
154
 
155
- include W3TC_DIR . '/Cdn_MaxCdnFsd_Popup_View_Zone.php';
156
  exit();
157
  }
158
 
@@ -251,7 +253,7 @@ class Cdn_MaxCdnFsd_Popup {
251
 
252
  $added = false;
253
  foreach ( $custom_domains as $d ) {
254
- if ( $d['custom_domain'] == $custom_domain ) {
255
  $added = true;
256
  break;
257
  }
@@ -270,9 +272,9 @@ class Cdn_MaxCdnFsd_Popup {
270
  $zone_domain = $response['tmp_url'];
271
 
272
  $c = Dispatcher::config();
273
- $c->set( 'cdn.maxcdn_fsd.api_key', $api_key );
274
- $c->set( 'cdn.maxcdn_fsd.zone_id', $zone_id );
275
- $c->set( 'cdn.maxcdn_fsd.zone_domain', $zone_domain );
276
  $c->save();
277
 
278
  $details = array(
@@ -281,7 +283,43 @@ class Cdn_MaxCdnFsd_Popup {
281
  'dns_cname_target' => $zone_domain,
282
  );
283
 
284
- include W3TC_DIR . '/Cdn_MaxCdnFsd_Popup_View_Success.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  exit();
286
  }
287
  }
3
 
4
 
5
 
6
+ class Cdnfsd_MaxCdn_Popup {
7
  static public function w3tc_ajax() {
8
+ $o = new Cdnfsd_MaxCdn_Popup();
9
 
10
  add_action( 'w3tc_ajax_cdn_maxcdn_fsd_intro',
11
  array( $o, 'w3tc_ajax_cdn_maxcdn_fsd_intro' ) );
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
 
22
 
32
  $config = Dispatcher::config();
33
 
34
  $this->render_intro( array(
35
+ 'api_key' => $config->get_string( 'cdnfsd.maxcdn.api_key' ) ) );
36
  }
37
 
38
 
44
  'w3tc_cdn_maxcdn_authorize' => 'y'
45
  ) );
46
 
47
+ include W3TC_DIR . '/Cdnfsd_MaxCdn_Popup_View_Intro.php';
48
  exit();
49
  }
50
 
83
  'zones' => $zones
84
  );
85
 
86
+ include W3TC_DIR . '/Cdnfsd_MaxCdn_Popup_View_Zones.php';
87
  exit();
88
  }
89
 
117
  if ( empty( $zone_id ) ) {
118
  // create new zone mode
119
  $details['name'] = Util_Request::get( 'zone_new_name' );
120
+ $details['ip']['new'] = Cdnfsd_Util::get_suggested_home_ip();
121
  } else {
122
  $api = \NetDNA::create( $api_key );
123
  try {
134
  $details['custom_domain']['current'] = '';
135
 
136
  foreach ( $custom_domains as $d ) {
137
+ $details['custom_domain']['current'] = $d;
138
+ if ( $d == Util_Environment::home_url_host() )
139
  break;
140
  }
141
 
145
  $details['url']['current'] = $zone['url'];
146
  $details['ip']['current'] = $zone['ip'];
147
 
148
+ $origin_ip = Cdnfsd_Util::get_suggested_home_ip();
149
  $cdn_ip = gethostbyname( $zone['tmp_url'] );
150
 
151
  if ( $origin_ip != $cdn_ip )
154
 
155
 
156
 
157
+ include W3TC_DIR . '/Cdnfsd_MaxCdn_Popup_View_Zone.php';
158
  exit();
159
  }
160
 
253
 
254
  $added = false;
255
  foreach ( $custom_domains as $d ) {
256
+ if ( $d == $custom_domain ) {
257
  $added = true;
258
  break;
259
  }
272
  $zone_domain = $response['tmp_url'];
273
 
274
  $c = Dispatcher::config();
275
+ $c->set( 'cdnfsd.maxcdn.api_key', $api_key );
276
+ $c->set( 'cdnfsd.maxcdn.zone_id', $zone_id );
277
+ $c->set( 'cdnfsd.maxcdn.zone_domain', $zone_domain );
278
  $c->save();
279
 
280
  $details = array(
283
  'dns_cname_target' => $zone_domain,
284
  );
285
 
286
+ include W3TC_DIR . '/Cdnfsd_MaxCdn_Popup_View_Success.php';
287
+ exit();
288
+ }
289
+
290
+
291
+
292
+ public function w3tc_ajax_cdn_maxcdn_fsd_configure_zone_skip() {
293
+ $api_key = $_REQUEST['api_key'];
294
+ $zone_id = Util_Request::get( 'zone_id', '' );
295
+
296
+ $api = \NetDNA::create( $api_key );
297
+
298
+ try {
299
+ $zone = $api->get_zone( $zone_id );
300
+ } catch ( \Exception $ex ) {
301
+ $this->render_intro( array(
302
+ 'api_key' => $api_key,
303
+ 'error_message' => 'Failed to obtain custom domains: ' . $ex->getMessage()
304
+ ) );
305
+ exit();
306
+ }
307
+
308
+ $zone_domain = $zone['cdn_url'];
309
+
310
+ $c = Dispatcher::config();
311
+ $c->set( 'cdnfsd.maxcdn.api_key', $api_key );
312
+ $c->set( 'cdnfsd.maxcdn.zone_id', $zone_id );
313
+ $c->set( 'cdnfsd.maxcdn.zone_domain', $zone_domain );
314
+ $c->save();
315
+
316
+ $details = array(
317
+ 'name' => $zone['name'],
318
+ 'home_domain' => Util_Environment::home_url_host(),
319
+ 'dns_cname_target' => $zone_domain,
320
+ );
321
+
322
+ include W3TC_DIR . '/Cdnfsd_MaxCdn_Popup_View_Success.php';
323
  exit();
324
  }
325
  }
Cdn_MaxCdnFsd_Popup_View_Intro.php → Cdnfsd_MaxCdn_Popup_View_Intro.php RENAMED
File without changes
Cdn_MaxCdnFsd_Popup_View_Success.php → Cdnfsd_MaxCdn_Popup_View_Success.php RENAMED
File without changes
Cdn_MaxCdnFsd_Popup_View_Zone.php → Cdnfsd_MaxCdn_Popup_View_Zone.php RENAMED
@@ -37,10 +37,10 @@ Util_Ui::hidden( '', 'name', $details['name'] );
37
  <td><?php $this->render_zone_boolean_change( $details, 'dns_check' ) ?></td>
38
  </tr>
39
  <tr>
40
- <th>CDN Domain:</th>
41
  <td>
42
  <?php $this->render_zone_value_change( $details, 'custom_domain' ) ?><br />
43
- <span class="description">Domain CDN will handle</span>
44
  </td>
45
  </tr>
46
  </table>
@@ -49,6 +49,10 @@ Util_Ui::hidden( '', 'name', $details['name'] );
49
  <input type="button"
50
  class="w3tc_cdn_maxcdn_fsd_configure_zone w3tc-button-save button-primary"
51
  value="<?php _e( 'Apply', 'w3-total-cache' ); ?>" />
 
 
 
 
52
  </p>
53
  <?php Util_Ui::postbox_footer(); ?>
54
  </div>
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>
49
  <input type="button"
50
  class="w3tc_cdn_maxcdn_fsd_configure_zone w3tc-button-save button-primary"
51
  value="<?php _e( 'Apply', 'w3-total-cache' ); ?>" />
52
+ <input type="button"
53
+ class="w3tc_cdn_maxcdn_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>
Cdn_MaxCdnFsd_Popup_View_Zones.php → Cdnfsd_MaxCdn_Popup_View_Zones.php RENAMED
File without changes
Cdnfsd_Page_View_Header.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+
9
+ <p>
10
+ <?php echo sprintf(
11
+ __( 'Content Delivery Network support via %1$s is currently %2$s.', 'w3-total-cache' ),
12
+ '<strong>'.Cdnfsd_Util::engine_name( $config->get_string( 'cdnfsd.engine' ) ).'</strong>',
13
+ '<span class="w3tc-' . ( $config->get_boolean( 'cdnfsd.enabled' ) ? 'enabled">' . __( 'enabled', 'w3-total-cache' ) : 'disabled">' . __( 'disabled', 'w3-total-cache' ) ) . '</span>'
14
+ ); ?>
15
+ </p>
Cdnfsd_Plugin.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * W3 Total Cache CDN Plugin
6
+ */
7
+ class Cdnfsd_Plugin {
8
+ /**
9
+ * Config
10
+ */
11
+ private $_config = null;
12
+
13
+ function __construct() {
14
+ $this->_config = Dispatcher::config();
15
+ }
16
+
17
+ /**
18
+ * Runs plugin
19
+ */
20
+ function run() {
21
+ add_filter( 'w3tc_footer_comment', array(
22
+ $this,
23
+ 'w3tc_footer_comment'
24
+ ) );
25
+
26
+ add_action( 'w3tc_flush_all', array(
27
+ '\W3TC\Cdnfsd_CacheFlush',
28
+ 'w3tc_flush_all'
29
+ ), 3000, 1 );
30
+ add_action( 'w3tc_flush_post', array(
31
+ '\W3TC\Cdnfsd_CacheFlush',
32
+ 'w3tc_flush_post'
33
+ ), 3000, 1 );
34
+ add_action( 'w3tc_flushable_posts', '__return_true', 3000 );
35
+ add_action( 'w3tc_flush_posts', array(
36
+ '\W3TC\Cdnfsd_CacheFlush',
37
+ 'w3tc_flush_all'
38
+ ), 3000 );
39
+ add_action( 'w3tc_flush_url', array(
40
+ '\W3TC\Cdnfsd_CacheFlush',
41
+ 'w3tc_flush_url'
42
+ ), 3000, 1 );
43
+ add_filter( 'w3tc_flush_execute_delayed_operations', array(
44
+ '\W3TC\Cdnfsd_CacheFlush',
45
+ 'w3tc_flush_execute_delayed_operations'
46
+ ), 3000 );
47
+
48
+ Util_AttachToActions::flush_posts_on_actions();
49
+ }
50
+
51
+ public function w3tc_footer_comment( $strings ) {
52
+ $config = Dispatcher::config();
53
+ $via = $config->get_string('cdnfsd.engine');
54
+
55
+ $strings[] = sprintf(
56
+ __( 'Content Delivery Network Full Site Delivery via %s', 'w3-total-cache' ),
57
+ ( $via ? $via : 'N/A' ) );
58
+
59
+ return $strings;
60
+ }
61
+ }
Cdnfsd_Plugin_Admin.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class Cdnfsd_Plugin_Admin {
5
+ function run() {
6
+ $c = Dispatcher::config();
7
+ $cdnfsd_engine = $c->get_string( 'cdnfsd.engine' );
8
+
9
+ // attach to actions without firing class loading at all without need
10
+ if ( $cdnfsd_engine == 'cloudfront' ) {
11
+ add_action( 'admin_print_scripts-performance_page_w3tc_cdn', array(
12
+ '\W3TC\Cdnfsd_CloudFront_Page',
13
+ 'admin_print_scripts_performance_page_w3tc_cdn' ) );
14
+ add_action( 'w3tc_ajax', array(
15
+ '\W3TC\Cdnfsd_CloudFront_Popup',
16
+ 'w3tc_ajax' ) );
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',
23
+ 'admin_print_scripts_performance_page_w3tc_cdn' ) );
24
+ add_action( 'w3tc_ajax', array(
25
+ '\W3TC\Cdnfsd_MaxCdn_Popup',
26
+ 'w3tc_ajax' ) );
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
+
42
+ add_action( 'w3tc_settings_general_boxarea_cdn_footer',
43
+ array( $this, 'w3tc_settings_general_boxarea_cdn_footer' ) );
44
+ }
45
+
46
+
47
+
48
+ public function w3tc_settings_general_boxarea_cdn_footer() {
49
+ $config = Dispatcher::config();
50
+
51
+ $cdnfsd_enabled = $config->get_boolean( 'cdnfsd.enabled' );
52
+ $cdnfsd_engine = $config->get_string( 'cdnfsd.engine' );
53
+
54
+ $is_pro = Util_Environment::is_w3tc_pro( $config );
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' ),
62
+ );
63
+ $cdnfsd_engine_values['cloudflare'] = array(
64
+ 'label' => __( 'CloudFlare (extension not activated)', 'w3-total-cache' ),
65
+ 'disabled' => true,
66
+ );
67
+ $cdnfsd_engine_values['limelight'] = array(
68
+ 'label' => __( 'Limelight', 'w3-total-cache' ),
69
+ );
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 ) ) {
82
+ $cdnfsd_engine_extra_description = '';
83
+ } else {
84
+ $cdnfsd_engine_extra_description =
85
+ ' See <a href="admin.php?page=w3tc_faq' . $tag .
86
+ '">setup instructions</a>';
87
+ }
88
+
89
+ include W3TC_DIR . '/Cdnfsd_GeneralPage_View.php';
90
+ }
91
+ }
Cdn_Fsd_Util.php → Cdnfsd_Util.php RENAMED
@@ -1,7 +1,15 @@
1
  <?php
2
  namespace W3TC;
3
 
4
- class Cdn_Fsd_Util {
 
 
 
 
 
 
 
 
5
  static public function get_suggested_home_ip() {
6
  $ip = gethostbyname( Util_Environment::home_url_host() );
7
 
1
  <?php
2
  namespace W3TC;
3
 
4
+
5
+
6
+ class Cdnfsd_Util {
7
+ static public function engine_name( $engine ) {
8
+ return $engine;
9
+ }
10
+
11
+
12
+
13
  static public function get_suggested_home_ip() {
14
  $ip = gethostbyname( Util_Environment::home_url_host() );
15
 
Cli.php CHANGED
@@ -296,6 +296,32 @@ class W3TotalCache_Command extends \WP_CLI_Command {
296
  }
297
  }
298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  /**
300
  * Update query string for all static files
301
  */
296
  }
297
  }
298
 
299
+ /**
300
+ * Imports configuration file
301
+ *
302
+ * ## OPTIONS
303
+ * <filename>
304
+ * : Filename to import
305
+ */
306
+ function import( $args = array(), $vars = array() ) {
307
+ $filename = array_shift( $args );
308
+
309
+ try {
310
+ $config = new Config();
311
+ if ( !file_exists( $filename ) || !is_readable( $filename ) ) {
312
+ throw new \Exception( 'Cant read file: ' . $filename );
313
+ }
314
+ if ( !$config->import( $filename ) ) {
315
+ throw new \Exception( 'import failed' );
316
+ }
317
+ $config->save();
318
+ } catch ( \Exception $e ) {
319
+ \WP_CLI::error( __( 'Config import failed: ' . $e->getMessage(), 'w3-total-cache' ) );
320
+ }
321
+
322
+ \WP_CLI::success( __( 'Configuration successfully imported.', 'w3-total-cache' ) );
323
+ }
324
+
325
  /**
326
  * Update query string for all static files
327
  */
Config.php CHANGED
@@ -29,7 +29,30 @@ class Config {
29
  * Reads config from file and returns it's content as array (or null)
30
  * Stored in this class to limit class loading
31
  */
32
- static public function util_array_from_file( $filename ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  if ( file_exists( $filename ) && is_readable( $filename ) ) {
34
  // including file directly instead of read+eval causes constant
35
  // problems with APC, ZendCache, and WSOD in a case of
@@ -37,8 +60,9 @@ class Config {
37
  $content = @file_get_contents( $filename );
38
  $config = @json_decode( substr( $content, 14 ), true );
39
 
40
- if ( is_array( $config ) )
41
  return $config;
 
42
  }
43
 
44
  return null;
@@ -61,20 +85,6 @@ class Config {
61
 
62
 
63
 
64
- /*
65
- * Returns config filename
66
- * Stored in this class to limit class loading
67
- * v<0.9.5
68
- */
69
- static public function util_config_filename_legacy_v1( $blog_id, $preview ) {
70
- $postfix = ( $preview ? '-preview' : '' ) . '.php';
71
-
72
- if ( $blog_id <= 0 )
73
- return W3TC_CONFIG_DIR . '/master' . $postfix;
74
- else
75
- return W3TC_CONFIG_DIR . '/' . sprintf( '%06d', $blog_id ) . $postfix;
76
- }
77
-
78
  /*
79
  * Returns config filename
80
  * Stored in this class to limit class loading
@@ -228,6 +238,8 @@ class Config {
228
  $this->set( 'extensions.active_frontend', $a );
229
  }
230
 
 
 
231
  /**
232
  * Sets config value.
233
  * Method to override
@@ -249,6 +261,8 @@ class Config {
249
  return $value;
250
  }
251
 
 
 
252
  /**
253
  * Check if we are in preview mode
254
  */
@@ -256,6 +270,8 @@ class Config {
256
  return $this->_preview;
257
  }
258
 
 
 
259
  /**
260
  * Returns true if we edit master config
261
  */
@@ -263,6 +279,8 @@ class Config {
263
  return $this->_is_master;
264
  }
265
 
 
 
266
  public function is_compiled() {
267
  return $this->_compiled;
268
  }
@@ -324,11 +342,20 @@ class Config {
324
  */
325
  public function import( $filename ) {
326
  if ( file_exists( $filename ) && is_readable( $filename ) ) {
327
- $data = file_get_contents( $filename );
328
- $config = @json_decode( $data, true );
 
 
329
 
330
- if ( is_array( $config ) ) {
331
- foreach ( $config as $key => $value )
 
 
 
 
 
 
 
332
  $this->set( $key, $value );
333
 
334
  return true;
@@ -355,17 +382,15 @@ class Config {
355
  * correctly
356
  */
357
  public function load() {
358
- $master_filename = Config::util_config_filename( 0, $this->_preview );
359
- $data = Config::util_array_from_file( $master_filename );
360
 
361
  // config file assumed is not up to date, use slow version
362
  if ( !isset( $data['version'] ) || $data['version'] != W3TC_VERSION )
363
  return $this->load_full();
364
 
365
  if ( !$this->is_master() ) {
366
- $child_filename = Config::util_config_filename( $this->_blog_id,
367
  $this->_preview );
368
- $child_data = Config::util_array_from_file( $child_filename );
369
 
370
  if ( !is_null( $child_data ) ) {
371
  if ( !isset( $data['version'] ) || $data['version'] != W3TC_VERSION )
29
  * Reads config from file and returns it's content as array (or null)
30
  * Stored in this class to limit class loading
31
  */
32
+ static public function util_array_from_storage( $blog_id, $preview ) {
33
+ if ( !defined( 'W3TC_CONFIG_CACHE_ENGINE' ) ) {
34
+ return self::_util_array_from_storage( $blog_id, $preview );
35
+ }
36
+
37
+ // config cache enabled
38
+ $config = ConfigCache::util_array_from_storage( $blog_id, $preview );
39
+ if ( !is_null( $config ) ) {
40
+ return $config;
41
+ }
42
+
43
+ $config = self::_util_array_from_storage( $blog_id, $preview );
44
+ ConfigCache::save_item( $blog_id, $preview, $config );
45
+ return $config;
46
+ }
47
+
48
+
49
+
50
+ static private function _util_array_from_storage( $blog_id, $preview ) {
51
+ if ( defined( 'W3TC_CONFIG_DATABASE' ) && W3TC_CONFIG_DATABASE ) {
52
+ return ConfigDbStorage::util_array_from_storage( $blog_id, $preview );
53
+ }
54
+
55
+ $filename = self::util_config_filename( $blog_id, $preview );
56
  if ( file_exists( $filename ) && is_readable( $filename ) ) {
57
  // including file directly instead of read+eval causes constant
58
  // problems with APC, ZendCache, and WSOD in a case of
60
  $content = @file_get_contents( $filename );
61
  $config = @json_decode( substr( $content, 14 ), true );
62
 
63
+ if ( is_array( $config ) ) {
64
  return $config;
65
+ }
66
  }
67
 
68
  return null;
85
 
86
 
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  /*
89
  * Returns config filename
90
  * Stored in this class to limit class loading
238
  $this->set( 'extensions.active_frontend', $a );
239
  }
240
 
241
+
242
+
243
  /**
244
  * Sets config value.
245
  * Method to override
261
  return $value;
262
  }
263
 
264
+
265
+
266
  /**
267
  * Check if we are in preview mode
268
  */
270
  return $this->_preview;
271
  }
272
 
273
+
274
+
275
  /**
276
  * Returns true if we edit master config
277
  */
279
  return $this->_is_master;
280
  }
281
 
282
+
283
+
284
  public function is_compiled() {
285
  return $this->_compiled;
286
  }
342
  */
343
  public function import( $filename ) {
344
  if ( file_exists( $filename ) && is_readable( $filename ) ) {
345
+ $content = file_get_contents( $filename );
346
+ if ( substr( $content, 0, 14 ) == '<?php exit; ?>' ) {
347
+ $content = substr( $content, 14 );
348
+ }
349
 
350
+ $data = @json_decode( $content, true );
351
+ if ( is_array( $data ) ) {
352
+ if ( !isset( $data['version'] ) || $data['version'] != W3TC_VERSION ) {
353
+ $c = new ConfigCompiler( $this->_blog_id, false );
354
+ $c->load( $data );
355
+ $data = $c->get_data();
356
+ }
357
+
358
+ foreach ( $data as $key => $value )
359
  $this->set( $key, $value );
360
 
361
  return true;
382
  * correctly
383
  */
384
  public function load() {
385
+ $data = Config::util_array_from_storage( 0, $this->_preview );
 
386
 
387
  // config file assumed is not up to date, use slow version
388
  if ( !isset( $data['version'] ) || $data['version'] != W3TC_VERSION )
389
  return $this->load_full();
390
 
391
  if ( !$this->is_master() ) {
392
+ $child_data = Config::util_array_from_storage( $this->_blog_id,
393
  $this->_preview );
 
394
 
395
  if ( !is_null( $child_data ) ) {
396
  if ( !isset( $data['version'] ) || $data['version'] != W3TC_VERSION )
ConfigCache.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * Provides access to config cache, used mostly when config is stored in
6
+ * database to not issue config loading database queries on each http request
7
+ */
8
+ class ConfigCache {
9
+ /**
10
+ * Reads config from config cache
11
+ */
12
+ static public function util_array_from_storage( $blog_id, $preview ) {
13
+ $cache = self::get_cache();
14
+
15
+ $config = $cache->get( self::get_key( $blog_id, $preview ) );
16
+ if ( is_array( $config ) ) {
17
+ return $config;
18
+ }
19
+
20
+ return null;
21
+ }
22
+
23
+
24
+
25
+ /**
26
+ * Removes config cache entry so that it can be read from original source
27
+ * on next attempt
28
+ */
29
+ static public function remove_item( $blog_id, $preview ) {
30
+ $cache = self::get_cache();
31
+
32
+ $cache->hard_delete( self::get_key( $blog_id, false ) );
33
+ $cache->hard_delete( self::get_key( $blog_id, true ) );
34
+ }
35
+
36
+
37
+
38
+ static public function save_item( $blog_id, $preview, $data ) {
39
+ $cache = self::get_cache();
40
+
41
+ $cache->set( self::get_key( $blog_id, $preview ), $data );
42
+ }
43
+
44
+
45
+
46
+ static private function get_cache() {
47
+ static $cache = null;
48
+
49
+ if ( !is_null( $cache ) ) {
50
+ return $cache;
51
+ }
52
+
53
+ switch ( W3TC_CONFIG_CACHE_ENGINE ) {
54
+ case 'memcached':
55
+ $engineConfig = array(
56
+ 'servers' => explode( ',', W3TC_CONFIG_CACHE_MEMCACHED_SERVERS ),
57
+ 'persistent' =>
58
+ ( defined( 'W3TC_CONFIG_CACHE_MEMCACHED_PERSISTENT' ) ?
59
+ W3TC_CONFIG_CACHE_MEMCACHED_PERSISTENT : true ),
60
+ 'aws_autodiscovery' =>
61
+ ( defined( 'W3TC_CONFIG_CACHE_MEMCACHED_AWS_AUTODISCOVERY' ) ?
62
+ W3TC_CONFIG_CACHE_MEMCACHED_AWS_AUTODISCOVERY : false ),
63
+ 'username' =>
64
+ ( defined( 'W3TC_CONFIG_CACHE_MEMCACHED_USERNAME' ) ?
65
+ W3TC_CONFIG_CACHE_MEMCACHED_USERNAME : '' ),
66
+ 'password' =>
67
+ ( defined( 'W3TC_CONFIG_CACHE_MEMCACHED_PASSWORD' ) ?
68
+ W3TC_CONFIG_CACHE_MEMCACHED_PASSWORD : '' ),
69
+ 'key_version_mode' => 'disabled'
70
+ );
71
+ break;
72
+
73
+ case 'redis':
74
+ $engineConfig = array(
75
+ 'servers' => explode( ',', W3TC_CONFIG_CACHE_REDIS_SERVERS ),
76
+ 'persistent' =>
77
+ ( defined( 'W3TC_CONFIG_CACHE_REDIS_PERSISTENT' ) ?
78
+ W3TC_CONFIG_CACHE_REDIS_PERSISTENT : true ),
79
+ 'dbid' =>
80
+ ( defined( 'W3TC_CONFIG_CACHE_REDIS_DBID' ) ?
81
+ W3TC_CONFIG_CACHE_REDIS_DBID : 0 ),
82
+ 'password' =>
83
+ ( defined( 'W3TC_CONFIG_CACHE_REDIS_PASSWORD' ) ?
84
+ W3TC_CONFIG_CACHE_REDIS_PASSWORD : '' ),
85
+ 'key_version_mode' => 'disabled'
86
+ );
87
+ break;
88
+
89
+ default:
90
+ $engineConfig = array();
91
+ }
92
+
93
+ $engineConfig['blog_id'] = '0';
94
+ $engineConfig['module'] = 'config';
95
+ $engineConfig['host'] = '';
96
+ $engineConfig['instance_id'] =
97
+ ( defined( 'W3TC_INSTANCE_ID' ) ? W3TC_INSTANCE_ID : 0 );
98
+
99
+ $cache = Cache::instance( W3TC_CONFIG_CACHE_ENGINE, $engineConfig );
100
+ return $cache;
101
+ }
102
+
103
+
104
+
105
+ static private function get_key( $blog_id, $preview ) {
106
+ return 'w3tc_config_' . $blog_id . ( $preview ? '_preview' : '' );
107
+ }
108
+ }
ConfigCompiler.php CHANGED
@@ -70,27 +70,6 @@ class ConfigCompiler {
70
 
71
 
72
 
73
- /**
74
- * Reads config from file and returns it's content as array (or null)
75
- * Stored in this class to limit class loading
76
- */
77
- static private function util_array_from_file_legacy_v1( $filename ) {
78
- if ( file_exists( $filename ) && is_readable( $filename ) ) {
79
- // including file directly instead of read+eval causes constant
80
- // problems with APC, ZendCache, and WSOD in a case of
81
- // broken config file
82
- $content = @file_get_contents( $filename );
83
- $config = @eval( substr( $content, 5 ) );
84
-
85
- if ( is_array( $config ) )
86
- return $config;
87
- }
88
-
89
- return null;
90
- }
91
-
92
-
93
-
94
  /**
95
  * Reads config from file and returns it's content as array (or null)
96
  * Stored in this class to limit class loading
@@ -128,14 +107,14 @@ class ConfigCompiler {
128
 
129
 
130
 
131
- public function load() {
132
  // apply data from master config
133
- $master_filename = Config::util_config_filename( 0, $this->_preview );
134
- $data = Config::util_array_from_file( $master_filename );
 
135
  if ( is_null( $data ) && $this->_preview ) {
136
  // try to read production data when preview not available
137
- $master_filename = Config::util_config_filename( 0, false );
138
- $data = Config::util_array_from_file( $master_filename );
139
  }
140
 
141
  // try to get legacy v2 data
@@ -145,13 +124,6 @@ class ConfigCompiler {
145
  $data = self::util_array_from_file_legacy_v2( $master_filename );
146
  }
147
 
148
- // try to get legacy v1 data
149
- if ( is_null( $data ) ) {
150
- $master_filename = Config::util_config_filename_legacy_v1( 0,
151
- $this->_preview );
152
- $data = self::util_array_from_file_legacy_v1( $master_filename );
153
- }
154
-
155
  if ( is_array( $data ) ) {
156
  $data = $this->upgrade( $data );
157
  foreach ( $data as $key => $value )
@@ -163,14 +135,12 @@ class ConfigCompiler {
163
 
164
 
165
  // apply child config
166
- $child_filename = Config::util_config_filename( $this->_blog_id,
167
  $this->_preview );
168
- $data = Config::util_array_from_file( $child_filename );
169
  if ( is_null( $data ) && $this->_preview ) {
170
  // try to read production data when preview not available
171
- $child_filename = Config::util_config_filename( $this->_blog_id,
172
  false );
173
- $data = Config::util_array_from_file( $child_filename );
174
  }
175
 
176
  // try to get legacy v2 data
@@ -180,13 +150,6 @@ class ConfigCompiler {
180
  $data = self::util_array_from_file_legacy_v2( $child_filename );
181
  }
182
 
183
- // try to get legacy v1 data
184
- if ( is_null( $data ) ) {
185
- $child_filename = Config::util_config_filename_legacy_v1(
186
- $this->_blog_id, $this->_preview );
187
- $data = self::util_array_from_file_legacy_v1( $child_filename );
188
- }
189
-
190
  if ( is_array( $data ) ) {
191
  $data = $this->upgrade( $data );
192
  foreach ( $data as $key => $value ) {
@@ -231,14 +194,7 @@ class ConfigCompiler {
231
  }
232
  }
233
 
234
- $filename = Config::util_config_filename( $this->_blog_id,
235
- $this->_preview );
236
- if ( defined( 'JSON_PRETTY_PRINT' ) )
237
- $config = json_encode( $data, JSON_PRETTY_PRINT );
238
- else // for older php versions
239
- $config = json_encode( $data );
240
-
241
- Util_File::file_put_contents_atomic( $filename, '<?php exit; ?>' . $config );
242
  }
243
 
244
 
@@ -276,6 +232,20 @@ class ConfigCompiler {
276
  }
277
  }
278
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  //
280
  // changes in 0.9.5
281
  //
@@ -425,6 +395,40 @@ class ConfigCompiler {
425
  }
426
  }
427
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  $file_data['version'] = W3TC_VERSION;
429
 
430
  return $file_data;
70
 
71
 
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  /**
74
  * Reads config from file and returns it's content as array (or null)
75
  * Stored in this class to limit class loading
107
 
108
 
109
 
110
+ public function load( $data = null ) {
111
  // apply data from master config
112
+ if ( is_null( $data ) ) {
113
+ $data = Config::util_array_from_storage( 0, $this->_preview );
114
+ }
115
  if ( is_null( $data ) && $this->_preview ) {
116
  // try to read production data when preview not available
117
+ $data = Config::util_array_from_storage( 0, false );
 
118
  }
119
 
120
  // try to get legacy v2 data
124
  $data = self::util_array_from_file_legacy_v2( $master_filename );
125
  }
126
 
 
 
 
 
 
 
 
127
  if ( is_array( $data ) ) {
128
  $data = $this->upgrade( $data );
129
  foreach ( $data as $key => $value )
135
 
136
 
137
  // apply child config
138
+ $data = Config::util_array_from_storage( $this->_blog_id,
139
  $this->_preview );
 
140
  if ( is_null( $data ) && $this->_preview ) {
141
  // try to read production data when preview not available
142
+ $data = Config::util_array_from_storage( $this->_blog_id,
143
  false );
 
144
  }
145
 
146
  // try to get legacy v2 data
150
  $data = self::util_array_from_file_legacy_v2( $child_filename );
151
  }
152
 
 
 
 
 
 
 
 
153
  if ( is_array( $data ) ) {
154
  $data = $this->upgrade( $data );
155
  foreach ( $data as $key => $value ) {
194
  }
195
  }
196
 
197
+ ConfigUtil::save_item( $this->_blog_id, $this->_preview, $data );
 
 
 
 
 
 
 
198
  }
199
 
200
 
232
  }
233
  }
234
 
235
+ //
236
+ // changes in 0.9.6
237
+ //
238
+ if ( !isset( $file_data['cdn.cors_header'] ) ) {
239
+ $file_data['cdn.cors_header'] = true;
240
+ }
241
+ if ( isset( $file_data['cdn.engine'] ) && $file_data['cdn.engine'] == 'netdna' ) {
242
+ $file_data['cdn.engine'] = 'maxcdn';
243
+ $file_data['cdn.maxcdn.authorization_key'] = $file_data['cdn.netdna.authorization_key'];
244
+ $file_data['cdn.maxcdn.domain'] = $file_data['cdn.netdna.domain'];
245
+ $file_data['cdn.maxcdn.ssl'] = $file_data['cdn.netdna.ssl'];
246
+ $file_data['cdn.maxcdn.zone_id'] = $file_data['cdn.netdna.zone_id'];
247
+ }
248
+
249
  //
250
  // changes in 0.9.5
251
  //
395
  }
396
  }
397
 
398
+ //
399
+ // changes in 0.9.5.4
400
+ //
401
+ if ( isset( $file_data['cdn.engine'] ) ) {
402
+ if ( $file_data['cdn.engine'] == 'maxcdn_fsd' ) {
403
+ $file_data['cdnfsd.engine'] = 'maxcdn';
404
+ $file_data['cdnfsd.enabled'] = $file_data['cdn.enabled'];
405
+
406
+ if ( isset( $file_data['cdn.maxcdn_fsd.api_key'] ) ) {
407
+ $file_data['cdnfsd.maxcdn.api_key'] =
408
+ $file_data['cdn.maxcdn_fsd.api_key'];
409
+ $file_data['cdnfsd.maxcdn.zone_id'] =
410
+ $file_data['cdn.maxcdn_fsd.zone_id'];
411
+ $file_data['cdnfsd.maxcdn.zone_domain'] =
412
+ $file_data['cdn.maxcdn_fsd.zone_domain'];
413
+ }
414
+ }
415
+ if ( $file_data['cdn.engine'] == 'cloudfront_fsd' ) {
416
+ $file_data['cdnfsd.engine'] = 'cloudfront';
417
+ $file_data['cdnfsd.enabled'] = $file_data['cdn.enabled'];
418
+
419
+ if ( isset( $file_data['cdn.cloudfront_fsd.access_key'] ) ) {
420
+ $file_data['cdnfsd.cloudfront.access_key'] =
421
+ $file_data['cdn.cloudfront_fsd.access_key'];
422
+ $file_data['cdnfsd.cloudfront.distribution_domain'] =
423
+ $file_data['cdn.cloudfront_fsd.distribution_domain'];
424
+ $file_data['cdnfsd.cloudfront.secret_key'] =
425
+ $file_data['cdn.cloudfront_fsd.secret_key'];
426
+ $file_data['cdnfsd.cloudfront.distribution_id'] =
427
+ $file_data['cdn.cloudfront_fsd.distribution_id'];
428
+ }
429
+ }
430
+ }
431
+
432
  $file_data['version'] = W3TC_VERSION;
433
 
434
  return $file_data;
ConfigDbStorage.php ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ /**
5
+ * class Config
6
+ * Provides configuration data using cache
7
+ */
8
+ class ConfigDbStorage {
9
+ /**
10
+ * Reads config from database
11
+ * Stored in this class to limit class loading
12
+ */
13
+ static public function util_array_from_storage( $blog_id, $preview ) {
14
+ $content = self::load_content( $blog_id, $preview );
15
+ $config = @json_decode( $content, true );
16
+
17
+ if ( is_array( $config ) )
18
+ return $config;
19
+
20
+ return null;
21
+ }
22
+
23
+
24
+
25
+ static public function is_item_exists( $blog_id, $preview ) {
26
+ $content = self::load_content( $blog_id, $preview );
27
+ return is_null( $content );
28
+ }
29
+
30
+
31
+
32
+ static public function remove_item( $blog_id, $preview ) {
33
+ $table = self::get_table( $blog_id );
34
+ $option_name = self::get_option_name( $blog_id, $preview );
35
+
36
+ global $wpdb;
37
+ $wpdb->query( $wpdb->prepare(
38
+ "DELETE FROM $table WHERE option_name = %s",
39
+ $option_name ) );
40
+ }
41
+
42
+
43
+
44
+ /**
45
+ * Deploys the config file from a preview config file
46
+ *
47
+ * @param integer $direction +1: preview->production
48
+ * -1: production->preview
49
+ * @param boolean $remove_source remove source file
50
+ */
51
+ static public function preview_production_copy( $blog_id, $direction ) {
52
+ if ( $direction > 0 ) {
53
+ $content = self::load_content( $blog_id, true );
54
+ self::save_item( $blog_id, false, $content );
55
+ } else {
56
+ $content = self::load_content( $blog_id, false );
57
+ self::save_item( $blog_id, true, $content );
58
+ }
59
+ }
60
+
61
+
62
+
63
+ static public function save_item( $blog_id, $preview, $data ) {
64
+ if ( is_string( $data ) ) {
65
+ $config = $data;
66
+ } else {
67
+ $config = json_encode( $data );
68
+ }
69
+
70
+ $table = self::get_table( $blog_id );
71
+ $option_name = self::get_option_name( $blog_id, $preview );
72
+
73
+ global $wpdb;
74
+ $is_exists = !is_null( self::load_content( $blog_id, $preview ) );
75
+
76
+ if ( $is_exists ) {
77
+ $wpdb->query( $wpdb->prepare(
78
+ "UPDATE $table SET option_value = %s WHERE option_name = %s",
79
+ $config, $option_name ) );
80
+ } else {
81
+ $wpdb->query( $wpdb->prepare(
82
+ "INSERT INTO $table (option_name, option_value) VALUES (%s, %s)",
83
+ $option_name, $config ) );
84
+ }
85
+ }
86
+
87
+
88
+
89
+ static private function get_table( $blog_id ) {
90
+ if ( defined('W3TC_CONFIG_DATABASE_TABLE' ) ) {
91
+ $template = W3TC_CONFIG_DATABASE_TABLE;
92
+ } else {
93
+ global $table_prefix;
94
+ $template = $table_prefix . '{blog_id_prefix}options';
95
+ }
96
+
97
+ if ( $blog_id <= 0 )
98
+ $blog_id_prefix = '';
99
+ else
100
+ $blog_id_prefix = $blog_id . '_';
101
+
102
+ return str_replace('{blog_id_prefix}', $blog_id_prefix, $template);
103
+ }
104
+
105
+
106
+
107
+ static private function get_option_name( $blog_id, $preview ) {
108
+ return 'w3tc_config_' . $blog_id . ( $preview ? '_preview' : '' );
109
+ }
110
+
111
+
112
+
113
+ static private function load_content( $blog_id, $preview ) {
114
+ $table = self::get_table( $blog_id );
115
+ $option_name = self::get_option_name( $blog_id, $preview );
116
+
117
+ if ( isset( $GLOBALS['wpdb'] ) ) {
118
+ global $wpdb;
119
+ $row = $wpdb->get_row( $wpdb->prepare(
120
+ "SELECT option_value FROM $table WHERE option_name = %s LIMIT 1",
121
+ $option_name ) );
122
+ } else {
123
+ $db = new _WpdbEssentials( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
124
+
125
+ if ( $db->ready ) {
126
+ $row = $db->get_row( $db->prepare(
127
+ "SELECT option_value FROM $table WHERE option_name = %s LIMIT 1",
128
+ $option_name ) );
129
+ } else {
130
+ error_log('Failed to load w3tc config');
131
+ $row = null;
132
+ }
133
+
134
+ // close connection immediately so that real pooled connection may be
135
+ // reused by later inialized wpdb object
136
+ $db->close();
137
+ }
138
+
139
+ if ( is_object( $row ) ) {
140
+ return $row->option_value;
141
+ }
142
+
143
+ return null;
144
+ }
145
+ }
146
+
147
+
148
+
149
+ class _WpdbEssentials {
150
+ public $last_error = '';
151
+ public $num_rows = 0;
152
+ var $rows_affected = 0;
153
+ var $last_query;
154
+ var $last_result;
155
+
156
+
157
+
158
+ public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
159
+ if ( function_exists( 'mysqli_connect' ) ) {
160
+ if ( defined( 'WP_USE_EXT_MYSQL' ) ) {
161
+ $this->use_mysqli = ! WP_USE_EXT_MYSQL;
162
+ } elseif ( version_compare( phpversion(), '5.5', '>=' ) || ! function_exists( 'mysql_connect' ) ) {
163
+ $this->use_mysqli = true;
164
+ } elseif ( false !== strpos( $GLOBALS['wp_version'], '-' ) ) {
165
+ $this->use_mysqli = true;
166
+ }
167
+ }
168
+
169
+ $this->dbuser = $dbuser;
170
+ $this->dbpassword = $dbpassword;
171
+ $this->dbname = $dbname;
172
+ $this->dbhost = $dbhost;
173
+
174
+ $this->db_connect();
175
+ }
176
+
177
+
178
+ public function db_connect( $allow_bail = true ) {
179
+ $this->is_mysql = true;
180
+
181
+ /*
182
+ * Deprecated in 3.9+ when using MySQLi. No equivalent
183
+ * $new_link parameter exists for mysqli_* functions.
184
+ */
185
+ $new_link = defined( 'MYSQL_NEW_LINK' ) ? MYSQL_NEW_LINK : true;
186
+ $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
187
+
188
+ if ( $this->use_mysqli ) {
189
+ $this->dbh = mysqli_init();
190
+
191
+ // mysqli_real_connect doesn't support the host param including a port or socket
192
+ // like mysql_connect does. This duplicates how mysql_connect detects a port and/or socket file.
193
+ $port = null;
194
+ $socket = null;
195
+ $host = $this->dbhost;
196
+ $port_or_socket = strstr( $host, ':' );
197
+ if ( ! empty( $port_or_socket ) ) {
198
+ $host = substr( $host, 0, strpos( $host, ':' ) );
199
+ $port_or_socket = substr( $port_or_socket, 1 );
200
+ if ( 0 !== strpos( $port_or_socket, '/' ) ) {
201
+ $port = intval( $port_or_socket );
202
+ $maybe_socket = strstr( $port_or_socket, ':' );
203
+ if ( ! empty( $maybe_socket ) ) {
204
+ $socket = substr( $maybe_socket, 1 );
205
+ }
206
+ } else {
207
+ $socket = $port_or_socket;
208
+ }
209
+ }
210
+
211
+ if ( WP_DEBUG ) {
212
+ mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
213
+ } else {
214
+ @mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
215
+ }
216
+
217
+ if ( $this->dbh->connect_errno ) {
218
+ $this->dbh = null;
219
+ $this->last_error =
220
+ 'Connection failed with ' . $this->dbh->connect_errno . ' error code';
221
+ if ( WP_DEBUG ) {
222
+ echo $this->last_error;
223
+ }
224
+ }
225
+ } else {
226
+ if ( WP_DEBUG ) {
227
+ $this->dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
228
+ } else {
229
+ $this->dbh = @mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $new_link, $client_flags );
230
+ }
231
+ }
232
+
233
+ if ( $this->dbh ) {
234
+ $this->has_connected = true;
235
+ $this->ready = true;
236
+ $this->select( $this->dbname, $this->dbh );
237
+ } else {
238
+ if ( WP_DEBUG ) {
239
+ echo 'Failed to connect to mysql server';
240
+ }
241
+ }
242
+ }
243
+
244
+
245
+
246
+ public function select( $db, $dbh = null ) {
247
+ if ( $this->use_mysqli ) {
248
+ $success = mysqli_select_db( $dbh, $db );
249
+ } else {
250
+ $success = mysql_select_db( $db, $dbh );
251
+ }
252
+ if ( ! $success ) {
253
+ $this->ready = false;
254
+ if ( WP_DEBUG ) {
255
+ echo 'Failed to select database';
256
+ }
257
+ }
258
+ }
259
+
260
+
261
+
262
+ public function prepare( $query, $args ) {
263
+ $args = func_get_args();
264
+ array_shift( $args );
265
+ // If args were passed as an array (as in vsprintf), move them up
266
+ if ( isset( $args[0] ) && is_array($args[0]) )
267
+ $args = $args[0];
268
+ $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
269
+ $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
270
+ $query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
271
+ $query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
272
+ array_walk( $args, array( $this, 'escape_by_ref' ) );
273
+ return @vsprintf( $query, $args );
274
+ }
275
+
276
+
277
+
278
+ public function escape_by_ref( &$string ) {
279
+ if ( ! is_float( $string ) )
280
+ $string = $this->_real_escape( $string );
281
+ }
282
+
283
+
284
+
285
+ function _real_escape( $string ) {
286
+ if ( $this->use_mysqli ) {
287
+ return mysqli_real_escape_string( $this->dbh, $string );
288
+ } else {
289
+ return mysql_real_escape_string( $string, $this->dbh );
290
+ }
291
+ }
292
+
293
+
294
+
295
+ public function get_row( $query = null ) {
296
+ $y = 0;
297
+
298
+ if ( $query ) {
299
+ $this->query( $query );
300
+ } else {
301
+ return null;
302
+ }
303
+
304
+ if ( !isset( $this->last_result[$y] ) )
305
+ return null;
306
+
307
+ return $this->last_result[$y] ? $this->last_result[$y] : null;
308
+ }
309
+
310
+
311
+
312
+ public function query( $query ) {
313
+ if ( ! $this->ready ) {
314
+ return false;
315
+ }
316
+ $this->_do_query( $query );
317
+ // If there is an error then take note of it.
318
+ if ( $this->use_mysqli ) {
319
+ if ( $this->dbh instanceof \mysqli ) {
320
+ $this->last_error = mysqli_error( $this->dbh );
321
+ } else {
322
+ $this->last_error = 'query: Unable to retrieve the error message from MySQL';
323
+ }
324
+ } else {
325
+ if ( is_resource( $this->dbh ) ) {
326
+ $this->last_error = mysql_error( $this->dbh );
327
+ } else {
328
+ $this->last_error = 'query: Unable to retrieve the error message from MySQL';
329
+ }
330
+ }
331
+
332
+ if ( $this->last_error ) {
333
+ if ( WP_DEBUG ) {
334
+ echo $this->last_error;
335
+ }
336
+ return false;
337
+ }
338
+
339
+ $num_rows = 0;
340
+ $this->last_result = array();
341
+ if ( $this->use_mysqli && $this->result instanceof \mysqli_result ) {
342
+ while ( $row = mysqli_fetch_object( $this->result ) ) {
343
+ $this->last_result[$num_rows] = $row;
344
+ $num_rows++;
345
+ }
346
+ } elseif ( is_resource( $this->result ) ) {
347
+ while ( $row = mysql_fetch_object( $this->result ) ) {
348
+ $this->last_result[$num_rows] = $row;
349
+ $num_rows++;
350
+ }
351
+ }
352
+
353
+ // Log number of rows the query returned
354
+ // and return number of rows selected
355
+ $this->num_rows = $num_rows;
356
+ $return_val = $num_rows;
357
+
358
+ return $return_val;
359
+ }
360
+
361
+ private function _do_query( $query ) {
362
+ if ( ! empty( $this->dbh ) && $this->use_mysqli ) {
363
+ $this->result = mysqli_query( $this->dbh, $query );
364
+ } elseif ( ! empty( $this->dbh ) ) {
365
+ $this->result = mysql_query( $query, $this->dbh );
366
+ }
367
+ }
368
+
369
+
370
+
371
+ public function close() {
372
+ if ( ! $this->dbh ) {
373
+ return false;
374
+ }
375
+
376
+ if ( $this->use_mysqli ) {
377
+ $closed = mysqli_close( $this->dbh );
378
+ } else {
379
+ $closed = mysql_close( $this->dbh );
380
+ }
381
+
382
+ if ( $closed ) {
383
+ $this->dbh = null;
384
+ $this->ready = false;
385
+ $this->has_connected = false;
386
+ }
387
+
388
+ return $closed;
389
+ }
390
+ }
ConfigKeys.php CHANGED
@@ -341,6 +341,7 @@ $keys = array(
341
  'type' => 'boolean',
342
  'default' => false
343
  ),
 
344
  'pgcache.cache.nginx_handle_xml' => array(
345
  'type' => 'boolean',
346
  'default' => false
@@ -430,6 +431,22 @@ $keys = array(
430
  'index\.php'
431
  )
432
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
  'pgcache.reject.ua' => array(
434
  'type' => 'array',
435
  'default' => array()
@@ -532,6 +549,38 @@ $keys = array(
532
  'type' => 'boolean',
533
  'default' => false
534
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
535
 
536
  'stats.enabled' => array(
537
  'type' => 'boolean',
@@ -944,7 +993,7 @@ $keys = array(
944
  ),
945
  'cdn.theme.files' => array(
946
  'type' => 'string',
947
- 'default' => '*.css;*.js;*.gif;*.png;*.jpg;*.ico;*.ttf;*.otf,*.woff,*.less'
948
  ),
949
  'cdn.minify.enable' => array(
950
  'type' => 'boolean',
@@ -997,6 +1046,14 @@ $keys = array(
997
  'type' => 'boolean',
998
  'default' => false
999
  ),
 
 
 
 
 
 
 
 
1000
 
1001
  'cdn.ftp.host' => array(
1002
  'type' => 'string',
@@ -1085,6 +1142,10 @@ $keys = array(
1085
  'type' => 'string',
1086
  'default' => ''
1087
  ),
 
 
 
 
1088
  'cdn.s3.cname' => array(
1089
  'type' => 'array',
1090
  'default' => array()
@@ -1111,6 +1172,10 @@ $keys = array(
1111
  'type' => 'string',
1112
  'default' => ''
1113
  ),
 
 
 
 
1114
  'cdn.cf.id' => array(
1115
  'type' => 'string',
1116
  'default' => ''
@@ -1228,34 +1293,6 @@ $keys = array(
1228
  'type' => 'string',
1229
  'default' => 'auto'
1230
  ),
1231
- 'cdn.netdna.alias' => array(
1232
- 'type' => 'string',
1233
- 'default' => ''
1234
- ),
1235
- 'cdn.netdna.consumerkey' => array(
1236
- 'type' => 'string',
1237
- 'default' => ''
1238
- ),
1239
- 'cdn.netdna.consumersecret' => array(
1240
- 'type' => 'string',
1241
- 'default' => ''
1242
- ),
1243
- 'cdn.netdna.authorization_key' => array(
1244
- 'type' => 'string',
1245
- 'default' => ''
1246
- ),
1247
- 'cdn.netdna.domain' => array(
1248
- 'type' => 'array',
1249
- 'default' => array()
1250
- ),
1251
- 'cdn.netdna.ssl' => array(
1252
- 'type' => 'string',
1253
- 'default' => 'auto'
1254
- ),
1255
- 'cdn.netdna.zone_id' => array(
1256
- 'type' => 'integer',
1257
- 'default' => 0
1258
- ),
1259
  'cdn.maxcdn.authorization_key' => array(
1260
  'type' => 'string',
1261
  'default' => ''
@@ -1384,6 +1421,19 @@ $keys = array(
1384
  'type' => 'boolean',
1385
  'default' => false
1386
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
1387
  'varnish.configuration_overloaded' => array(
1388
  'type' => 'boolean',
1389
  'default' => false
@@ -1438,7 +1488,7 @@ $keys = array(
1438
  ),
1439
  'browsercache.cssjs.expires' => array(
1440
  'type' => 'boolean',
1441
- 'default' => false
1442
  ),
1443
  'browsercache.cssjs.lifetime' => array(
1444
  'type' => 'integer',
@@ -1446,7 +1496,7 @@ $keys = array(
1446
  ),
1447
  'browsercache.cssjs.nocookies' => array(
1448
  'type' => 'boolean',
1449
- 'default' => false
1450
  ),
1451
  'browsercache.cssjs.cache.control' => array(
1452
  'type' => 'boolean',
@@ -1458,7 +1508,7 @@ $keys = array(
1458
  ),
1459
  'browsercache.cssjs.etag' => array(
1460
  'type' => 'boolean',
1461
- 'default' => false
1462
  ),
1463
  'browsercache.cssjs.w3tc' => array(
1464
  'type' => 'boolean',
@@ -1498,7 +1548,7 @@ $keys = array(
1498
  ),
1499
  'browsercache.html.etag' => array(
1500
  'type' => 'boolean',
1501
- 'default' => false
1502
  ),
1503
  'browsercache.html.w3tc' => array(
1504
  'type' => 'boolean',
@@ -1518,7 +1568,7 @@ $keys = array(
1518
  ),
1519
  'browsercache.other.expires' => array(
1520
  'type' => 'boolean',
1521
- 'default' => false
1522
  ),
1523
  'browsercache.other.lifetime' => array(
1524
  'type' => 'integer',
@@ -1526,7 +1576,7 @@ $keys = array(
1526
  ),
1527
  'browsercache.other.nocookies' => array(
1528
  'type' => 'boolean',
1529
- 'default' => false
1530
  ),
1531
  'browsercache.other.cache.control' => array(
1532
  'type' => 'boolean',
@@ -1538,7 +1588,7 @@ $keys = array(
1538
  ),
1539
  'browsercache.other.etag' => array(
1540
  'type' => 'boolean',
1541
- 'default' => false
1542
  ),
1543
  'browsercache.other.w3tc' => array(
1544
  'type' => 'boolean',
@@ -1735,17 +1785,13 @@ $keys = array(
1735
  ),
1736
 
1737
 
1738
- 'common.edge' => array(
1739
- 'type' => 'boolean',
1740
- 'default' => false
1741
- ),
1742
  'common.support' => array(
1743
  'type' => 'string',
1744
  'default' => ''
1745
  ),
1746
  'common.track_usage' => array(
1747
  'type' => 'boolean',
1748
- 'default' => true
1749
  ),
1750
  'common.tweeted' => array(
1751
  'type' => 'boolean',
@@ -1775,6 +1821,10 @@ $keys = array(
1775
  'type' => 'string',
1776
  'default' => ''
1777
  ),
 
 
 
 
1778
  'widget.pagespeed.show_in_admin_bar' => array(
1779
  'type' => 'boolean',
1780
  'default' => false
341
  'type' => 'boolean',
342
  'default' => false
343
  ),
344
+ // name backwards-compatible. in reality works for apache too
345
  'pgcache.cache.nginx_handle_xml' => array(
346
  'type' => 'boolean',
347
  'default' => false
431
  'index\.php'
432
  )
433
  ),
434
+ 'pgcache.reject.categories' => array(
435
+ 'type' => 'array',
436
+ 'default' => array()
437
+ ),
438
+ 'pgcache.reject.tags' => array(
439
+ 'type' => 'array',
440
+ 'default' => array()
441
+ ),
442
+ 'pgcache.reject.authors' => array(
443
+ 'type' => 'array',
444
+ 'default' => array()
445
+ ),
446
+ 'pgcache.reject.custom' => array(
447
+ 'type' => 'array',
448
+ 'default' => array()
449
+ ),
450
  'pgcache.reject.ua' => array(
451
  'type' => 'array',
452
  'default' => array()
549
  'type' => 'boolean',
550
  'default' => false
551
  ),
552
+ 'pgcache.cookiegroups.enabled' => array(
553
+ 'type' => 'boolean',
554
+ 'default' => false
555
+ ),
556
+ 'pgcache.cookiegroups.groups' => array(
557
+ 'type' => 'array',
558
+ 'default' => array(
559
+ 'mobile' => array(
560
+ 'enabled' => false,
561
+ 'cache' => true,
562
+ 'cookies' => array(
563
+ 'wptouch-pro-view=mobile',
564
+ 'wptouch-pro-cache-state=mobile'
565
+ )
566
+ ),
567
+ 'loggedin' => array(
568
+ 'enabled' => false,
569
+ 'cache' => true,
570
+ 'cookies' => array(
571
+ 'wordpress_logged_in_.*'
572
+ )
573
+ ),
574
+ 'subscribers' => array(
575
+ 'enabled' => false,
576
+ 'cache' => true,
577
+ 'cookies' => array(
578
+ 'role=subscriber',
579
+ 'role=member'
580
+ )
581
+ )
582
+ )
583
+ ),
584
 
585
  'stats.enabled' => array(
586
  'type' => 'boolean',
993
  ),
994
  'cdn.theme.files' => array(
995
  'type' => 'string',
996
+ 'default' => '*.css;*.js;*.gif;*.png;*.jpg;*.ico;*.ttf;*.otf;*.woff;*.woff2;*.less'
997
  ),
998
  'cdn.minify.enable' => array(
999
  'type' => 'boolean',
1046
  'type' => 'boolean',
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
1056
+ ),
1057
 
1058
  'cdn.ftp.host' => array(
1059
  'type' => 'string',
1142
  'type' => 'string',
1143
  'default' => ''
1144
  ),
1145
+ 'cdn.s3.bucket.location' => array(
1146
+ 'type' => 'string',
1147
+ 'default' => 'us-east-1'
1148
+ ),
1149
  'cdn.s3.cname' => array(
1150
  'type' => 'array',
1151
  'default' => array()
1172
  'type' => 'string',
1173
  'default' => ''
1174
  ),
1175
+ 'cdn.cf.bucket.location' => array(
1176
+ 'type' => 'string',
1177
+ 'default' => 'us-east-1'
1178
+ ),
1179
  'cdn.cf.id' => array(
1180
  'type' => 'string',
1181
  'default' => ''
1293
  'type' => 'string',
1294
  'default' => 'auto'
1295
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1296
  'cdn.maxcdn.authorization_key' => array(
1297
  'type' => 'string',
1298
  'default' => ''
1421
  'type' => 'boolean',
1422
  'default' => false
1423
  ),
1424
+ 'cdnfsd.enabled' => array(
1425
+ 'type' => 'boolean',
1426
+ 'default' => false
1427
+ ),
1428
+ 'cdnfsd.engine' => array(
1429
+ 'type' => 'string',
1430
+ 'default' => ''
1431
+ ),
1432
+ 'cdnfsd.debug' => array(
1433
+ 'type' => 'boolean',
1434
+ 'default' => false
1435
+ ),
1436
+
1437
  'varnish.configuration_overloaded' => array(
1438
  'type' => 'boolean',
1439
  'default' => false
1488
  ),
1489
  'browsercache.cssjs.expires' => array(
1490
  'type' => 'boolean',
1491
+ 'default' => true
1492
  ),
1493
  'browsercache.cssjs.lifetime' => array(
1494
  'type' => 'integer',
1496
  ),
1497
  'browsercache.cssjs.nocookies' => array(
1498
  'type' => 'boolean',
1499
+ 'default' => true
1500
  ),
1501
  'browsercache.cssjs.cache.control' => array(
1502
  'type' => 'boolean',
1508
  ),
1509
  'browsercache.cssjs.etag' => array(
1510
  'type' => 'boolean',
1511
+ 'default' => true
1512
  ),
1513
  'browsercache.cssjs.w3tc' => array(
1514
  'type' => 'boolean',
1548
  ),
1549
  'browsercache.html.etag' => array(
1550
  'type' => 'boolean',
1551
+ 'default' => true
1552
  ),
1553
  'browsercache.html.w3tc' => array(
1554
  'type' => 'boolean',
1568
  ),
1569
  'browsercache.other.expires' => array(
1570
  'type' => 'boolean',
1571
+ 'default' => true
1572
  ),
1573
  'browsercache.other.lifetime' => array(
1574
  'type' => 'integer',
1576
  ),
1577
  'browsercache.other.nocookies' => array(
1578
  'type' => 'boolean',
1579
+ 'default' => true
1580
  ),
1581
  'browsercache.other.cache.control' => array(
1582
  'type' => 'boolean',
1588
  ),
1589
  'browsercache.other.etag' => array(
1590
  'type' => 'boolean',
1591
+ 'default' => true
1592
  ),
1593
  'browsercache.other.w3tc' => array(
1594
  'type' => 'boolean',
1785
  ),
1786
 
1787
 
 
 
 
 
1788
  'common.support' => array(
1789
  'type' => 'string',
1790
  'default' => ''
1791
  ),
1792
  'common.track_usage' => array(
1793
  'type' => 'boolean',
1794
+ 'default' => false
1795
  ),
1796
  'common.tweeted' => array(
1797
  'type' => 'boolean',
1821
  'type' => 'string',
1822
  'default' => ''
1823
  ),
1824
+ 'widget.pagespeed.key.restrict.referrer' => array(
1825
+ 'type' => 'string',
1826
+ 'default' => ''
1827
+ ),
1828
  'widget.pagespeed.show_in_admin_bar' => array(
1829
  'type' => 'boolean',
1830
  'default' => false
ConfigState.php CHANGED
@@ -9,8 +9,6 @@ namespace W3TC;
9
  * common.install - time() of plugin installation
10
  * common.support_us_invitations - number of invitations to support us shown
11
  * common.next_support_us_invitation - time() of next support us invitation
12
- * common.edge_invitations
13
- * common.next_edge_invitation
14
  * common.hide_note_wp_content_permissions
15
  * common.hide_note_no_zlib
16
  * common.hide_note_zlib_output_compression
9
  * common.install - time() of plugin installation
10
  * common.support_us_invitations - number of invitations to support us shown
11
  * common.next_support_us_invitation - time() of next support us invitation
 
 
12
  * common.hide_note_wp_content_permissions
13
  * common.hide_note_no_zlib
14
  * common.hide_note_zlib_output_compression
ConfigUtil.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ class ConfigUtil {
5
+ static public function is_item_exists( $blog_id, $preview ) {
6
+ if ( defined( 'W3TC_CONFIG_DATABASE' ) && W3TC_CONFIG_DATABASE ) {
7
+ return ConfigDbStorage::is_item_exists( $blog_id, $preview );
8
+ }
9
+
10
+ return file_exists( Config::util_config_filename( 0, false ) );
11
+ }
12
+
13
+
14
+
15
+ static public function remove_item( $blog_id, $preview ) {
16
+ if ( defined( 'W3TC_CONFIG_DATABASE' ) && W3TC_CONFIG_DATABASE ) {
17
+ ConfigDbStorage::remove_item( $blog_id, $preview );
18
+ } else {
19
+ $filename = Config::util_config_filename( $blog_id, $preview );
20
+ @unlink( $filename );
21
+ }
22
+
23
+ if ( defined( 'W3TC_CONFIG_CACHE_ENGINE' ) ) {
24
+ ConfigCache::remove_item( $blog_id, $preview );
25
+ }
26
+ }
27
+
28
+
29
+
30
+ /**
31
+ * Deploys the config file from a preview config file
32
+ *
33
+ * @param integer $direction +1: preview->production
34
+ * -1: production->preview
35
+ * @param boolean $remove_source remove source file
36
+ */
37
+ static public function preview_production_copy( $blog_id, $direction ) {
38
+ if ( defined( 'W3TC_CONFIG_DATABASE' ) && W3TC_CONFIG_DATABASE ) {
39
+ ConfigDbStorage::preview_production_copy( $blog_id, $direction );
40
+ } else {
41
+ $preview_filename = Config::util_config_filename( $blog_id, true );
42
+ $production_filename = Config::util_config_filename( $blog_id, false );
43
+
44
+ if ( $direction > 0 ) {
45
+ $src = $preview_filename;
46
+ $dest = $production_filename;
47
+ } else {
48
+ $src = $production_filename;
49
+ $dest = $preview_filename;
50
+ }
51
+
52
+ if ( !@copy( $src, $dest ) ) {
53
+ Util_Activation::throw_on_write_error( $dest );
54
+ }
55
+ }
56
+
57
+ if ( defined( 'W3TC_CONFIG_CACHE_ENGINE' ) ) {
58
+ ConfigCache::remove_item( $blog_id, $preview );
59
+ }
60
+ }
61
+
62
+
63
+
64
+ static public function save_item( $blog_id, $preview, $data ) {
65
+ if ( defined( 'W3TC_CONFIG_DATABASE' ) && W3TC_CONFIG_DATABASE ) {
66
+ ConfigDbStorage::save_item( $blog_id, $preview, $data );
67
+ } else {
68
+ $filename = Config::util_config_filename( $blog_id, $preview );
69
+ if ( defined( 'JSON_PRETTY_PRINT' ) )
70
+ $config = json_encode( $data, JSON_PRETTY_PRINT );
71
+ else // for older php versions
72
+ $config = json_encode( $data );
73
+
74
+ Util_File::file_put_contents_atomic( $filename, '<?php exit; ?>' . $config );
75
+ }
76
+
77
+ if ( defined( 'W3TC_CONFIG_CACHE_ENGINE' ) ) {
78
+ ConfigCache::remove_item( $blog_id, $preview );
79
+ }
80
+ }
81
+ }
DbCache_Environment.php CHANGED
@@ -114,7 +114,7 @@ class DbCache_Environment {
114
  if ( isset( $_GET['page'] ) )
115
  $url = 'admin.php?page=' . $_GET['page'] . '&amp;';
116
  else
117
- $url = basename( Util_Environment::remove_query( $_SERVER['REQUEST_URI'] ) ) . '?page=w3tc_dashboard&amp;';
118
  $remove_url = Util_Ui::admin_url( $url . 'w3tc_default_remove_add_in=dbcache' );
119
  throw new Util_WpFile_FilesystemOperationException(
120
  sprintf( __( 'The Database add-in file db.php is not a W3 Total Cache drop-in.
@@ -151,6 +151,9 @@ class DbCache_Environment {
151
  * @return boolean
152
  */
153
  public function db_check_old_add_in() {
 
 
 
154
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_DB ) )
155
  && strstr( $script_data, 'w3_instance' ) !== false );
156
  }
@@ -161,6 +164,9 @@ class DbCache_Environment {
161
  * @return boolean
162
  */
163
  public function is_dbcache_add_in() {
 
 
 
164
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_DB ) )
165
  && strstr( $script_data, 'DbCache_Wpdb' ) !== false );
166
  }
114
  if ( isset( $_GET['page'] ) )
115
  $url = 'admin.php?page=' . $_GET['page'] . '&amp;';
116
  else
117
+ $url = basename( Util_Environment::remove_query_all( $_SERVER['REQUEST_URI'] ) ) . '?page=w3tc_dashboard&amp;';
118
  $remove_url = Util_Ui::admin_url( $url . 'w3tc_default_remove_add_in=dbcache' );
119
  throw new Util_WpFile_FilesystemOperationException(
120
  sprintf( __( 'The Database add-in file db.php is not a W3 Total Cache drop-in.
151
  * @return boolean
152
  */
153
  public function db_check_old_add_in() {
154
+ if ( !$this->db_installed() )
155
+ return false;
156
+
157
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_DB ) )
158
  && strstr( $script_data, 'w3_instance' ) !== false );
159
  }
164
  * @return boolean
165
  */
166
  public function is_dbcache_add_in() {
167
+ if ( !$this->db_installed() )
168
+ return false;
169
+
170
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_DB ) )
171
  && strstr( $script_data, 'DbCache_Wpdb' ) !== false );
172
  }
DbCache_Wpdb.php CHANGED
@@ -26,6 +26,11 @@ class DbCache_Wpdb extends DbCache_WpdbBase {
26
  $processors[] = new DbCache_WpdbInjection_QueryCaching();
27
  }
28
  if ( Util_Environment::is_dbcluster() ) {
 
 
 
 
 
29
  $processors[] = new Enterprise_Dbcache_WpdbInjection_Cluster();
30
  }
31
 
@@ -49,9 +54,9 @@ class DbCache_Wpdb extends DbCache_WpdbBase {
49
  return $instance;
50
  }
51
 
52
- private $processor_number;
53
  private $active_processor;
54
- private $active_processors;
55
 
56
  private $debug;
57
  private $request_time_start = 0;
@@ -60,6 +65,9 @@ class DbCache_Wpdb extends DbCache_WpdbBase {
60
  * @param boolean $call_default_constructor
61
  */
62
  public function __construct( $processors = null ) {
 
 
 
63
  // cant force empty parameter list due to wp requirements
64
  if ( !is_array( $processors ) )
65
  throw new Exception( 'called incorrectly, use instance()' );
@@ -130,6 +138,13 @@ class DbCache_Wpdb extends DbCache_WpdbBase {
130
  return $v;
131
  }
132
 
 
 
 
 
 
 
 
133
  /**
134
  * Initializes object after processors configured. Called from instance() only
135
  */
@@ -152,6 +167,10 @@ class DbCache_Wpdb extends DbCache_WpdbBase {
152
  return $this->active_processor->query( $query );
153
  }
154
 
 
 
 
 
155
  /**
156
  * Overriten logic of wp_db by processor.
157
  */
@@ -247,6 +266,10 @@ class DbCache_Wpdb extends DbCache_WpdbBase {
247
  return parent::query( $query );
248
  }
249
 
 
 
 
 
250
  /**
251
  * Default implementation, calls wp_db apropriate method
252
  */
@@ -397,6 +420,23 @@ class _CallUnderlying {
397
  }
398
  }
399
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
400
  /**
401
  * Calls underlying processor's aproptiate method of wp_db
402
  */
26
  $processors[] = new DbCache_WpdbInjection_QueryCaching();
27
  }
28
  if ( Util_Environment::is_dbcluster() ) {
29
+ // dbcluster use mysqli only since other is obsolete now
30
+ if ( !defined( 'WP_USE_EXT_MYSQL' ) ) {
31
+ define( 'WP_USE_EXT_MYSQL', false );
32
+ }
33
+
34
  $processors[] = new Enterprise_Dbcache_WpdbInjection_Cluster();
35
  }
36
 
54
  return $instance;
55
  }
56
 
57
+ private $active_processor_number;
58
  private $active_processor;
59
+ private $processors;
60
 
61
  private $debug;
62
  private $request_time_start = 0;
65
  * @param boolean $call_default_constructor
66
  */
67
  public function __construct( $processors = null ) {
68
+ // required to initialize $use_mysqli which is private
69
+ parent::__construct( '', '', '', '' );
70
+
71
  // cant force empty parameter list due to wp requirements
72
  if ( !is_array( $processors ) )
73
  throw new Exception( 'called incorrectly, use instance()' );
138
  return $v;
139
  }
140
 
141
+ function db_connect( $allow_bail = true ) {
142
+ if ( empty( $this->dbuser ) ) {
143
+ // skip connection - called from constructor
144
+ } else
145
+ return parent::db_connect( $allow_bail );
146
+ }
147
+
148
  /**
149
  * Initializes object after processors configured. Called from instance() only
150
  */
167
  return $this->active_processor->query( $query );
168
  }
169
 
170
+ function _escape( $data ) {
171
+ return $this->active_processor->_escape( $data );
172
+ }
173
+
174
  /**
175
  * Overriten logic of wp_db by processor.
176
  */
266
  return parent::query( $query );
267
  }
268
 
269
+ function default__escape( $data ) {
270
+ return parent::_escape( $data );
271
+ }
272
+
273
  /**
274
  * Default implementation, calls wp_db apropriate method
275
  */
420
  }
421
  }
422
 
423
+ /**
424
+ * Calls underlying processor's aproptiate method of wp_db
425
+ */
426
+ function _escape( $data ) {
427
+ $switched = $this->wpdb_mixin->switch_active_processor( 1 );
428
+
429
+ try {
430
+ $r = $this->wpdb_mixin->_escape( $data );
431
+
432
+ $this->wpdb_mixin->switch_active_processor( -$switched );
433
+ return $r;
434
+ } catch ( \Exception $e ) {
435
+ $this->wpdb_mixin->switch_active_processor( -$switched );
436
+ throw $e;
437
+ }
438
+ }
439
+
440
  /**
441
  * Calls underlying processor's aproptiate method of wp_db
442
  */
DbCache_WpdbInjection.php CHANGED
@@ -54,6 +54,14 @@ class DbCache_WpdbInjection {
54
  return $this->wpdb_mixin->default_query( $query );
55
  }
56
 
 
 
 
 
 
 
 
 
57
  /**
58
  * Placeholder for apropriate wp_db method replacement.
59
  * By default calls wp_db implementation
54
  return $this->wpdb_mixin->default_query( $query );
55
  }
56
 
57
+ /**
58
+ * Placeholder for apropriate wp_db method replacement.
59
+ * By default calls wp_db implementation
60
+ */
61
+ function _escape( $data ) {
62
+ return $this->wpdb_mixin->default__escape( $data );
63
+ }
64
+
65
  /**
66
  * Placeholder for apropriate wp_db method replacement.
67
  * By default calls wp_db implementation
DbCache_WpdbInjection_QueryCaching.php CHANGED
@@ -185,6 +185,10 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
185
  return $return_val;
186
  }
187
 
 
 
 
 
188
  /**
189
  * Initializes object, calls underlying processor
190
  */
@@ -612,9 +616,25 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
612
  }
613
 
614
  public function w3tc_footer_comment( $strings ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  if ( $this->debug ) {
 
616
  $strings[] = "Db cache debug info:";
617
- $strings[] = sprintf( "%s%s", str_pad( 'Engine: ', 20 ), Cache::engine_name( $this->_config->get_string( 'dbcache.engine' ) ) );
618
  $strings[] = sprintf( "%s%d", str_pad( 'Total queries: ', 20 ), $this->query_total );
619
  $strings[] = sprintf( "%s%d", str_pad( 'Cached queries: ', 20 ), $this->query_hits );
620
  $strings[] = sprintf( "%s%.4f", str_pad( 'Total query time: ', 20 ), $this->time_total );
@@ -639,22 +659,8 @@ class DbCache_WpdbInjection_QueryCaching extends DbCache_WpdbInjection {
639
  trim( $query['query'] ) );
640
  }
641
  }
642
- } else {
643
- $reason = $this->get_reject_reason();
644
- $append = ( $reason ? sprintf( ' (%s)', $reason ) : '' );
645
-
646
- if ( $this->query_hits ) {
647
- $strings[] = sprintf(
648
- __( 'Database Caching %d/%d queries in %.3f seconds using %s%s', 'w3-total-cache' ),
649
- $this->query_hits, $this->query_total, $this->time_total,
650
- Cache::engine_name( $this->_config->get_string( 'dbcache.engine' ) ),
651
- $append );
652
- } else {
653
- $strings[] = sprintf(
654
- __( 'Database Caching using %s%s', 'w3-total-cache' ),
655
- Cache::engine_name( $this->_config->get_string( 'dbcache.engine' ) ),
656
- $append );
657
- }
658
  }
659
 
660
  return $strings;
185
  return $return_val;
186
  }
187
 
188
+ function _escape( $data ) {
189
+ return $this->next_injection->_escape( $data );
190
+ }
191
+
192
  /**
193
  * Initializes object, calls underlying processor
194
  */
616
  }
617
 
618
  public function w3tc_footer_comment( $strings ) {
619
+ $reason = $this->get_reject_reason();
620
+ $append = ( $reason ? sprintf( ' (%s)', $reason ) : '' );
621
+
622
+ if ( $this->query_hits ) {
623
+ $strings[] = sprintf(
624
+ __( 'Database Caching %d/%d queries in %.3f seconds using %s%s', 'w3-total-cache' ),
625
+ $this->query_hits, $this->query_total, $this->time_total,
626
+ Cache::engine_name( $this->_config->get_string( 'dbcache.engine' ) ),
627
+ $append );
628
+ } else {
629
+ $strings[] = sprintf(
630
+ __( 'Database Caching using %s%s', 'w3-total-cache' ),
631
+ Cache::engine_name( $this->_config->get_string( 'dbcache.engine' ) ),
632
+ $append );
633
+ }
634
+
635
  if ( $this->debug ) {
636
+ $strings[] = '';
637
  $strings[] = "Db cache debug info:";
 
638
  $strings[] = sprintf( "%s%d", str_pad( 'Total queries: ', 20 ), $this->query_total );
639
  $strings[] = sprintf( "%s%d", str_pad( 'Cached queries: ', 20 ), $this->query_hits );
640
  $strings[] = sprintf( "%s%.4f", str_pad( 'Total query time: ', 20 ), $this->time_total );
659
  trim( $query['query'] ) );
660
  }
661
  }
662
+
663
+ $strings[] = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  }
665
 
666
  return $strings;
Dispatcher.php CHANGED
@@ -152,7 +152,7 @@ class Dispatcher {
152
  return '';
153
 
154
  return Util_RuleSnippet::canonical_without_location( $cdnftp,
155
- $add_header_rules );
156
  }
157
 
158
  /**
@@ -211,19 +211,6 @@ class Dispatcher {
211
  $cdn->headers_support() == W3TC_CDN_HEADER_MIRRORING );
212
  }
213
 
214
- /**
215
- * Checks whether canonical should be generated or not by browsercache plugin
216
- *
217
- * @param Config $config
218
- * @return string|null
219
- */
220
- static public function allow_origin_generated_by( $config ) {
221
- if ( $config->get_boolean( 'cdn.enabled' ) )
222
- return 'cdn';
223
-
224
- return null;
225
- }
226
-
227
  /**
228
  * If BrowserCache should generate rules specific for CDN. Used with CDN FTP
229
  *
152
  return '';
153
 
154
  return Util_RuleSnippet::canonical_without_location( $cdnftp,
155
+ $add_header_rules, $config->get_boolean( 'cdn.cors_header') );
156
  }
157
 
158
  /**
211
  $cdn->headers_support() == W3TC_CDN_HEADER_MIRRORING );
212
  }
213
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  /**
215
  * If BrowserCache should generate rules specific for CDN. Used with CDN FTP
216
  *
Enterprise_CacheFlush_MakeSnsEvent.php CHANGED
@@ -100,8 +100,11 @@ class Enterprise_CacheFlush_MakeSnsEvent extends Enterprise_SnsBase {
100
  * @param unknown $post_id
101
  * @return boolean
102
  */
103
- function flush_post( $post_id ) {
104
- return $this->_prepare_message( array( 'action' => 'flush_post', 'post_id' => $post_id ) );
 
 
 
105
  }
106
 
107
  /**
@@ -134,8 +137,11 @@ class Enterprise_CacheFlush_MakeSnsEvent extends Enterprise_SnsBase {
134
  * @param string $url
135
  * @return boolean
136
  */
137
- function flush_url( $url ) {
138
- return $this->_prepare_message( array( 'action' => 'flush_url', 'url' => $url ) );
 
 
 
139
  }
140
 
141
  /**
100
  * @param unknown $post_id
101
  * @return boolean
102
  */
103
+ function flush_post( $post_id, $extras = null ) {
104
+ return $this->_prepare_message( array(
105
+ 'action' => 'flush_post',
106
+ 'post_id' => $post_id,
107
+ 'extras' => $extras ) );
108
  }
109
 
110
  /**
137
  * @param string $url
138
  * @return boolean
139
  */
140
+ function flush_url( $url, $extras ) {
141
+ return $this->_prepare_message( array(
142
+ 'action' => 'flush_url',
143
+ 'url' => $url,
144
+ 'extras' => $extras ) );
145
  }
146
 
147
  /**
Enterprise_Dbcache_WpdbInjection_Cluster.php CHANGED
@@ -11,56 +11,56 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
11
  *
12
  * @var bool
13
  */
14
- var $check_tcp_responsiveness = true;
15
 
16
  /**
17
  * Minimum number of connections to try before bailing
18
  *
19
  * @var int
20
  */
21
- var $min_tries = 3;
22
 
23
  /**
24
  * Whether to use mysqli_connect with persistence
25
  *
26
  * @var bool
27
  */
28
- var $persistent = false;
29
 
30
  /**
31
  * Cache of tables-to-dataset mapping if blog_dataset callback defined
32
  *
33
  * @var array
34
  */
35
- var $_blog_to_dataset = array();
36
 
37
  /**
38
  * Optional directory of callbacks to determine datasets from queries
39
  *
40
  * @var array
41
  */
42
- var $_callbacks = array();
43
 
44
  /**
45
  * The multi-dimensional array of datasets and servers
46
  *
47
  * @var array
48
  */
49
- var $_cluster_servers = array();
50
 
51
  /**
52
  * Zone where application runs
53
  *
54
  * @var array
55
  */
56
- var $_current_zone = array( 'name' => 'all', 'zone_priorities' => array( 'all' ) );
57
 
58
  /**
59
  * Established connections
60
  *
61
  * @var array
62
  */
63
- var $_connections;
64
 
65
  /**
66
  * After any SQL_CALC_FOUND_ROWS query, the query "SELECT FOUND_ROWS()"
@@ -71,19 +71,19 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
71
  *
72
  * @var resource
73
  */
74
- var $_last_found_rows_result;
75
 
76
  /**
77
  * The last table that was queried
78
  *
79
  * @var string
80
  */
81
- var $_last_table;
82
 
83
  /**
84
  * Reject reason
85
  */
86
- var $_reject_reason = null;
87
 
88
  /**
89
  * Send Reads To Masters. This disables slave connections while true.
@@ -91,7 +91,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
91
  *
92
  * @var array
93
  */
94
- var $_send_reads_to_master = false;
95
 
96
 
97
  /**
@@ -99,21 +99,21 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
99
  *
100
  * @var bool
101
  */
102
- var $use_master_in_backend = true;
103
 
104
  /**
105
  * Which charset to use for connections
106
  *
107
  * @var string
108
  */
109
- var $charset = null;
110
 
111
  /**
112
  * Which collate to use for connections
113
  *
114
  * @var string
115
  */
116
- var $collate = null;
117
 
118
  /**
119
  * Initializes object
@@ -122,11 +122,13 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
122
  global $wpdb_cluster;
123
  $wpdb_cluster = $this;
124
 
125
- if ( file_exists( WP_CONTENT_DIR . '/db-cluster-config.php' ) ) {
 
 
126
  // The config file resides in WP_CONTENT_DIR
127
  require WP_CONTENT_DIR . '/db-cluster-config.php';
128
  } else {
129
- $this->_reject_reason = 'db-cluster-config.php configuration file not found, ' .
130
  'using single-server configuration';
131
  $this->next_injection->initialize();
132
  return;
@@ -141,6 +143,47 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
141
  $this->init_charset();
142
  }
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  /**
145
  * Sets default charset and collate
146
  * If DB_CHARSET not set uses utf8
@@ -312,7 +355,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
312
 
313
  // Try to reuse an existing connection
314
  $dbh = $this->_db_connect_reuse_connection();
315
- if ( is_resource( $dbh ) ) {
316
  $this->wpdb_mixin->dbh = $dbh;
317
  return $dbh;
318
  }
@@ -338,6 +381,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
338
  } while ( count( $servers ) < $this->min_tries );
339
  // Connect to a database server
340
  $success = false;
 
341
  $dbhname = $this->dbhname;
342
 
343
  foreach ( $servers as $zone_index ) {
@@ -365,15 +409,24 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
365
 
366
  $dbh = null;
367
  if ( is_null( $tcp_responded ) || $tcp_responded ) {
368
- $dbh = @mysqli_connect(
369
- ($this->persistent ? 'p:' : '') . $host . ':' . $port,
370
- $user, $password, true);
 
 
 
 
 
 
 
371
  }
372
 
373
  $elapsed = $this->wpdb_mixin->timer_stop();
374
 
375
- if ( is_resource( $dbh ) ) {
376
- if ( mysqli_select_db( $name, $dbh ) ) {
 
 
377
  $this->_connections[$dbhname] = array(
378
  'dbh' => $dbh,
379
  'database_name' => $name );
@@ -388,7 +441,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
388
  return $this->db_connect( $query, true );
389
  }
390
 
391
- return $this->wpdb_mixin->bail( "Unable to connect to $host:$port to $operation table '{$this->wpdb_mixin->table}' ($dataset)" );
392
  }
393
 
394
  $dbh = $this->_connections[$dbhname]['dbh'];
@@ -440,7 +493,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
440
  $connection = & $this->_connections[$dbhname];
441
  $dbh = $connection['dbh'];
442
 
443
- if ( !is_resource( $dbh ) )
444
  return null;
445
 
446
  if ( !mysqli_ping( $dbh ) ) {
@@ -466,13 +519,13 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
466
  $collate = $this->wpdb_mixin->collate;
467
  if ( $this->has_cap( 'collation', $dbh ) && !empty( $charset ) ) {
468
  if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset', $dbh ) ) {
469
- mysqli_set_charset( $charset, $dbh );
470
  $this->wpdb_mixin->real_escape = true;
471
  } else {
472
  $query = $this->wpdb_mixin->prepare( 'SET NAMES %s', $charset );
473
  if ( !empty( $collate ) )
474
  $query .= $this->wpdb_mixin->prepare( ' COLLATE %s', $collate );
475
- mysqli_query( $query, $dbh );
476
  }
477
  }
478
  }
@@ -511,18 +564,18 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
511
  $elapsed = 0;
512
  } else {
513
  $this->db_connect( $query );
514
- if ( !is_resource( $this->wpdb_mixin->dbh ) )
515
  return false;
516
 
517
  $this->wpdb_mixin->timer_start();
518
- $this->wpdb_mixin->result = mysqli_query( $query, $this->wpdb_mixin->dbh );
519
  $elapsed = $this->wpdb_mixin->timer_stop();
520
  ++$this->wpdb_mixin->num_queries;
521
 
522
  if ( preg_match( '/^\s*SELECT\s+SQL_CALC_FOUND_ROWS\s/i', $query ) ) {
523
  if ( false === strpos( $query, "NO_SELECT_FOUND_ROWS" ) ) {
524
  $this->wpdb_mixin->timer_start();
525
- $this->wpdb_mixin->_last_found_rows_result = mysqli_query( "SELECT FOUND_ROWS()", $this->wpdb_mixin->dbh );
526
  $elapsed += $this->wpdb_mixin->timer_stop();
527
  ++$this->wpdb_mixin->num_queries;
528
  $query .= "; SELECT FOUND_ROWS()";
@@ -566,8 +619,6 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
566
  $num_rows++;
567
  }
568
 
569
- @mysqli_free_result( $this->wpdb_mixin->result );
570
-
571
  // Log number of rows the query returned
572
  $this->num_rows = $num_rows;
573
 
@@ -576,6 +627,19 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
576
  }
577
  }
578
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
  /**
580
  * Whether or not MySQL database is at least the required minimum version.
581
  * The additional argument allows the caller to check a specific database.
@@ -633,14 +697,15 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
633
  * @return false|string false on failure, version number on success
634
  */
635
  function db_version( $dbh_or_table = false ) {
 
636
  if ( !$dbh_or_table && $this->wpdb_mixin->dbh )
637
  $dbh = $this->wpdb_mixin->dbh;
638
- elseif ( is_resource( $dbh_or_table ) )
639
  $dbh = $dbh_or_table;
640
  else
641
  $dbh = $this->db_connect( "SELECT FROM $dbh_or_table $this->wpdb_mixin->users" );
642
 
643
- if ( $dbh )
644
  return preg_replace( '/[^0-9.].*/', '', mysqli_get_server_info( $dbh ) );
645
  return false;
646
  }
@@ -653,7 +718,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
653
  function _disconnect( $dbhname ) {
654
  if ( isset( $this->_connections[$dbhname] ) ) {
655
  $dbh = $this->_connections[$dbhname]['dbh'];
656
- if ( is_resource( $dbh ) )
657
  mysqli_close( $dbh );
658
 
659
  unset( $this->_connections[$dbhname] );
@@ -773,7 +838,7 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
773
  * @return resource mysql database connection
774
  */
775
  function _db_connect_fallback() {
776
- if ( is_resource( $this->wpdb_mixin->dbh ) )
777
  return $this->wpdb_mixin->dbh;
778
  if ( !defined( 'DB_HOST' )
779
  || !defined( 'DB_USER' )
@@ -781,19 +846,27 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
781
  || !defined( 'DB_NAME' ) )
782
  return $this->wpdb_mixin->bail( "We were unable to query because there was no database defined." );
783
 
784
- $this->wpdb_mixin->dbh = @mysqli_connect(
785
- ( $this->persistent? 'p:': '' ) . DB_HOST, DB_USER, DB_PASSWORD,
786
- true );
 
 
 
 
 
 
 
 
787
 
788
- if ( !is_resource( $this->wpdb_mixin->dbh ) )
789
  return $this->wpdb_mixin->bail( "We were unable to connect to the database. (DB_HOST)" );
790
- if ( !mysqli_select_db( DB_NAME, $this->wpdb_mixin->dbh ) )
791
  return $this->wpdb_mixin->bail( "We were unable to select the database." );
792
  if ( !empty( $this->wpdb_mixin->charset ) ) {
793
  $collation_query = "SET NAMES '$this->wpdb_mixin->charset'";
794
  if ( !empty( $this->wpdb_mixin->collate ) )
795
  $collation_query .= " COLLATE '$this->wpdb_mixin->collate'";
796
- mysqli_query( $collation_query, $this->wpdb_mixin->dbh );
797
  }
798
 
799
  return $this->wpdb_mixin->dbh;
@@ -813,4 +886,4 @@ class Enterprise_Dbcache_WpdbInjection_Cluster extends DbCache_WpdbInjection {
813
 
814
  public function w3tc_usage_statistics_of_request( $storage ) {
815
  }
816
- }
11
  *
12
  * @var bool
13
  */
14
+ public $check_tcp_responsiveness = true;
15
 
16
  /**
17
  * Minimum number of connections to try before bailing
18
  *
19
  * @var int
20
  */
21
+ public $min_tries = 3;
22
 
23
  /**
24
  * Whether to use mysqli_connect with persistence
25
  *
26
  * @var bool
27
  */
28
+ public $persistent = false;
29
 
30
  /**
31
  * Cache of tables-to-dataset mapping if blog_dataset callback defined
32
  *
33
  * @var array
34
  */
35
+ private $_blog_to_dataset = array();
36
 
37
  /**
38
  * Optional directory of callbacks to determine datasets from queries
39
  *
40
  * @var array
41
  */
42
+ private $_callbacks = array();
43
 
44
  /**
45
  * The multi-dimensional array of datasets and servers
46
  *
47
  * @var array
48
  */
49
+ private $_cluster_servers = array();
50
 
51
  /**
52
  * Zone where application runs
53
  *
54
  * @var array
55
  */
56
+ private $_current_zone = array( 'name' => 'all', 'zone_priorities' => array( 'all' ) );
57
 
58
  /**
59
  * Established connections
60
  *
61
  * @var array
62
  */
63
+ private $_connections;
64
 
65
  /**
66
  * After any SQL_CALC_FOUND_ROWS query, the query "SELECT FOUND_ROWS()"
71
  *
72
  * @var resource
73
  */
74
+ private $_last_found_rows_result;
75
 
76
  /**
77
  * The last table that was queried
78
  *
79
  * @var string
80
  */
81
+ private $_last_table;
82
 
83
  /**
84
  * Reject reason
85
  */
86
+ private $_reject_reason = null;
87
 
88
  /**
89
  * Send Reads To Masters. This disables slave connections while true.
91
  *
92
  * @var array
93
  */
94
+ private $_send_reads_to_master = false;
95
 
96
 
97
  /**
99
  *
100
  * @var bool
101
  */
102
+ public $use_master_in_backend = true;
103
 
104
  /**
105
  * Which charset to use for connections
106
  *
107
  * @var string
108
  */
109
+ public $charset = null;
110
 
111
  /**
112
  * Which collate to use for connections
113
  *
114
  * @var string
115
  */
116
+ public $collate = null;
117
 
118
  /**
119
  * Initializes object
122
  global $wpdb_cluster;
123
  $wpdb_cluster = $this;
124
 
125
+ if ( isset( $GLOBALS['w3tc_dbcluster_config'] ) ) {
126
+ $this->apply_configuration( $GLOBALS['w3tc_dbcluster_config'] );
127
+ } elseif ( file_exists( WP_CONTENT_DIR . '/db-cluster-config.php' ) ) {
128
  // The config file resides in WP_CONTENT_DIR
129
  require WP_CONTENT_DIR . '/db-cluster-config.php';
130
  } else {
131
+ $this->_reject_reason = 'w3tc dbcluster configuration not found, ' .
132
  'using single-server configuration';
133
  $this->next_injection->initialize();
134
  return;
143
  $this->init_charset();
144
  }
145
 
146
+
147
+ /**
148
+ * Applies configuration from array
149
+ */
150
+ public function apply_configuration( $c ) {
151
+ if ( isset( $c['persistent'] ) ) {
152
+ $this->persistent = $c['persistent'];
153
+ }
154
+ if ( isset( $c['check_tcp_responsiveness'] ) ) {
155
+ $this->persistent = $c['check_tcp_responsiveness'];
156
+ }
157
+ if ( isset( $c['use_master_in_backend'] ) ) {
158
+ $this->persistent = $c['use_master_in_backend'];
159
+ }
160
+ if ( isset( $c['charset'] ) ) {
161
+ $this->persistent = $c['charset'];
162
+ }
163
+ if ( isset( $c['collate'] ) ) {
164
+ $this->persistent = $c['collate'];
165
+ }
166
+
167
+ if ( isset( $c['filters'] ) && is_array( $c['filters'] ) ) {
168
+ foreach ($c['filters'] as $filter) {
169
+ $this->add_callback( $filter['function_to_add'], $filter['tag'] );
170
+ }
171
+ }
172
+
173
+ if ( isset( $c['databases'] ) && is_array( $c['databases'] ) ) {
174
+ foreach ($c['databases'] as $key => $db) {
175
+ $this->add_database( $db );
176
+ }
177
+ }
178
+
179
+ if ( isset( $c['zones'] ) && is_array( $c['zones'] ) ) {
180
+ foreach ($c['zones'] as $key => $zone) {
181
+ $zone['name'] = $key;
182
+ $this->add_zone( $zone );
183
+ }
184
+ }
185
+ }
186
+
187
  /**
188
  * Sets default charset and collate
189
  * If DB_CHARSET not set uses utf8
355
 
356
  // Try to reuse an existing connection
357
  $dbh = $this->_db_connect_reuse_connection();
358
+ if ( is_object( $dbh ) ) {
359
  $this->wpdb_mixin->dbh = $dbh;
360
  return $dbh;
361
  }
381
  } while ( count( $servers ) < $this->min_tries );
382
  // Connect to a database server
383
  $success = false;
384
+ $errno = 0;
385
  $dbhname = $this->dbhname;
386
 
387
  foreach ( $servers as $zone_index ) {
409
 
410
  $dbh = null;
411
  if ( is_null( $tcp_responded ) || $tcp_responded ) {
412
+ $dbh = mysqli_init();
413
+
414
+ $socket = null;
415
+ $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
416
+
417
+ if ( WP_DEBUG ) {
418
+ mysqli_real_connect( $dbh, $host, $user, $password, null, $port, $socket, $client_flags );
419
+ } else {
420
+ @mysqli_real_connect( $dbh, $host, $user, $password, null, $port, $socket, $client_flags );
421
+ }
422
  }
423
 
424
  $elapsed = $this->wpdb_mixin->timer_stop();
425
 
426
+ if ( !is_null( $dbh ) ) {
427
+ if ( $dbh->connect_errno ) {
428
+ $errno = $dbh->connect_errno;
429
+ } elseif ( mysqli_select_db( $dbh, $name ) ) {
430
  $this->_connections[$dbhname] = array(
431
  'dbh' => $dbh,
432
  'database_name' => $name );
441
  return $this->db_connect( $query, true );
442
  }
443
 
444
+ return $this->wpdb_mixin->bail( "Unable to connect to $host:$port to $operation table '{$this->wpdb_mixin->table}' ($dataset) with $errno" );
445
  }
446
 
447
  $dbh = $this->_connections[$dbhname]['dbh'];
493
  $connection = & $this->_connections[$dbhname];
494
  $dbh = $connection['dbh'];
495
 
496
+ if ( !is_object( $dbh ) )
497
  return null;
498
 
499
  if ( !mysqli_ping( $dbh ) ) {
519
  $collate = $this->wpdb_mixin->collate;
520
  if ( $this->has_cap( 'collation', $dbh ) && !empty( $charset ) ) {
521
  if ( function_exists( 'mysqli_set_charset' ) && $this->has_cap( 'set_charset', $dbh ) ) {
522
+ mysqli_set_charset( $dbh, $charset );
523
  $this->wpdb_mixin->real_escape = true;
524
  } else {
525
  $query = $this->wpdb_mixin->prepare( 'SET NAMES %s', $charset );
526
  if ( !empty( $collate ) )
527
  $query .= $this->wpdb_mixin->prepare( ' COLLATE %s', $collate );
528
+ mysqli_query( $dbh, $query );
529
  }
530
  }
531
  }
564
  $elapsed = 0;
565
  } else {
566
  $this->db_connect( $query );
567
+ if ( !is_object( $this->wpdb_mixin->dbh ) )
568
  return false;
569
 
570
  $this->wpdb_mixin->timer_start();
571
+ $this->wpdb_mixin->result = mysqli_query( $this->wpdb_mixin->dbh, $query );
572
  $elapsed = $this->wpdb_mixin->timer_stop();
573
  ++$this->wpdb_mixin->num_queries;
574
 
575
  if ( preg_match( '/^\s*SELECT\s+SQL_CALC_FOUND_ROWS\s/i', $query ) ) {
576
  if ( false === strpos( $query, "NO_SELECT_FOUND_ROWS" ) ) {
577
  $this->wpdb_mixin->timer_start();
578
+ $this->wpdb_mixin->_last_found_rows_result = mysqli_query( $this->wpdb_mixin->dbh, "SELECT FOUND_ROWS()" );
579
  $elapsed += $this->wpdb_mixin->timer_stop();
580
  ++$this->wpdb_mixin->num_queries;
581
  $query .= "; SELECT FOUND_ROWS()";
619
  $num_rows++;
620
  }
621
 
 
 
622
  // Log number of rows the query returned
623
  $this->num_rows = $num_rows;
624
 
627
  }
628
  }
629
 
630
+ /**
631
+ * Usually it's called from inside other higher-level function
632
+ * so connection is available, but sometimes called directly.
633
+ * So connection should be initialized
634
+ **/
635
+ function _escape( $data ) {
636
+ if ( !$this->wpdb_mixin->dbh ) {
637
+ $this->db_connect( 'SELECT * FROM nothing' );
638
+ }
639
+
640
+ return $this->wpdb_mixin->default__escape( $data );
641
+ }
642
+
643
  /**
644
  * Whether or not MySQL database is at least the required minimum version.
645
  * The additional argument allows the caller to check a specific database.
697
  * @return false|string false on failure, version number on success
698
  */
699
  function db_version( $dbh_or_table = false ) {
700
+ $dbh = null;
701
  if ( !$dbh_or_table && $this->wpdb_mixin->dbh )
702
  $dbh = $this->wpdb_mixin->dbh;
703
+ elseif ( is_object( $dbh_or_table ) )
704
  $dbh = $dbh_or_table;
705
  else
706
  $dbh = $this->db_connect( "SELECT FROM $dbh_or_table $this->wpdb_mixin->users" );
707
 
708
+ if ( !is_null( $dbh ) )
709
  return preg_replace( '/[^0-9.].*/', '', mysqli_get_server_info( $dbh ) );
710
  return false;
711
  }
718
  function _disconnect( $dbhname ) {
719
  if ( isset( $this->_connections[$dbhname] ) ) {
720
  $dbh = $this->_connections[$dbhname]['dbh'];
721
+ if ( is_object( $dbh ) )
722
  mysqli_close( $dbh );
723
 
724
  unset( $this->_connections[$dbhname] );
838
  * @return resource mysql database connection
839
  */
840
  function _db_connect_fallback() {
841
+ if ( is_object( $this->wpdb_mixin->dbh ) )
842
  return $this->wpdb_mixin->dbh;
843
  if ( !defined( 'DB_HOST' )
844
  || !defined( 'DB_USER' )
846
  || !defined( 'DB_NAME' ) )
847
  return $this->wpdb_mixin->bail( "We were unable to query because there was no database defined." );
848
 
849
+ $this->wpdb_mixin->dbh = mysqli_init();
850
+
851
+ $port = null;
852
+ $socket = null;
853
+ $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
854
+
855
+ if ( WP_DEBUG ) {
856
+ mysqli_real_connect( $this->wpdb_mixin->dbh, DB_HOST, DB_USER, DB_PASSWORD, null, $port, $socket, $client_flags );
857
+ } else {
858
+ @mysqli_real_connect( $this->wpdb_mixin->dbh, $host, $user, $password, null, $port, $socket, $client_flags );
859
+ }
860
 
861
+ if ( !is_object( $this->wpdb_mixin->dbh ) )
862
  return $this->wpdb_mixin->bail( "We were unable to connect to the database. (DB_HOST)" );
863
+ if ( !mysqli_select_db( $this->wpdb_mixin->dbh, DB_NAME ) )
864
  return $this->wpdb_mixin->bail( "We were unable to select the database." );
865
  if ( !empty( $this->wpdb_mixin->charset ) ) {
866
  $collation_query = "SET NAMES '$this->wpdb_mixin->charset'";
867
  if ( !empty( $this->wpdb_mixin->collate ) )
868
  $collation_query .= " COLLATE '$this->wpdb_mixin->collate'";
869
+ mysqli_query( $this->wpdb_mixin->dbh, $collation_query );
870
  }
871
 
872
  return $this->wpdb_mixin->dbh;
886
 
887
  public function w3tc_usage_statistics_of_request( $storage ) {
888
  }
889
+ }
Extension_Amp_Plugin.php CHANGED
@@ -2,9 +2,9 @@
2
  namespace W3TC;
3
 
4
  class Extension_Amp_Plugin {
5
- function __construct() {
6
- $is_amp_endpoint = null;
7
- }
8
 
9
  public function run() {
10
  add_filter( 'w3tc_minify_js_enable',
@@ -67,10 +67,6 @@ class Extension_Amp_Plugin {
67
  }
68
 
69
  $queued_urls = array_merge( $queued_urls, $amp_urls );
70
-
71
- $filename = Util_Debug::log_filename( 'pagecache' );
72
- file_put_contents( $filename, "\nstart\n" . implode("\n", $queued_urls), FILE_APPEND );
73
-
74
  return $queued_urls;
75
  }
76
 
2
  namespace W3TC;
3
 
4
  class Extension_Amp_Plugin {
5
+ private $is_amp_endpoint = null;
6
+
7
+
8
 
9
  public function run() {
10
  add_filter( 'w3tc_minify_js_enable',
67
  }
68
 
69
  $queued_urls = array_merge( $queued_urls, $amp_urls );
 
 
 
 
70
  return $queued_urls;
71
  }
72
 
Extension_CloudFlare_Api.php CHANGED
@@ -181,7 +181,7 @@ class Extension_CloudFlare_Api {
181
  if ( is_null( $response_json ) || !isset( $response_json['success'] ) ) {
182
  throw new \Exception(
183
  'Failed to reach API endpoint, got unexpected response ' .
184
- $result['body'] );
185
  }
186
 
187
  if ( !$response_json['success'] ) {
181
  if ( is_null( $response_json ) || !isset( $response_json['success'] ) ) {
182
  throw new \Exception(
183
  'Failed to reach API endpoint, got unexpected response ' .
184
+ str_replace( '<', '.', str_replace( '>', '.', $result['body'] ) ) );
185
  }
186
 
187
  if ( !$response_json['success'] ) {
Extension_CloudFlare_Cdn_Page_View.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+ <form id="cdn_form" action="admin.php?page=w3tc_cdn" method="post">
9
+ <div class="metabox-holder">
10
+ <?php Util_Ui::postbox_header( __( 'Configuration: Full-Site Delivery', 'w3-total-cache' ),
11
+ '', 'configuration' ); ?>
12
+ <table class="form-table">
13
+ <tr>
14
+ <th style="width: 300px;">
15
+ <label>
16
+ <?php
17
+ _e( 'Configuration:',
18
+ 'w3-total-cache' );
19
+ ?>
20
+ </label>
21
+ </th>
22
+ <td>
23
+ <a href="admin.php?page=w3tc_extensions&extension=cloudflare&action=view">Open Configuration Page</a>
24
+ </td>
25
+ </tr>
26
+ </table>
27
+
28
+ <?php Util_Ui::button_config_save( 'cdn_configuration' ); ?>
29
+ <?php Util_Ui::postbox_footer(); ?>
30
+ </div>
31
+ </form>
Extension_CloudFlare_Page.php CHANGED
@@ -3,8 +3,10 @@ namespace W3TC;
3
 
4
  class Extension_CloudFlare_Page {
5
  static public function admin_print_scripts_w3tc_extensions() {
6
- if ( isset( $_REQUEST['extension'] ) &&
7
- $_REQUEST['extension'] == 'cloudflare' ) {
 
 
8
  wp_enqueue_script( 'w3tc_extension_cloudflare',
9
  plugins_url( 'Extension_CloudFlare_Page_View.js', W3TC_FILE ),
10
  array( 'jquery' ), '1.0' );
@@ -13,6 +15,12 @@ class Extension_CloudFlare_Page {
13
 
14
 
15
 
 
 
 
 
 
 
16
  static public function w3tc_extension_page_cloudflare() {
17
  $c = Dispatcher::config();
18
  $api = Extension_CloudFlare_SettingsForUi::api();
3
 
4
  class Extension_CloudFlare_Page {
5
  static public function admin_print_scripts_w3tc_extensions() {
6
+ if ( ( isset( $_REQUEST['extension'] ) &&
7
+ $_REQUEST['extension'] == 'cloudflare' ) ||
8
+ ( isset( $_REQUEST['page'] ) &&
9
+ $_REQUEST['page'] == 'w3tc_cdnfsd' ) ) {
10
  wp_enqueue_script( 'w3tc_extension_cloudflare',
11
  plugins_url( 'Extension_CloudFlare_Page_View.js', W3TC_FILE ),
12
  array( 'jquery' ), '1.0' );
15
 
16
 
17
 
18
+ static public function w3tc_settings_box_cdnfsd() {
19
+ include W3TC_DIR . '/Extension_CloudFlare_Cdn_Page_View.php';
20
+ }
21
+
22
+
23
+
24
  static public function w3tc_extension_page_cloudflare() {
25
  $c = Dispatcher::config();
26
  $api = Extension_CloudFlare_SettingsForUi::api();
Extension_CloudFlare_Plugin_Admin.php CHANGED
@@ -9,7 +9,7 @@ class Extension_CloudFlare_Plugin_Admin {
9
 
10
  static public function w3tc_extensions( $extensions, $config ) {
11
  $current_user = wp_get_current_user();
12
-
13
  $message = array();
14
  $message[] = 'CloudFlare';
15
  $cloudflare_signup_email = '';
@@ -64,6 +64,11 @@ class Extension_CloudFlare_Plugin_Admin {
64
  $widget->init();
65
 
66
  // modify settings page
 
 
 
 
 
67
  add_filter( 'w3tc_settings_general_anchors',
68
  array( $this, 'w3tc_settings_general_anchors' ) );
69
  add_action( 'w3tc_settings_general_boxarea_cloudflare',
@@ -73,10 +78,6 @@ class Extension_CloudFlare_Plugin_Admin {
73
  array( $this, 'action_cloudflare_api_request' ) );
74
 
75
  // modify main menu
76
- add_action( 'w3tc_extension_page_cloudflare', array(
77
- '\W3TC\Extension_CloudFlare_Page',
78
- 'w3tc_extension_page_cloudflare'
79
- ) );
80
  add_filter( 'w3tc_admin_bar_menu', array( $this, 'w3tc_admin_bar_menu' ) );
81
 
82
  // dashboard
@@ -85,13 +86,31 @@ class Extension_CloudFlare_Plugin_Admin {
85
  add_filter( 'w3tc_admin_actions', array( $this, 'w3tc_admin_actions' ) );
86
 
87
  // own settings page
 
 
 
 
88
  add_action( 'admin_print_scripts-performance_page_w3tc_extensions',
89
  array( '\W3TC\Extension_CloudFlare_Page',
90
  'admin_print_scripts_w3tc_extensions'
91
  ) );
 
92
  add_action( 'w3tc_ajax',
93
  array( '\W3TC\Extension_CloudFlare_Popup', 'w3tc_ajax' ) );
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  // add check to comments page
96
  add_filter( 'comment_row_actions', array( $this, 'comment_row_actions' ),
97
  10, 2 );
@@ -119,7 +138,7 @@ class Extension_CloudFlare_Plugin_Admin {
119
 
120
 
121
 
122
- function admin_notices() {
123
  $plugins = get_plugins();
124
  if ( array_key_exists( 'cloudflare/cloudflare.php', $plugins ) && $this->_config->get_boolean( 'notes.cloudflare_plugin' ) ) {
125
 
@@ -289,6 +308,39 @@ class Extension_CloudFlare_Plugin_Admin {
289
 
290
 
291
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  public function w3tc_settings_general_anchors( $anchors ) {
293
  $anchors[] = array( 'id' => 'cloudflare', 'text' => 'CloudFlare' );
294
  return $anchors;
9
 
10
  static public function w3tc_extensions( $extensions, $config ) {
11
  $current_user = wp_get_current_user();
12
+
13
  $message = array();
14
  $message[] = 'CloudFlare';
15
  $cloudflare_signup_email = '';
64
  $widget->init();
65
 
66
  // modify settings page
67
+ add_filter( 'w3tc_ui_config_item_cdnfsd.enabled',
68
+ array( $this, 'w3tc_ui_config_item_cdnfsd_enabled' ) );
69
+ add_filter( 'w3tc_ui_config_item_cdnfsd.engine',
70
+ array( $this, 'w3tc_ui_config_item_cdnfsd_engine' ) );
71
+
72
  add_filter( 'w3tc_settings_general_anchors',
73
  array( $this, 'w3tc_settings_general_anchors' ) );
74
  add_action( 'w3tc_settings_general_boxarea_cloudflare',
78
  array( $this, 'action_cloudflare_api_request' ) );
79
 
80
  // modify main menu
 
 
 
 
81
  add_filter( 'w3tc_admin_bar_menu', array( $this, 'w3tc_admin_bar_menu' ) );
82
 
83
  // dashboard
86
  add_filter( 'w3tc_admin_actions', array( $this, 'w3tc_admin_actions' ) );
87
 
88
  // own settings page
89
+ add_action( 'w3tc_extension_page_cloudflare', array(
90
+ '\W3TC\Extension_CloudFlare_Page',
91
+ 'w3tc_extension_page_cloudflare'
92
+ ) );
93
  add_action( 'admin_print_scripts-performance_page_w3tc_extensions',
94
  array( '\W3TC\Extension_CloudFlare_Page',
95
  'admin_print_scripts_w3tc_extensions'
96
  ) );
97
+
98
  add_action( 'w3tc_ajax',
99
  array( '\W3TC\Extension_CloudFlare_Popup', 'w3tc_ajax' ) );
100
 
101
+ $cdnfsd_engine = $c->get_string( 'cdnfsd.engine' );
102
+
103
+ if ( empty( $cdnfsd_engine ) || $cdnfsd_engine == 'cloudflare' ) {
104
+ add_action( 'w3tc_settings_box_cdnfsd', array(
105
+ '\W3TC\Extension_CloudFlare_Page',
106
+ 'w3tc_settings_box_cdnfsd'
107
+ ) );
108
+ add_action( 'admin_print_scripts-performance_page_w3tc_cdn',
109
+ array( '\W3TC\Extension_CloudFlare_Page',
110
+ 'admin_print_scripts_w3tc_extensions'
111
+ ) );
112
+ }
113
+
114
  // add check to comments page
115
  add_filter( 'comment_row_actions', array( $this, 'comment_row_actions' ),
116
  10, 2 );
138
 
139
 
140
 
141
+ public function admin_notices() {
142
  $plugins = get_plugins();
143
  if ( array_key_exists( 'cloudflare/cloudflare.php', $plugins ) && $this->_config->get_boolean( 'notes.cloudflare_plugin' ) ) {
144
 
308
 
309
 
310
 
311
+ public function w3tc_ui_config_item_cdnfsd_enabled( $a ) {
312
+ $c = Dispatcher::config();
313
+ $cdnfsd_engine = $c->get_string( 'cdnfsd.engine' );
314
+
315
+ // overwrite behavior if controlled by extension
316
+ if ( empty( $cdnfsd_engine ) || $cdnfsd_engine == 'cloudflare' ) {
317
+ $a['value'] = true;
318
+ }
319
+
320
+ return $a;
321
+ }
322
+
323
+
324
+
325
+ public function w3tc_ui_config_item_cdnfsd_engine( $a ) {
326
+ $c = Dispatcher::config();
327
+ $cdnfsd_engine = $c->get_string( 'cdnfsd.engine' );
328
+
329
+ // overwrite behavior if controlled by extension
330
+ if ( empty( $cdnfsd_engine ) || $cdnfsd_engine == 'cloudflare' ) {
331
+ $a['value'] = 'cloudflare';
332
+ }
333
+
334
+ if ( isset( $a['selectbox_values']['cloudflare'] ) ) {
335
+ $a['selectbox_values']['cloudflare']['label'] = 'CloudFlare';
336
+ $a['selectbox_values']['cloudflare']['disabled'] = null;
337
+ }
338
+
339
+ return $a;
340
+ }
341
+
342
+
343
+
344
  public function w3tc_settings_general_anchors( $anchors ) {
345
  $anchors[] = array( 'id' => 'cloudflare', 'text' => 'CloudFlare' );
346
  return $anchors;
Extension_CloudFlare_Popup_View_Zones.php CHANGED
@@ -5,8 +5,8 @@ if ( !defined( 'W3TC' ) )
5
  die();
6
  ?>
7
  <form action="admin.php?page=w3tc_cdn" method="post" style="padding: 20px"
8
- class="w3tc_extension_cloudflare_form">
9
- <?php
10
  Util_Ui::hidden( '', 'w3tc_action', 'extension_cloudflare_zones_done' );
11
  Util_Ui::hidden( '', 'email', $details['email'] );
12
  Util_Ui::hidden( '', 'key', $details['key'] );
@@ -14,46 +14,48 @@ Util_Ui::hidden( '', 'page', '' );
14
  echo Util_Ui::nonce_field( 'w3tc' );
15
 
16
  ?>
17
- <?php
18
  if ( isset( $details['error_message'] ) )
19
  echo '<div class="error">' . $details['error_message'] . '</div>';
20
 
21
  ?>
22
- <div class="metabox-holder">
23
- <?php Util_Ui::postbox_header( __( 'Select zone', 'w3-total-cache' ) ); ?>
24
- <table class="form-table">
25
- <tr>
26
- <td>Zone:</td>
27
- <td>
28
- <?php foreach ( $details['zones'] as $z ): ?>
29
- <label>
30
- <input name="zone_id" type="radio" class="w3tc-ignore-change"
31
- value="<?php echo $z['id'] ?>" />
32
- <?php echo htmlspecialchars( $z['name'] ) ?>
33
- </label><br />
34
- <?php endforeach ?>
35
- </tr>
36
- <tr>
37
- <td></td>
38
- <td>
39
- <?php
40
- if ( $details['total_pages'] > 1 ):
41
- for ( $page = 1; $page <= $details['total_pages']; $page++ ):
42
- if ( $page == $details['page']):
43
- echo $page;
44
- else: ?>
45
- <a href="#" class="w3tc_cloudflare_zone_page" data-page="<?php echo $page ?>"><?php echo $page ?></a>
46
- <?php endif ?>
47
- &nbsp;
48
- <?php endfor ?>
49
- <?php endif ?>
50
- </table>
 
 
51
 
52
- <p class="submit">
53
- <input type="button"
54
- class="w3tc_popup_submit w3tc-button-save button-primary"
55
- value="<?php _e( 'Next', 'w3-total-cache' ); ?>" />
56
- </p>
57
- <?php Util_Ui::postbox_footer(); ?>
58
- </div>
59
  </form>
5
  die();
6
  ?>
7
  <form action="admin.php?page=w3tc_cdn" method="post" style="padding: 20px"
8
+ class="w3tc_extension_cloudflare_form">
9
+ <?php
10
  Util_Ui::hidden( '', 'w3tc_action', 'extension_cloudflare_zones_done' );
11
  Util_Ui::hidden( '', 'email', $details['email'] );
12
  Util_Ui::hidden( '', 'key', $details['key'] );
14
  echo Util_Ui::nonce_field( 'w3tc' );
15
 
16
  ?>
17
+ <?php
18
  if ( isset( $details['error_message'] ) )
19
  echo '<div class="error">' . $details['error_message'] . '</div>';
20
 
21
  ?>
22
+ <div class="metabox-holder">
23
+ <?php Util_Ui::postbox_header( __( 'Select zone', 'w3-total-cache' ) ); ?>
24
+ <table class="form-table">
25
+ <tr>
26
+ <td>Zone:</td>
27
+ <td>
28
+ <?php foreach ( $details['zones'] as $z ): ?>
29
+ <label>
30
+ <input name="zone_id" type="radio" class="w3tc-ignore-change"
31
+ value="<?php echo $z['id'] ?>" />
32
+ <?php echo htmlspecialchars( $z['name'] ) ?>
33
+ </label><br />
34
+ <?php endforeach ?>
35
+ </tr>
36
+ <tr>
37
+ <td></td>
38
+ <td>
39
+ <?php
40
+ if ( $details['total_pages'] > 1 ):
41
+ for ( $page = 1; $page <= $details['total_pages']; $page++ ):
42
+ if ( $page == $details['page']):
43
+ echo $page;
44
+ else: ?>
45
+ <a href="#" class="w3tc_cloudflare_zone_page" data-page="<?php echo $page ?>"><?php echo $page ?></a>
46
+ <?php endif ?>
47
+ &nbsp;
48
+ <?php endfor ?>
49
+ <?php endif ?>
50
+ </td>
51
+ </tr>
52
+ </table>
53
 
54
+ <p class="submit">
55
+ <input type="button"
56
+ class="w3tc_popup_submit w3tc-button-save button-primary"
57
+ value="<?php _e( 'Next', 'w3-total-cache' ); ?>" />
58
+ </p>
59
+ <?php Util_Ui::postbox_footer(); ?>
60
+ </div>
61
  </form>
Extension_CloudFlare_SettingsForUi.php CHANGED
@@ -89,8 +89,8 @@ class Extension_CloudFlare_SettingsForUi {
89
  $current_value = $settings[$settings_key]['value'];
90
 
91
  // convert checkbox value to on/off
92
- // excetion: rocket loader is not checkbox so contains real value
93
- if ( $settings_key != 'rocket_loader' ) {
94
  if ( $current_value == 'on' || $current_value == 'off' ) {
95
  // it's boolean, so control is checkbox - convert it
96
  $value = ( $value == '0' ? 'off' : 'on' );
89
  $current_value = $settings[$settings_key]['value'];
90
 
91
  // convert checkbox value to on/off
92
+ // exception: rocket loader, ssl is not checkbox so contains real value
93
+ if ( $settings_key != 'rocket_loader' && $settings_key != 'ssl' ) {
94
  if ( $current_value == 'on' || $current_value == 'off' ) {
95
  // it's boolean, so control is checkbox - convert it
96
  $value = ( $value == '0' ? 'off' : 'on' );
Extension_FragmentCache_Plugin_Admin.php CHANGED
@@ -92,14 +92,13 @@ class Extension_FragmentCache_Plugin_Admin {
92
 
93
 
94
  public function w3tc_admin_menu( $menu ) {
95
- $menu = array_merge( $menu, array(
96
- 'w3tc_fragmentcache' => array(
97
- 'page_title' => __( 'Fragment Cache', 'w3-total-cache' ),
98
- 'menu_text' => '<span class="w3tc_menu_item_pro">' .
99
- __( 'Fragment Cache', 'w3-total-cache' ) . '</span>',
100
- 'visible_always' => false
101
- )
102
- ) );
103
 
104
  return $menu;
105
  }
92
 
93
 
94
  public function w3tc_admin_menu( $menu ) {
95
+ $menu['w3tc_fragmentcache'] = array(
96
+ 'page_title' => __( 'Fragment Cache', 'w3-total-cache' ),
97
+ 'menu_text' => '<span class="w3tc_menu_item_pro">' .
98
+ __( 'Fragment Cache', 'w3-total-cache' ) . '</span>',
99
+ 'visible_always' => false,
100
+ 'order' => 1100
101
+ );
 
102
 
103
  return $menu;
104
  }
Extension_FragmentCache_WpObjectCache.php CHANGED
@@ -571,15 +571,20 @@ class Extension_FragmentCache_WpObjectCache {
571
  * @return string
572
  */
573
  public function w3tc_footer_comment( $strings ) {
 
 
 
 
 
 
 
 
 
574
  if ( $this->_config->get_boolean( array( 'fragmentcache', 'debug' ) ) ) {
575
- $strings[] = "Fragment Cache debug info:";
576
- $strings[] = sprintf( "%s%s", str_pad( 'Engine: ', 20 ), Cache::engine_name( $this->_config->get_string( array( 'fragmentcache', 'engine' ) ) ) );
577
  $strings[] = sprintf( "%s%s", str_pad( 'Caching: ', 20 ), ( $this->_caching ? 'enabled' : 'disabled' ) );
578
 
579
- if ( !$this->_caching ) {
580
- $strings[] = sprintf( "%s%s", str_pad( 'Reject reason: ', 20 ), $this->cache_reject_reason );
581
- }
582
-
583
  $strings[] = sprintf( "%s%d", str_pad( 'Total calls: ', 20 ), $this->cache_total );
584
  $strings[] = sprintf( "%s%d", str_pad( 'Cache hits: ', 20 ), $this->cache_hits );
585
  $strings[] = sprintf( "%s%d", str_pad( 'Cache misses: ', 20 ), $this->cache_misses );
@@ -609,15 +614,7 @@ class Extension_FragmentCache_WpObjectCache {
609
  str_pad( ( $debug['group'] == 'transient' ? 'site' : 'network' ), 10, ' ', STR_PAD_LEFT ),
610
  $debug['id'] );
611
  }
612
- } else {
613
- $append = ( $this->cache_reject_reason != '' ?
614
- sprintf( ' (%s)', $this->cache_reject_reason ) :'' );
615
-
616
- $strings[] = sprintf(
617
- __( 'Fragment Caching %d/%d fragments using %s%s', 'w3-total-cache' ),
618
- $this->cache_hits, $this->cache_total,
619
- Cache::engine_name( $this->_config->get_string( array( 'fragmentcache', 'engine' ) ) ),
620
- $append );
621
  }
622
 
623
  return $strings;
571
  * @return string
572
  */
573
  public function w3tc_footer_comment( $strings ) {
574
+ $append = ( $this->cache_reject_reason != '' ?
575
+ sprintf( ' (%s)', $this->cache_reject_reason ) :'' );
576
+
577
+ $strings[] = sprintf(
578
+ __( 'Fragment Caching %d/%d fragments using %s%s', 'w3-total-cache' ),
579
+ $this->cache_hits, $this->cache_total,
580
+ Cache::engine_name( $this->_config->get_string( array( 'fragmentcache', 'engine' ) ) ),
581
+ $append );
582
+
583
  if ( $this->_config->get_boolean( array( 'fragmentcache', 'debug' ) ) ) {
584
+ $strings[] = '';
585
+ $strings[] = 'Fragment Cache debug info:';
586
  $strings[] = sprintf( "%s%s", str_pad( 'Caching: ', 20 ), ( $this->_caching ? 'enabled' : 'disabled' ) );
587
 
 
 
 
 
588
  $strings[] = sprintf( "%s%d", str_pad( 'Total calls: ', 20 ), $this->cache_total );
589
  $strings[] = sprintf( "%s%d", str_pad( 'Cache hits: ', 20 ), $this->cache_hits );
590
  $strings[] = sprintf( "%s%d", str_pad( 'Cache misses: ', 20 ), $this->cache_misses );
614
  str_pad( ( $debug['group'] == 'transient' ? 'site' : 'network' ), 10, ' ', STR_PAD_LEFT ),
615
  $debug['id'] );
616
  }
617
+ $strings[] = '';
 
 
 
 
 
 
 
 
618
  }
619
 
620
  return $strings;
Extension_NewRelic_Plugin.php CHANGED
@@ -70,22 +70,34 @@ class Extension_NewRelic_Plugin {
70
  function ob_callback_browser( $buffer ) {
71
  $core = Dispatcher::component( 'Extension_NewRelic_Core' );
72
  $app = $core->get_effective_browser_application();
73
- if ( isset( $app['loader_script'] ) && !$this->_should_disable_auto_rum() ) {
74
  $buffer = preg_replace( '~<head(\s+[^>]*)*>~Ui',
75
  '\\0' . $app['loader_script'], $buffer, 1 );
76
  }
77
 
 
 
 
 
 
78
  return $buffer;
79
  }
80
 
81
  function ob_callback_apm( $buffer ) {
82
- if ( $this->_config->get_boolean( array( 'newrelic', 'include_rum' ) ) ) {
83
- if ( ( $this->_config->get_boolean( 'browsercache.html.compression' ) ||
84
- $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' ) && !$this->_should_disable_auto_rum() ) {
 
85
  $buffer = preg_replace( '~<head(\s+[^>]*)*>~Ui', '\\0' . \NewRelicWrapper::get_browser_timing_header(), $buffer, 1 );
86
  $buffer = preg_replace( '~<\\/body>~', \NewRelicWrapper::get_browser_timing_footer() . '\\0', $buffer, 1 );
87
  }
88
  }
 
 
 
 
 
 
89
  return $buffer;
90
  }
91
 
@@ -103,12 +115,19 @@ class Extension_NewRelic_Plugin {
103
  \NewRelicWrapper::disable_auto_rum();
104
  }
105
 
106
- function _should_disable_auto_rum() {
 
 
 
 
 
 
 
107
  $reject_reason = apply_filters( 'w3tc_newrelic_should_disable_auto_rum', null );
108
  if ( !empty( $reject_reason ) ) {
109
  $this->newrelic_reject_reason =
110
  __( 'rejected by filter: ', 'w3-total-cache' ) . $reject_reason;
111
- return true;
112
  }
113
 
114
 
@@ -118,7 +137,7 @@ class Extension_NewRelic_Plugin {
118
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
119
  $this->newrelic_reject_reason = __( 'DOING_AJAX constant is defined', 'w3-total-cache' );
120
 
121
- return true;
122
  }
123
 
124
 
@@ -128,7 +147,7 @@ class Extension_NewRelic_Plugin {
128
  if ( defined( 'DONOTAUTORUM' ) && DONOTAUTORUM ) {
129
  $this->newrelic_reject_reason = __( 'DONOTAUTORUM constant is defined', 'w3-total-cache' );
130
 
131
- return true;
132
  }
133
 
134
  /**
@@ -139,10 +158,10 @@ class Extension_NewRelic_Plugin {
139
  $this->newrelic_reject_reason = __( 'logged in role is rejected',
140
  'w3-total-cache' );
141
 
142
- return true;
143
  }
144
 
145
- return false;
146
  }
147
 
148
  /**
@@ -183,11 +202,9 @@ class Extension_NewRelic_Plugin {
183
  }
184
 
185
  public function w3tc_footer_comment( $strings ) {
186
- $append = ( $this->newrelic_reject_reason != '' ) ?
187
- sprintf( ' (%s)', $this->newrelic_reject_reason ) : '';
188
  $strings[] = sprintf(
189
  __( "Application Monitoring using New Relic%s", 'w3-total-cache' ),
190
- $append );
191
 
192
  return $strings;
193
  }
70
  function ob_callback_browser( $buffer ) {
71
  $core = Dispatcher::component( 'Extension_NewRelic_Core' );
72
  $app = $core->get_effective_browser_application();
73
+ if ( isset( $app['loader_script'] ) && $this->_can_add_tracker_script( $buffer ) ) {
74
  $buffer = preg_replace( '~<head(\s+[^>]*)*>~Ui',
75
  '\\0' . $app['loader_script'], $buffer, 1 );
76
  }
77
 
78
+ $buffer = str_replace('{w3tc_newrelic_reject_reason}',
79
+ ( $this->newrelic_reject_reason != '' ? sprintf( ' (%s)', $this->newrelic_reject_reason )
80
+ : '' ),
81
+ $buffer );
82
+
83
  return $buffer;
84
  }
85
 
86
  function ob_callback_apm( $buffer ) {
87
+ if ( !$this->_can_add_tracker_script( $buffer ) ) {
88
+ $this->disable_auto_rum();
89
+ } else {
90
+ if ( $this->_config->get_boolean( array( 'newrelic', 'include_rum' ) ) ) {
91
  $buffer = preg_replace( '~<head(\s+[^>]*)*>~Ui', '\\0' . \NewRelicWrapper::get_browser_timing_header(), $buffer, 1 );
92
  $buffer = preg_replace( '~<\\/body>~', \NewRelicWrapper::get_browser_timing_footer() . '\\0', $buffer, 1 );
93
  }
94
  }
95
+
96
+ $buffer = str_replace('{w3tc_newrelic_reject_reason}',
97
+ ( $this->newrelic_reject_reason != '' ? sprintf( ' (%s)', $this->newrelic_reject_reason )
98
+ : '' ),
99
+ $buffer );
100
+
101
  return $buffer;
102
  }
103
 
115
  \NewRelicWrapper::disable_auto_rum();
116
  }
117
 
118
+ function _can_add_tracker_script( $buffer ) {
119
+ //
120
+ $v = '';
121
+ if ( preg_match('~^\s*<\?xml[^>]*>\s*<xsl:stylesheet~', $buffer, $v ) ) {
122
+ $this->newrelic_reject_reason = __( 'XSL not tracked', 'w3-total-cache' );
123
+ return false;
124
+ }
125
+
126
  $reject_reason = apply_filters( 'w3tc_newrelic_should_disable_auto_rum', null );
127
  if ( !empty( $reject_reason ) ) {
128
  $this->newrelic_reject_reason =
129
  __( 'rejected by filter: ', 'w3-total-cache' ) . $reject_reason;
130
+ return false;
131
  }
132
 
133
 
137
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
138
  $this->newrelic_reject_reason = __( 'DOING_AJAX constant is defined', 'w3-total-cache' );
139
 
140
+ return false;
141
  }
142
 
143
 
147
  if ( defined( 'DONOTAUTORUM' ) && DONOTAUTORUM ) {
148
  $this->newrelic_reject_reason = __( 'DONOTAUTORUM constant is defined', 'w3-total-cache' );
149
 
150
+ return false;
151
  }
152
 
153
  /**
158
  $this->newrelic_reject_reason = __( 'logged in role is rejected',
159
  'w3-total-cache' );
160
 
161
+ return false;
162
  }
163
 
164
+ return true;
165
  }
166
 
167
  /**
202
  }
203
 
204
  public function w3tc_footer_comment( $strings ) {
 
 
205
  $strings[] = sprintf(
206
  __( "Application Monitoring using New Relic%s", 'w3-total-cache' ),
207
+ '{w3tc_newrelic_reject_reason}' );
208
 
209
  return $strings;
210
  }
Extension_NewRelic_Plugin_Admin.php CHANGED
@@ -88,13 +88,12 @@ class Extension_NewRelic_Plugin_Admin {
88
  $c = Dispatcher::config();
89
  $monitoring_type = $c->get_string( array( 'newrelic', 'monitoring_type' ) );
90
  if ( $monitoring_type == 'apm' ) {
91
- $menu = array_merge( $menu, array(
92
- 'w3tc_monitoring' => array(
93
- 'page_title' => __( 'Monitoring', 'w3-total-cache' ),
94
- 'menu_text' => __( 'Monitoring', 'w3-total-cache' ),
95
- 'visible_always' => false
96
- )
97
- ) );
98
  }
99
 
100
  return $menu;
88
  $c = Dispatcher::config();
89
  $monitoring_type = $c->get_string( array( 'newrelic', 'monitoring_type' ) );
90
  if ( $monitoring_type == 'apm' ) {
91
+ $menu['w3tc_monitoring'] = array(
92
+ 'page_title' => __( 'Monitoring', 'w3-total-cache' ),
93
+ 'menu_text' => __( 'Monitoring', 'w3-total-cache' ),
94
+ 'visible_always' => false,
95
+ 'order' => 1200
96
+ );
 
97
  }
98
 
99
  return $menu;
Extension_NewRelic_Popup_View.js CHANGED
@@ -6,7 +6,7 @@ jQuery(function($) {
6
  close: '',
7
  width: 800,
8
  height: 400,
9
- url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
10
  '&w3tc_action=newrelic_popup',
11
  });
12
  })
@@ -14,8 +14,8 @@ jQuery(function($) {
14
 
15
 
16
  .on('click', '.w3tcnr_list_applications', function() {
17
- var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
18
- '&w3tc_action=newrelic_list_applications&api_key=' +
19
  encodeURIComponent($('.w3tcnr_api_key').val());
20
  W3tc_Lightbox.load(url);
21
  })
@@ -23,26 +23,26 @@ jQuery(function($) {
23
 
24
 
25
  .on('click', '.w3tcnr_apply_configuration', function() {
26
- var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
27
  '&w3tc_action=newrelic_apply_configuration';
28
  $('.w3tcnr_form').find('input').each(function(i) {
29
  var name = $(this).attr('name');
30
  var type = $(this).attr('type');
31
  if (type == 'radio') {
32
- if (!$(this).attr('checked'))
33
  return;
34
  }
35
 
36
  if (name)
37
- url += '&' + encodeURIComponent(name) + '=' +
38
  encodeURIComponent($(this).val());
39
  });
40
  $('.w3tcnr_form').find('select').each(function(i) {
41
  var name = $(this).attr('name');
42
- url += '&' + encodeURIComponent(name) + '=' +
43
  encodeURIComponent($(this).val());
44
  });
45
 
46
  W3tc_Lightbox.load(url);
47
  });
48
- });
6
  close: '',
7
  width: 800,
8
  height: 400,
9
+ url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
10
  '&w3tc_action=newrelic_popup',
11
  });
12
  })
14
 
15
 
16
  .on('click', '.w3tcnr_list_applications', function() {
17
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
18
+ '&w3tc_action=newrelic_list_applications&api_key=' +
19
  encodeURIComponent($('.w3tcnr_api_key').val());
20
  W3tc_Lightbox.load(url);
21
  })
23
 
24
 
25
  .on('click', '.w3tcnr_apply_configuration', function() {
26
+ var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
27
  '&w3tc_action=newrelic_apply_configuration';
28
  $('.w3tcnr_form').find('input').each(function(i) {
29
  var name = $(this).attr('name');
30
  var type = $(this).attr('type');
31
  if (type == 'radio') {
32
+ if (!$(this).prop('checked'))
33
  return;
34
  }
35
 
36
  if (name)
37
+ url += '&' + encodeURIComponent(name) + '=' +
38
  encodeURIComponent($(this).val());
39
  });
40
  $('.w3tcnr_form').find('select').each(function(i) {
41
  var name = $(this).attr('name');
42
+ url += '&' + encodeURIComponent(name) + '=' +
43
  encodeURIComponent($(this).val());
44
  });
45
 
46
  W3tc_Lightbox.load(url);
47
  });
48
+ });
Extension_Swarmify_Page.php CHANGED
@@ -3,14 +3,7 @@ namespace W3TC;
3
 
4
 
5
 
6
- class Extension_Swarmify_Page extends Base_Page_Settings {
7
- /**
8
- * Current page
9
- */
10
- protected $_page = 'w3tc_swarmify';
11
-
12
-
13
-
14
  public function render_content() {
15
  $config = Dispatcher::config();
16
 
3
 
4
 
5
 
6
+ class Extension_Swarmify_Page {
 
 
 
 
 
 
 
7
  public function render_content() {
8
  $config = Dispatcher::config();
9
 
Extension_WordPressSeo_Plugin_Admin.php CHANGED
@@ -3,23 +3,11 @@ namespace W3TC;
3
 
4
  class Extension_WordPressSeo_Plugin_Admin {
5
  function run() {
6
- add_action( 'admin_init', array( $this, 'admin_init' ) );
7
  add_filter( 'w3tc_extension_plugin_links_wordpress-seo', array( $this, 'remove_settings' ) );
8
  add_action( 'w3tc_activate_extension_wordpress-seo', array( $this, 'activate' ) );
9
  add_action( 'w3tc_deactivate_extension_wordpress-seo', array( $this, 'deactivate' ) );
10
  }
11
 
12
- public function admin_init() {
13
- $config = Dispatcher::config();
14
- $groups = $config->get_array( 'mobile.rgroups' );
15
- if ( Util_Environment::is_w3tc_edge( $config ) &&
16
- isset( $groups['google'] ) &&
17
- sizeof( $groups['google']['agents'] ) == 1 &&
18
- $groups['google']['agents'][0] == 'googlebot' ) {
19
- w3tc_delete_user_agent_group( 'google' );
20
- }
21
- }
22
-
23
  /**
24
  *
25
  *
3
 
4
  class Extension_WordPressSeo_Plugin_Admin {
5
  function run() {
 
6
  add_filter( 'w3tc_extension_plugin_links_wordpress-seo', array( $this, 'remove_settings' ) );
7
  add_action( 'w3tc_activate_extension_wordpress-seo', array( $this, 'activate' ) );
8
  add_action( 'w3tc_deactivate_extension_wordpress-seo', array( $this, 'deactivate' ) );
9
  }
10
 
 
 
 
 
 
 
 
 
 
 
 
11
  /**
12
  *
13
  *
Extensions_Plugin_Admin.php CHANGED
@@ -99,14 +99,14 @@ class Extensions_Plugin_Admin {
99
  * @return array
100
  */
101
  public function w3tc_admin_menu( $menu ) {
102
- $menu_item = array(
103
- 'w3tc_extensions' => array(
104
- 'page_title' => __( 'Extensions', 'w3-total-cache' ),
105
- 'menu_text' => __( 'Extensions', 'w3-total-cache' ),
106
- 'visible_always' => false
107
- )
108
  );
109
- return array_merge( $menu, $menu_item );
 
110
  }
111
 
112
  /**
99
  * @return array
100
  */
101
  public function w3tc_admin_menu( $menu ) {
102
+ $menu['w3tc_extensions'] = array(
103
+ 'page_title' => __( 'Extensions', 'w3-total-cache' ),
104
+ 'menu_text' => __( 'Extensions', 'w3-total-cache' ),
105
+ 'visible_always' => false,
106
+ 'order' => 1900
 
107
  );
108
+
109
+ return $menu;
110
  }
111
 
112
  /**
Generic_AdminActions_Config.php CHANGED
@@ -89,7 +89,7 @@ class Generic_AdminActions_Config {
89
  * @return void
90
  */
91
  function w3tc_config_preview_enable() {
92
- $this->preview_production_copy( -1 );
93
  Util_Environment::set_preview( true );
94
 
95
  Util_Admin::redirect( array(
@@ -104,9 +104,7 @@ class Generic_AdminActions_Config {
104
  */
105
  function w3tc_config_preview_disable() {
106
  $blog_id = Util_Environment::blog_id();
107
- $preview_filename = Config::util_config_filename( $blog_id, true );
108
- @unlink( $preview_filename );
109
-
110
  Util_Environment::set_preview( false );
111
 
112
  Util_Admin::redirect( array(
@@ -120,7 +118,7 @@ class Generic_AdminActions_Config {
120
  * @return void
121
  */
122
  function w3tc_config_preview_deploy() {
123
- $this->preview_production_copy( 1 );
124
  Util_Environment::set_preview( false );
125
 
126
  Util_Admin::redirect( array(
@@ -130,34 +128,6 @@ class Generic_AdminActions_Config {
130
 
131
 
132
 
133
- /**
134
- * Deploys the config file from a preview config file
135
- *
136
- * @param integer $direction +1: preview->production
137
- * -1: production->preview
138
- * @param boolean $remove_source remove source file
139
- */
140
- private function preview_production_copy( $direction = 1 ) {
141
- $blog_id = Util_Environment::blog_id();
142
-
143
- $preview_filename = Config::util_config_filename( $blog_id, true );
144
- $production_filename = Config::util_config_filename( $blog_id, false );
145
-
146
- if ( $direction > 0 ) {
147
- $src = $preview_filename;
148
- $dest = $production_filename;
149
- } else {
150
- $src = $production_filename;
151
- $dest = $preview_filename;
152
- }
153
-
154
- if ( !@copy( $src, $dest ) ) {
155
- Util_Activation::throw_on_write_error( $dest );
156
- }
157
- }
158
-
159
-
160
-
161
  /**
162
  * Save dbcluster config action
163
  *
@@ -195,11 +165,11 @@ class Generic_AdminActions_Config {
195
  $this->_config->set( 'common.tweeted', $tweeted );
196
  if ( $track_usage )
197
  $this->_config->set( 'common.track_usage', true );
 
 
198
 
199
  if ( $signmeup ) {
200
- if ( Util_Environment::is_w3tc_enterprise( $this->_config ) )
201
- $license = 'enterprise';
202
- elseif ( Util_Environment::is_w3tc_pro( $this->_config ) )
203
  $license = 'pro';
204
  else
205
  $license = 'community';
89
  * @return void
90
  */
91
  function w3tc_config_preview_enable() {
92
+ ConfigUtil::preview_production_copy( Util_Environment::blog_id(), -1 );
93
  Util_Environment::set_preview( true );
94
 
95
  Util_Admin::redirect( array(
104
  */
105
  function w3tc_config_preview_disable() {
106
  $blog_id = Util_Environment::blog_id();
107
+ ConfigUtil::remove_item( $blog_id, true );
 
 
108
  Util_Environment::set_preview( false );
109
 
110
  Util_Admin::redirect( array(
118
  * @return void
119
  */
120
  function w3tc_config_preview_deploy() {
121
+ ConfigUtil::preview_production_copy( Util_Environment::blog_id(), 1 );
122
  Util_Environment::set_preview( false );
123
 
124
  Util_Admin::redirect( array(
128
 
129
 
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  /**
132
  * Save dbcluster config action
133
  *
165
  $this->_config->set( 'common.tweeted', $tweeted );
166
  if ( $track_usage )
167
  $this->_config->set( 'common.track_usage', true );
168
+ else
169
+ $this->_config->set( 'common.track_usage', false );
170
 
171
  if ( $signmeup ) {
172
+ if ( Util_Environment::is_w3tc_pro( $this->_config ) )
 
 
173
  $license = 'pro';
174
  else
175
  $license = 'community';
Generic_AdminActions_Default.php CHANGED
@@ -317,7 +317,8 @@ class Generic_AdminActions_Default {
317
  }
318
 
319
  // todo: move to cdn module
320
- if ( in_array( $engine = $this->_config->get_string( 'cdn.engine' ), array( 'netdna', 'maxcdn' ) ) ) {
 
321
  require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
322
  $keys = explode( '+', $this->_config->get_string( 'cdn.'.$engine.'.authorization_key' ) );
323
  if ( sizeof( $keys ) == 3 ) {
@@ -548,11 +549,13 @@ class Generic_AdminActions_Default {
548
  break;
549
 
550
  case 'maxcdn':
551
- $config->set( 'cdn.maxcdn.domain', $cdn_domains );
552
- break;
 
 
 
553
 
554
- case 'netdna':
555
- $config->set( 'cdn.netdna.domain', $cdn_domains );
556
  break;
557
 
558
  case 'cotendo':
@@ -740,7 +743,7 @@ class Generic_AdminActions_Default {
740
  array_map( 'stripslashes_deep', $request_value );
741
  else
742
  $request_value = stripslashes( $request_value );
743
- if ( strpos( $request_key, 'memcached_servers' ) )
744
  $request_value = explode( ',', $request_value );
745
 
746
  $key = Util_Ui::config_key_from_http_name( $request_key );
317
  }
318
 
319
  // todo: move to cdn module
320
+ $engine = $this->_config->get_string( 'cdn.engine' );
321
+ if ( $engine == 'maxcdn' ) {
322
  require_once W3TC_LIB_NETDNA_DIR . '/NetDNA.php';
323
  $keys = explode( '+', $this->_config->get_string( 'cdn.'.$engine.'.authorization_key' ) );
324
  if ( sizeof( $keys ) == 3 ) {
549
  break;
550
 
551
  case 'maxcdn':
552
+ $v = $config->get( 'cdn.maxcdn.domain' );
553
+ if ( isset( $v['http_default'] ) )
554
+ $cdn_domains['http_default'] = $v['http_default'];
555
+ if ( isset( $v['https_default'] ) )
556
+ $cdn_domains['https_default'] = $v['https_default'];
557
 
558
+ $config->set( 'cdn.maxcdn.domain', $cdn_domains );
 
559
  break;
560
 
561
  case 'cotendo':
743
  array_map( 'stripslashes_deep', $request_value );
744
  else
745
  $request_value = stripslashes( $request_value );
746
+ if ( strpos( $request_key, 'memcached__servers' ) || strpos( $request_key, 'redis__servers' ) )
747
  $request_value = explode( ',', $request_value );
748
 
749
  $key = Util_Ui::config_key_from_http_name( $request_key );
Generic_AdminActions_EdgeMode.php DELETED
@@ -1,28 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
-
5
-
6
- class Generic_AdminActions_EdgeMode {
7
-
8
- private $_config = null;
9
-
10
- function __construct() {
11
- $this->_config = Dispatcher::config();
12
- }
13
-
14
- public function w3tc_edge_mode_enable() {
15
- $this->_config->set( 'common.edge', true );
16
- $this->_config->set( 'common.track_usage', true );
17
- $this->_config->save();
18
-
19
- Util_Admin::redirect( array( 'w3tc_note' => 'enabled_edge' ) );
20
- }
21
-
22
- public function w3tc_edge_mode_disable() {
23
- $this->_config->set( 'common.edge', false );
24
- $this->_config->save();
25
-
26
- Util_Admin::redirect( array( 'w3tc_note' => 'disabled_edge' ) );
27
- }
28
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Generic_AdminActions_Flush.php CHANGED
@@ -16,7 +16,7 @@ class Generic_AdminActions_Flush {
16
  * @return void
17
  */
18
  function w3tc_flush_all() {
19
- w3tc_flush_all();
20
  $this->_redirect_after_flush( 'flush_all' );
21
  }
22
 
16
  * @return void
17
  */
18
  function w3tc_flush_all() {
19
+ w3tc_flush_all( array( 'ui_action' => 'flush_button' ) );
20
  $this->_redirect_after_flush( 'flush_all' );
21
  }
22
 
Generic_AdminActions_Test.php CHANGED
@@ -39,6 +39,8 @@ class Generic_AdminActions_Test {
39
  */
40
  function w3tc_test_redis() {
41
  $servers = Util_Request::get_array( 'servers' );
 
 
42
 
43
  if ( count( $servers ) <= 0 )
44
  $success = false;
@@ -48,7 +50,9 @@ class Generic_AdminActions_Test {
48
  foreach ( $servers as $server ) {
49
  @$cache = Cache::instance( 'redis', array(
50
  'servers' => $server,
51
- 'persistent' => false
 
 
52
  ) );
53
  if ( is_null( $cache ) )
54
  $success = false;
@@ -204,7 +208,9 @@ class Generic_AdminActions_Test {
204
 
205
  $config = Dispatcher::config();
206
  $key = $config->get_string( 'widget.pagespeed.key' );
207
- $w3_pagespeed = new PageSpeed_Api( $key );
 
 
208
 
209
  $results = $w3_pagespeed->analyze( get_home_url() );
210
  include W3TC_INC_POPUP_DIR . '/pagespeed_results.php';
39
  */
40
  function w3tc_test_redis() {
41
  $servers = Util_Request::get_array( 'servers' );
42
+ $password = Util_Request::get_string('password', '');
43
+ $dbid = Util_Request::get_integer( 'dbid', 0 );
44
 
45
  if ( count( $servers ) <= 0 )
46
  $success = false;
50
  foreach ( $servers as $server ) {
51
  @$cache = Cache::instance( 'redis', array(
52
  'servers' => $server,
53
+ 'persistent' => false,
54
+ 'password' => $password,
55
+ 'dbid' => $dbid
56
  ) );
57
  if ( is_null( $cache ) )
58
  $success = false;
208
 
209
  $config = Dispatcher::config();
210
  $key = $config->get_string( 'widget.pagespeed.key' );
211
+ $ref = $config->get_string( 'widget.pagespeed.key.restrict.referrer' );
212
+
213
+ $w3_pagespeed = new PageSpeed_Api( $key, $ref );
214
 
215
  $results = $w3_pagespeed->analyze( get_home_url() );
216
  include W3TC_INC_POPUP_DIR . '/pagespeed_results.php';
Generic_ConfigLabels.php CHANGED
@@ -11,6 +11,7 @@ class Generic_ConfigLabels {
11
  'cluster.messagebus.sns.topic_arn' => __( 'Topic <acronym title="Identification">ID</acronym>:', 'w3-total-cache' ),
12
  'cluster.messagebus.debug' => __( 'Message Bus', 'w3-total-cache' ),
13
  'widget.pagespeed.key' => __( 'Page Speed <acronym title="Application Programming Interface">API</acronym> Key:', 'w3-total-cache' ),
 
14
  'common.force_master' => __( 'Use single network configuration file for all sites.', 'w3-total-cache' ),
15
  'config.path' => __( 'Nginx server configuration file path', 'w3-total-cache' ),
16
  'config.check' => __( 'Verify rewrite rules', 'w3-total-cache' ),
11
  'cluster.messagebus.sns.topic_arn' => __( 'Topic <acronym title="Identification">ID</acronym>:', 'w3-total-cache' ),
12
  'cluster.messagebus.debug' => __( 'Message Bus', 'w3-total-cache' ),
13
  'widget.pagespeed.key' => __( 'Page Speed <acronym title="Application Programming Interface">API</acronym> Key:', 'w3-total-cache' ),
14
+ 'widget.pagespeed.key.restrict.referrer' => __( 'Key Restriction (Referrer):', 'w3-total-cache' ),
15
  'common.force_master' => __( 'Use single network configuration file for all sites.', 'w3-total-cache' ),
16
  'config.path' => __( 'Nginx server configuration file path', 'w3-total-cache' ),
17
  'config.check' => __( 'Verify rewrite rules', 'w3-total-cache' ),
Generic_Environment.php CHANGED
@@ -22,20 +22,18 @@ class Generic_Environment {
22
  $this->add_index_to_folders();
23
 
24
  if ( count( $exs->exceptions() ) <= 0 ) {
25
- $f = file_exists( Config::util_config_filename( 0, false ) );
 
26
  $f2 = file_exists( Config::util_config_filename_legacy_v2( 0, false ) );
27
 
28
  $c = Dispatcher::config_master();
29
  if ( ( $f || $f2 ) && $c->is_compiled() ) {
30
  $c->save();
31
- $f = file_exists( Config::util_config_filename( 0, false ) );
32
  }
33
 
34
  if ( $f && $f2 )
35
  @unlink( Config::util_config_filename_legacy_v2( 0, false ) );
36
-
37
- if ( !$f && !$f2 && $config->get_integer( 'common.instance_id', 0 ) == 0 )
38
- $this->notify_no_config_present( $config, $exs );
39
  }
40
 
41
  if ( count( $exs->exceptions() ) > 0 )
@@ -134,10 +132,13 @@ class Generic_Environment {
134
  private function create_required_folders( $exs ) {
135
  // folders that we create if not exists
136
  $directories = array(
137
- W3TC_CACHE_DIR,
138
- W3TC_CONFIG_DIR
139
  );
140
 
 
 
 
 
141
  foreach ( $directories as $directory ) {
142
  try{
143
  Util_WpFile::create_writeable_folder( $directory, WP_CONTENT_DIR );
@@ -178,26 +179,6 @@ class Generic_Environment {
178
  }
179
  }
180
 
181
- /**
182
- * Check config file
183
- *
184
- * @param Config $config
185
- * @param Util_Environment_Exceptions $exs
186
- */
187
- private function notify_no_config_present( $config, $exs ) {
188
- $onclick = 'document.location.href=\'' .
189
- addslashes( wp_nonce_url(
190
- 'admin.php?page=w3tc_general&w3tc_save_options', 'w3tc' ) ) .
191
- '\';';
192
- $button = '<input type="button" class="button w3tc" ' .
193
- 'value="save the settings" onclick="' . $onclick . '" />';
194
-
195
- $exs->push( new Util_Environment_Exception( '<strong>W3 Total Cache:</strong> ' .
196
- 'Default settings are in use. The configuration file could ' .
197
- 'not be read or doesn\'t exist. Please ' . $button .
198
- ' to create the file.' ) );
199
- }
200
-
201
  /**
202
  * Returns true if advanced-cache.php is installed
203
  *
22
  $this->add_index_to_folders();
23
 
24
  if ( count( $exs->exceptions() ) <= 0 ) {
25
+ // save actual version of config is it's built on legacy configs
26
+ $f = ConfigUtil::is_item_exists( 0, false );
27
  $f2 = file_exists( Config::util_config_filename_legacy_v2( 0, false ) );
28
 
29
  $c = Dispatcher::config_master();
30
  if ( ( $f || $f2 ) && $c->is_compiled() ) {
31
  $c->save();
32
+ $f = ConfigUtil::is_item_exists( 0, false );
33
  }
34
 
35
  if ( $f && $f2 )
36
  @unlink( Config::util_config_filename_legacy_v2( 0, false ) );
 
 
 
37
  }
38
 
39
  if ( count( $exs->exceptions() ) > 0 )
132
  private function create_required_folders( $exs ) {
133
  // folders that we create if not exists
134
  $directories = array(
135
+ W3TC_CACHE_DIR
 
136
  );
137
 
138
+ if ( !(defined( 'W3TC_CONFIG_DATABASE' ) && W3TC_CONFIG_DATABASE ) ) {
139
+ $directories[] = W3TC_CONFIG_DIR;
140
+ }
141
+
142
  foreach ( $directories as $directory ) {
143
  try{
144
  Util_WpFile::create_writeable_folder( $directory, WP_CONTENT_DIR );
179
  }
180
  }
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  /**
183
  * Returns true if advanced-cache.php is installed
184
  *
Generic_Faq.php CHANGED
@@ -31,8 +31,6 @@ class Generic_Faq {
31
 
32
  self::parse_file( $faq, 'faq', '', '' );
33
 
34
- if ( Util_Environment::is_w3tc_edge( $config ) )
35
- self::parse_file( $faq, 'faq-edge', 'edge', '<b>Edge:</b> ' );
36
  if ( Util_Environment::is_w3tc_pro( $config ) )
37
  self::parse_file( $faq, 'faq-pro', 'pro', '<b>Pro:</b> ' );
38
 
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
 
Generic_GeneralPage_View_ShowEdge.js CHANGED
@@ -4,8 +4,8 @@ jQuery(function() {
4
  id:'w3tc-overlay',
5
  close: '',
6
  width: 800,
7
- height: 210,
8
- url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
9
  '&w3tc_action=generic_edge'
10
  });
11
- });
4
  id:'w3tc-overlay',
5
  close: '',
6
  width: 800,
7
+ height: 240,
8
+ url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
9
  '&w3tc_action=generic_edge'
10
  });
11
+ });
Generic_GeneralPage_View_ShowSupportUs.js CHANGED
@@ -4,7 +4,10 @@ jQuery(function() {
4
  close: '',
5
  width: 800,
6
  height: 445,
7
- url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
8
- '&w3tc_action=generic_support_us'
 
 
 
9
  });
10
- });
4
  close: '',
5
  width: 800,
6
  height: 445,
7
+ url: ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
8
+ '&w3tc_action=generic_support_us',
9
+ callback: function(lightbox) {
10
+ jQuery(".palette-twitter").click(function() {jQuery("#tweeted").val("1");});
11
+ }
12
  });
13
+ });
Generic_Page_Dashboard_View.css CHANGED
@@ -32,15 +32,15 @@
32
  #w3tc-dashboard-widgets div.postbox,
33
  #w3tc-dashboard-widgets #postbox-container-3 .hndle,
34
  #w3tc-dashboard-widgets #postbox-container-3 .inside,
35
- #w3tc-dashboard-widgets #postbox-container-3 .meta-box-sortables
36
- #w3tc-dashboard-widgets #postbox-container-3 .widefat{
37
  background: none;
38
  }
39
  #w3tc-dashboard-widgets #postbox-container-3 .postbox,
40
  #w3tc-dashboard-widgets #postbox-container-3 .hndle,
41
  #w3tc-dashboard-widgets #postbox-container-3 .inside,
42
- #w3tc-dashboard-widgets #postbox-container-3 .meta-box-sortables
43
- #w3tc-dashboard-widgets #postbox-container-3 .widefat{
44
  border:none;
45
  }
46
  #w3tc-dashboard-widgets {
@@ -94,13 +94,6 @@
94
  background: url("pub/img/w3tc_google-logo.png") 0 3px no-repeat;
95
  }
96
 
97
- .w3tc-widget-netdna-logo {
98
- float: left;
99
- width: 150px;
100
- height: 35px;
101
- background: url("pub/img/w3tc_netdna-logo.png") 0 5px no-repeat;
102
- }
103
-
104
  .w3tc-widget-maxcdn-logo {
105
  width: 150px;
106
  height: 35px;
@@ -112,6 +105,34 @@
112
  float:left;
113
  margin-right:10px;
114
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  /**
116
  * HiDPI Displays
117
  */
@@ -159,13 +180,5 @@ only screen and ( min-resolution: 2dppx) {
159
  background-image: url("pub/img/w3tc_netdna-logo-retina.png");
160
  background-size: 177px 90px;
161
  }
162
-
163
- .w3tc-widget-maxcdn-logo{
164
- float: left;
165
- width: 180px;
166
- height: 90px;
167
- background-image: url("pub/img/w3tc_maxcdn-logo-retina.png");
168
- background-size: 468px 90px;
169
- }
170
  }
171
- */
32
  #w3tc-dashboard-widgets div.postbox,
33
  #w3tc-dashboard-widgets #postbox-container-3 .hndle,
34
  #w3tc-dashboard-widgets #postbox-container-3 .inside,
35
+ #w3tc-dashboard-widgets #postbox-container-3 .meta-box-sortables,
36
+ #w3tc-dashboard-widgets #postbox-container-3 .widefat {
37
  background: none;
38
  }
39
  #w3tc-dashboard-widgets #postbox-container-3 .postbox,
40
  #w3tc-dashboard-widgets #postbox-container-3 .hndle,
41
  #w3tc-dashboard-widgets #postbox-container-3 .inside,
42
+ #w3tc-dashboard-widgets #postbox-container-3 .meta-box-sortables,
43
+ #w3tc-dashboard-widgets #postbox-container-3 .widefat {
44
  border:none;
45
  }
46
  #w3tc-dashboard-widgets {
94
  background: url("pub/img/w3tc_google-logo.png") 0 3px no-repeat;
95
  }
96
 
 
 
 
 
 
 
 
97
  .w3tc-widget-maxcdn-logo {
98
  width: 150px;
99
  height: 35px;
105
  float:left;
106
  margin-right:10px;
107
  }
108
+
109
+ @media only screen and (max-device-width: 480px) {
110
+ #w3tc-dashboard-widgets #postbox-container-left {
111
+ margin-right: 0px;
112
+ }
113
+ #w3tc-dashboard-widgets {
114
+ min-width: auto;
115
+ }
116
+ #postbox-container-right {
117
+ width: 100%;
118
+ white-space: nowrap;
119
+ float: left;
120
+ margin-left: 0px;
121
+ }
122
+ #w3tc-dashboard-widgets {
123
+ background: none;
124
+ }
125
+ #w3tc-dashboard-widgets #normal-sortables .postbox {
126
+ width: 100%;
127
+ }
128
+ .w3tc_generic_widgetservice_label {
129
+ display: inline;
130
+ }
131
+ #cdn_maxcdn_authorization_key {
132
+ width: 100%;
133
+ }
134
+ }
135
+
136
  /**
137
  * HiDPI Displays
138
  */
180
  background-image: url("pub/img/w3tc_netdna-logo-retina.png");
181
  background-size: 177px 90px;
182
  }
 
 
 
 
 
 
 
 
183
  }
184
+ */
Generic_Page_General.php CHANGED
@@ -35,7 +35,6 @@ class Generic_Page_General extends Base_Page_Settings {
35
  $varnish_enabled = $modules->is_enabled( 'varnish' );
36
 
37
  $enabled = $modules->plugin_is_enabled();
38
- $enabled_checkbox = $modules->all_modules_enabled();
39
 
40
  $check_rules = Util_Rule::can_check_rules();
41
  $disc_enhanced_enabled = !( ! $check_rules || ( !$this->is_master() && Util_Environment::is_wpmu() && $config_master->get_string( 'pgcache.engine' ) != 'file_generic' ) );
35
  $varnish_enabled = $modules->is_enabled( 'varnish' );
36
 
37
  $enabled = $modules->plugin_is_enabled();
 
38
 
39
  $check_rules = Util_Rule::can_check_rules();
40
  $disc_enhanced_enabled = !( ! $check_rules || ( !$this->is_master() && Util_Environment::is_wpmu() && $config_master->get_string( 'pgcache.engine' ) != 'file_generic' ) );
Generic_Plugin.php CHANGED
@@ -499,24 +499,25 @@ class Generic_Plugin {
499
  if ( Util_Environment::is_preview_mode() )
500
  $buffer .= "\r\n<!-- W3 Total Cache used in preview mode -->";
501
 
502
- if ( $this->_config->get_string( 'common.support' ) != '' ||
503
- $this->_config->get_boolean( 'common.tweeted' ) ) {
504
- $buffer .= sprintf( "\r\n<!-- Served from: %s @ %s by W3 Total Cache -->",
505
- Util_Content::escape_comment( $host ), $date );
506
- } else {
507
- $strings = array();
508
- $strings = apply_filters( 'w3tc_footer_comment', $strings );
509
-
510
- $buffer .= "\r\n<!-- Performance optimized by W3 Total Cache. Learn more: https://www.w3-edge.com/products/\r\n";
511
-
512
- if ( count( $strings ) ) {
513
- $buffer .= "\r\n" .
514
- Util_Content::escape_comment( implode( "\r\n", $strings ) ) .
515
- "\r\n";
516
- }
517
-
518
- $buffer .= sprintf( "\r\n Served from: %s @ %s by W3 Total Cache -->", Util_Content::escape_comment( $host ), $date );
519
- }
 
520
 
521
  $buffer = apply_filters( 'w3tc_process_content', $buffer );
522
  }
499
  if ( Util_Environment::is_preview_mode() )
500
  $buffer .= "\r\n<!-- W3 Total Cache used in preview mode -->";
501
 
502
+ $strings = array();
503
+
504
+ if ( $this->_config->get_string( 'common.support' ) == '' &&
505
+ !$this->_config->get_boolean( 'common.tweeted' ) ) {
506
+ $strings[] = 'Performance optimized by W3 Total Cache. Learn more: https://www.w3-edge.com/products/';
507
+ $strings[] = '';
508
+ }
509
+
510
+ $strings = apply_filters( 'w3tc_footer_comment', $strings );
511
+
512
+ if ( count( $strings ) ) {
513
+ $strings[] = '';
514
+ $strings[] = sprintf( "Served from: %s @ %s by W3 Total Cache",
515
+ Util_Content::escape_comment( $host ), $date );
516
+
517
+ $buffer .= "\r\n<!--\r\n" .
518
+ Util_Content::escape_comment( implode( "\r\n", $strings ) ) .
519
+ "\r\n-->";
520
+ }
521
 
522
  $buffer = apply_filters( 'w3tc_process_content', $buffer );
523
  }
Generic_Plugin_Admin.php CHANGED
@@ -67,7 +67,7 @@ class Generic_Plugin_Admin {
67
  if ( is_network_admin() ) {
68
  add_action( 'network_admin_menu', array(
69
  $this,
70
- 'admin_menu'
71
  ) );
72
  add_filter( 'network_admin_plugin_action_links_' . W3TC_FILE, array(
73
  $this,
@@ -329,14 +329,23 @@ class Generic_Plugin_Admin {
329
  <?php
330
  }
331
 
 
 
 
 
 
 
 
 
 
332
  /**
333
  * Admin menu
334
  *
335
  * @return void
336
  */
337
- function admin_menu() {
338
  $base_capability = apply_filters( 'w3tc_capability_menu',
339
- 'manage_options' );
340
 
341
  if ( current_user_can( $base_capability ) ) {
342
  $menus = Dispatcher::component( 'Root_AdminMenu' );
@@ -649,7 +658,7 @@ class Generic_Plugin_Admin {
649
  'flush_minify' => __( 'Minify cache successfully emptied.', 'w3-total-cache' ),
650
  'flush_browser_cache' => __( 'Media Query string has been successfully updated.', 'w3-total-cache' ),
651
  'flush_varnish' => __( 'Varnish servers successfully purged.', 'w3-total-cache' ),
652
- 'flush_cdn' => __( 'CDN was successfully purged.', 'w3-total-cache' ),
653
  'support_request' => __( 'The support request has been successfully sent.', 'w3-total-cache' ),
654
  'config_import' => __( 'Settings successfully imported.', 'w3-total-cache' ),
655
  'config_reset' => __( 'Settings successfully restored.', 'w3-total-cache' ),
67
  if ( is_network_admin() ) {
68
  add_action( 'network_admin_menu', array(
69
  $this,
70
+ 'network_admin_menu'
71
  ) );
72
  add_filter( 'network_admin_plugin_action_links_' . W3TC_FILE, array(
73
  $this,
329
  <?php
330
  }
331
 
332
+
333
+ function network_admin_menu() {
334
+ $this->_admin_menu( 'manage_network_options' );
335
+ }
336
+
337
+ function admin_menu() {
338
+ $this->_admin_menu( 'manage_options' );
339
+ }
340
+
341
  /**
342
  * Admin menu
343
  *
344
  * @return void
345
  */
346
+ private function _admin_menu( $base_capability ) {
347
  $base_capability = apply_filters( 'w3tc_capability_menu',
348
+ $base_capability );
349
 
350
  if ( current_user_can( $base_capability ) ) {
351
  $menus = Dispatcher::component( 'Root_AdminMenu' );
658
  'flush_minify' => __( 'Minify cache successfully emptied.', 'w3-total-cache' ),
659
  'flush_browser_cache' => __( 'Media Query string has been successfully updated.', 'w3-total-cache' ),
660
  'flush_varnish' => __( 'Varnish servers successfully purged.', 'w3-total-cache' ),
661
+ 'flush_cdn' => __( '<acronym title="Content Delivery Network">CDN</acronym> was successfully purged.', 'w3-total-cache' ),
662
  'support_request' => __( 'The support request has been successfully sent.', 'w3-total-cache' ),
663
  'config_import' => __( 'Settings successfully imported.', 'w3-total-cache' ),
664
  'config_reset' => __( 'Settings successfully restored.', 'w3-total-cache' ),
Generic_Plugin_AdminCompatibility.php CHANGED
@@ -24,8 +24,6 @@ class Generic_Plugin_AdminCompatibility {
24
  add_action( 'admin_notices', array( $this, 'verify' ) );
25
  add_action( 'network_admin_notices', array( $this, 'verify' ) );
26
  }
27
-
28
- $this->_backwards_import();
29
  }
30
 
31
  /**
@@ -110,29 +108,4 @@ class Generic_Plugin_AdminCompatibility {
110
  }
111
  return sprintf( "<p>$message</p><ul class=\"w3tc-incomp-plugins\">%s</ul>", implode( '', $plugin_names ) );
112
  }
113
-
114
- /**
115
- * Handle importing changed configuration from older versions
116
- */
117
- private function _backwards_import() {
118
- if ( $this->_config->get_string( 'cdn.engine' ) == 'netdna' && $this->_config->get_string( 'cdn.netdna.authorization_key' ) == '' ) {
119
-
120
- $alias = $this->_config->get_string( 'cdn.netdna.alias' );
121
- $consumerkey = $this->_config->get_string( 'cdn.netdna.consumerkey' );
122
- $consumersecret = $this->_config->get_string( 'cdn.netdna.consumersecret' );
123
- if ( $alias && $consumerkey && $consumersecret ) {
124
- $this->_config->set( 'cdn.maxcdn.authorization_key', "$alias+$consumerkey+$consumersecret" );
125
- $this->_config->set( 'cdn.netdna.authorization_key', "$alias+$consumerkey+$consumersecret" );
126
- $this->_config->set( 'cdn.engine', 'maxcdn' );
127
- $this->_config->set( 'cdn.maxcdn.zone_id', $this->_config->get_integer( 'cdn.netdna.zone_id', 0 ) );
128
- $this->_config->set( 'cdn.maxcdn.domain', $this->_config->get_array( 'cdn.netdna.domain' ) );
129
- $this->_config->set( 'cdn.maxcdn.ssl', $this->_config->get_string( 'cdn.netdna.ssl' ) );
130
-
131
- try{
132
- $this->_config->save();
133
- $this->_config->refresh_cache();
134
- } catch ( \Exception $ex ) {}
135
- }
136
- }
137
- }
138
  }
24
  add_action( 'admin_notices', array( $this, 'verify' ) );
25
  add_action( 'network_admin_notices', array( $this, 'verify' ) );
26
  }
 
 
27
  }
28
 
29
  /**
108
  }
109
  return sprintf( "<p>$message</p><ul class=\"w3tc-incomp-plugins\">%s</ul>", implode( '', $plugin_names ) );
110
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
Generic_Plugin_AdminNotifications.php CHANGED
@@ -71,29 +71,6 @@ class Generic_Plugin_AdminNotifications {
71
 
72
  do_action( 'w3tc_message_action_generic_support_us' );
73
  }
74
-
75
-
76
- // edge mode
77
- $edge_reminder = !$support_reminder &&
78
- !Util_Environment::is_w3tc_edge( $this->_config ) &&
79
- $state->get_integer( 'common.edge_invitations' ) < 3 &&
80
- ( $state->get_integer( 'common.install' ) <
81
- ( time() - W3TC_EDGE_TIMEOUT ) ) &&
82
- ( $state->get_integer( 'common.next_edge_invitation' ) < time() );
83
-
84
- if ( $edge_reminder ) {
85
- if ( $state->get_integer( 'common.edge_invitations' ) > 1 )
86
- $next = time() + 30 * 24 * 60 * 60;
87
- else
88
- $next = time() + W3TC_EDGE_TIMEOUT;
89
-
90
- $state->set( 'common.next_edge_invitation', $next );
91
- $state->set( 'common.edge_invitations',
92
- $state->get_integer( 'common.edge_invitations' ) + 1 );
93
- $state->save();
94
-
95
- do_action( 'w3tc_message_action_generic_edge' );
96
- }
97
  }
98
 
99
  /**
@@ -144,10 +121,4 @@ class Generic_Plugin_AdminNotifications {
144
  plugins_url( 'Generic_GeneralPage_View_ShowEdge.js', W3TC_FILE ),
145
  array(), W3TC_VERSION );
146
  }
147
-
148
-
149
-
150
- public function w3tc_ajax_generic_edge() {
151
- include W3TC_INC_LIGHTBOX_DIR . '/edge.php';
152
- }
153
  }
71
 
72
  do_action( 'w3tc_message_action_generic_support_us' );
73
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
75
 
76
  /**
121
  plugins_url( 'Generic_GeneralPage_View_ShowEdge.js', W3TC_FILE ),
122
  array(), W3TC_VERSION );
123
  }
 
 
 
 
 
 
124
  }
Minify_ContentMinifier.php CHANGED
@@ -31,7 +31,7 @@ class Minify_ContentMinifier {
31
 
32
  'css' => array( 'Minify_CSS', 'minify' ),
33
  'yuicss' => array( 'Minify_YUICompressor', 'minifyCss' ),
34
- 'cssmin' => array( 'Minify0_CSSmin', 'minify' ),
35
  'csstidy' => array( 'Minify_CSSTidy', 'minify' ),
36
 
37
  'html' => array( 'Minify_HTML', 'minify' ),
31
 
32
  'css' => array( 'Minify_CSS', 'minify' ),
33
  'yuicss' => array( 'Minify_YUICompressor', 'minifyCss' ),
34
+ 'cssmin' => array( 'w3tc_tubalmartin\CssMin\Minifier', 'minify' ),
35
  'csstidy' => array( 'Minify_CSSTidy', 'minify' ),
36
 
37
  'html' => array( 'Minify_HTML', 'minify' ),
Minify_Plugin.php CHANGED
@@ -59,11 +59,10 @@ class Minify_Plugin {
59
  add_filter( 'w3tc_admin_bar_menu',
60
  array( $this, 'w3tc_admin_bar_menu' ) );
61
 
62
- if ( !$this->_config->get_boolean( 'minify.debug' ) )
63
- add_filter( 'w3tc_footer_comment', array(
64
- $this,
65
- 'w3tc_footer_comment'
66
- ) );
67
 
68
  if ( $this->_config->get_string( 'minify.engine' ) == 'file' ) {
69
  add_action( 'w3_minify_cleanup', array(
@@ -425,21 +424,17 @@ class Minify_Plugin {
425
  : '' ) );
426
 
427
  if ( $this->_config->get_boolean( 'minify.debug' ) ) {
428
- $strings[] = "Minify debug info:";
429
- $strings[] = sprintf( "%s%s", str_pad( 'Engine: ', 20 ), Cache::engine_name( $this->_config->get_string( 'minify.engine' ) ) );
430
  $strings[] = sprintf( "%s%s", str_pad( 'Theme: ', 20 ), $this->get_theme() );
431
  $strings[] = sprintf( "%s%s", str_pad( 'Template: ', 20 ), $this->get_template() );
432
 
433
- if ( $this->minify_reject_reason ) {
434
- $strings[] = sprintf( "%s%s", str_pad( 'Reject reason: ', 20 ), $this->minify_reject_reason );
435
- }
436
-
437
  if ( $this->error ) {
438
  $strings[] = sprintf( "%s%s", str_pad( 'Errors: ', 20 ), $this->error );
439
  }
440
 
441
  if ( count( $this->replaced_styles ) ) {
442
- $strings[] = "Replaced CSS files:";
443
 
444
  foreach ( $this->replaced_styles as $index => $file ) {
445
  $strings[] = sprintf( "%d. %s", $index + 1, Util_Content::escape_comment( $file ) );
@@ -447,12 +442,13 @@ class Minify_Plugin {
447
  }
448
 
449
  if ( count( $this->replaced_scripts ) ) {
450
- $strings[] = "Replaced JavaScript files:";
451
 
452
  foreach ( $this->replaced_scripts as $index => $file ) {
453
  $strings[] = sprintf( "%d. %s\r\n", $index + 1, Util_Content::escape_comment( $file ) );
454
  }
455
  }
 
456
  }
457
 
458
  return $strings;
@@ -713,7 +709,6 @@ class Minify_Plugin {
713
  case ( is_author() && ( $template_file = get_author_template() ) ):
714
  case ( is_date() && ( $template_file = get_date_template() ) ):
715
  case ( is_archive() && ( $template_file = get_archive_template() ) ):
716
- case ( is_comments_popup() && ( $template_file = get_comments_popup_template() ) ):
717
  case ( is_paged() && ( $template_file = get_paged_template() ) ):
718
  break;
719
 
@@ -847,10 +842,14 @@ class Minify_Plugin {
847
 
848
  if ( count( $files ) ) {
849
  if ( $embed_to_html ) {
850
- $return['body'] =
851
- $this->minify_helpers->get_minified_content_for_files(
852
- $files, 'css' );
853
- } else {
 
 
 
 
854
  $return['url'] = $this->minify_helpers->get_minify_url_for_files(
855
  $files, 'css' );
856
  if ( !is_null( $return['url'] ) ) {
@@ -1185,11 +1184,12 @@ class _W3_MinifyHelpers {
1185
  $minify = Dispatcher::component( 'Minify_MinifiedFileRequestHandler' );
1186
 
1187
  $m = $minify->process( $minify_filename, true );
1188
- if ( isset( $m['content'] ) )
1189
- $style = $m['content'];
1190
- else
1191
- $style = 'not set';
1192
 
 
1193
  return "<style type=\"text/css\" media=\"all\">$style</style>\r\n";
1194
  }
1195
 
@@ -1485,7 +1485,9 @@ class _W3_MinifyJsAuto {
1485
  if ( $tag_pos === false ) {
1486
  // script is external but not found, skip processing it
1487
  error_log( 'script not found:' . $script_tag );
1488
- Minify_Core::log( 'script not found:' . $script_tag );
 
 
1489
  return;
1490
  }
1491
 
59
  add_filter( 'w3tc_admin_bar_menu',
60
  array( $this, 'w3tc_admin_bar_menu' ) );
61
 
62
+ add_filter( 'w3tc_footer_comment', array(
63
+ $this,
64
+ 'w3tc_footer_comment'
65
+ ) );
 
66
 
67
  if ( $this->_config->get_string( 'minify.engine' ) == 'file' ) {
68
  add_action( 'w3_minify_cleanup', array(
424
  : '' ) );
425
 
426
  if ( $this->_config->get_boolean( 'minify.debug' ) ) {
427
+ $strings[] = '';
428
+ $strings[] = 'Minify debug info:';
429
  $strings[] = sprintf( "%s%s", str_pad( 'Theme: ', 20 ), $this->get_theme() );
430
  $strings[] = sprintf( "%s%s", str_pad( 'Template: ', 20 ), $this->get_template() );
431
 
 
 
 
 
432
  if ( $this->error ) {
433
  $strings[] = sprintf( "%s%s", str_pad( 'Errors: ', 20 ), $this->error );
434
  }
435
 
436
  if ( count( $this->replaced_styles ) ) {
437
+ $strings[] = 'Replaced CSS files:';
438
 
439
  foreach ( $this->replaced_styles as $index => $file ) {
440
  $strings[] = sprintf( "%d. %s", $index + 1, Util_Content::escape_comment( $file ) );
442
  }
443
 
444
  if ( count( $this->replaced_scripts ) ) {
445
+ $strings[] = 'Replaced JavaScript files:';
446
 
447
  foreach ( $this->replaced_scripts as $index => $file ) {
448
  $strings[] = sprintf( "%d. %s\r\n", $index + 1, Util_Content::escape_comment( $file ) );
449
  }
450
  }
451
+ $strings[] = '';
452
  }
453
 
454
  return $strings;
709
  case ( is_author() && ( $template_file = get_author_template() ) ):
710
  case ( is_date() && ( $template_file = get_date_template() ) ):
711
  case ( is_archive() && ( $template_file = get_archive_template() ) ):
 
712
  case ( is_paged() && ( $template_file = get_paged_template() ) ):
713
  break;
714
 
842
 
843
  if ( count( $files ) ) {
844
  if ( $embed_to_html ) {
845
+ $body = $this->minify_helpers->get_minified_content_for_files(
846
+ $files, 'css' );
847
+ if ( !is_null( $body ) ) {
848
+ $return['body'] = $body;
849
+ }
850
+ }
851
+
852
+ if ( empty( $return['body'] ) ) {
853
  $return['url'] = $this->minify_helpers->get_minify_url_for_files(
854
  $files, 'css' );
855
  if ( !is_null( $return['url'] ) ) {
1184
  $minify = Dispatcher::component( 'Minify_MinifiedFileRequestHandler' );
1185
 
1186
  $m = $minify->process( $minify_filename, true );
1187
+ if ( !isset( $m['content'] ) )
1188
+ return null;
1189
+ if ( empty( $m['content'] ) )
1190
+ return null;
1191
 
1192
+ $style = $m['content'];
1193
  return "<style type=\"text/css\" media=\"all\">$style</style>\r\n";
1194
  }
1195
 
1485
  if ( $tag_pos === false ) {
1486
  // script is external but not found, skip processing it
1487
  error_log( 'script not found:' . $script_tag );
1488
+ if ( $this->debug ) {
1489
+ Minify_Core::log( 'script not found:' . $script_tag );
1490
+ }
1491
  return;
1492
  }
1493
 
Minify_Plugin_Admin.php CHANGED
@@ -90,9 +90,7 @@ class Minify_Plugin_Admin {
90
 
91
  public function admin_print_scripts_w3tc_general() {
92
  $state = Dispatcher::config_state();
93
- if ( !$state->get_boolean( 'minify.hide_minify_help' ) &&
94
- !Util_Environment::is_w3tc_edge( $this->_config ) &&
95
- !Util_Environment::is_w3tc_enterprise( $this->_config ) ) {
96
  wp_enqueue_script( 'w3tc-minify-help',
97
  plugins_url( 'Minify_GeneralPage_View_ShowHelp.js', W3TC_FILE ),
98
  array(), W3TC_VERSION );
90
 
91
  public function admin_print_scripts_w3tc_general() {
92
  $state = Dispatcher::config_state();
93
+ if ( !$state->get_boolean( 'minify.hide_minify_help' ) ) {
 
 
94
  wp_enqueue_script( 'w3tc-minify-help',
95
  plugins_url( 'Minify_GeneralPage_View_ShowHelp.js', W3TC_FILE ),
96
  array(), W3TC_VERSION );
ModuleStatus.php CHANGED
@@ -56,22 +56,6 @@ class ModuleStatus {
56
  return apply_filters( "w3tc_module_is_running-{$module}", $this->is_enabled( $module ) );
57
  }
58
 
59
- /**
60
- *
61
- *
62
- * @return bool
63
- */
64
- public function all_modules_enabled() {
65
- return $this->is_enabled( 'pgcache' )
66
- && $this->is_enabled( 'minify' )
67
- && $this->is_enabled( 'dbcache' )
68
- && $this->is_enabled( 'objectcache' )
69
- && $this->is_enabled( 'browsercache' )
70
- && $this->is_enabled( 'cdn' )
71
- && $this->is_enabled( 'varnish' )
72
- && $this->is_enabled( 'fragmentcache' );
73
- }
74
-
75
  /**
76
  *
77
  *
56
  return apply_filters( "w3tc_module_is_running-{$module}", $this->is_enabled( $module ) );
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  /**
60
  *
61
  *
ObjectCache_Environment.php CHANGED
@@ -115,7 +115,7 @@ class ObjectCache_Environment {
115
  if ( isset( $_GET['page'] ) )
116
  $url = 'admin.php?page=' . $_GET['page'] . '&amp;';
117
  else
118
- $url = basename( Util_Environment::remove_query(
119
  $_SERVER['REQUEST_URI'] ) ) . '?page=w3tc_dashboard&amp;';
120
  $remove_url = Util_Ui::admin_url( $url .
121
  'w3tc_default_remove_add_in=objectcache' );
@@ -155,6 +155,9 @@ class ObjectCache_Environment {
155
  * @return boolean
156
  */
157
  public function is_objectcache_old_add_in() {
 
 
 
158
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_OBJECT_CACHE ) )
159
  && ( ( strstr( $script_data, 'W3 Total Cache Object Cache' ) !== false ) ||
160
  strstr( $script_data, 'w3_instance' ) !== false ) );
@@ -166,6 +169,9 @@ class ObjectCache_Environment {
166
  * @return boolean
167
  */
168
  public function is_objectcache_add_in() {
 
 
 
169
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_OBJECT_CACHE ) )
170
  && strstr( $script_data, '//ObjectCache Version: 1.4' ) !== false );
171
  }
115
  if ( isset( $_GET['page'] ) )
116
  $url = 'admin.php?page=' . $_GET['page'] . '&amp;';
117
  else
118
+ $url = basename( Util_Environment::remove_query_all(
119
  $_SERVER['REQUEST_URI'] ) ) . '?page=w3tc_dashboard&amp;';
120
  $remove_url = Util_Ui::admin_url( $url .
121
  'w3tc_default_remove_add_in=objectcache' );
155
  * @return boolean
156
  */
157
  public function is_objectcache_old_add_in() {
158
+ if ( !$this->objectcache_installed() )
159
+ return false;
160
+
161
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_OBJECT_CACHE ) )
162
  && ( ( strstr( $script_data, 'W3 Total Cache Object Cache' ) !== false ) ||
163
  strstr( $script_data, 'w3_instance' ) !== false ) );
169
  * @return boolean
170
  */
171
  public function is_objectcache_add_in() {
172
+ if ( !$this->objectcache_installed() )
173
+ return false;
174
+
175
  return ( ( $script_data = @file_get_contents( W3TC_ADDIN_FILE_OBJECT_CACHE ) )
176
  && strstr( $script_data, '//ObjectCache Version: 1.4' ) !== false );
177
  }
ObjectCache_WpObjectCache_Regular.php CHANGED
@@ -125,7 +125,8 @@ class ObjectCache_WpObjectCache_Regular {
125
  $this->_debug = $this->_config->get_boolean( 'objectcache.debug' );
126
  $this->_caching = $_wp_using_ext_object_cache = $this->_can_cache();
127
  $this->global_groups = $this->_config->get_array( 'objectcache.groups.global' );
128
- $this->nonpersistent_groups = $this->_config->get_array( 'objectcache.groups.nonpersistent' );
 
129
 
130
  $this->_blog_id = Util_Environment::blog_id();
131
  }
@@ -143,10 +144,10 @@ class ObjectCache_WpObjectCache_Regular {
143
  }
144
 
145
  $key = $this->_get_cache_key( $id, $group );
146
- $internal = isset( $this->cache[$key] );
147
  $fallback_used = false;
148
 
149
- if ( $internal && !$force ) {
150
  $found = true;
151
  $value = $this->cache[$key];
152
  } elseif ( $this->_caching &&
@@ -163,7 +164,7 @@ class ObjectCache_WpObjectCache_Regular {
163
  json_encode($a);
164
  */
165
 
166
- if ( is_array( $v ) && $v['content'] != null ) {
167
  $found = true;
168
  $value = $v['content'];
169
  } else {
@@ -191,10 +192,12 @@ class ObjectCache_WpObjectCache_Regular {
191
  $found = ( $value !== false );
192
  }
193
 
194
- $this->cache[$key] = $value;
195
- $this->cache_total++;
 
 
 
196
 
197
- if ( $value !== false ) {
198
  $this->cache_hits++;
199
  } else {
200
  $this->cache_misses++;
@@ -220,7 +223,7 @@ class ObjectCache_WpObjectCache_Regular {
220
  if ( !$found )
221
  $returned = 'not in cache';
222
  else {
223
- if ( $internal )
224
  $returned = 'from in-call cache';
225
  else
226
  $returned = 'from persistent cache';
@@ -412,8 +415,8 @@ class ObjectCache_WpObjectCache_Regular {
412
 
413
  if ( $this->_debug ) {
414
  $this->debug_info[] = array(
415
- 'id' => $id,
416
- 'group' => $group,
417
  'operation' => 'flush',
418
  'returned' => $reason,
419
  'data_size' => 0,
@@ -540,7 +543,7 @@ class ObjectCache_WpObjectCache_Regular {
540
  if ( ! isset( $value ) )
541
  $value = get_site_option( $transient_option );
542
  } else {
543
- $value == false;
544
  }
545
 
546
  return $value;
@@ -614,11 +617,14 @@ class ObjectCache_WpObjectCache_Regular {
614
  function stats() {
615
  echo '<h2>Summary</h2>';
616
  echo '<p>';
617
- echo '<strong>Engine</strong>: ' . Cache::engine_name( $this->_config->get_string( 'objectcache.engine' ) ) . '<br />';
618
- echo '<strong>Caching</strong>: ' . ( $this->_caching ? 'enabled' : 'disabled' ) . '<br />';
 
 
619
 
620
  if ( !$this->_caching ) {
621
- echo '<strong>Reject reason</strong>: ' . $this->get_reject_reason() . '<br />';
 
622
  }
623
 
624
  echo '<strong>Total calls</strong>: ' . $this->cache_total . '<br />';
@@ -631,13 +637,13 @@ class ObjectCache_WpObjectCache_Regular {
631
 
632
  if ( $this->_debug ) {
633
  echo '<table cellpadding="0" cellspacing="3" border="1">';
634
- echo '<tr><td>#</td><td>Status</td><td>Source</td><td>Data size (b)</td><td>Query time (s)</td><td>ID:Group</td></tr>';
635
 
636
  foreach ( $this->debug_info as $index => $debug ) {
637
  echo '<tr>';
638
  echo '<td>' . ( $index + 1 ) . '</td>';
639
- echo '<td>' . ( $debug['cached'] ? 'cached' : 'not cached' ) . '</td>';
640
- echo '<td>' . ( $debug['internal'] ? 'internal' : 'persistent' ) . '</td>';
641
  echo '<td>' . $debug['data_size'] . '</td>';
642
  echo '<td>' . round( $debug['time'], 4 ) . '</td>';
643
  echo '<td>' . sprintf( '%s:%s', $debug['id'], $debug['group'] ) . '</td>';
@@ -732,7 +738,8 @@ class ObjectCache_WpObjectCache_Regular {
732
  case 'memcached':
733
  $engineConfig = array(
734
  'servers' => $this->_config->get_array( 'objectcache.memcached.servers' ),
735
- 'persistent' => $this->_config->get_boolean( 'objectcache.memcached.persistent' ),
 
736
  'aws_autodiscovery' => $this->_config->get_boolean( 'objectcache.memcached.aws_autodiscovery' ),
737
  'username' => $this->_config->get_string( 'objectcache.memcached.username' ),
738
  'password' => $this->_config->get_string( 'objectcache.memcached.password' )
@@ -742,7 +749,8 @@ class ObjectCache_WpObjectCache_Regular {
742
  case 'redis':
743
  $engineConfig = array(
744
  'servers' => $this->_config->get_array( 'objectcache.redis.servers' ),
745
- 'persistent' => $this->_config->get_boolean( 'objectcache.redis.persistent' ),
 
746
  'dbid' => $this->_config->get_integer( 'objectcache.redis.dbid' ),
747
  'password' => $this->_config->get_string( 'objectcache.redis.password' )
748
  );
@@ -824,7 +832,8 @@ class ObjectCache_WpObjectCache_Regular {
824
  $this->_can_cache_dynamic = true;
825
  } else {
826
  if ( $this->_caching ) {
827
- if ( defined( 'WP_ADMIN' ) ) {
 
828
  $this->_can_cache_dynamic = false;
829
  $this->cache_reject_reason = 'WP_ADMIN defined';
830
  return $this->_can_cache_dynamic;
@@ -840,14 +849,20 @@ class ObjectCache_WpObjectCache_Regular {
840
  }
841
 
842
  public function w3tc_footer_comment( $strings ) {
843
- if ( $this->_config->get_boolean( 'objectcache.debug' ) ) {
844
- $strings[] = "Object Cache debug info:";
845
- $strings[] = sprintf( "%s%s", str_pad( 'Engine: ', 20 ), Cache::engine_name( $this->_config->get_string( 'objectcache.engine' ) ) );
846
- $strings[] = sprintf( "%s%s", str_pad( 'Caching: ', 20 ), ( $this->_caching ? 'enabled' : 'disabled' ) );
847
 
848
- if ( !$this->_caching ) {
849
- $strings[] = sprintf( "%s%s", str_pad( 'Reject reason: ', 20 ), $this->cache_reject_reason );
850
- }
 
 
 
 
 
 
 
 
851
 
852
  $strings[] = sprintf( "%s%d", str_pad( 'Total calls: ', 20 ), $this->cache_total );
853
  $strings[] = sprintf( "%s%d", str_pad( 'Cache hits: ', 20 ), $this->cache_hits );
@@ -874,15 +889,7 @@ class ObjectCache_WpObjectCache_Regular {
874
  str_pad( $debug['group'], 15, ' ', STR_PAD_LEFT ),
875
  $debug['id'] );
876
  }
877
- } else {
878
- $reason = $this->get_reject_reason();
879
- $append = ( $reason != '' ? sprintf( ' (%s)', $reason ) : '' );
880
-
881
- $strings[] = sprintf(
882
- __( 'Object Caching %d/%d objects using %s%s', 'w3-total-cache' ),
883
- $this->cache_hits, $this->cache_total,
884
- Cache::engine_name( $this->_config->get_string( 'objectcache.engine' ) ),
885
- $append );
886
  }
887
 
888
  return $strings;
125
  $this->_debug = $this->_config->get_boolean( 'objectcache.debug' );
126
  $this->_caching = $_wp_using_ext_object_cache = $this->_can_cache();
127
  $this->global_groups = $this->_config->get_array( 'objectcache.groups.global' );
128
+ $this->nonpersistent_groups = $this->_config->get_array(
129
+ 'objectcache.groups.nonpersistent' );
130
 
131
  $this->_blog_id = Util_Environment::blog_id();
132
  }
144
  }
145
 
146
  $key = $this->_get_cache_key( $id, $group );
147
+ $in_incall_cache = isset( $this->cache[$key] );
148
  $fallback_used = false;
149
 
150
+ if ( $in_incall_cache && !$force ) {
151
  $found = true;
152
  $value = $this->cache[$key];
153
  } elseif ( $this->_caching &&
164
  json_encode($a);
165
  */
166
 
167
+ if ( is_array( $v ) && isset( $v['content'] ) ) {
168
  $found = true;
169
  $value = $v['content'];
170
  } else {
192
  $found = ( $value !== false );
193
  }
194
 
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++;
223
  if ( !$found )
224
  $returned = 'not in cache';
225
  else {
226
+ if ( $in_incall_cache )
227
  $returned = 'from in-call cache';
228
  else
229
  $returned = 'from persistent cache';
415
 
416
  if ( $this->_debug ) {
417
  $this->debug_info[] = array(
418
+ 'id' => '',
419
+ 'group' => '',
420
  'operation' => 'flush',
421
  'returned' => $reason,
422
  'data_size' => 0,
543
  if ( ! isset( $value ) )
544
  $value = get_site_option( $transient_option );
545
  } else {
546
+ $value = false;
547
  }
548
 
549
  return $value;
617
  function stats() {
618
  echo '<h2>Summary</h2>';
619
  echo '<p>';
620
+ echo '<strong>Engine</strong>: ' . Cache::engine_name(
621
+ $this->_config->get_string( 'objectcache.engine' ) ) . '<br />';
622
+ echo '<strong>Caching</strong>: ' .
623
+ ( $this->_caching ? 'enabled' : 'disabled' ) . '<br />';
624
 
625
  if ( !$this->_caching ) {
626
+ echo '<strong>Reject reason</strong>: ' .
627
+ $this->get_reject_reason() . '<br />';
628
  }
629
 
630
  echo '<strong>Total calls</strong>: ' . $this->cache_total . '<br />';
637
 
638
  if ( $this->_debug ) {
639
  echo '<table cellpadding="0" cellspacing="3" border="1">';
640
+ echo '<tr><td>#</td><td>Operation</td><td>Returned</td><td>Data size (b)</td><td>Query time (s)</td><td>ID:Group</td></tr>';
641
 
642
  foreach ( $this->debug_info as $index => $debug ) {
643
  echo '<tr>';
644
  echo '<td>' . ( $index + 1 ) . '</td>';
645
+ echo '<td>' . $debug['operation'] . '</td>';
646
+ echo '<td>' . $debug['returned'] . '</td>';
647
  echo '<td>' . $debug['data_size'] . '</td>';
648
  echo '<td>' . round( $debug['time'], 4 ) . '</td>';
649
  echo '<td>' . sprintf( '%s:%s', $debug['id'], $debug['group'] ) . '</td>';
738
  case 'memcached':
739
  $engineConfig = array(
740
  'servers' => $this->_config->get_array( 'objectcache.memcached.servers' ),
741
+ 'persistent' => $this->_config->get_boolean(
742
+ 'objectcache.memcached.persistent' ),
743
  'aws_autodiscovery' => $this->_config->get_boolean( 'objectcache.memcached.aws_autodiscovery' ),
744
  'username' => $this->_config->get_string( 'objectcache.memcached.username' ),
745
  'password' => $this->_config->get_string( 'objectcache.memcached.password' )
749
  case 'redis':
750
  $engineConfig = array(
751
  'servers' => $this->_config->get_array( 'objectcache.redis.servers' ),
752
+ 'persistent' => $this->_config->get_boolean(
753
+ 'objectcache.redis.persistent' ),
754
  'dbid' => $this->_config->get_integer( 'objectcache.redis.dbid' ),
755
  'password' => $this->_config->get_string( 'objectcache.redis.password' )
756
  );
832
  $this->_can_cache_dynamic = true;
833
  } else {
834
  if ( $this->_caching ) {
835
+ if ( defined( 'WP_ADMIN' ) &&
836
+ ( !defined( 'DOING_AJAX' ) || !DOING_AJAX ) ) {
837
  $this->_can_cache_dynamic = false;
838
  $this->cache_reject_reason = 'WP_ADMIN defined';
839
  return $this->_can_cache_dynamic;
849
  }
850
 
851
  public function w3tc_footer_comment( $strings ) {
852
+ $reason = $this->get_reject_reason();
853
+ $append = ( $reason != '' ? sprintf( ' (%s)', $reason ) : '' );
 
 
854
 
855
+ $strings[] = sprintf(
856
+ __( 'Object Caching %d/%d objects using %s%s', 'w3-total-cache' ),
857
+ $this->cache_hits, $this->cache_total,
858
+ Cache::engine_name( $this->_config->get_string( 'objectcache.engine' ) ),
859
+ $append );
860
+
861
+ if ( $this->_config->get_boolean( 'objectcache.debug' ) ) {
862
+ $strings[] = '';
863
+ $strings[] = 'Object Cache debug info:';
864
+ $strings[] = sprintf( "%s%s", str_pad( 'Caching: ', 20 ),
865
+ ( $this->_caching ? 'enabled' : 'disabled' ) );
866
 
867
  $strings[] = sprintf( "%s%d", str_pad( 'Total calls: ', 20 ), $this->cache_total );
868
  $strings[] = sprintf( "%s%d", str_pad( 'Cache hits: ', 20 ), $this->cache_hits );
889
  str_pad( $debug['group'], 15, ' ', STR_PAD_LEFT ),
890
  $debug['id'] );
891
  }
892
+ $strings[] = '';
 
 
 
 
 
 
 
 
893
  }
894
 
895
  return $strings;
PageSpeed_Api.php CHANGED
@@ -12,16 +12,20 @@ define( 'W3TC_PAGESPEED_API_URL', 'https://www.googleapis.com/pagespeedonline/v1
12
  class PageSpeed_Api {
13
  /**
14
  * API Key
15
- *
16
- * @var string
17
  */
18
- var $key = '';
 
 
 
 
 
19
 
20
  /**
21
  * PHP5-style constructor
22
  */
23
- function __construct( $api_key ) {
24
  $this->key = $api_key;
 
25
  }
26
 
27
  /**
@@ -51,7 +55,11 @@ class PageSpeed_Api {
51
  'key' => $this->key,
52
  ) );
53
 
54
- $response = Util_Http::get( $request_url, array( 'timeout' => 120 ) );
 
 
 
 
55
  if ( !is_wp_error( $response ) && $response['response']['code'] == 200 ) {
56
  return $response['body'];
57
  }
12
  class PageSpeed_Api {
13
  /**
14
  * API Key
 
 
15
  */
16
+ private $key = '';
17
+
18
+ /**
19
+ * Referrer for key restricting
20
+ */
21
+ private $key_restrict_referrer = '';
22
 
23
  /**
24
  * PHP5-style constructor
25
  */
26
+ function __construct( $api_key, $api_ref ) {
27
  $this->key = $api_key;
28
+ $this->key_restrict_referrer = $api_ref;
29
  }
30
 
31
  /**
55
  'key' => $this->key,
56
  ) );
57
 
58
+ $response = Util_Http::get( $request_url, array(
59
+ 'timeout' => 120,
60
+ 'headers' => array( 'Referer' => $this->key_restrict_referrer )
61
+ ) );
62
+
63
  if ( !is_wp_error( $response ) && $response['response']['code'] == 200 ) {
64
  return $response['body'];
65
  }
PageSpeed_Plugin_Widget.php CHANGED
@@ -91,8 +91,9 @@ class PageSpeed_Plugin_Widget {
91
 
92
  $config = Dispatcher::config();
93
  $key = $config->get_string( 'widget.pagespeed.key' );
 
94
 
95
- $w3_pagespeed = new PageSpeed_Api( $key );
96
  $r = $w3_pagespeed->analyze( get_home_url() );
97
 
98
  if ( !$r ) {
@@ -132,7 +133,8 @@ class PageSpeed_Plugin_Widget {
132
 
133
  $config = Dispatcher::config();
134
  $key = $config->get_string( 'widget.pagespeed.key' );
135
- $w3_pagespeed = new PageSpeed_Api( $key );
 
136
 
137
  $r = $w3_pagespeed->analyze( $url );
138
 
91
 
92
  $config = Dispatcher::config();
93
  $key = $config->get_string( 'widget.pagespeed.key' );
94
+ $ref = $config->get_string( 'widget.pagespeed.key.restrict.referrer' );
95
 
96
+ $w3_pagespeed = new PageSpeed_Api( $key, $ref );
97
  $r = $w3_pagespeed->analyze( get_home_url() );
98
 
99
  if ( !$r ) {
133
 
134
  $config = Dispatcher::config();
135
  $key = $config->get_string( 'widget.pagespeed.key' );
136
+ $ref = $config->get_string( 'widget.pagespeed.key.restrict.referrer' );
137
+ $w3_pagespeed = new PageSpeed_Api( $key, $ref );
138
 
139
  $r = $w3_pagespeed->analyze( $url );
140
 
PgCache_ConfigLabels.php CHANGED
@@ -47,6 +47,10 @@ class PgCache_ConfigLabels {
47
  'pgcache.reject.ua' => __( 'Rejected user agents:', 'w3-total-cache' ),
48
  'pgcache.reject.cookie' => __( 'Rejected cookies:', 'w3-total-cache' ),
49
  'pgcache.reject.uri' => __( 'Never cache the following pages:', 'w3-total-cache' ),
 
 
 
 
50
  'pgcache.accept.files' => __( 'Cache exception list:', 'w3-total-cache' ),
51
  'pgcache.accept.uri' => __( 'Non-trailing slash pages:', 'w3-total-cache' ),
52
  'pgcache.cache.headers' => __( 'Specify page headers:', 'w3-total-cache' ),
47
  'pgcache.reject.ua' => __( 'Rejected user agents:', 'w3-total-cache' ),
48
  'pgcache.reject.cookie' => __( 'Rejected cookies:', 'w3-total-cache' ),
49
  'pgcache.reject.uri' => __( 'Never cache the following pages:', 'w3-total-cache' ),
50
+ 'pgcache.reject.categories' => __( 'Never cache pages associated with these categories:', 'w3-total-cache' ),
51
+ 'pgcache.reject.tags' => __( 'Never cache pages that use these tags:', 'w3-total-cache' ),
52
+ 'pgcache.reject.authors' => __( 'Never cache pages by these authors:', 'w3-total-cache' ),
53
+ 'pgcache.reject.custom' => __( 'Never cache pages that use these custom fields:', 'w3-total-cache' ),
54
  'pgcache.accept.files' => __( 'Cache exception list:', 'w3-total-cache' ),
55
  'pgcache.accept.uri' => __( 'Non-trailing slash pages:', 'w3-total-cache' ),
56
  'pgcache.cache.headers' => __( 'Specify page headers:', 'w3-total-cache' ),
PgCache_ContentGrabber.php CHANGED
@@ -73,6 +73,7 @@ class PgCache_ContentGrabber {
73
  * @var string
74
  */
75
  var $_page_key = '';
 
76
 
77
  /**
78
  * Shutdown buffer
@@ -185,6 +186,14 @@ class PgCache_ContentGrabber {
185
  ( $this->_caching ? 'true' : 'false' ) );
186
  }
187
 
 
 
 
 
 
 
 
 
188
  if ( $this->_caching && !$this->_late_caching ) {
189
  $this->_cached_data = $this->_extract_cached_page( false );
190
  if ( $this->_cached_data ) {
@@ -217,10 +226,10 @@ class PgCache_ContentGrabber {
217
  function _extract_cached_page( $with_filter ) {
218
  $cache = $this->_get_cache();
219
 
220
- $mobile_group = $this->_get_mobile_group();
221
- $referrer_group = $this->_get_referrer_group();
222
- $encryption = $this->_get_encryption();
223
- $compression = $this->_get_compression();
224
 
225
  $group = '';
226
  $sitemap_regex = $this->_config->get_string( 'pgcache.purge.sitemap_regex' );
@@ -234,8 +243,7 @@ class PgCache_ContentGrabber {
234
  /**
235
  * Check if page is cached
236
  */
237
- if ( !$this->_set_extract_page_key( $mobile_group, $referrer_group,
238
- $encryption, $compression, '', $with_filter ) ) {
239
  $data = null;
240
  } else {
241
  $data = $cache->get_with_old( $this->_page_key, $group );
@@ -246,8 +254,9 @@ class PgCache_ContentGrabber {
246
  * Try to get uncompressed version of cache
247
  */
248
  if ( $compression && !$data ) {
249
- if ( !$this->_set_extract_page_key( $mobile_group,
250
- $referrer_group, $encryption, false, '', $with_filter ) ) {
 
251
  $data = null;
252
  } else {
253
  $data = $cache->get_with_old( $this->_page_key, $group );
@@ -271,17 +280,20 @@ class PgCache_ContentGrabber {
271
 
272
 
273
 
274
- private function _set_extract_page_key( $mobile_group, $referrer_group,
275
- $encryption, $compression, $content_type = '', $with_filter ) {
276
- $this->_page_key = $this->_get_page_key( $mobile_group, $referrer_group,
277
- $encryption, $compression, $content_type );
278
 
279
  if ( $with_filter ) {
280
  // return empty value if caching should not happen
281
  $this->_page_key = apply_filters( 'w3tc_page_extract_key',
282
- $this->_page_key, $mobile_group, $referrer_group,
283
- $encryption, $compression, $content_type,
284
- $this->_request_host . $this->_request_uri );
 
 
 
 
 
285
  }
286
 
287
  if ( !empty( $this->_page_key ) )
@@ -317,7 +329,7 @@ class PgCache_ContentGrabber {
317
  // its last modification date is now, and any compression
318
  // browser wants cant be used, since its compressed now
319
  $time = time();
320
- $compression = $this->_get_compression();
321
  } else {
322
  $time = $data['time'];
323
  $compression = $data['compression'];
@@ -361,6 +373,7 @@ class PgCache_ContentGrabber {
361
  $can_cache = apply_filters( 'w3tc_can_cache', $original_can_cache, $this, $buffer );
362
  if ( $can_cache != $original_can_cache )
363
  $this->cache_reject_reason = 'Third-party plugin has modified caching activity';
 
364
  if ( $this->_debug ) {
365
  self::log( 'storing cached page: ' .
366
  ( $can_cache ? 'true' : 'false' ) .
@@ -368,12 +381,17 @@ class PgCache_ContentGrabber {
368
  ' reason ' . $this->cache_reject_reason );
369
  }
370
 
 
 
 
 
 
371
  if ( $can_cache ) {
372
  $buffer = $this->_maybe_save_cached_result( $buffer, $has_dynamic );
373
  } else {
374
  if ( $has_dynamic ) {
375
  // send common headers since output will be compressed
376
- $compression_header = $this->_get_compression();
377
  if ( defined( 'W3TC_PAGECACHE_OUTPUT_COMPRESSION_OFF' ) )
378
  $compression_header = false;
379
  $headers = $this->_get_common_headers( $compression_header );
@@ -385,16 +403,15 @@ class PgCache_ContentGrabber {
385
  if ( $this->_old_exists ) {
386
  $cache = $this->_get_cache();
387
 
388
- $mobile_group = $this->_get_mobile_group();
389
- $referrer_group = $this->_get_referrer_group();
390
- $encryption = $this->_get_encryption();
391
  $compressions_to_store = $this->_get_compressions();
392
- $content_type = '';
393
 
394
  foreach ( $compressions_to_store as $_compression ) {
395
- $_page_key = $this->_get_page_key( $mobile_group,
396
- $referrer_group, $encryption, $_compression,
397
- $content_type );
398
  $cache->hard_delete( $_page_key );
399
  }
400
  }
@@ -425,7 +442,7 @@ class PgCache_ContentGrabber {
425
  * @return void
426
  */
427
  public function shutdown() {
428
- $compression = $this->_get_compression();
429
 
430
  // Parse dynamic content
431
  $buffer = $this->_parse_dynamic( $this->_shutdown_buffer );
@@ -459,10 +476,10 @@ class PgCache_ContentGrabber {
459
  }
460
 
461
  if ( !$this->_config->get_boolean('pgcache.cache.ssl') && Util_Environment::is_https() ) {
462
- $this->cache_reject_reason = 'SSL caching disabled';
463
 
464
- return false;
465
- }
466
 
467
  /**
468
  * Skip if posting
@@ -498,7 +515,7 @@ class PgCache_ContentGrabber {
498
  /**
499
  * Check request URI
500
  */
501
- if ( !in_array( $_SERVER['PHP_SELF'], $this->_config->get_array( 'pgcache.accept.files' ) ) && !$this->_check_request_uri() ) {
502
  $this->cache_reject_reason = 'Requested URI is rejected';
503
 
504
  return false;
@@ -568,7 +585,6 @@ class PgCache_ContentGrabber {
568
  */
569
  if ( defined( 'DONOTCACHEPAGE' ) && DONOTCACHEPAGE ) {
570
  $this->cache_reject_reason = 'DONOTCACHEPAGE constant is defined';
571
-
572
  return false;
573
  }
574
 
@@ -617,6 +633,39 @@ class PgCache_ContentGrabber {
617
  return false;
618
  }
619
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  return true;
621
  }
622
 
@@ -741,7 +790,7 @@ class PgCache_ContentGrabber {
741
  *
742
  * @return boolean
743
  */
744
- function _check_request_uri() {
745
  $auto_reject_uri = array(
746
  'wp-login',
747
  'wp-register'
@@ -766,6 +815,100 @@ class PgCache_ContentGrabber {
766
  return true;
767
  }
768
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
769
  /**
770
  * Checks User Agent
771
  *
@@ -896,42 +1039,70 @@ class PgCache_ContentGrabber {
896
  }
897
 
898
  /**
899
- * Returns current mobile group
900
  *
901
  * @return string
902
  */
903
- function _get_mobile_group() {
904
- if ( $this->_mobile ) {
905
- return $this->_mobile->get_group();
906
- }
 
 
 
 
 
 
 
907
 
908
- return '';
909
- }
 
 
 
 
910
 
911
- /**
912
- * Returns current referrer group
913
- *
914
- * @return string
915
- */
916
- function _get_referrer_group() {
917
- if ( $this->_referrer ) {
918
- return $this->_referrer->get_group();
919
- }
920
 
921
- return '';
922
  }
923
 
924
- /**
925
- * Returns current encryption
926
- *
927
- * @return string
928
- */
929
- function _get_encryption() {
930
- if ( Util_Environment::is_https() ) {
931
- return 'ssl';
932
- }
933
 
934
- return '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
935
  }
936
 
937
  /**
@@ -941,7 +1112,7 @@ class PgCache_ContentGrabber {
941
  */
942
  function _get_compression() {
943
  if ( $this->_debug ) // cannt generate/use compressed files during debug mode
944
- return false;
945
 
946
  if ( !Util_Environment::is_zlib_enabled() && !$this->_is_buggy_ie() ) {
947
  $compressions = $this->_get_compressions();
@@ -955,7 +1126,7 @@ class PgCache_ContentGrabber {
955
  }
956
  }
957
 
958
- return false;
959
  }
960
 
961
  /**
@@ -1082,17 +1253,9 @@ class PgCache_ContentGrabber {
1082
  /**
1083
  * Returns page key
1084
  *
1085
- * @param string $mobile_group
1086
- * @param string $referrer_group
1087
- * @param string $encryption
1088
- * @param string $compression
1089
- * @param string $content_type
1090
- * @param string $request_uri
1091
  * @return string
1092
  */
1093
- function _get_page_key( $mobile_group = '', $referrer_group = '',
1094
- $encryption = '', $compression = '', $content_type = '', $request_url = '' ) {
1095
-
1096
  if ( $request_url ) {
1097
  $parts = parse_url( $request_url );
1098
  $key = $parts['host'] .
@@ -1135,48 +1298,40 @@ class PgCache_ContentGrabber {
1135
  }
1136
 
1137
  /**
1138
- * Append mobile group
1139
  */
1140
- if ( $mobile_group ) {
1141
- $key .= '_' . $mobile_group;
1142
- }
1143
-
1144
- /**
1145
- * Append referrer group
1146
- */
1147
- if ( $referrer_group ) {
1148
- $key .= '_' . $referrer_group;
1149
- }
1150
-
1151
- /**
1152
- * Append encryption
1153
- */
1154
- if ( $encryption ) {
1155
- $key .= '_' . $encryption;
1156
- }
1157
-
1158
- if ( Util_Environment::is_preview_mode() ) {
1159
  $key .= '_preview';
1160
- }
1161
 
1162
  if ( $this->_enhanced_mode ) {
1163
- /**
1164
- * Append HTML extension.
1165
- * For nginx - we create .xml cache entries and redirect to them
1166
- */
1167
- if ( Util_Environment::is_nginx() && substr( $content_type, 0, 8 ) == 'text/xml' &&
1168
- $this->_config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) )
1169
- $key .= '.xml';
1170
- else
1171
- $key .= '.html';
 
 
 
 
1172
  }
1173
 
1174
  /**
1175
  * Append compression
1176
  */
1177
- if ( $compression ) {
1178
- $key .= '_' . $compression;
1179
- }
1180
 
1181
  return $key;
1182
  }
@@ -1192,25 +1347,20 @@ class PgCache_ContentGrabber {
1192
  */
1193
  public function w3tc_footer_comment( $strings ) {
1194
  $strings[] = sprintf(
1195
- __( 'Page Caching using %s%s', 'w3-total-cache' ),
1196
  Cache::engine_name( $this->_config->get_string( 'pgcache.engine' ) ),
1197
- ( $this->cache_reject_reason != ''
1198
- ? sprintf( ' (%s)', $this->cache_reject_reason )
1199
- : '' ) );
1200
 
1201
 
1202
  if ( $this->_debug ) {
1203
  $time_total = Util_Debug::microtime() - $this->_time_start;
1204
  $engine = $this->_config->get_string( 'pgcache.engine' );
1205
- $strings[] = "Page cache debug info:";
 
1206
  $strings[] = sprintf( "%s%s", str_pad( 'Engine: ', 20 ), Cache::engine_name( $engine ) );
1207
  $strings[] = sprintf( "%s%s", str_pad( 'Cache key: ', 20 ), $this->_page_key );
1208
 
1209
- if ( $this->cache_reject_reason != '' ) {
1210
- $strings[] = sprintf( "%s%s", str_pad( 'Reject reason: ', 20 ),
1211
- $this->cache_reject_reason );
1212
- }
1213
-
1214
  $strings[] = sprintf( "%s%.3fs", str_pad( 'Creation Time: ', 20 ), time() );
1215
 
1216
  $headers = $this->_get_response_headers();
@@ -1224,6 +1374,8 @@ class PgCache_ContentGrabber {
1224
  Util_Content::escape_comment( $i['value'] ) );
1225
  }
1226
  }
 
 
1227
  }
1228
 
1229
  return $strings;
@@ -1256,7 +1408,7 @@ class PgCache_ContentGrabber {
1256
  } elseif ( $name == 'Status-Code' ) {
1257
  if ( function_exists( 'http_response_code' ) ) // php5.3 compatibility)
1258
  @http_response_code( $headers['Status-Code'] );
1259
- } else {
1260
  @header( $name . ': ' . $value, !isset( $repeating[$name] ) );
1261
  $repeating[$name] = true;
1262
  }
@@ -1381,7 +1533,7 @@ class PgCache_ContentGrabber {
1381
 
1382
  $vary = '';
1383
  //compressed && UAG
1384
- if ( $compression && $this->_get_mobile_group() ) {
1385
  $vary = 'Accept-Encoding,User-Agent,Cookie';
1386
  $headers['Content-Encoding'] = $compression;
1387
  //compressed
@@ -1389,7 +1541,7 @@ class PgCache_ContentGrabber {
1389
  $vary = 'Accept-Encoding';
1390
  $headers['Content-Encoding'] = $compression;
1391
  //uncompressed && UAG
1392
- } elseif ( $this->_get_mobile_group() ) {
1393
  $vary = 'User-Agent,Cookie';
1394
  }
1395
 
@@ -1579,19 +1731,18 @@ class PgCache_ContentGrabber {
1579
  $headers = headers_list();
1580
  foreach ( $headers as $header ) {
1581
  $header = strtolower( $header );
1582
- if ( stripos( $header, 'content-type' ) !== false ) {
1583
- $temp = explode( ';', $header );
1584
- $temp = array_shift( $temp );
1585
- $temp = explode( ':', $temp );
1586
- $content_type = trim( $temp[1] );
1587
  }
1588
  }
1589
 
1590
  $cache_headers = apply_filters( 'w3tc_is_cacheable_content_type',
1591
  array(
1592
  '' /* redirects, they have only Location header set */,
1593
- 'application/json', 'text/html', 'text/xml',
1594
- 'application/xhtml+xml'
 
1595
  )
1596
  );
1597
  return in_array( $content_type, $cache_headers );
@@ -1599,10 +1750,25 @@ class PgCache_ContentGrabber {
1599
 
1600
  private function _check_query_string() {
1601
  $accept_qs = $this->_config->get_array( 'pgcache.accept.qs' );
 
 
 
 
 
 
 
 
 
 
 
 
 
1602
  foreach ( $_GET as $key => $value ) {
1603
- if ( !in_array( strtolower( $key ), $accept_qs ) )
1604
  return false;
 
1605
  }
 
1606
  return true;
1607
  }
1608
 
@@ -1644,10 +1810,10 @@ class PgCache_ContentGrabber {
1644
  return $buffer;
1645
  }
1646
 
1647
- $mobile_group = $this->_get_mobile_group();
1648
- $referrer_group = $this->_get_referrer_group();
1649
- $encryption = $this->_get_encryption();
1650
- $compression_header = $this->_get_compression();
1651
  $compressions_to_store = $this->_get_compressions();
1652
 
1653
  /**
@@ -1663,7 +1829,6 @@ class PgCache_ContentGrabber {
1663
  $compression_of_returned_content =
1664
  ( $has_dynamic ? false : $compression_header );
1665
 
1666
- $content_type = '';
1667
  $is_404 = ( function_exists( 'is_404' ) ? is_404() : false );
1668
  $response_headers = $this->_get_response_headers();
1669
  $headers = $this->_get_cached_headers( $response_headers['plain'] );
@@ -1678,9 +1843,9 @@ class PgCache_ContentGrabber {
1678
  // they will be turned into fresh files and catch further requests
1679
  if ( isset( $response_headers['kv']['Location'] ) ) {
1680
  foreach ( $compressions_to_store as $_compression ) {
1681
- $_page_key = $this->_get_page_key( $mobile_group,
1682
- $referrer_group, $encryption, $_compression,
1683
- $content_type );
1684
  $cache = $this->_get_cache();
1685
  $cache->hard_delete( $_page_key );
1686
  }
@@ -1689,6 +1854,7 @@ class PgCache_ContentGrabber {
1689
  }
1690
  }
1691
 
 
1692
  if ( $this->_enhanced_mode && !$this->_late_init ) {
1693
  register_shutdown_function( array(
1694
  $this,
@@ -1718,9 +1884,11 @@ class PgCache_ContentGrabber {
1718
  $group = 'sitemaps';
1719
 
1720
  foreach ( $compressions_to_store as $_compression ) {
1721
- $this->_set_extract_page_key( $mobile_group,
1722
- $referrer_group, $encryption, $_compression,
1723
- $content_type, true );
 
 
1724
  if ( empty( $this->_page_key ) )
1725
  continue;
1726
 
73
  * @var string
74
  */
75
  var $_page_key = '';
76
+ private $_page_key_extension;
77
 
78
  /**
79
  * Shutdown buffer
186
  ( $this->_caching ? 'true' : 'false' ) );
187
  }
188
 
189
+ $this->_page_key_extension = $this->_get_key_extension();
190
+ if ( !$this->_page_key_extension['cache'] ) {
191
+ $this->_caching = false;
192
+ $this->cache_reject_reason =
193
+ $this->_page_key_extension['cache_reject_reason'];
194
+ }
195
+
196
+
197
  if ( $this->_caching && !$this->_late_caching ) {
198
  $this->_cached_data = $this->_extract_cached_page( false );
199
  if ( $this->_cached_data ) {
226
  function _extract_cached_page( $with_filter ) {
227
  $cache = $this->_get_cache();
228
 
229
+ $mobile_group = $this->_page_key_extension['useragent'];
230
+ $referrer_group = $this->_page_key_extension['referrer'];
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' );
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 );
254
  * Try to get uncompressed version of cache
255
  */
256
  if ( $compression && !$data ) {
257
+ if ( !$this->_set_extract_page_key(
258
+ array_merge( $this->_page_key_extension,
259
+ array( 'compression' => '') ), $with_filter ) ) {
260
  $data = null;
261
  } else {
262
  $data = $cache->get_with_old( $this->_page_key, $group );
280
 
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 ) {
287
  // return empty value if caching should not happen
288
  $this->_page_key = apply_filters( 'w3tc_page_extract_key',
289
+ $this->_page_key,
290
+ $page_key_extension['useragent'],
291
+ $page_key_extension['referrer'],
292
+ $page_key_extension['encryption'],
293
+ $page_key_extension['compression'],
294
+ $page_key_extension['content_type'],
295
+ $this->_request_host . $this->_request_uri,
296
+ $page_key_extension );
297
  }
298
 
299
  if ( !empty( $this->_page_key ) )
329
  // its last modification date is now, and any compression
330
  // browser wants cant be used, since its compressed now
331
  $time = time();
332
+ $compression = $this->_page_key_extension['compression'];
333
  } else {
334
  $time = $data['time'];
335
  $compression = $data['compression'];
373
  $can_cache = apply_filters( 'w3tc_can_cache', $original_can_cache, $this, $buffer );
374
  if ( $can_cache != $original_can_cache )
375
  $this->cache_reject_reason = 'Third-party plugin has modified caching activity';
376
+
377
  if ( $this->_debug ) {
378
  self::log( 'storing cached page: ' .
379
  ( $can_cache ? 'true' : 'false' ) .
381
  ' reason ' . $this->cache_reject_reason );
382
  }
383
 
384
+ $buffer = str_replace('{w3tc_pagecache_reject_reason}',
385
+ ( $this->cache_reject_reason != '' ? sprintf( ' (%s)', $this->cache_reject_reason )
386
+ : '' ),
387
+ $buffer );
388
+
389
  if ( $can_cache ) {
390
  $buffer = $this->_maybe_save_cached_result( $buffer, $has_dynamic );
391
  } else {
392
  if ( $has_dynamic ) {
393
  // send common headers since output will be compressed
394
+ $compression_header = $this->_page_key_extension['compression'];
395
  if ( defined( 'W3TC_PAGECACHE_OUTPUT_COMPRESSION_OFF' ) )
396
  $compression_header = false;
397
  $headers = $this->_get_common_headers( $compression_header );
403
  if ( $this->_old_exists ) {
404
  $cache = $this->_get_cache();
405
 
406
+ $mobile_group = $this->_page_key_extension['useragent'];
407
+ $referrer_group = $this->_page_key_extension['referrer'];
408
+ $encryption = $this->_page_key_extension['encryption'];
409
  $compressions_to_store = $this->_get_compressions();
 
410
 
411
  foreach ( $compressions_to_store as $_compression ) {
412
+ $_page_key = $this->_get_page_key(
413
+ array_merge( $this->_page_key_extension,
414
+ array( 'compression' => $_compression ) ) );
415
  $cache->hard_delete( $_page_key );
416
  }
417
  }
442
  * @return void
443
  */
444
  public function shutdown() {
445
+ $compression = $this->_page_key_extension['compression'];
446
 
447
  // Parse dynamic content
448
  $buffer = $this->_parse_dynamic( $this->_shutdown_buffer );
476
  }
477
 
478
  if ( !$this->_config->get_boolean('pgcache.cache.ssl') && Util_Environment::is_https() ) {
479
+ $this->cache_reject_reason = 'SSL caching disabled';
480
 
481
+ return false;
482
+ }
483
 
484
  /**
485
  * Skip if posting
515
  /**
516
  * Check request URI
517
  */
518
+ if ( !$this->_passed_accept_files() && !$this->_passed_reject_uri() ) {
519
  $this->cache_reject_reason = 'Requested URI is rejected';
520
 
521
  return false;
585
  */
586
  if ( defined( 'DONOTCACHEPAGE' ) && DONOTCACHEPAGE ) {
587
  $this->cache_reject_reason = 'DONOTCACHEPAGE constant is defined';
 
588
  return false;
589
  }
590
 
633
  return false;
634
  }
635
 
636
+ if ( !$this->_passed_accept_files() ) {
637
+ if ( is_single() ) {
638
+ /**
639
+ * Don't cache pages associated with categories
640
+ */
641
+ if ( $this->_passed_reject_categories() ) {
642
+ $this->cache_reject_reason = 'Page associated with a rejected category';
643
+ return false;
644
+ }
645
+ /**
646
+ * Don't cache pages that use tags
647
+ */
648
+ if ( $this->_passed_reject_tags() ) {
649
+ $this->cache_reject_reason = 'Page using a rejected tag';
650
+ return false;
651
+ }
652
+ }
653
+ /**
654
+ * Don't cache pages by these authors
655
+ */
656
+ if ( $this->_passed_reject_authors() ) {
657
+ $this->cache_reject_reason = 'Page written by a rejected author';
658
+ return false;
659
+ }
660
+ /**
661
+ * Don't cache pages using custom fields
662
+ */
663
+ if ( $this->_passed_reject_custom_fields() ) {
664
+ $this->cache_reject_reason = 'Page using a rejected custom field';
665
+ return false;
666
+ }
667
+ }
668
+
669
  return true;
670
  }
671
 
790
  *
791
  * @return boolean
792
  */
793
+ function _passed_reject_uri() {
794
  $auto_reject_uri = array(
795
  'wp-login',
796
  'wp-register'
815
  return true;
816
  }
817
 
818
+ /**
819
+ * Check if in the cache exception list
820
+ *
821
+ * @return boolean
822
+ */
823
+ function _passed_accept_files() {
824
+ $accept_uri = $this->_config->get_array( 'pgcache.accept.files' );
825
+ $accept_uri = array_map( array( '\W3TC\Util_Environment', 'parse_path' ), $accept_uri );
826
+ foreach ( $accept_uri as &$val ) $val = trim( str_replace( "~", "\~", $val ) );
827
+ $accept_uri = array_filter( $accept_uri, function( $val ){ return $val != ""; } );
828
+ if ( !empty( $accept_uri ) && @preg_match( '~' . implode( "|", $accept_uri ) . '~i', $this->_request_uri ) ) {
829
+ return true;
830
+ }
831
+ return false;
832
+ }
833
+ /**
834
+ * Checks page against rejected categories
835
+ *
836
+ * @return boolean
837
+ */
838
+ function _passed_reject_categories() {
839
+ $reject_categories = $this->_config->get_array( 'pgcache.reject.categories' );
840
+ if ( !empty( $reject_categories ) ) {
841
+ if ( $cats = get_the_category() ) {
842
+ foreach( $cats as $cat ) {
843
+ if ( in_array( $cat->slug, $reject_categories ) ) {
844
+ return true;
845
+ }
846
+ }
847
+ }
848
+ }
849
+ return false;
850
+ }
851
+ /**
852
+ * Checks page against rejected tags
853
+ *
854
+ * @return boolean
855
+ */
856
+ function _passed_reject_tags() {
857
+ $reject_tags = $this->_config->get_array( 'pgcache.reject.tags' );
858
+ if ( !empty( $reject_tags ) ) {
859
+ if ( $tags = get_the_tags() ) {
860
+ foreach( $tags as $tag ) {
861
+ if ( in_array( $tag->slug,$reject_tags ) ) {
862
+ return true;
863
+ }
864
+ }
865
+ }
866
+ }
867
+ return false;
868
+ }
869
+ /**
870
+ * Checks page against rejected authors
871
+ *
872
+ * @return boolean
873
+ */
874
+ function _passed_reject_authors() {
875
+ $reject_authors = $this->_config->get_array( 'pgcache.reject.authors' );
876
+ if ( !empty( $reject_authors ) ) {
877
+ if ( $author = get_the_author_meta( 'user_login' ) ) {
878
+ if ( in_array( $author, $reject_authors ) ) {
879
+ return true;
880
+ }
881
+ }
882
+ }
883
+ return false;
884
+ }
885
+ /**
886
+ * Checks page against rejected custom fields
887
+ *
888
+ * @return boolean
889
+ */
890
+ function _passed_reject_custom_fields() {
891
+ $reject_custom = $this->_config->get_array( 'pgcache.reject.custom' );
892
+ if ( empty( $reject_custom ) )
893
+ return false;
894
+
895
+ foreach ( $reject_custom as &$val ) {
896
+ $val = preg_quote( trim( $val ), '~' );
897
+ }
898
+ $reject_custom = implode( '|', array_filter( $reject_custom ) );
899
+ if ( !empty( $reject_custom ) ) {
900
+ if ( $customs = get_post_custom() ) {
901
+ foreach ( $customs as $key => $value ) {
902
+ if ( @preg_match( '~' . $reject_custom . '~i', $key . ( isset( $value[0] ) ? "={$value[0]}" : "" ) ) ) {
903
+ return true;
904
+ }
905
+ }
906
+ }
907
+ }
908
+
909
+ return false;
910
+ }
911
+
912
  /**
913
  * Checks User Agent
914
  *
1039
  }
1040
 
1041
  /**
1042
+ * Returns page key extension for current request
1043
  *
1044
  * @return string
1045
  */
1046
+ private function _get_key_extension() {
1047
+ $extension = array(
1048
+ 'useragent' => '',
1049
+ 'referrer' => '',
1050
+ 'cookie' => '',
1051
+ 'encryption' => '',
1052
+ 'compression' => $this->_get_compression(),
1053
+ 'content_type' => '',
1054
+ 'cache' => true,
1055
+ 'cache_reject_reason' => '',
1056
+ );
1057
 
1058
+ if ( $this->_mobile )
1059
+ $extension['useragent'] = $this->_mobile->get_group();
1060
+ if ( $this->_referrer )
1061
+ $extension['referrer'] = $this->_referrer->get_group();
1062
+ if ( Util_Environment::is_https() )
1063
+ $extension['encryption'] = 'ssl';
1064
 
1065
+ $this->_fill_key_extension_cookie( $extension );
 
 
 
 
 
 
 
 
1066
 
1067
+ return $extension;
1068
  }
1069
 
1070
+ private function _fill_key_extension_cookie( &$extension ) {
1071
+ if ( !$this->_config->get_boolean( 'pgcache.cookiegroups.enabled' ) )
1072
+ return;
 
 
 
 
 
 
1073
 
1074
+ $groups = $this->_config->get_array( 'pgcache.cookiegroups.groups' );
1075
+ foreach ( $groups as $group_name => $g ) {
1076
+ if ( isset( $g['enabled'] ) && $g['enabled'] ) {
1077
+
1078
+ $cookies = array();
1079
+ foreach ($g['cookies'] as $cookie ) {
1080
+ $cookie = trim( $cookie );
1081
+ if ( !empty( $cookie ) ) {
1082
+ $cookie = str_replace( '+', ' ', $cookie );
1083
+ $cookie = Util_Environment::preg_quote( $cookie );
1084
+ if ( strpos( $cookie, '=') === false )
1085
+ $cookie .= '=.*';
1086
+ $cookies[] = $cookie;
1087
+ }
1088
+ }
1089
+
1090
+ if ( count( $cookies ) > 0 ) {
1091
+ $cookies_regexp = '~^(' . implode( '|', $cookies ) . ')$~i';
1092
+
1093
+ foreach ( $_COOKIE as $key => $value ) {
1094
+ if ( @preg_match( $cookies_regexp, $key . '=' . $value ) ) {
1095
+ $extension['cookie'] = $group_name;
1096
+ if ( !$g['cache'] ) {
1097
+ $extension['cache'] = false;
1098
+ $extension['cache_reject_reason'] = 'cookiegroup ' . $group_name;
1099
+ }
1100
+ return;
1101
+ }
1102
+ }
1103
+ }
1104
+ }
1105
+ }
1106
  }
1107
 
1108
  /**
1112
  */
1113
  function _get_compression() {
1114
  if ( $this->_debug ) // cannt generate/use compressed files during debug mode
1115
+ return '';
1116
 
1117
  if ( !Util_Environment::is_zlib_enabled() && !$this->_is_buggy_ie() ) {
1118
  $compressions = $this->_get_compressions();
1126
  }
1127
  }
1128
 
1129
+ return '';
1130
  }
1131
 
1132
  /**
1253
  /**
1254
  * Returns page key
1255
  *
 
 
 
 
 
 
1256
  * @return string
1257
  */
1258
+ function _get_page_key( $page_key_extension, $request_url = '' ) {
 
 
1259
  if ( $request_url ) {
1260
  $parts = parse_url( $request_url );
1261
  $key = $parts['host'] .
1298
  }
1299
 
1300
  /**
1301
+ * Append extensions
1302
  */
1303
+ if ( !empty( $page_key_extension['useragent'] ) )
1304
+ $key .= '_' . $page_key_extension['useragent'];
1305
+ if ( !empty( $page_key_extension['referrer'] ) )
1306
+ $key .= '_' . $page_key_extension['referrer'];
1307
+ if ( !empty( $page_key_extension['cookie'] ) )
1308
+ $key .= '_' . $page_key_extension['cookie'];
1309
+ if ( !empty( $page_key_extension['encryption'] ) )
1310
+ $key .= '_' . $page_key_extension['encryption'];
1311
+ if ( Util_Environment::is_preview_mode() )
 
 
 
 
 
 
 
 
 
 
1312
  $key .= '_preview';
 
1313
 
1314
  if ( $this->_enhanced_mode ) {
1315
+ $key_postfix = '.html';
1316
+ if ( $this->_config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
1317
+ $content_type = isset( $page_key_extension['content_type'] ) ?
1318
+ $page_key_extension['content_type'] : '';
1319
+
1320
+ if ( @preg_match( "~(text/xml|text/xsl|application/rdf\+xml|application/rss\+xml|application/atom\+xml)~i", $content_type ) ||
1321
+ strpos( $this->_request_uri, "/feed/" ) !== false ||
1322
+ strpos( $this->_request_uri, ".xsl" ) !== false ) {
1323
+ $key_postfix = '.xml';
1324
+ }
1325
+ }
1326
+
1327
+ $key .= $key_postfix;
1328
  }
1329
 
1330
  /**
1331
  * Append compression
1332
  */
1333
+ if ( $page_key_extension['compression'] )
1334
+ $key .= '_' . $page_key_extension['compression'];
 
1335
 
1336
  return $key;
1337
  }
1347
  */
1348
  public function w3tc_footer_comment( $strings ) {
1349
  $strings[] = sprintf(
1350
+ __( 'Page Caching using %s%s%s', 'w3-total-cache' ),
1351
  Cache::engine_name( $this->_config->get_string( 'pgcache.engine' ) ),
1352
+ '{w3tc_pagecache_reject_reason}',
1353
+ isset($this->_page_key_extension['cookie']) ? ' ' . $this->_page_key_extension['cookie'] : '' );
 
1354
 
1355
 
1356
  if ( $this->_debug ) {
1357
  $time_total = Util_Debug::microtime() - $this->_time_start;
1358
  $engine = $this->_config->get_string( 'pgcache.engine' );
1359
+ $strings[] = '';
1360
+ $strings[] = 'Page cache debug info:';
1361
  $strings[] = sprintf( "%s%s", str_pad( 'Engine: ', 20 ), Cache::engine_name( $engine ) );
1362
  $strings[] = sprintf( "%s%s", str_pad( 'Cache key: ', 20 ), $this->_page_key );
1363
 
 
 
 
 
 
1364
  $strings[] = sprintf( "%s%.3fs", str_pad( 'Creation Time: ', 20 ), time() );
1365
 
1366
  $headers = $this->_get_response_headers();
1374
  Util_Content::escape_comment( $i['value'] ) );
1375
  }
1376
  }
1377
+
1378
+ $strings[] = '';
1379
  }
1380
 
1381
  return $strings;
1408
  } elseif ( $name == 'Status-Code' ) {
1409
  if ( function_exists( 'http_response_code' ) ) // php5.3 compatibility)
1410
  @http_response_code( $headers['Status-Code'] );
1411
+ } elseif ( !empty( $name ) && !empty( $value ) ) {
1412
  @header( $name . ': ' . $value, !isset( $repeating[$name] ) );
1413
  $repeating[$name] = true;
1414
  }
1533
 
1534
  $vary = '';
1535
  //compressed && UAG
1536
+ if ( $compression && $this->_page_key_extension['useragent'] ) {
1537
  $vary = 'Accept-Encoding,User-Agent,Cookie';
1538
  $headers['Content-Encoding'] = $compression;
1539
  //compressed
1541
  $vary = 'Accept-Encoding';
1542
  $headers['Content-Encoding'] = $compression;
1543
  //uncompressed && UAG
1544
+ } elseif ( $this->_page_key_extension['useragent'] ) {
1545
  $vary = 'User-Agent,Cookie';
1546
  }
1547
 
1731
  $headers = headers_list();
1732
  foreach ( $headers as $header ) {
1733
  $header = strtolower( $header );
1734
+ $m = null;
1735
+ if ( preg_match( '~\s*content-type\s*:([^;]+)~', $header, $m ) ) {
1736
+ $content_type = trim( $m[1] );
 
 
1737
  }
1738
  }
1739
 
1740
  $cache_headers = apply_filters( 'w3tc_is_cacheable_content_type',
1741
  array(
1742
  '' /* redirects, they have only Location header set */,
1743
+ 'application/json', 'text/html', 'text/xml', 'text/xsl',
1744
+ 'application/xhtml+xml', 'application/rss+xml',
1745
+ 'application/atom+xml', 'application/rdf+xml'
1746
  )
1747
  );
1748
  return in_array( $content_type, $cache_headers );
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
+
1755
+ if ( empty( $accept_qs) ) {
1756
+ return false;
1757
+ }
1758
+
1759
+ foreach ( $accept_qs as &$val ) {
1760
+ $val = Util_Environment::preg_quote( str_replace( "+", " ", $val ) );
1761
+ $val .= ( strpos( $val, '=' ) === false ? '=.*?' : '' );
1762
+ }
1763
+
1764
+ $accept_qs = implode( '|', $accept_qs );
1765
+
1766
  foreach ( $_GET as $key => $value ) {
1767
+ if ( !@preg_match( '~^(' . $accept_qs . ')$~i', $key . "=$value" ) ) {
1768
  return false;
1769
+ }
1770
  }
1771
+
1772
  return true;
1773
  }
1774
 
1810
  return $buffer;
1811
  }
1812
 
1813
+ $mobile_group = $this->_page_key_extension['useragent'];
1814
+ $referrer_group = $this->_page_key_extension['referrer'];
1815
+ $encryption = $this->_page_key_extension['encryption'];
1816
+ $compression_header = $this->_page_key_extension['compression'];
1817
  $compressions_to_store = $this->_get_compressions();
1818
 
1819
  /**
1829
  $compression_of_returned_content =
1830
  ( $has_dynamic ? false : $compression_header );
1831
 
 
1832
  $is_404 = ( function_exists( 'is_404' ) ? is_404() : false );
1833
  $response_headers = $this->_get_response_headers();
1834
  $headers = $this->_get_cached_headers( $response_headers['plain'] );
1843
  // they will be turned into fresh files and catch further requests
1844
  if ( isset( $response_headers['kv']['Location'] ) ) {
1845
  foreach ( $compressions_to_store as $_compression ) {
1846
+ $_page_key = $this->_get_page_key(
1847
+ array_merge( $this->_page_key_extension,
1848
+ array( 'compression' => $_compression ) ) );
1849
  $cache = $this->_get_cache();
1850
  $cache->hard_delete( $_page_key );
1851
  }
1854
  }
1855
  }
1856
 
1857
+ $content_type = '';
1858
  if ( $this->_enhanced_mode && !$this->_late_init ) {
1859
  register_shutdown_function( array(
1860
  $this,
1884
  $group = 'sitemaps';
1885
 
1886
  foreach ( $compressions_to_store as $_compression ) {
1887
+ $this->_set_extract_page_key(
1888
+ array_merge( $this->_page_key_extension,
1889
+ array(
1890
+ 'compression' => $_compression,
1891
+ 'content_type' => $content_type ) ), true );
1892
  if ( empty( $this->_page_key ) )
1893
  continue;
1894
 
PgCache_Environment.php CHANGED
@@ -582,6 +582,7 @@ class PgCache_Environment {
582
  */
583
  $env_W3TC_UA = '';
584
  $env_W3TC_REF = '';
 
585
  $env_W3TC_SSL = '';
586
  $env_W3TC_ENC = '';
587
 
@@ -596,6 +597,30 @@ class PgCache_Environment {
596
  $rules .= " RewriteRule ^(.*\\/)?w3tc_rewrite_test([0-9]+)/?$ $1?w3tc_rewrite_test=1 [L]\n";
597
  }
598
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
599
  /**
600
  * Check for mobile redirect
601
  */
@@ -670,6 +695,36 @@ class PgCache_Environment {
670
  }
671
  }
672
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  /**
674
  * Set HTTPS
675
  */
@@ -678,6 +733,8 @@ class PgCache_Environment {
678
  $rules .= " RewriteRule .* - [E=W3TC_SSL:_ssl]\n";
679
  $rules .= " RewriteCond %{SERVER_PORT} =443\n";
680
  $rules .= " RewriteRule .* - [E=W3TC_SSL:_ssl]\n";
 
 
681
  $env_W3TC_SSL = '%{ENV:W3TC_SSL}';
682
  }
683
 
@@ -704,7 +761,9 @@ class PgCache_Environment {
704
  /**
705
  * Query string should be empty
706
  */
707
- $use_cache_rules .= " RewriteCond %{QUERY_STRING} =\"\"\n";
 
 
708
 
709
  /**
710
  * Check permalink structure trailing slash
@@ -732,18 +791,24 @@ class PgCache_Environment {
732
  * Make final rewrites for specific files
733
  */
734
  $uri_prefix = $cache_path . '/%{HTTP_HOST}/%{REQUEST_URI}/' .
735
- '_index' . $env_W3TC_UA . $env_W3TC_REF . $env_W3TC_SSL . $env_W3TC_PREVIEW;
 
736
  $switch = " -" . ( $config->get_boolean( 'pgcache.file.nfs' ) ? 'F' : 'f' );
737
 
738
  $document_root = Util_Rule::apache_docroot_variable();
739
 
740
- // write rule to rewrite to .html file
741
- $ext = '.html';
742
- $rules .= $use_cache_rules;
743
- $rules .= " RewriteCond \"" . $document_root . $uri_prefix . $ext .
744
- $env_W3TC_ENC . "\"" . $switch . "\n";
745
- $rules .= " RewriteRule .* \"" . $uri_prefix . $ext .
746
- $env_W3TC_ENC . "\" [L]\n";
 
 
 
 
 
747
 
748
  $rules .= "</IfModule>\n";
749
 
@@ -812,6 +877,7 @@ class PgCache_Environment {
812
  */
813
  $env_w3tc_ua = '';
814
  $env_w3tc_ref = '';
 
815
  $env_w3tc_ssl = '';
816
  $env_w3tc_ext = '';
817
  $env_w3tc_enc = '';
@@ -822,6 +888,30 @@ class PgCache_Environment {
822
  $rules .= "rewrite ^(.*\\/)?w3tc_rewrite_test([0-9]+)/?$ $1?w3tc_rewrite_test=1 last;\n";
823
  }
824
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
825
  /**
826
  * Check for mobile redirect
827
  */
@@ -880,7 +970,10 @@ class PgCache_Environment {
880
  /**
881
  * Query string should be empty
882
  */
883
- $rules .= "if (\$query_string != \"\") {\n";
 
 
 
884
  $rules .= " set \$w3tc_rewrite 0;\n";
885
  $rules .= "}\n";
886
 
@@ -981,12 +1074,53 @@ class PgCache_Environment {
981
  }
982
  }
983
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
984
  if ( $config->get_boolean( 'pgcache.cache.ssl' ) ) {
985
  $rules .= "set \$w3tc_ssl \"\";\n";
986
 
987
  $rules .= "if (\$scheme = https) {\n";
988
  $rules .= " set \$w3tc_ssl _ssl;\n";
989
  $rules .= "}\n";
 
 
 
990
 
991
  $env_w3tc_ssl = "\$w3tc_ssl";
992
  }
@@ -1005,7 +1139,7 @@ class PgCache_Environment {
1005
  $cache_path = str_replace( Util_Environment::document_root(), '', $cache_dir );
1006
  $uri_prefix = $cache_path . "/\$http_host/" .
1007
  "\$request_uri/_index" . $env_w3tc_ua . $env_w3tc_ref .
1008
- $env_w3tc_ssl . $env_w3tc_preview;
1009
 
1010
  if ( !$config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
1011
  $env_w3tc_ext = '.html';
@@ -1134,7 +1268,14 @@ class PgCache_Environment {
1134
 
1135
  // allow to read files by apache if they are blocked at some level above
1136
  $rules .= "<Files ~ \"\.(html|html_gzip|xml|xml_gzip)$\">\n";
1137
- $rules .= " Allow from all\n";
 
 
 
 
 
 
 
1138
  $rules .= "</Files>\n";
1139
 
1140
  if ( !$etag ) {
@@ -1326,14 +1467,23 @@ class PgCache_Environment {
1326
  $rules = '';
1327
  $rules .= W3TC_MARKER_BEGIN_PGCACHE_CACHE . "\n";
1328
 
1329
- $rules .= "location ~ " . $cache_dir . ".*html$ {\n";
1330
- $rules .= $common_rules;
1331
- $rules .= "}\n";
 
 
1332
 
1333
  if ( $compression ) {
 
 
 
 
 
 
 
1334
  $rules .= "location ~ " . $cache_dir . ".*gzip$ {\n";
1335
  $rules .= " gzip off;\n";
1336
- $rules .= " types {}\n";
1337
  $rules .= " default_type text/html;\n";
1338
  $rules .= $common_rules;
1339
  $rules .= " add_header Content-Encoding gzip;\n";
582
  */
583
  $env_W3TC_UA = '';
584
  $env_W3TC_REF = '';
585
+ $env_W3TC_COOKIE = '';
586
  $env_W3TC_SSL = '';
587
  $env_W3TC_ENC = '';
588
 
597
  $rules .= " RewriteRule ^(.*\\/)?w3tc_rewrite_test([0-9]+)/?$ $1?w3tc_rewrite_test=1 [L]\n";
598
  }
599
 
600
+
601
+ /**
602
+ * Set accept query strings
603
+ */
604
+ $w3tc_query_strings = $config->get_array( 'pgcache.accept.qs' );
605
+ Util_Rule::array_trim( $w3tc_query_strings );
606
+
607
+ if ( !empty( $w3tc_query_strings ) ) {
608
+ $w3tc_query_strings = str_replace( ' ', '+', $w3tc_query_strings );
609
+ $w3tc_query_strings = array_map( array( '\W3TC\Util_Environment', 'preg_quote' ), $w3tc_query_strings );
610
+
611
+ $rules .= " RewriteRule ^ - [E=W3TC_QUERY_STRING:%{QUERY_STRING}]\n";
612
+
613
+ foreach ( $w3tc_query_strings as $query ) {
614
+ $query .= ( strpos( $query, '=' ) === false ? '=.*?' : '' );
615
+ $rules .= " RewriteCond %{ENV:W3TC_QUERY_STRING} ^(.*?&|)" .
616
+ $query . "(&.*|)$ [NC]\n";
617
+ $rules .= " RewriteRule ^ - [E=W3TC_QUERY_STRING:%1%2]\n";
618
+ }
619
+
620
+ $rules .= " RewriteCond %{ENV:W3TC_QUERY_STRING} ^&+$\n";
621
+ $rules .= " RewriteRule ^ - [E=W3TC_QUERY_STRING]\n";
622
+ }
623
+
624
  /**
625
  * Check for mobile redirect
626
  */
695
  }
696
  }
697
 
698
+ /**
699
+ * Set cookie group
700
+ */
701
+ if ( $config->get_boolean( 'pgcache.cookiegroups.enabled' ) ) {
702
+ $cookie_groups = $config->get_array( 'pgcache.cookiegroups.groups' );
703
+
704
+ foreach ( $cookie_groups as $group_name => $g ) {
705
+ if ( isset( $g['enabled'] ) && $g['enabled'] ) {
706
+ $cookies = array();
707
+ foreach ($g['cookies'] as $cookie ) {
708
+ $cookie = trim( $cookie );
709
+ if ( !empty( $cookie ) ) {
710
+ $cookie = str_replace( '+', ' ', $cookie );
711
+ $cookie = Util_Environment::preg_quote( $cookie );
712
+ if ( strpos( $cookie, '=') === false )
713
+ $cookie .= '=.*';
714
+ $cookies[] = $cookie;
715
+ }
716
+ }
717
+
718
+ if ( count( $cookies ) > 0 ) {
719
+ $cookies_regexp = '^(.*;\s*)?(' . implode( '|', $cookies ) . ')(\s*;.*)?$';
720
+ $rules .= " RewriteCond %{HTTP_COOKIE} $cookies_regexp [NC]\n";
721
+ $rules .= " RewriteRule .* - [E=W3TC_COOKIE:_" . $group_name . "]\n";
722
+ $env_W3TC_COOKIE = '%{ENV:W3TC_COOKIE}';
723
+ }
724
+ }
725
+ }
726
+ }
727
+
728
  /**
729
  * Set HTTPS
730
  */
733
  $rules .= " RewriteRule .* - [E=W3TC_SSL:_ssl]\n";
734
  $rules .= " RewriteCond %{SERVER_PORT} =443\n";
735
  $rules .= " RewriteRule .* - [E=W3TC_SSL:_ssl]\n";
736
+ $rules .= " RewriteCond %{HTTP:X-Forwarded-Proto} =https [NC]\n";
737
+ $rules .= " RewriteRule .* - [E=W3TC_SSL:_ssl]\n";
738
  $env_W3TC_SSL = '%{ENV:W3TC_SSL}';
739
  }
740
 
761
  /**
762
  * Query string should be empty
763
  */
764
+ $use_cache_rules .= empty( $w3tc_query_strings ) ?
765
+ " RewriteCond %{QUERY_STRING} =\"\"\n" :
766
+ " RewriteCond %{ENV:W3TC_QUERY_STRING} =\"\"\n";
767
 
768
  /**
769
  * Check permalink structure trailing slash
791
  * Make final rewrites for specific files
792
  */
793
  $uri_prefix = $cache_path . '/%{HTTP_HOST}/%{REQUEST_URI}/' .
794
+ '_index' . $env_W3TC_UA . $env_W3TC_REF . $env_W3TC_COOKIE .
795
+ $env_W3TC_SSL . $env_W3TC_PREVIEW;
796
  $switch = " -" . ( $config->get_boolean( 'pgcache.file.nfs' ) ? 'F' : 'f' );
797
 
798
  $document_root = Util_Rule::apache_docroot_variable();
799
 
800
+ // write rule to rewrite to .html/.xml file
801
+ $exts = array( '.html' );
802
+ if ($config->get_boolean('pgcache.cache.nginx_handle_xml'))
803
+ $exts[] = '.xml';
804
+
805
+ foreach ( $exts as $ext ) {
806
+ $rules .= $use_cache_rules;
807
+ $rules .= " RewriteCond \"" . $document_root . $uri_prefix . $ext .
808
+ $env_W3TC_ENC . "\"" . $switch . "\n";
809
+ $rules .= " RewriteRule .* \"" . $uri_prefix . $ext .
810
+ $env_W3TC_ENC . "\" [L]\n";
811
+ }
812
 
813
  $rules .= "</IfModule>\n";
814
 
877
  */
878
  $env_w3tc_ua = '';
879
  $env_w3tc_ref = '';
880
+ $env_w3tc_cookie = '';
881
  $env_w3tc_ssl = '';
882
  $env_w3tc_ext = '';
883
  $env_w3tc_enc = '';
888
  $rules .= "rewrite ^(.*\\/)?w3tc_rewrite_test([0-9]+)/?$ $1?w3tc_rewrite_test=1 last;\n";
889
  }
890
 
891
+ /**
892
+ * Set accept query strings
893
+ */
894
+ $w3tc_query_strings = $config->get_array( 'pgcache.accept.qs' );
895
+ Util_Rule::array_trim( $w3tc_query_strings );
896
+
897
+ if ( !empty( $w3tc_query_strings ) ) {
898
+ $w3tc_query_strings = str_replace( ' ', '+', $w3tc_query_strings );
899
+ $w3tc_query_strings = array_map( array( '\W3TC\Util_Environment', 'preg_quote' ), $w3tc_query_strings );
900
+
901
+ $rules .= "set \$w3tc_query_string \$query_string;\n";
902
+
903
+ foreach ( $w3tc_query_strings as $query ) {
904
+ $query .= ( strpos( $query, '=' ) === false ? '.*?' : '' );
905
+ $rules .= "if (\$w3tc_query_string ~* \"^(.*?&|)".$query."(&.*|)$\") {\n";
906
+ $rules .= " set \$w3tc_query_string $1$2;\n";
907
+ $rules .= "}\n";
908
+ }
909
+
910
+ $rules .= "if (\$w3tc_query_string ~ ^&+$) {\n";
911
+ $rules .= " set \$w3tc_query_string \"\";\n";
912
+ $rules .= "}\n";
913
+ }
914
+
915
  /**
916
  * Check for mobile redirect
917
  */
970
  /**
971
  * Query string should be empty
972
  */
973
+ $querystring_variable = ( empty( $w3tc_query_strings ) ?
974
+ '$query_string' : '$w3tc_query_string' );
975
+
976
+ $rules .= "if (" . $querystring_variable . " != \"\") {\n";
977
  $rules .= " set \$w3tc_rewrite 0;\n";
978
  $rules .= "}\n";
979
 
1074
  }
1075
  }
1076
 
1077
+ /**
1078
+ * Set cookie group
1079
+ */
1080
+ if ( $config->get_boolean( 'pgcache.cookiegroups.enabled' ) ) {
1081
+ $cookie_groups = $config->get_array( 'pgcache.cookiegroups.groups' );
1082
+ $set_cookie_var = true;
1083
+
1084
+ foreach ( $cookie_groups as $group_name => $g ) {
1085
+ if ( isset( $g['enabled'] ) && $g['enabled'] ) {
1086
+ $cookies = array();
1087
+ foreach ($g['cookies'] as $cookie ) {
1088
+ $cookie = trim( $cookie );
1089
+ if ( !empty( $cookie ) ) {
1090
+ $cookie = str_replace( '+', ' ', $cookie );
1091
+ $cookie = Util_Environment::preg_quote( $cookie );
1092
+ if ( strpos( $cookie, '=') === false )
1093
+ $cookie .= '=.*';
1094
+ $cookies[] = $cookie;
1095
+ }
1096
+ }
1097
+
1098
+ if ( count( $cookies ) > 0 ) {
1099
+ $cookies_regexp = '"^(.*;)?(' . implode( '|', $cookies ) . ')(;.*)?$"';
1100
+
1101
+ if ( $set_cookie_var ) {
1102
+ $rules .= "set \$w3tc_cookie \"\";\n";
1103
+ $set_cookie_var = false;
1104
+ }
1105
+ $rules .= "if (\$http_cookie ~* $cookies_regexp) {\n";
1106
+ $rules .= " set \$w3tc_cookie _" . $group_name . ";\n";
1107
+ $rules .= "}\n";
1108
+
1109
+ $env_w3tc_cookie = "\$w3tc_cookie";
1110
+ }
1111
+ }
1112
+ }
1113
+ }
1114
+
1115
  if ( $config->get_boolean( 'pgcache.cache.ssl' ) ) {
1116
  $rules .= "set \$w3tc_ssl \"\";\n";
1117
 
1118
  $rules .= "if (\$scheme = https) {\n";
1119
  $rules .= " set \$w3tc_ssl _ssl;\n";
1120
  $rules .= "}\n";
1121
+ $rules .= "if (\$http_x_forwarded_proto = 'https') {\n";
1122
+ $rules .= " set \$w3tc_ssl _ssl;\n";
1123
+ $rules .= "}\n";
1124
 
1125
  $env_w3tc_ssl = "\$w3tc_ssl";
1126
  }
1139
  $cache_path = str_replace( Util_Environment::document_root(), '', $cache_dir );
1140
  $uri_prefix = $cache_path . "/\$http_host/" .
1141
  "\$request_uri/_index" . $env_w3tc_ua . $env_w3tc_ref .
1142
+ $env_w3tc_cookie . $env_w3tc_ssl . $env_w3tc_preview;
1143
 
1144
  if ( !$config->get_boolean( 'pgcache.cache.nginx_handle_xml' ) ) {
1145
  $env_w3tc_ext = '.html';
1268
 
1269
  // allow to read files by apache if they are blocked at some level above
1270
  $rules .= "<Files ~ \"\.(html|html_gzip|xml|xml_gzip)$\">\n";
1271
+
1272
+ if ( version_compare( Util_Environment::get_server_version(), '2.4', '>=' ) ) {
1273
+ $rules .= " Require all granted\n";
1274
+ } else {
1275
+ $rules .= " Order Allow,Deny\n";
1276
+ $rules .= " Allow from all\n";
1277
+ }
1278
+
1279
  $rules .= "</Files>\n";
1280
 
1281
  if ( !$etag ) {
1467
  $rules = '';
1468
  $rules .= W3TC_MARKER_BEGIN_PGCACHE_CACHE . "\n";
1469
 
1470
+ if ( !empty( $common_rules ) ) {
1471
+ $rules .= "location ~ " . $cache_dir . ".*html$ {\n";
1472
+ $rules .= $common_rules;
1473
+ $rules .= "}\n";
1474
+ }
1475
 
1476
  if ( $compression ) {
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
+
1484
  $rules .= "location ~ " . $cache_dir . ".*gzip$ {\n";
1485
  $rules .= " gzip off;\n";
1486
+ $rules .= " types {" . $maybe_xml . "}\n";
1487
  $rules .= " default_type text/html;\n";
1488
  $rules .= $common_rules;
1489
  $rules .= " add_header Content-Encoding gzip;\n";
PgCache_Flush.php CHANGED
@@ -45,7 +45,7 @@ class PgCache_Flush extends PgCache_ContentGrabber {
45
  return false;
46
 
47
  $full_urls = array();
48
- $post = null;
49
  $terms = array();
50
 
51
  $feeds = $this->_config->get_array( 'pgcache.purge.feed.types' );
@@ -58,9 +58,6 @@ class PgCache_Flush extends PgCache_ContentGrabber {
58
  $terms = $this->_append_parent_terms( $terms, $terms );
59
  }
60
 
61
- $post = get_post( $post_id );
62
- $post_type = in_array( $post->post_type, array(
63
- 'post', 'page', 'attachment', 'revision' ) ) ? null : $post->post_type;
64
  $front_page = get_option( 'show_on_front' );
65
 
66
  /**
@@ -102,7 +99,7 @@ class PgCache_Flush extends PgCache_ContentGrabber {
102
  /**
103
  * Post author URLs
104
  */
105
- if ( $this->_config->get_boolean( 'pgcache.purge.author' ) ) {
106
  $full_urls = array_merge( $full_urls,
107
  Util_PageUrls::get_post_author_urls( $post->post_author,
108
  $limit_post_pages ) );
@@ -143,7 +140,13 @@ class PgCache_Flush extends PgCache_ContentGrabber {
143
  /**
144
  * Feed URLs
145
  */
146
- if ( $this->_config->get_boolean( 'pgcache.purge.feed.blog' ) ) {
 
 
 
 
 
 
147
  $full_urls = array_merge( $full_urls,
148
  Util_PageUrls::get_feed_urls( $feeds, $post_type ) );
149
  }
@@ -205,8 +208,11 @@ class PgCache_Flush extends PgCache_ContentGrabber {
205
  foreach ( $encryptions as $encryption ) {
206
  foreach ( $compressions as $compression ) {
207
  $page_keys = array();
208
- $page_keys[] = $this->_get_page_key( $mobile_group,
209
- $referrer_group, $encryption, $compression, false,
 
 
 
210
  $url );
211
  $page_keys = apply_filters(
212
  'w3tc_pagecache_flush_url_keys', $page_keys );
45
  return false;
46
 
47
  $full_urls = array();
48
+ $post = get_post( $post_id );
49
  $terms = array();
50
 
51
  $feeds = $this->_config->get_array( 'pgcache.purge.feed.types' );
58
  $terms = $this->_append_parent_terms( $terms, $terms );
59
  }
60
 
 
 
 
61
  $front_page = get_option( 'show_on_front' );
62
 
63
  /**
99
  /**
100
  * Post author URLs
101
  */
102
+ if ( $this->_config->get_boolean( 'pgcache.purge.author' ) && $post ) {
103
  $full_urls = array_merge( $full_urls,
104
  Util_PageUrls::get_post_author_urls( $post->post_author,
105
  $limit_post_pages ) );
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
  }
208
  foreach ( $encryptions as $encryption ) {
209
  foreach ( $compressions as $compression ) {
210
  $page_keys = array();
211
+ $page_keys[] = $this->_get_page_key( array(
212
+ 'useragent' => $mobile_group,
213
+ 'referrer' => $referrer_group,
214
+ 'encryption' => $encryption,
215
+ 'compression' => $compression ),
216
  $url );
217
  $page_keys = apply_filters(
218
  'w3tc_pagecache_flush_url_keys', $page_keys );
PgCache_Page.php CHANGED
@@ -33,9 +33,7 @@ class PgCache_Page extends Base_Page_Settings {
33
  $permalink_structure = get_option( 'permalink_structure' );
34
 
35
  $varnish_enabled = $this->_config->get_boolean( 'varnish.enabled' );
36
- $cdn_mirror_purge_enabled =
37
- Cdn_Util::is_engine_fsd( $this->_config->get_string( 'cdn.engine' ) ) &&
38
- $this->_config->get_boolean( 'cdn.enabled' );
39
  include W3TC_INC_DIR . '/options/pgcache.php';
40
  }
41
  }
33
  $permalink_structure = get_option( 'permalink_structure' );
34
 
35
  $varnish_enabled = $this->_config->get_boolean( 'varnish.enabled' );
36
+ $cdnfsd_enabled = $this->_config->get_boolean( 'cdnfsd.enabled' );
 
 
37
  include W3TC_INC_DIR . '/options/pgcache.php';
38
  }
39
  }
PgCache_Page_CookieGroups.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+
5
+
6
+ class PgCache_Page_CookieGroups {
7
+ static public function admin_init_w3tc_pgcache_cookiegroups() {
8
+ wp_enqueue_script( 'jquery-ui-sortable' );
9
+ wp_enqueue_script( 'w3tc_pgcache_page_cookiegroups',
10
+ plugins_url( 'PgCache_Page_CookieGroups_View.js', W3TC_FILE ),
11
+ array( 'jquery', 'jquery-ui-sortable' ), '1.0' );
12
+ }
13
+
14
+
15
+
16
+ static public function w3tc_settings_page_w3tc_pgcache_cookiegroups() {
17
+ $c = Dispatcher::config();
18
+
19
+ $groups = array(
20
+ 'value' => $c->get_array( 'pgcache.cookiegroups.groups' ),
21
+ 'disabled' => $c->is_sealed( 'pgcache.cookiegroups.groups' )
22
+ );
23
+
24
+ $groups = apply_filters( 'w3tc_ui_config_item_pgcache.cookiegroups.groups', $groups );
25
+ $config = Dispatcher::config();
26
+
27
+ include W3TC_DIR . '/PgCache_Page_CookieGroups_View.php';
28
+ }
29
+
30
+
31
+
32
+ static public function w3tc_config_ui_save_w3tc_pgcache_cookiegroups( $config ) {
33
+ $groups = Util_Request::get_array( 'cookiegroups' );
34
+
35
+ $mobile_groups = array();
36
+ $cached_mobile_groups = array();
37
+
38
+ foreach ( $groups as $group => $group_config ) {
39
+ $group = strtolower( $group );
40
+ $group = preg_replace( '~[^0-9a-z_]+~', '_', $group );
41
+ $group = trim( $group, '_' );
42
+
43
+ if ( $group ) {
44
+ $enabled = ( isset( $group_config['enabled'] ) ?
45
+ (boolean) $group_config['enabled'] : false );
46
+ $cache = ( isset( $group_config['cache'] ) ?
47
+ (boolean) $group_config['cache'] : false );
48
+ $cookies = ( isset( $group_config['cookies'] ) ?
49
+ explode( "\r\n", trim( $group_config['cookies'] ) ) :
50
+ array() );
51
+
52
+ $cookies = array_unique( $cookies );
53
+ sort( $cookies );
54
+
55
+ $cookiegroups[$group] = array(
56
+ 'enabled' => $enabled,
57
+ 'cache' => $cache,
58
+ 'cookies' => $cookies
59
+ );
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Allow plugins modify W3TC mobile groups
65
+ */
66
+ $cookiegroups = apply_filters( 'w3tc_pgcache_cookiegroups', $cookiegroups );
67
+
68
+ $enabled = false;
69
+ foreach ( $cookiegroups as $group_config ) {
70
+ if ( $group_config['enabled'] ) {
71
+ $enabled = true;
72
+ break;
73
+ }
74
+ }
75
+ $config->set( 'pgcache.cookiegroups.enabled', $enabled );
76
+ $config->set( 'pgcache.cookiegroups.groups', $cookiegroups );
77
+ }
78
+ }
PgCache_Page_CookieGroups_View.js ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function() {
2
+
3
+
4
+ function w3tc_cookiegroups_clear() {
5
+ if (!jQuery('#cookiegroups li').size()) {
6
+ jQuery('#cookiegroups_empty').show();
7
+ } else {
8
+ jQuery('#cookiegroups_empty').hide();
9
+ }
10
+ }
11
+
12
+
13
+
14
+ jQuery('#w3tc_cookiegroup_add').click(function() {
15
+ var group = prompt('Enter group name (only "0-9", "a-z", "_" symbols are allowed).');
16
+
17
+ if (group !== null) {
18
+ group = group.toLowerCase();
19
+ group = group.replace(/[^0-9a-z_]+/g, '_');
20
+ group = group.replace(/^_+/, '');
21
+ group = group.replace(/_+$/, '');
22
+
23
+ if (group) {
24
+ var exists = false;
25
+
26
+ jQuery('.cookiegroup_name').each(function() {
27
+ if (jQuery(this).html() == group) {
28
+ alert('Group already exists!');
29
+ exists = true;
30
+ return false;
31
+ }
32
+ });
33
+
34
+ if (!exists) {
35
+ var li = jQuery('<li id="cookiegroup_' + group + '">' +
36
+ '<table class="form-table">' +
37
+ '<tr>' +
38
+ '<th>Group name:</th>' +
39
+ '<td><span class="cookiegroup_number">' + (jQuery('#cookiegroups li').size() + 1) + '.</span> ' +
40
+ '<span class="cookiegroup_name">' + group + '</span> ' +
41
+ '<input type="button" class="button cookiegroup_delete" value="Delete group" /></td>' +
42
+ '</tr>' +
43
+ '<tr>' +
44
+ '<th><label for="cookiegroup_' + group + '_enabled">Enabled:</label></th>' +
45
+ '<td>' +
46
+ '<input id="cookiegroup_' + group + '_enabled" type="checkbox" name="cookiegroups[' +
47
+ group + '][enabled]" value="1" checked="checked" /></td>' +
48
+ '</tr>' +
49
+ '<tr>' +
50
+ '<th><label for="cookiegroup_' + group + '_cache">Cache:</label></th>' +
51
+ '<td>' +
52
+ '<input id="cookiegroup_' + group + '_cache" type="checkbox" name="cookiegroups[' +
53
+ group + '][cache]" value="1" checked="checked" /></td></tr>' +
54
+ '<tr>' +
55
+ '<th><label for="cookiegroups_' + group + '_cookies">Cookies:</label></th>' +
56
+ '<td><textarea id="cookiegroups_' + group + '_cookies" name="cookiegroups[' +
57
+ group + '][cookies]" rows="10" cols="50"></textarea><br />' +
58
+ '<span class="description">Specify the cookies for this group. Values like \'cookie\', \'cookie=value\', and cookie[a-z]+=value[a-z]+are supported. Remember to escape special characters like spaces, dots or dashes with a backslash. Regular expressions are also supported.</span></td></tr>' +
59
+ '</table></li>');
60
+ var select = li.find('select');
61
+
62
+ jQuery('#cookiegroups').append(li);
63
+ w3tc_cookiegroups_clear();
64
+ window.location.hash = '#cookiegroup_' + group;
65
+ li.find('textarea').focus();
66
+ }
67
+ } else {
68
+ alert('Empty group name!');
69
+ }
70
+ }
71
+ });
72
+
73
+ jQuery('.w3tc_cookiegroup_delete').live('click', function() {
74
+ if (confirm('Are you sure want to delete this group?')) {
75
+ jQuery(this).parents('#cookiegroups li').remove();
76
+ w3tc_cookiegroups_clear();
77
+ w3tc_beforeupload_bind();
78
+ }
79
+ });
80
+
81
+ w3tc_cookiegroups_clear();
82
+
83
+ // add sortable
84
+ if (jQuery.ui && jQuery.ui.sortable) {
85
+ jQuery('#cookiegroups').sortable({
86
+ axis: 'y',
87
+ stop: function() {
88
+ jQuery('#cookiegroups').find('.cookiegroup_number').each(function(index) {
89
+ jQuery(this).html((index + 1) + '.');
90
+ });
91
+ }
92
+ });
93
+ }
94
+
95
+
96
+ });
PgCache_Page_CookieGroups_View.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace W3TC;
3
+
4
+ if ( !defined( 'W3TC' ) )
5
+ die();
6
+
7
+ ?>
8
+
9
+ <p>
10
+ <?php _e( 'Cookie group support is always <span class="w3tc-enabled">enabled</span>.', 'w3-total-cache' ); ?>
11
+ </p>
12
+
13
+ <form action="admin.php?page=w3tc_pgcache_cookiegroups" method="post">
14
+ <div class="metabox-holder">
15
+ <?php Util_Ui::postbox_header( __( 'Manage Cookie Groups', 'w3-total-cache' ), '', 'manage' ); ?>
16
+ <p>
17
+ <input id="w3tc_cookiegroup_add" type="button" class="button"
18
+ <?php disabled( $groups['disabled'] ) ?>
19
+ value="<?php _e( 'Create a group', 'w3-total-cache' ); ?>" />
20
+ <?php _e( 'of Cookies by specifying names in the Cookies field. Assign a set of Cookies to ensure that a unique cache is created for each Cookie group. Drag and drop groups into order (if needed) to determine their priority (top -&gt; down).', 'w3-total-cache' ); ?>
21
+ </p>
22
+
23
+ <ul id="cookiegroups" class="w3tc_cachegroups">
24
+ <?php $index = 0; foreach ( $groups['value'] as $group => $group_config ): $index++; ?>
25
+ <li id="cookiegroup_<?php echo esc_attr( $group ); ?>">
26
+ <table class="form-table">
27
+ <tr>
28
+ <th>
29
+ <?php _e( 'Group name:', 'w3-total-cache' ); ?>
30
+ </th>
31
+ <td>
32
+ <span class="cookiegroup_number"><?php echo $index; ?>.</span>
33
+ <span class="cookiegroup_name"><?php echo htmlspecialchars( $group ); ?></span>
34
+ <input type="button" class="button w3tc_cookiegroup_delete"
35
+ value="Delete group"
36
+ <?php disabled( $groups['disabled'] ) ?> />
37
+ </td>
38
+ </tr>
39
+ <tr>
40
+ <th>
41
+ <label for="cookiegroup_<?php echo esc_attr( $group ); ?>_enabled">
42
+ <?php _e( 'Enabled:', 'w3-total-cache' ); ?>
43
+ </label>
44
+ </th>
45
+ <td>
46
+ <input id="cookiegroup_<?php echo esc_attr( $group ); ?>_enabled"
47
+ type="checkbox"
48
+ name="cookiegroups[<?php echo esc_attr( $group ); ?>][enabled]"
49
+ <?php disabled( $groups['disabled'] ) ?> value="1"
50
+ <?php checked( $group_config['enabled'], true ); ?> />
51
+ </td>
52
+ </tr>
53
+ <tr>
54
+ <th>
55
+ <label for="cookiegroup_<?php echo esc_attr( $group ); ?>_cache">
56
+ <?php _e( 'Cache:', 'w3-total-cache' ); ?>
57
+ </label>
58
+ </th>
59
+ <td>
60
+ <input id="cookiegroup_<?php echo esc_attr( $group ); ?>_cache"
61
+ type="checkbox"
62
+ name="cookiegroups[<?php echo esc_attr( $group ); ?>][cache]"
63
+ <?php disabled( $groups['disabled'] ) ?> value="1"
64
+ <?php checked( $group_config['cache'], true ); ?> />
65
+ </td>
66
+ </tr>
67
+ <tr>
68
+ <th>
69
+ <label for="cookiegroup_<?php echo esc_attr( $group ); ?>_cookies">
70
+ <?php _e( 'Cookies:', 'w3-total-cache' ); ?>
71
+ </label>
72
+ </th>
73
+ <td>
74
+ <textarea id="cookiegroup_<?php echo esc_attr( $group ); ?>_cookies"
75
+ name="cookiegroups[<?php echo esc_attr( $group ); ?>][cookies]"
76
+ rows="10" cols="50" <?php disabled( $groups['disabled'] ) ?>><?php echo esc_textarea( implode( "\r\n", (array) $group_config['cookies'] ) ); ?></textarea>
77
+ <br />
78
+ <span class="description">
79
+ <?php _e( 'Specify the cookies for this group. Values like \'cookie\', \'cookie=value\', and cookie[a-z]+=value[a-z]+ are supported. Remember to escape special characters like spaces, dots or dashes with a backslash. Regular expressions are also supported.', 'w3-total-cache' ); ?>
80
+ </span>
81
+ </td>
82
+ </tr>
83
+ </table>
84
+ </li>
85
+ <?php endforeach; ?>
86
+ </ul>
87
+ <div id="cookiegroups_empty" style="display: none;"><?php _e( 'No groups added. All Cookies recieve the same page and minify cache results.', 'w3-total-cache' ) ?></div>
88
+
89
+ <?php
90
+ if ( !$groups['disabled'] )
91
+ Util_Ui::button_config_save( 'pgcache_cookiegroups' );
92
+ Util_Ui::postbox_footer();
93
+
94
+ Util_Ui::postbox_header( __( 'Note(s):', 'w3-total-cache' ), '',
95
+ 'notes' );
96
+ ?>
97
+ <table class="form-table">
98
+ <tr>
99
+ <th colspan="2">
100
+ <ul>
101
+ <li>
102
+ <?php _e( 'Content is cached for each group separately.', 'w3-total-cache' ) ?>
103
+ </li>
104
+ <li>
105
+ <?php _e( 'Per the above, make sure that visitors are notified about the cookie as per any regulations in your market.', 'w3-total-cache' ) ?>
106
+ </li>
107
+ </ul>
108
+ </th>
109
+ </tr>
110
+ </table>
111
+ <?php Util_Ui::postbox_footer(); ?>
112
+ </div>
113
+ </form>
PgCache_Plugin_Admin.php CHANGED
@@ -35,6 +35,24 @@ class PgCache_Plugin_Admin {
35
  add_filter( 'w3tc_usage_statistics_summary_from_history', array(
36
  $this, 'w3tc_usage_statistics_summary_from_history' ), 10, 2 );
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
 
40
  function cleanup() {
@@ -206,6 +224,20 @@ class PgCache_Plugin_Admin {
206
  arsort( $locs );
207
 
208
  $urls = array_keys( $locs );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  }
210
  }
211
 
@@ -268,6 +300,17 @@ class PgCache_Plugin_Admin {
268
  return $errors;
269
  }
270
 
 
 
 
 
 
 
 
 
 
 
 
271
  public function w3tc_usage_statistics_summary_from_history( $summary, $history ) {
272
  // memcached servers
273
  if ( $this->_config->get_string( 'pgcache.engine' ) == 'memcached' ) {
35
  add_filter( 'w3tc_usage_statistics_summary_from_history', array(
36
  $this, 'w3tc_usage_statistics_summary_from_history' ), 10, 2 );
37
  }
38
+
39
+ // cookie groups
40
+ add_filter( 'w3tc_admin_menu', array( $this, 'w3tc_admin_menu' ) );
41
+ add_action( 'admin_init_w3tc_pgcache_cookiegroups', array(
42
+ '\W3TC\PgCache_Page_CookieGroups',
43
+ 'admin_init_w3tc_pgcache_cookiegroups'
44
+ ) );
45
+
46
+ add_action( 'w3tc_settings_page-w3tc_pgcache_cookiegroups', array(
47
+ '\W3TC\PgCache_Page_CookieGroups',
48
+ 'w3tc_settings_page_w3tc_pgcache_cookiegroups'
49
+ ) );
50
+
51
+ add_action( 'w3tc_config_ui_save-w3tc_pgcache_cookiegroups', array(
52
+ '\W3TC\PgCache_Page_CookieGroups',
53
+ 'w3tc_config_ui_save_w3tc_pgcache_cookiegroups'
54
+ ), 10, 1 );
55
+
56
  }
57
 
58
  function cleanup() {
224
  arsort( $locs );
225
 
226
  $urls = array_keys( $locs );
227
+ } elseif ( preg_match_all( '~<rss[^>]*>(.*?)</rss>~is', $response['body'], $sitemap_matches ) ) {
228
+
229
+ // rss feed format
230
+ if ( preg_match_all( '~<link[^>]*>(.*?)</link>~is', $response['body'], $url_matches ) ) {
231
+ foreach ( $url_matches[1] as $url_match ) {
232
+ $url = trim( $url_match );
233
+ $cdata_matches = null;
234
+ if ( preg_match( '~<!\[CDATA\[(.*)\]\]>~is', $url, $cdata_matches ) ) {
235
+ $url = $cdata_matches[1];
236
+ }
237
+
238
+ $urls[] = $url;
239
+ }
240
+ }
241
  }
242
  }
243
 
300
  return $errors;
301
  }
302
 
303
+ public function w3tc_admin_menu( $menu ) {
304
+ $menu['w3tc_pgcache_cookiegroups'] = array(
305
+ 'page_title' => __( 'Cookie Groups', 'w3-total-cache' ),
306
+ 'menu_text' => __( 'Cookie Groups', 'w3-total-cache' ),
307
+ 'visible_always' => false,
308
+ 'order' => 950
309
+ );
310
+
311
+ return $menu;
312
+ }
313
+
314
  public function w3tc_usage_statistics_summary_from_history( $summary, $history ) {
315
  // memcached servers
316
  if ( $this->_config->get_string( 'pgcache.engine' ) == 'memcached' ) {
Root_AdminActions.php CHANGED
@@ -45,7 +45,6 @@ class Root_AdminActions {
45
  'config' => 'Generic_AdminActions_Config',
46
  'test' => 'Generic_AdminActions_Test',
47
  'licensing' => 'Licensing_AdminActions',
48
- 'edge_mode' => 'Generic_AdminActions_EdgeMode',
49
  'extensions' => 'Extensions_AdminActions',
50
  'default' => 'Generic_AdminActions_Default',
51
  'support' => 'Support_AdminActions'
45
  'config' => 'Generic_AdminActions_Config',
46
  'test' => 'Generic_AdminActions_Test',
47
  'licensing' => 'Licensing_AdminActions',
 
48
  'extensions' => 'Extensions_AdminActions',
49
  'default' => 'Generic_AdminActions_Default',
50
  'support' => 'Support_AdminActions'
Root_AdminActivation.php CHANGED
@@ -43,7 +43,7 @@ class Root_AdminActivation {
43
 
44
  // try to save config file if needed, optional thing so exceptions
45
  // hidden
46
- if ( !file_exists( Config::util_config_filename( 0, false ) ) ) {
47
  try {
48
  // create folders
49
  $e->fix_in_wpadmin( $config );
43
 
44
  // try to save config file if needed, optional thing so exceptions
45
  // hidden
46
+ if ( !ConfigUtil::is_item_exists( 0, false ) ) {
47
  try {
48
  // create folders
49
  $e->fix_in_wpadmin( $config );
Root_AdminMenu.php CHANGED
@@ -25,86 +25,101 @@ class Root_AdminMenu {
25
  'w3tc_dashboard' => array(
26
  'page_title' => __( 'Dashboard', 'w3-total-cache' ),
27
  'menu_text' => __( 'Dashboard', 'w3-total-cache' ),
28
- 'visible_always' => true
 
29
  ),
30
  'w3tc_general' => array(
31
  'page_title' => __( 'General Settings', 'w3-total-cache' ),
32
  'menu_text' => __( 'General Settings', 'w3-total-cache' ),
33
- 'visible_always' => false
 
34
  ),
35
  'w3tc_pgcache' => array(
36
  'page_title' => __( 'Page Cache', 'w3-total-cache' ),
37
  'menu_text' => __( 'Page Cache', 'w3-total-cache' ),
38
- 'visible_always' => false
 
39
  ),
40
  'w3tc_minify' => array(
41
  'page_title' => __( 'Minify', 'w3-total-cache' ),
42
  'menu_text' => __( 'Minify', 'w3-total-cache' ),
43
- 'visible_always' => false
 
44
  ),
45
  'w3tc_dbcache' => array(
46
  'page_title' => __( 'Database Cache', 'w3-total-cache' ),
47
  'menu_text' => __( 'Database Cache', 'w3-total-cache' ),
48
- 'visible_always' => false
 
49
  ),
50
  'w3tc_objectcache' => array(
51
  'page_title' => __( 'Object Cache', 'w3-total-cache' ),
52
  'menu_text' => __( 'Object Cache', 'w3-total-cache' ),
53
- 'visible_always' => false
54
- )
55
- );
56
- $pages = array_merge( $pages, array(
57
- 'w3tc_browsercache' => array(
58
- 'page_title' => __( 'Browser Cache', 'w3-total-cache' ),
59
- 'menu_text' => __( 'Browser Cache', 'w3-total-cache' ),
60
- 'visible_always' => false
61
- ),
62
- 'w3tc_mobile' => array(
63
- 'page_title' => __( 'User Agent Groups', 'w3-total-cache' ),
64
- 'menu_text' => __( 'User Agent Groups', 'w3-total-cache' ),
65
- 'visible_always' => false
66
- ),
67
- 'w3tc_referrer' => array(
68
- 'page_title' => __( 'Referrer Groups', 'w3-total-cache' ),
69
- 'menu_text' => __( 'Referrer Groups', 'w3-total-cache' ),
70
- 'visible_always' => false
71
- ),
72
- 'w3tc_cdn' => array(
73
- 'page_title' => __( 'Content Delivery Network', 'w3-total-cache' ),
74
- 'menu_text' => __( '<acronym title="Content Delivery Network">CDN</acronym>', 'w3-total-cache' ),
75
- 'visible_always' => false
76
- )
77
- ) );
78
- $pages_tail = array(
 
79
  'w3tc_faq' => array(
80
  'page_title' => __( 'FAQ', 'w3-total-cache' ),
81
  'menu_text' => __( 'FAQ', 'w3-total-cache' ),
82
- 'visible_always' => true
 
83
  ),
84
  'w3tc_support' => array(
85
  'page_title' => __( 'Support', 'w3-total-cache' ),
86
  'menu_text' => __( '<span style="color: red;">Support</span>', 'w3-total-cache' ),
87
- 'visible_always' => true
 
88
  ),
89
  'w3tc_install' => array(
90
  'page_title' => __( 'Install', 'w3-total-cache' ),
91
  'menu_text' => __( 'Install', 'w3-total-cache' ),
92
- 'visible_always' => false
 
93
  ),
94
  'w3tc_about' => array(
95
  'page_title' => __( 'About', 'w3-total-cache' ),
96
  'menu_text' => __( 'About', 'w3-total-cache' ),
97
- 'visible_always' => true
 
98
  )
99
  );
100
  $pages = apply_filters( 'w3tc_admin_menu', $pages, $this->_config );
101
- $pages = array_merge( $pages, $pages_tail );
102
  return $pages;
103
  }
104
 
105
  function generate( $base_capability ) {
106
  $pages = $this->generate_menu_array();
107
 
 
 
 
 
 
108
  add_menu_page( __( 'Performance', 'w3-total-cache' ),
109
  __( 'Performance', 'w3-total-cache' ),
110
  apply_filters( 'w3tc_capability_menu_w3tc_dashboard',
25
  'w3tc_dashboard' => array(
26
  'page_title' => __( 'Dashboard', 'w3-total-cache' ),
27
  'menu_text' => __( 'Dashboard', 'w3-total-cache' ),
28
+ 'visible_always' => true,
29
+ 'order' => 100
30
  ),
31
  'w3tc_general' => array(
32
  'page_title' => __( 'General Settings', 'w3-total-cache' ),
33
  'menu_text' => __( 'General Settings', 'w3-total-cache' ),
34
+ 'visible_always' => false,
35
+ 'order' => 200
36
  ),
37
  'w3tc_pgcache' => array(
38
  'page_title' => __( 'Page Cache', 'w3-total-cache' ),
39
  'menu_text' => __( 'Page Cache', 'w3-total-cache' ),
40
+ 'visible_always' => false,
41
+ 'order' => 300
42
  ),
43
  'w3tc_minify' => array(
44
  'page_title' => __( 'Minify', 'w3-total-cache' ),
45
  'menu_text' => __( 'Minify', 'w3-total-cache' ),
46
+ 'visible_always' => false,
47
+ 'order' => 400
48
  ),
49
  'w3tc_dbcache' => array(
50
  'page_title' => __( 'Database Cache', 'w3-total-cache' ),
51
  'menu_text' => __( 'Database Cache', 'w3-total-cache' ),
52
+ 'visible_always' => false,
53
+ 'order' => 500
54
  ),
55
  'w3tc_objectcache' => array(
56
  'page_title' => __( 'Object Cache', 'w3-total-cache' ),
57
  'menu_text' => __( 'Object Cache', 'w3-total-cache' ),
58
+ 'visible_always' => false,
59
+ 'order' => 600
60
+ ),
61
+ 'w3tc_browsercache' => array(
62
+ 'page_title' => __( 'Browser Cache', 'w3-total-cache' ),
63
+ 'menu_text' => __( 'Browser Cache', 'w3-total-cache' ),
64
+ 'visible_always' => false,
65
+ 'order' => 700
66
+ ),
67
+ 'w3tc_mobile' => array(
68
+ 'page_title' => __( 'User Agent Groups', 'w3-total-cache' ),
69
+ 'menu_text' => __( 'User Agent Groups', 'w3-total-cache' ),
70
+ 'visible_always' => false,
71
+ 'order' => 800
72
+ ),
73
+ 'w3tc_referrer' => array(
74
+ 'page_title' => __( 'Referrer Groups', 'w3-total-cache' ),
75
+ 'menu_text' => __( 'Referrer Groups', 'w3-total-cache' ),
76
+ 'visible_always' => false,
77
+ 'order' => 900
78
+ ),
79
+ 'w3tc_cdn' => array(
80
+ 'page_title' => __( 'Content Delivery Network', 'w3-total-cache' ),
81
+ 'menu_text' => __( '<acronym title="Content Delivery Network">CDN</acronym>', 'w3-total-cache' ),
82
+ 'visible_always' => false,
83
+ 'order' => 1000
84
+ ),
85
  'w3tc_faq' => array(
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' ),
93
  'menu_text' => __( '<span style="color: red;">Support</span>', 'w3-total-cache' ),
94
+ 'visible_always' => true,
95
+ 'order' => 2100
96
  ),
97
  'w3tc_install' => array(
98
  'page_title' => __( 'Install', 'w3-total-cache' ),
99
  'menu_text' => __( 'Install', 'w3-total-cache' ),
100
+ 'visible_always' => false,
101
+ 'order' => 2200
102
  ),
103
  'w3tc_about' => array(
104
  'page_title' => __( 'About', 'w3-total-cache' ),
105
  'menu_text' => __( 'About', 'w3-total-cache' ),
106
+ 'visible_always' => true,
107
+ 'order' => 2300
108
  )
109
  );
110
  $pages = apply_filters( 'w3tc_admin_menu', $pages, $this->_config );
111
+
112
  return $pages;
113
  }
114
 
115
  function generate( $base_capability ) {
116
  $pages = $this->generate_menu_array();
117
 
118
+ uasort( $pages, function($a, $b) {
119
+ return ($a['order'] - $b['order']);
120
+ }
121
+ );
122
+
123
  add_menu_page( __( 'Performance', 'w3-total-cache' ),
124
  __( 'Performance', 'w3-total-cache' ),
125
  apply_filters( 'w3tc_capability_menu_w3tc_dashboard',
Root_Loader.php CHANGED
@@ -29,6 +29,8 @@ class Root_Loader {
29
  $plugins[] = new PgCache_Plugin();
30
  if ( $c->get_boolean( 'cdn.enabled' ) )
31
  $plugins[] = new Cdn_Plugin();
 
 
32
  if ( $c->get_boolean( 'browsercache.enabled' ) )
33
  $plugins[] = new BrowserCache_Plugin();
34
  if ( $c->get_boolean( 'minify.enabled' ) )
@@ -51,18 +53,18 @@ class Root_Loader {
51
  $plugins[] = new SystemOpCache_Plugin_Admin();
52
 
53
  $plugins[] = new Cdn_Plugin_Admin();
 
54
  if ( $c->get_string( 'cdn.engine' ) == 'highwinds' ) {
55
- } else if ( $c->get_string( 'cdn.engine' ) != 'netdna' )
56
- $plugins[] = new Cdn_Plugin_WidgetMaxCdn();
57
- else
58
- $plugins[] = new Cdn_Plugin_WidgetNetDna();
59
 
60
- if ( $c->get_boolean( 'widget.pagespeed.enabled' ) )
61
- $plugins[] = new PageSpeed_Plugin_Widget();
62
 
63
- $plugins[] = new Generic_Plugin_AdminCompatibility();
64
 
65
- if ( !( defined( 'W3TC_PRO' ) || Util_Environment::is_w3tc_enterprise() ) )
66
  $plugins[] = new Licensing_Plugin_Admin();
67
 
68
  if ( $c->get_boolean( 'pgcache.enabled' ) ||
29
  $plugins[] = new PgCache_Plugin();
30
  if ( $c->get_boolean( 'cdn.enabled' ) )
31
  $plugins[] = new Cdn_Plugin();
32
+ if ( $c->get_boolean( 'cdnfsd.enabled' ) )
33
+ $plugins[] = new Cdnfsd_Plugin();
34
  if ( $c->get_boolean( 'browsercache.enabled' ) )
35
  $plugins[] = new BrowserCache_Plugin();
36
  if ( $c->get_boolean( 'minify.enabled' ) )
53
  $plugins[] = new SystemOpCache_Plugin_Admin();
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
+ }
 
61
 
62
+ if ( $c->get_boolean( 'widget.pagespeed.enabled' ) )
63
+ $plugins[] = new PageSpeed_Plugin_Widget();
64
 
65
+ $plugins[] = new Generic_Plugin_AdminCompatibility();
66
 
67
+ if ( !( defined( 'W3TC_PRO' ) || defined( 'W3TC_ENTERPRISE' ) ) )
68
  $plugins[] = new Licensing_Plugin_Admin();
69
 
70
  if ( $c->get_boolean( 'pgcache.enabled' ) ||
Support_AdminActions.php CHANGED
@@ -21,8 +21,6 @@ class Support_AdminActions {
21
  $license_level = 'community';
22
  if ( Util_Environment::is_w3tc_pro( $c ) )
23
  $license_level = 'pro';
24
- elseif ( Util_Environment::is_w3tc_enterprise( $c ) )
25
- $license_level = 'enterprise';
26
 
27
  $post['license_level'] = $license_level . ' ' .
28
  $c->get_string( 'plugin.license_key' );
21
  $license_level = 'community';
22
  if ( Util_Environment::is_w3tc_pro( $c ) )
23
  $license_level = 'pro';
 
 
24
 
25
  $post['license_level'] = $license_level . ' ' .
26
  $c->get_string( 'plugin.license_key' );
Util_Admin.php CHANGED
@@ -313,8 +313,6 @@ class Util_Admin {
313
  'cdn.azure.ssl',
314
  'cdn.mirror.domain',
315
  'cdn.mirror.ssl',
316
- 'cdn.netdna.domain',
317
- 'cdn.netdna.ssl',
318
  'cdn.cotendo.domain',
319
  'cdn.cotendo.ssl',
320
  'cdn.edgecast.domain',
@@ -742,30 +740,10 @@ class Util_Admin {
742
  static public function get_current_page() {
743
  $page = Util_Request::get_string( 'page' );
744
 
745
- switch ( true ) {
746
- case ( $page == 'w3tc_dashboard' ):
747
- case ( $page == 'w3tc_general' ):
748
- case ( $page == 'w3tc_pgcache' ):
749
- case ( $page == 'w3tc_minify' ):
750
- case ( $page == 'w3tc_dbcache' ):
751
- case ( $page == 'w3tc_objectcache' ):
752
- case ( $page == 'w3tc_fragmentcache' ):
753
- case ( $page == 'w3tc_browsercache' ):
754
- case ( $page == 'w3tc_mobile' ):
755
- case ( $page == 'w3tc_referrer' ):
756
- case ( $page == 'w3tc_cdn' ):
757
- case ( $page == 'w3tc_extensions' ):
758
- case ( $page == 'w3tc_install' ):
759
- case ( $page == 'w3tc_faq' ):
760
- case ( $page == 'w3tc_about' ):
761
- case ( $page == 'w3tc_support' ):
762
- break;
763
-
764
- default:
765
- $page = 'w3tc_dashboard';
766
- }
767
 
768
- return $page;
769
  }
770
 
771
  /**
313
  'cdn.azure.ssl',
314
  'cdn.mirror.domain',
315
  'cdn.mirror.ssl',
 
 
316
  'cdn.cotendo.domain',
317
  'cdn.cotendo.ssl',
318
  'cdn.edgecast.domain',
740
  static public function get_current_page() {
741
  $page = Util_Request::get_string( 'page' );
742
 
743
+ if ( substr( $page, 0, 5 ) == 'w3tc_' )
744
+ return $page;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
 
746
+ return 'w3tc_dashboard';
747
  }
748
 
749
  /**
Util_AttachToActions.php CHANGED
@@ -19,6 +19,18 @@ class Util_AttachToActions {
19
  $o,
20
  'on_post_change'
21
  ), 0, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
22
  add_action( 'publish_post', array(
23
  $o,
24
  'on_post_change'
19
  $o,
20
  'on_post_change'
21
  ), 0, 2 );
22
+
23
+ // when post status is changed to draft - it looses its URL
24
+ // so we need to flush before update is happened
25
+ add_action( 'pre_post_update', array(
26
+ $o,
27
+ 'on_post_change'
28
+ ), 0 );
29
+ add_action( 'wp_trash_post', array(
30
+ $o,
31
+ 'on_post_change'
32
+ ), 0 );
33
+
34
  add_action( 'publish_post', array(
35
  $o,
36
  'on_post_change'
Util_Debug.php CHANGED
@@ -50,4 +50,13 @@ class Util_Debug {
50
 
51
  return $filename;
52
  }
 
 
 
 
 
 
 
 
 
53
  }
50
 
51
  return $filename;
52
  }
53
+
54
+
55
+
56
+ static public function log( $module, $message ) {
57
+ $message = strtr( $message, '<>', '..' );
58
+ $filename = Util_Debug::log_filename( $module );
59
+
60
+ return @file_put_contents( $filename, date( 'r' ) . ' ' . $message . "\n", FILE_APPEND );
61
+ }
62
  }
Util_Environment.php CHANGED
@@ -135,9 +135,14 @@ class Util_Environment {
135
  * @return boolean
136
  */
137
  static public function is_dbcluster() {
 
 
 
 
 
 
138
  return defined( 'W3TC_FILE_DB_CLUSTER_CONFIG' ) &&
139
- @file_exists( W3TC_FILE_DB_CLUSTER_CONFIG )
140
- && defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE;
141
  }
142
 
143
  /**
@@ -844,7 +849,7 @@ class Util_Environment {
844
  * Removes WP query string from URL
845
  */
846
  static public function remove_query( $url ) {
847
- $url = preg_replace( '~[&\?]+(ver=([a-z0-9-_\.]+|[0-9-]+))~i', '', $url );
848
 
849
  return $url;
850
  }
@@ -1023,6 +1028,10 @@ class Util_Environment {
1023
  }
1024
 
1025
  static public function instance_id() {
 
 
 
 
1026
  static $instance_id;
1027
 
1028
  if ( !isset( $instance_id ) ) {
@@ -1039,8 +1048,6 @@ class Util_Environment {
1039
  * @return string
1040
  */
1041
  static public function w3tc_edition( $config = null ) {
1042
- if ( Util_Environment::is_w3tc_enterprise( $config ) )
1043
- return 'enterprise';
1044
  if ( Util_Environment::is_w3tc_pro( $config ) && Util_Environment::is_w3tc_pro_dev() )
1045
  return 'pro development';
1046
  if ( Util_Environment::is_w3tc_pro( $config ) )
@@ -1057,6 +1064,8 @@ class Util_Environment {
1057
  static public function is_w3tc_pro( $config = null ) {
1058
  if ( defined( 'W3TC_PRO' ) && W3TC_PRO )
1059
  return true;
 
 
1060
 
1061
  if ( is_object( $config ) ) {
1062
  $plugin_type = $config->get_string( 'plugin.type' );
@@ -1065,9 +1074,6 @@ class Util_Environment {
1065
  return true;
1066
  }
1067
 
1068
- if ( Util_Environment::is_w3tc_enterprise( $config ) )
1069
- return true;
1070
-
1071
  return false;
1072
  }
1073
 
@@ -1080,32 +1086,6 @@ class Util_Environment {
1080
  return defined( 'W3TC_PRO_DEV_MODE' ) && W3TC_PRO_DEV_MODE;
1081
  }
1082
 
1083
- /**
1084
- *
1085
- *
1086
- * @param Config $config
1087
- * @return bool
1088
- */
1089
- static public function is_w3tc_enterprise( $config = null ) {
1090
- if ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE )
1091
- return true;
1092
-
1093
- if ( is_object( $config ) &&
1094
- $config->get_string( 'plugin.type' ) == 'enterprise' )
1095
- return true;
1096
-
1097
- return false;
1098
- }
1099
-
1100
- /**
1101
- * Checks if site is using edge mode.
1102
- *
1103
- * @return bool
1104
- */
1105
- static public function is_w3tc_edge( $config ) {
1106
- return $config->get_boolean( 'common.edge' );
1107
- }
1108
-
1109
  /**
1110
  * Quotes regular expression string
1111
  *
@@ -1215,4 +1195,16 @@ class Util_Environment {
1215
 
1216
  return (boolean) $value;
1217
  }
 
 
 
 
 
 
 
 
 
 
 
 
1218
  }
135
  * @return boolean
136
  */
137
  static public function is_dbcluster() {
138
+ if ( !defined( 'W3TC_PRO' ) || !W3TC_PRO )
139
+ return false;
140
+
141
+ if ( isset( $GLOBALS['w3tc_dbcluster_config'] ) )
142
+ return true;
143
+
144
  return defined( 'W3TC_FILE_DB_CLUSTER_CONFIG' ) &&
145
+ @file_exists( W3TC_FILE_DB_CLUSTER_CONFIG );
 
146
  }
147
 
148
  /**
849
  * Removes WP query string from URL
850
  */
851
  static public function remove_query( $url ) {
852
+ $url = preg_replace( '~(\?|&amp;|&#038;|&)+ver=[a-z0-9-_\.]+~i', '', $url );
853
 
854
  return $url;
855
  }
1028
  }
1029
 
1030
  static public function instance_id() {
1031
+ if ( defined( 'W3TC_INSTANCE_ID' ) ) {
1032
+ return W3TC_INSTANCE_ID;
1033
+ }
1034
+
1035
  static $instance_id;
1036
 
1037
  if ( !isset( $instance_id ) ) {
1048
  * @return string
1049
  */
1050
  static public function w3tc_edition( $config = null ) {
 
 
1051
  if ( Util_Environment::is_w3tc_pro( $config ) && Util_Environment::is_w3tc_pro_dev() )
1052
  return 'pro development';
1053
  if ( Util_Environment::is_w3tc_pro( $config ) )
1064
  static public function is_w3tc_pro( $config = null ) {
1065
  if ( defined( 'W3TC_PRO' ) && W3TC_PRO )
1066
  return true;
1067
+ if ( defined( 'W3TC_ENTERPRISE' ) && W3TC_ENTERPRISE )
1068
+ return true;
1069
 
1070
  if ( is_object( $config ) ) {
1071
  $plugin_type = $config->get_string( 'plugin.type' );
1074
  return true;
1075
  }
1076
 
 
 
 
1077
  return false;
1078
  }
1079
 
1086
  return defined( 'W3TC_PRO_DEV_MODE' ) && W3TC_PRO_DEV_MODE;
1087
  }
1088
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1089
  /**
1090
  * Quotes regular expression string
1091
  *
1195
 
1196
  return (boolean) $value;
1197
  }
1198
+
1199
+ /**
1200
+ * Returns the apache, nginx version
1201
+ *
1202
+ * @return string
1203
+ */
1204
+ static public function get_server_version() {
1205
+ $sig= explode( '/', $_SERVER['SERVER_SOFTWARE'] );
1206
+ $temp = isset( $sig[1] ) ? explode( ' ', $sig[1] ) : array( '0' );
1207
+ $version = $temp[0];
1208
+ return $version;
1209
+ }
1210
  }
Util_PageUrls.php CHANGED
@@ -500,7 +500,9 @@ class Util_PageUrls {
500
 
501
  $base = trailingslashit( get_bloginfo( 'url' ) );
502
 
503
- if ( $wp_rewrite->using_index_permalinks() && ( $pagenum > 1 || '' != $request ) )
 
 
504
  $base .= 'index.php/';
505
 
506
  if ( $pagenum > 1 ) {
500
 
501
  $base = trailingslashit( get_bloginfo( 'url' ) );
502
 
503
+ if ( !is_null( $wp_rewrite ) &&
504
+ $wp_rewrite->using_index_permalinks() &&
505
+ ( $pagenum > 1 || '' != $request ) )
506
  $base .= 'index.php/';
507
 
508
  if ( $pagenum > 1 ) {
Util_Rule.php CHANGED
@@ -240,9 +240,15 @@ class Util_Rule {
240
  if ( $data === false )
241
  $data = '';
242
 
243
- $rules_missing = !empty( $rules ) && ( strstr( Util_Rule::clean_rules( $data ), Util_Rule::clean_rules( $rules ) ) === false );
244
- if ( !$rules_missing )
245
- return;
 
 
 
 
 
 
246
 
247
  $replace_start = strpos( $data, $start );
248
  $replace_end = strpos( $data, $end );
240
  if ( $data === false )
241
  $data = '';
242
 
243
+ if ( empty( $rules ) ) {
244
+ $rules_present = ( strpos( $data, $start ) !== false );
245
+ if ( !$rules_present )
246
+ return;
247
+ } else {
248
+ $rules_missing = ( strstr( Util_Rule::clean_rules( $data ), Util_Rule::clean_rules( $rules ) ) === false );
249
+ if ( !$rules_missing )
250
+ return;
251
+ }
252
 
253
  $replace_start = strpos( $data, $start );
254
  $replace_end = strpos( $data, $end );
Util_RuleSnippet.php CHANGED
@@ -8,7 +8,8 @@ class Util_RuleSnippet {
8
  * @param bool $cdnftp
9
  * @return string
10
  */
11
- static public function canonical_without_location( $cdnftp = false, $add_header_rules ) {
 
12
  $rules = '';
13
 
14
  switch ( true ) {
@@ -34,14 +35,17 @@ class Util_RuleSnippet {
34
  $link_header = ' add_header Link "<$scheme://' .
35
  $home . '$uri>; rel=\"canonical\"";' . "\n";
36
 
37
- $rules .=
38
- $link_header .
 
 
39
  ' if ($request_uri ~ ^[^?]*\\.(ttf|ttc|otf|eot|woff|woff2|font.css)(\\?|$)) {' .
40
  "\n " . $link_header .
41
  " " .
42
  str_replace( "\n", "\n ", $add_header_rules ) .
43
  " add_header Access-Control-Allow-Origin \"*\";\n" .
44
  " }\n";
 
45
 
46
  break;
47
  }
@@ -55,7 +59,7 @@ class Util_RuleSnippet {
55
  * @param bool $cdnftp
56
  * @return string
57
  */
58
- static public function canonical( $cdnftp = false ) {
59
  $rules = '';
60
 
61
  $mime_types = self::_get_other_types();
@@ -68,13 +72,13 @@ class Util_RuleSnippet {
68
  $extensions_uppercase = array_map( 'strtoupper', $extensions );
69
  $rules .= "<FilesMatch \"\\.(" . implode( '|',
70
  array_merge( $extensions_lowercase, $extensions_uppercase ) ) . ")$\">\n";
71
- $rules .= self::canonical_without_location( $cdnftp, '' );
72
  $rules .= "</FilesMatch>\n";
73
  break;
74
 
75
  case Util_Environment::is_nginx():
76
  $rules .= "location ~ \.(" . implode( '|', $extensions ) . ")$ {\n";
77
- $rules .= self::canonical_without_location( $cdnftp, '' );
78
  $rules .= "}\n";
79
  break;
80
  }
@@ -82,33 +86,6 @@ class Util_RuleSnippet {
82
  return $rules;
83
  }
84
 
85
-
86
- /**
87
- * Returns allow-origin rules
88
- *
89
- * @param bool $cdnftp
90
- * @return string
91
- */
92
- static public function allow_origin( $cdnftp = false ) {
93
- switch ( true ) {
94
- case Util_Environment::is_apache():
95
- case Util_Environment::is_litespeed():
96
- $r = "<IfModule mod_headers.c>\n";
97
- $r .= " Header set Access-Control-Allow-Origin \"*\"\n";
98
- $r .= "</IfModule>\n";
99
-
100
- if ( !$cdnftp )
101
- return $r;
102
- else
103
- return
104
- "<FilesMatch \"\.(ttf|ttc|otf|eot|woff|woff2|font.css)$\">\n" .
105
- $r .
106
- "</FilesMatch>\n";
107
- }
108
-
109
- return '';
110
- }
111
-
112
  /**
113
  * Returns other mime types
114
  *
8
  * @param bool $cdnftp
9
  * @return string
10
  */
11
+ static public function canonical_without_location( $cdnftp = false,
12
+ $add_header_rules, $cors_header ) {
13
  $rules = '';
14
 
15
  switch ( true ) {
35
  $link_header = ' add_header Link "<$scheme://' .
36
  $home . '$uri>; rel=\"canonical\"";' . "\n";
37
 
38
+ $rules .= $link_header;
39
+
40
+ if ( $cors_header ) {
41
+ $rules .=
42
  ' if ($request_uri ~ ^[^?]*\\.(ttf|ttc|otf|eot|woff|woff2|font.css)(\\?|$)) {' .
43
  "\n " . $link_header .
44
  " " .
45
  str_replace( "\n", "\n ", $add_header_rules ) .
46
  " add_header Access-Control-Allow-Origin \"*\";\n" .
47
  " }\n";
48
+ }
49
 
50
  break;
51
  }
59
  * @param bool $cdnftp
60
  * @return string
61
  */
62
+ static public function canonical( $cdnftp = false, $cors_header ) {
63
  $rules = '';
64
 
65
  $mime_types = self::_get_other_types();
72
  $extensions_uppercase = array_map( 'strtoupper', $extensions );
73
  $rules .= "<FilesMatch \"\\.(" . implode( '|',
74
  array_merge( $extensions_lowercase, $extensions_uppercase ) ) . ")$\">\n";
75
+ $rules .= self::canonical_without_location( $cdnftp, '', $cors_header );
76
  $rules .= "</FilesMatch>\n";
77
  break;
78
 
79
  case Util_Environment::is_nginx():
80
  $rules .= "location ~ \.(" . implode( '|', $extensions ) . ")$ {\n";
81
+ $rules .= self::canonical_without_location( $cdnftp, '', $cors_header );
82
  $rules .= "}\n";
83
  break;
84
  }
86
  return $rules;
87
  }
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  /**
90
  * Returns other mime types
91
  *
Util_Ui.php CHANGED
@@ -531,7 +531,7 @@ class Util_Ui {
531
  $a = apply_filters( 'w3tc_ui_settings_item', $a );
532
 
533
  if ( isset( $a['style'] ) ) {
534
- echo '<tr><th colspan="2"';
535
  } else {
536
  echo '<tr><th';
537
 
531
  $a = apply_filters( 'w3tc_ui_settings_item', $a );
532
 
533
  if ( isset( $a['style'] ) ) {
534
+ echo '<tr><th colspan="2">';
535
  } else {
536
  echo '<tr><th';
537
 
inc/lightbox/edge.php DELETED
@@ -1,24 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- if ( !defined( 'W3TC' ) )
5
- die();
6
-
7
- ?>
8
- <div id="w3tc-edge-mode">
9
- <div class="w3tc-overlay-logo"></div>
10
- <header>
11
- </header>
12
- <div class="content">
13
- <p><strong><?php _e( 'Enable "Edge Mode" to opt-in to pre-release features or simply close this window to continue to enjoy bug fixes, security fixes and stable updates only.', 'w3-total-cache' ) ?></strong></p>
14
- <p><?php _e( 'We want to ensure that those who are interested in ongoing performance optimizations always have access to the latest functionality and optimization techniques. Those who enable edge mode should have experience in troubleshooting WordPress installations.', 'w3-total-cache' ) ?></p>
15
- </div>
16
- <div class="w3tc_overlay_footer">
17
- <?php
18
- echo Util_Ui::action_button( __( 'Enable Edge Mode', 'w3-total-cache' ),
19
- Util_Ui::url( array( 'w3tc_edge_mode_enable' => 'y' ) ),
20
- "btn w3tc-size image btn-default palette-turquoise" )
21
- ?>
22
- <input type="button" class="btn w3tc-size btn-default outset palette-light-grey w3tc_lightbox_close" value="Cancel">
23
- </div>
24
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/lightbox/self_test.php CHANGED
@@ -11,10 +11,9 @@ if ( !defined( 'W3TC' ) )
11
  <legend><?php _e( 'Legend', 'w3-total-cache' ); ?></legend>
12
 
13
  <p>
14
- <?php _e( '<code>Installed</code>: Functionality will work properly.', 'w3-total-cache' ); ?><br />
15
- <?php _e( '<code>Not detected</code>: May be installed, but cannot be automatically confirmed.', 'w3-total-cache' ); ?><br />
16
- <?php _e( '<code>Ok</code>: Current value is acceptable.', 'w3-total-cache' ); ?><br />
17
- <?php _e( '<code>Yes / No</code>: The value was successful detected.', 'w3-total-cache' ); ?>
18
  </p>
19
  </fieldset>
20
 
@@ -44,16 +43,16 @@ if ( !defined( 'W3TC' ) )
44
  <?php elseif ( stristr( $_SERVER['SERVER_SOFTWARE'], 'iis' ) !== false ): ?>
45
  <code>Microsoft IIS</code>
46
  <?php else: ?>
47
- <code>Not detected</code>
48
  <?php endif; ?>
49
  </li>
50
 
51
  <li>
52
  FTP functions:
53
  <?php if ( function_exists( 'ftp_connect' ) ): ?>
54
- <code>Installed</code>
55
  <?php else: ?>
56
- <code>Not installed</code>
57
  <?php endif; ?>
58
  <span class="w3tc-self-test-hint"><?php _e( '(required for Self-hosted (<acronym title="File Transfer Protocol">FTP</acronym>) <acronym title="Content Delivery Network">CDN</acronym> support)', 'w3-total-cache' ); ?></span>
59
  </li>
@@ -61,9 +60,9 @@ if ( !defined( 'W3TC' ) )
61
  <li>
62
  <?php _e( 'Multibyte String support:', 'w3-total-cache' ); ?>
63
  <?php if ( function_exists( 'mb_substr' ) ): ?>
64
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
65
  <?php else: ?>
66
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
67
  <?php endif; ?>
68
  <span class="w3tc-self-test-hint"><?php _e( '(required for Rackspace Cloud Files support)', 'w3-total-cache' ); ?></span>
69
  </li>
@@ -71,9 +70,9 @@ if ( !defined( 'W3TC' ) )
71
  <li>
72
  <?php _e( 'cURL extension:', 'w3-total-cache' ); ?>
73
  <?php if ( function_exists( 'curl_init' ) ): ?>
74
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
75
  <?php else: ?>
76
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
77
  <?php endif; ?>
78
  <span class="w3tc-self-test-hint"><?php _e( '(required for Amazon S3, Amazon CloudFront, Rackspace CloudFiles support)', 'w3-total-cache' ); ?></span>
79
  </li>
@@ -81,9 +80,9 @@ if ( !defined( 'W3TC' ) )
81
  <li>
82
  zlib extension:
83
  <?php if ( function_exists( 'gzencode' ) ): ?>
84
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
85
  <?php else: ?>
86
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
87
  <?php endif; ?>
88
  <span class="w3tc-self-test-hint"><?php _e( '(required for compression support)', 'w3-total-cache' ); ?></span>
89
  </li>
@@ -91,53 +90,53 @@ if ( !defined( 'W3TC' ) )
91
  <li>
92
  Opcode cache:
93
  <?php if ( Util_Installed::opcache() ): ?>
94
- <code><?php _e( 'Installed (OPCache)', 'w3-total-cache' ); ?></code>
95
  <?php elseif ( Util_Installed::apc() ): ?>
96
- <code><?php _e( 'Installed (APC)', 'w3-total-cache' ); ?></code>
97
  <?php elseif ( Util_Installed::eaccelerator() ): ?>
98
- <code><?php _e( 'Installed (eAccelerator)', 'w3-total-cache' ); ?></code>
99
  <?php elseif ( Util_Installed::xcache() ): ?>
100
- <code><?php _e( 'Installed (XCache)', 'w3-total-cache' ); ?></code>
101
  <?php elseif ( PHP_VERSION >= 6 ): ?>
102
- <code><?php _e( 'PHP6', 'w3-total-cache' ); ?></code>
103
  <?php else: ?>
104
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
105
  <?php endif; ?>
106
  </li>
107
 
108
  <li>
109
  <?php _e( 'Memcached extension:', 'w3-total-cache' ); ?>
110
  <?php if ( class_exists( '\Memcached' ) ): ?>
111
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
112
  <?php else: ?>
113
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
114
  <?php endif; ?>
115
  </li>
116
 
117
  <li>
118
  <?php _e( 'Memcache extension:', 'w3-total-cache' ); ?>
119
  <?php if ( class_exists( '\Memcache' ) ): ?>
120
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
121
  <?php else: ?>
122
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
123
  <?php endif; ?>
124
  </li>
125
 
126
  <li>
127
  <?php _e( 'Redis extension:', 'w3-total-cache' ); ?>
128
  <?php if ( Util_Installed::redis() ): ?>
129
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
130
  <?php else: ?>
131
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
132
  <?php endif; ?>
133
  </li>
134
 
135
  <li>
136
  <?php _e( 'HTML Tidy extension:', 'w3-total-cache' ); ?>
137
  <?php if ( Util_Installed::tidy() ): ?>
138
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
139
  <?php else: ?>
140
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
141
  <?php endif; ?>
142
  <span class="w3tc-self-test-hint"><?php _e( '(required for HTML Tidy minifier support)', 'w3-total-cache' ); ?></span>
143
  </li>
@@ -145,11 +144,11 @@ if ( !defined( 'W3TC' ) )
145
  <li>
146
  <?php _e( 'Mime type detection:', 'w3-total-cache' ); ?>
147
  <?php if ( function_exists( 'finfo_open' ) ): ?>
148
- <code><?php _e( 'Installed (Fileinfo)', 'w3-total-cache' ); ?></code>
149
  <?php elseif ( function_exists( 'mime_content_type' ) ): ?>
150
- <code><?php _e( 'Installed (mime_content_type)', 'w3-total-cache' ); ?></code>
151
  <?php else: ?>
152
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
153
  <?php endif; ?>
154
  <span class="w3tc-self-test-hint"><?php _e( '(required for <acronym title="Content Delivery Network">CDN</acronym> support)', 'w3-total-cache' ); ?></span>
155
  </li>
@@ -157,11 +156,11 @@ if ( !defined( 'W3TC' ) )
157
  <li>
158
  <?php _e( 'Hash function:', 'w3-total-cache' ); ?>
159
  <?php if ( function_exists( 'hash' ) ): ?>
160
- <code><?php _e( 'Installed (hash)', 'w3-total-cache' ); ?></code>
161
  <?php elseif ( function_exists( 'mhash' ) ): ?>
162
- <code><?php _e( 'Installed (mhash)', 'w3-total-cache' ); ?></code>
163
  <?php else: ?>
164
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
165
  <?php endif; ?>
166
  <span class="w3tc-self-test-hint"><?php _e( '(required for NetDNA / MaxCDN <acronym title="Content Delivery Network">CDN</acronym> purge support)', 'w3-total-cache' ); ?></span>
167
  </li>
@@ -169,27 +168,27 @@ if ( !defined( 'W3TC' ) )
169
  <li>
170
  <?php _e( 'Open basedir:', 'w3-total-cache' ); ?>
171
  <?php $open_basedir = ini_get( 'open_basedir' ); if ( $open_basedir ): ?>
172
- <code><?php _e( 'On:', 'w3-total-cache' ); ?> <?php echo htmlspecialchars( $open_basedir ); ?></code>
173
  <?php else: ?>
174
- <code><?php _e( 'Off', 'w3-total-cache' ); ?></code>
175
  <?php endif; ?>
176
  </li>
177
 
178
  <li>
179
  <?php _e( 'zlib output compression:', 'w3-total-cache' ); ?>
180
  <?php if ( Util_Environment::to_boolean( ini_get( 'zlib.output_compression' ) ) ): ?>
181
- <code><?php _e( 'On', 'w3-total-cache' ); ?></code>
182
  <?php else: ?>
183
- <code><?php _e( 'Off', 'w3-total-cache' ); ?></code>
184
  <?php endif; ?>
185
  </li>
186
 
187
  <li>
188
  <?php _e( 'set_time_limit:', 'w3-total-cache' ); ?>
189
  <?php if ( function_exists( 'set_time_limit' ) ): ?>
190
- <code><?php _e( 'Available', 'w3-total-cache' ); ?></code>
191
  <?php else: ?>
192
- <code><?php _e( 'Not available', 'w3-total-cache' ); ?></code>
193
  <?php endif; ?>
194
  </li>
195
 
@@ -214,12 +213,12 @@ $modules = array(
214
  <?php echo $module; ?>:
215
  <?php if ( $apache_modules ): ?>
216
  <?php if ( in_array( $module, $apache_modules ) ): ?>
217
- <code><?php _e( 'Installed', 'w3-total-cache' ); ?></code>
218
  <?php else: ?>
219
- <code><?php _e( 'Not installed', 'w3-total-cache' ); ?></code>
220
  <?php endif; ?>
221
  <?php else: ?>
222
- <code><?php _e( 'Not detected', 'w3-total-cache' ); ?></code>
223
  <?php endif; ?>
224
  <span class="w3tc-self-test-hint"><?php _e( '(required for disk enhanced Page Cache and Browser Cache)', 'w3-total-cache' ); ?></span>
225
  </li>
@@ -254,15 +253,15 @@ $paths = array_unique( array(
254
  <?php echo htmlspecialchars( $path ); ?>:
255
  <?php if ( file_exists( $path ) ): ?>
256
  <?php if ( Util_File::is_writable( $path ) ): ?>
257
- <code><?php _e( 'OK', 'w3-total-cache' ); ?></code>
258
  <?php else: ?>
259
- <code><?php _e( 'Not write-able', 'w3-total-cache' ); ?></code>
260
  <?php endif; ?>
261
  <?php else: ?>
262
  <?php if ( Util_File::is_writable_dir( dirname( $path ) ) ): ?>
263
- <code><?php _e( 'Write-able', 'w3-total-cache' ); ?></code>
264
  <?php else: ?>
265
- <code><?php _e( 'Not write-able', 'w3-total-cache' ); ?></code>
266
  <?php endif; ?>
267
  <?php endif; ?>
268
  </li>
@@ -271,9 +270,9 @@ $paths = array_unique( array(
271
  <li>
272
  <?php echo Util_Environment::normalize_path( WP_CONTENT_DIR ); ?>:
273
  <?php if ( Util_File::is_writable_dir( WP_CONTENT_DIR ) ): ?>
274
- <code><?php _e( 'OK', 'w3-total-cache' ); ?></code>
275
  <?php else: ?>
276
- <code><?php _e( 'Not write-able', 'w3-total-cache' ); ?></code>
277
  <?php endif; ?>
278
  </li>
279
 
@@ -281,47 +280,49 @@ $paths = array_unique( array(
281
  <?php $uploads_dir = @wp_upload_dir(); ?>
282
  <?php echo htmlspecialchars( $uploads_dir['path'] ); ?>:
283
  <?php if ( !empty( $uploads_dir['error'] ) ): ?>
284
- <code><?php _e( 'Error:', 'w3-total-cache' ); ?> <?php echo htmlspecialchars( $uploads_dir['error'] ); ?></code>
285
  <?php elseif ( !Util_File::is_writable_dir( $uploads_dir['path'] ) ): ?>
286
- <code><?php _e( 'Not write-able', 'w3-total-cache' ); ?></code>
287
  <?php else: ?>
288
- <code><?php _e( 'OK', 'w3-total-cache' ); ?></code>
289
  <?php endif; ?>
290
  </li>
291
 
292
  <li>
293
  <?php _e( 'Fancy permalinks:', 'w3-total-cache' ); ?>
294
  <?php $permalink_structure = get_option( 'permalink_structure' ); if ( $permalink_structure ): ?>
295
- <code><?php echo htmlspecialchars( $permalink_structure ); ?></code>
296
  <?php else: ?>
297
- <code><?php _e( 'Disabled', 'w3-total-cache' ); ?></code>
298
  <?php endif; ?>
299
  </li>
300
 
301
  <li>
302
  <?php _e( 'WP_CACHE define:', 'w3-total-cache' ); ?>
303
- <?php if ( defined( 'WP_CACHE' ) ): ?>
304
- <code><?php _e( 'Defined', 'w3-total-cache' ); ?> (<?php echo WP_CACHE ? 'true' : 'false'; ?>)</code>
 
 
305
  <?php else: ?>
306
- <code><?php _e( 'Not defined', 'w3-total-cache' ); ?></code>
307
  <?php endif; ?>
308
  </li>
309
 
310
  <li>
311
  <?php _e( 'URL rewrite:', 'w3-total-cache' ); ?>
312
  <?php if ( Util_Rule::can_check_rules() ): ?>
313
- <code><?php _e( 'Enabled', 'w3-total-cache' ); ?></code>
314
  <?php else: ?>
315
- <code><?php _e( 'Disabled', 'w3-total-cache' ); ?></code>
316
  <?php endif; ?>
317
  </li>
318
 
319
  <li>
320
  <?php _e( 'Network mode:', 'w3-total-cache' ); ?>
321
  <?php if ( Util_Environment::is_wpmu() ): ?>
322
- <code><?php _e( 'Yes', 'w3-total-cache' ); ?> (<?php echo Util_Environment::is_wpmu_subdomain() ? 'subdomain' : 'subdir'; ?>)</code>
323
  <?php else: ?>
324
- <code><?php _e( 'No', 'w3-total-cache' ); ?></code>
325
  <?php endif; ?>
326
  </li>
327
  </ul>
11
  <legend><?php _e( 'Legend', 'w3-total-cache' ); ?></legend>
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>
19
 
43
  <?php elseif ( stristr( $_SERVER['SERVER_SOFTWARE'], 'iis' ) !== false ): ?>
44
  <code>Microsoft IIS</code>
45
  <?php else: ?>
46
+ <span style="background-color: #FFFF00">Not detected</span>
47
  <?php endif; ?>
48
  </li>
49
 
50
  <li>
51
  FTP functions:
52
  <?php if ( function_exists( 'ftp_connect' ) ): ?>
53
+ <span style="background-color: #33cc33">Installed</span>
54
  <?php else: ?>
55
+ <span style="background-color: #FFFF00">Not installed</span>
56
  <?php endif; ?>
57
  <span class="w3tc-self-test-hint"><?php _e( '(required for Self-hosted (<acronym title="File Transfer Protocol">FTP</acronym>) <acronym title="Content Delivery Network">CDN</acronym> support)', 'w3-total-cache' ); ?></span>
58
  </li>
60
  <li>
61
  <?php _e( 'Multibyte String support:', 'w3-total-cache' ); ?>
62
  <?php if ( function_exists( 'mb_substr' ) ): ?>
63
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
64
  <?php else: ?>
65
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
66
  <?php endif; ?>
67
  <span class="w3tc-self-test-hint"><?php _e( '(required for Rackspace Cloud Files support)', 'w3-total-cache' ); ?></span>
68
  </li>
70
  <li>
71
  <?php _e( 'cURL extension:', 'w3-total-cache' ); ?>
72
  <?php if ( function_exists( 'curl_init' ) ): ?>
73
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
74
  <?php else: ?>
75
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
76
  <?php endif; ?>
77
  <span class="w3tc-self-test-hint"><?php _e( '(required for Amazon S3, Amazon CloudFront, Rackspace CloudFiles support)', 'w3-total-cache' ); ?></span>
78
  </li>
80
  <li>
81
  zlib extension:
82
  <?php if ( function_exists( 'gzencode' ) ): ?>
83
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
84
  <?php else: ?>
85
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
86
  <?php endif; ?>
87
  <span class="w3tc-self-test-hint"><?php _e( '(required for compression support)', 'w3-total-cache' ); ?></span>
88
  </li>
90
  <li>
91
  Opcode cache:
92
  <?php if ( Util_Installed::opcache() ): ?>
93
+ <span style="background-color: #33cc33"><?php _e( 'Installed (OPCache)', 'w3-total-cache' ); ?></span>
94
  <?php elseif ( Util_Installed::apc() ): ?>
95
+ <span style="background-color: #33cc33"><?php _e( 'Installed (APC)', 'w3-total-cache' ); ?></span>
96
  <?php elseif ( Util_Installed::eaccelerator() ): ?>
97
+ <span style="background-color: #33cc33"><?php _e( 'Installed (eAccelerator)', 'w3-total-cache' ); ?></span>
98
  <?php elseif ( Util_Installed::xcache() ): ?>
99
+ <span style="background-color: #33cc33"><?php _e( 'Installed (XCache)', 'w3-total-cache' ); ?></span>
100
  <?php elseif ( PHP_VERSION >= 6 ): ?>
101
+ <span style="background-color: #33cc33"><?php _e( 'PHP6', 'w3-total-cache' ); ?></span>
102
  <?php else: ?>
103
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
104
  <?php endif; ?>
105
  </li>
106
 
107
  <li>
108
  <?php _e( 'Memcached extension:', 'w3-total-cache' ); ?>
109
  <?php if ( class_exists( '\Memcached' ) ): ?>
110
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
111
  <?php else: ?>
112
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
113
  <?php endif; ?>
114
  </li>
115
 
116
  <li>
117
  <?php _e( 'Memcache extension:', 'w3-total-cache' ); ?>
118
  <?php if ( class_exists( '\Memcache' ) ): ?>
119
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
120
  <?php else: ?>
121
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
122
  <?php endif; ?>
123
  </li>
124
 
125
  <li>
126
  <?php _e( 'Redis extension:', 'w3-total-cache' ); ?>
127
  <?php if ( Util_Installed::redis() ): ?>
128
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
129
  <?php else: ?>
130
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
131
  <?php endif; ?>
132
  </li>
133
 
134
  <li>
135
  <?php _e( 'HTML Tidy extension:', 'w3-total-cache' ); ?>
136
  <?php if ( Util_Installed::tidy() ): ?>
137
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
138
  <?php else: ?>
139
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
140
  <?php endif; ?>
141
  <span class="w3tc-self-test-hint"><?php _e( '(required for HTML Tidy minifier support)', 'w3-total-cache' ); ?></span>
142
  </li>
144
  <li>
145
  <?php _e( 'Mime type detection:', 'w3-total-cache' ); ?>
146
  <?php if ( function_exists( 'finfo_open' ) ): ?>
147
+ <span style="background-color: #33cc33"><?php _e( 'Installed (Fileinfo)', 'w3-total-cache' ); ?></span>
148
  <?php elseif ( function_exists( 'mime_content_type' ) ): ?>
149
+ <span style="background-color: #33cc33"><?php _e( 'Installed (mime_content_type)', 'w3-total-cache' ); ?></span>
150
  <?php else: ?>
151
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
152
  <?php endif; ?>
153
  <span class="w3tc-self-test-hint"><?php _e( '(required for <acronym title="Content Delivery Network">CDN</acronym> support)', 'w3-total-cache' ); ?></span>
154
  </li>
156
  <li>
157
  <?php _e( 'Hash function:', 'w3-total-cache' ); ?>
158
  <?php if ( function_exists( 'hash' ) ): ?>
159
+ <span style="background-color: #33cc33"><?php _e( 'Installed (hash)', 'w3-total-cache' ); ?></span>
160
  <?php elseif ( function_exists( 'mhash' ) ): ?>
161
+ <span style="background-color: #33cc33"><?php _e( 'Installed (mhash)', 'w3-total-cache' ); ?></span>
162
  <?php else: ?>
163
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
164
  <?php endif; ?>
165
  <span class="w3tc-self-test-hint"><?php _e( '(required for NetDNA / MaxCDN <acronym title="Content Delivery Network">CDN</acronym> purge support)', 'w3-total-cache' ); ?></span>
166
  </li>
168
  <li>
169
  <?php _e( 'Open basedir:', 'w3-total-cache' ); ?>
170
  <?php $open_basedir = ini_get( 'open_basedir' ); if ( $open_basedir ): ?>
171
+ <span style="background-color: #33cc33"><?php _e( 'On:', 'w3-total-cache' ); ?> <?php echo htmlspecialchars( $open_basedir ); ?></span>
172
  <?php else: ?>
173
+ <span style="background-color: #FFFF00"><?php _e( 'Off', 'w3-total-cache' ); ?></span>
174
  <?php endif; ?>
175
  </li>
176
 
177
  <li>
178
  <?php _e( 'zlib output compression:', 'w3-total-cache' ); ?>
179
  <?php if ( Util_Environment::to_boolean( ini_get( 'zlib.output_compression' ) ) ): ?>
180
+ <span style="background-color: #33cc33"><?php _e( 'On', 'w3-total-cache' ); ?></span>
181
  <?php else: ?>
182
+ <span style="background-color: #FFFF00"><?php _e( 'Off', 'w3-total-cache' ); ?></span>
183
  <?php endif; ?>
184
  </li>
185
 
186
  <li>
187
  <?php _e( 'set_time_limit:', 'w3-total-cache' ); ?>
188
  <?php if ( function_exists( 'set_time_limit' ) ): ?>
189
+ <span style="background-color: #33cc33"><?php _e( 'Available', 'w3-total-cache' ); ?></span>
190
  <?php else: ?>
191
+ <span style="background-color: #FFFF00"><?php _e( 'Not available', 'w3-total-cache' ); ?></span>
192
  <?php endif; ?>
193
  </li>
194
 
213
  <?php echo $module; ?>:
214
  <?php if ( $apache_modules ): ?>
215
  <?php if ( in_array( $module, $apache_modules ) ): ?>
216
+ <span style="background-color: #33cc33"><?php _e( 'Installed', 'w3-total-cache' ); ?></span>
217
  <?php else: ?>
218
+ <span style="background-color: #FFFF00"><?php _e( 'Not installed', 'w3-total-cache' ); ?></span>
219
  <?php endif; ?>
220
  <?php else: ?>
221
+ <span style="background-color: #FF0000"><?php _e( 'Not detected', 'w3-total-cache' ); ?></span>
222
  <?php endif; ?>
223
  <span class="w3tc-self-test-hint"><?php _e( '(required for disk enhanced Page Cache and Browser Cache)', 'w3-total-cache' ); ?></span>
224
  </li>
253
  <?php echo htmlspecialchars( $path ); ?>:
254
  <?php if ( file_exists( $path ) ): ?>
255
  <?php if ( Util_File::is_writable( $path ) ): ?>
256
+ <span style="background-color: #33cc33"><?php _e( 'OK', 'w3-total-cache' ); ?></span>
257
  <?php else: ?>
258
+ <span style="background-color: #FF0000"><?php _e( 'Not write-able', 'w3-total-cache' ); ?></span>
259
  <?php endif; ?>
260
  <?php else: ?>
261
  <?php if ( Util_File::is_writable_dir( dirname( $path ) ) ): ?>
262
+ <span style="background-color: #33cc33"><?php _e( 'Write-able', 'w3-total-cache' ); ?></span>
263
  <?php else: ?>
264
+ <span style="background-color: #FF0000"><?php _e( 'Not write-able', 'w3-total-cache' ); ?></span>
265
  <?php endif; ?>
266
  <?php endif; ?>
267
  </li>
270
  <li>
271
  <?php echo Util_Environment::normalize_path( WP_CONTENT_DIR ); ?>:
272
  <?php if ( Util_File::is_writable_dir( WP_CONTENT_DIR ) ): ?>
273
+ <span style="background-color: #33cc33"><?php _e( 'OK', 'w3-total-cache' ); ?></span>
274
  <?php else: ?>
275
+ <span style="background-color: #FF0000"><?php _e( 'Not write-able', 'w3-total-cache' ); ?></span>
276
  <?php endif; ?>
277
  </li>
278
 
280
  <?php $uploads_dir = @wp_upload_dir(); ?>
281
  <?php echo htmlspecialchars( $uploads_dir['path'] ); ?>:
282
  <?php if ( !empty( $uploads_dir['error'] ) ): ?>
283
+ <span style="background-color: #FF0000"><?php _e( 'Error:', 'w3-total-cache' ); ?> <?php echo htmlspecialchars( $uploads_dir['error'] ); ?></span>
284
  <?php elseif ( !Util_File::is_writable_dir( $uploads_dir['path'] ) ): ?>
285
+ <span style="background-color: #FF0000"><?php _e( 'Not write-able', 'w3-total-cache' ); ?></span>
286
  <?php else: ?>
287
+ <span style="background-color: #33cc33"><?php _e( 'OK', 'w3-total-cache' ); ?></span>
288
  <?php endif; ?>
289
  </li>
290
 
291
  <li>
292
  <?php _e( 'Fancy permalinks:', 'w3-total-cache' ); ?>
293
  <?php $permalink_structure = get_option( 'permalink_structure' ); if ( $permalink_structure ): ?>
294
+ <span style="background-color: #33cc33"><?php echo htmlspecialchars( $permalink_structure ); ?></span>
295
  <?php else: ?>
296
+ <span style="background-color: #FF0000"><?php _e( 'Disabled', 'w3-total-cache' ); ?></span>
297
  <?php endif; ?>
298
  </li>
299
 
300
  <li>
301
  <?php _e( 'WP_CACHE define:', 'w3-total-cache' ); ?>
302
+ <?php if ( defined( 'WP_CACHE' ) && WP_CACHE == 'true' ): ?>
303
+ <span style="background-color: #33cc33"><?php _e( 'Defined (true)', 'w3-total-cache' ); ?></span>
304
+ <?php elseif ( defined( 'WP_CACHE' ) && WP_CACHE == 'false' ): ?>
305
+ <span style="background-color: #FF0000"><?php _e( 'Defined (false)', 'w3-total-cache' ); ?></span>
306
  <?php else: ?>
307
+ <span style="background-color: #FF0000"><?php _e( 'Not defined', 'w3-total-cache' ); ?></span>
308
  <?php endif; ?>
309
  </li>
310
 
311
  <li>
312
  <?php _e( 'URL rewrite:', 'w3-total-cache' ); ?>
313
  <?php if ( Util_Rule::can_check_rules() ): ?>
314
+ <span style="background-color: #33cc33"><?php _e( 'Enabled', 'w3-total-cache' ); ?></span>
315
  <?php else: ?>
316
+ <span style="background-color: #FF0000"><?php _e( 'Disabled', 'w3-total-cache' ); ?></span>
317
  <?php endif; ?>
318
  </li>
319
 
320
  <li>
321
  <?php _e( 'Network mode:', 'w3-total-cache' ); ?>
322
  <?php if ( Util_Environment::is_wpmu() ): ?>
323
+ <span style="background-color: #33cc33"><?php _e( 'Yes', 'w3-total-cache' ); ?> (<?php echo Util_Environment::is_wpmu_subdomain() ? 'subdomain' : 'subdir'; ?>)</span>
324
  <?php else: ?>
325
+ <span style="background-color: #FF0000"><?php _e( 'No', 'w3-total-cache' ); ?></span>
326
  <?php endif; ?>
327
  </li>
328
  </ul>
inc/lightbox/support_us.php CHANGED
@@ -62,7 +62,11 @@ 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
  </label>
67
  </li>
68
  <li>
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>
inc/lightbox/upgrade.php CHANGED
@@ -18,14 +18,14 @@ if ( !defined( 'W3TC' ) )
18
  </div>
19
  <div class="w3tc_overlay_upgrade_description">
20
  <div class="w3tc_overlay_upgrade_content_l">
21
- <img src="<?php echo plugins_url( 'pub/img/overlay/w3-meteor.png', W3TC_FILE ) ?>"
22
  width="238" height="178" />
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) CDN'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>
18
  </div>
19
  <div class="w3tc_overlay_upgrade_description">
20
  <div class="w3tc_overlay_upgrade_content_l">
21
+ <img src="<?php echo plugins_url( 'pub/img/overlay/w3-meteor.png', W3TC_FILE ) ?>"
22
  width="238" height="178" />
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>
inc/options/about.php CHANGED
@@ -18,7 +18,7 @@ if ( !defined( 'W3TC' ) )
18
  <li><?php _e( 'Bandwidth savings via Minify and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression of <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym>, JavaScript and feeds', 'w3-total-cache' ); ?></li>
19
  <li><?php _e( 'Increased web server concurrency and increased scale (easily sustain high traffic spikes)', 'w3-total-cache' ); ?></li>
20
  <li><?php _e( 'Transparent content delivery network (<acronym title="Content Delivery Network">CDN</acronym>) integration with Media Library, theme files and WordPress core', 'w3-total-cache' ); ?></li>
21
- <li><?php _e( 'Caching of pages / posts in memory or on disk or on CDN (mirror only)', 'w3-total-cache' ); ?></li>
22
  <li><?php _e( 'Caching of (minified) <acronym title="Cascading Style Sheet">CSS</acronym> and JavaScript in memory, on disk or on <acronym title="Content Delivery Network">CDN</acronym>', 'w3-total-cache' ); ?></li>
23
  <li><?php _e( 'Caching of database objects in memory or on disk', 'w3-total-cache' ); ?></li>
24
  <li><?php _e( 'Caching of objects in memory or on disk', 'w3-total-cache' ); ?></li>
18
  <li><?php _e( 'Bandwidth savings via Minify and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression of <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym>, JavaScript and feeds', 'w3-total-cache' ); ?></li>
19
  <li><?php _e( 'Increased web server concurrency and increased scale (easily sustain high traffic spikes)', 'w3-total-cache' ); ?></li>
20
  <li><?php _e( 'Transparent content delivery network (<acronym title="Content Delivery Network">CDN</acronym>) integration with Media Library, theme files and WordPress core', 'w3-total-cache' ); ?></li>
21
+ <li><?php _e( 'Caching of pages / posts in memory or on disk or on <acronym title="Content Delivery Network">CDN</acronym> (mirror only)', 'w3-total-cache' ); ?></li>
22
  <li><?php _e( 'Caching of (minified) <acronym title="Cascading Style Sheet">CSS</acronym> and JavaScript in memory, on disk or on <acronym title="Content Delivery Network">CDN</acronym>', 'w3-total-cache' ); ?></li>
23
  <li><?php _e( 'Caching of database objects in memory or on disk', 'w3-total-cache' ); ?></li>
24
  <li><?php _e( 'Caching of objects in memory or on disk', 'w3-total-cache' ); ?></li>
inc/options/cdn.php CHANGED
@@ -156,10 +156,11 @@ if ( !$upload_blogfiles_enabled )
156
  <?php Util_Ui::button_config_save( 'cdn_general' ); ?>
157
  <?php Util_Ui::postbox_footer(); ?>
158
 
159
- <?php Util_Ui::postbox_header( __( 'Configuration', 'w3-total-cache' ), '', 'configuration' ); ?>
160
  <table class="form-table">
161
  <?php
162
  if ( $cdn_engine == 'google_drive' || $cdn_engine == 'highwinds' ||
 
163
  $cdn_engine == 'rackspace_cdn' || $cdn_engine == 'rscf' ) {
164
  do_action( 'w3tc_settings_cdn_boxarea_configuration' );
165
  } else if ( Cdn_Util::is_engine( $cdn_engine ) ) {
@@ -171,6 +172,8 @@ if ( $cdn_engine == 'google_drive' || $cdn_engine == 'highwinds' ||
171
  <?php Util_Ui::button_config_save( 'cdn_configuration' ); ?>
172
  <?php Util_Ui::postbox_footer(); ?>
173
 
 
 
174
  <?php Util_Ui::postbox_header( __( 'Advanced', 'w3-total-cache' ), '', 'advanced' ); ?>
175
  <table class="form-table">
176
  <tr>
@@ -179,6 +182,19 @@ if ( $cdn_engine == 'google_drive' || $cdn_engine == 'highwinds' ||
179
  <span class="description">When <acronym title="Secure Sockets Layer">SSL</acronym> pages are returned no <acronym title="Content Delivery Network">CDN</acronym> <acronym title="Uniform Resource Indicator">URL</acronym>s will appear in HTML pages.</span>
180
  </th>
181
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  <tr>
183
  <th colspan="2">
184
  <?php $this->checkbox( 'cdn.reject.logged_roles' ) ?> <?php Util_Ui::e_config_label( 'cdn.reject.logged_roles' ) ?></label><br />
156
  <?php Util_Ui::button_config_save( 'cdn_general' ); ?>
157
  <?php Util_Ui::postbox_footer(); ?>
158
 
159
+ <?php Util_Ui::postbox_header( __( 'Configuration: Objects', 'w3-total-cache' ), '', 'configuration' ); ?>
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 ) ) {
172
  <?php Util_Ui::button_config_save( 'cdn_configuration' ); ?>
173
  <?php Util_Ui::postbox_footer(); ?>
174
 
175
+ <?php do_action( 'w3tc_settings_box_cdnfsd' ); ?>
176
+
177
  <?php Util_Ui::postbox_header( __( 'Advanced', 'w3-total-cache' ), '', 'advanced' ); ?>
178
  <table class="form-table">
179
  <tr>
182
  <span class="description">When <acronym title="Secure Sockets Layer">SSL</acronym> pages are returned no <acronym title="Content Delivery Network">CDN</acronym> <acronym title="Uniform Resource Indicator">URL</acronym>s will appear in HTML pages.</span>
183
  </th>
184
  </tr>
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>
192
+ <th colspan="2">
193
+ <?php $this->checkbox( 'cdn.cors_header' ) ?> Add <acronym title="Access-Control-Allow-Origin">CORS</acronym> header</label><br />
194
+ <span class="description">Add <acronym title="Access-Control-Allow-Origin">CORS</acronym> headers to allow cross-domain assets usage.</span>
195
+ </th>
196
+ </tr>
197
+
198
  <tr>
199
  <th colspan="2">
200
  <?php $this->checkbox( 'cdn.reject.logged_roles' ) ?> <?php Util_Ui::e_config_label( 'cdn.reject.logged_roles' ) ?></label><br />
inc/options/cdn/akamai.php CHANGED
@@ -61,7 +61,7 @@ if ( !defined( 'W3TC' ) )
61
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
62
  <td>
63
  <?php $cnames = $this->_config->get_array( 'cdn.akamai.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
64
- <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
65
  </td>
66
  </tr>
67
  <tr>
61
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
62
  <td>
63
  <?php $cnames = $this->_config->get_array( 'cdn.akamai.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
64
+ <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>
65
  </td>
66
  </tr>
67
  <tr>
inc/options/cdn/att.php CHANGED
@@ -27,14 +27,14 @@ if ( !defined( 'W3TC' ) )
27
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.att.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
28
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.att.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
29
  </select>
30
- <br /><span class="description"><?php _e( 'Some <acronym>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>
31
  </td>
32
  </tr>
33
  <tr>
34
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
35
  <td>
36
  <?php $cnames = $this->_config->get_array( 'cdn.att.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
37
- <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
38
  </td>
39
  </tr>
40
  <tr>
27
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.att.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
28
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.att.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
29
  </select>
30
+ <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>
31
  </td>
32
  </tr>
33
  <tr>
34
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
35
  <td>
36
  <?php $cnames = $this->_config->get_array( 'cdn.att.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
37
+ <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>
38
  </td>
39
  </tr>
40
  <tr>
inc/options/cdn/azure.php CHANGED
@@ -36,7 +36,7 @@ if ( !defined( 'W3TC' ) )
36
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.azure.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
37
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.azure.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
38
  </select>
39
- <br /><span class="description"><?php _e( 'Some <acronym>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>
40
  </td>
41
  </tr>
42
  <tr>
36
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.azure.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
37
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.azure.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
38
  </select>
39
+ <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>
40
  </td>
41
  </tr>
42
  <tr>
inc/options/cdn/cf.php CHANGED
@@ -26,12 +26,29 @@ if ( !defined( 'W3TC' ) )
26
  </tr>
27
  <tr>
28
  <th><label for="cdn_cf_bucket"><?php _e( 'Bucket:', 'w3-total-cache' ); ?></label></th>
29
- <td>
30
- <input id="cdn_cf_bucket" type="text" name="cdn__cf__bucket"
31
- <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'cdn.cf.bucket' ) ); ?>" size="30" />
32
- <input class="button button-cdn-cf-bucket-location cdn_cf {nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"
33
- <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> type="button" value="<?php _e( 'Create bucket &amp; distribution', 'w3-total-cache' ); ?>" />
34
- </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  </tr>
36
  <tr>
37
  <th><label for="cdn_cf_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support:', 'w3-total-cache' ); ?></label></th>
@@ -41,7 +58,7 @@ if ( !defined( 'W3TC' ) )
41
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.cf.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
42
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.cf.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
43
  </select>
44
- <br /><span class="description"><?php _e( 'Some <acronym>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>
45
  </td>
46
  </tr>
47
  <tr>
26
  </tr>
27
  <tr>
28
  <th><label for="cdn_cf_bucket"><?php _e( 'Bucket:', 'w3-total-cache' ); ?></label></th>
29
+ <td>
30
+ <input id="cdn_cf_bucket" type="text" name="cdn__cf__bucket"
31
+ <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> value="<?php echo esc_attr( strtolower( $this->_config->get_string( 'cdn.cf.bucket' ) ) ); ?>" size="30" />
32
+ <select id="cdn_cf_bucket_location" name="cdn__cf__bucket__location" style="margin-top:-4px">
33
+ <option value="" style="display:none;">Select Bucket Location</option>
34
+ <option value="us-east-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'us-east-1' ); ?>>US East (N. Virginia)</option>
35
+ <option value="us-east-2"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'us-east-2' ); ?>>US East (Ohio)</option>
36
+ <option value="us-west-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'us-west-1' ); ?>>US-West (N. California)</option>
37
+ <option value="us-west-2"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'us-west-2' ); ?>>US-West (Oregon)</option>
38
+ <option value="ca-central-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'ca-central-1' ); ?>>Canada (Montreal)</option>
39
+ <option value="ap-south-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'ap-south-1' ); ?>>Asia Pacific (Mumbai)</option>
40
+ <option value="ap-northeast-2"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'ap-northeast-2' ); ?>>Asia Pacific (Seoul)</option>
41
+ <option value="ap-southeast-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'ap-southeast-1' ); ?>>Asia Pacific (Singapore)</option>
42
+ <option value="ap-southeast-2"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'ap-southeast-2' ); ?>>Asia Pacific (Sydney)</option>
43
+ <option value="ap-northeast-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'ap-northeast-1' ); ?>>Asia Pacific (Tokyo)</option>
44
+ <option value="eu-central-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'eu-central-1' ); ?>>EU (Frankfurt)</option>
45
+ <option value="eu-west-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'eu-west-1' ); ?>>EU (Ireland)</option>
46
+ <option value="eu-west-2"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'eu-west-2' ); ?>>EU (London)</option>
47
+ <option value="sa-east-1"<?php selected( $this->_config->get_string( 'cdn.cf.bucket.location' ), 'sa-east-1' ); ?>>South America (S&atilde;o Paulo)</option>
48
+ </select>
49
+ <b>or</b>
50
+ <input id="cdn_create_container" class="button {type: 'cf', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Create as new bucket with distribution', 'w3-total-cache' ); ?>" /> <span id="cdn_create_container_status" class="w3tc-status w3tc-process"></span>
51
+ </td>
52
  </tr>
53
  <tr>
54
  <th><label for="cdn_cf_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support:', 'w3-total-cache' ); ?></label></th>
58
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.cf.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
59
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.cf.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
60
  </select>
61
+ <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>
62
  </td>
63
  </tr>
64
  <tr>
inc/options/cdn/cf2.php CHANGED
@@ -41,7 +41,7 @@ if ( !defined( 'W3TC' ) )
41
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.cf2.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
42
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.cf2.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
43
  </select>
44
- <br /><span class="description"><?php _e( 'Some <acronym>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>
45
  </td>
46
  </tr>
47
  <tr>
41
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.cf2.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
42
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.cf2.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
43
  </select>
44
+ <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>
45
  </td>
46
  </tr>
47
  <tr>
inc/options/cdn/common/cnames.php CHANGED
@@ -11,13 +11,22 @@ if (! count($cnames)) {
11
  $cnames = array('');
12
  }
13
 
14
- $count = count($cnames);
 
 
 
 
 
 
 
 
 
 
15
 
16
- foreach ($cnames as $index => $cname):
17
  $label = '';
18
 
19
  if ($count > 1):
20
- switch ($index):
21
  case 0:
22
  $label = __('(reserved for CSS)', 'w3-total-cache');
23
  break;
@@ -47,7 +56,7 @@ foreach ($cnames as $index => $cname):
47
  <?php Util_Ui::sealing_disabled('cdn.') ?> value="<?php _e('Delete', 'w3-total-cache'); ?>"<?php if (!$index): ?> style="display: none;"<?php endif; ?> />
48
  <span><?php echo htmlspecialchars($label); ?></span>
49
  </li>
50
- <?php endforeach; ?>
51
  </ol>
52
  <input id="cdn_cname_add" class="button" type="button" value="<?php _e('Add CNAME', 'w3-total-cache'); ?>"
53
  <?php Util_Ui::sealing_disabled('cdn.') ?> />
11
  $cnames = array('');
12
  }
13
 
14
+ $count = count( $cnames );
15
+ if ( isset( $cnames['http_default'] ) )
16
+ $count--;
17
+ if ( isset( $cnames['https_default'] ) )
18
+ $count--;
19
+
20
+ $real_index = 0;
21
+ foreach ( $cnames as $index => $cname ):
22
+ if ( $index === 'http_default' || $index === 'https_default' ) {
23
+ continue;
24
+ }
25
 
 
26
  $label = '';
27
 
28
  if ($count > 1):
29
+ switch ($real_index):
30
  case 0:
31
  $label = __('(reserved for CSS)', 'w3-total-cache');
32
  break;
56
  <?php Util_Ui::sealing_disabled('cdn.') ?> value="<?php _e('Delete', 'w3-total-cache'); ?>"<?php if (!$index): ?> style="display: none;"<?php endif; ?> />
57
  <span><?php echo htmlspecialchars($label); ?></span>
58
  </li>
59
+ <?php $real_index++; endforeach; ?>
60
  </ol>
61
  <input id="cdn_cname_add" class="button" type="button" value="<?php _e('Add CNAME', 'w3-total-cache'); ?>"
62
  <?php Util_Ui::sealing_disabled('cdn.') ?> />
inc/options/cdn/cotendo.php CHANGED
@@ -34,14 +34,14 @@ if ( !defined( 'W3TC' ) )
34
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.cotendo.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
35
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.cotendo.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
36
  </select>
37
- <br /><span class="description"><?php _e( 'Some <acronym>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>
38
  </td>
39
  </tr>
40
  <tr>
41
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
42
  <td>
43
  <?php $cnames = $this->_config->get_array( 'cdn.cotendo.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
44
- <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
45
  </td>
46
  </tr>
47
  <tr>
34
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.cotendo.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
35
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.cotendo.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
36
  </select>
37
+ <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>
38
  </td>
39
  </tr>
40
  <tr>
41
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
42
  <td>
43
  <?php $cnames = $this->_config->get_array( 'cdn.cotendo.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
44
+ <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>
45
  </td>
46
  </tr>
47
  <tr>
inc/options/cdn/edgecast.php CHANGED
@@ -27,14 +27,14 @@ if ( !defined( 'W3TC' ) )
27
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.edgecast.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
28
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.edgecast.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
29
  </select>
30
- <br /><span class="description"><?php _e( 'Some <acronym>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>
31
  </td>
32
  </tr>
33
  <tr>
34
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
35
  <td>
36
  <?php $cnames = $this->_config->get_array( 'cdn.edgecast.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
37
- <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
38
  </td>
39
  </tr>
40
  <tr>
27
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.edgecast.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
28
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.edgecast.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
29
  </select>
30
+ <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>
31
  </td>
32
  </tr>
33
  <tr>
34
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
35
  <td>
36
  <?php $cnames = $this->_config->get_array( 'cdn.edgecast.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
37
+ <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>
38
  </td>
39
  </tr>
40
  <tr>
inc/options/cdn/ftp.php CHANGED
@@ -58,7 +58,7 @@ if ( !defined( 'W3TC' ) )
58
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.ftp.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
59
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.ftp.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
60
  </select>
61
- <br /><span class="description"><?php _e( 'Some <acronym>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>
62
  </td>
63
  </tr>
64
  <tr>
58
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.ftp.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
59
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.ftp.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
60
  </select>
61
+ <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>
62
  </td>
63
  </tr>
64
  <tr>
inc/options/cdn/maxcdn.php DELETED
@@ -1,89 +0,0 @@
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( wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_maxcdn_signup' ), 'w3tc' ) )?>" target="_blank" id="netdna-maxcdn-create-account" class="button-primary"><?php _e( 'Sign Up Now and Save 25%', 'w3-total-cache' ) ?></a>
13
- <br />
14
- <span class="description"><?php _e( 'MaxCDN 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
- <?php if ( $authorized ): ?>
20
- <tr>
21
- <th style="width: 300px;"><label><?php !$pull_zones ? _e( 'Create pull zone:', 'w3-total-cache' ) : _e( 'Create new pull zone:', 'w3-total-cache' )?></label></th>
22
- <td>
23
- <button id="netdna-maxcdn-create-pull-zone" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> class="button-primary {type: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"><?php !$pull_zones ? _e( 'Create pull zone', 'w3-total-cache' ) : _e( 'Create new pull zone', 'w3-total-cache' )?></button>
24
- <br />
25
- <span class="description"><?php _e( 'Click the Create Pull Zone button above and create a pull zone manually for this site.', 'w3-total-cache' )?></span>
26
- </td>
27
- </tr>
28
- <?php elseif ( !$authorized ): ?>
29
- <tr>
30
- <th style="width: 300px;"><label><?php _e( 'Specify account credentials:', 'w3-total-cache' )?></label></th>
31
- <td>
32
- <a id="cdn_maxcdn_oauth" class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_maxcdn_authorize' ), 'w3tc' )?>" target="_blank"><?php _e( 'Authorize', 'w3-total-cache' )?></a>
33
- <br />
34
- <span class="description"><?php _e( 'Click the Authorize button above, log in, paste the key below and save settings.', 'w3-total-cache' )?></span>
35
- </td>
36
- </tr>
37
- <?php endif ?>
38
- <tr>
39
- <th style="width: 300px;"><label for="cdn_maxcdn_authorization_key"><?php _e( 'Authorization key', 'w3-total-cache' )?>:</label></th>
40
- <td id="authorization_area">
41
- <input id="cdn_maxcdn_authorization_key" class="w3tc-ignore-change" type="text"
42
- <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> name="cdn__maxcdn__authorization_key" value="<?php echo esc_attr( $this->_config->get_string( 'cdn.maxcdn.authorization_key' ) ); ?>" size="60" onblur="w3tc_validate_cdn_key_result('maxcdn','<?php echo wp_create_nonce( 'w3tc' ); ?>')" />
43
- <input id="validate_cdn_key" type="button" class="button {type: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Validate', 'w3-total-cache' ) ?>" /><span id="validate_cdn_key_result" style="margin-left:5px;padding:3px 8px 3px 20px;"></span>
44
- <br /><span class="description"><?php _e( 'Consists of alias+key+secret . Example: bluewidgets+asd897asd98a7sd+798a7sd9 . If you use "Authorize" its already formatted correctly.', 'w3-total-cache' )?></span>
45
- </td>
46
- </tr>
47
- <tr id="create_zone_area" style="<?php echo $authorized && ( !$have_zone || is_null( $zone_info ) ) ? '' : 'display: none' ?>">
48
- <th><?php _e( 'Create zone:', 'w3-total-cache' ) ?></th>
49
- <td><input type="button" class="button" onclick="w3tc_create_zone('maxcdn','<?php echo wp_create_nonce( 'w3tc' ); ?>')" value="<?php _e( 'Create Default Zone', 'w3-total-cache' ) ?>" id="create_default_zone" />
50
- <span id="create_pull_zone_result" style="padding:3px 0 3px 20px;"></span>
51
- <br /><span class="description"><?php _e( 'You have no zone connected with this site. Click button to create a default zone automatically.', 'w3-total-cache' ) ?></span>
52
- </td>
53
- </tr>
54
- <tr id="select_pull_zone" style="<?php echo !( $authorized && $pull_zones ) ? 'display:none' : '' ?>">
55
- <th><label for="cdn_maxcdn_zone_id"><?php _e( 'Select pull zone:', 'w3-total-cache' )?></label></th>
56
- <td>
57
- <select id="cdn_maxcdn_zone_id" name="cdn__maxcdn__zone_id" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?>>
58
- <?php foreach ( $pull_zones as $zone ):?>
59
- <option value="<?php echo $zone['id'] ?>" <?php selected( $zone['id'], $this->_config->get_integer( 'cdn.maxcdn.zone_id' ) )?>><?php echo $zone['name']?></option>
60
- <?php endforeach; ?>
61
- </select> <input id="use_poll_zone" type="button" class="button {type: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Use Zone', 'w3-total-cache' ) ?>" /><span id="use_pull_zone_result" style="margin-left:15px;padding:3px 8px 3px 8px;"></span>
62
- <br />
63
- <span class="description"><?php _e( 'Select the pull zone to use with this site.', 'w3-total-cache' )?></span>
64
- </td>
65
- </tr>
66
-
67
- <tr>
68
- <th><label for="cdn_maxcdn_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support', 'w3-total-cache' )?>:</label></th>
69
- <td>
70
- <select id="cdn_maxcdn_ssl" name="cdn__maxcdn__ssl" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?>>
71
- <option value="auto"<?php selected( $this->_config->get_string( 'cdn.maxcdn.ssl' ), 'auto' ); ?>><?php _e( 'Auto (determine connection type automatically)', 'w3-total-cache' )?></option>
72
- <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.maxcdn.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' )?></option>
73
- <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.maxcdn.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' )?></option>
74
- </select>
75
- <br /><span class="description"><?php _e( 'Some <acronym>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>
76
- </td>
77
- </tr>
78
- <tr>
79
- <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' )?></th>
80
- <td>
81
- <?php $cnames = $this->_config->get_array( 'cdn.maxcdn.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
82
- <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' )?></span>
83
- </td>
84
- </tr>
85
- <tr>
86
- <th colspan="2">
87
- <input id="cdn_test" class="button {type: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Test MaxCDN', 'w3-total-cache' )?>" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
88
- </th>
89
- </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/cdn/mirror.php CHANGED
@@ -13,14 +13,14 @@ if ( !defined( 'W3TC' ) )
13
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.mirror.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
14
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.mirror.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
15
  </select>
16
- <br /><span class="description"><?php _e( 'Some <acronym>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>
17
  </td>
18
  </tr>
19
  <tr>
20
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
21
  <td>
22
  <?php $cnames = $this->_config->get_array( 'cdn.mirror.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
23
- <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' ); ?></span>
24
  </td>
25
  </tr>
26
  <tr>
13
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.mirror.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
14
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.mirror.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
15
  </select>
16
+ <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>
17
  </td>
18
  </tr>
19
  <tr>
20
  <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' ); ?></th>
21
  <td>
22
  <?php $cnames = $this->_config->get_array( 'cdn.mirror.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
23
+ <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>
24
  </td>
25
  </tr>
26
  <tr>
inc/options/cdn/netdna.php DELETED
@@ -1,89 +0,0 @@
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( wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_maxcdn_signup' ), 'w3tc' ) )?>" target="_blank" id="netdna-maxcdn-create-account" class="button-primary"><?php _e( 'Create Account', 'w3-total-cache' ) ?></a>
13
- <br />
14
- <span class="description"><?php _e( 'Are you a new customer? Click the Create Account button to receive a discount on a new MaxCDN account.', 'w3-total-cache' )?></span>
15
- </td>
16
- </tr>
17
- <?php endif ?>
18
-
19
- <?php if ( $authorized ): ?>
20
- <tr>
21
- <th style="width: 300px;"><label><?php !$pull_zones ? _e( 'Create pull zone:', 'w3-total-cache' ) : _e( 'Create new pull zone:', 'w3-total-cache' )?></label></th>
22
- <td>
23
- <button id="netdna-maxcdn-create-pull-zone" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> class="button-primary {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"><?php !$pull_zones ? _e( 'Create pull zone', 'w3-total-cache' ) : _e( 'Create new pull zone', 'w3-total-cache' )?></button>
24
- <br />
25
- <span class="description"><?php _e( 'Click the Create Pull Zone button above and create a pull zone manually for this site.', 'w3-total-cache' )?></span>
26
- </td>
27
- </tr>
28
- <?php elseif ( !$authorized ): ?>
29
- <tr>
30
- <th style="width: 300px;"><label><?php _e( 'Specify account credentials:', 'w3-total-cache' )?></label></th>
31
- <td>
32
- <a id="cdn_netdna_oauth" class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_netdna_authorize' ), 'w3tc' )?>" target="_blank"><?php _e( 'Authorize', 'w3-total-cache' )?></a>
33
- <br />
34
- <span class="description"><?php _e( 'Click the Authorize button above, log in, paste the key below and save settings.', 'w3-total-cache' )?></span>
35
- </td>
36
- </tr>
37
- <?php endif ?>
38
- <tr>
39
- <th style="width: 300px;"><label for="cdn_netdna_authorization_key"><?php _e( 'Authorization key', 'w3-total-cache' )?>:</label></th>
40
- <td id="authorization_area">
41
- <input id="cdn_netdna_authorization_key" class="w3tc-ignore-change" type="text"
42
- <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> name="cdn__netdna__authorization_key" value="<?php echo esc_attr( $this->_config->get_string( 'cdn.netdna.authorization_key' ) ); ?>" size="60" onblur="w3tc_validate_cdn_key_result('netdna','<?php echo wp_create_nonce( 'w3tc' ); ?>')" />
43
- <input id="validate_cdn_key" type="button" class="button {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Validate', 'w3-total-cache' ) ?>" /><span id="validate_cdn_key_result" style="margin-left:15px;padding:3px 8px 3px 8px;"></span>
44
- <br /><span class="description"><?php _e( 'Consists of alias+key+secret . Example: bluewidgets+asd897asd98a7sd+798a7sd9 . If you use "Authorize" its already formatted correctly.', 'w3-total-cache' )?></span>
45
- </td>
46
- </tr>
47
- <tr id="create_zone_area" style="<?php echo $authorized && ( !$have_zone || is_null( $zone_info ) ) ? '' : 'display: none' ?>">
48
- <th><?php _e( 'Create zone:', 'w3-total-cache' ) ?></th>
49
- <td><input type="button" class="button" onclick="w3tc_create_zone('netdna','<?php echo wp_create_nonce( 'w3tc' ); ?>')" value="<?php _e( 'Create Default Zone', 'w3-total-cache' ) ?>" id="create_default_zone" />
50
- <span id="create_pull_zone_result" style="padding:3px 0 3px 20px;"></span>
51
- <br /><span class="description"><?php _e( 'You have no zone connected with this site. Click button to create a default zone automatically.', 'w3-total-cache' ) ?></span>
52
- </td>
53
- </tr>
54
- <tr id="select_pull_zone" style="<?php echo !( $authorized && $pull_zones ) ? 'display:none' : '' ?>">
55
- <th><label for="cdn_netdna_zone_id"><?php _e( 'Select pull zone:', 'w3-total-cache' )?></label></th>
56
- <td>
57
- <select id="cdn_netdna_zone_id" name="cdn__netdna__zone_id" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?>>
58
- <?php foreach ( $pull_zones as $zone ):?>
59
- <option value="<?php echo $zone['id'] ?>" <?php selected( $zone['id'], $this->_config->get_integer( 'cdn.netdna.zone_id' ) )?>><?php echo $zone['name']?></option>
60
- <?php endforeach; ?>
61
- </select> <input id="use_poll_zone" type="button" class="button {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Use Zone', 'w3-total-cache' ) ?>" /><span id="use_pull_zone_result" style="margin-left:15px;padding:3px 8px 3px 8px;"></span>
62
- <br />
63
- <span class="description"><?php _e( 'Select the pull zone to use with this site.', 'w3-total-cache' )?></span>
64
- </td>
65
- </tr>
66
-
67
- <tr>
68
- <th><label for="cdn_netdna_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support', 'w3-total-cache' )?>:</label></th>
69
- <td>
70
- <select id="cdn_netdna_ssl" name="cdn__netdna__ssl" <?php Util_Ui::sealing_disabled( 'cdn.' ) ?>>
71
- <option value="auto"<?php selected( $this->_config->get_string( 'cdn.netdna.ssl' ), 'auto' ); ?>><?php _e( 'Auto (determine connection type automatically)', 'w3-total-cache' )?></option>
72
- <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.netdna.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' )?></option>
73
- <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.netdna.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' )?></option>
74
- </select>
75
- <br /><span class="description"><?php _e( 'Some <acronym>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>
76
- </td>
77
- </tr>
78
- <tr>
79
- <th><?php _e( 'Replace site\'s hostname with:', 'w3-total-cache' )?></th>
80
- <td>
81
- <?php $cnames = $this->_config->get_array( 'cdn.netdna.domain' ); include W3TC_INC_DIR . '/options/cdn/common/cnames.php'; ?>
82
- <br /><span class="description"><?php _e( 'Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site\'s hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.', 'w3-total-cache' )?></span>
83
- </td>
84
- </tr>
85
- <tr>
86
- <th colspan="2">
87
- <input id="cdn_test" class="button {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Test NetDNA', 'w3-total-cache' )?>" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
88
- </th>
89
- </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/cdn/rscf.php CHANGED
@@ -47,7 +47,7 @@ Util_Ui::config_item( array(
47
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.rscf.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
48
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.rscf.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
49
  </select>
50
- <br /><span class="description"><?php _e( 'Some <acronym>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>
51
  </td>
52
  </tr>
53
  <tr>
47
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.rscf.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
48
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.rscf.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
49
  </select>
50
+ <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>
51
  </td>
52
  </tr>
53
  <tr>
inc/options/cdn/s3.php CHANGED
@@ -26,11 +26,29 @@ if ( !defined( 'W3TC' ) )
26
  </tr>
27
  <tr>
28
  <th><label for="cdn_s3_bucket"><?php _e( 'Bucket:', 'w3-total-cache' ); ?></label></th>
29
- <td>
30
- <input id="cdn_s3_bucket" type="text" name="cdn__s3__bucket"
31
- <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> value="<?php echo esc_attr( $this->_config->get_string( 'cdn.s3.bucket' ) ); ?>" size="30" />
32
- <input class="button button-cdn-s3-bucket-location cdn_s3 {nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Create bucket', 'w3-total-cache' ); ?>" />
33
- </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  </tr>
35
  <tr>
36
  <th><label for="cdn_s3_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support:', 'w3-total-cache' ); ?></label></th>
@@ -40,7 +58,7 @@ if ( !defined( 'W3TC' ) )
40
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
41
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
42
  </select>
43
- <br /><span class="description"><?php _e( 'Some <acronym>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>
44
  </td>
45
  </tr>
46
  <tr>
26
  </tr>
27
  <tr>
28
  <th><label for="cdn_s3_bucket"><?php _e( 'Bucket:', 'w3-total-cache' ); ?></label></th>
29
+ <td>
30
+ <input id="cdn_s3_bucket" type="text" name="cdn__s3__bucket"
31
+ <?php Util_Ui::sealing_disabled( 'cdn.' ) ?> value="<?php echo esc_attr( strtolower( $this->_config->get_string( 'cdn.s3.bucket' ) ) ); ?>" size="30" />
32
+ <select id="cdn_s3_bucket_location" name="cdn__s3__bucket__location" style="margin-top:-4px">
33
+ <option value="" style="display:none;">Select Bucket Location</option>
34
+ <option value="us-east-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'us-east-1' ); ?>>US East (N. Virginia)</option>
35
+ <option value="us-east-2"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'us-east-2' ); ?>>US East (Ohio)</option>
36
+ <option value="us-west-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'us-west-1' ); ?>>US-West (N. California)</option>
37
+ <option value="us-west-2"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'us-west-2' ); ?>>US-West (Oregon)</option>
38
+ <option value="ca-central-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'ca-central-1' ); ?>>Canada (Montreal)</option>
39
+ <option value="ap-south-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'ap-south-1' ); ?>>Asia Pacific (Mumbai)</option>
40
+ <option value="ap-northeast-2"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'ap-northeast-2' ); ?>>Asia Pacific (Seoul)</option>
41
+ <option value="ap-southeast-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'ap-southeast-1' ); ?>>Asia Pacific (Singapore)</option>
42
+ <option value="ap-southeast-2"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'ap-southeast-2' ); ?>>Asia Pacific (Sydney)</option>
43
+ <option value="ap-northeast-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'ap-northeast-1' ); ?>>Asia Pacific (Tokyo)</option>
44
+ <option value="eu-central-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'eu-central-1' ); ?>>EU (Frankfurt)</option>
45
+ <option value="eu-west-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'eu-west-1' ); ?>>EU (Ireland)</option>
46
+ <option value="eu-west-2"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'eu-west-2' ); ?>>EU (London)</option>
47
+ <option value="sa-east-1"<?php selected( $this->_config->get_string( 'cdn.s3.bucket.location' ), 'sa-east-1' ); ?>>South America (S&atilde;o Paulo)</option>
48
+ </select>
49
+ <b>or</b>
50
+ <input id="cdn_create_container" class="button {type: 's3', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" type="button" value="<?php _e( 'Create as new bucket', 'w3-total-cache' ); ?>" /> <span id="cdn_create_container_status" class="w3tc-status w3tc-process"></span>
51
+ </td>
52
  </tr>
53
  <tr>
54
  <th><label for="cdn_s3_ssl"><?php _e( '<acronym title="Secure Sockets Layer">SSL</acronym> support:', 'w3-total-cache' ); ?></label></th>
58
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
59
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
60
  </select>
61
+ <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>
62
  </td>
63
  </tr>
64
  <tr>
inc/options/cdn/s3_compatible.php CHANGED
@@ -42,7 +42,7 @@ Util_Ui::config_item( array(
42
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
43
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
44
  </select>
45
- <br /><span class="description"><?php _e( 'Some <acronym>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>
46
  </td>
47
  </tr>
48
  <tr>
42
  <option value="enabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'enabled' ); ?>><?php _e( 'Enabled (always use SSL)', 'w3-total-cache' ); ?></option>
43
  <option value="disabled"<?php selected( $this->_config->get_string( 'cdn.s3.ssl' ), 'disabled' ); ?>><?php _e( 'Disabled (always use HTTP)', 'w3-total-cache' ); ?></option>
44
  </select>
45
+ <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>
46
  </td>
47
  </tr>
48
  <tr>
inc/options/common/header.php CHANGED
@@ -34,7 +34,7 @@ $licensing_visible = ( ( !Util_Environment::is_wpmu() || is_network_admin() ) &&
34
  array( 'id' => 'browser_cache', 'text' => __( 'Browser Cache', 'w3-total-cache' ) ),
35
  array( 'id' => 'cdn', 'text' => __( '<abbr title="Content Delivery Network">CDN</abbr>', 'w3-total-cache' ) ),
36
  array( 'id' => 'reverse_proxy', 'text' => __( 'Reverse Proxy', 'w3-total-cache' ) ) ) );
37
- if ( Util_Environment::is_w3tc_enterprise() )
38
  $anchors[] = array( 'id' => 'amazon_sns', 'text' => __( 'Amazon <abbr title="Simple Notification Service">SNS</abbr>', 'w3-total-cache' ) );
39
  $anchors[] = array( 'id' => 'monitoring', 'text' => __( 'Monitoring', 'w3-total-cache' ) );
40
  if ( $licensing_visible )
34
  array( 'id' => 'browser_cache', 'text' => __( 'Browser Cache', 'w3-total-cache' ) ),
35
  array( 'id' => 'cdn', 'text' => __( '<abbr title="Content Delivery Network">CDN</abbr>', 'w3-total-cache' ) ),
36
  array( 'id' => 'reverse_proxy', 'text' => __( 'Reverse Proxy', 'w3-total-cache' ) ) ) );
37
+ if ( Util_Environment::is_w3tc_pro() )
38
  $anchors[] = array( 'id' => 'amazon_sns', 'text' => __( 'Amazon <abbr title="Simple Notification Service">SNS</abbr>', 'w3-total-cache' ) );
39
  $anchors[] = array( 'id' => 'monitoring', 'text' => __( 'Monitoring', 'w3-total-cache' ) );
40
  if ( $licensing_visible )
inc/options/dashboard.php CHANGED
@@ -8,10 +8,10 @@ if ( !defined( 'W3TC' ) )
8
  <?php include W3TC_INC_DIR . '/options/common/header.php'; ?>
9
 
10
  <p>
11
- <?php echo sprintf( __( 'The plugin is currently <span class="w3tc-%s">%s</span> in <strong>%s%s</strong> mode.', 'w3-total-cache' )
12
  , $enabled ? "enabled" : "disabled"
13
  , $enabled ? __( 'enabled', 'w3-total-cache' ) : __( 'disabled', 'w3-total-cache' )
14
- , Util_Environment::w3tc_edition( $this->_config ), ( Util_Environment::is_w3tc_edge( $this->_config ) ? __( ' edge', 'w3-total-cache' ) : '' ) );
15
  ?>
16
  </p>
17
  <form id="w3tc_dashboard" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
8
  <?php include W3TC_INC_DIR . '/options/common/header.php'; ?>
9
 
10
  <p>
11
+ <?php echo sprintf( __( 'The plugin is currently <span class="w3tc-%s">%s</span> in <strong>%s</strong> mode.', 'w3-total-cache' )
12
  , $enabled ? "enabled" : "disabled"
13
  , $enabled ? __( 'enabled', 'w3-total-cache' ) : __( 'disabled', 'w3-total-cache' )
14
+ , Util_Environment::w3tc_edition( $this->_config ) );
15
  ?>
16
  </p>
17
  <form id="w3tc_dashboard" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
inc/options/general.php CHANGED
@@ -16,14 +16,6 @@ echo sprintf( 'The plugin is currently %1$s If an option is disabled it means th
16
  <div class="metabox-holder">
17
  <?php Util_Ui::postbox_header( __( 'General', 'w3-total-cache' ), '' ); ?>
18
  <table class="form-table">
19
- <tr>
20
- <th colspan="2">
21
- <label>
22
- <input id="enabled" type="checkbox" name="enabled" value="1"<?php checked( $enabled_checkbox, true ); ?> />
23
- <?php _e( 'Toggle all caching types on or off (at once)', 'w3-total-cache' ); ?>
24
- </label>
25
- </th>
26
- </tr>
27
  <tr>
28
  <th>Preview mode:</th>
29
  <td>
@@ -220,7 +212,7 @@ Util_Ui::config_item_engine( array(
220
  ) );
221
  ?>
222
 
223
- <?php if ( Util_Environment::is_w3tc_enterprise() && is_network_admin() ): ?>
224
  <?php include W3TC_INC_OPTIONS_DIR . '/enterprise/dbcluster_general_section.php' ?>
225
  <?php endif; ?>
226
  </table>
@@ -329,7 +321,7 @@ Util_Ui::button_config_save( 'general_varnish',
329
  ?>
330
  <?php Util_Ui::postbox_footer(); ?>
331
 
332
- <?php if ( Util_Environment::is_w3tc_enterprise() ): ?>
333
  <?php Util_Ui::postbox_header( 'Message Bus', '', 'amazon_sns' ); ?>
334
  <p>
335
  Allows policy management to be shared between a dynamic pool of servers. For example, each server in a pool to use opcode caching (which is not a shared resource) and purging is then syncronized between any number of servers in real-time; each server therefore behaves identically even though resources are not shared.
@@ -430,6 +422,13 @@ Util_Ui::config_item( array(
430
  <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.
431
  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>
432
  </td>
 
 
 
 
 
 
 
433
  </tr>
434
  <?php
435
  Util_Ui::config_item( array(
@@ -488,27 +487,6 @@ Util_Ui::config_item( array(
488
  ?>
489
 
490
  <?php do_action( 'w3tc_settings_general_boxarea_miscellaneous_content' ); ?>
491
- <?php if ( is_network_admin() || !Util_Environment::is_wpmu() ): ?>
492
- <tr id="edge_mode">
493
- <th colspan="2">
494
- <?php
495
- if ( !Util_Environment::is_w3tc_edge( $this->_config ) )
496
- echo '<a href="' .
497
- Util_Ui::url( array( 'w3tc_edge_mode_enable' => 'y' ) ) .
498
- '"><strong>' .
499
- __( 'Enable Edge mode', 'w3-total-cache' ) .
500
- '</strong></a>';
501
- else
502
- echo '<a href="' .
503
- Util_Ui::url( array( 'w3tc_edge_mode_disable' => 'y' ) ) .
504
- '"><strong>' .
505
- __( 'Disable Edge mode', 'w3-total-cache' ) .
506
- '</strong></a>';
507
- ?>
508
- <br /><span class="description"><?php _e( 'Enable this to try out new functionality under development. Might cause issues on some sites.', 'w3-total-cache' ); ?></span>
509
- </th>
510
- </tr>
511
- <?php endif; ?>
512
  </table>
513
 
514
  <?php Util_Ui::button_config_save( 'general_misc' ); ?>
@@ -529,8 +507,9 @@ Util_Ui::config_item( array(
529
  <?php $this->checkbox_debug( array( 'fragmentcache', 'debug' ) ) ?> <?php _e( 'Fragment Cache', 'w3-total-cache' ) ?></label><br />
530
  <?php endif; ?>
531
  <?php $this->checkbox_debug( 'cdn.debug' ) ?> <?php Util_Ui::e_config_label( 'cdn.debug' ) ?></label><br />
 
532
  <?php $this->checkbox_debug( 'varnish.debug' ) ?> <?php Util_Ui::e_config_label( 'varnish.debug' ) ?></label><br />
533
- <?php if ( Util_Environment::is_w3tc_enterprise() ): ?>
534
  <?php $this->checkbox_debug( 'cluster.messagebus.debug' ) ?> <?php Util_Ui::e_config_label( 'cluster.messagebus.debug' ) ?></label><br />
535
  <?php endif; ?>
536
  <span class="description"><?php _e( 'If selected, detailed caching information will be appear at the end of each page in a <acronym title="Hypertext Markup Language">HTML</acronym> comment. View a page\'s source code to review.', 'w3-total-cache' ); ?></span>
16
  <div class="metabox-holder">
17
  <?php Util_Ui::postbox_header( __( 'General', 'w3-total-cache' ), '' ); ?>
18
  <table class="form-table">
 
 
 
 
 
 
 
 
19
  <tr>
20
  <th>Preview mode:</th>
21
  <td>
212
  ) );
213
  ?>
214
 
215
+ <?php if ( Util_Environment::is_w3tc_pro() && is_network_admin() ): ?>
216
  <?php include W3TC_INC_OPTIONS_DIR . '/enterprise/dbcluster_general_section.php' ?>
217
  <?php endif; ?>
218
  </table>
321
  ?>
322
  <?php Util_Ui::postbox_footer(); ?>
323
 
324
+ <?php if ( Util_Environment::is_w3tc_pro() ): ?>
325
  <?php Util_Ui::postbox_header( 'Message Bus', '', 'amazon_sns' ); ?>
326
  <p>
327
  Allows policy management to be shared between a dynamic pool of servers. For example, each server in a pool to use opcode caching (which is not a shared resource) and purging is then syncronized between any number of servers in real-time; each server therefore behaves identically even though resources are not shared.
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>
427
+ <th><label for="widget_pagespeed_key"><?php Util_Ui::e_config_label( 'widget.pagespeed.key.restrict.referrer', 'general' ) ?></label></th>
428
+ <td>
429
+ <input id="widget_pagespeed_key_restrict_referrer" type="text" name="widget__pagespeed__key__restrict__referrer" value="<?php echo esc_attr( $this->_config->get_string( 'widget.pagespeed.key.restrict.referrer' ) ); ?>" size="60" /><br>
430
+ <span class="description">Although not required, to prevent unauthorized use and quota theft, you have the option to restrict your key using a designated HTTP referrer. If you decide to use it, you will need to set this referrer within the API Console's "Http Referrers (web sites)" key restriction area (under Credentials).</span>
431
+ </td>
432
  </tr>
433
  <?php
434
  Util_Ui::config_item( array(
487
  ?>
488
 
489
  <?php do_action( 'w3tc_settings_general_boxarea_miscellaneous_content' ); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  </table>
491
 
492
  <?php Util_Ui::button_config_save( 'general_misc' ); ?>
507
  <?php $this->checkbox_debug( array( 'fragmentcache', 'debug' ) ) ?> <?php _e( 'Fragment Cache', 'w3-total-cache' ) ?></label><br />
508
  <?php endif; ?>
509
  <?php $this->checkbox_debug( 'cdn.debug' ) ?> <?php Util_Ui::e_config_label( 'cdn.debug' ) ?></label><br />
510
+ <?php $this->checkbox_debug( 'cdnfsd.debug' ) ?> <?php Util_Ui::e_config_label( 'cdnfsd.debug' ) ?></label><br />
511
  <?php $this->checkbox_debug( 'varnish.debug' ) ?> <?php Util_Ui::e_config_label( 'varnish.debug' ) ?></label><br />
512
+ <?php if ( Util_Environment::is_w3tc_pro() ): ?>
513
  <?php $this->checkbox_debug( 'cluster.messagebus.debug' ) ?> <?php Util_Ui::e_config_label( 'cluster.messagebus.debug' ) ?></label><br />
514
  <?php endif; ?>
515
  <span class="description"><?php _e( 'If selected, detailed caching information will be appear at the end of each page in a <acronym title="Hypertext Markup Language">HTML</acronym> comment. View a page\'s source code to review.', 'w3-total-cache' ); ?></span>
inc/options/minify.php CHANGED
@@ -320,7 +320,7 @@ Util_Ui::config_item( array(
320
  'description' => __( 'For better performance, send files to browser before they are requested when using the <acronym title="Hypertext Markup Language">HTTP</acronym>/2 protocol.',
321
  'w3-total-cache' ) .
322
  ( $this->_config->get_string( 'pgcache.engine' ) != 'file_generic' ? '' :
323
- __( ' <br /><b>Not supported by "Disk: Enhanced" page cache engine</b>', 'w3-total-cache' ) )
324
  ) ); ?>
325
  </table>
326
 
@@ -445,7 +445,7 @@ Util_Ui::config_item( array(
445
  'description' => __( 'For better performance, send files to browser before they are requested when using the <acronym title="Hypertext Markup Language">HTTP</acronym>/2 protocol.',
446
  'w3-total-cache' ) .
447
  ( $this->_config->get_string( 'pgcache.engine' ) != 'file_generic' ? '' :
448
- __( ' <br /><b>Not supported by "Disk: Enhanced" page cache engine</b>', 'w3-total-cache' ) )
449
  ) ); ?>
450
  </table>
451
 
320
  'description' => __( 'For better performance, send files to browser before they are requested when using the <acronym title="Hypertext Markup Language">HTTP</acronym>/2 protocol.',
321
  'w3-total-cache' ) .
322
  ( $this->_config->get_string( 'pgcache.engine' ) != 'file_generic' ? '' :
323
+ __( ' <br /><b>Not supported by "Disk: Enhanced" page cache engine for Nginx</b>', 'w3-total-cache' ) )
324
  ) ); ?>
325
  </table>
326
 
445
  'description' => __( 'For better performance, send files to browser before they are requested when using the <acronym title="Hypertext Markup Language">HTTP</acronym>/2 protocol.',
446
  'w3-total-cache' ) .
447
  ( $this->_config->get_string( 'pgcache.engine' ) != 'file_generic' ? '' :
448
+ __( ' <br /><b>Not supported by "Disk: Enhanced" page cache engine for Nginx</b>', 'w3-total-cache' ) )
449
  ) ); ?>
450
  </table>
451
 
inc/options/minify/yuijs2.php CHANGED
@@ -6,16 +6,16 @@ if ( !defined( 'W3TC' ) )
6
 
7
  ?>
8
  <tr>
9
- <th><label for="minify_yuijs_path_java"><?php _e( 'Path to JAVA executable:', 'w3-total-cache' ); ?></label></th>
10
  <td>
11
- <input id="minify_yuijs_path_java" class="js_enabled" type="text"
12
  <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__yuijs__path__java" value="<?php echo esc_attr( $this->_config->get_string( 'minify.yuijs.path.java' ) ); ?>" size="100" />
13
  </td>
14
  </tr>
15
  <tr>
16
- <th><label for="minify_yuijs_path_jar"><?php _e( 'Path to JAR file:', 'w3-total-cache' ); ?></label></th>
17
  <td>
18
- <input id="minify_yuijs_path_jar" class="js_enabled" type="text"
19
  <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__yuijs__path__jar" value="<?php echo esc_attr( $this->_config->get_string( 'minify.yuijs.path.jar' ) ); ?>" size="100" />
20
  </td>
21
  </tr>
@@ -27,9 +27,9 @@ if ( !defined( 'W3TC' ) )
27
  </td>
28
  </tr>
29
  <tr>
30
- <th><label for="minify_yuijs_options_line-break"><?php Util_Ui::e_config_label( 'minify.yuijs.options.line-break' ) ?></label></th>
31
  <td>
32
- <input id="minify_yuijs_options_line-break" class="js_enabled"
33
  type="text" <?php Util_Ui::sealing_disabled( 'minify.' ) ?>
34
  name="minify__yuijs__options__line-break" value="<?php echo esc_attr( $this->_config->get_integer( 'minify.yuijs.options.line-break' ) ); ?>" size="8" style="text-align: right;" /> <?php _e( 'symbols (set to 0 to disable)', 'w3-total-cache' ); ?>
35
  </td>
6
 
7
  ?>
8
  <tr>
9
+ <th><label for="minify__yuijs__path__java"><?php _e( 'Path to JAVA executable:', 'w3-total-cache' ); ?></label></th>
10
  <td>
11
+ <input id="minify__yuijs__path__java" class="js_enabled" type="text"
12
  <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__yuijs__path__java" value="<?php echo esc_attr( $this->_config->get_string( 'minify.yuijs.path.java' ) ); ?>" size="100" />
13
  </td>
14
  </tr>
15
  <tr>
16
+ <th><label for="minify__yuijs__path__jar"><?php _e( 'Path to JAR file:', 'w3-total-cache' ); ?></label></th>
17
  <td>
18
+ <input id="minify__yuijs__path__jar" class="js_enabled" type="text"
19
  <?php Util_Ui::sealing_disabled( 'minify.' ) ?> name="minify__yuijs__path__jar" value="<?php echo esc_attr( $this->_config->get_string( 'minify.yuijs.path.jar' ) ); ?>" size="100" />
20
  </td>
21
  </tr>
27
  </td>
28
  </tr>
29
  <tr>
30
+ <th><label for="minify__yuijs__options__line-break"><?php Util_Ui::e_config_label( 'minify.yuijs.options.line-break' ) ?></label></th>
31
  <td>
32
+ <input id="minify__yuijs__options__line-break" class="js_enabled"
33
  type="text" <?php Util_Ui::sealing_disabled( 'minify.' ) ?>
34
  name="minify__yuijs__options__line-break" value="<?php echo esc_attr( $this->_config->get_integer( 'minify.yuijs.options.line-break' ) ); ?>" size="8" style="text-align: right;" /> <?php _e( 'symbols (set to 0 to disable)', 'w3-total-cache' ); ?>
35
  </td>
inc/options/pgcache.php CHANGED
@@ -166,8 +166,8 @@ Util_Ui::config_item( array(
166
  <?php
167
  $modules = array();
168
  if ( $pgcache_enabled ) $modules[] = 'Page Cache';
169
- if ( $varnish_enabled ) $modules [] = 'Varnish';
170
- if ( $cdn_mirror_purge_enabled ) $modules[] = 'CDN';
171
  Util_Ui::postbox_header( __( 'Purge Policy: ', 'w3-total-cache' ) . implode( ', ', $modules ), '', 'purge_policy' ); ?>
172
  <table class="form-table">
173
  <tr>
@@ -336,7 +336,7 @@ if ( $this->_config->get_string( 'pgcache.engine' ) == 'memcached' ) {
336
  <textarea id="pgcache_accept_qs" name="pgcache__accept__qs"
337
  <?php Util_Ui::sealing_disabled( 'pgcache.' ) ?>
338
  cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'pgcache.accept.qs' ) ) ); ?></textarea><br />
339
- <span class="description"><?php _e( 'Always cache <acronym title="Uniform Resource Locator">URL</acronym>s with these query strings.', 'w3-total-cache' ); ?></span>
340
  </td>
341
  </tr>
342
  <tr>
@@ -371,6 +371,42 @@ echo sprintf(
371
  </span>
372
  </td>
373
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  <tr>
375
  <th><label for="pgcache_accept_files"><?php Util_Ui::e_config_label( 'pgcache.accept.files' ) ?></label></th>
376
  <td>
@@ -400,12 +436,12 @@ echo sprintf(
400
  <span class="description"><?php _e( 'Specify additional page headers to cache.', 'w3-total-cache' )?></span>
401
  </td>
402
  </tr>
403
- <?php if ( Util_Environment::is_nginx() && $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' ): ?>
404
  <tr>
405
  <th><label><?php Util_Ui::e_config_label( 'pgcache.cache.nginx_handle_xml' ) ?></label></th>
406
  <td>
407
- <?php $this->checkbox( 'pgcache.cache.nginx_handle_xml', true ) ?> <?php Util_Ui::e_config_label( 'pgcache.cache.nginx_handle_xml' ) ?></label><br />
408
- <span class="description"><?php _e( 'Return correct Content-Type header for XML files. Slows down cache engine.', 'w3-total-cache' ); ?></span>
409
  </td>
410
  </tr>
411
  <?php endif; ?>
166
  <?php
167
  $modules = array();
168
  if ( $pgcache_enabled ) $modules[] = 'Page Cache';
169
+ if ( $varnish_enabled ) $modules [] = 'Reverse Proxy';
170
+ if ( $cdnfsd_enabled ) $modules[] = 'CDN';
171
  Util_Ui::postbox_header( __( 'Purge Policy: ', 'w3-total-cache' ) . implode( ', ', $modules ), '', 'purge_policy' ); ?>
172
  <table class="form-table">
173
  <tr>
336
  <textarea id="pgcache_accept_qs" name="pgcache__accept__qs"
337
  <?php Util_Ui::sealing_disabled( 'pgcache.' ) ?>
338
  cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'pgcache.accept.qs' ) ) ); ?></textarea><br />
339
+ <span class="description"><?php _e( 'Always cache <acronym title="Uniform Resource Locator">URL</acronym>s that use these query string name-value pairs. The value part is not required. But if used, separate name-value pairs with an equals sign (i.e., name=value). Each pair should be on their own line.', 'w3-total-cache' ); ?></span>
340
  </td>
341
  </tr>
342
  <tr>
371
  </span>
372
  </td>
373
  </tr>
374
+ <tr>
375
+ <th><label for="pgcache_reject_categories"><?php Util_Ui::e_config_label( 'pgcache.reject.categories' ) ?></label></th>
376
+ <td>
377
+ <textarea id="pgcache_reject_categories" name="pgcache__reject__categories"
378
+ <?php Util_Ui::sealing_disabled( 'pgcache' ) ?>
379
+ cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array('pgcache.reject.categories' ) ) ); ?></textarea><br />
380
+ <span class="description"><?php _e( 'Always ignore all pages filed under the specified category slugs.', 'w3-total-cache' ); ?></span>
381
+ </td>
382
+ </tr>
383
+ <tr>
384
+ <th><label for="pgcache_reject_tags"><?php Util_Ui::e_config_label( 'pgcache.reject.tags' ) ?></label></th>
385
+ <td>
386
+ <textarea id="pgcache_reject_tags" name="pgcache__reject__tags"
387
+ <?php Util_Ui::sealing_disabled( 'pgcache' ) ?>
388
+ cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'pgcache.reject.tags' ) ) ); ?></textarea><br />
389
+ <span class="description"><?php _e( 'Always ignore all pages filed under the specified tag slugs.', 'w3-total-cache' ); ?></span>
390
+ </td>
391
+ </tr>
392
+ <tr>
393
+ <th><label for="pgcache_reject_authors"><?php Util_Ui::e_config_label( 'pgcache.reject.authors' ) ?></label></th>
394
+ <td>
395
+ <textarea id="pgcache_reject_authors" name="pgcache__reject__authors"
396
+ <?php Util_Ui::sealing_disabled( 'pgcache' ) ?>
397
+ cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array( 'pgcache.reject.authors' ) ) ); ?></textarea><br />
398
+ <span class="description"><?php _e( 'Always ignore all pages filed under the specified author usernames.', 'w3-total-cache' ); ?></span>
399
+ </td>
400
+ </tr>
401
+ <tr>
402
+ <th><label for="pgcache_reject_custom"><?php Util_Ui::e_config_label( 'pgcache.reject.custom' ) ?></label></th>
403
+ <td>
404
+ <textarea id="pgcache_reject_custom" name="pgcache__reject__custom"
405
+ <?php Util_Ui::sealing_disabled( 'pgcache' ) ?>
406
+ cols="40" rows="5"><?php echo esc_textarea( implode( "\r\n", $this->_config->get_array('pgcache.reject.custom' ) ) ); ?></textarea><br />
407
+ <span class="description"><?php _e( 'Always ignore all pages filed under the specified custom fields. Separate name-value pairs with an equals sign (i.e., name=value).', 'w3-total-cache' ); ?></span>
408
+ </td>
409
+ </tr>
410
  <tr>
411
  <th><label for="pgcache_accept_files"><?php Util_Ui::e_config_label( 'pgcache.accept.files' ) ?></label></th>
412
  <td>
436
  <span class="description"><?php _e( 'Specify additional page headers to cache.', 'w3-total-cache' )?></span>
437
  </td>
438
  </tr>
439
+ <?php if ( $this->_config->get_string( 'pgcache.engine' ) == 'file_generic' ): ?>
440
  <tr>
441
  <th><label><?php Util_Ui::e_config_label( 'pgcache.cache.nginx_handle_xml' ) ?></label></th>
442
  <td>
443
+ <?php $this->checkbox( 'pgcache.cache.nginx_handle_xml' ) ?> <?php Util_Ui::e_config_label( 'pgcache.cache.nginx_handle_xml' ) ?></label><br />
444
+ <span class="description"><?php _e( 'Return correct Content-Type header for XML files (e.g., feeds and sitemaps). Slows down cache engine.', 'w3-total-cache' ); ?></span>
445
  </td>
446
  </tr>
447
  <?php endif; ?>
inc/popup/cdn_purge.php CHANGED
@@ -8,7 +8,7 @@ if ( !defined( 'W3TC' ) )
8
  <?php include W3TC_INC_DIR . '/popup/common/header.php';?>
9
 
10
  <p>
11
- <?php _e( 'Remove objects from the CDN by specifying the relative path on individual lines below and clicking the "Purge" button when done. For example:', 'w3-total-cache' ); ?>
12
  </p>
13
  <p>
14
  <?php switch ( $this->_config->get_string( 'cdn.engine' ) ):
8
  <?php include W3TC_INC_DIR . '/popup/common/header.php';?>
9
 
10
  <p>
11
+ <?php _e( 'Remove objects from the <acronym title="Content Delivery Network">CDN</acronym> by specifying the relative path on individual lines below and clicking the "Purge" button when done. For example:', 'w3-total-cache' ); ?>
12
  </p>
13
  <p>
14
  <?php switch ( $this->_config->get_string( 'cdn.engine' ) ):
inc/widget/maxcdn_signup.php CHANGED
@@ -18,34 +18,5 @@ if ( !defined( 'W3TC' ) )
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_dashboard&w3tc_cdn_maxcdn_authorize' ), 'w3tc' )?>" target="_blank"><?php _e( 'Authorize', 'w3-total-cache' )?></a>
22
- <form action="admin.php?page=w3tc_dashboard" method="post">
23
- <p>
24
- <label for="cdn_maxcdn_authorization_key"><?php _e( 'Authorization key', 'w3-total-cache' )?>:</label>
25
- <input name="maxcdn" value="1" type="hidden" />
26
- <input id="cdn_maxcdn_authorization_key" class="w3tc-ignore-change" type="text" <?php echo $is_sealed? 'disabled="disabled"':'' ?> name="cdn.maxcdn.authorization_key"
27
- value="<?php echo esc_attr( $this->_config->get_string( 'cdn.maxcdn.authorization_key' ) ); ?>" size="31"
28
- onblur="w3tc_validate_cdn_key_result('maxcdn','<?php echo wp_create_nonce( 'w3tc' ); ?>')" />
29
- <br />
30
- <input id="validate_cdn_key" type="button" class="button {type: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Validate', 'w3-total-cache' ) ?>" /><span id="validate_cdn_key_result" style="margin-left:5px;padding:3px 8px 3px 20px;"></span>
31
- <span id="validate_cdn_key_result" style="margin-left:5px;padding:3px 8px 3px 20px;"></span>
32
- </p>
33
- </form>
34
- <p id="create_zone_area" style="<?php echo $authorized && ( !$have_zone || is_null( $zone_info ) ) ? '' : 'display: none' ?>"><input type="button" class="button" onclick="w3tc_create_zone('maxcdn','<?php echo wp_create_nonce( 'w3tc' ); ?>')" value="<?php _e( 'Create Default Zone', 'w3-total-cache' ) ?>" />
35
- <span id="create_pull_zone_result" style="margin-left:15px;padding:3px 8px 3px 8px;"></span>
36
- <br /><span class="description"><?php _e( 'You have no zone connected with this site. Click button to create a default zone.', 'w3-total-cache' ) ?></span>
37
- </p>
38
- <p id="select_pull_zone" style="<?php echo !( $authorized && $pull_zones ) ? 'display:none' : '' ?>">
39
- <select id="cdn_maxcdn_zone_id" name="cdn.maxcdn.zone_id">
40
- <?php foreach ( $pull_zones as $zone ):?>
41
- <option value="<?php echo $zone['id'] ?>" <?php selected( $zone['id'], $this->_config->get_integer( 'cdn.maxcdn.zone_id' ) )?>><?php echo $zone['name']?></option>
42
- <?php endforeach; ?>
43
- </select> <input id="use_poll_zone" type="button" class="button {type: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Use Zone', 'w3-total-cache' ) ?>" /><span id="use_pull_zone_result" style="margin-left:15px;padding:3px 8px 3px 8px;"></span>
44
- <br />
45
- <span class="description"><?php _e( 'Select the pull zone to use with this site.', 'w3-total-cache' )?></span>
46
- </p>
47
- <p id="cdn_result_message" class="description"></p>
48
- <?php if ( $authorized && ( !$have_zone || is_null( $zone_info ) ) ): ?>
49
- <button id="netdna-maxcdn-create-pull-zone" class="button-primary {type: 'maxcdn', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"><?php _e( 'Create Pull Zone', 'w3-total-cache' )?></button>
50
- <?php endif ?>
51
  </div>
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>
inc/widget/netdna.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="netdna-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.netdna.com/zones/pull/{$zone_id}"?>"><?php _e( 'Manage', 'w3-total-cache' )?></a></li>
30
- <li><a class="button" href="<?php echo "https://cp.netdna.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( 'Reports - 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/netdna_signup.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
- namespace W3TC;
3
-
4
- if ( !defined( 'W3TC' ) )
5
- die();
6
-
7
- /**
8
- *
9
- *
10
- * @var bool $authorized
11
- * @var bool $have_zone
12
- */
13
- ?>
14
- <div id="netdna-widget" class="sign-up maxcdn-netdna-widget-base">
15
- <?php if ( $error ): ?>
16
- <?php Util_Ui::error_box( '<p>' . sprintf( __( 'NetDNA encountered an error trying to retrieve data, make sure your host support cURL and outgoing requests: %s', 'w3-total-cache' ), $error ) . '</p>' ) ?>
17
- <?php endif; ?>
18
- <h4><?php _e( 'Current customers', 'w3-total-cache' )?></h4>
19
- <p><?php _e( "Once you've signed up or if you're an existing NetDNA customer, to enable CDN:", 'w3-total-cache' )?></p>
20
- <?php if ( $authorized && ( !$have_zone || is_null( $zone_info ) ) ): ?>
21
- <button id="netdna-maxcdn-create-pull-zone" class="button-primary {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"><?php _e( 'Create Pull Zone', 'w3-total-cache' )?></button>
22
- <?php elseif ( !$authorized ): ?>
23
- <a class="button-primary" href="<?php echo wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_netdna_authorize' ), 'w3tc' )?>" target="_blank"><?php _e( 'Authorize', 'w3-total-cache' )?></a>
24
- <form action="admin.php?page=w3tc_dashboard" method="post">
25
- <p>
26
- <label for="cdn_netdna_authorization_key"><?php _e( 'Authorization key', 'w3-total-cache' )?>:</label>
27
- <input name="netdna" value="1" type="hidden" />
28
- <input id="cdn_netdna_authorization_key" class="w3tc-ignore-change" type="text" <?php echo $is_sealed? 'disabled="disabled"':'' ?> name="cdn.netdna.authorization_key" value="<?php echo esc_attr( $this->_config->get_string( 'cdn.netdna.authorization_key' ) ); ?>" size="31"
29
- onblur="w3tc_validate_cdn_key_result('netdna','<?php echo wp_create_nonce( 'w3tc' ); ?>')" />
30
- <br />
31
- <input id="validate_cdn_key" type="button" class="button {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Validate', 'w3-total-cache' ) ?>" /><span id="validate_cdn_key_result" style="margin-left:5px;padding:3px 8px 3px 20px;"></span>
32
- <span id="validate_cdn_key_result" style="margin-left:5px;padding:3px 8px 3px 20px;"></span>
33
- </p>
34
- </form>
35
- <?php endif ?>
36
- <p id="create_zone_area" style="<?php echo $authorized && ( !$have_zone || is_null( $zone_info ) ) ? '' : 'display: none' ?>"><input type="button" class="button" onclick="w3tc_create_zone('netdna','<?php echo wp_create_nonce( 'w3tc' ); ?>')" value="<?php _e( 'Create Default Zone', 'w3-total-cache' ) ?>" />
37
- <span id="create_pull_zone_result" style="margin-left:15px;padding:3px 8px 3px 8px;"></span>
38
- <br /><span class="description"><?php _e( 'You have no zone connected with this site. Click button to create a default zone.', 'w3-total-cache' ) ?></span>
39
- </p>
40
- <p id="select_pull_zone" style="<?php echo !( $authorized && $pull_zones ) ? 'display:none' : '' ?>">
41
- <select id="cdn_netdna_zone_id" name="cdn.netdna.zone_id">
42
- <?php foreach ( $pull_zones as $zone ):?>
43
- <option value="<?php echo $zone['id'] ?>" <?php selected( $zone['id'], $this->_config->get_integer( 'cdn.netdna.zone_id' ) )?>><?php echo $zone['name']?></option>
44
- <?php endforeach; ?>
45
- </select> <input id="use_poll_zone" type="button" class="button {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}" value="<?php _e( 'Use Zone', 'w3-total-cache' ) ?>" /><span id="use_pull_zone_result" style="margin-left:15px;padding:3px 8px 3px 8px;"></span>
46
- <br />
47
- <span class="description"><?php _e( 'Select the pull zone to use with this site.', 'w3-total-cache' )?></span>
48
- </p>
49
- <p id="cdn_result_message" class="description"></p>
50
- <?php if ( $authorized && ( !$have_zone || is_null( $zone_info ) ) ): ?>
51
- <button id="netdna-maxcdn-create-pull-zone" class="button-primary {type: 'netdna', nonce: '<?php echo wp_create_nonce( 'w3tc' ); ?>'}"><?php _e( 'Create Pull Zone', 'w3-total-cache' )?></button>
52
- <?php endif ?>
53
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ini/config-db-sample.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ define( 'W3TC_CONFIG_DATABASE', true );
4
+
5
+ // optional - specify table to store
6
+ define( 'W3TC_CONFIG_DATABASE_TABLE', 'wp_options' );
7
+
8
+ // cache config in cache to prevent db queries on each http request.
9
+ // if multiple http servers used - use only shared cache storage used by all
10
+ // machines, since distributed flush operations are not supported for config
11
+ // cache
12
+
13
+ //
14
+ // memcached cache config
15
+ //
16
+ define( 'W3TC_CONFIG_CACHE_ENGINE', 'memcached');
17
+ define( 'W3TC_CONFIG_CACHE_MEMCACHED_SERVERS', '127.0.0.1:11211' );
18
+
19
+ // optional memcached settings
20
+ define( 'W3TC_CONFIG_CACHE_MEMCACHED_PERSISTENT', true );
21
+ define( 'W3TC_CONFIG_CACHE_MEMCACHED_AWS_AUTODISCOVERY', false );
22
+ define( 'W3TC_CONFIG_CACHE_MEMCACHED_USERNAME', '' );
23
+ define( 'W3TC_CONFIG_CACHE_MEMCACHED_PASSWORD', '' );
24
+
25
+ //
26
+ // redis config cache
27
+ //
28
+ define( 'W3TC_CONFIG_CACHE_ENGINE', 'redis');
29
+ define( 'W3TC_CONFIG_CACHE_REDIS_SERVERS', '127.0.0.1:6379' );
30
+
31
+ // optional redis settings
32
+ define( 'W3TC_CONFIG_CACHE_REDIS_PERSISTENT', true );
33
+ define( 'W3TC_CONFIG_CACHE_REDIS_DBID', 0 );
34
+ define( 'W3TC_CONFIG_CACHE_REDIS_PASSWORD', '' );
ini/dbcluster-config-sample.php CHANGED
@@ -1,156 +1,172 @@
1
  <?php
2
 
3
- global $wpdb_cluster;
4
 
5
- /**
6
- * Persistent (bool)
7
- *
8
- * This determines whether to use mysql_connect or mysql_pconnect. The effects
9
- * of this setting may vary and should be carefully tested.
10
- * Default: false
11
- */
12
- $wpdb_cluster->persistent = false;
 
13
 
14
- /**
15
- * check_tcp_responsiveness
16
- *
17
- * Enables checking TCP responsiveness by fsockopen prior to mysql_connect or
18
- * mysql_pconnect. This was added because PHP's mysql functions do not provide
19
- * a variable timeout setting. Disabling it may improve average performance by
20
- * a very tiny margin but lose protection against connections failing slowly.
21
- * Default: true
22
- */
23
- $wpdb_cluster->check_tcp_responsiveness = true;
24
 
25
- /**
26
- * Default is to always (reads & writes) use the master db when user is in administration backend.
27
- * Set use_master_in_backend to false to disable this behavior.
28
- *
29
- * WARNING: if your cluster has any replication delays then when this is enabled, you may not see
30
- * any admin changes until the replication catches up with the change written to your master
31
- * server and will see old content/configuration until that point in time - You should test this
32
- * in your environment fully.
33
- */
34
- //$wpdb_cluster->use_master_in_backend = false;
35
 
36
- /**
37
- * This set the charset that the db connection should use.
38
- * If DB_CHARSET is set there is no need to set $wpdb_cluster->charset.
39
- */
40
- //$wpdb_cluster->charset = 'utf-8';
41
 
42
- /**
43
- * This set the charset that the db connection should use.
44
- * If DB_COLLATE is set there is no need to set $wpdb_cluster->collate.
45
- */
46
- //$wpdb_cluster->collate = 'utf8_general_ci';
47
- /** Configuration Functions **/
48
 
49
- /**
50
- * $wpdb_cluster->add_database( $database );
51
- *
52
- * $database is an associative array with these parameters:
53
- * host (required) Hostname with optional :port. Default port is 3306.
54
- * user (required) MySQL user name.
55
- * password (required) MySQL user password.
56
- * name (required) MySQL database name.
57
- * read (optional) Whether server is readable. Default is 1 (readable).
58
- * Also used to assign preference.
59
- * write (optional) Whether server is writable. Default is 1 (writable).
60
- * Also used to assign preference in multi-master mode.
61
- * dataset (optional) Name of dataset. Default is 'global'.
62
- * timeout (optional) Seconds to wait for TCP responsiveness. Default is 0.2
63
- * connect_function (optional) connection function to use
64
- * zone (optional) name of zone where server is located.
65
- * Used for web applications hosted on cluster
66
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
- /**
69
- * $wpdb_cluster->add_callback( $callback, $callback_group = 'dataset' );
70
- *
71
- * $callback is a callable function or method. $callback_group is the
72
- * group of callbacks, this $callback belongs to.
73
- *
74
- * Callbacks are executed in the order in which they are registered until one
75
- * of them returns something other than null.
76
- *
77
- * The default $callback_group is 'dataset'. Callback in this group
78
- * will be called with two arguments and expected to compute a dataset or return null.
79
- * $dataset = $callback($table, &$wpdb);
80
- *
81
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
- /** Masters and slaves
84
- *
85
- * A database definition can include 'read' and 'write' parameters. These
86
- * operate as boolean switches but they are typically specified as integers.
87
- * They allow or disallow use of the database for reading or writing.
88
- *
89
- * A master database might be configured to allow reading and writing:
90
- * 'write' => true,
91
- * 'read' => true,
92
- * while a slave would be allowed only to read:
93
- * 'write' => false,
94
- * 'read' => true,
95
- *
96
- * It might be advantageous to disallow reading from the master, such as when
97
- * there are many slaves available and the master is very busy with writes.
98
- * 'write' => true,
99
- * 'read' => false,
100
- */
 
 
 
 
 
 
 
101
 
102
- /**
103
- * Web applications hosted on cluster
104
- *
105
- * When your databases are located in separate physical locations there is
106
- * typically an advantage to connecting to a nearby server instead of a more
107
- * distant one. This can be configured by defining zones.
108
- *
109
- * Add 'zone' parameter to add_server call:
110
- * 'zone' => 'A'
111
- *
112
- * Plugin determines where application is running by checking
113
- * $_SERVER['SERVER_NAME'] system variable against defined in zone definition
114
- * and then connects to servers following defined order:
115
- * Value '*' can be used as 'server_names' item to indicate any server.
116
- *
117
- * $wpdb_cluster->add_zone(array(
118
- * 'name' => 'A',
119
- * 'server_names' => array('host1', 'host1.1'),
120
- * 'zone_priorities' => array('A', 'B')
121
- * ));
122
- *
123
- * As a result it will try to connect to servers in zone A first, then servers
124
- * in zone B.
125
- */
126
 
127
- /**
128
- * This is the most basic way to add a server using only the
129
- * required parameters: host, user, password, name.
130
- * This adds the DB defined in wp-config.php as a read/write server for
131
- * the 'global' dataset. (Every table is in 'global' by default.)
132
- */
133
- $wpdb_cluster->add_database(array(
134
- 'host' => DB_HOST, // If port is other than 3306, use host:port.
135
- 'user' => DB_USER,
136
- 'password' => DB_PASSWORD,
137
- 'name' => DB_NAME,
138
- ));
139
 
140
  /**
141
  * This adds the same server again, only this time it is configured as a slave.
142
  * The last three parameters are set to the defaults but are shown for clarity.
143
  */
144
  /*
145
- $wpdb_cluster->add_database(array(
146
- 'host' => DB_HOST, // If port is other than 3306, use host:port.
147
- 'user' => DB_USER,
148
- 'password' => DB_PASSWORD,
149
- 'name' => DB_NAME,
150
- 'write' => false,
151
- 'read' => true,
152
- 'dataset' => 'global',
153
- 'timeout' => 0.2,
 
 
 
 
 
 
 
154
  ));
155
  */
156
 
@@ -161,20 +177,30 @@ $wpdb_cluster->add_database(array(
161
  * separated from the global dataset.
162
  */
163
  /*
164
- $wpdb_cluster->add_database(array(
165
- 'host' => 'global.db.example.com',
166
- 'user' => 'globaluser',
167
- 'password' => 'globalpassword',
168
- 'name' => 'globaldb',
169
- ));
170
- $wpdb_cluster->add_database(array(
171
- 'host' => 'blog.db.example.com',
172
- 'user' => 'bloguser',
173
- 'password' => 'blogpassword',
174
- 'name' => 'blogdb',
175
- 'dataset' => 'blog2',
176
- ));
177
- $wpdb_cluster->add_callback('my_db_callback', 'blog_dataset');
 
 
 
 
 
 
 
 
 
 
178
  function my_db_callback($blog_id, $wpdb_cluster) {
179
  if ($blog_id > 5))
180
  return 'blog2';
1
  <?php
2
 
3
+ global $w3tc_dbcluster_config;
4
 
5
+ $w3tc_dbcluster_config = array(
6
+ /**
7
+ * Persistent (bool)
8
+ *
9
+ * This determines whether to use mysql_connect or mysql_pconnect. The effects
10
+ * of this setting may vary and should be carefully tested.
11
+ * Default: false
12
+ */
13
+ 'persistent' => false,
14
 
15
+ /**
16
+ * check_tcp_responsiveness
17
+ *
18
+ * Enables checking TCP responsiveness by fsockopen prior to mysql_connect or
19
+ * mysql_pconnect. This was added because PHP's mysql functions do not provide
20
+ * a variable timeout setting. Disabling it may improve average performance by
21
+ * a very tiny margin but lose protection against connections failing slowly.
22
+ * Default: true
23
+ */
24
+ 'check_tcp_responsiveness' => true,
25
 
26
+ /**
27
+ * Default is to always (reads & writes) use the master db when user is in administration backend.
28
+ * Set use_master_in_backend to false to disable this behavior.
29
+ *
30
+ * WARNING: if your cluster has any replication delays then when this is enabled, you may not see
31
+ * any admin changes until the replication catches up with the change written to your master
32
+ * server and will see old content/configuration until that point in time - You should test this
33
+ * in your environment fully.
34
+ */
35
+ 'use_master_in_backend' => true,
36
 
37
+ /**
38
+ * This set the charset that the db connection should use.
39
+ * If DB_CHARSET is set there is no need to set $wpdb_cluster->charset.
40
+ */
41
+ 'charset' => DB_CHARSET,
42
 
43
+ /**
44
+ * This set the charset that the db connection should use.
45
+ * If DB_COLLATE is set there is no need to set $wpdb_cluster->collate.
46
+ */
47
+ 'collate' => DB_COLLATE,
48
+ /** Configuration Functions **/
49
 
50
+ /**
51
+ * database is an associative array with these parameters:
52
+ * host (required) Hostname with optional :port. Default port is 3306.
53
+ * user (required) MySQL user name.
54
+ * password (required) MySQL user password.
55
+ * name (required) MySQL database name.
56
+ * read (optional) Whether server is readable. Default is 1 (readable).
57
+ * Also used to assign preference.
58
+ * write (optional) Whether server is writable. Default is 1 (writable).
59
+ * Also used to assign preference in multi-master mode.
60
+ * dataset (optional) Name of dataset. Default is 'global'.
61
+ * timeout (optional) Seconds to wait for TCP responsiveness. Default is 0.2
62
+ * connect_function (optional) connection function to use
63
+ * zone (optional) name of zone where server is located.
64
+ * Used for web applications hosted on cluster
65
+ *
66
+ * Read & write
67
+ * A database definition can include 'read' and 'write' parameters. These
68
+ * operate as boolean switches but they are typically specified as integers.
69
+ * They allow or disallow use of the database for reading or writing.
70
+ *
71
+ * A master database might be configured to allow reading and writing:
72
+ * 'write' => true,
73
+ * 'read' => true,
74
+ * while a slave would be allowed only to read:
75
+ * 'write' => false,
76
+ * 'read' => true,
77
+ *
78
+ * It might be advantageous to disallow reading from the master, such as when
79
+ * there are many slaves available and the master is very busy with writes.
80
+ * 'write' => true,
81
+ * 'read' => false,
82
+ *
83
+ */
84
+ 'databases' => array(
85
+ 'master' => array(
86
+ 'host' => DB_HOST, // If port is other than 3306, use host:port.
87
+ 'user' => DB_USER,
88
+ 'password' => DB_PASSWORD,
89
+ 'name' => DB_NAME
90
+ )
91
+ ),
92
 
93
+ /**
94
+ * Zones (for web applications hosted on cluster)
95
+ *
96
+ * When your databases are located in separate physical locations there is
97
+ * typically an advantage to connecting to a nearby server instead of a more
98
+ * distant one. This can be configured by defining zones.
99
+ *
100
+ * Add 'zone' parameter to add_server call:
101
+ * 'zone' => 'A'
102
+ *
103
+ * Plugin determines where application is running by checking
104
+ * $_SERVER['SERVER_NAME'] system variable against defined in zone definition
105
+ * and then connects to servers following defined order:
106
+ * Value '*' can be used as 'server_names' item to indicate any server.
107
+ *
108
+ * 'zones' => array(
109
+ * 'zone_name' => array(
110
+ * 'server_names' => array('host1', 'host1.1'),
111
+ * 'zone_priorities' => array('A', 'B')
112
+ * )
113
+ * )
114
+ *
115
+ * As a result it will try to connect to servers in zone A first, then servers
116
+ * in zone B.
117
+ */
118
+ 'zones' => array(
119
+ ),
120
 
121
+ /**
122
+ * Filters
123
+ *
124
+ * Filters are executed on <tag> event in the order in which they are
125
+ * registered until one of them returns something other than null.
126
+ *
127
+ * Tags:
128
+ * 'dataset' - fitler will be called with two arguments and expected to
129
+ * return a dataset to connect to
130
+ * $dataset = $callback($table, &$wpdb);
131
+ * 'blog_dataset' - fitler will be called with argument $blog_id and
132
+ * expected to return a dataset to connect to.
133
+ * Used when data are partitioned at blog level
134
+ * $dataset = $callback($blog_id);
135
+ *
136
+ * 'filters' => array(
137
+ * array(
138
+ * 'tag' => 'tag_to_add',
139
+ * 'function_to_add' => 'function_name'
140
+
141
+ * );
142
+ */
143
+ 'filters' => array(
144
+ )
145
+ );
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
  /**
150
  * This adds the same server again, only this time it is configured as a slave.
151
  * The last three parameters are set to the defaults but are shown for clarity.
152
  */
153
  /*
154
+ $w3tc_dbcluster_config = array(
155
+ 'databases' => array(
156
+ 'master' => array(
157
+ 'host' => DB_HOST,
158
+ 'user' => DB_USER,
159
+ 'password' => DB_PASSWORD,
160
+ 'name' => DB_NAME
161
+ ),
162
+ 'slave' => array(
163
+ 'host' => DB_HOST,
164
+ 'user' => DB_USER,
165
+ 'password' => DB_PASSWORD,
166
+ 'name' => DB_NAME,
167
+ 'write' => false,
168
+ 'read' => true,
169
+ 'timeout' => 0.2,
170
  ));
171
  */
172
 
177
  * separated from the global dataset.
178
  */
179
  /*
180
+ $w3tc_dbcluster_config = array(
181
+ 'databases' => array(
182
+ 'master' => array(
183
+ 'host' => 'global.db.example.com',
184
+ 'user' => 'globaluser',
185
+ 'password' => 'globalpassword',
186
+ 'name' => 'globaldb',
187
+ ),
188
+ 'partition2' => array(
189
+ 'host' => 'blog.db.example.com',
190
+ 'user' => 'bloguser',
191
+ 'password' => 'blogpassword',
192
+ 'name' => 'blogdb',
193
+ 'dataset' => 'blog2',
194
+ ),
195
+ )
196
+ 'filters' => array(
197
+ array(
198
+ 'tag' => 'blog_dataset',
199
+ 'function_to_add' => 'my_db_callback'
200
+ )
201
+ )
202
+ );
203
+
204
  function my_db_callback($blog_id, $wpdb_cluster) {
205
  if ($blog_id > 5))
206
  return 'blog2';
ini/web.config CHANGED
@@ -3,8 +3,33 @@
3
  <system.webServer>
4
  <rewrite>
5
  <rules>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  <rule name="w3tc_rewrite_test" stopProcessing="true">
7
- <match url="wp-content/cache/minify/w3tc_rewrite_test" />
8
  <conditions>
9
  <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
10
  <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
@@ -12,10 +37,9 @@
12
  <action type="Rewrite" url="index.php" />
13
  </rule>
14
  <rule name="w3tc-minify-file" stopProcessing="true">
15
- <match url="wp-content/cache/minify/(.+\.(css|js))$" />
16
  <conditions>
17
  <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
18
- <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
19
  </conditions>
20
  <action type="Rewrite" url="index.php" />
21
  </rule>
@@ -29,6 +53,7 @@
29
  </rule>
30
  </rules>
31
  </rewrite>
 
32
  <staticContent>
33
  <clientCache cacheControlMaxAge="30.00:00:00" cacheControlMode="UseMaxAge"/>
34
  </staticContent>
3
  <system.webServer>
4
  <rewrite>
5
  <rules>
6
+ <!-- http website -->
7
+ <rule name="w3tc_pagecache" stopProcessing="true">
8
+ <match url="(.*)" />
9
+ <conditions logicalGrouping="MatchAll">
10
+ <add input="{REQUEST_METHOD}" pattern="^POST$" negate="true" />
11
+ <add input="{QUERY_STRING}" pattern=".*=.*" negate="true" />
12
+ <add input="{HTTP_COOKIE}" pattern="^.*(comment_author_|wordpress|wp-postpass_).*$" negate="true" />
13
+ <add input="{DOCUMENT_ROOT}/wp-content/cache/page_enhanced/{HTTP_HOST}/{R:1}_index.html"
14
+ matchType="IsFile" />
15
+ </conditions>
16
+ <action type="Rewrite" url="wp-content/cache/page_enhanced/{HTTP_HOST}/{R:1}_index.html" />
17
+ </rule>
18
+ <!-- https website -->
19
+ <rule name="w3tc_pagecache_ssl" stopProcessing="true">
20
+ <match url="(.*)" />
21
+ <conditions logicalGrouping="MatchAll">
22
+ <add input="{REQUEST_METHOD}" pattern="^POST$" negate="true" />
23
+ <add input="{QUERY_STRING}" pattern=".*=.*" negate="true" />
24
+ <add input="{HTTP_COOKIE}" pattern="^.*(comment_author_|wordpress|wp-postpass_).*$" negate="true" />
25
+ <add input="{DOCUMENT_ROOT}/wp-content/cache/page_enhanced/{HTTP_HOST}/{R:1}_index_ssl.html"
26
+ matchType="IsFile" />
27
+ </conditions>
28
+ <action type="Rewrite" url="wp-content/cache/page_enhanced/{HTTP_HOST}/{R:1}_index_ssl.html" />
29
+ </rule>
30
+ <!-- minify, disk engine -->
31
  <rule name="w3tc_rewrite_test" stopProcessing="true">
32
+ <match url="/wp-content/cache/minify/w3tc_rewrite_test" />
33
  <conditions>
34
  <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
35
  <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
37
  <action type="Rewrite" url="index.php" />
38
  </rule>
39
  <rule name="w3tc-minify-file" stopProcessing="true">
40
+ <match url="/wp-content/cache/minify/(.+\.(css|js))$" />
41
  <conditions>
42
  <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
 
43
  </conditions>
44
  <action type="Rewrite" url="index.php" />
45
  </rule>
53
  </rule>
54
  </rules>
55
  </rewrite>
56
+ <!-- leverage browser cache -->
57
  <staticContent>
58
  <clientCache cacheControlMaxAge="30.00:00:00" cacheControlMode="UseMaxAge"/>
59
  </staticContent>
languages/faq-en_US.xml CHANGED
@@ -251,6 +251,11 @@ Note: To disable page caching of specific theme templates or plugin files you ne
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
  </section>
255
  <section name="Minification">
256
  <entry>
@@ -407,7 +412,7 @@ Note: To disable page caching of specific theme templates or plugin files you ne
407
  <entry>
408
  <question><![CDATA[ How do I configure Rackspace Cloud Files as my <acronym title="Content Delivery Network">CDN</acronym>? ]]></question>
409
  <answer><![CDATA[
410
- <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 CDN.</p>
411
  <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>
412
  <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>
413
  ]]></answer>
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>
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>
languages/faq-pro-en_US.xml CHANGED
@@ -32,7 +32,7 @@
32
  <answer><![CDATA[
33
  <p>
34
  <ol>
35
- <li>Select CDN 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.
@@ -50,7 +50,7 @@
50
  <answer><![CDATA[
51
  <p>
52
  <ol>
53
- <li>Select CDN 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>
@@ -102,8 +102,8 @@
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 CDN. 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 CDN the wrong URLs will be used when linking to CSS, JS and other files.
107
  </p>
108
  <p>Configure CloudFront:</p>
109
  <ol>
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.
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>
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>
languages/w3-total-cache.pot CHANGED
@@ -537,7 +537,7 @@ msgid "Update via FTP"
537
  msgstr ""
538
 
539
  #: inc/functions/admin_ui.php:73 inc/functions/widgets.php:61
540
- #: inc/lightbox/edge.php:15 inc/options/support/form.php:26
541
  #: inc/options/support/payment.php:21
542
  msgid "Cancel"
543
  msgstr ""
@@ -655,23 +655,6 @@ msgstr ""
655
  msgid "Something that describes your zone. Length: 1-255 chars"
656
  msgstr ""
657
 
658
- #: inc/lightbox/edge.php:7
659
- msgid ""
660
- "You can now keep up-to-date on all of the web performance optimization (WPO) "
661
- "techniques that will make your website as fast as possible without having to "
662
- "worry about new features breaking your website when you update!"
663
- msgstr ""
664
-
665
- #: inc/lightbox/edge.php:8
666
- msgid ""
667
- "Enable \"edge mode\" to opt-in to pre-release features or simply close this "
668
- "window to opt-in to bug fixes, security fixes and settings updates only."
669
- msgstr ""
670
-
671
- #: inc/lightbox/edge.php:13
672
- msgid "Enable Edge Mode"
673
- msgstr ""
674
-
675
  #: inc/lightbox/minify_recommendations.php:5
676
  msgid ""
677
  "To get started with minify, we've identified the following external CSS and "
@@ -2904,14 +2887,6 @@ msgstr ""
2904
  msgid "Disable Edge mode"
2905
  msgstr ""
2906
 
2907
- #: inc/options/general.php:653
2908
- msgid ""
2909
- "Enable this to try out new functionality under development. Might cause "
2910
- "issues on some sites. If you have issues and can't access wp-admin, remove "
2911
- "\"define('W3TC_EDGE_MODE', true);\" from your wp-config.php file and edge "
2912
- "mode features will be disabled."
2913
- msgstr ""
2914
-
2915
  #: inc/options/general.php:666
2916
  msgid ""
2917
  "Detailed information about each cache will be appended in (publicly "
537
  msgstr ""
538
 
539
  #: inc/functions/admin_ui.php:73 inc/functions/widgets.php:61
540
+ #: inc/options/support/form.php:26
541
  #: inc/options/support/payment.php:21
542
  msgid "Cancel"
543
  msgstr ""
655
  msgid "Something that describes your zone. Length: 1-255 chars"
656
  msgstr ""
657
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
658
  #: inc/lightbox/minify_recommendations.php:5
659
  msgid ""
660
  "To get started with minify, we've identified the following external CSS and "
2887
  msgid "Disable Edge mode"
2888
  msgstr ""
2889
 
 
 
 
 
 
 
 
 
2890
  #: inc/options/general.php:666
2891
  msgid ""
2892
  "Detailed information about each cache will be appended in (publicly "
lib/Minify/CSSmin.php DELETED
@@ -1,758 +0,0 @@
1
- <?php
2
-
3
- /*!
4
- * cssmin.php rev ebaf67b 12/06/2013
5
- * Author: Tubal Martin - http://tubalmartin.me/
6
- * Repo: https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port
7
- *
8
- * This is a PHP port of the CSS minification tool distributed with YUICompressor,
9
- * itself a port of the cssmin utility by Isaac Schlueter - http://foohack.com/
10
- * Permission is hereby granted to use the PHP version under the same
11
- * conditions as the YUICompressor.
12
- */
13
-
14
- /*!
15
- * YUI Compressor
16
- * http://developer.yahoo.com/yui/compressor/
17
- * Author: Julien Lecomte - http://www.julienlecomte.net/
18
- * Copyright (c) 2013 Yahoo! Inc. All rights reserved.
19
- * The copyrights embodied in the content of this file are licensed
20
- * by Yahoo! Inc. under the BSD (revised) open source license.
21
- */
22
-
23
- class Minify0_CSSmin
24
- {
25
- const NL = '___YUICSSMIN_PRESERVED_NL___';
26
- const TOKEN = '___YUICSSMIN_PRESERVED_TOKEN_';
27
- const COMMENT = '___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_';
28
- const CLASSCOLON = '___YUICSSMIN_PSEUDOCLASSCOLON___';
29
- const QUERY_FRACTION = '___YUICSSMIN_QUERY_FRACTION___';
30
-
31
- private $comments;
32
- private $preserved_tokens;
33
- private $memory_limit;
34
- private $max_execution_time;
35
- private $pcre_backtrack_limit;
36
- private $pcre_recursion_limit;
37
- private $raise_php_limits;
38
-
39
- /**
40
- * @param bool|int $raise_php_limits
41
- * If true, PHP settings will be raised if needed
42
- */
43
- public function __construct($raise_php_limits = TRUE)
44
- {
45
- // Set suggested PHP limits
46
- $this->memory_limit = 128 * 1048576; // 128MB in bytes
47
- $this->max_execution_time = 60; // 1 min
48
- $this->pcre_backtrack_limit = 1000 * 1000;
49
- $this->pcre_recursion_limit = 500 * 1000;
50
-
51
- $this->raise_php_limits = (bool) $raise_php_limits;
52
- }
53
-
54
- /**
55
- * Minify a string of CSS
56
- * @param string $css
57
- * @param int|bool $linebreak_pos
58
- * @return string
59
- */
60
- public function run($css = '', $linebreak_pos = FALSE)
61
- {
62
- if (empty($css)) {
63
- return '';
64
- }
65
-
66
- if ($this->raise_php_limits) {
67
- $this->do_raise_php_limits();
68
- }
69
-
70
- $this->comments = array();
71
- $this->preserved_tokens = array();
72
-
73
- $start_index = 0;
74
- $length = strlen($css);
75
-
76
- $css = $this->extract_data_urls($css);
77
-
78
- // collect all comment blocks...
79
- while (($start_index = $this->index_of($css, '/*', $start_index)) >= 0) {
80
- $end_index = $this->index_of($css, '*/', $start_index + 2);
81
- if ($end_index < 0) {
82
- $end_index = $length;
83
- }
84
- $comment_found = $this->str_slice($css, $start_index + 2, $end_index);
85
- $this->comments[] = $comment_found;
86
- $comment_preserve_string = self::COMMENT . (count($this->comments) - 1) . '___';
87
- $css = $this->str_slice($css, 0, $start_index + 2) . $comment_preserve_string . $this->str_slice($css, $end_index);
88
- // Set correct start_index: Fixes issue #2528130
89
- $start_index = $end_index + 2 + strlen($comment_preserve_string) - strlen($comment_found);
90
- }
91
-
92
- // preserve strings so their content doesn't get accidentally minified
93
- $css = preg_replace_callback('/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S", array($this, 'replace_string'), $css);
94
-
95
- // Let's divide css code in chunks of 25.000 chars aprox.
96
- // Reason: PHP's PCRE functions like preg_replace have a "backtrack limit"
97
- // of 100.000 chars by default (php < 5.3.7) so if we're dealing with really
98
- // long strings and a (sub)pattern matches a number of chars greater than
99
- // the backtrack limit number (i.e. /(.*)/s) PCRE functions may fail silently
100
- // returning NULL and $css would be empty.
101
- $charset = '';
102
- $charset_regexp = '/(@charset)( [^;]+;)/i';
103
- $css_chunks = array();
104
- $css_chunk_length = 25000; // aprox size, not exact
105
- $start_index = 0;
106
- $i = $css_chunk_length; // save initial iterations
107
- $l = strlen($css);
108
-
109
-
110
- // if the number of characters is 25000 or less, do not chunk
111
- if ($l <= $css_chunk_length) {
112
- $css_chunks[] = $css;
113
- } else {
114
- // chunk css code securely
115
- while ($i < $l) {
116
- $i += 50; // save iterations. 500 checks for a closing curly brace }
117
- if ($l - $start_index <= $css_chunk_length || $i >= $l) {
118
- $css_chunks[] = $this->str_slice($css, $start_index);
119
- break;
120
- }
121
- if ($css[$i - 1] === '}' && $i - $start_index > $css_chunk_length) {
122
- // If there are two ending curly braces }} separated or not by spaces,
123
- // join them in the same chunk (i.e. @media blocks)
124
- $next_chunk = substr($css, $i);
125
- if (preg_match('/^\s*\}/', $next_chunk)) {
126
- $i = $i + $this->index_of($next_chunk, '}') + 1;
127
- }
128
-
129
- $css_chunks[] = $this->str_slice($css, $start_index, $i);
130
- $start_index = $i;
131
- }
132
- }
133
- }
134
-
135
- // Minify each chunk
136
- for ($i = 0, $n = count($css_chunks); $i < $n; $i++) {
137
- $css_chunks[$i] = $this->minify($css_chunks[$i], $linebreak_pos);
138
- // Keep the first @charset at-rule found
139
- if (empty($charset) && preg_match($charset_regexp, $css_chunks[$i], $matches)) {
140
- $charset = strtolower($matches[1]) . $matches[2];
141
- }
142
- // Delete all @charset at-rules
143
- $css_chunks[$i] = preg_replace($charset_regexp, '', $css_chunks[$i]);
144
- }
145
-
146
- // Update the first chunk and push the charset to the top of the file.
147
- $css_chunks[0] = $charset . $css_chunks[0];
148
-
149
- return implode('', $css_chunks);
150
- }
151
-
152
- /**
153
- * Sets the memory limit for this script
154
- * @param int|string $limit
155
- */
156
- public function set_memory_limit($limit)
157
- {
158
- $this->memory_limit = $this->normalize_int($limit);
159
- }
160
-
161
- /**
162
- * Sets the maximum execution time for this script
163
- * @param int|string $seconds
164
- */
165
- public function set_max_execution_time($seconds)
166
- {
167
- $this->max_execution_time = (int) $seconds;
168
- }
169
-
170
- /**
171
- * Sets the PCRE backtrack limit for this script
172
- * @param int $limit
173
- */
174
- public function set_pcre_backtrack_limit($limit)
175
- {
176
- $this->pcre_backtrack_limit = (int) $limit;
177
- }
178
-
179
- /**
180
- * Sets the PCRE recursion limit for this script
181
- * @param int $limit
182
- */
183
- public function set_pcre_recursion_limit($limit)
184
- {
185
- $this->pcre_recursion_limit = (int) $limit;
186
- }
187
-
188
- /**
189
- * Try to configure PHP to use at least the suggested minimum settings
190
- */
191
- private function do_raise_php_limits()
192
- {
193
- $php_limits = array(
194
- 'memory_limit' => $this->memory_limit,
195
- 'max_execution_time' => $this->max_execution_time,
196
- 'pcre.backtrack_limit' => $this->pcre_backtrack_limit,
197
- 'pcre.recursion_limit' => $this->pcre_recursion_limit
198
- );
199
-
200
- // If current settings are higher respect them.
201
- foreach ($php_limits as $name => $suggested) {
202
- $current = $this->normalize_int(ini_get($name));
203
- // memory_limit exception: allow -1 for "no memory limit".
204
- if ($current > -1 && ($suggested == -1 || $current < $suggested)) {
205
- ini_set($name, $suggested);
206
- }
207
- }
208
- }
209
-
210
- /**
211
- * Does bulk of the minification
212
- * @param string $css
213
- * @param int|bool $linebreak_pos
214
- * @return string
215
- */
216
- private function minify($css, $linebreak_pos)
217
- {
218
- // strings are safe, now wrestle the comments
219
- for ($i = 0, $max = count($this->comments); $i < $max; $i++) {
220
-
221
- $token = $this->comments[$i];
222
- $placeholder = '/' . self::COMMENT . $i . '___/';
223
-
224
- // ! in the first position of the comment means preserve
225
- // so push to the preserved tokens keeping the !
226
- if (substr($token, 0, 1) === '!') {
227
- $this->preserved_tokens[] = $token;
228
- $token_tring = self::TOKEN . (count($this->preserved_tokens) - 1) . '___';
229
- $css = preg_replace($placeholder, $token_tring, $css, 1);
230
- // Preserve new lines for /*! important comments
231
- $css = preg_replace('/\s*[\n\r\f]+\s*(\/\*'. $token_tring .')/S', self::NL.'$1', $css);
232
- $css = preg_replace('/('. $token_tring .'\*\/)\s*[\n\r\f]+\s*/', '$1'.self::NL, $css);
233
- continue;
234
- }
235
-
236
- // \ in the last position looks like hack for Mac/IE5
237
- // shorten that to /*\*/ and the next one to /**/
238
- if (substr($token, (strlen($token) - 1), 1) === '\\') {
239
- $this->preserved_tokens[] = '\\';
240
- $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
241
- $i = $i + 1; // attn: advancing the loop
242
- $this->preserved_tokens[] = '';
243
- $css = preg_replace('/' . self::COMMENT . $i . '___/', self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
244
- continue;
245
- }
246
-
247
- // keep empty comments after child selectors (IE7 hack)
248
- // e.g. html >/**/ body
249
- if (strlen($token) === 0) {
250
- $start_index = $this->index_of($css, $this->str_slice($placeholder, 1, -1));
251
- if ($start_index > 2) {
252
- if (substr($css, $start_index - 3, 1) === '>') {
253
- $this->preserved_tokens[] = '';
254
- $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1);
255
- }
256
- }
257
- }
258
-
259
- // in all other cases kill the comment
260
- $css = preg_replace('/\/\*' . $this->str_slice($placeholder, 1, -1) . '\*\//', '', $css, 1);
261
- }
262
-
263
-
264
- // Normalize all whitespace strings to single spaces. Easier to work with that way.
265
- $css = preg_replace('/\s+/', ' ', $css);
266
-
267
- // Shorten & preserve calculations calc(...) since spaces are important
268
- $css = preg_replace_callback('/calc(\(((?:[^\(\)]+|(?1))*)\))/i', array($this, 'replace_calc'), $css);
269
-
270
- // Replace positive sign from numbers preceded by : or a white-space before the leading space is removed
271
- // +1.2em to 1.2em, +.8px to .8px, +2% to 2%
272
- $css = preg_replace('/((?<!\\\\)\:|\s)\+(\.?\d+)/S', '$1$2', $css);
273
-
274
- // Remove leading zeros from integer and float numbers preceded by : or a white-space
275
- // 000.6 to .6, -0.8 to -.8, 0050 to 50, -01.05 to -1.05
276
- $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)0+(\.?\d+)/S', '$1$2$3', $css);
277
-
278
- // Remove trailing zeros from float numbers preceded by : or a white-space
279
- // -6.0100em to -6.01em, .0100 to .01, 1.200px to 1.2px
280
- $css = preg_replace('/((?<!\\\\)\:|\s)(\-?)(\d?\.\d+?)0+([^\d])/S', '$1$2$3$4', $css);
281
-
282
- // Remove trailing .0 -> -9.0 to -9
283
- $css = preg_replace('/((?<!\\\\)\:|\s)(\-?\d+)\.0([^\d])/S', '$1$2$3', $css);
284
-
285
- // Replace 0 length numbers with 0
286
- $css = preg_replace('/((?<!\\\\)\:|\s)\-?\.?0+([^\d])/S', '${1}0$2', $css);
287
-
288
- // Remove the spaces before the things that should not have spaces before them.
289
- // But, be careful not to turn "p :link {...}" into "p:link{...}"
290
- // Swap out any pseudo-class colons with the token, and then swap back.
291
- $css = preg_replace_callback('/(?:^|\})(?:(?:[^\{\:])+\:)+(?:[^\{]*\{)/', array($this, 'replace_colon'), $css);
292
-
293
- // Remove spaces before the things that should not have spaces before them.
294
- $css = preg_replace('/\s+([\!\{\}\;\:\>\+\(\)\]\~\=,])/', '$1', $css);
295
-
296
- // Restore spaces for !important
297
- $css = preg_replace('/\!important/i', ' !important', $css);
298
-
299
- // bring back the colon
300
- $css = preg_replace('/' . self::CLASSCOLON . '/', ':', $css);
301
-
302
- // retain space for special IE6 cases
303
- $css = preg_replace_callback('/\:first\-(line|letter)(\{|,)/i', array($this, 'lowercase_pseudo_first'), $css);
304
-
305
- // no space after the end of a preserved comment
306
- $css = preg_replace('/\*\/ /', '*/', $css);
307
-
308
- // lowercase some popular @directives
309
- $css = preg_replace_callback('/@(font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframe|media|page|namespace)/i', array($this, 'lowercase_directives'), $css);
310
-
311
- // lowercase some more common pseudo-elements
312
- $css = preg_replace_callback('/:(active|after|before|checked|disabled|empty|enabled|first-(?:child|of-type)|focus|hover|last-(?:child|of-type)|link|only-(?:child|of-type)|root|:selection|target|visited)/i', array($this, 'lowercase_pseudo_elements'), $css);
313
-
314
- // lowercase some more common functions
315
- $css = preg_replace_callback('/:(lang|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|(?:-(?:moz|webkit)-)?any)\(/i', array($this, 'lowercase_common_functions'), $css);
316
-
317
- // lower case some common function that can be values
318
- // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us
319
- $css = preg_replace_callback('/([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/iS', array($this, 'lowercase_common_functions_values'), $css);
320
-
321
- // Put the space back in some cases, to support stuff like
322
- // @media screen and (-webkit-min-device-pixel-ratio:0){
323
- $css = preg_replace('/\band\(/i', 'and (', $css);
324
-
325
- // Remove the spaces after the things that should not have spaces after them.
326
- $css = preg_replace('/([\!\{\}\:;\>\+\(\[\~\=,])\s+/S', '$1', $css);
327
-
328
- // remove unnecessary semicolons
329
- $css = preg_replace('/;+\}/', '}', $css);
330
-
331
- // Fix for issue: #2528146
332
- // Restore semicolon if the last property is prefixed with a `*` (lte IE7 hack)
333
- // to avoid issues on Symbian S60 3.x browsers.
334
- $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css);
335
-
336
- // Replace 0 length units 0(px,em,%) with 0.
337
- $css = preg_replace('/(^|[^0-9])(?:0?\.)?0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%|deg|g?rad|m?s|k?hz)/iS', '${1}0', $css);
338
-
339
- // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0.
340
- $css = preg_replace('/\:0(?: 0){1,3}(;|\}| \!)/', ':0$1', $css);
341
-
342
- // Fix for issue: #2528142
343
- // Replace text-shadow:0; with text-shadow:0 0 0;
344
- $css = preg_replace('/(text-shadow\:0)(;|\}| \!)/i', '$1 0 0$2', $css);
345
-
346
- // Replace background-position:0; with background-position:0 0;
347
- // same for transform-origin
348
- // Changing -webkit-mask-position: 0 0 to just a single 0 will result in the second parameter defaulting to 50% (center)
349
- $css = preg_replace('/(background\-position|webkit-mask-position|(?:webkit|moz|o|ms|)\-?transform\-origin)\:0(;|\}| \!)/iS', '$1:0 0$2', $css);
350
-
351
- // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space)
352
- // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space)
353
- // This makes it more likely that it'll get further compressed in the next step.
354
- $css = preg_replace_callback('/rgb\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'rgb_to_hex'), $css);
355
- $css = preg_replace_callback('/hsl\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'hsl_to_hex'), $css);
356
-
357
- // Shorten colors from #AABBCC to #ABC or short color name.
358
- $css = $this->compress_hex_colors($css);
359
-
360
- // border: none to border:0, outline: none to outline:0
361
- $css = preg_replace('/(border\-?(?:top|right|bottom|left|)|outline)\:none(;|\}| \!)/iS', '$1:0$2', $css);
362
-
363
- // shorter opacity IE filter
364
- $css = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $css);
365
-
366
- // Find a fraction that is used for Opera's -o-device-pixel-ratio query
367
- // Add token to add the "\" back in later
368
- $css = preg_replace('/\(([a-z\-]+):([0-9]+)\/([0-9]+)\)/i', '($1:$2'. self::QUERY_FRACTION .'$3)', $css);
369
-
370
- // Remove empty rules.
371
- $css = preg_replace('/[^\};\{\/]+\{\}/S', '', $css);
372
-
373
- // Add "/" back to fix Opera -o-device-pixel-ratio query
374
- $css = preg_replace('/'. self::QUERY_FRACTION .'/', '/', $css);
375
-
376
- // Some source control tools don't like it when files containing lines longer
377
- // than, say 8000 characters, are checked in. The linebreak option is used in
378
- // that case to split long lines after a specific column.
379
- if ($linebreak_pos !== FALSE && (int) $linebreak_pos >= 0) {
380
- $linebreak_pos = (int) $linebreak_pos;
381
- $start_index = $i = 0;
382
- while ($i < strlen($css)) {
383
- $i++;
384
- if ($css[$i - 1] === '}' && $i - $start_index > $linebreak_pos) {
385
- $css = $this->str_slice($css, 0, $i) . "\n" . $this->str_slice($css, $i);
386
- $start_index = $i;
387
- }
388
- }
389
- }
390
-
391
- // Replace multiple semi-colons in a row by a single one
392
- // See SF bug #1980989
393
- $css = preg_replace('/;;+/', ';', $css);
394
-
395
- // Restore new lines for /*! important comments
396
- $css = preg_replace('/'. self::NL .'/', "\n", $css);
397
-
398
- // Lowercase all uppercase properties
399
- $css = preg_replace_callback('/(\{|\;)([A-Z\-]+)(\:)/', array($this, 'lowercase_properties'), $css);
400
-
401
- // restore preserved comments and strings
402
- for ($i = 0, $max = count($this->preserved_tokens); $i < $max; $i++) {
403
- $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1);
404
- }
405
-
406
- // Trim the final string (for any leading or trailing white spaces)
407
- return trim($css);
408
- }
409
-
410
- /**
411
- * Utility method to replace all data urls with tokens before we start
412
- * compressing, to avoid performance issues running some of the subsequent
413
- * regexes against large strings chunks.
414
- *
415
- * @param string $css
416
- * @return string
417
- */
418
- private function extract_data_urls($css)
419
- {
420
- // Leave data urls alone to increase parse performance.
421
- $max_index = strlen($css) - 1;
422
- $append_index = $index = $last_index = $offset = 0;
423
- $sb = array();
424
- $pattern = '/url\(\s*(["\']?)data\:/i';
425
-
426
- // Since we need to account for non-base64 data urls, we need to handle
427
- // ' and ) being part of the data string. Hence switching to indexOf,
428
- // to determine whether or not we have matching string terminators and
429
- // handling sb appends directly, instead of using matcher.append* methods.
430
-
431
- while (preg_match($pattern, $css, $m, 0, $offset)) {
432
- $index = $this->index_of($css, $m[0], $offset);
433
- $last_index = $index + strlen($m[0]);
434
- $start_index = $index + 4; // "url(".length()
435
- $end_index = $last_index - 1;
436
- $terminator = $m[1]; // ', " or empty (not quoted)
437
- $found_terminator = FALSE;
438
-
439
- if (strlen($terminator) === 0) {
440
- $terminator = ')';
441
- }
442
-
443
- while ($found_terminator === FALSE && $end_index+1 <= $max_index) {
444
- $end_index = $this->index_of($css, $terminator, $end_index + 1);
445
-
446
- // endIndex == 0 doesn't really apply here
447
- if ($end_index > 0 && substr($css, $end_index - 1, 1) !== '\\') {
448
- $found_terminator = TRUE;
449
- if (')' != $terminator) {
450
- $end_index = $this->index_of($css, ')', $end_index);
451
- }
452
- }
453
- }
454
-
455
- // Enough searching, start moving stuff over to the buffer
456
- $sb[] = $this->str_slice($css, $append_index, $index);
457
-
458
- if ($found_terminator) {
459
- $token = $this->str_slice($css, $start_index, $end_index);
460
- $token = preg_replace('/\s+/', '', $token);
461
- $this->preserved_tokens[] = $token;
462
-
463
- $preserver = 'url(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___)';
464
- $sb[] = $preserver;
465
-
466
- $append_index = $end_index + 1;
467
- } else {
468
- // No end terminator found, re-add the whole match. Should we throw/warn here?
469
- $sb[] = $this->str_slice($css, $index, $last_index);
470
- $append_index = $last_index;
471
- }
472
-
473
- $offset = $last_index;
474
- }
475
-
476
- $sb[] = $this->str_slice($css, $append_index);
477
-
478
- return implode('', $sb);
479
- }
480
-
481
- /**
482
- * Utility method to compress hex color values of the form #AABBCC to #ABC or short color name.
483
- *
484
- * DOES NOT compress CSS ID selectors which match the above pattern (which would break things).
485
- * e.g. #AddressForm { ... }
486
- *
487
- * DOES NOT compress IE filters, which have hex color values (which would break things).
488
- * e.g. filter: chroma(color="#FFFFFF");
489
- *
490
- * DOES NOT compress invalid hex values.
491
- * e.g. background-color: #aabbccdd
492
- *
493
- * @param string $css
494
- * @return string
495
- */
496
- private function compress_hex_colors($css)
497
- {
498
- // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters)
499
- $pattern = '/(\=\s*?["\']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/iS';
500
- $_index = $index = $last_index = $offset = 0;
501
- $sb = array();
502
- // See: http://ajaxmin.codeplex.com/wikipage?title=CSS%20Colors
503
- $short_safe = array(
504
- '#808080' => 'gray',
505
- '#008000' => 'green',
506
- '#800000' => 'maroon',
507
- '#000080' => 'navy',
508
- '#808000' => 'olive',
509
- '#ffa500' => 'orange',
510
- '#800080' => 'purple',
511
- '#c0c0c0' => 'silver',
512
- '#008080' => 'teal',
513
- '#f00' => 'red'
514
- );
515
-
516
- while (preg_match($pattern, $css, $m, 0, $offset)) {
517
- $index = $this->index_of($css, $m[0], $offset);
518
- $last_index = $index + strlen($m[0]);
519
- $is_filter = $m[1] !== null && $m[1] !== '';
520
-
521
- $sb[] = $this->str_slice($css, $_index, $index);
522
-
523
- if ($is_filter) {
524
- // Restore, maintain case, otherwise filter will break
525
- $sb[] = $m[1] . '#' . $m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7];
526
- } else {
527
- if (strtolower($m[2]) == strtolower($m[3]) &&
528
- strtolower($m[4]) == strtolower($m[5]) &&
529
- strtolower($m[6]) == strtolower($m[7])) {
530
- // Compress.
531
- $hex = '#' . strtolower($m[3] . $m[5] . $m[7]);
532
- } else {
533
- // Non compressible color, restore but lower case.
534
- $hex = '#' . strtolower($m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7]);
535
- }
536
- // replace Hex colors to short safe color names
537
- $sb[] = array_key_exists($hex, $short_safe) ? $short_safe[$hex] : $hex;
538
- }
539
-
540
- $_index = $offset = $last_index - strlen($m[8]);
541
- }
542
-
543
- $sb[] = $this->str_slice($css, $_index);
544
-
545
- return implode('', $sb);
546
- }
547
-
548
- /* CALLBACKS
549
- * ---------------------------------------------------------------------------------------------
550
- */
551
-
552
- private function replace_string($matches)
553
- {
554
- $match = $matches[0];
555
- $quote = substr($match, 0, 1);
556
- // Must use addcslashes in PHP to avoid parsing of backslashes
557
- $match = addcslashes($this->str_slice($match, 1, -1), '\\');
558
-
559
- // maybe the string contains a comment-like substring?
560
- // one, maybe more? put'em back then
561
- if (($pos = $this->index_of($match, self::COMMENT)) >= 0) {
562
- for ($i = 0, $max = count($this->comments); $i < $max; $i++) {
563
- $match = preg_replace('/' . self::COMMENT . $i . '___/', $this->comments[$i], $match, 1);
564
- }
565
- }
566
-
567
- // minify alpha opacity in filter strings
568
- $match = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $match);
569
-
570
- $this->preserved_tokens[] = $match;
571
- return $quote . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . $quote;
572
- }
573
-
574
- private function replace_colon($matches)
575
- {
576
- return preg_replace('/\:/', self::CLASSCOLON, $matches[0]);
577
- }
578
-
579
- private function replace_calc($matches)
580
- {
581
- $this->preserved_tokens[] = trim(preg_replace('/\s*([\*\/\(\),])\s*/', '$1', $matches[2]));
582
- return 'calc('. self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')';
583
- }
584
-
585
- private function rgb_to_hex($matches)
586
- {
587
- // Support for percentage values rgb(100%, 0%, 45%);
588
- if ($this->index_of($matches[1], '%') >= 0){
589
- $rgbcolors = explode(',', str_replace('%', '', $matches[1]));
590
- for ($i = 0; $i < count($rgbcolors); $i++) {
591
- $rgbcolors[$i] = $this->round_number(floatval($rgbcolors[$i]) * 2.55);
592
- }
593
- } else {
594
- $rgbcolors = explode(',', $matches[1]);
595
- }
596
-
597
- // Values outside the sRGB color space should be clipped (0-255)
598
- for ($i = 0; $i < count($rgbcolors); $i++) {
599
- $rgbcolors[$i] = $this->clamp_number(intval($rgbcolors[$i], 10), 0, 255);
600
- $rgbcolors[$i] = sprintf("%02x", $rgbcolors[$i]);
601
- }
602
-
603
- // Fix for issue #2528093
604
- if (!preg_match('/[\s\,\);\}]/', $matches[2])){
605
- $matches[2] = ' ' . $matches[2];
606
- }
607
-
608
- return '#' . implode('', $rgbcolors) . $matches[2];
609
- }
610
-
611
- private function hsl_to_hex($matches)
612
- {
613
- $values = explode(',', str_replace('%', '', $matches[1]));
614
- $h = floatval($values[0]);
615
- $s = floatval($values[1]);
616
- $l = floatval($values[2]);
617
-
618
- // Wrap and clamp, then fraction!
619
- $h = ((($h % 360) + 360) % 360) / 360;
620
- $s = $this->clamp_number($s, 0, 100) / 100;
621
- $l = $this->clamp_number($l, 0, 100) / 100;
622
-
623
- if ($s == 0) {
624
- $r = $g = $b = $this->round_number(255 * $l);
625
- } else {
626
- $v2 = $l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($s * $l);
627
- $v1 = (2 * $l) - $v2;
628
- $r = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h + (1/3)));
629
- $g = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h));
630
- $b = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h - (1/3)));
631
- }
632
-
633
- return $this->rgb_to_hex(array('', $r.','.$g.','.$b, $matches[2]));
634
- }
635
-
636
- private function lowercase_pseudo_first($matches)
637
- {
638
- return ':first-'. strtolower($matches[1]) .' '. $matches[2];
639
- }
640
-
641
- private function lowercase_directives($matches)
642
- {
643
- return '@'. strtolower($matches[1]);
644
- }
645
-
646
- private function lowercase_pseudo_elements($matches)
647
- {
648
- return ':'. strtolower($matches[1]);
649
- }
650
-
651
- private function lowercase_common_functions($matches)
652
- {
653
- return ':'. strtolower($matches[1]) .'(';
654
- }
655
-
656
- private function lowercase_common_functions_values($matches)
657
- {
658
- return $matches[1] . strtolower($matches[2]);
659
- }
660
-
661
- private function lowercase_properties($matches)
662
- {
663
- return $matches[1].strtolower($matches[2]).$matches[3];
664
- }
665
-
666
- /* HELPERS
667
- * ---------------------------------------------------------------------------------------------
668
- */
669
-
670
- private function hue_to_rgb($v1, $v2, $vh)
671
- {
672
- $vh = $vh < 0 ? $vh + 1 : ($vh > 1 ? $vh - 1 : $vh);
673
- if ($vh * 6 < 1) return $v1 + ($v2 - $v1) * 6 * $vh;
674
- if ($vh * 2 < 1) return $v2;
675
- if ($vh * 3 < 2) return $v1 + ($v2 - $v1) * ((2/3) - $vh) * 6;
676
- return $v1;
677
- }
678
-
679
- private function round_number($n)
680
- {
681
- return intval(floor(floatval($n) + 0.5), 10);
682
- }
683
-
684
- private function clamp_number($n, $min, $max)
685
- {
686
- return min(max($n, $min), $max);
687
- }
688
-
689
- /**
690
- * PHP port of Javascript's "indexOf" function for strings only
691
- * Author: Tubal Martin http://blog.margenn.com
692
- *
693
- * @param string $haystack
694
- * @param string $needle
695
- * @param int $offset index (optional)
696
- * @return int
697
- */
698
- private function index_of($haystack, $needle, $offset = 0)
699
- {
700
- $index = strpos($haystack, $needle, $offset);
701
-
702
- return ($index !== FALSE) ? $index : -1;
703
- }
704
-
705
- /**
706
- * PHP port of Javascript's "slice" function for strings only
707
- * Author: Tubal Martin http://blog.margenn.com
708
- * Tests: http://margenn.com/tubal/str_slice/
709
- *
710
- * @param string $str
711
- * @param int $start index
712
- * @param int|bool $end index (optional)
713
- * @return string
714
- */
715
- private function str_slice($str, $start = 0, $end = FALSE)
716
- {
717
- if ($end !== FALSE && ($start < 0 || $end <= 0)) {
718
- $max = strlen($str);
719
-
720
- if ($start < 0) {
721
- if (($start = $max + $start) < 0) {
722
- return '';
723
- }
724
- }
725
-
726
- if ($end < 0) {
727
- if (($end = $max + $end) < 0) {
728
- return '';
729
- }
730
- }
731
-
732
- if ($end <= $start) {
733
- return '';
734
- }
735
- }
736
-
737
- $slice = ($end === FALSE) ? substr($str, $start) : substr($str, $start, $end - $start);
738
- return ($slice === FALSE) ? '' : $slice;
739
- }
740
-
741
- /**
742
- * Convert strings like "64M" or "30" to int values
743
- * @param mixed $size
744
- * @return int
745
- */
746
- private function normalize_int($size)
747
- {
748
- if (is_string($size)) {
749
- switch (substr($size, -1)) {
750
- case 'M': case 'm': return $size * 1048576;
751
- case 'K': case 'k': return $size * 1024;
752
- case 'G': case 'g': return $size * 1073741824;
753
- }
754
- }
755
-
756
- return (int) $size;
757
- }
758
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/Minify/Minify/CSS/UriRewriter.php CHANGED
@@ -434,11 +434,10 @@ class Minify_CSS_UriRewriter {
434
 
435
  if (preg_match('~\.([a-z-_]+)(\?.*)?$~', $uri, $matches)) {
436
  $extension = $matches[1];
437
- $query = (isset($matches[2]) ? $matches[2] : '');
438
 
439
  if ($extension && in_array($extension, self::$_browserCacheExtensions)) {
440
  $uri = \W3TC\Util_Environment::remove_query($uri);
441
- $uri .= ($query ? '&' : '?') . self::$_browserCacheId;
442
  }
443
  }
444
  }
434
 
435
  if (preg_match('~\.([a-z-_]+)(\?.*)?$~', $uri, $matches)) {
436
  $extension = $matches[1];
 
437
 
438
  if ($extension && in_array($extension, self::$_browserCacheExtensions)) {
439
  $uri = \W3TC\Util_Environment::remove_query($uri);
440
+ $uri .= ( strpos( $uri, '?' ) !== false ? '&' : '?' ) . self::$_browserCacheId;
441
  }
442
  }
443
  }
lib/Minify/Minify/Cache/File.php CHANGED
@@ -48,7 +48,7 @@ class Minify_Cache_File {
48
  // retry with make dir
49
  \W3TC\Util_File::mkdir_from_safe(dirname($path), W3TC_CACHE_DIR);
50
 
51
- if (!@file_put_contents($path, $data, $flag))
52
  return false;
53
  }
54
 
@@ -152,7 +152,8 @@ class Minify_Cache_File {
152
  @flock($fp, LOCK_UN);
153
  @fclose($fp);
154
 
155
- return $ret;
 
156
  }
157
  } else {
158
  $data['content'] = @file_get_contents($path);
48
  // retry with make dir
49
  \W3TC\Util_File::mkdir_from_safe(dirname($path), W3TC_CACHE_DIR);
50
 
51
+ if (!@file_put_contents($path, $data['content'], $flag))
52
  return false;
53
  }
54
 
152
  @flock($fp, LOCK_UN);
153
  @fclose($fp);
154
 
155
+ $data['content'] = $ret;
156
+ return $data;
157
  }
158
  } else {
159
  $data['content'] = @file_get_contents($path);
lib/Minify/Minify/ClosureCompiler.php CHANGED
@@ -90,7 +90,14 @@ class Minify_ClosureCompiler {
90
  ),
91
  $userOptions
92
  );
93
- $cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile)
 
 
 
 
 
 
 
94
  . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset'])
95
  ? " --charset {$o['charset']}"
96
  : '');
90
  ),
91
  $userOptions
92
  );
93
+
94
+ $javaExecutable = self::$javaExecutable;
95
+
96
+ if ( false !== strpos(trim($javaExecutable), ' ') ) {
97
+ $javaExecutable = '"'.$javaExecutable.'"';
98
+ }
99
+
100
+ $cmd = $javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile)
101
  . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset'])
102
  ? " --charset {$o['charset']}"
103
  : '');
lib/Minify/Minify/HTML.php CHANGED
@@ -184,7 +184,7 @@ class Minify_HTML {
184
  protected function _ignoredComment($comment)
185
  {
186
  foreach ($this->_ignoredComments as $ignoredComment) {
187
- if (stristr($comment, $ignoredComment) !== false) {
188
  return true;
189
  }
190
  }
184
  protected function _ignoredComment($comment)
185
  {
186
  foreach ($this->_ignoredComments as $ignoredComment) {
187
+ if (!empty($ignoredComment) && stristr($comment, $ignoredComment) !== false) {
188
  return true;
189
  }
190
  }
lib/Minify/Minify/YUICompressor.php CHANGED
@@ -1,17 +1,17 @@
1
  <?php
2
  /**
3
- * Class Minify_YUICompressor
4
  * @package Minify
5
  */
6
 
7
  /**
8
  * Compress Javascript/CSS using the YUI Compressor
9
- *
10
  * You must set $jarFile and $tempDir before calling the minify functions.
11
  * Also, depending on your shell's environment, you may need to specify
12
  * the full path to java in $javaExecutable or use putenv() to setup the
13
  * Java environment.
14
- *
15
  * <code>
16
  * Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.4.6.jar';
17
  * Minify_YUICompressor::$tempDir = '/tmp';
@@ -25,7 +25,7 @@
25
  * array('stack-size' => '2048k')
26
  *
27
  * @todo unit tests, $options docs
28
- *
29
  * @package Minify
30
  * @author Stephen Clay <steve@mrclay.org>
31
  */
@@ -38,7 +38,7 @@ class Minify_YUICompressor {
38
  * @var string
39
  */
40
  public static $jarFile = null;
41
-
42
  /**
43
  * Writable temp directory. This must be set before calling minifyJs()
44
  * or minifyCss().
@@ -46,40 +46,40 @@ class Minify_YUICompressor {
46
  * @var string
47
  */
48
  public static $tempDir = null;
49
-
50
  /**
51
  * Filepath of "java" executable (may be needed if not in shell's PATH)
52
  *
53
  * @var string
54
  */
55
  public static $javaExecutable = 'java';
56
-
57
  /**
58
  * Minify a Javascript string
59
- *
60
  * @param string $js
61
- *
62
  * @param array $options (verbose is ignored)
63
- *
64
  * @see http://www.julienlecomte.net/yuicompressor/README
65
- *
66
- * @return string
67
  */
68
  public static function minifyJs($js, $options = array())
69
  {
70
  return self::_minify('js', $js, $options);
71
  }
72
-
73
  /**
74
  * Minify a CSS string
75
- *
76
  * @param string $css
77
- *
78
  * @param array $options (verbose is ignored)
79
- *
80
  * @see http://www.julienlecomte.net/yuicompressor/README
81
- *
82
- * @return string
83
  */
84
  public static function minifyCss($css, $options = array())
85
  {
@@ -88,7 +88,7 @@ class Minify_YUICompressor {
88
 
89
  return $css;
90
  }
91
-
92
  private static function _minify($type, $content, $options)
93
  {
94
  self::_prepare();
@@ -103,7 +103,7 @@ class Minify_YUICompressor {
103
  }
104
  return implode("\n", $output);
105
  }
106
-
107
  private static function _getCmd($userOptions, $type, $tmpFile)
108
  {
109
  if (!is_file(self::$javaExecutable)) {
@@ -125,28 +125,34 @@ class Minify_YUICompressor {
125
  )
126
  ,$userOptions
127
  );
128
- $cmd = self::$javaExecutable
 
 
 
 
 
 
129
  . (!empty($o['stack-size'])
130
  ? ' -Xss' . $o['stack-size']
131
  : '')
132
  . ' -jar ' . escapeshellarg(self::$jarFile)
133
  . " --type {$type}"
134
  . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset'])
135
- ? " --charset {$o['charset']}"
136
  : '')
137
  . (is_numeric($o['line-break']) && $o['line-break'] >= 0
138
  ? ' --line-break ' . (int)$o['line-break']
139
  : '');
140
  if ($type === 'js') {
141
  foreach (array('nomunge', 'preserve-semi', 'disable-optimizations') as $opt) {
142
- $cmd .= $o[$opt]
143
  ? " --{$opt}"
144
  : '';
145
  }
146
  }
147
  return $cmd . ' ' . escapeshellarg($tmpFile);
148
  }
149
-
150
  private static function _prepare()
151
  {
152
  if (! is_file(self::$jarFile)) {
1
  <?php
2
  /**
3
+ * Class Minify_YUICompressor
4
  * @package Minify
5
  */
6
 
7
  /**
8
  * Compress Javascript/CSS using the YUI Compressor
9
+ *
10
  * You must set $jarFile and $tempDir before calling the minify functions.
11
  * Also, depending on your shell's environment, you may need to specify
12
  * the full path to java in $javaExecutable or use putenv() to setup the
13
  * Java environment.
14
+ *
15
  * <code>
16
  * Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.4.6.jar';
17
  * Minify_YUICompressor::$tempDir = '/tmp';
25
  * array('stack-size' => '2048k')
26
  *
27
  * @todo unit tests, $options docs
28
+ *
29
  * @package Minify
30
  * @author Stephen Clay <steve@mrclay.org>
31
  */
38
  * @var string
39
  */
40
  public static $jarFile = null;
41
+
42
  /**
43
  * Writable temp directory. This must be set before calling minifyJs()
44
  * or minifyCss().
46
  * @var string
47
  */
48
  public static $tempDir = null;
49
+
50
  /**
51
  * Filepath of "java" executable (may be needed if not in shell's PATH)
52
  *
53
  * @var string
54
  */
55
  public static $javaExecutable = 'java';
56
+
57
  /**
58
  * Minify a Javascript string
59
+ *
60
  * @param string $js
61
+ *
62
  * @param array $options (verbose is ignored)
63
+ *
64
  * @see http://www.julienlecomte.net/yuicompressor/README
65
+ *
66
+ * @return string
67
  */
68
  public static function minifyJs($js, $options = array())
69
  {
70
  return self::_minify('js', $js, $options);
71
  }
72
+
73
  /**
74
  * Minify a CSS string
75
+ *
76
  * @param string $css
77
+ *
78
  * @param array $options (verbose is ignored)
79
+ *
80
  * @see http://www.julienlecomte.net/yuicompressor/README
81
+ *
82
+ * @return string
83
  */
84
  public static function minifyCss($css, $options = array())
85
  {
88
 
89
  return $css;
90
  }
91
+
92
  private static function _minify($type, $content, $options)
93
  {
94
  self::_prepare();
103
  }
104
  return implode("\n", $output);
105
  }
106
+
107
  private static function _getCmd($userOptions, $type, $tmpFile)
108
  {
109
  if (!is_file(self::$javaExecutable)) {
125
  )
126
  ,$userOptions
127
  );
128
+
129
+ $javaExecutable = self::$javaExecutable;
130
+ if ( false !== strpos(trim($javaExecutable), ' ') ) {
131
+ $javaExecutable = '"'. $javaExecutable . '"';
132
+ }
133
+
134
+ $cmd = $javaExecutable
135
  . (!empty($o['stack-size'])
136
  ? ' -Xss' . $o['stack-size']
137
  : '')
138
  . ' -jar ' . escapeshellarg(self::$jarFile)
139
  . " --type {$type}"
140
  . (preg_match('/^[\\da-zA-Z0-9\\-]+$/', $o['charset'])
141
+ ? " --charset {$o['charset']}"
142
  : '')
143
  . (is_numeric($o['line-break']) && $o['line-break'] >= 0
144
  ? ' --line-break ' . (int)$o['line-break']
145
  : '');
146
  if ($type === 'js') {
147
  foreach (array('nomunge', 'preserve-semi', 'disable-optimizations') as $opt) {
148
+ $cmd .= $o[$opt]
149
  ? " --{$opt}"
150
  : '';
151
  }
152
  }
153
  return $cmd . ' ' . escapeshellarg($tmpFile);
154
  }
155
+
156
  private static function _prepare()
157
  {
158
  if (! is_file(self::$jarFile)) {
lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Colors.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace w3tc_tubalmartin\CssMin;
4
+
5
+ class Colors
6
+ {
7
+ public static function getHexToNamedMap()
8
+ {
9
+ // Hex colors longer than named counterpart
10
+ return array(
11
+ '#f0ffff' => 'azure',
12
+ '#f5f5dc' => 'beige',
13
+ '#ffe4c4' => 'bisque',
14
+ '#a52a2a' => 'brown',
15
+ '#ff7f50' => 'coral',
16
+ '#ffd700' => 'gold',
17
+ '#808080' => 'gray',
18
+ '#008000' => 'green',
19
+ '#4b0082' => 'indigo',
20
+ '#fffff0' => 'ivory',
21
+ '#f0e68c' => 'khaki',
22
+ '#faf0e6' => 'linen',
23
+ '#800000' => 'maroon',
24
+ '#000080' => 'navy',
25
+ '#fdf5e6' => 'oldlace',
26
+ '#808000' => 'olive',
27
+ '#ffa500' => 'orange',
28
+ '#da70d6' => 'orchid',
29
+ '#cd853f' => 'peru',
30
+ '#ffc0cb' => 'pink',
31
+ '#dda0dd' => 'plum',
32
+ '#800080' => 'purple',
33
+ '#f00' => 'red',
34
+ '#fa8072' => 'salmon',
35
+ '#a0522d' => 'sienna',
36
+ '#c0c0c0' => 'silver',
37
+ '#fffafa' => 'snow',
38
+ '#d2b48c' => 'tan',
39
+ '#008080' => 'teal',
40
+ '#ff6347' => 'tomato',
41
+ '#ee82ee' => 'violet',
42
+ '#f5deb3' => 'wheat'
43
+ );
44
+ }
45
+
46
+ public static function getNamedToHexMap()
47
+ {
48
+ // Named colors longer than hex counterpart
49
+ return array(
50
+ 'aliceblue' => '#f0f8ff',
51
+ 'antiquewhite' => '#faebd7',
52
+ 'aquamarine' => '#7fffd4',
53
+ 'black' => '#000',
54
+ 'blanchedalmond' => '#ffebcd',
55
+ 'blueviolet' => '#8a2be2',
56
+ 'burlywood' => '#deb887',
57
+ 'cadetblue' => '#5f9ea0',
58
+ 'chartreuse' => '#7fff00',
59
+ 'chocolate' => '#d2691e',
60
+ 'cornflowerblue' => '#6495ed',
61
+ 'cornsilk' => '#fff8dc',
62
+ 'darkblue' => '#00008b',
63
+ 'darkcyan' => '#008b8b',
64
+ 'darkgoldenrod' => '#b8860b',
65
+ 'darkgray' => '#a9a9a9',
66
+ 'darkgreen' => '#006400',
67
+ 'darkgrey' => '#a9a9a9',
68
+ 'darkkhaki' => '#bdb76b',
69
+ 'darkmagenta' => '#8b008b',
70
+ 'darkolivegreen' => '#556b2f',
71
+ 'darkorange' => '#ff8c00',
72
+ 'darkorchid' => '#9932cc',
73
+ 'darksalmon' => '#e9967a',
74
+ 'darkseagreen' => '#8fbc8f',
75
+ 'darkslateblue' => '#483d8b',
76
+ 'darkslategray' => '#2f4f4f',
77
+ 'darkslategrey' => '#2f4f4f',
78
+ 'darkturquoise' => '#00ced1',
79
+ 'darkviolet' => '#9400d3',
80
+ 'deeppink' => '#ff1493',
81
+ 'deepskyblue' => '#00bfff',
82
+ 'dodgerblue' => '#1e90ff',
83
+ 'firebrick' => '#b22222',
84
+ 'floralwhite' => '#fffaf0',
85
+ 'forestgreen' => '#228b22',
86
+ 'fuchsia' => '#f0f',
87
+ 'gainsboro' => '#dcdcdc',
88
+ 'ghostwhite' => '#f8f8ff',
89
+ 'goldenrod' => '#daa520',
90
+ 'greenyellow' => '#adff2f',
91
+ 'honeydew' => '#f0fff0',
92
+ 'indianred' => '#cd5c5c',
93
+ 'lavender' => '#e6e6fa',
94
+ 'lavenderblush' => '#fff0f5',
95
+ 'lawngreen' => '#7cfc00',
96
+ 'lemonchiffon' => '#fffacd',
97
+ 'lightblue' => '#add8e6',
98
+ 'lightcoral' => '#f08080',
99
+ 'lightcyan' => '#e0ffff',
100
+ 'lightgoldenrodyellow' => '#fafad2',
101
+ 'lightgray' => '#d3d3d3',
102
+ 'lightgreen' => '#90ee90',
103
+ 'lightgrey' => '#d3d3d3',
104
+ 'lightpink' => '#ffb6c1',
105
+ 'lightsalmon' => '#ffa07a',
106
+ 'lightseagreen' => '#20b2aa',
107
+ 'lightskyblue' => '#87cefa',
108
+ 'lightslategray' => '#778899',
109
+ 'lightslategrey' => '#778899',
110
+ 'lightsteelblue' => '#b0c4de',
111
+ 'lightyellow' => '#ffffe0',
112
+ 'limegreen' => '#32cd32',
113
+ 'mediumaquamarine' => '#66cdaa',
114
+ 'mediumblue' => '#0000cd',
115
+ 'mediumorchid' => '#ba55d3',
116
+ 'mediumpurple' => '#9370db',
117
+ 'mediumseagreen' => '#3cb371',
118
+ 'mediumslateblue' => '#7b68ee',
119
+ 'mediumspringgreen' => '#00fa9a',
120
+ 'mediumturquoise' => '#48d1cc',
121
+ 'mediumvioletred' => '#c71585',
122
+ 'midnightblue' => '#191970',
123
+ 'mintcream' => '#f5fffa',
124
+ 'mistyrose' => '#ffe4e1',
125
+ 'moccasin' => '#ffe4b5',
126
+ 'navajowhite' => '#ffdead',
127
+ 'olivedrab' => '#6b8e23',
128
+ 'orangered' => '#ff4500',
129
+ 'palegoldenrod' => '#eee8aa',
130
+ 'palegreen' => '#98fb98',
131
+ 'paleturquoise' => '#afeeee',
132
+ 'palevioletred' => '#db7093',
133
+ 'papayawhip' => '#ffefd5',
134
+ 'peachpuff' => '#ffdab9',
135
+ 'powderblue' => '#b0e0e6',
136
+ 'rebeccapurple' => '#663399',
137
+ 'rosybrown' => '#bc8f8f',
138
+ 'royalblue' => '#4169e1',
139
+ 'saddlebrown' => '#8b4513',
140
+ 'sandybrown' => '#f4a460',
141
+ 'seagreen' => '#2e8b57',
142
+ 'seashell' => '#fff5ee',
143
+ 'slateblue' => '#6a5acd',
144
+ 'slategray' => '#708090',
145
+ 'slategrey' => '#708090',
146
+ 'springgreen' => '#00ff7f',
147
+ 'steelblue' => '#4682b4',
148
+ 'turquoise' => '#40e0d0',
149
+ 'white' => '#fff',
150
+ 'whitesmoke' => '#f5f5f5',
151
+ 'yellow' => '#ff0',
152
+ 'yellowgreen' => '#9acd32'
153
+ );
154
+ }
155
+ }
lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Command.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace w3tc_tubalmartin\CssMin;
4
+
5
+ class Command
6
+ {
7
+ const SUCCESS_EXIT = 0;
8
+ const FAILURE_EXIT = 1;
9
+
10
+ protected $stats = array();
11
+
12
+ public static function main()
13
+ {
14
+ $command = new self;
15
+ $command->run();
16
+ }
17
+
18
+ public function run()
19
+ {
20
+ $opts = getopt(
21
+ 'hi:o:',
22
+ array(
23
+ 'help',
24
+ 'input:',
25
+ 'output:',
26
+ 'dry-run',
27
+ 'keep-sourcemap',
28
+ 'keep-sourcemap-comment',
29
+ 'linebreak-position:',
30
+ 'memory-limit:',
31
+ 'pcre-backtrack-limit:',
32
+ 'pcre-recursion-limit:',
33
+ 'remove-important-comments'
34
+ )
35
+ );
36
+
37
+ $help = $this->getOpt(array('h', 'help'), $opts);
38
+ $input = $this->getOpt(array('i', 'input'), $opts);
39
+ $output = $this->getOpt(array('o', 'output'), $opts);
40
+ $dryrun = $this->getOpt('dry-run', $opts);
41
+ $keepSourceMapComment = $this->getOpt(array('keep-sourcemap', 'keep-sourcemap-comment'), $opts);
42
+ $linebreakPosition = $this->getOpt('linebreak-position', $opts);
43
+ $memoryLimit = $this->getOpt('memory-limit', $opts);
44
+ $backtrackLimit = $this->getOpt('pcre-backtrack-limit', $opts);
45
+ $recursionLimit = $this->getOpt('pcre-recursion-limit', $opts);
46
+ $removeImportantComments = $this->getOpt('remove-important-comments', $opts);
47
+
48
+ if (!is_null($help)) {
49
+ $this->showHelp();
50
+ die(self::SUCCESS_EXIT);
51
+ }
52
+
53
+ if (is_null($input)) {
54
+ fwrite(STDERR, '-i <file> argument is missing' . PHP_EOL);
55
+ $this->showHelp();
56
+ die(self::FAILURE_EXIT);
57
+ }
58
+
59
+ if (!is_readable($input)) {
60
+ fwrite(STDERR, 'Input file is not readable' . PHP_EOL);
61
+ die(self::FAILURE_EXIT);
62
+ }
63
+
64
+ $css = file_get_contents($input);
65
+
66
+ if ($css === false) {
67
+ fwrite(STDERR, 'Input CSS code could not be retrieved from input file' . PHP_EOL);
68
+ die(self::FAILURE_EXIT);
69
+ }
70
+
71
+ $this->setStat('original-size', strlen($css));
72
+
73
+ $cssmin = new Minifier;
74
+
75
+ if (!is_null($keepSourceMapComment)) {
76
+ $cssmin->keepSourceMapComment();
77
+ }
78
+
79
+ if (!is_null($removeImportantComments)) {
80
+ $cssmin->removeImportantComments();
81
+ }
82
+
83
+ if (!is_null($linebreakPosition)) {
84
+ $cssmin->setLineBreakPosition($linebreakPosition);
85
+ }
86
+
87
+ if (!is_null($memoryLimit)) {
88
+ $cssmin->setMemoryLimit($memoryLimit);
89
+ }
90
+
91
+ if (!is_null($backtrackLimit)) {
92
+ $cssmin->setPcreBacktrackLimit($backtrackLimit);
93
+ }
94
+
95
+ if (!is_null($recursionLimit)) {
96
+ $cssmin->setPcreRecursionLimit($recursionLimit);
97
+ }
98
+
99
+ $this->setStat('compression-time-start', microtime(true));
100
+
101
+ $css = $cssmin->run($css);
102
+
103
+ $this->setStat('compression-time-end', microtime(true));
104
+ $this->setStat('peak-memory-usage', memory_get_peak_usage(true));
105
+ $this->setStat('compressed-size', strlen($css));
106
+
107
+ if (!is_null($dryrun)) {
108
+ $this->showStats();
109
+ die(self::SUCCESS_EXIT);
110
+ }
111
+
112
+ if (is_null($output)) {
113
+ fwrite(STDOUT, $css . PHP_EOL);
114
+ $this->showStats();
115
+ die(self::SUCCESS_EXIT);
116
+ }
117
+
118
+ if (!is_writable(dirname($output))) {
119
+ fwrite(STDERR, 'Output file is not writable' . PHP_EOL);
120
+ die(self::FAILURE_EXIT);
121
+ }
122
+
123
+ if (file_put_contents($output, $css) === false) {
124
+ fwrite(STDERR, 'Compressed CSS code could not be saved to output file' . PHP_EOL);
125
+ die(self::FAILURE_EXIT);
126
+ }
127
+
128
+ $this->showStats();
129
+
130
+ die(self::SUCCESS_EXIT);
131
+ }
132
+
133
+ protected function getOpt($opts, $options)
134
+ {
135
+ $value = null;
136
+
137
+ if (is_string($opts)) {
138
+ $opts = array($opts);
139
+ }
140
+
141
+ foreach ($opts as $opt) {
142
+ if (array_key_exists($opt, $options)) {
143
+ $value = $options[$opt];
144
+ break;
145
+ }
146
+ }
147
+
148
+ return $value;
149
+ }
150
+
151
+ protected function setStat($statName, $statValue)
152
+ {
153
+ $this->stats[$statName] = $statValue;
154
+ }
155
+
156
+ protected function formatBytes($size, $precision = 2)
157
+ {
158
+ $base = log($size, 1024);
159
+ $suffixes = array('B', 'K', 'M', 'G', 'T');
160
+ return round(pow(1024, $base - floor($base)), $precision) .' '. $suffixes[floor($base)];
161
+ }
162
+
163
+ protected function formatMicroSeconds($microSecs, $precision = 2)
164
+ {
165
+ // ms
166
+ $time = round($microSecs * 1000, $precision);
167
+
168
+ if ($time >= 60 * 1000) {
169
+ $time = round($time / 60 * 1000, $precision) .' m'; // m
170
+ } elseif ($time >= 1000) {
171
+ $time = round($time / 1000, $precision) .' s'; // s
172
+ } else {
173
+ $time .= ' ms';
174
+ }
175
+
176
+ return $time;
177
+ }
178
+
179
+ protected function showStats()
180
+ {
181
+ $spaceSavings = round((1 - ($this->stats['compressed-size'] / $this->stats['original-size'])) * 100, 2);
182
+ $compressionRatio = round($this->stats['original-size'] / $this->stats['compressed-size'], 2);
183
+ $compressionTime = $this->formatMicroSeconds(
184
+ $this->stats['compression-time-end'] - $this->stats['compression-time-start']
185
+ );
186
+ $peakMemoryUsage = $this->formatBytes($this->stats['peak-memory-usage']);
187
+
188
+ print <<<EOT
189
+
190
+ ------------------------------
191
+ CSSMIN STATS
192
+ ------------------------------
193
+ Space savings: {$spaceSavings} %
194
+ Compression ratio: {$compressionRatio}:1
195
+ Compression time: $compressionTime
196
+ Peak memory usage: $peakMemoryUsage
197
+
198
+
199
+ EOT;
200
+ }
201
+
202
+ protected function showHelp()
203
+ {
204
+ print <<<'EOT'
205
+ Usage: cssmin [options] -i <file> [-o <file>]
206
+
207
+ -i|--input <file> File containing uncompressed CSS code.
208
+ -o|--output <file> File to use to save compressed CSS code.
209
+
210
+ Options:
211
+
212
+ -h|--help Prints this usage information.
213
+ --dry-run Performs a dry run displaying statistics.
214
+ --keep-sourcemap[-comment] Keeps the sourcemap special comment in the output.
215
+ --linebreak-position <pos> Splits long lines after a specific column in the output.
216
+ --memory-limit <limit> Sets the memory limit for this script.
217
+ --pcre-backtrack-limit <limit> Sets the PCRE backtrack limit for this script.
218
+ --pcre-recursion-limit <limit> Sets the PCRE recursion limit for this script.
219
+ --remove-important-comments Removes !important comments from output.
220
+
221
+ EOT;
222
+ }
223
+ }
lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Minifier.php ADDED
@@ -0,0 +1,862 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*!
4
+ * CssMin
5
+ * Author: Tubal Martin - http://tubalmartin.me/
6
+ * Repo: https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port
7
+ *
8
+ * This is a PHP port of the CSS minification tool distributed with YUICompressor,
9
+ * itself a port of the cssmin utility by Isaac Schlueter - http://foohack.com/
10
+ * Permission is hereby granted to use the PHP version under the same
11
+ * conditions as the YUICompressor.
12
+ */
13
+
14
+ /*!
15
+ * YUI Compressor
16
+ * http://developer.yahoo.com/yui/compressor/
17
+ * Author: Julien Lecomte - http://www.julienlecomte.net/
18
+ * Copyright (c) 2013 Yahoo! Inc. All rights reserved.
19
+ * The copyrights embodied in the content of this file are licensed
20
+ * by Yahoo! Inc. under the BSD (revised) open source license.
21
+ */
22
+
23
+ namespace w3tc_tubalmartin\CssMin;
24
+
25
+ class Minifier
26
+ {
27
+ const QUERY_FRACTION = '_CSSMIN_QF_';
28
+ const COMMENT_TOKEN = '_CSSMIN_CMT_%d_';
29
+ const COMMENT_TOKEN_START = '_CSSMIN_CMT_';
30
+ const RULE_BODY_TOKEN = '_CSSMIN_RBT_%d_';
31
+ const PRESERVED_TOKEN = '_CSSMIN_PTK_%d_';
32
+
33
+ // Token lists
34
+ private $comments = array();
35
+ private $ruleBodies = array();
36
+ private $preservedTokens = array();
37
+
38
+ // Output options
39
+ private $keepImportantComments = true;
40
+ private $keepSourceMapComment = false;
41
+ private $linebreakPosition = 0;
42
+
43
+ // PHP ini limits
44
+ private $raisePhpLimits;
45
+ private $memoryLimit;
46
+ private $maxExecutionTime = 60; // 1 min
47
+ private $pcreBacktrackLimit;
48
+ private $pcreRecursionLimit;
49
+
50
+ // Color maps
51
+ private $hexToNamedColorsMap;
52
+ private $namedToHexColorsMap;
53
+
54
+ // Regexes
55
+ private $numRegex;
56
+ private $charsetRegex = '/@charset [^;]+;/Si';
57
+ private $importRegex = '/@import [^;]+;/Si';
58
+ private $namespaceRegex = '/@namespace [^;]+;/Si';
59
+ private $namedToHexColorsRegex;
60
+ private $shortenOneZeroesRegex;
61
+ private $shortenTwoZeroesRegex;
62
+ private $shortenThreeZeroesRegex;
63
+ private $shortenFourZeroesRegex;
64
+ private $unitsGroupRegex = '(?:ch|cm|em|ex|gd|in|mm|px|pt|pc|q|rem|vh|vmax|vmin|vw|%)';
65
+
66
+ /**
67
+ * @param bool|int $raisePhpLimits If true, PHP settings will be raised if needed
68
+ */
69
+ public function __construct($raisePhpLimits = true)
70
+ {
71
+ $this->raisePhpLimits = (bool) $raisePhpLimits;
72
+ $this->memoryLimit = 128 * 1048576; // 128MB in bytes
73
+ $this->pcreBacktrackLimit = 1000 * 1000;
74
+ $this->pcreRecursionLimit = 500 * 1000;
75
+ $this->hexToNamedColorsMap = Colors::getHexToNamedMap();
76
+ $this->namedToHexColorsMap = Colors::getNamedToHexMap();
77
+ $this->namedToHexColorsRegex = sprintf(
78
+ '/([:,( ])(%s)( |,|\)|;|$)/Si',
79
+ implode('|', array_keys($this->namedToHexColorsMap))
80
+ );
81
+ $this->numRegex = sprintf('-?\d*\.?\d+%s?', $this->unitsGroupRegex);
82
+ $this->setShortenZeroValuesRegexes();
83
+ }
84
+
85
+ /**
86
+ * Parses & minifies the given input CSS string
87
+ * @param string $css
88
+ * @return string
89
+ */
90
+ public function run($css = '')
91
+ {
92
+ if (empty($css) || !is_string($css)) {
93
+ return '';
94
+ }
95
+
96
+ $this->resetRunProperties();
97
+
98
+ if ($this->raisePhpLimits) {
99
+ $this->doRaisePhpLimits();
100
+ }
101
+
102
+ return $this->minify($css);
103
+ }
104
+
105
+ /**
106
+ * Sets whether to keep or remove sourcemap special comment.
107
+ * Sourcemap comments are removed by default.
108
+ * @param bool $keepSourceMapComment
109
+ */
110
+ public function keepSourceMapComment($keepSourceMapComment = true)
111
+ {
112
+ $this->keepSourceMapComment = (bool) $keepSourceMapComment;
113
+ }
114
+
115
+ /**
116
+ * Sets whether to keep or remove important comments.
117
+ * Important comments outside of a declaration block are kept by default.
118
+ * @param bool $removeImportantComments
119
+ */
120
+ public function removeImportantComments($removeImportantComments = true)
121
+ {
122
+ $this->keepImportantComments = !(bool) $removeImportantComments;
123
+ }
124
+
125
+ /**
126
+ * Sets the approximate column after which long lines will be splitted in the output
127
+ * with a linebreak.
128
+ * @param int $position
129
+ */
130
+ public function setLineBreakPosition($position)
131
+ {
132
+ $this->linebreakPosition = (int) $position;
133
+ }
134
+
135
+ /**
136
+ * Sets the memory limit for this script
137
+ * @param int|string $limit
138
+ */
139
+ public function setMemoryLimit($limit)
140
+ {
141
+ $this->memoryLimit = Utils::normalizeInt($limit);
142
+ }
143
+
144
+ /**
145
+ * Sets the maximum execution time for this script
146
+ * @param int|string $seconds
147
+ */
148
+ public function setMaxExecutionTime($seconds)
149
+ {
150
+ $this->maxExecutionTime = (int) $seconds;
151
+ }
152
+
153
+ /**
154
+ * Sets the PCRE backtrack limit for this script
155
+ * @param int $limit
156
+ */
157
+ public function setPcreBacktrackLimit($limit)
158
+ {
159
+ $this->pcreBacktrackLimit = (int) $limit;
160
+ }
161
+
162
+ /**
163
+ * Sets the PCRE recursion limit for this script
164
+ * @param int $limit
165
+ */
166
+ public function setPcreRecursionLimit($limit)
167
+ {
168
+ $this->pcreRecursionLimit = (int) $limit;
169
+ }
170
+
171
+ /**
172
+ * Builds regular expressions needed for shortening zero values
173
+ */
174
+ private function setShortenZeroValuesRegexes()
175
+ {
176
+ $zeroRegex = '0'. $this->unitsGroupRegex;
177
+ $numOrPosRegex = '('. $this->numRegex .'|top|left|bottom|right|center) ';
178
+ $oneZeroSafeProperties = array(
179
+ '(?:line-)?height',
180
+ '(?:(?:min|max)-)?width',
181
+ 'top',
182
+ 'left',
183
+ 'background-position',
184
+ 'bottom',
185
+ 'right',
186
+ 'border(?:-(?:top|left|bottom|right))?(?:-width)?',
187
+ 'border-(?:(?:top|bottom)-(?:left|right)-)?radius',
188
+ 'column-(?:gap|width)',
189
+ 'margin(?:-(?:top|left|bottom|right))?',
190
+ 'outline-width',
191
+ 'padding(?:-(?:top|left|bottom|right))?'
192
+ );
193
+
194
+ // First zero regex
195
+ $regex = '/(^|;)('. implode('|', $oneZeroSafeProperties) .'):%s/Si';
196
+ $this->shortenOneZeroesRegex = sprintf($regex, $zeroRegex);
197
+
198
+ // Multiple zeroes regexes
199
+ $regex = '/(^|;)(margin|padding|border-(?:width|radius)|background-position):%s/Si';
200
+ $this->shortenTwoZeroesRegex = sprintf($regex, $numOrPosRegex . $zeroRegex);
201
+ $this->shortenThreeZeroesRegex = sprintf($regex, $numOrPosRegex . $numOrPosRegex . $zeroRegex);
202
+ $this->shortenFourZeroesRegex = sprintf($regex, $numOrPosRegex . $numOrPosRegex . $numOrPosRegex . $zeroRegex);
203
+ }
204
+
205
+ /**
206
+ * Resets properties whose value may change between runs
207
+ */
208
+ private function resetRunProperties()
209
+ {
210
+ $this->comments = array();
211
+ $this->ruleBodies = array();
212
+ $this->preservedTokens = array();
213
+ }
214
+
215
+ /**
216
+ * Tries to configure PHP to use at least the suggested minimum settings
217
+ * @return void
218
+ */
219
+ private function doRaisePhpLimits()
220
+ {
221
+ $phpLimits = array(
222
+ 'memory_limit' => $this->memoryLimit,
223
+ 'max_execution_time' => $this->maxExecutionTime,
224
+ 'pcre.backtrack_limit' => $this->pcreBacktrackLimit,
225
+ 'pcre.recursion_limit' => $this->pcreRecursionLimit
226
+ );
227
+
228
+ // If current settings are higher respect them.
229
+ foreach ($phpLimits as $name => $suggested) {
230
+ $current = Utils::normalizeInt(ini_get($name));
231
+
232
+ if ($current >= $suggested) {
233
+ continue;
234
+ }
235
+
236
+ // memoryLimit exception: allow -1 for "no memory limit".
237
+ if ($name === 'memory_limit' && $current === -1) {
238
+ continue;
239
+ }
240
+
241
+ // maxExecutionTime exception: allow 0 for "no memory limit".
242
+ if ($name === 'max_execution_time' && $current === 0) {
243
+ continue;
244
+ }
245
+
246
+ ini_set($name, $suggested);
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Registers a preserved token
252
+ * @param string $token
253
+ * @return string The token ID string
254
+ */
255
+ private function registerPreservedToken($token)
256
+ {
257
+ $tokenId = sprintf(self::PRESERVED_TOKEN, count($this->preservedTokens));
258
+ $this->preservedTokens[$tokenId] = $token;
259
+ return $tokenId;
260
+ }
261
+
262
+ /**
263
+ * Registers a candidate comment token
264
+ * @param string $comment
265
+ * @return string The comment token ID string
266
+ */
267
+ private function registerCommentToken($comment)
268
+ {
269
+ $tokenId = sprintf(self::COMMENT_TOKEN, count($this->comments));
270
+ $this->comments[$tokenId] = $comment;
271
+ return $tokenId;
272
+ }
273
+
274
+ /**
275
+ * Registers a rule body token
276
+ * @param string $body the minified rule body
277
+ * @return string The rule body token ID string
278
+ */
279
+ private function registerRuleBodyToken($body)
280
+ {
281
+ if (empty($body)) {
282
+ return '';
283
+ }
284
+
285
+ $tokenId = sprintf(self::RULE_BODY_TOKEN, count($this->ruleBodies));
286
+ $this->ruleBodies[$tokenId] = $body;
287
+ return $tokenId;
288
+ }
289
+
290
+ /**
291
+ * Parses & minifies the given input CSS string
292
+ * @param string $css
293
+ * @return string
294
+ */
295
+ private function minify($css)
296
+ {
297
+ // Process data urls
298
+ $css = $this->processDataUrls($css);
299
+
300
+ // Process comments
301
+ $css = preg_replace_callback(
302
+ '/(?<!\\\\)\/\*(.*?)\*(?<!\\\\)\//Ss',
303
+ array($this, 'processCommentsCallback'),
304
+ $css
305
+ );
306
+
307
+ // IE7: Process Microsoft matrix filters (whitespaces between Matrix parameters). Can contain strings inside.
308
+ $css = preg_replace_callback(
309
+ '/filter:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^)]+)\)/Ss',
310
+ array($this, 'processOldIeSpecificMatrixDefinitionCallback'),
311
+ $css
312
+ );
313
+
314
+ // Process quoted unquotable attribute selectors to unquote them. Covers most common cases.
315
+ // Likelyhood of a quoted attribute selector being a substring in a string: Very very low.
316
+ $css = preg_replace(
317
+ '/\[\s*([a-z][a-z-]+)\s*([\*\|\^\$~]?=)\s*[\'"](-?[a-z_][a-z0-9-_]+)[\'"]\s*\]/Ssi',
318
+ '[$1$2$3]',
319
+ $css
320
+ );
321
+
322
+ // Process strings so their content doesn't get accidentally minified
323
+ $css = preg_replace_callback(
324
+ '/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S",
325
+ array($this, 'processStringsCallback'),
326
+ $css
327
+ );
328
+
329
+ // Normalize all whitespace strings to single spaces. Easier to work with that way.
330
+ $css = preg_replace('/\s+/S', ' ', $css);
331
+
332
+ // Process comments
333
+ $css = $this->processComments($css);
334
+
335
+ // Process rule bodies
336
+ $css = $this->processRuleBodies($css);
337
+
338
+ // Process at-rules and selectors
339
+ $css = $this->processAtRulesAndSelectors($css);
340
+
341
+ // Restore preserved rule bodies before splitting
342
+ $css = strtr($css, $this->ruleBodies);
343
+
344
+ // Some source control tools don't like it when files containing lines longer
345
+ // than, say 8000 characters, are checked in. The linebreak option is used in
346
+ // that case to split long lines after a specific column.
347
+ if ($this->linebreakPosition > 0) {
348
+ $l = strlen($css);
349
+ $offset = $this->linebreakPosition;
350
+ while (preg_match('/(?<!\\\\)\}(?!\n)/S', $css, $matches, PREG_OFFSET_CAPTURE, $offset)) {
351
+ $matchIndex = $matches[0][1];
352
+ $css = substr_replace($css, "\n", $matchIndex + 1, 0);
353
+ $offset = $matchIndex + 2 + $this->linebreakPosition;
354
+ $l += 1;
355
+ if ($offset > $l) {
356
+ break;
357
+ }
358
+ }
359
+ }
360
+
361
+ // Restore preserved comments and strings
362
+ $css = strtr($css, $this->preservedTokens);
363
+
364
+ return trim($css);
365
+ }
366
+
367
+ /**
368
+ * Searches & replaces all data urls with tokens before we start compressing,
369
+ * to avoid performance issues running some of the subsequent regexes against large string chunks.
370
+ * @param string $css
371
+ * @return string
372
+ */
373
+ private function processDataUrls($css)
374
+ {
375
+ $ret = '';
376
+ $searchOffset = $substrOffset = 0;
377
+
378
+ // Since we need to account for non-base64 data urls, we need to handle
379
+ // ' and ) being part of the data string.
380
+ while (preg_match('/url\(\s*(["\']?)data:/Si', $css, $m, PREG_OFFSET_CAPTURE, $searchOffset)) {
381
+ $matchStartIndex = $m[0][1];
382
+ $dataStartIndex = $matchStartIndex + 4; // url( length
383
+ $searchOffset = $matchStartIndex + strlen($m[0][0]);
384
+ $terminator = $m[1][0]; // ', " or empty (not quoted)
385
+ $terminatorRegex = '/(?<!\\\\)'. (strlen($terminator) === 0 ? '' : $terminator.'\s*') .'(\))/S';
386
+
387
+ $ret .= substr($css, $substrOffset, $matchStartIndex - $substrOffset);
388
+
389
+ // Terminator found
390
+ if (preg_match($terminatorRegex, $css, $matches, PREG_OFFSET_CAPTURE, $searchOffset)) {
391
+ $matchEndIndex = $matches[1][1];
392
+ $searchOffset = $matchEndIndex + 1;
393
+ $token = substr($css, $dataStartIndex, $matchEndIndex - $dataStartIndex);
394
+
395
+ // Remove all spaces only for base64 encoded URLs.
396
+ if (stripos($token, 'base64,') !== false) {
397
+ $token = preg_replace('/\s+/S', '', $token);
398
+ }
399
+
400
+ $ret .= 'url('. $this->registerPreservedToken(trim($token)) .')';
401
+ // No end terminator found, re-add the whole match. Should we throw/warn here?
402
+ } else {
403
+ $ret .= substr($css, $matchStartIndex, $searchOffset - $matchStartIndex);
404
+ }
405
+
406
+ $substrOffset = $searchOffset;
407
+ }
408
+
409
+ $ret .= substr($css, $substrOffset);
410
+
411
+ return $ret;
412
+ }
413
+
414
+ /**
415
+ * Registers all comments found as candidates to be preserved.
416
+ * @param array $matches
417
+ * @return string
418
+ */
419
+ private function processCommentsCallback($matches)
420
+ {
421
+ return '/*'. $this->registerCommentToken($matches[1]) .'*/';
422
+ }
423
+
424
+ /**
425
+ * Preserves old IE Matrix string definition
426
+ * @param array $matches
427
+ * @return string
428
+ */
429
+ private function processOldIeSpecificMatrixDefinitionCallback($matches)
430
+ {
431
+ return 'filter:progid:DXImageTransform.Microsoft.Matrix('. $this->registerPreservedToken($matches[1]) .')';
432
+ }
433
+
434
+ /**
435
+ * Preserves strings found
436
+ * @param array $matches
437
+ * @return string
438
+ */
439
+ private function processStringsCallback($matches)
440
+ {
441
+ $match = $matches[0];
442
+ $quote = substr($match, 0, 1);
443
+ $match = substr($match, 1, -1);
444
+
445
+ // maybe the string contains a comment-like substring?
446
+ // one, maybe more? put'em back then
447
+ if (strpos($match, self::COMMENT_TOKEN_START) !== false) {
448
+ $match = strtr($match, $this->comments);
449
+ }
450
+
451
+ // minify alpha opacity in filter strings
452
+ $match = str_ireplace('progid:DXImageTransform.Microsoft.Alpha(Opacity=', 'alpha(opacity=', $match);
453
+
454
+ return $quote . $this->registerPreservedToken($match) . $quote;
455
+ }
456
+
457
+ /**
458
+ * Preserves or removes comments found.
459
+ * @param string $css
460
+ * @return string
461
+ */
462
+ private function processComments($css)
463
+ {
464
+ foreach ($this->comments as $commentId => $comment) {
465
+ $commentIdString = '/*'. $commentId .'*/';
466
+
467
+ // ! in the first position of the comment means preserve
468
+ // so push to the preserved tokens keeping the !
469
+ if ($this->keepImportantComments && strpos($comment, '!') === 0) {
470
+ $preservedTokenId = $this->registerPreservedToken($comment);
471
+ // Put new lines before and after /*! important comments
472
+ $css = str_replace($commentIdString, "\n/*$preservedTokenId*/\n", $css);
473
+ continue;
474
+ }
475
+
476
+ // # sourceMappingURL= in the first position of the comment means sourcemap
477
+ // so push to the preserved tokens if {$this->keepSourceMapComment} is truthy.
478
+ if ($this->keepSourceMapComment && strpos($comment, '# sourceMappingURL=') === 0) {
479
+ $preservedTokenId = $this->registerPreservedToken($comment);
480
+ // Add new line before the sourcemap comment
481
+ $css = str_replace($commentIdString, "\n/*$preservedTokenId*/", $css);
482
+ continue;
483
+ }
484
+
485
+ // Keep empty comments after child selectors (IE7 hack)
486
+ // e.g. html >/**/ body
487
+ if (strlen($comment) === 0 && strpos($css, '>/*'.$commentId) !== false) {
488
+ $css = str_replace($commentId, $this->registerPreservedToken(''), $css);
489
+ continue;
490
+ }
491
+
492
+ // in all other cases kill the comment
493
+ $css = str_replace($commentIdString, '', $css);
494
+ }
495
+
496
+ // Normalize whitespace again
497
+ $css = preg_replace('/ +/S', ' ', $css);
498
+
499
+ return $css;
500
+ }
501
+
502
+ /**
503
+ * Finds, minifies & preserves all rule bodies.
504
+ * @param string $css the whole stylesheet.
505
+ * @return string
506
+ */
507
+ private function processRuleBodies($css)
508
+ {
509
+ $ret = '';
510
+ $searchOffset = $substrOffset = 0;
511
+
512
+ while (($blockStartPos = strpos($css, '{', $searchOffset)) !== false) {
513
+ $blockEndPos = strpos($css, '}', $blockStartPos);
514
+ $nextBlockStartPos = strpos($css, '{', $blockStartPos + 1);
515
+ $ret .= substr($css, $substrOffset, $blockStartPos - $substrOffset);
516
+
517
+ if ($nextBlockStartPos !== false && $nextBlockStartPos < $blockEndPos) {
518
+ $ret .= substr($css, $blockStartPos, $nextBlockStartPos - $blockStartPos);
519
+ $searchOffset = $nextBlockStartPos;
520
+ } else {
521
+ $ruleBody = substr($css, $blockStartPos + 1, $blockEndPos - $blockStartPos - 1);
522
+ $ruleBodyToken = $this->registerRuleBodyToken($this->processRuleBody($ruleBody));
523
+ $ret .= '{'. $ruleBodyToken .'}';
524
+ $searchOffset = $blockEndPos + 1;
525
+ }
526
+
527
+ $substrOffset = $searchOffset;
528
+ }
529
+
530
+ $ret .= substr($css, $substrOffset);
531
+
532
+ return $ret;
533
+ }
534
+
535
+ /**
536
+ * Compresses non-group rule bodies.
537
+ * @param string $body The rule body without curly braces
538
+ * @return string
539
+ */
540
+ private function processRuleBody($body)
541
+ {
542
+ $body = trim($body);
543
+
544
+ // Remove spaces before the things that should not have spaces before them.
545
+ $body = preg_replace('/ ([:=,)*\/;\n])/S', '$1', $body);
546
+
547
+ // Remove the spaces after the things that should not have spaces after them.
548
+ $body = preg_replace('/([:=,(*\/!;\n]) /S', '$1', $body);
549
+
550
+ // Replace multiple semi-colons in a row by a single one
551
+ $body = preg_replace('/;;+/S', ';', $body);
552
+
553
+ // Remove semicolon before closing brace except when:
554
+ // - The last property is prefixed with a `*` (lte IE7 hack) to avoid issues on Symbian S60 3.x browsers.
555
+ if (!preg_match('/\*[a-z0-9-]+:[^;]+;$/Si', $body)) {
556
+ $body = rtrim($body, ';');
557
+ }
558
+
559
+ // Remove important comments inside a rule body (because they make no sense here).
560
+ if (strpos($body, '/*') !== false) {
561
+ $body = preg_replace('/\n?\/\*[A-Z0-9_]+\*\/\n?/S', '', $body);
562
+ }
563
+
564
+ // Empty rule body? Exit :)
565
+ if (empty($body)) {
566
+ return '';
567
+ }
568
+
569
+ // Shorten font-weight values
570
+ $body = preg_replace(
571
+ array('/(font-weight:)bold\b/Si', '/(font-weight:)normal\b/Si'),
572
+ array('${1}700', '${1}400'),
573
+ $body
574
+ );
575
+
576
+ // Shorten background property
577
+ $body = preg_replace('/(background:)(?:none|transparent)( !|;|$)/Si', '${1}0 0$2', $body);
578
+
579
+ // Shorten opacity IE filter
580
+ $body = str_ireplace('progid:DXImageTransform.Microsoft.Alpha(Opacity=', 'alpha(opacity=', $body);
581
+
582
+ // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space)
583
+ // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space)
584
+ // This makes it more likely that it'll get further compressed in the next step.
585
+ $body = preg_replace_callback(
586
+ '/(rgb|hsl)\(([0-9,.% -]+)\)(.|$)/Si',
587
+ array($this, 'shortenHslAndRgbToHexCallback'),
588
+ $body
589
+ );
590
+
591
+ // Shorten colors from #AABBCC to #ABC or shorter color name:
592
+ // - Look for hex colors which don't have a "=" in front of them (to avoid MSIE filters)
593
+ $body = preg_replace_callback(
594
+ '/(?<!=)#([0-9a-f]{3,6})( |,|\)|;|$)/Si',
595
+ array($this, 'shortenHexColorsCallback'),
596
+ $body
597
+ );
598
+
599
+ // Shorten long named colors with a shorter HEX counterpart: white -> #fff.
600
+ // Run at least 2 times to cover most cases
601
+ $body = preg_replace_callback(
602
+ array($this->namedToHexColorsRegex, $this->namedToHexColorsRegex),
603
+ array($this, 'shortenNamedColorsCallback'),
604
+ $body
605
+ );
606
+
607
+ // Replace positive sign from numbers before the leading space is removed.
608
+ // +1.2em to 1.2em, +.8px to .8px, +2% to 2%
609
+ $body = preg_replace('/([ :,(])\+(\.?\d+)/S', '$1$2', $body);
610
+
611
+ // shorten ms to s
612
+ $body = preg_replace_callback('/([ :,(])(-?)(\d{3,})ms/Si', function ($matches) {
613
+ return $matches[1] . $matches[2] . ((int) $matches[3] / 1000) .'s';
614
+ }, $body);
615
+
616
+ // Remove leading zeros from integer and float numbers.
617
+ // 000.6 to .6, -0.8 to -.8, 0050 to 50, -01.05 to -1.05
618
+ $body = preg_replace('/([ :,(])(-?)0+([1-9]?\.?\d+)/S', '$1$2$3', $body);
619
+
620
+ // Remove trailing zeros from float numbers.
621
+ // -6.0100em to -6.01em, .0100 to .01, 1.200px to 1.2px
622
+ $body = preg_replace('/([ :,(])(-?\d?\.\d+?)0+([^\d])/S', '$1$2$3', $body);
623
+
624
+ // Remove trailing .0 -> -9.0 to -9
625
+ $body = preg_replace('/([ :,(])(-?\d+)\.0([^\d])/S', '$1$2$3', $body);
626
+
627
+ // Replace 0 length numbers with 0
628
+ $body = preg_replace('/([ :,(])-?\.?0+([^\d])/S', '${1}0$2', $body);
629
+
630
+ // Shorten zero values for safe properties only
631
+ $body = preg_replace(
632
+ array(
633
+ $this->shortenOneZeroesRegex,
634
+ $this->shortenTwoZeroesRegex,
635
+ $this->shortenThreeZeroesRegex,
636
+ $this->shortenFourZeroesRegex
637
+ ),
638
+ array(
639
+ '$1$2:0',
640
+ '$1$2:$3 0',
641
+ '$1$2:$3 $4 0',
642
+ '$1$2:$3 $4 $5 0'
643
+ ),
644
+ $body
645
+ );
646
+
647
+ // Replace 0 0 0; or 0 0 0 0; with 0 0 for background-position property.
648
+ $body = preg_replace('/(background-position):0(?: 0){2,3}( !|;|$)/Si', '$1:0 0$2', $body);
649
+
650
+ // Shorten suitable shorthand properties with repeated values
651
+ $body = preg_replace(
652
+ array(
653
+ '/(margin|padding|border-(?:width|radius)):('.$this->numRegex.')(?: \2)+( !|;|$)/Si',
654
+ '/(border-(?:style|color)):([#a-z0-9]+)(?: \2)+( !|;|$)/Si'
655
+ ),
656
+ '$1:$2$3',
657
+ $body
658
+ );
659
+ $body = preg_replace(
660
+ array(
661
+ '/(margin|padding|border-(?:width|radius)):'.
662
+ '('.$this->numRegex.') ('.$this->numRegex.') \2 \3( !|;|$)/Si',
663
+ '/(border-(?:style|color)):([#a-z0-9]+) ([#a-z0-9]+) \2 \3( !|;|$)/Si'
664
+ ),
665
+ '$1:$2 $3$4',
666
+ $body
667
+ );
668
+ $body = preg_replace(
669
+ array(
670
+ '/(margin|padding|border-(?:width|radius)):'.
671
+ '('.$this->numRegex.') ('.$this->numRegex.') ('.$this->numRegex.') \3( !|;|$)/Si',
672
+ '/(border-(?:style|color)):([#a-z0-9]+) ([#a-z0-9]+) ([#a-z0-9]+) \3( !|;|$)/Si'
673
+ ),
674
+ '$1:$2 $3 $4$5',
675
+ $body
676
+ );
677
+
678
+ // Lowercase some common functions that can be values
679
+ $body = preg_replace_callback(
680
+ '/(?:attr|blur|brightness|circle|contrast|cubic-bezier|drop-shadow|ellipse|from|grayscale|'.
681
+ 'hsla?|hue-rotate|inset|invert|local|minmax|opacity|perspective|polygon|rgba?|rect|repeat|saturate|sepia|'.
682
+ 'steps|to|url|var|-webkit-gradient|'.
683
+ '(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|(?:repeating-)?(?:linear|radial)-gradient))\(/Si',
684
+ array($this, 'strtolowerCallback'),
685
+ $body
686
+ );
687
+
688
+ // Lowercase all uppercase properties
689
+ $body = preg_replace_callback('/(?:^|;)[A-Z-]+:/S', array($this, 'strtolowerCallback'), $body);
690
+
691
+ return $body;
692
+ }
693
+
694
+ /**
695
+ * Compresses At-rules and selectors.
696
+ * @param string $css the whole stylesheet with rule bodies tokenized.
697
+ * @return string
698
+ */
699
+ private function processAtRulesAndSelectors($css)
700
+ {
701
+ $charset = '';
702
+ $imports = '';
703
+ $namespaces = '';
704
+
705
+ // Remove spaces before the things that should not have spaces before them.
706
+ $css = preg_replace('/ ([@{};>+)\]~=,\/\n])/S', '$1', $css);
707
+
708
+ // Remove the spaces after the things that should not have spaces after them.
709
+ $css = preg_replace('/([{}:;>+(\[~=,\/\n]) /S', '$1', $css);
710
+
711
+ // Shorten shortable double colon (CSS3) pseudo-elements to single colon (CSS2)
712
+ $css = preg_replace('/::(before|after|first-(?:line|letter))(\{|,)/Si', ':$1$2', $css);
713
+
714
+ // Retain space for special IE6 cases
715
+ $css = preg_replace_callback('/:first-(line|letter)(\{|,)/Si', function ($matches) {
716
+ return ':first-'. strtolower($matches[1]) .' '. $matches[2];
717
+ }, $css);
718
+
719
+ // Find a fraction that may used in some @media queries such as: (min-aspect-ratio: 1/1)
720
+ // Add token to add the "/" back in later
721
+ $css = preg_replace('/\(([a-z-]+):([0-9]+)\/([0-9]+)\)/Si', '($1:$2'. self::QUERY_FRACTION .'$3)', $css);
722
+
723
+ // Remove empty rule blocks up to 2 levels deep.
724
+ $css = preg_replace(array_fill(0, 2, '/(\{)[^{};\/\n]+\{\}/S'), '$1', $css);
725
+ $css = preg_replace('/[^{};\/\n]+\{\}/S', '', $css);
726
+
727
+ // Two important comments next to each other? Remove extra newline.
728
+ if ($this->keepImportantComments) {
729
+ $css = str_replace("\n\n", "\n", $css);
730
+ }
731
+
732
+ // Restore fraction
733
+ $css = str_replace(self::QUERY_FRACTION, '/', $css);
734
+
735
+ // Lowercase some popular @directives
736
+ $css = preg_replace_callback(
737
+ '/(?<!\\\\)@(?:charset|document|font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframes|media|'.
738
+ 'namespace|page|supports|viewport)/Si',
739
+ array($this, 'strtolowerCallback'),
740
+ $css
741
+ );
742
+
743
+ // Lowercase some popular media types
744
+ $css = preg_replace_callback(
745
+ '/[ ,](?:all|aural|braille|handheld|print|projection|screen|tty|tv|embossed|speech)[ ,;{]/Si',
746
+ array($this, 'strtolowerCallback'),
747
+ $css
748
+ );
749
+
750
+ // Lowercase some common pseudo-classes & pseudo-elements
751
+ $css = preg_replace_callback(
752
+ '/(?<!\\\\):(?:active|after|before|checked|default|disabled|empty|enabled|first-(?:child|of-type)|'.
753
+ 'focus(?:-within)?|hover|indeterminate|in-range|invalid|lang\(|last-(?:child|of-type)|left|link|not\(|'.
754
+ 'nth-(?:child|of-type)\(|nth-last-(?:child|of-type)\(|only-(?:child|of-type)|optional|out-of-range|'.
755
+ 'read-(?:only|write)|required|right|root|:selection|target|valid|visited)/Si',
756
+ array($this, 'strtolowerCallback'),
757
+ $css
758
+ );
759
+
760
+ // @charset handling
761
+ if (preg_match($this->charsetRegex, $css, $matches)) {
762
+ // Keep the first @charset at-rule found
763
+ $charset = $matches[0];
764
+ // Delete all @charset at-rules
765
+ $css = preg_replace($this->charsetRegex, '', $css);
766
+ }
767
+
768
+ // @import handling
769
+ $css = preg_replace_callback($this->importRegex, function ($matches) use (&$imports) {
770
+ // Keep all @import at-rules found for later
771
+ $imports .= $matches[0];
772
+ // Delete all @import at-rules
773
+ return '';
774
+ }, $css);
775
+
776
+ // @namespace handling
777
+ $css = preg_replace_callback($this->namespaceRegex, function ($matches) use (&$namespaces) {
778
+ // Keep all @namespace at-rules found for later
779
+ $namespaces .= $matches[0];
780
+ // Delete all @namespace at-rules
781
+ return '';
782
+ }, $css);
783
+
784
+ // Order critical at-rules:
785
+ // 1. @charset first
786
+ // 2. @imports below @charset
787
+ // 3. @namespaces below @imports
788
+ $css = $charset . $imports . $namespaces . $css;
789
+
790
+ return $css;
791
+ }
792
+
793
+ /**
794
+ * Converts hsl() & rgb() colors to HEX format.
795
+ * @param $matches
796
+ * @return string
797
+ */
798
+ private function shortenHslAndRgbToHexCallback($matches)
799
+ {
800
+ $type = $matches[1];
801
+ $values = explode(',', $matches[2]);
802
+ $terminator = $matches[3];
803
+
804
+ if ($type === 'hsl') {
805
+ $values = Utils::hslToRgb($values);
806
+ }
807
+
808
+ $hexColors = Utils::rgbToHex($values);
809
+
810
+ // Restore space after rgb() or hsl() function in some cases such as:
811
+ // background-image: linear-gradient(to bottom, rgb(210,180,140) 10%, rgb(255,0,0) 90%);
812
+ if (!empty($terminator) && !preg_match('/[ ,);]/S', $terminator)) {
813
+ $terminator = ' '. $terminator;
814
+ }
815
+
816
+ return '#'. implode('', $hexColors) . $terminator;
817
+ }
818
+
819
+ /**
820
+ * Compresses HEX color values of the form #AABBCC to #ABC or short color name.
821
+ * @param $matches
822
+ * @return string
823
+ */
824
+ private function shortenHexColorsCallback($matches)
825
+ {
826
+ $hex = $matches[1];
827
+
828
+ // Shorten suitable 6 chars HEX colors
829
+ if (strlen($hex) === 6 && preg_match('/^([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3$/Si', $hex, $m)) {
830
+ $hex = $m[1] . $m[2] . $m[3];
831
+ }
832
+
833
+ // Lowercase
834
+ $hex = '#'. strtolower($hex);
835
+
836
+ // Replace Hex colors with shorter color names
837
+ $color = array_key_exists($hex, $this->hexToNamedColorsMap) ? $this->hexToNamedColorsMap[$hex] : $hex;
838
+
839
+ return $color . $matches[2];
840
+ }
841
+
842
+ /**
843
+ * Shortens all named colors with a shorter HEX counterpart for a set of safe properties
844
+ * e.g. white -> #fff
845
+ * @param array $matches
846
+ * @return string
847
+ */
848
+ private function shortenNamedColorsCallback($matches)
849
+ {
850
+ return $matches[1] . $this->namedToHexColorsMap[strtolower($matches[2])] . $matches[3];
851
+ }
852
+
853
+ /**
854
+ * Makes a string lowercase
855
+ * @param array $matches
856
+ * @return string
857
+ */
858
+ private function strtolowerCallback($matches)
859
+ {
860
+ return strtolower($matches[0]);
861
+ }
862
+ }
lib/Minify/YUI-CSS-compressor-PHP-port-4.1.0/Utils.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace w3tc_tubalmartin\CssMin;
4
+
5
+ class Utils
6
+ {
7
+ /**
8
+ * Clamps a number between a minimum and a maximum value.
9
+ * @param int|float $n the number to clamp
10
+ * @param int|float $min the lower end number allowed
11
+ * @param int|float $max the higher end number allowed
12
+ * @return int|float
13
+ */
14
+ public static function clampNumber($n, $min, $max)
15
+ {
16
+ return min(max($n, $min), $max);
17
+ }
18
+
19
+ /**
20
+ * Clamps a RGB color number outside the sRGB color space
21
+ * @param int|float $n the number to clamp
22
+ * @return int|float
23
+ */
24
+ public static function clampNumberSrgb($n)
25
+ {
26
+ return self::clampNumber($n, 0, 255);
27
+ }
28
+
29
+ /**
30
+ * Converts a HSL color into a RGB color
31
+ * @param array $hslValues
32
+ * @return array
33
+ */
34
+ public static function hslToRgb($hslValues)
35
+ {
36
+ $h = floatval($hslValues[0]);
37
+ $s = floatval(str_replace('%', '', $hslValues[1]));
38
+ $l = floatval(str_replace('%', '', $hslValues[2]));
39
+
40
+ // Wrap and clamp, then fraction!
41
+ $h = ((($h % 360) + 360) % 360) / 360;
42
+ $s = self::clampNumber($s, 0, 100) / 100;
43
+ $l = self::clampNumber($l, 0, 100) / 100;
44
+
45
+ if ($s == 0) {
46
+ $r = $g = $b = self::roundNumber(255 * $l);
47
+ } else {
48
+ $v2 = $l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($s * $l);
49
+ $v1 = (2 * $l) - $v2;
50
+ $r = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h + (1/3)));
51
+ $g = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h));
52
+ $b = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h - (1/3)));
53
+ }
54
+
55
+ return array($r, $g, $b);
56
+ }
57
+
58
+ /**
59
+ * Tests and selects the correct formula for each RGB color channel
60
+ * @param $v1
61
+ * @param $v2
62
+ * @param $vh
63
+ * @return mixed
64
+ */
65
+ public static function hueToRgb($v1, $v2, $vh)
66
+ {
67
+ $vh = $vh < 0 ? $vh + 1 : ($vh > 1 ? $vh - 1 : $vh);
68
+
69
+ if ($vh * 6 < 1) {
70
+ return $v1 + ($v2 - $v1) * 6 * $vh;
71
+ }
72
+
73
+ if ($vh * 2 < 1) {
74
+ return $v2;
75
+ }
76
+
77
+ if ($vh * 3 < 2) {
78
+ return $v1 + ($v2 - $v1) * ((2 / 3) - $vh) * 6;
79
+ }
80
+
81
+ return $v1;
82
+ }
83
+
84
+ /**
85
+ * Convert strings like "64M" or "30" to int values
86
+ * @param mixed $size
87
+ * @return int
88
+ */
89
+ public static function normalizeInt($size)
90
+ {
91
+ if (is_string($size)) {
92
+ $letter = substr($size, -1);
93
+ $size = intval($size);
94
+ switch ($letter) {
95
+ case 'M':
96
+ case 'm':
97
+ return (int) $size * 1048576;
98
+ case 'K':
99
+ case 'k':
100
+ return (int) $size * 1024;
101
+ case 'G':
102
+ case 'g':
103
+ return (int) $size * 1073741824;
104
+ }
105
+ }
106
+ return (int) $size;
107
+ }
108
+
109
+ /**
110
+ * Converts a string containing and RGB percentage value into a RGB integer value i.e. '90%' -> 229.5
111
+ * @param $rgbPercentage
112
+ * @return int
113
+ */
114
+ public static function rgbPercentageToRgbInteger($rgbPercentage)
115
+ {
116
+ if (strpos($rgbPercentage, '%') !== false) {
117
+ $rgbPercentage = self::roundNumber(floatval(str_replace('%', '', $rgbPercentage)) * 2.55);
118
+ }
119
+
120
+ return intval($rgbPercentage, 10);
121
+ }
122
+
123
+ /**
124
+ * Converts a RGB color into a HEX color
125
+ * @param array $rgbColors
126
+ * @return array
127
+ */
128
+ public static function rgbToHex($rgbColors)
129
+ {
130
+ $hexColors = array();
131
+
132
+ // Values outside the sRGB color space should be clipped (0-255)
133
+ for ($i = 0, $l = count($rgbColors); $i < $l; $i++) {
134
+ $hexColors[$i] = sprintf("%02x", self::clampNumberSrgb(self::rgbPercentageToRgbInteger($rgbColors[$i])));
135
+ }
136
+
137
+ return $hexColors;
138
+ }
139
+
140
+ /**
141
+ * Rounds a number to its closest integer
142
+ * @param $n
143
+ * @return int
144
+ */
145
+ public static function roundNumber($n)
146
+ {
147
+ return intval(round(floatval($n)), 10);
148
+ }
149
+ }
lib/NetDNA/NetDNA.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  if (!defined('ABSPATH')) {
4
- die();
5
  }
6
 
7
  require_once(W3TC_LIB_DIR . '/OAuth/W3tcOAuth.php');
@@ -25,52 +25,52 @@ class NetDNA {
25
 
26
 
27
 
28
- static public function create($authorization_key) {
29
- $keys = explode('+', $authorization_key);
30
- $alias = '';
31
- $consumerkey = '';
32
- $consumersecret = '';
33
 
34
- if (sizeof($keys) == 3)
35
- list($alias, $consumerkey, $consumersecret) = $keys;
36
 
37
- $api = new NetDNA($alias, $consumerkey, $consumersecret);
38
- return $api;
39
- }
40
 
41
- /**
42
- * @param string $alias
43
- * @param string $key
44
- * @param string $secret
45
- */
46
- public function __construct($alias, $key, $secret) {
47
  $this->alias = $alias;
48
  $this->key = $key;
49
  $this->secret = $secret;
50
  }
51
 
52
- public function get_zone_domain($name) {
53
- return $name . '.' . $this->alias . '.netdna-cdn.com';
54
- }
55
-
56
- public function is_valid() {
57
- return !empty($this->alias) && !empty($this->key) &&
58
- !empty($this->secret);
59
- }
60
-
61
- /**
62
- * @param $selected_call
63
- * @param $method_type
64
- * @param $params
65
- * @return string
66
- * @throws W3tcWpHttpException
67
- */
68
- private function execute($selected_call, $method_type, $params) {
69
- //increase the http request timeout
70
- add_filter('http_request_timeout', array($this, 'filter_timeout_time'));
71
- add_filter('https_ssl_verify', array($this, 'https_ssl_verify'));
72
-
73
- $consumer = new W3tcOAuthConsumer($this->key, $this->secret, NULL);
74
 
75
  // the endpoint for your request
76
  $endpoint = "$this->netdnarws_url/$this->alias$selected_call";
@@ -78,7 +78,7 @@ class NetDNA {
78
  //parse endpoint before creating OAuth request
79
  $parsed = parse_url($endpoint);
80
  if (array_key_exists("parsed", $parsed)) {
81
- parse_str($parsed['query'], $params);
82
  }
83
 
84
  //generate a request from your consumer
@@ -88,37 +88,37 @@ class NetDNA {
88
  $sig_method = new W3tcOAuthSignatureMethod_HMAC_SHA1();
89
  $req_req->sign_request($sig_method, $consumer, NULL);
90
 
91
- $request = array();
92
- $request['sslverify'] = false;
93
- $request['method'] = $method_type;
94
 
95
- if ($method_type == "POST") {
96
- $request['body'] = $req_req->to_postdata();
97
- $request['headers']['Content-Type'] =
98
- 'application/x-www-form-urlencoded; charset=' . get_option('blog_charset');
99
 
100
- $url = $req_req->get_normalized_http_url();
101
- } else {
102
- // notice GET, PUT and DELETE both needs to be passed in URL
103
- $url = $req_req->to_url();
104
- }
105
 
106
- $response = wp_remote_request($url, $request);
107
 
108
- $json_output = '';
109
- if (!is_wp_error($response)) {
110
  // make call
111
- $result = wp_remote_retrieve_body($response);
112
- $headers = wp_remote_retrieve_headers($response);
113
- $response_code = wp_remote_retrieve_response_code($response);
114
- // $json_output contains the output string
115
- $json_output = $result;
116
- } else {
117
- $response_code = $response->get_error_code();
118
- }
119
-
120
- remove_filter('https_ssl_verify', array($this, 'https_ssl_verify'));
121
- remove_filter('http_request_timeout', array($this, 'filter_timeout_time'));
122
 
123
  // catch errors
124
  if(is_wp_error($response)) {
@@ -128,358 +128,375 @@ class NetDNA {
128
  return $json_output;
129
  }
130
 
131
- /**
132
- * @param $selected_call
133
- * @param array $params
134
- * @return string
135
- * @throws W3tcWpHttpException
136
- */
137
- public function get($selected_call, $params = array()){
138
  return $this->execute($selected_call, 'GET', $params);
139
  }
140
 
141
- /**
142
- * @param $selected_call
143
- * @param array $params
144
- * @return string
145
- * @throws W3tcWpHttpException
146
- */
147
- public function post($selected_call, $params = array()){
148
  return $this->execute($selected_call, 'POST', $params);
149
  }
150
 
151
- /**
152
- * @param $selected_call
153
- * @param array $params
154
- * @return string
155
- * @throws W3tcWpHttpException
156
- */
157
- public function put($selected_call, $params = array()){
158
  return $this->execute($selected_call, 'PUT', $params);
159
  }
160
 
161
- /**
162
- * @param $selected_call
163
- * @param array $params
164
- * @return string
165
- * @throws W3tcWpHttpException
166
- */
167
- public function delete($selected_call, $params = array()){
168
  return $this->execute($selected_call, 'DELETE', $params);
169
  }
170
 
171
- /**
172
- * Finds the zone id that matches the provided url.
173
- * @param $url
174
- * @return null|int
175
- * @throws W3tcWpHttpException
176
- */
177
- public function get_zone_id($url) {
178
- $zone_id = null;
179
- $pull_zones = json_decode($this->get('/zones/pull.json'));
180
-
181
- if (preg_match("(200|201)", $pull_zones->code)) {
182
- foreach ($pull_zones->data->pullzones as $zone) {
183
- if (trim($zone->url, '/') != trim($url, '/'))
184
- continue;
185
- else {
186
- $zone_id = $zone->id;
187
- break;
188
- }
189
- }
190
- } else
191
- return null;
192
- return $zone_id;
193
- }
194
-
195
- /**
196
- * Retrieves statistics for the zone id
197
- * @param $zone_id
198
- * @return null|array
199
- * @throws W3tcWpHttpException
200
- */
201
- public function get_stats_per_zone($zone_id) {
202
- $api_stats = json_decode($this->get("/reports/{$zone_id}/stats.json"), true);
203
- if (preg_match("(200|201)", $api_stats['code'])) {
204
- $summary = $api_stats['data']['summary'];
205
- return $summary;
206
- } else
207
- return null;
208
- }
209
-
210
- /**
211
- * Returns list of files for the zone id
212
- * @param $zone_id
213
- * @return null|array
214
- * @throws W3tcWpHttpException
215
- */
216
- public function get_list_of_file_types_per_zone($zone_id) {
217
- $api_list = json_decode($this->get("/reports/pull/{$zone_id}/filetypes.json"), true);
218
- if (preg_match("(200|201)", $api_list['code'])) {
219
- $stats['total'] = $api_list['data']['total'];
220
-
221
- foreach($api_list['data']['filetypes'] as $filetyp) {
222
- $stats['filetypes'][] = $filetyp;
223
- }
224
- $stats['summary'] = $api_list['data']['summary'];
225
- return $stats;
226
- } else
227
- return null;
228
- }
229
-
230
- /**
231
- * Retrieves a list of popular files for zone id
232
- *
233
- * @param $zone_id
234
- * @return null|array
235
- * @throws W3tcWpHttpException
236
- */
237
- public function get_list_of_popularfiles_per_zone($zone_id) {
238
- $api_popularfiles = json_decode($this->get("/reports/{$zone_id}/popularfiles.json"), true);
239
- if (preg_match("(200|201)", $api_popularfiles['code'])) {
240
- $popularfiles = $api_popularfiles['data']['popularfiles'];
241
- return $popularfiles;
242
- } else
243
- return null;
244
- }
245
-
246
- /**
247
- * Retrieves an account connected with the authorization key
248
- *
249
- * @throws Exception
250
- * @return null|string
251
- */
252
- public function get_account() {
253
- $api_account = json_decode($this->get("/account.json"), true);
254
- if (preg_match("(200|201)", $api_account['code'])) {
255
- $account = $api_account['data']['account'];
256
- return $account;
257
- } else
258
- throw new Exception($api_account['error']['message']);
259
- }
260
-
261
- /**
262
- * Retrieves a pull zone
263
- * @param $zone_id
264
- * @throws Exception
265
- * @return null|string
266
- */
267
- public function get_pull_zone($zone_id) {
268
- $api_pull_zone = json_decode($this->get("/zones/pull.json/{$zone_id}"), true);
269
- if (preg_match("(200|201)", $api_pull_zone['code'])) {
270
- $pull_zone = $api_pull_zone['data']['pullzone'];
271
- return $pull_zone;
272
- } else
273
- throw new Exception($api_pull_zone['error']['message']);
274
- }
275
-
276
- /**
277
- * Creates a pull zone
278
- * @param $zone
279
- * @return mixed
280
- * @throws Exception
281
- */
282
- public function create_pull_zone($zone) {
283
- $zone_data = json_decode($this->post('/zones/pull.json', $zone), true);
284
- if (preg_match("(200|201)", $zone_data['code'])) {
285
- return $zone_data['data']['pullzone'];
286
- } else
287
- throw new Exception($zone_data['error']['message']);
288
- }
289
-
290
- /**
291
- * Returns all zones connected to an url
292
- * @param $url
293
- * @throws Exception
294
- * @return array|null
295
- */
296
- public function get_zones_by_url($url) {
297
- $zone_id = null;
298
- $pull_zones = json_decode($this->get('/zones/pull.json'), true);
299
- $zones = array();
300
- if (preg_match("(200|201)", $pull_zones['code'])) {
301
- foreach ($pull_zones ['data']['pullzones'] as $zone) {
302
- if (trim($zone['url'], '/') != trim($url, '/'))
303
- continue;
304
- else {
305
- $zones[] = $zone;
306
- }
307
- }
308
- } else
309
- throw new Exception($pull_zones['error']['message']);
310
- return $zones;
311
- }
312
-
313
- /**
314
- * Retrieves pull zones
315
- * @throws Exception
316
- * @return array|null
317
- */
318
- public function get_pull_zones() {
319
- $pull_zones = json_decode($this->get('/zones/pull.json'), true);
320
- $zones = array();
321
- if (preg_match("(200|201)", $pull_zones['code'])) {
322
- foreach ($pull_zones ['data']['pullzones'] as $zone) {
323
- $zones[] = $zone;
324
- }
325
- } else {
326
- throw new Exception($pull_zones['error']['message']);
327
- }
328
- return $zones;
329
- }
330
-
331
- /**
332
- * Increase http request timeout to 60 seconds
333
- * @param int $time
334
- * @return int
335
- */
336
- public function filter_timeout_time($time) {
337
- return 60;
338
- }
339
-
340
- /**
341
- * Don't check certificate, some users have limited CA list
342
- */
343
- public function https_ssl_verify($v) {
344
- return false;
345
- }
346
-
347
- /**
348
- * Update a pull zone
349
- * @param $zone_id
350
- * @param $zone
351
- * @throws Exception
352
- * @return
353
- */
354
- public function update_pull_zone($zone_id, $zone) {
355
- $zone_data = json_decode($this->put("/zones/pull.json/$zone_id", $zone), true);
356
- if (preg_match("(200|201)", $zone_data['code'])) {
357
- return $zone_data['data']['pullzone'];
358
- } else
359
- throw new Exception($zone_data['error']['message']);
360
- }
361
-
362
- /**
363
- * Creates a new pull zone with default settings
364
- * @param string $url the sites url 4-100 chars; only valid URLs accepted
365
- * @param null|string $name 3-32 chars; only letters, digits, and dash (-)accepted
366
- * @param null|string $label length: 1-255 chars
367
- * @param array $zone_settings custom settings
368
- * @return string
369
- */
370
- public function create_default_pull_zone($url, $name = null, $label = null, $zone_settings=array()) {
371
- $zone_defaults = array();
372
- if (is_null($name)) {
373
- $name = md5($url);
374
- $len = strlen($name)>24 ? 24 : strlen($name);
375
- $name = substr($name, 0, $len);
376
- }
377
- if (is_null($label))
378
- $label = sprintf(__('Zone for %s was created by W3 Total Cache', 'w3-total-cache'), $url);
379
- $zone_defaults['name'] = $name;
380
- $zone_defaults['label'] = $label;
381
- $zone_defaults['url'] = $url;
382
- $zone_defaults['use_stale'] = 0;
383
- $zone_defaults['queries'] = 1;
384
- $zone_defaults['compress'] = 1;
385
- $zone_defaults['backend_compress'] = 1;
386
- $zone_defaults['disallow_robots'] = 1;
387
- $zone_defaults = array_merge( $zone_defaults, $zone_settings);
388
- $response = $this->create_pull_zone($zone_defaults);
389
- return $response;
390
- }
391
-
392
- /**
393
- * Returns number of zones
394
- * @throws Exception
395
- * @return array
396
- */
397
- public function get_zone_count() {
398
- $pull_zones = json_decode($this->get('/zones.json/count'), true);
399
- if (preg_match("(200|201)", $pull_zones['code'])) {
400
- return intval($pull_zones ['data']['count']);
401
- } else
402
- throw new Exception($pull_zones['error']['message']);
403
- }
404
-
405
- /**
406
- * Creates custom domains
407
- * @param $zone_id
408
- * @throws Exception
409
- * @return array|null
410
- */
411
- public function create_custom_domain($zone_id, $custom_domain) {
412
- $custom_domain = json_decode($this->post("/zones/pull/$zone_id/customdomains.json", array(
413
- 'custom_domain' => $custom_domain)), true);
414
- if (preg_match("(200|201)", $custom_domain['code'])) {
415
- return $custom_domain;
416
- } else
417
- throw $this->to_exception($custom_domain);
418
- }
419
-
420
- private function to_exception($response) {
421
- $message = $response['error']['message'];
422
- if (isset($response['data']) && isset($response['data']['errors'])) {
423
- foreach ($response['data']['errors'] as $field => $error)
424
- $message .= '. ' . $field . ': ' . $error;
425
- }
426
-
427
- return new Exception($message);
428
- }
429
-
430
- /**
431
- * Returns custom domains
432
- * @param $zone_id
433
- * @throws Exception
434
- * @return array|null
435
- */
436
- public function get_custom_domains($zone_id) {
437
- $custom_domains = json_decode($this->get("/zones/pull/$zone_id/customdomains.json"), true);
438
- $domains = array();
439
- if (preg_match("(200|201)", $custom_domains['code'])) {
440
- foreach ($custom_domains['data']['customdomains'] as $domain) {
441
- $domains[] = $domain['custom_domain'];
442
- }
443
- } else
444
- throw new Exception($custom_domains['error']['message']);
445
- return $domains;
446
- }
447
-
448
- /**
449
- * Returns the zone data for the provided zone id
450
- *
451
- * @param int $zone_id
452
- * @throws Exception
453
- * @return array
454
- */
455
- public function get_zone($zone_id) {
456
- $zone_data = json_decode($this->get("/zones/pull.json/$zone_id"), true);
457
- if (preg_match("(200|201)", $zone_data['code'])) {
458
- return $zone_data['data']['pullzone'];
459
- } else
460
- throw new Exception($zone_data['error']['message']);
461
- }
462
-
463
- /**
464
- * Deletes files from cache
465
- * @param $zone_id
466
- * @param $files array of relative paths to files to delete
467
- * Deletes whole zone if empty list passed
468
- **/
469
- public function cache_delete($zone_id, $files = array()) {
470
- if (empty($files))
471
- $params = array();
472
- else
473
- $params = array('files' => $files);
474
-
475
- $response = json_decode($this->delete(
476
- '/zones/pull.json/' . $zone_id . '/cache',
477
- $params), true);
478
-
479
- if (preg_match("(200|201)", $response['code'])) {
480
- return true;
481
- } else
482
- throw $this->to_exception($response);
483
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
 
485
  }
1
  <?php
2
 
3
  if (!defined('ABSPATH')) {
4
+ die();
5
  }
6
 
7
  require_once(W3TC_LIB_DIR . '/OAuth/W3tcOAuth.php');
25
 
26
 
27
 
28
+ static public function create($authorization_key) {
29
+ $keys = explode('+', $authorization_key);
30
+ $alias = '';
31
+ $consumerkey = '';
32
+ $consumersecret = '';
33
 
34
+ if (sizeof($keys) == 3)
35
+ list($alias, $consumerkey, $consumersecret) = $keys;
36
 
37
+ $api = new NetDNA($alias, $consumerkey, $consumersecret);
38
+ return $api;
39
+ }
40
 
41
+ /**
42
+ * @param string $alias
43
+ * @param string $key
44
+ * @param string $secret
45
+ */
46
+ public function __construct($alias, $key, $secret) {
47
  $this->alias = $alias;
48
  $this->key = $key;
49
  $this->secret = $secret;
50
  }
51
 
52
+ public function get_zone_domain($name) {
53
+ return $name . '.' . $this->alias . '.netdna-cdn.com';
54
+ }
55
+
56
+ public function is_valid() {
57
+ return !empty($this->alias) && !empty($this->key) &&
58
+ !empty($this->secret);
59
+ }
60
+
61
+ /**
62
+ * @param $selected_call
63
+ * @param $method_type
64
+ * @param $params
65
+ * @return string
66
+ * @throws W3tcWpHttpException
67
+ */
68
+ private function execute($selected_call, $method_type, $params) {
69
+ //increase the http request timeout
70
+ add_filter('http_request_timeout', array($this, 'filter_timeout_time'));
71
+ add_filter('https_ssl_verify', array($this, 'https_ssl_verify'));
72
+
73
+ $consumer = new W3tcOAuthConsumer($this->key, $this->secret, NULL);
74
 
75
  // the endpoint for your request
76
  $endpoint = "$this->netdnarws_url/$this->alias$selected_call";
78
  //parse endpoint before creating OAuth request
79
  $parsed = parse_url($endpoint);
80
  if (array_key_exists("parsed", $parsed)) {
81
+ parse_str($parsed['query'], $params);
82
  }
83
 
84
  //generate a request from your consumer
88
  $sig_method = new W3tcOAuthSignatureMethod_HMAC_SHA1();
89
  $req_req->sign_request($sig_method, $consumer, NULL);
90
 
91
+ $request = array();
92
+ $request['sslverify'] = false;
93
+ $request['method'] = $method_type;
94
 
95
+ if ($method_type == "POST" || $method_type == "PUT") {
96
+ $request['body'] = $req_req->to_postdata();
97
+ $request['headers']['Content-Type'] =
98
+ 'application/x-www-form-urlencoded; charset=' . get_option('blog_charset');
99
 
100
+ $url = $req_req->get_normalized_http_url();
101
+ } else {
102
+ // notice GET, PUT and DELETE both needs to be passed in URL
103
+ $url = $req_req->to_url();
104
+ }
105
 
106
+ $response = wp_remote_request($url, $request);
107
 
108
+ $json_output = '';
109
+ if (!is_wp_error($response)) {
110
  // make call
111
+ $result = wp_remote_retrieve_body($response);
112
+ $headers = wp_remote_retrieve_headers($response);
113
+ $response_code = wp_remote_retrieve_response_code($response);
114
+ // $json_output contains the output string
115
+ $json_output = $result;
116
+ } else {
117
+ $response_code = $response->get_error_code();
118
+ }
119
+
120
+ remove_filter('https_ssl_verify', array($this, 'https_ssl_verify'));
121
+ remove_filter('http_request_timeout', array($this, 'filter_timeout_time'));
122
 
123
  // catch errors
124
  if(is_wp_error($response)) {
128
  return $json_output;
129
  }
130
 
131
+ /**
132
+ * @param $selected_call
133
+ * @param array $params
134
+ * @return string
135
+ * @throws W3tcWpHttpException
136
+ */
137
+ public function get($selected_call, $params = array()){
138
  return $this->execute($selected_call, 'GET', $params);
139
  }
140
 
141
+ /**
142
+ * @param $selected_call
143
+ * @param array $params
144
+ * @return string
145
+ * @throws W3tcWpHttpException
146
+ */
147
+ public function post($selected_call, $params = array()){
148
  return $this->execute($selected_call, 'POST', $params);
149
  }
150
 
151
+ /**
152
+ * @param $selected_call
153
+ * @param array $params
154
+ * @return string
155
+ * @throws W3tcWpHttpException
156
+ */
157
+ public function put($selected_call, $params = array()){
158
  return $this->execute($selected_call, 'PUT', $params);
159
  }
160
 
161
+ /**
162
+ * @param $selected_call
163
+ * @param array $params
164
+ * @return string
165
+ * @throws W3tcWpHttpException
166
+ */
167
+ public function delete($selected_call, $params = array()){
168
  return $this->execute($selected_call, 'DELETE', $params);
169
  }
170
 
171
+ /**
172
+ * Finds the zone id that matches the provided url.
173
+ * @param $url
174
+ * @return null|int
175
+ * @throws W3tcWpHttpException
176
+ */
177
+ public function get_zone_id($url) {
178
+ $zone_id = null;
179
+ $pull_zones = json_decode($this->get('/zones/pull.json'));
180
+
181
+ if (preg_match("(200|201)", $pull_zones->code)) {
182
+ foreach ($pull_zones->data->pullzones as $zone) {
183
+ if (trim($zone->url, '/') != trim($url, '/'))
184
+ continue;
185
+ else {
186
+ $zone_id = $zone->id;
187
+ break;
188
+ }
189
+ }
190
+ } else
191
+ return null;
192
+ return $zone_id;
193
+ }
194
+
195
+ /**
196
+ * Retrieves statistics for the zone id
197
+ * @param $zone_id
198
+ * @return null|array
199
+ * @throws W3tcWpHttpException
200
+ */
201
+ public function get_stats_per_zone($zone_id) {
202
+ $api_stats = json_decode($this->get("/reports/{$zone_id}/stats.json"), true);
203
+ if (preg_match("(200|201)", $api_stats['code'])) {
204
+ $summary = $api_stats['data']['summary'];
205
+ return $summary;
206
+ } else
207
+ return null;
208
+ }
209
+
210
+ /**
211
+ * Returns list of files for the zone id
212
+ * @param $zone_id
213
+ * @return null|array
214
+ * @throws W3tcWpHttpException
215
+ */
216
+ public function get_list_of_file_types_per_zone($zone_id) {
217
+ $api_list = json_decode($this->get("/reports/pull/{$zone_id}/filetypes.json"), true);
218
+ if (preg_match("(200|201)", $api_list['code'])) {
219
+ $stats['total'] = $api_list['data']['total'];
220
+
221
+ foreach($api_list['data']['filetypes'] as $filetyp) {
222
+ $stats['filetypes'][] = $filetyp;
223
+ }
224
+ $stats['summary'] = $api_list['data']['summary'];
225
+ return $stats;
226
+ } else
227
+ return null;
228
+ }
229
+
230
+ /**
231
+ * Retrieves a list of popular files for zone id
232
+ *
233
+ * @param $zone_id
234
+ * @return null|array
235
+ * @throws W3tcWpHttpException
236
+ */
237
+ public function get_list_of_popularfiles_per_zone($zone_id) {
238
+ $api_popularfiles = json_decode($this->get("/reports/{$zone_id}/popularfiles.json"), true);
239
+ if (preg_match("(200|201)", $api_popularfiles['code'])) {
240
+ $popularfiles = $api_popularfiles['data']['popularfiles'];
241
+ return $popularfiles;
242
+ } else
243
+ return null;
244
+ }
245
+
246
+ /**
247
+ * Retrieves an account connected with the authorization key
248
+ *
249
+ * @throws Exception
250
+ * @return null|string
251
+ */
252
+ public function get_account() {
253
+ $api_account = json_decode($this->get("/account.json"), true);
254
+ if (preg_match("(200|201)", $api_account['code'])) {
255
+ $account = $api_account['data']['account'];
256
+ return $account;
257
+ } else
258
+ throw new Exception($this->error_message($api_account));
259
+ }
260
+
261
+ /**
262
+ * Retrieves a pull zone
263
+ * @param $zone_id
264
+ * @throws Exception
265
+ * @return null|string
266
+ */
267
+ public function get_pull_zone($zone_id) {
268
+ $api_pull_zone = json_decode($this->get("/zones/pull.json/{$zone_id}"), true);
269
+ if (preg_match("(200|201)", $api_pull_zone['code'])) {
270
+ $pull_zone = $api_pull_zone['data']['pullzone'];
271
+ return $pull_zone;
272
+ } else
273
+ throw new Exception($this->error_message($api_pull_zone));
274
+ }
275
+
276
+ /**
277
+ * Creates a pull zone
278
+ * @param $zone
279
+ * @return mixed
280
+ * @throws Exception
281
+ */
282
+ public function create_pull_zone($zone) {
283
+ $zone_data = json_decode($this->post('/zones/pull.json', $zone), true);
284
+ if (preg_match("(200|201)", $zone_data['code'])) {
285
+ return $zone_data['data']['pullzone'];
286
+ } else
287
+ throw new Exception($this->error_message($zone_data));
288
+ }
289
+
290
+ private function error_message($o) {
291
+ $m = isset( $o['error']['message'] ) ? $o['error']['message'] : '';
292
+
293
+ if ( isset( $o['data']['errors'] ) && is_array( $o['data']['errors'] ) ) {
294
+ foreach ( $o['data']['errors'] as $k => $v ) {
295
+ $m .= '. ' . $k . ': ' . $v;
296
+ }
297
+ }
298
+
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
328
+ * @return array|null
329
+ */
330
+ public function get_pull_zones() {
331
+ $pull_zones = json_decode($this->get('/zones/pull.json'), true);
332
+ $zones = array();
333
+ if (preg_match("(200|201)", $pull_zones['code'])) {
334
+ foreach ($pull_zones ['data']['pullzones'] as $zone) {
335
+ $zones[] = $zone;
336
+ }
337
+ } else {
338
+ throw new Exception($this->error_message($zone_data));
339
+ }
340
+ return $zones;
341
+ }
342
+
343
+ /**
344
+ * Increase http request timeout to 60 seconds
345
+ * @param int $time
346
+ * @return int
347
+ */
348
+ public function filter_timeout_time($time) {
349
+ return 600;
350
+ }
351
+
352
+ /**
353
+ * Don't check certificate, some users have limited CA list
354
+ */
355
+ public function https_ssl_verify($v) {
356
+ return false;
357
+ }
358
+
359
+ /**
360
+ * Update a pull zone
361
+ * @param $zone_id
362
+ * @param $zone
363
+ * @throws Exception
364
+ * @return
365
+ */
366
+ public function update_pull_zone($zone_id, $zone) {
367
+ $zone_data = json_decode($this->put("/zones/pull.json/$zone_id", $zone), true);
368
+ if (preg_match("(200|201)", $zone_data['code'])) {
369
+ return $zone_data['data']['pullzone'];
370
+ } else {
371
+ throw new Exception($this->error_message($zone_data));
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
421
+ * @throws Exception
422
+ * @return array|null
423
+ */
424
+ public function create_custom_domain($zone_id, $custom_domain) {
425
+ $custom_domain = json_decode($this->post("/zones/pull/$zone_id/customdomains.json", array(
426
+ 'custom_domain' => $custom_domain)), true);
427
+ if (preg_match("(200|201)", $custom_domain['code'])) {
428
+ return $custom_domain;
429
+ } else
430
+ throw $this->to_exception($custom_domain);
431
+ }
432
+
433
+ private function to_exception($response) {
434
+ $message = $response['error']['message'];
435
+ if ( isset( $response['data'] ) && isset( $response['data']['errors'] ) ) {
436
+ foreach ( $response['data']['errors'] as $field => $error ) {
437
+ if ( isset( $error['error'] ) )
438
+ $message .= '. ' . $field . ': ' . $error['error'];
439
+ else
440
+ $message .= '. ' . $field . ': ' . $error;
441
+ }
442
+ }
443
+
444
+ return new Exception($message);
445
+ }
446
+
447
+ /**
448
+ * Returns custom domains
449
+ * @param $zone_id
450
+ * @throws Exception
451
+ * @return array|null
452
+ */
453
+ public function get_custom_domains($zone_id) {
454
+ $custom_domains = json_decode($this->get("/zones/pull/$zone_id/customdomains.json"), true);
455
+ $domains = array();
456
+ if (preg_match("(200|201)", $custom_domains['code'])) {
457
+ foreach ($custom_domains['data']['customdomains'] as $domain) {
458
+ $domains[] = $domain['custom_domain'];
459
+ }
460
+ } else
461
+ throw new Exception($this->error_message($custom_domains));
462
+ return $domains;
463
+ }
464
+
465
+ /**
466
+ * Returns the zone data for the provided zone id
467
+ *
468
+ * @param int $zone_id
469
+ * @throws Exception
470
+ * @return array
471
+ */
472
+ public function get_zone($zone_id) {
473
+ $zone_data = json_decode($this->get("/zones/pull.json/$zone_id"), true);
474
+ if (preg_match("(200|201)", $zone_data['code'])) {
475
+ return $zone_data['data']['pullzone'];
476
+ } else
477
+ throw new Exception($this->error_message($zone_data));
478
+ }
479
+
480
+ /**
481
+ * Deletes files from cache
482
+ * @param $zone_id
483
+ * @param $files array of relative paths to files to delete
484
+ * Deletes whole zone if empty list passed
485
+ **/
486
+ public function cache_delete($zone_id, $files = array()) {
487
+ if (empty($files))
488
+ $params = array();
489
+ else
490
+ $params = array('files' => $files);
491
+
492
+ $response = json_decode($this->delete(
493
+ '/zones/pull.json/' . $zone_id . '/cache',
494
+ $params), true);
495
+
496
+ if (preg_match("(200|201)", $response['code'])) {
497
+ return true;
498
+ } else
499
+ throw $this->to_exception($response);
500
+ }
501
 
502
  }
lib/S3.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
  /**
3
- * $Id: S3.php 47 2009-07-20 01:25:40Z don.schonknecht $
4
  *
5
- * Copyright (c) 2008, Donovan Schönknecht. All rights reserved.
6
  *
7
  * Redistribution and use in source and binary forms, with or without
8
  * modification, are permitted provided that the following conditions are met:
@@ -32,9 +32,10 @@
32
  * Amazon S3 PHP class
33
  *
34
  * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
35
- * @version 0.4.0
36
  */
37
- class S3 {
 
38
  // ACL flags
39
  const ACL_PRIVATE = 'private';
40
  const ACL_PUBLIC_READ = 'public-read';
@@ -42,34 +43,237 @@ class S3 {
42
  const ACL_AUTHENTICATED_READ = 'authenticated-read';
43
 
44
  const LOCATION_US = '';
45
- const LOCATION_EU = 'EU';
46
- const LOCATION_US_WEST = 'us-west-1';
47
- const LOCATION_AP_SOUTHEAST = 'ap-southeast-1';
48
 
49
- const ORIGIN_TYPE_S3 = 'S3';
50
- const ORIING_TYPE_CUSTOM = 'Custom';
51
 
52
- public static $use_ssl = true;
 
 
53
 
54
- private static $__accessKey; // AWS Access key
55
- private static $__secretKey; // AWS Secret key
56
- private static $__api_host; // AWS host where API is located
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  /**
60
  * Constructor - if you're not using the class statically
61
  *
62
  * @param string $accessKey Access key
63
  * @param string $secretKey Secret key
64
- * @param boolean $use_ssl Enable SSL
 
65
  * @return void
66
  */
67
- public function __construct($accessKey = null, $secretKey = null,
68
- $use_ssl = true, $api_host = 's3.amazonaws.com') {
69
  if ($accessKey !== null && $secretKey !== null)
70
- self::setAuth($accessKey, $secretKey, $api_host);
71
- self::$use_ssl = $use_ssl;
72
- self::$__api_host = $api_host;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  }
74
 
75
 
@@ -80,37 +284,191 @@ class S3 {
80
  * @param string $secretKey Secret key
81
  * @return void
82
  */
83
- public static function setAuth($accessKey, $secretKey) {
 
84
  self::$__accessKey = $accessKey;
85
  self::$__secretKey = $secretKey;
86
  }
87
 
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  /**
90
  * Get a list of buckets
91
  *
92
  * @param boolean $detailed Returns detailed bucket list when true
93
  * @return array | false
94
  */
95
- public static function listBuckets($detailed = false) {
96
- $rest = new S3Request('GET', '', '', self::$__api_host);
 
97
  $rest = $rest->getResponse();
98
  if ($rest->error === false && $rest->code !== 200)
99
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
100
- if ($rest->error !== false) {
101
- trigger_error(sprintf("S3::listBuckets(): [%s] %s",
102
- $rest->error['code'],
103
- $rest->error['message']
104
- ), E_USER_WARNING);
105
  return false;
106
  }
107
  $results = array();
108
  if (!isset($rest->body->Buckets)) return $results;
109
 
110
- if ($detailed) {
 
111
  if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
112
  $results['owner'] = array(
113
- 'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->ID
114
  );
115
  $results['buckets'] = array();
116
  foreach ($rest->body->Buckets->Bucket as $b)
@@ -124,6 +482,99 @@ class S3 {
124
  }
125
 
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  /**
128
  * Put a bucket
129
  *
@@ -132,11 +583,15 @@ class S3 {
132
  * @param string $location Set as "EU" to create buckets hosted in Europe
133
  * @return boolean
134
  */
135
- public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false) {
136
- $rest = new S3Request('PUT', $bucket, '', self::$__api_host);
 
137
  $rest->setAmzHeader('x-amz-acl', $acl);
138
 
139
- if ($location) {
 
 
 
140
  $dom = new DOMDocument;
141
  $createBucketConfiguration = $dom->createElement('CreateBucketConfiguration');
142
  $locationConstraint = $dom->createElement('LocationConstraint', $location);
@@ -150,14 +605,32 @@ class S3 {
150
 
151
  if ($rest->error === false && $rest->code !== 200)
152
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
153
- if ($rest->error !== false) {
154
- trigger_error(sprintf("S3::putBucket('%s', '%s', '%s'): [%s] %s",
155
- $bucket,
156
- $acl,
157
- $location,
158
- $rest->error['code'],
159
- $rest->error['message']
160
- ), E_USER_WARNING);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  return false;
162
  }
163
  return true;
@@ -171,14 +644,49 @@ class S3 {
171
  * @param mixed $md5sum Use MD5 hash (supply a string if you want to use your own)
172
  * @return array | false
173
  */
174
- private static function inputFile($file, $md5sum = true) {
175
- if (!file_exists($file) || !is_file($file) || !is_readable($file)) {
176
- trigger_error('S3::inputFile(): Unable to open input file: '.$file, E_USER_WARNING);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  return false;
178
  }
179
- return array('file' => $file, 'size' => filesize($file),
180
- 'md5sum' => $md5sum !== false ? (is_string($md5sum) ? $md5sum :
181
- base64_encode(md5_file($file, true))) : '');
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
 
184
 
@@ -191,15 +699,19 @@ class S3 {
191
  * @param constant $acl ACL constant
192
  * @param array $metaHeaders Array of x-amz-meta-* headers
193
  * @param array $requestHeaders Array of request headers or content type as a string
 
 
194
  * @return boolean
195
  */
196
- public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) {
 
197
  if ($input === false) return false;
198
- $rest = new S3Request('PUT', $bucket, $uri, self::$__api_host);
199
 
200
- if (is_string($input)) $input = array(
201
  'data' => $input, 'size' => strlen($input),
202
- 'md5sum' => base64_encode(md5($input, true))
 
203
  );
204
 
205
  // Data
@@ -214,33 +726,46 @@ class S3 {
214
  if (isset($input['size']) && $input['size'] >= 0)
215
  $rest->size = $input['size'];
216
  else {
217
- if (isset($input['file']))
 
218
  $rest->size = filesize($input['file']);
 
219
  elseif (isset($input['data']))
220
  $rest->size = strlen($input['data']);
221
  }
222
 
223
  // Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
224
  if (is_array($requestHeaders))
225
- foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
 
226
  elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
227
  $input['type'] = $requestHeaders;
228
 
229
  // Content-Type
230
- if (!isset($input['type'])) {
 
231
  if (isset($requestHeaders['Content-Type']))
232
  $input['type'] =& $requestHeaders['Content-Type'];
233
  elseif (isset($input['file']))
234
- $input['type'] = self::_getMimeType($input['file']);
235
  else
236
  $input['type'] = 'application/octet-stream';
237
  }
238
 
 
 
 
 
 
 
239
  // We need to post with Content-Length and Content-Type, MD5 is optional
240
- if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false)) {
 
241
  $rest->setHeader('Content-Type', $input['type']);
242
  if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
243
 
 
 
244
  $rest->setAmzHeader('x-amz-acl', $acl);
245
  foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
246
  $rest->getResponse();
@@ -249,11 +774,10 @@ class S3 {
249
 
250
  if ($rest->response->error === false && $rest->response->code !== 200)
251
  $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
252
- if ($rest->response->error !== false) {
253
- trigger_error(sprintf("S3::putObject(): [%s] %s",
254
- $rest->response->error['code'],
255
- $rest->response->error['message']
256
- ), E_USER_WARNING);
257
  return false;
258
  }
259
  return true;
@@ -271,7 +795,8 @@ class S3 {
271
  * @param string $contentType Content type
272
  * @return boolean
273
  */
274
- public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null) {
 
275
  return self::putObject(self::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType);
276
  }
277
 
@@ -287,7 +812,8 @@ class S3 {
287
  * @param string $contentType Content type
288
  * @return boolean
289
  */
290
- public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain') {
 
291
  return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
292
  }
293
 
@@ -300,9 +826,11 @@ class S3 {
300
  * @param mixed $saveTo Filename or resource to write to
301
  * @return mixed
302
  */
303
- public static function getObject($bucket, $uri, $saveTo = false) {
304
- $rest = new S3Request('GET', $bucket, $uri, self::$__api_host);
305
- if ($saveTo !== false) {
 
 
306
  if (is_resource($saveTo))
307
  $rest->fp =& $saveTo;
308
  else
@@ -315,14 +843,10 @@ class S3 {
315
 
316
  if ($rest->response->error === false && $rest->response->code !== 200)
317
  $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
318
- if ($rest->response->error !== false) {
319
- trigger_error(sprintf("S3::getObject('%s', '%s', '%s'): [%s] %s",
320
- $bucket,
321
- $uri,
322
- $saveTo,
323
- $rest->response->error['code'],
324
- $rest->response->error['message']
325
- ), E_USER_WARNING);
326
  return false;
327
  }
328
  return $rest->response;
@@ -337,19 +861,16 @@ class S3 {
337
  * @param boolean $returnInfo Return response information
338
  * @return mixed | false
339
  */
340
- public static function getObjectInfo($bucket, $uri, $returnInfo = true) {
341
- $rest = new S3Request('HEAD', $bucket, $uri, self::$__api_host);
 
342
  $rest = $rest->getResponse();
343
  if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
344
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
345
- if ($rest->error !== false) {
346
- trigger_error(sprintf("S3::getObjectInfo('%s', '%s', %d): [%s] %s",
347
- $bucket,
348
- $uri,
349
- $returnInfo,
350
- $rest->error['code'],
351
- $rest->error['message']
352
- ), E_USER_WARNING);
353
  return false;
354
  }
355
  return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
@@ -357,24 +878,674 @@ class S3 {
357
 
358
 
359
  /**
360
- * Delete an object
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  *
362
- * @param string $bucket Bucket name
363
- * @param string $uri Object URI
364
  * @return boolean
365
  */
366
- public static function deleteObject($bucket, $uri) {
367
- $rest = new S3Request('DELETE', $bucket, $uri, self::$__api_host);
368
- $rest = $rest->getResponse();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  if ($rest->error === false && $rest->code !== 204)
370
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
371
- if ($rest->error !== false) {
372
- trigger_error(sprintf("S3::deleteObject('%s', '%s'): [%s] %s",
373
- $bucket,
374
- $uri,
375
- $rest->error['code'],
376
- $rest->error['message']
377
- ), E_USER_WARNING);
378
  return false;
379
  }
380
  return true;
@@ -382,137 +1553,195 @@ class S3 {
382
 
383
 
384
  /**
385
- * Create a CloudFront distribution
386
  *
387
- * @param string $dnsName Origin DNS name
388
- * @param string $originType Origin Type
389
- * @param boolean $enabled Enabled (true/false)
390
- * @param array $cnames Array containing CNAME aliases
391
- * @param string $comment Use the bucket name as the hostname
392
- * @return array | false
393
  */
394
- public static function createDistribution($dnsName, $originType = self::ORIGIN_TYPE_S3, $enabled = true, $cnames = array(), $comment = '') {
395
- self::$use_ssl = true; // CloudFront requires SSL
396
- $rest = new S3Request('POST', '', '2010-11-01/distribution',
397
- 'cloudfront.amazonaws.com');
398
- $rest->data = self::_getCloudFrontDistributionConfigXML($dnsName,
399
- $originType, $enabled, $comment, (string)microtime(true), $cnames);
400
- $rest->size = strlen($rest->data);
401
- $rest->setHeader('Content-Type', 'application/xml');
402
- $rest = self::_getCloudFrontResponse($rest);
403
 
404
- if ($rest->error === false && $rest->code !== 201)
 
 
 
 
 
 
405
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
406
- if ($rest->error !== false) {
407
- trigger_error(sprintf("S3::createDistribution('%s', '%s', %d, '%s', '%s'): [%s] %s",
408
- $dnsName,
409
- $originType,
410
- $enabled,
411
- implode(', ', $cnames),
412
- $comment,
413
- $rest->error['code'],
414
- $rest->error['message']
415
- ), E_USER_WARNING);
416
  return false;
417
- } elseif ($rest->body instanceof SimpleXMLElement)
418
- return self::_parseCloudFrontDistributionConfig($rest->body);
419
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  }
421
 
422
  /**
423
- * Get CloudFront distribution info
424
  *
425
- * @param string $distributionId Distribution ID from listDistributions()
426
- * @return array | false
427
  */
428
- public static function getDistribution($distributionId) {
429
- self::$use_ssl = true; // CloudFront requires SSL
430
- $rest = new S3Request('GET', '',
431
- '2010-11-01/distribution/' . $distributionId,
432
- 'cloudfront.amazonaws.com');
433
- $rest = self::_getCloudFrontResponse($rest);
 
 
 
 
 
 
 
434
 
435
  if ($rest->error === false && $rest->code !== 200)
436
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
437
- if ($rest->error !== false) {
438
- trigger_error(sprintf("S3::getDistribution(%d): [%s] %s",
439
- $distributionId,
440
- $rest->error['code'],
441
- $rest->error['message']
442
- ), E_USER_WARNING);
443
  return false;
444
- } elseif ($rest->body instanceof SimpleXMLElement) {
445
- $dist = self::_parseCloudFrontDistributionConfig($rest->body);
446
- $dist['hash'] = $rest->headers['hash'];
447
- return $dist;
 
 
 
 
 
448
  }
449
  return false;
450
  }
451
 
452
 
453
  /**
454
- * Update a CloudFront distribution
455
  *
456
- * @param array $dist Distribution array info identical to output of getDistribution()
457
- * @return array | false
 
 
 
458
  */
459
- public static function updateDistribution($dist) {
460
- self::$use_ssl = true; // CloudFront requires SSL
461
- $rest = new S3Request('PUT', '',
462
- '2010-11-01/distribution/' . $dist['id'] . '/config',
463
- 'cloudfront.amazonaws.com');
464
- $rest->data = self::_getCloudFrontDistributionConfigXML($dist['origin'], $dist['type'], $dist['enabled'], $dist['comment'], $dist['callerReference'], $dist['cnames']);
 
 
 
 
 
 
 
465
  $rest->size = strlen($rest->data);
466
- $rest->setHeader('If-Match', $dist['hash']);
467
- $rest = self::_getCloudFrontResponse($rest);
468
 
469
- if ($rest->error === false && $rest->code !== 200)
470
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
471
- if ($rest->error !== false) {
472
- trigger_error(sprintf("S3::updateDistribution('%s'): [%s] %s",
473
- serialize($dist),
474
- $rest->error['code'],
475
- $rest->error['message']
476
- ), E_USER_WARNING);
477
  return false;
478
- } else {
479
- $dist = self::_parseCloudFrontDistributionConfig($rest->body);
480
- $dist['hash'] = $rest->headers['hash'];
481
- return $dist;
482
  }
483
- return false;
484
  }
485
 
486
 
487
  /**
488
- * Get a list of CloudFront distributions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
  *
 
490
  * @return array
491
  */
492
- public static function listDistributions() {
493
- self::$use_ssl = true; // CloudFront requires SSL
494
- $rest = new S3Request('GET', '', '2010-11-01/distribution',
495
- 'cloudfront.amazonaws.com');
496
- $rest = self::_getCloudFrontResponse($rest);
 
 
 
 
 
 
 
 
 
497
 
498
  if ($rest->error === false && $rest->code !== 200)
499
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
500
- if ($rest->error !== false) {
501
- trigger_error(sprintf("S3::listDistributions(): [%s] %s",
502
- $rest->error['code'],
503
- $rest->error['message']
504
- ), E_USER_WARNING);
505
  return false;
506
- } elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->DistributionSummary)) {
 
 
507
  $list = array();
508
- if (isset($rest->body->Marker, $rest->body->MaxItems, $rest->body->IsTruncated)) {
509
- //$info['marker'] = (string)$rest->body->Marker;
510
- //$info['maxItems'] = (int)$rest->body->MaxItems;
511
- //$info['isTruncated'] = (string)$rest->body->IsTruncated == 'true' ? true : false;
512
- }
513
- foreach ($rest->body->DistributionSummary as $summary) {
514
- $list[(string)$summary->Id] = self::_parseCloudFrontDistributionConfig($summary);
515
- }
516
  return $list;
517
  }
518
  return array();
@@ -522,45 +1751,56 @@ class S3 {
522
  /**
523
  * Get a DistributionConfig DOMDocument
524
  *
 
 
525
  * @internal Used to create XML in createDistribution() and updateDistribution()
526
- * @param string $dnsName Origin DNS name
527
- * @param string $originType Origin type
528
  * @param boolean $enabled Enabled (true/false)
529
  * @param string $comment Comment to append
530
  * @param string $callerReference Caller reference
531
  * @param array $cnames Array of CNAME aliases
 
 
 
532
  * @return string
533
  */
534
- private static function _getCloudFrontDistributionConfigXML($dnsName, $originType, $enabled, $comment, $callerReference = '0', $cnames = array()) {
 
535
  $dom = new DOMDocument('1.0', 'UTF-8');
536
-
537
- $dom->formatOutput = true;
538
  $distributionConfig = $dom->createElement('DistributionConfig');
539
  $distributionConfig->setAttribute('xmlns', 'http://cloudfront.amazonaws.com/doc/2010-11-01/');
540
 
541
- if ($originType == 's3') {
542
  $origin = $dom->createElement('S3Origin');
543
- $origin->appendChild($dom->createElement('DNSName', $dnsName));
544
  } else {
545
  $origin = $dom->createElement('CustomOrigin');
546
- $origin->appendChild($dom->createElement('DNSName', $dnsName));
547
  $origin->appendChild($dom->createElement('OriginProtocolPolicy', 'http-only'));
548
  }
549
 
 
550
  $distributionConfig->appendChild($origin);
551
- $distributionConfig->appendChild($dom->createElement('CallerReference', $callerReference));
552
 
553
- foreach ($cnames as $cname) {
 
 
 
554
  $distributionConfig->appendChild($dom->createElement('CNAME', $cname));
555
- }
 
556
 
557
- if ($comment !== '') {
558
- $distributionConfig->appendChild($dom->createElement('Comment', $comment));
 
 
 
559
  }
560
 
561
- $distributionConfig->appendChild($dom->createElement('Enabled', $enabled ? 'true' : 'false'));
562
  $dom->appendChild($distributionConfig);
563
-
564
  return $dom->saveXML();
565
  }
566
 
@@ -568,170 +1808,77 @@ class S3 {
568
  /**
569
  * Parse a CloudFront distribution config
570
  *
 
 
571
  * @internal Used to parse the CloudFront DistributionConfig node to an array
572
  * @param object &$node DOMNode
573
  * @return array
574
  */
575
- private static function _parseCloudFrontDistributionConfig(&$node) {
576
- $dist = array();
 
 
577
 
578
- if (isset($node->Id)) {
579
- $dist['id'] = (string) $node->Id;
580
- }
581
-
582
- if (isset($node->Status)) {
583
- $dist['status'] = (string) $node->Status;
584
- }
 
585
 
586
- if (isset($node->LastModifiedTime)) {
587
- $dist['time'] = strtotime((string) $node->LastModifiedTime);
588
- }
589
 
590
- if (isset($node->DomainName)) {
591
- $dist['domain'] = (string) $node->DomainName;
592
- }
593
 
594
- if (isset($node->S3Origin)) {
595
- $dist['type'] = 's3';
 
596
 
597
  if (isset($node->S3Origin->DNSName)) {
598
- $dist['origin'] = (string) $node->S3Origin->DNSName;
599
  }
 
 
 
600
  } elseif (isset($node->CustomOrigin)) {
601
- $dist['type'] = 'custom';
602
 
603
  if (isset($node->CustomOrigin->DNSName)) {
604
  $dist['origin'] = (string) $node->CustomOrigin->DNSName;
605
  }
606
- }
607
-
608
- if (isset($node->CallerReference)) {
609
- $dist['callerReference'] = (string) $node->CallerReference;
610
- }
611
-
612
- if (isset($node->CNAME)) {
613
- $dist['cnames'] = array();
614
-
615
- foreach ($node->CNAME as $cname) {
616
- $dist['cnames'][] = (string) $cname;
617
- }
618
- }
619
-
620
- if (isset($node->Comment)) {
621
- $dist['comment'] = (string) $node->Comment;
622
- }
623
 
624
- if (isset($node->Enabled)) {
625
- $dist['enabled'] = ((string) $node->Enabled == 'true' ? true : false);
626
  }
627
 
628
- if (isset($node->DistributionConfig)) {
629
- $dist = array_merge($dist, self::_parseCloudFrontDistributionConfig($node->DistributionConfig));
630
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
631
 
 
632
  return $dist;
633
  }
634
 
635
 
636
- /**
637
- * Creates invalidation bath
638
- *
639
- * @static
640
- * @param integer $distributionId
641
- * @param array $paths
642
- * @return array|bool
643
- */
644
- public static function createInvalidation($distributionId, $paths) {
645
- self::$use_ssl = true; // CloudFront requires SSL
646
-
647
- $rest = new S3Request('POST', '',
648
- '2010-11-01/distribution/' . $distributionId . '/invalidation',
649
- 'cloudfront.amazonaws.com');
650
-
651
- $rest->data = self::_getCloudFrontInvalidationBath($paths);
652
- $rest->size = strlen($rest->data);
653
- $rest->setHeader('Content-Type', 'application/xml');
654
-
655
- $rest = self::_getCloudFrontResponse($rest);
656
-
657
- if ($rest->error === false && $rest->code !== 201) {
658
- $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
659
- }
660
-
661
- if ($rest->error !== false) {
662
- trigger_error(sprintf("S3::createInvalidation(%d, '%s'): [%s] %s",
663
- $distributionId,
664
- implode(', ', $paths),
665
- $rest->error['code'],
666
- $rest->error['message']
667
- ), E_USER_WARNING);
668
- return false;
669
- } elseif ($rest->body instanceof SimpleXMLElement) {
670
- return self::_parseCloudFrontInvalidation($rest->body);
671
- }
672
-
673
- return false;
674
- }
675
-
676
-
677
- /**
678
- * Returns invalidation bath XML
679
- *
680
- * @static
681
- * @param array $files
682
- * @return string
683
- */
684
- private static function _getCloudFrontInvalidationBath($paths) {
685
- $dom = new DOMDocument('1.0', 'UTF-8');
686
- $dom->formatOutput = true;
687
-
688
- $invalidationBath = $dom->createElement('InvalidationBatch');
689
-
690
- foreach ($paths as $path) {
691
- $invalidationBath->appendChild($dom->createElement('Path', $path));
692
- }
693
-
694
- $invalidationBath->appendChild($dom->createElement('CallerReference', date('YmdHis')));
695
- $dom->appendChild($invalidationBath);
696
-
697
- return $dom->saveXML();
698
- }
699
-
700
-
701
- /**
702
- * Parse CloudFront invalidation XML
703
- *
704
- * @static
705
- * @param DOMNode $node
706
- * @return array
707
- */
708
- private static function _parseCloudFrontInvalidation(&$node) {
709
- $invalidation = array();
710
-
711
- if (isset($node->Id)) {
712
- $invalidation['id'] = $node->Id;
713
- }
714
-
715
- if (isset($node->Status)) {
716
- $invalidation['status'] = $node->Status;
717
- }
718
-
719
- if (isset($node->CreateTime)) {
720
- $invalidation['createTime'] = $node->CreateTime;
721
- }
722
-
723
- if (isset($node->InvalidationBatch)) {
724
- $invalidation['invalidationBath'] = array();
725
-
726
- foreach ($node->InvalidationBatch as $path) {
727
- $invalidation['invalidationBath'][] = $path;
728
- }
729
- }
730
-
731
- return $invalidation;
732
- }
733
-
734
-
735
  /**
736
  * Grab CloudFront response
737
  *
@@ -739,14 +1886,17 @@ class S3 {
739
  * @param object &$rest S3Request instance
740
  * @return object
741
  */
742
- private static function _getCloudFrontResponse(&$rest) {
 
743
  $rest->getResponse();
744
  if ($rest->response->error === false && isset($rest->response->body) &&
745
- is_string($rest->response->body) && substr($rest->response->body, 0, 5) == '<?xml') {
 
746
  $rest->response->body = simplexml_load_string($rest->response->body);
747
  // Grab CloudFront errors
748
  if (isset($rest->response->body->Error, $rest->response->body->Error->Code,
749
- $rest->response->body->Error->Message)) {
 
750
  $rest->response->error = array(
751
  'code' => (string)$rest->response->body->Error->Code,
752
  'message' => (string)$rest->response->body->Error->Message
@@ -761,13 +1911,30 @@ class S3 {
761
  /**
762
  * Get MIME type for file
763
  *
 
 
 
 
764
  * @internal Used to get mime types
765
  * @param string &$file File path
766
  * @return string
767
  */
768
- public static function _getMimeType(&$file) {
769
- $type = Util_Mime::get_mime_type($file);
770
- return $type;
 
 
 
 
 
 
 
 
 
 
 
 
 
771
  }
772
 
773
 
@@ -778,8 +1945,9 @@ class S3 {
778
  * @param string $string String to sign
779
  * @return string
780
  */
781
- public static function _getSignature($string) {
782
- return 'AWS '.self::$__accessKey.':'.self::_getHash($string);
 
783
  }
784
 
785
 
@@ -788,11 +1956,12 @@ class S3 {
788
  *
789
  * This uses the hash extension if loaded
790
  *
791
- * @internal Used by _getSignature()
792
  * @param string $string String to sign
793
  * @return string
794
  */
795
- private static function _getHash($string) {
 
796
  return base64_encode(extension_loaded('hash') ?
797
  hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
798
  (str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
@@ -800,55 +1969,260 @@ class S3 {
800
  (str_repeat(chr(0x36), 64))) . $string)))));
801
  }
802
 
803
- }
804
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
805
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
806
 
807
- class S3Request {
 
 
 
 
 
808
  private $verb;
809
- private $bucket;
810
- private $uri;
811
- private $resource = '';
812
- private $parameters = array();
813
- private $amzHeaders = array();
814
-
815
- public $fp = false;
816
- public $size = 0;
817
- public $data = false;
818
- public $response;
819
- public $headers = array(
820
- 'Host' => '',
821
- 'Date' => '',
822
- 'Content-MD5' => '',
823
- 'Content-Type' => ''
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
824
  );
825
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
  /**
827
  * Constructor
828
  *
829
  * @param string $verb Verb
830
  * @param string $bucket Bucket name
831
  * @param string $uri Object URI
 
832
  * @return mixed
833
  */
834
- function __construct($verb, $bucket = '', $uri = '',
835
- $api_host = 's3.amazonaws.com') {
 
 
836
  $this->verb = $verb;
837
- $this->bucket = strtolower($bucket);
838
  $this->uri = $uri !== '' ? '/'.str_replace('%2F', '/', rawurlencode($uri)) : '/';
839
 
840
- if ($this->bucket !== '') {
841
- $this->headers['Host'] = $this->bucket.'.'.$api_host;
842
- $this->resource = '/'.$this->bucket.$this->uri;
843
- } else {
844
- $this->headers['Host'] = $api_host;
845
- //$this->resource = strlen($this->uri) > 1 ? '/'.$this->bucket.$this->uri : $this->uri;
 
 
 
 
 
 
 
 
 
 
 
 
846
  $this->resource = $this->uri;
847
  }
848
- $this->headers['Date'] = gmdate('D, d M Y H:i:s T');
849
 
 
 
850
  $this->response = new STDClass;
851
  $this->response->error = false;
 
 
852
  }
853
 
854
 
@@ -859,7 +2233,8 @@ class S3Request {
859
  * @param string $value Value
860
  * @return void
861
  */
862
- public function setParameter($key, $value) {
 
863
  $this->parameters[$key] = $value;
864
  }
865
 
@@ -871,7 +2246,8 @@ class S3Request {
871
  * @param string $value Value
872
  * @return void
873
  */
874
- public function setHeader($key, $value) {
 
875
  $this->headers[$key] = $value;
876
  }
877
 
@@ -883,7 +2259,8 @@ class S3Request {
883
  * @param string $value Value
884
  * @return void
885
  */
886
- public function setAmzHeader($key, $value) {
 
887
  $this->amzHeaders[$key] = $value;
888
  }
889
 
@@ -893,13 +2270,14 @@ class S3Request {
893
  *
894
  * @return object | false
895
  */
896
- public function getResponse() {
 
897
  $query = '';
898
- if (sizeof($this->parameters) > 0) {
 
899
  $query = substr($this->uri, -1) !== '?' ? '?' : '&';
900
  foreach ($this->parameters as $var => $value)
901
  if ($value == null || $value == '') $query .= $var.'&';
902
- // Parameters should be encoded (thanks Sean O'Dea)
903
  else $query .= $var.'='.rawurlencode($value).'&';
904
  $query = substr($query, 0, -1);
905
  $this->uri .= $query;
@@ -907,24 +2285,42 @@ class S3Request {
907
  if (array_key_exists('acl', $this->parameters) ||
908
  array_key_exists('location', $this->parameters) ||
909
  array_key_exists('torrent', $this->parameters) ||
 
910
  array_key_exists('logging', $this->parameters))
911
  $this->resource .= $query;
912
  }
913
- $url = ((S3::$use_ssl && extension_loaded('openssl')) ?
914
- 'https://':'http://').$this->headers['Host'].$this->uri;
915
- //var_dump($this->bucket, $this->uri, $this->resource, $url);
916
 
917
  // Basic setup
918
  $curl = curl_init();
919
  curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
920
 
921
- if (S3::$use_ssl) {
922
- curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
923
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
 
 
 
 
 
 
 
 
 
924
  }
925
 
926
  curl_setopt($curl, CURLOPT_URL, $url);
927
 
 
 
 
 
 
 
 
 
928
  // Headers
929
  $headers = array(); $amz = array();
930
  foreach ($this->amzHeaders as $header => $value)
@@ -937,44 +2333,70 @@ class S3Request {
937
  if (strlen($value) > 0) $amz[] = strtolower($header).':'.$value;
938
 
939
  // AMZ headers must be sorted
940
- if (sizeof($amz) > 0) {
941
- sort($amz);
 
 
942
  $amz = "\n".implode("\n", $amz);
943
  } else $amz = '';
944
 
945
- // Authorization string (CloudFront stringToSign should only contain a date)
946
- $headers[] = 'Authorization: ' . S3::_getSignature(
947
- $this->headers['Host'] == 'cloudfront.amazonaws.com' ? $this->headers['Date'] :
948
- $this->verb . "\n" .
949
- $this->headers['Content-MD5'] . "\n" .
950
- $this->headers['Content-Type'] . "\n" .
951
- $this->headers['Date'] .
952
- $amz . "\n" .
953
- $this->resource
954
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
955
 
956
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
957
  curl_setopt($curl, CURLOPT_HEADER, false);
958
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
959
- curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '_responseWriteCallback'));
960
- curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '_responseHeaderCallback'));
961
- @curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
962
 
963
  // Request types
964
- switch ($this->verb) {
 
965
  case 'GET': break;
966
  case 'PUT': case 'POST': // POST only used for CloudFront
967
- if ($this->fp !== false) {
 
968
  curl_setopt($curl, CURLOPT_PUT, true);
969
  curl_setopt($curl, CURLOPT_INFILE, $this->fp);
970
  if ($this->size >= 0)
971
  curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
972
- } elseif ($this->data !== false) {
 
 
973
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
974
  curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
975
- if ($this->size >= 0)
976
- curl_setopt($curl, CURLOPT_BUFFERSIZE, $this->size);
977
- } else
978
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
979
  break;
980
  case 'HEAD':
@@ -1001,12 +2423,14 @@ class S3Request {
1001
 
1002
  // Parse body into XML
1003
  if ($this->response->error === false && isset($this->response->headers['type']) &&
1004
- $this->response->headers['type'] == 'application/xml' && isset($this->response->body)) {
 
1005
  $this->response->body = simplexml_load_string($this->response->body);
1006
 
1007
  // Grab S3 errors
1008
- if (!in_array($this->response->code, array(200, 204)) &&
1009
- isset($this->response->body->Code, $this->response->body->Message)) {
 
1010
  $this->response->error = array(
1011
  'code' => (string)$this->response->body->Code,
1012
  'message' => (string)$this->response->body->Message
@@ -1023,6 +2447,24 @@ class S3Request {
1023
  return $this->response;
1024
  }
1025
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1026
 
1027
  /**
1028
  * CURL write callback
@@ -1031,39 +2473,95 @@ class S3Request {
1031
  * @param string &$data Data
1032
  * @return integer
1033
  */
1034
- private function _responseWriteCallback(&$curl, &$data) {
1035
- if ($this->response->code == 200 && $this->fp !== false)
 
1036
  return fwrite($this->fp, $data);
1037
  else
1038
- $this->response->body .= $data;
 
 
 
 
 
1039
  return strlen($data);
1040
  }
1041
 
1042
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1043
  /**
1044
  * CURL header callback
1045
  *
1046
- * @param resource &$curl CURL resource
1047
- * @param string &$data Data
1048
  * @return integer
1049
  */
1050
- private function _responseHeaderCallback(&$curl, &$data) {
 
1051
  if (($strlen = strlen($data)) <= 2) return $strlen;
1052
  if (substr($data, 0, 4) == 'HTTP')
1053
  $this->response->code = (int)substr($data, 9, 3);
1054
- else {
1055
- list($header, $value) = explode(': ', trim($data), 2);
1056
- if ($header == 'Last-Modified')
 
 
 
 
1057
  $this->response->headers['time'] = strtotime($value);
1058
- elseif ($header == 'Content-Length')
 
 
1059
  $this->response->headers['size'] = (int)$value;
1060
- elseif ($header == 'Content-Type')
1061
  $this->response->headers['type'] = $value;
1062
- elseif ($header == 'ETag')
1063
  $this->response->headers['hash'] = $value{0} == '"' ? substr($value, 1, -1) : $value;
1064
  elseif (preg_match('/^x-amz-meta-.*$/', $header))
1065
- $this->response->headers[$header] = is_numeric($value) ? (int)$value : $value;
1066
  }
1067
  return $strlen;
1068
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1069
  }
1
  <?php
2
  /**
3
+ * $Id$
4
  *
5
+ * Copyright (c) 2013, Donovan Schonknecht. All rights reserved.
6
  *
7
  * Redistribution and use in source and binary forms, with or without
8
  * modification, are permitted provided that the following conditions are met:
32
  * Amazon S3 PHP class
33
  *
34
  * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
35
+ * @version 0.5.1 + Signature v4 support ;)
36
  */
37
+ class S3
38
+ {
39
  // ACL flags
40
  const ACL_PRIVATE = 'private';
41
  const ACL_PUBLIC_READ = 'public-read';
43
  const ACL_AUTHENTICATED_READ = 'authenticated-read';
44
 
45
  const LOCATION_US = '';
 
 
 
46
 
47
+ const ORIGIN_TYPE_S3 = 's3';
48
+ const ORIGIN_TYPE_CUSTOM = 'custom';
49
 
50
+ const STORAGE_CLASS_STANDARD = 'STANDARD';
51
+ const STORAGE_CLASS_RRS = 'REDUCED_REDUNDANCY';
52
+ const STORAGE_CLASS_STANDARD_IA = 'STANDARD_IA';
53
 
54
+ const SSE_NONE = '';
55
+ const SSE_AES256 = 'AES256';
 
56
 
57
+ /**
58
+ * The AWS Access key
59
+ *
60
+ * @var string
61
+ * @access private
62
+ * @static
63
+ */
64
+ private static $__accessKey = null;
65
+
66
+ /**
67
+ * AWS Secret Key
68
+ *
69
+ * @var string
70
+ * @access private
71
+ * @static
72
+ */
73
+ private static $__secretKey = null;
74
+
75
+ /**
76
+ * SSL Client key
77
+ *
78
+ * @var string
79
+ * @access private
80
+ * @static
81
+ */
82
+ private static $__sslKey = null;
83
+
84
+ /**
85
+ * Default delimiter to be used, for example while getBucket().
86
+ * @var string
87
+ * @access public
88
+ * @static
89
+ */
90
+ public static $defDelimiter = null;
91
+
92
+ /**
93
+ * AWS URI
94
+ *
95
+ * @var string
96
+ * @acess public
97
+ * @static
98
+ */
99
+ public static $endpoint = 's3.amazonaws.com';
100
+
101
+ /**
102
+ * AWS Region
103
+ *
104
+ * @var string
105
+ * @acess public
106
+ * @static
107
+ */
108
+ public static $region = '';
109
+
110
+ /**
111
+ * Proxy information
112
+ *
113
+ * @var null|array
114
+ * @access public
115
+ * @static
116
+ */
117
+ public static $proxy = null;
118
+
119
+ /**
120
+ * Connect using SSL?
121
+ *
122
+ * @var bool
123
+ * @access public
124
+ * @static
125
+ */
126
+ public static $useSSL = false;
127
+
128
+ /**
129
+ * Use SSL validation?
130
+ *
131
+ * @var bool
132
+ * @access public
133
+ * @static
134
+ */
135
+ public static $useSSLValidation = true;
136
+
137
+ /**
138
+ * Use SSL version
139
+ *
140
+ * @var const
141
+ * @access public
142
+ * @static
143
+ */
144
+ public static $useSSLVersion = 1; //CURL_SSLVERSION_TLSv1;
145
+
146
+ /**
147
+ * Use PHP exceptions?
148
+ *
149
+ * @var bool
150
+ * @access public
151
+ * @static
152
+ */
153
+ public static $useExceptions = false;
154
+
155
+ /**
156
+ * Time offset applied to time()
157
+ * @access private
158
+ * @static
159
+ */
160
+ private static $__timeOffset = 0;
161
+
162
+ /**
163
+ * SSL client key
164
+ *
165
+ * @var bool
166
+ * @access public
167
+ * @static
168
+ */
169
+ public static $sslKey = null;
170
+
171
+ /**
172
+ * SSL client certfificate
173
+ *
174
+ * @var string
175
+ * @acess public
176
+ * @static
177
+ */
178
+ public static $sslCert = null;
179
+
180
+ /**
181
+ * SSL CA cert (only required if you are having problems with your system CA cert)
182
+ *
183
+ * @var string
184
+ * @access public
185
+ * @static
186
+ */
187
+ public static $sslCACert = null;
188
+
189
+ /**
190
+ * AWS Key Pair ID
191
+ *
192
+ * @var string
193
+ * @access private
194
+ * @static
195
+ */
196
+ private static $__signingKeyPairId = null;
197
+
198
+ /**
199
+ * Key resource, freeSigningKey() must be called to clear it from memory
200
+ *
201
+ * @var bool
202
+ * @access private
203
+ * @static
204
+ */
205
+ private static $__signingKeyResource = false;
206
+
207
+ /**
208
+ * AWS Signature Version
209
+ *
210
+ * @var string
211
+ * @acess public
212
+ * @static
213
+ */
214
+ public static $signVer = 'v4';
215
 
216
  /**
217
  * Constructor - if you're not using the class statically
218
  *
219
  * @param string $accessKey Access key
220
  * @param string $secretKey Secret key
221
+ * @param boolean $useSSL Enable SSL
222
+ * @param string $endpoint Amazon URI
223
  * @return void
224
  */
225
+ public function __construct($accessKey = null, $secretKey = null, $useSSL = false, $endpoint = 's3.amazonaws.com', $region = '')
226
+ {
227
  if ($accessKey !== null && $secretKey !== null)
228
+ self::setAuth($accessKey, $secretKey);
229
+ self::$useSSL = $useSSL;
230
+ self::$endpoint = $endpoint;
231
+ self::$region = $region;
232
+ }
233
+
234
+
235
+ /**
236
+ * Set the service endpoint
237
+ *
238
+ * @param string $host Hostname
239
+ * @return void
240
+ */
241
+ public function setEndpoint($host)
242
+ {
243
+ self::$endpoint = $host;
244
+ }
245
+
246
+
247
+ /**
248
+ * Set the service region
249
+ *
250
+ * @param string $region
251
+ * @return void
252
+ */
253
+ public function setRegion($region)
254
+ {
255
+ self::$region = $region;
256
+ }
257
+
258
+
259
+ /**
260
+ * Get the service region
261
+ *
262
+ * @return string $region
263
+ * @static
264
+ */
265
+ public static function getRegion()
266
+ {
267
+ $region = self::$region;
268
+
269
+ // parse region from endpoint if not specific
270
+ if (empty($region)) {
271
+ if (preg_match("/s3[.-](?:website-|dualstack\.)?(.+)\.amazonaws\.com/i",self::$endpoint,$match) !== 0 && strtolower($match[1]) !== "external-1") {
272
+ $region = $match[1];
273
+ }
274
+ }
275
+
276
+ return empty($region) ? 'us-east-1' : $region;
277
  }
278
 
279
 
284
  * @param string $secretKey Secret key
285
  * @return void
286
  */
287
+ public static function setAuth($accessKey, $secretKey)
288
+ {
289
  self::$__accessKey = $accessKey;
290
  self::$__secretKey = $secretKey;
291
  }
292
 
293
 
294
+ /**
295
+ * Check if AWS keys have been set
296
+ *
297
+ * @return boolean
298
+ */
299
+ public static function hasAuth() {
300
+ return (self::$__accessKey !== null && self::$__secretKey !== null);
301
+ }
302
+
303
+
304
+ /**
305
+ * Set SSL on or off
306
+ *
307
+ * @param boolean $enabled SSL enabled
308
+ * @param boolean $validate SSL certificate validation
309
+ * @return void
310
+ */
311
+ public static function setSSL($enabled, $validate = true)
312
+ {
313
+ self::$useSSL = $enabled;
314
+ self::$useSSLValidation = $validate;
315
+ }
316
+
317
+
318
+ /**
319
+ * Set SSL client certificates (experimental)
320
+ *
321
+ * @param string $sslCert SSL client certificate
322
+ * @param string $sslKey SSL client key
323
+ * @param string $sslCACert SSL CA cert (only required if you are having problems with your system CA cert)
324
+ * @return void
325
+ */
326
+ public static function setSSLAuth($sslCert = null, $sslKey = null, $sslCACert = null)
327
+ {
328
+ self::$sslCert = $sslCert;
329
+ self::$sslKey = $sslKey;
330
+ self::$sslCACert = $sslCACert;
331
+ }
332
+
333
+
334
+ /**
335
+ * Set proxy information
336
+ *
337
+ * @param string $host Proxy hostname and port (localhost:1234)
338
+ * @param string $user Proxy username
339
+ * @param string $pass Proxy password
340
+ * @param constant $type CURL proxy type
341
+ * @return void
342
+ */
343
+ public static function setProxy($host, $user = null, $pass = null, $type = CURLPROXY_SOCKS5)
344
+ {
345
+ self::$proxy = array('host' => $host, 'type' => $type, 'user' => $user, 'pass' => $pass);
346
+ }
347
+
348
+
349
+ /**
350
+ * Set the error mode to exceptions
351
+ *
352
+ * @param boolean $enabled Enable exceptions
353
+ * @return void
354
+ */
355
+ public static function setExceptions($enabled = true)
356
+ {
357
+ self::$useExceptions = $enabled;
358
+ }
359
+
360
+
361
+ /**
362
+ * Set AWS time correction offset (use carefully)
363
+ *
364
+ * This can be used when an inaccurate system time is generating
365
+ * invalid request signatures. It should only be used as a last
366
+ * resort when the system time cannot be changed.
367
+ *
368
+ * @param string $offset Time offset (set to zero to use AWS server time)
369
+ * @return void
370
+ */
371
+ public static function setTimeCorrectionOffset($offset = 0)
372
+ {
373
+ if ($offset == 0)
374
+ {
375
+ $rest = new S3Request('HEAD');
376
+ $rest = $rest->getResponse();
377
+ $awstime = $rest->headers['date'];
378
+ $systime = time();
379
+ $offset = $systime > $awstime ? -($systime - $awstime) : ($awstime - $systime);
380
+ }
381
+ self::$__timeOffset = $offset;
382
+ }
383
+
384
+
385
+ /**
386
+ * Set signing key
387
+ *
388
+ * @param string $keyPairId AWS Key Pair ID
389
+ * @param string $signingKey Private Key
390
+ * @param boolean $isFile Load private key from file, set to false to load string
391
+ * @return boolean
392
+ */
393
+ public static function setSigningKey($keyPairId, $signingKey, $isFile = true)
394
+ {
395
+ self::$__signingKeyPairId = $keyPairId;
396
+ if ((self::$__signingKeyResource = openssl_pkey_get_private($isFile ?
397
+ file_get_contents($signingKey) : $signingKey)) !== false) return true;
398
+ self::triggerError('S3::setSigningKey(): Unable to open load private key: '.$signingKey, __FILE__, __LINE__);
399
+ return false;
400
+ }
401
+
402
+
403
+ /**
404
+ * Set Signature Version
405
+ *
406
+ * @param string $version of signature ('v4' or 'v2')
407
+ * @return void
408
+ */
409
+ public static function setSignatureVersion($version = 'v2')
410
+ {
411
+ self::$signVer = $version;
412
+ }
413
+
414
+
415
+ /**
416
+ * Free signing key from memory, MUST be called if you are using setSigningKey()
417
+ *
418
+ * @return void
419
+ */
420
+ public static function freeSigningKey()
421
+ {
422
+ if (self::$__signingKeyResource !== false)
423
+ openssl_free_key(self::$__signingKeyResource);
424
+ }
425
+
426
+
427
+ /**
428
+ * Internal error handler
429
+ *
430
+ * @internal Internal error handler
431
+ * @param string $message Error message
432
+ * @param string $file Filename
433
+ * @param integer $line Line number
434
+ * @param integer $code Error code
435
+ * @return void
436
+ */
437
+ private static function triggerError($message, $file, $line, $code = 0)
438
+ {
439
+ if (self::$useExceptions)
440
+ throw new S3Exception($message, $file, $line, $code);
441
+ else
442
+ trigger_error($message, E_USER_WARNING);
443
+ }
444
+
445
+
446
  /**
447
  * Get a list of buckets
448
  *
449
  * @param boolean $detailed Returns detailed bucket list when true
450
  * @return array | false
451
  */
452
+ public static function listBuckets($detailed = false)
453
+ {
454
+ $rest = new S3Request('GET', '', '', self::$endpoint);
455
  $rest = $rest->getResponse();
456
  if ($rest->error === false && $rest->code !== 200)
457
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
458
+ if ($rest->error !== false)
459
+ {
460
+ self::triggerError(sprintf("S3::listBuckets(): [%s] %s", $rest->error['code'],
461
+ $rest->error['message']), __FILE__, __LINE__);
 
462
  return false;
463
  }
464
  $results = array();
465
  if (!isset($rest->body->Buckets)) return $results;
466
 
467
+ if ($detailed)
468
+ {
469
  if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
470
  $results['owner'] = array(
471
+ 'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
472
  );
473
  $results['buckets'] = array();
474
  foreach ($rest->body->Buckets->Bucket as $b)
482
  }
483
 
484
 
485
+ /**
486
+ * Get contents for a bucket
487
+ *
488
+ * If maxKeys is null this method will loop through truncated result sets
489
+ *
490
+ * @param string $bucket Bucket name
491
+ * @param string $prefix Prefix
492
+ * @param string $marker Marker (last file listed)
493
+ * @param string $maxKeys Max keys (maximum number of keys to return)
494
+ * @param string $delimiter Delimiter
495
+ * @param boolean $returnCommonPrefixes Set to true to return CommonPrefixes
496
+ * @return array | false
497
+ */
498
+ public static function getBucket($bucket, $prefix = null, $marker = null, $maxKeys = null, $delimiter = null, $returnCommonPrefixes = false)
499
+ {
500
+ $rest = new S3Request('GET', $bucket, '', self::$endpoint);
501
+ if ($maxKeys == 0) $maxKeys = null;
502
+ if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
503
+ if ($marker !== null && $marker !== '') $rest->setParameter('marker', $marker);
504
+ if ($maxKeys !== null && $maxKeys !== '') $rest->setParameter('max-keys', $maxKeys);
505
+ if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
506
+ else if (!empty(self::$defDelimiter)) $rest->setParameter('delimiter', self::$defDelimiter);
507
+ $response = $rest->getResponse();
508
+ if ($response->error === false && $response->code !== 200)
509
+ $response->error = array('code' => $response->code, 'message' => 'Unexpected HTTP status');
510
+ if ($response->error !== false)
511
+ {
512
+ self::triggerError(sprintf("S3::getBucket(): [%s] %s",
513
+ $response->error['code'], $response->error['message']), __FILE__, __LINE__);
514
+ return false;
515
+ }
516
+
517
+ $results = array();
518
+
519
+ $nextMarker = null;
520
+ if (isset($response->body, $response->body->Contents))
521
+ foreach ($response->body->Contents as $c)
522
+ {
523
+ $results[(string)$c->Key] = array(
524
+ 'name' => (string)$c->Key,
525
+ 'time' => strtotime((string)$c->LastModified),
526
+ 'size' => (int)$c->Size,
527
+ 'hash' => substr((string)$c->ETag, 1, -1)
528
+ );
529
+ $nextMarker = (string)$c->Key;
530
+ }
531
+
532
+ if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
533
+ foreach ($response->body->CommonPrefixes as $c)
534
+ $results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
535
+
536
+ if (isset($response->body, $response->body->IsTruncated) &&
537
+ (string)$response->body->IsTruncated == 'false') return $results;
538
+
539
+ if (isset($response->body, $response->body->NextMarker))
540
+ $nextMarker = (string)$response->body->NextMarker;
541
+
542
+ // Loop through truncated results if maxKeys isn't specified
543
+ if ($maxKeys == null && $nextMarker !== null && (string)$response->body->IsTruncated == 'true')
544
+ do
545
+ {
546
+ $rest = new S3Request('GET', $bucket, '', self::$endpoint);
547
+ if ($prefix !== null && $prefix !== '') $rest->setParameter('prefix', $prefix);
548
+ $rest->setParameter('marker', $nextMarker);
549
+ if ($delimiter !== null && $delimiter !== '') $rest->setParameter('delimiter', $delimiter);
550
+
551
+ if (($response = $rest->getResponse()) == false || $response->code !== 200) break;
552
+
553
+ if (isset($response->body, $response->body->Contents))
554
+ foreach ($response->body->Contents as $c)
555
+ {
556
+ $results[(string)$c->Key] = array(
557
+ 'name' => (string)$c->Key,
558
+ 'time' => strtotime((string)$c->LastModified),
559
+ 'size' => (int)$c->Size,
560
+ 'hash' => substr((string)$c->ETag, 1, -1)
561
+ );
562
+ $nextMarker = (string)$c->Key;
563
+ }
564
+
565
+ if ($returnCommonPrefixes && isset($response->body, $response->body->CommonPrefixes))
566
+ foreach ($response->body->CommonPrefixes as $c)
567
+ $results[(string)$c->Prefix] = array('prefix' => (string)$c->Prefix);
568
+
569
+ if (isset($response->body, $response->body->NextMarker))
570
+ $nextMarker = (string)$response->body->NextMarker;
571
+
572
+ } while ($response !== false && (string)$response->body->IsTruncated == 'true');
573
+
574
+ return $results;
575
+ }
576
+
577
+
578
  /**
579
  * Put a bucket
580
  *
583
  * @param string $location Set as "EU" to create buckets hosted in Europe
584
  * @return boolean
585
  */
586
+ public static function putBucket($bucket, $acl = self::ACL_PRIVATE, $location = false)
587
+ {
588
+ $rest = new S3Request('PUT', $bucket, '', self::$endpoint);
589
  $rest->setAmzHeader('x-amz-acl', $acl);
590
 
591
+ if (empty($location)) $location = self::getRegion();
592
+
593
+ if ($location !== false && $location !== "us-east-1")
594
+ {
595
  $dom = new DOMDocument;
596
  $createBucketConfiguration = $dom->createElement('CreateBucketConfiguration');
597
  $locationConstraint = $dom->createElement('LocationConstraint', $location);
605
 
606
  if ($rest->error === false && $rest->code !== 200)
607
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
608
+ if ($rest->error !== false)
609
+ {
610
+ self::triggerError(sprintf("S3::putBucket({$bucket}, {$acl}, {$location}): [%s] %s",
611
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
612
+ return false;
613
+ }
614
+ return true;
615
+ }
616
+
617
+
618
+ /**
619
+ * Delete an empty bucket
620
+ *
621
+ * @param string $bucket Bucket name
622
+ * @return boolean
623
+ */
624
+ public static function deleteBucket($bucket)
625
+ {
626
+ $rest = new S3Request('DELETE', $bucket, '', self::$endpoint);
627
+ $rest = $rest->getResponse();
628
+ if ($rest->error === false && $rest->code !== 204)
629
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
630
+ if ($rest->error !== false)
631
+ {
632
+ self::triggerError(sprintf("S3::deleteBucket({$bucket}): [%s] %s",
633
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
634
  return false;
635
  }
636
  return true;
644
  * @param mixed $md5sum Use MD5 hash (supply a string if you want to use your own)
645
  * @return array | false
646
  */
647
+ public static function inputFile($file, $md5sum = true)
648
+ {
649
+ if (!file_exists($file) || !is_file($file) || !is_readable($file))
650
+ {
651
+ self::triggerError('S3::inputFile(): Unable to open input file: '.$file, __FILE__, __LINE__);
652
+ return false;
653
+ }
654
+ clearstatcache(false, $file);
655
+ return array('file' => $file, 'size' => filesize($file), 'md5sum' => $md5sum !== false ?
656
+ (is_string($md5sum) ? $md5sum : base64_encode(md5_file($file, true))) : '', 'sha256sum' => hash_file('sha256', $file));
657
+ }
658
+
659
+
660
+ /**
661
+ * Create input array info for putObject() with a resource
662
+ *
663
+ * @param string $resource Input resource to read from
664
+ * @param integer $bufferSize Input byte size
665
+ * @param string $md5sum MD5 hash to send (optional)
666
+ * @return array | false
667
+ */
668
+ public static function inputResource(&$resource, $bufferSize = false, $md5sum = '')
669
+ {
670
+ if (!is_resource($resource) || (int)$bufferSize < 0)
671
+ {
672
+ self::triggerError('S3::inputResource(): Invalid resource or buffer size', __FILE__, __LINE__);
673
  return false;
674
  }
675
+
676
+ // Try to figure out the bytesize
677
+ if ($bufferSize === false)
678
+ {
679
+ if (fseek($resource, 0, SEEK_END) < 0 || ($bufferSize = ftell($resource)) === false)
680
+ {
681
+ self::triggerError('S3::inputResource(): Unable to obtain resource size', __FILE__, __LINE__);
682
+ return false;
683
+ }
684
+ fseek($resource, 0);
685
+ }
686
+
687
+ $input = array('size' => $bufferSize, 'md5sum' => $md5sum);
688
+ $input['fp'] =& $resource;
689
+ return $input;
690
  }
691
 
692
 
699
  * @param constant $acl ACL constant
700
  * @param array $metaHeaders Array of x-amz-meta-* headers
701
  * @param array $requestHeaders Array of request headers or content type as a string
702
+ * @param constant $storageClass Storage class constant
703
+ * @param constant $serverSideEncryption Server-side encryption
704
  * @return boolean
705
  */
706
+ public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD, $serverSideEncryption = self::SSE_NONE)
707
+ {
708
  if ($input === false) return false;
709
+ $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint);
710
 
711
+ if (!is_array($input)) $input = array(
712
  'data' => $input, 'size' => strlen($input),
713
+ 'md5sum' => base64_encode(md5($input, true)),
714
+ 'sha256sum' => hash('sha256', $input)
715
  );
716
 
717
  // Data
726
  if (isset($input['size']) && $input['size'] >= 0)
727
  $rest->size = $input['size'];
728
  else {
729
+ if (isset($input['file'])) {
730
+ clearstatcache(false, $input['file']);
731
  $rest->size = filesize($input['file']);
732
+ }
733
  elseif (isset($input['data']))
734
  $rest->size = strlen($input['data']);
735
  }
736
 
737
  // Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
738
  if (is_array($requestHeaders))
739
+ foreach ($requestHeaders as $h => $v)
740
+ strpos($h, 'x-amz-') === 0 ? $rest->setAmzHeader($h, $v) : $rest->setHeader($h, $v);
741
  elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
742
  $input['type'] = $requestHeaders;
743
 
744
  // Content-Type
745
+ if (!isset($input['type']))
746
+ {
747
  if (isset($requestHeaders['Content-Type']))
748
  $input['type'] =& $requestHeaders['Content-Type'];
749
  elseif (isset($input['file']))
750
+ $input['type'] = self::getMIMEType($input['file']);
751
  else
752
  $input['type'] = 'application/octet-stream';
753
  }
754
 
755
+ if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
756
+ $rest->setAmzHeader('x-amz-storage-class', $storageClass);
757
+
758
+ if ($serverSideEncryption !== self::SSE_NONE) // Server-side encryption
759
+ $rest->setAmzHeader('x-amz-server-side-encryption', $serverSideEncryption);
760
+
761
  // We need to post with Content-Length and Content-Type, MD5 is optional
762
+ if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false))
763
+ {
764
  $rest->setHeader('Content-Type', $input['type']);
765
  if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);
766
 
767
+ if (isset($input['sha256sum'])) $rest->setAmzHeader('x-amz-content-sha256', $input['sha256sum']);
768
+
769
  $rest->setAmzHeader('x-amz-acl', $acl);
770
  foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
771
  $rest->getResponse();
774
 
775
  if ($rest->response->error === false && $rest->response->code !== 200)
776
  $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
777
+ if ($rest->response->error !== false)
778
+ {
779
+ self::triggerError(sprintf("S3::putObject(): [%s] %s",
780
+ $rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
 
781
  return false;
782
  }
783
  return true;
795
  * @param string $contentType Content type
796
  * @return boolean
797
  */
798
+ public static function putObjectFile($file, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = null)
799
+ {
800
  return self::putObject(self::inputFile($file), $bucket, $uri, $acl, $metaHeaders, $contentType);
801
  }
802
 
812
  * @param string $contentType Content type
813
  * @return boolean
814
  */
815
+ public static function putObjectString($string, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $contentType = 'text/plain')
816
+ {
817
  return self::putObject($string, $bucket, $uri, $acl, $metaHeaders, $contentType);
818
  }
819
 
826
  * @param mixed $saveTo Filename or resource to write to
827
  * @return mixed
828
  */
829
+ public static function getObject($bucket, $uri, $saveTo = false)
830
+ {
831
+ $rest = new S3Request('GET', $bucket, $uri, self::$endpoint);
832
+ if ($saveTo !== false)
833
+ {
834
  if (is_resource($saveTo))
835
  $rest->fp =& $saveTo;
836
  else
843
 
844
  if ($rest->response->error === false && $rest->response->code !== 200)
845
  $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
846
+ if ($rest->response->error !== false)
847
+ {
848
+ self::triggerError(sprintf("S3::getObject({$bucket}, {$uri}): [%s] %s",
849
+ $rest->response->error['code'], $rest->response->error['message']), __FILE__, __LINE__);
 
 
 
 
850
  return false;
851
  }
852
  return $rest->response;
861
  * @param boolean $returnInfo Return response information
862
  * @return mixed | false
863
  */
864
+ public static function getObjectInfo($bucket, $uri, $returnInfo = true)
865
+ {
866
+ $rest = new S3Request('HEAD', $bucket, $uri, self::$endpoint);
867
  $rest = $rest->getResponse();
868
  if ($rest->error === false && ($rest->code !== 200 && $rest->code !== 404))
869
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
870
+ if ($rest->error !== false)
871
+ {
872
+ self::triggerError(sprintf("S3::getObjectInfo({$bucket}, {$uri}): [%s] %s",
873
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
 
 
 
 
874
  return false;
875
  }
876
  return $rest->code == 200 ? $returnInfo ? $rest->headers : true : false;
878
 
879
 
880
  /**
881
+ * Copy an object
882
+ *
883
+ * @param string $srcBucket Source bucket name
884
+ * @param string $srcUri Source object URI
885
+ * @param string $bucket Destination bucket name
886
+ * @param string $uri Destination object URI
887
+ * @param constant $acl ACL constant
888
+ * @param array $metaHeaders Optional array of x-amz-meta-* headers
889
+ * @param array $requestHeaders Optional array of request headers (content type, disposition, etc.)
890
+ * @param constant $storageClass Storage class constant
891
+ * @return mixed | false
892
+ */
893
+ public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array(), $storageClass = self::STORAGE_CLASS_STANDARD)
894
+ {
895
+ $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint);
896
+ $rest->setHeader('Content-Length', 0);
897
+ foreach ($requestHeaders as $h => $v)
898
+ strpos($h, 'x-amz-') === 0 ? $rest->setAmzHeader($h, $v) : $rest->setHeader($h, $v);
899
+ foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
900
+ if ($storageClass !== self::STORAGE_CLASS_STANDARD) // Storage class
901
+ $rest->setAmzHeader('x-amz-storage-class', $storageClass);
902
+ $rest->setAmzHeader('x-amz-acl', $acl);
903
+ $rest->setAmzHeader('x-amz-copy-source', sprintf('/%s/%s', $srcBucket, rawurlencode($srcUri)));
904
+ if (sizeof($requestHeaders) > 0 || sizeof($metaHeaders) > 0)
905
+ $rest->setAmzHeader('x-amz-metadata-directive', 'REPLACE');
906
+
907
+ $rest = $rest->getResponse();
908
+ if ($rest->error === false && $rest->code !== 200)
909
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
910
+ if ($rest->error !== false)
911
+ {
912
+ self::triggerError(sprintf("S3::copyObject({$srcBucket}, {$srcUri}, {$bucket}, {$uri}): [%s] %s",
913
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
914
+ return false;
915
+ }
916
+ return isset($rest->body->LastModified, $rest->body->ETag) ? array(
917
+ 'time' => strtotime((string)$rest->body->LastModified),
918
+ 'hash' => substr((string)$rest->body->ETag, 1, -1)
919
+ ) : false;
920
+ }
921
+
922
+
923
+ /**
924
+ * Set up a bucket redirection
925
+ *
926
+ * @param string $bucket Bucket name
927
+ * @param string $location Target host name
928
+ * @return boolean
929
+ */
930
+ public static function setBucketRedirect($bucket = NULL, $location = NULL)
931
+ {
932
+ $rest = new S3Request('PUT', $bucket, '', self::$endpoint);
933
+
934
+ if( empty($bucket) || empty($location) ) {
935
+ self::triggerError("S3::setBucketRedirect({$bucket}, {$location}): Empty parameter.", __FILE__, __LINE__);
936
+ return false;
937
+ }
938
+
939
+ $dom = new DOMDocument;
940
+ $websiteConfiguration = $dom->createElement('WebsiteConfiguration');
941
+ $redirectAllRequestsTo = $dom->createElement('RedirectAllRequestsTo');
942
+ $hostName = $dom->createElement('HostName', $location);
943
+ $redirectAllRequestsTo->appendChild($hostName);
944
+ $websiteConfiguration->appendChild($redirectAllRequestsTo);
945
+ $dom->appendChild($websiteConfiguration);
946
+ $rest->setParameter('website', null);
947
+ $rest->data = $dom->saveXML();
948
+ $rest->size = strlen($rest->data);
949
+ $rest->setHeader('Content-Type', 'application/xml');
950
+ $rest = $rest->getResponse();
951
+
952
+ if ($rest->error === false && $rest->code !== 200)
953
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
954
+ if ($rest->error !== false)
955
+ {
956
+ self::triggerError(sprintf("S3::setBucketRedirect({$bucket}, {$location}): [%s] %s",
957
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
958
+ return false;
959
+ }
960
+ return true;
961
+ }
962
+
963
+
964
+ /**
965
+ * Set logging for a bucket
966
+ *
967
+ * @param string $bucket Bucket name
968
+ * @param string $targetBucket Target bucket (where logs are stored)
969
+ * @param string $targetPrefix Log prefix (e,g; domain.com-)
970
+ * @return boolean
971
+ */
972
+ public static function setBucketLogging($bucket, $targetBucket, $targetPrefix = null)
973
+ {
974
+ // The S3 log delivery group has to be added to the target bucket's ACP
975
+ if ($targetBucket !== null && ($acp = self::getAccessControlPolicy($targetBucket, '')) !== false)
976
+ {
977
+ // Only add permissions to the target bucket when they do not exist
978
+ $aclWriteSet = false;
979
+ $aclReadSet = false;
980
+ foreach ($acp['acl'] as $acl)
981
+ if ($acl['type'] == 'Group' && $acl['uri'] == 'http://acs.amazonaws.com/groups/s3/LogDelivery')
982
+ {
983
+ if ($acl['permission'] == 'WRITE') $aclWriteSet = true;
984
+ elseif ($acl['permission'] == 'READ_ACP') $aclReadSet = true;
985
+ }
986
+ if (!$aclWriteSet) $acp['acl'][] = array(
987
+ 'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'WRITE'
988
+ );
989
+ if (!$aclReadSet) $acp['acl'][] = array(
990
+ 'type' => 'Group', 'uri' => 'http://acs.amazonaws.com/groups/s3/LogDelivery', 'permission' => 'READ_ACP'
991
+ );
992
+ if (!$aclReadSet || !$aclWriteSet) self::setAccessControlPolicy($targetBucket, '', $acp);
993
+ }
994
+
995
+ $dom = new DOMDocument;
996
+ $bucketLoggingStatus = $dom->createElement('BucketLoggingStatus');
997
+ $bucketLoggingStatus->setAttribute('xmlns', 'http://s3.amazonaws.com/doc/2006-03-01/');
998
+ if ($targetBucket !== null)
999
+ {
1000
+ if ($targetPrefix == null) $targetPrefix = $bucket . '-';
1001
+ $loggingEnabled = $dom->createElement('LoggingEnabled');
1002
+ $loggingEnabled->appendChild($dom->createElement('TargetBucket', $targetBucket));
1003
+ $loggingEnabled->appendChild($dom->createElement('TargetPrefix', $targetPrefix));
1004
+ // TODO: Add TargetGrants?
1005
+ $bucketLoggingStatus->appendChild($loggingEnabled);
1006
+ }
1007
+ $dom->appendChild($bucketLoggingStatus);
1008
+
1009
+ $rest = new S3Request('PUT', $bucket, '', self::$endpoint);
1010
+ $rest->setParameter('logging', null);
1011
+ $rest->data = $dom->saveXML();
1012
+ $rest->size = strlen($rest->data);
1013
+ $rest->setHeader('Content-Type', 'application/xml');
1014
+ $rest = $rest->getResponse();
1015
+ if ($rest->error === false && $rest->code !== 200)
1016
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1017
+ if ($rest->error !== false)
1018
+ {
1019
+ self::triggerError(sprintf("S3::setBucketLogging({$bucket}, {$targetBucket}): [%s] %s",
1020
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1021
+ return false;
1022
+ }
1023
+ return true;
1024
+ }
1025
+
1026
+
1027
+ /**
1028
+ * Get logging status for a bucket
1029
+ *
1030
+ * This will return false if logging is not enabled.
1031
+ * Note: To enable logging, you also need to grant write access to the log group
1032
+ *
1033
+ * @param string $bucket Bucket name
1034
+ * @return array | false
1035
+ */
1036
+ public static function getBucketLogging($bucket)
1037
+ {
1038
+ $rest = new S3Request('GET', $bucket, '', self::$endpoint);
1039
+ $rest->setParameter('logging', null);
1040
+ $rest = $rest->getResponse();
1041
+ if ($rest->error === false && $rest->code !== 200)
1042
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1043
+ if ($rest->error !== false)
1044
+ {
1045
+ self::triggerError(sprintf("S3::getBucketLogging({$bucket}): [%s] %s",
1046
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1047
+ return false;
1048
+ }
1049
+ if (!isset($rest->body->LoggingEnabled)) return false; // No logging
1050
+ return array(
1051
+ 'targetBucket' => (string)$rest->body->LoggingEnabled->TargetBucket,
1052
+ 'targetPrefix' => (string)$rest->body->LoggingEnabled->TargetPrefix,
1053
+ );
1054
+ }
1055
+
1056
+
1057
+ /**
1058
+ * Disable bucket logging
1059
+ *
1060
+ * @param string $bucket Bucket name
1061
+ * @return boolean
1062
+ */
1063
+ public static function disableBucketLogging($bucket)
1064
+ {
1065
+ return self::setBucketLogging($bucket, null);
1066
+ }
1067
+
1068
+
1069
+ /**
1070
+ * Get a bucket's location
1071
+ *
1072
+ * @param string $bucket Bucket name
1073
+ * @return string | false
1074
+ */
1075
+ public static function getBucketLocation($bucket)
1076
+ {
1077
+ $rest = new S3Request('GET', $bucket, '', self::$endpoint);
1078
+ $rest->setParameter('location', null);
1079
+ $rest = $rest->getResponse();
1080
+ if ($rest->error === false && $rest->code !== 200)
1081
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1082
+ if ($rest->error !== false)
1083
+ {
1084
+ self::triggerError(sprintf("S3::getBucketLocation({$bucket}): [%s] %s",
1085
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1086
+ return false;
1087
+ }
1088
+ return (isset($rest->body[0]) && (string)$rest->body[0] !== '') ? (string)$rest->body[0] : 'US';
1089
+ }
1090
+
1091
+
1092
+ /**
1093
+ * Set object or bucket Access Control Policy
1094
+ *
1095
+ * @param string $bucket Bucket name
1096
+ * @param string $uri Object URI
1097
+ * @param array $acp Access Control Policy Data (same as the data returned from getAccessControlPolicy)
1098
+ * @return boolean
1099
+ */
1100
+ public static function setAccessControlPolicy($bucket, $uri = '', $acp = array())
1101
+ {
1102
+ $dom = new DOMDocument;
1103
+ $dom->formatOutput = true;
1104
+ $accessControlPolicy = $dom->createElement('AccessControlPolicy');
1105
+ $accessControlList = $dom->createElement('AccessControlList');
1106
+
1107
+ // It seems the owner has to be passed along too
1108
+ $owner = $dom->createElement('Owner');
1109
+ $owner->appendChild($dom->createElement('ID', $acp['owner']['id']));
1110
+ $owner->appendChild($dom->createElement('DisplayName', $acp['owner']['name']));
1111
+ $accessControlPolicy->appendChild($owner);
1112
+
1113
+ foreach ($acp['acl'] as $g)
1114
+ {
1115
+ $grant = $dom->createElement('Grant');
1116
+ $grantee = $dom->createElement('Grantee');
1117
+ $grantee->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
1118
+ if (isset($g['id']))
1119
+ { // CanonicalUser (DisplayName is omitted)
1120
+ $grantee->setAttribute('xsi:type', 'CanonicalUser');
1121
+ $grantee->appendChild($dom->createElement('ID', $g['id']));
1122
+ }
1123
+ elseif (isset($g['email']))
1124
+ { // AmazonCustomerByEmail
1125
+ $grantee->setAttribute('xsi:type', 'AmazonCustomerByEmail');
1126
+ $grantee->appendChild($dom->createElement('EmailAddress', $g['email']));
1127
+ }
1128
+ elseif ($g['type'] == 'Group')
1129
+ { // Group
1130
+ $grantee->setAttribute('xsi:type', 'Group');
1131
+ $grantee->appendChild($dom->createElement('URI', $g['uri']));
1132
+ }
1133
+ $grant->appendChild($grantee);
1134
+ $grant->appendChild($dom->createElement('Permission', $g['permission']));
1135
+ $accessControlList->appendChild($grant);
1136
+ }
1137
+
1138
+ $accessControlPolicy->appendChild($accessControlList);
1139
+ $dom->appendChild($accessControlPolicy);
1140
+
1141
+ $rest = new S3Request('PUT', $bucket, $uri, self::$endpoint);
1142
+ $rest->setParameter('acl', null);
1143
+ $rest->data = $dom->saveXML();
1144
+ $rest->size = strlen($rest->data);
1145
+ $rest->setHeader('Content-Type', 'application/xml');
1146
+ $rest = $rest->getResponse();
1147
+ if ($rest->error === false && $rest->code !== 200)
1148
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1149
+ if ($rest->error !== false)
1150
+ {
1151
+ self::triggerError(sprintf("S3::setAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
1152
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1153
+ return false;
1154
+ }
1155
+ return true;
1156
+ }
1157
+
1158
+
1159
+ /**
1160
+ * Get object or bucket Access Control Policy
1161
+ *
1162
+ * @param string $bucket Bucket name
1163
+ * @param string $uri Object URI
1164
+ * @return mixed | false
1165
+ */
1166
+ public static function getAccessControlPolicy($bucket, $uri = '')
1167
+ {
1168
+ $rest = new S3Request('GET', $bucket, $uri, self::$endpoint);
1169
+ $rest->setParameter('acl', null);
1170
+ $rest = $rest->getResponse();
1171
+ if ($rest->error === false && $rest->code !== 200)
1172
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1173
+ if ($rest->error !== false)
1174
+ {
1175
+ self::triggerError(sprintf("S3::getAccessControlPolicy({$bucket}, {$uri}): [%s] %s",
1176
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1177
+ return false;
1178
+ }
1179
+
1180
+ $acp = array();
1181
+ if (isset($rest->body->Owner, $rest->body->Owner->ID, $rest->body->Owner->DisplayName))
1182
+ $acp['owner'] = array(
1183
+ 'id' => (string)$rest->body->Owner->ID, 'name' => (string)$rest->body->Owner->DisplayName
1184
+ );
1185
+
1186
+ if (isset($rest->body->AccessControlList))
1187
+ {
1188
+ $acp['acl'] = array();
1189
+ foreach ($rest->body->AccessControlList->Grant as $grant)
1190
+ {
1191
+ foreach ($grant->Grantee as $grantee)
1192
+ {
1193
+ if (isset($grantee->ID, $grantee->DisplayName)) // CanonicalUser
1194
+ $acp['acl'][] = array(
1195
+ 'type' => 'CanonicalUser',
1196
+ 'id' => (string)$grantee->ID,
1197
+ 'name' => (string)$grantee->DisplayName,
1198
+ 'permission' => (string)$grant->Permission
1199
+ );
1200
+ elseif (isset($grantee->EmailAddress)) // AmazonCustomerByEmail
1201
+ $acp['acl'][] = array(
1202
+ 'type' => 'AmazonCustomerByEmail',
1203
+ 'email' => (string)$grantee->EmailAddress,
1204
+ 'permission' => (string)$grant->Permission
1205
+ );
1206
+ elseif (isset($grantee->URI)) // Group
1207
+ $acp['acl'][] = array(
1208
+ 'type' => 'Group',
1209
+ 'uri' => (string)$grantee->URI,
1210
+ 'permission' => (string)$grant->Permission
1211
+ );
1212
+ else continue;
1213
+ }
1214
+ }
1215
+ }
1216
+ return $acp;
1217
+ }
1218
+
1219
+
1220
+ /**
1221
+ * Delete an object
1222
+ *
1223
+ * @param string $bucket Bucket name
1224
+ * @param string $uri Object URI
1225
+ * @return boolean
1226
+ */
1227
+ public static function deleteObject($bucket, $uri)
1228
+ {
1229
+ $rest = new S3Request('DELETE', $bucket, $uri, self::$endpoint);
1230
+ $rest = $rest->getResponse();
1231
+ if ($rest->error === false && $rest->code !== 204)
1232
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1233
+ if ($rest->error !== false)
1234
+ {
1235
+ self::triggerError(sprintf("S3::deleteObject(): [%s] %s",
1236
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1237
+ return false;
1238
+ }
1239
+ return true;
1240
+ }
1241
+
1242
+
1243
+ /**
1244
+ * Get a query string authenticated URL
1245
+ *
1246
+ * @param string $bucket Bucket name
1247
+ * @param string $uri Object URI
1248
+ * @param integer $lifetime Lifetime in seconds
1249
+ * @param boolean $hostBucket Use the bucket name as the hostname
1250
+ * @param boolean $https Use HTTPS ($hostBucket should be false for SSL verification)
1251
+ * @return string
1252
+ */
1253
+ public static function getAuthenticatedURL($bucket, $uri, $lifetime, $hostBucket = false, $https = false)
1254
+ {
1255
+ $expires = self::getTime() + $lifetime;
1256
+ $uri = str_replace(array('%2F', '%2B'), array('/', '+'), rawurlencode($uri));
1257
+ return sprintf(($https ? 'https' : 'http').'://%s/%s?AWSAccessKeyId=%s&Expires=%u&Signature=%s',
1258
+ // $hostBucket ? $bucket : $bucket.'.s3.amazonaws.com', $uri, self::$__accessKey, $expires,
1259
+ $hostBucket ? $bucket : self::$endpoint.'/'.$bucket, $uri, self::$__accessKey, $expires,
1260
+ urlencode(self::getHash("GET\n\n\n{$expires}\n/{$bucket}/{$uri}")));
1261
+ }
1262
+
1263
+
1264
+ /**
1265
+ * Get a CloudFront signed policy URL
1266
+ *
1267
+ * @param array $policy Policy
1268
+ * @return string
1269
+ */
1270
+ public static function getSignedPolicyURL($policy)
1271
+ {
1272
+ $data = json_encode($policy);
1273
+ $signature = '';
1274
+ if (!openssl_sign($data, $signature, self::$__signingKeyResource)) return false;
1275
+
1276
+ $encoded = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($data));
1277
+ $signature = str_replace(array('+', '='), array('-', '_', '~'), base64_encode($signature));
1278
+
1279
+ $url = $policy['Statement'][0]['Resource'] . '?';
1280
+ foreach (array('Policy' => $encoded, 'Signature' => $signature, 'Key-Pair-Id' => self::$__signingKeyPairId) as $k => $v)
1281
+ $url .= $k.'='.str_replace('%2F', '/', rawurlencode($v)).'&';
1282
+ return substr($url, 0, -1);
1283
+ }
1284
+
1285
+
1286
+ /**
1287
+ * Get a CloudFront canned policy URL
1288
+ *
1289
+ * @param string $url URL to sign
1290
+ * @param integer $lifetime URL lifetime
1291
+ * @return string
1292
+ */
1293
+ public static function getSignedCannedURL($url, $lifetime)
1294
+ {
1295
+ return self::getSignedPolicyURL(array(
1296
+ 'Statement' => array(
1297
+ array('Resource' => $url, 'Condition' => array(
1298
+ 'DateLessThan' => array('AWS:EpochTime' => self::getTime() + $lifetime)
1299
+ ))
1300
+ )
1301
+ ));
1302
+ }
1303
+
1304
+
1305
+ /**
1306
+ * Get upload POST parameters for form uploads
1307
+ *
1308
+ * @param string $bucket Bucket name
1309
+ * @param string $uriPrefix Object URI prefix
1310
+ * @param constant $acl ACL constant
1311
+ * @param integer $lifetime Lifetime in seconds
1312
+ * @param integer $maxFileSize Maximum filesize in bytes (default 5MB)
1313
+ * @param string $successRedirect Redirect URL or 200 / 201 status code
1314
+ * @param array $amzHeaders Array of x-amz-meta-* headers
1315
+ * @param array $headers Array of request headers or content type as a string
1316
+ * @param boolean $flashVars Includes additional "Filename" variable posted by Flash
1317
+ * @return object
1318
+ */
1319
+ public static function getHttpUploadPostParams($bucket, $uriPrefix = '', $acl = self::ACL_PRIVATE, $lifetime = 3600,
1320
+ $maxFileSize = 5242880, $successRedirect = "201", $amzHeaders = array(), $headers = array(), $flashVars = false)
1321
+ {
1322
+ // Create policy object
1323
+ $policy = new stdClass;
1324
+ $policy->expiration = gmdate('Y-m-d\TH:i:s\Z', (self::getTime() + $lifetime));
1325
+ $policy->conditions = array();
1326
+ $obj = new stdClass; $obj->bucket = $bucket; array_push($policy->conditions, $obj);
1327
+ $obj = new stdClass; $obj->acl = $acl; array_push($policy->conditions, $obj);
1328
+
1329
+ $obj = new stdClass; // 200 for non-redirect uploads
1330
+ if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
1331
+ $obj->success_action_status = (string)$successRedirect;
1332
+ else // URL
1333
+ $obj->success_action_redirect = $successRedirect;
1334
+ array_push($policy->conditions, $obj);
1335
+
1336
+ if ($acl !== self::ACL_PUBLIC_READ)
1337
+ array_push($policy->conditions, array('eq', '$acl', $acl));
1338
+
1339
+ array_push($policy->conditions, array('starts-with', '$key', $uriPrefix));
1340
+ if ($flashVars) array_push($policy->conditions, array('starts-with', '$Filename', ''));
1341
+ foreach (array_keys($headers) as $headerKey)
1342
+ array_push($policy->conditions, array('starts-with', '$'.$headerKey, ''));
1343
+ foreach ($amzHeaders as $headerKey => $headerVal)
1344
+ {
1345
+ $obj = new stdClass;
1346
+ $obj->{$headerKey} = (string)$headerVal;
1347
+ array_push($policy->conditions, $obj);
1348
+ }
1349
+ array_push($policy->conditions, array('content-length-range', 0, $maxFileSize));
1350
+ $policy = base64_encode(str_replace('\/', '/', json_encode($policy)));
1351
+
1352
+ // Create parameters
1353
+ $params = new stdClass;
1354
+ $params->AWSAccessKeyId = self::$__accessKey;
1355
+ $params->key = $uriPrefix.'${filename}';
1356
+ $params->acl = $acl;
1357
+ $params->policy = $policy; unset($policy);
1358
+ $params->signature = self::getHash($params->policy);
1359
+ if (is_numeric($successRedirect) && in_array((int)$successRedirect, array(200, 201)))
1360
+ $params->success_action_status = (string)$successRedirect;
1361
+ else
1362
+ $params->success_action_redirect = $successRedirect;
1363
+ foreach ($headers as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
1364
+ foreach ($amzHeaders as $headerKey => $headerVal) $params->{$headerKey} = (string)$headerVal;
1365
+ return $params;
1366
+ }
1367
+
1368
+
1369
+ /**
1370
+ * Create a CloudFront distribution
1371
+ *
1372
+ * @param string $bucket Bucket name
1373
+ * @param string $originType origin type (s3 or custom)
1374
+ * @param boolean $enabled Enabled (true/false)
1375
+ * @param array $cnames Array containing CNAME aliases
1376
+ * @param string $comment Use the bucket name as the hostname
1377
+ * @param string $defaultRootObject Default root object
1378
+ * @param string $originAccessIdentity Origin access identity
1379
+ * @param array $trustedSigners Array of trusted signers
1380
+ * @return array | false
1381
+ */
1382
+ public static function createDistribution($bucket, $originType = self::ORIGIN_TYPE_S3, $enabled = true, $cnames = array(), $comment = null, $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
1383
+ {
1384
+ if (!extension_loaded('openssl'))
1385
+ {
1386
+ self::triggerError(sprintf("S3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): %s",
1387
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1388
+ return false;
1389
+ }
1390
+ $useSSL = self::$useSSL;
1391
+
1392
+ self::$useSSL = true; // CloudFront requires SSL
1393
+ $rest = new S3Request('POST', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
1394
+ $rest->data = self::getCloudFrontDistributionConfigXML(
1395
+ $bucket,
1396
+ $originType,
1397
+ $enabled,
1398
+ (string)$comment,
1399
+ (string)microtime(true),
1400
+ $cnames,
1401
+ $defaultRootObject,
1402
+ $originAccessIdentity,
1403
+ $trustedSigners
1404
+ );
1405
+
1406
+ $rest->size = strlen($rest->data);
1407
+ $rest->setHeader('Content-Type', 'application/xml');
1408
+ $rest = self::getCloudFrontResponse($rest);
1409
+
1410
+ self::$useSSL = $useSSL;
1411
+
1412
+ if ($rest->error === false && $rest->code !== 201)
1413
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1414
+ if ($rest->error !== false)
1415
+ {
1416
+ self::triggerError(sprintf("S3::createDistribution({$bucket}, ".(int)$enabled.", [], '$comment'): [%s] %s",
1417
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1418
+ return false;
1419
+ } elseif ($rest->body instanceof SimpleXMLElement)
1420
+ return self::parseCloudFrontDistributionConfig($rest->body);
1421
+ return false;
1422
+ }
1423
+
1424
+
1425
+ /**
1426
+ * Get CloudFront distribution info
1427
+ *
1428
+ * @param string $distributionId Distribution ID from listDistributions()
1429
+ * @return array | false
1430
+ */
1431
+ public static function getDistribution($distributionId)
1432
+ {
1433
+ if (!extension_loaded('openssl'))
1434
+ {
1435
+ self::triggerError(sprintf("S3::getDistribution($distributionId): %s",
1436
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1437
+ return false;
1438
+ }
1439
+ $useSSL = self::$useSSL;
1440
+
1441
+ self::$useSSL = true; // CloudFront requires SSL
1442
+ $rest = new S3Request('GET', '', '2010-11-01/distribution/'.$distributionId, 'cloudfront.amazonaws.com');
1443
+ $rest = self::getCloudFrontResponse($rest);
1444
+
1445
+ self::$useSSL = $useSSL;
1446
+
1447
+ if ($rest->error === false && $rest->code !== 200)
1448
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1449
+ if ($rest->error !== false)
1450
+ {
1451
+ self::triggerError(sprintf("S3::getDistribution($distributionId): [%s] %s",
1452
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1453
+ return false;
1454
+ }
1455
+ elseif ($rest->body instanceof SimpleXMLElement)
1456
+ {
1457
+ $dist = self::parseCloudFrontDistributionConfig($rest->body);
1458
+ $dist['hash'] = $rest->headers['hash'];
1459
+ $dist['id'] = $distributionId;
1460
+ return $dist;
1461
+ }
1462
+ return false;
1463
+ }
1464
+
1465
+
1466
+ /**
1467
+ * Update a CloudFront distribution
1468
+ *
1469
+ * @param array $dist Distribution array info identical to output of getDistribution()
1470
+ * @return array | false
1471
+ */
1472
+ public static function updateDistribution($dist)
1473
+ {
1474
+ if (!extension_loaded('openssl'))
1475
+ {
1476
+ self::triggerError(sprintf("S3::updateDistribution({$dist['id']}): %s",
1477
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1478
+ return false;
1479
+ }
1480
+
1481
+ $useSSL = self::$useSSL;
1482
+
1483
+ self::$useSSL = true; // CloudFront requires SSL
1484
+ $rest = new S3Request('PUT', '', '2010-11-01/distribution/'.$dist['id'].'/config', 'cloudfront.amazonaws.com');
1485
+ $rest->data = self::getCloudFrontDistributionConfigXML(
1486
+ $dist['origin'],
1487
+ $dist['type'],
1488
+ $dist['enabled'],
1489
+ $dist['comment'],
1490
+ $dist['callerReference'],
1491
+ $dist['cnames'],
1492
+ $dist['defaultRootObject'],
1493
+ $dist['originAccessIdentity'],
1494
+ $dist['trustedSigners']
1495
+ );
1496
+
1497
+ $rest->size = strlen($rest->data);
1498
+ $rest->setHeader('If-Match', $dist['hash']);
1499
+ $rest = self::getCloudFrontResponse($rest);
1500
+
1501
+ self::$useSSL = $useSSL;
1502
+
1503
+ if ($rest->error === false && $rest->code !== 200)
1504
+ $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1505
+ if ($rest->error !== false)
1506
+ {
1507
+ self::triggerError(sprintf("S3::updateDistribution({$dist['id']}): [%s] %s",
1508
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
1509
+ return false;
1510
+ } else {
1511
+ $dist = self::parseCloudFrontDistributionConfig($rest->body);
1512
+ $dist['hash'] = $rest->headers['hash'];
1513
+ return $dist;
1514
+ }
1515
+ return false;
1516
+ }
1517
+
1518
+
1519
+ /**
1520
+ * Delete a CloudFront distribution
1521
  *
1522
+ * @param array $dist Distribution array info identical to output of getDistribution()
 
1523
  * @return boolean
1524
  */
1525
+ public static function deleteDistribution($dist)
1526
+ {
1527
+ if (!extension_loaded('openssl'))
1528
+ {
1529
+ self::triggerError(sprintf("S3::deleteDistribution({$dist['id']}): %s",
1530
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1531
+ return false;
1532
+ }
1533
+
1534
+ $useSSL = self::$useSSL;
1535
+
1536
+ self::$useSSL = true; // CloudFront requires SSL
1537
+ $rest = new S3Request('DELETE', '', '2008-06-30/distribution/'.$dist['id'], 'cloudfront.amazonaws.com');
1538
+ $rest->setHeader('If-Match', $dist['hash']);
1539
+ $rest = self::getCloudFrontResponse($rest);
1540
+
1541
+ self::$useSSL = $useSSL;
1542
+
1543
  if ($rest->error === false && $rest->code !== 204)
1544
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1545
+ if ($rest->error !== false)
1546
+ {
1547
+ self::triggerError(sprintf("S3::deleteDistribution({$dist['id']}): [%s] %s",
1548
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
 
 
 
1549
  return false;
1550
  }
1551
  return true;
1553
 
1554
 
1555
  /**
1556
+ * Get a list of CloudFront distributions
1557
  *
1558
+ * @return array
 
 
 
 
 
1559
  */
1560
+ public static function listDistributions()
1561
+ {
1562
+ if (!extension_loaded('openssl'))
1563
+ {
1564
+ self::triggerError(sprintf("S3::listDistributions(): [%s] %s",
1565
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1566
+ return false;
1567
+ }
 
1568
 
1569
+ $useSSL = self::$useSSL;
1570
+ self::$useSSL = true; // CloudFront requires SSL
1571
+ $rest = new S3Request('GET', '', '2010-11-01/distribution', 'cloudfront.amazonaws.com');
1572
+ $rest = self::getCloudFrontResponse($rest);
1573
+ self::$useSSL = $useSSL;
1574
+
1575
+ if ($rest->error === false && $rest->code !== 200)
1576
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1577
+ if ($rest->error !== false)
1578
+ {
1579
+ self::triggerError(sprintf("S3::listDistributions(): [%s] %s",
1580
+ $rest->error['code'], $rest->error['message']), __FILE__, __LINE__);
 
 
 
 
 
 
1581
  return false;
1582
+ }
1583
+ elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->DistributionSummary))
1584
+ {
1585
+ $list = array();
1586
+ if (isset($rest->body->Marker, $rest->body->MaxItems, $rest->body->IsTruncated))
1587
+ {
1588
+ //$info['marker'] = (string)$rest->body->Marker;
1589
+ //$info['maxItems'] = (int)$rest->body->MaxItems;
1590
+ //$info['isTruncated'] = (string)$rest->body->IsTruncated == 'true' ? true : false;
1591
+ }
1592
+ foreach ($rest->body->DistributionSummary as $summary)
1593
+ $list[(string)$summary->Id] = self::parseCloudFrontDistributionConfig($summary);
1594
+
1595
+ return $list;
1596
+ }
1597
+ return array();
1598
  }
1599
 
1600
  /**
1601
+ * List CloudFront Origin Access Identities
1602
  *
1603
+ * @return array
 
1604
  */
1605
+ public static function listOriginAccessIdentities()
1606
+ {
1607
+ if (!extension_loaded('openssl'))
1608
+ {
1609
+ self::triggerError(sprintf("S3::listOriginAccessIdentities(): [%s] %s",
1610
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1611
+ return false;
1612
+ }
1613
+
1614
+ self::$useSSL = true; // CloudFront requires SSL
1615
+ $rest = new S3Request('GET', '', '2010-11-01/origin-access-identity/cloudfront', 'cloudfront.amazonaws.com');
1616
+ $rest = self::getCloudFrontResponse($rest);
1617
+ $useSSL = self::$useSSL;
1618
 
1619
  if ($rest->error === false && $rest->code !== 200)
1620
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1621
+ if ($rest->error !== false)
1622
+ {
1623
+ trigger_error(sprintf("S3::listOriginAccessIdentities(): [%s] %s",
1624
+ $rest->error['code'], $rest->error['message']), E_USER_WARNING);
 
 
1625
  return false;
1626
+ }
1627
+
1628
+ if (isset($rest->body->CloudFrontOriginAccessIdentitySummary))
1629
+ {
1630
+ $identities = array();
1631
+ foreach ($rest->body->CloudFrontOriginAccessIdentitySummary as $identity)
1632
+ if (isset($identity->S3CanonicalUserId))
1633
+ $identities[(string)$identity->Id] = array('id' => (string)$identity->Id, 's3CanonicalUserId' => (string)$identity->S3CanonicalUserId);
1634
+ return $identities;
1635
  }
1636
  return false;
1637
  }
1638
 
1639
 
1640
  /**
1641
+ * Invalidate objects in a CloudFront distribution
1642
  *
1643
+ * Thanks to Martin Lindkvist for S3::invalidateDistribution()
1644
+ *
1645
+ * @param string $distributionId Distribution ID from listDistributions()
1646
+ * @param array $paths Array of object paths to invalidate
1647
+ * @return boolean
1648
  */
1649
+ public static function invalidateDistribution($distributionId, $paths)
1650
+ {
1651
+ if (!extension_loaded('openssl'))
1652
+ {
1653
+ self::triggerError(sprintf("S3::invalidateDistribution(): [%s] %s",
1654
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1655
+ return false;
1656
+ }
1657
+
1658
+ $useSSL = self::$useSSL;
1659
+ self::$useSSL = true; // CloudFront requires SSL
1660
+ $rest = new S3Request('POST', '', '2010-08-01/distribution/'.$distributionId.'/invalidation', 'cloudfront.amazonaws.com');
1661
+ $rest->data = self::getCloudFrontInvalidationBatchXML($paths, (string)microtime(true));
1662
  $rest->size = strlen($rest->data);
1663
+ $rest = self::getCloudFrontResponse($rest);
1664
+ self::$useSSL = $useSSL;
1665
 
1666
+ if ($rest->error === false && $rest->code !== 201)
1667
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1668
+ if ($rest->error !== false)
1669
+ {
1670
+ trigger_error(sprintf("S3::invalidate('{$distributionId}',{$paths}): [%s] %s",
1671
+ $rest->error['code'], $rest->error['message']), E_USER_WARNING);
 
 
1672
  return false;
 
 
 
 
1673
  }
1674
+ return true;
1675
  }
1676
 
1677
 
1678
  /**
1679
+ * Get a InvalidationBatch DOMDocument
1680
+ *
1681
+ * @internal Used to create XML in invalidateDistribution()
1682
+ * @param array $paths Paths to objects to invalidateDistribution
1683
+ * @param int $callerReference
1684
+ * @return string
1685
+ */
1686
+ private static function getCloudFrontInvalidationBatchXML($paths, $callerReference = '0')
1687
+ {
1688
+ $dom = new DOMDocument('1.0', 'UTF-8');
1689
+ $dom->formatOutput = true;
1690
+ $invalidationBatch = $dom->createElement('InvalidationBatch');
1691
+ foreach ($paths as $path)
1692
+ $invalidationBatch->appendChild($dom->createElement('Path', $path));
1693
+
1694
+ $invalidationBatch->appendChild($dom->createElement('CallerReference', $callerReference));
1695
+ $dom->appendChild($invalidationBatch);
1696
+ return $dom->saveXML();
1697
+ }
1698
+
1699
+
1700
+ /**
1701
+ * List your invalidation batches for invalidateDistribution() in a CloudFront distribution
1702
+ *
1703
+ * http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/ListInvalidation.html
1704
+ * returned array looks like this:
1705
+ * Array
1706
+ * (
1707
+ * [I31TWB0CN9V6XD] => InProgress
1708
+ * [IT3TFE31M0IHZ] => Completed
1709
+ * [I12HK7MPO1UQDA] => Completed
1710
+ * [I1IA7R6JKTC3L2] => Completed
1711
+ * )
1712
  *
1713
+ * @param string $distributionId Distribution ID from listDistributions()
1714
  * @return array
1715
  */
1716
+ public static function getDistributionInvalidationList($distributionId)
1717
+ {
1718
+ if (!extension_loaded('openssl'))
1719
+ {
1720
+ self::triggerError(sprintf("S3::getDistributionInvalidationList(): [%s] %s",
1721
+ "CloudFront functionality requires SSL"), __FILE__, __LINE__);
1722
+ return false;
1723
+ }
1724
+
1725
+ $useSSL = self::$useSSL;
1726
+ self::$useSSL = true; // CloudFront requires SSL
1727
+ $rest = new S3Request('GET', '', '2010-11-01/distribution/'.$distributionId.'/invalidation', 'cloudfront.amazonaws.com');
1728
+ $rest = self::getCloudFrontResponse($rest);
1729
+ self::$useSSL = $useSSL;
1730
 
1731
  if ($rest->error === false && $rest->code !== 200)
1732
  $rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
1733
+ if ($rest->error !== false)
1734
+ {
1735
+ trigger_error(sprintf("S3::getDistributionInvalidationList('{$distributionId}'): [%s]",
1736
+ $rest->error['code'], $rest->error['message']), E_USER_WARNING);
 
1737
  return false;
1738
+ }
1739
+ elseif ($rest->body instanceof SimpleXMLElement && isset($rest->body->InvalidationSummary))
1740
+ {
1741
  $list = array();
1742
+ foreach ($rest->body->InvalidationSummary as $summary)
1743
+ $list[(string)$summary->Id] = (string)$summary->Status;
1744
+
 
 
 
 
 
1745
  return $list;
1746
  }
1747
  return array();
1751
  /**
1752
  * Get a DistributionConfig DOMDocument
1753
  *
1754
+ * http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?PutConfig.html
1755
+ *
1756
  * @internal Used to create XML in createDistribution() and updateDistribution()
1757
+ * @param string $bucket S3 Origin bucket
1758
+ * @param string $originType origin type (s3 or custom)
1759
  * @param boolean $enabled Enabled (true/false)
1760
  * @param string $comment Comment to append
1761
  * @param string $callerReference Caller reference
1762
  * @param array $cnames Array of CNAME aliases
1763
+ * @param string $defaultRootObject Default root object
1764
+ * @param string $originAccessIdentity Origin access identity
1765
+ * @param array $trustedSigners Array of trusted signers
1766
  * @return string
1767
  */
1768
+ private static function getCloudFrontDistributionConfigXML($bucket, $originType, $enabled, $comment, $callerReference = '0', $cnames = array(), $defaultRootObject = null, $originAccessIdentity = null, $trustedSigners = array())
1769
+ {
1770
  $dom = new DOMDocument('1.0', 'UTF-8');
1771
+ $dom->formatOutput = true;
 
1772
  $distributionConfig = $dom->createElement('DistributionConfig');
1773
  $distributionConfig->setAttribute('xmlns', 'http://cloudfront.amazonaws.com/doc/2010-11-01/');
1774
 
1775
+ if ($originType == self::ORIGIN_TYPE_S3) {
1776
  $origin = $dom->createElement('S3Origin');
1777
+ $origin->appendChild($dom->createElement('DNSName', $bucket));
1778
  } else {
1779
  $origin = $dom->createElement('CustomOrigin');
1780
+ $origin->appendChild($dom->createElement('DNSName', $bucket));
1781
  $origin->appendChild($dom->createElement('OriginProtocolPolicy', 'http-only'));
1782
  }
1783
 
1784
+ if ($originAccessIdentity !== null) $origin->appendChild($dom->createElement('OriginAccessIdentity', $originAccessIdentity));
1785
  $distributionConfig->appendChild($origin);
 
1786
 
1787
+ if ($defaultRootObject !== null) $distributionConfig->appendChild($dom->createElement('DefaultRootObject', $defaultRootObject));
1788
+
1789
+ $distributionConfig->appendChild($dom->createElement('CallerReference', $callerReference));
1790
+ foreach ($cnames as $cname)
1791
  $distributionConfig->appendChild($dom->createElement('CNAME', $cname));
1792
+ if ($comment !== '') $distributionConfig->appendChild($dom->createElement('Comment', $comment));
1793
+ $distributionConfig->appendChild($dom->createElement('Enabled', $enabled ? 'true' : 'false'));
1794
 
1795
+ if (!empty($trustedSigners)) {
1796
+ $trusted = $dom->createElement('TrustedSigners');
1797
+ foreach ($trustedSigners as $id => $type)
1798
+ $trusted->appendChild($id !== '' ? $dom->createElement($type, $id) : $dom->createElement($type));
1799
+ $distributionConfig->appendChild($trusted);
1800
  }
1801
 
 
1802
  $dom->appendChild($distributionConfig);
1803
+ //var_dump($dom->saveXML());
1804
  return $dom->saveXML();
1805
  }
1806
 
1808
  /**
1809
  * Parse a CloudFront distribution config
1810
  *
1811
+ * See http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/index.html?GetDistribution.html
1812
+ *
1813
  * @internal Used to parse the CloudFront DistributionConfig node to an array
1814
  * @param object &$node DOMNode
1815
  * @return array
1816
  */
1817
+ private static function parseCloudFrontDistributionConfig(&$node)
1818
+ {
1819
+ if (isset($node->DistributionConfig))
1820
+ return self::parseCloudFrontDistributionConfig($node->DistributionConfig);
1821
 
1822
+ $dist = array();
1823
+ if (isset($node->Id, $node->Status, $node->LastModifiedTime, $node->DomainName))
1824
+ {
1825
+ $dist['id'] = (string)$node->Id;
1826
+ $dist['status'] = (string)$node->Status;
1827
+ $dist['time'] = strtotime((string)$node->LastModifiedTime);
1828
+ $dist['domain'] = (string)$node->DomainName;
1829
+ }
1830
 
1831
+ if (isset($node->CallerReference))
1832
+ $dist['callerReference'] = (string)$node->CallerReference;
 
1833
 
1834
+ if (isset($node->Enabled))
1835
+ $dist['enabled'] = (string)$node->Enabled == 'true' ? true : false;
 
1836
 
1837
+ if (isset($node->S3Origin))
1838
+ {
1839
+ $dist['type'] = self::ORIGIN_TYPE_S3;
1840
 
1841
  if (isset($node->S3Origin->DNSName)) {
1842
+ $dist['origin'] = (string)$node->S3Origin->DNSName;
1843
  }
1844
+
1845
+ $dist['originAccessIdentity'] = isset($node->S3Origin->OriginAccessIdentity) ?
1846
+ (string)$node->S3Origin->OriginAccessIdentity : null;
1847
  } elseif (isset($node->CustomOrigin)) {
1848
+ $dist['type'] = self::ORIGIN_TYPE_CUSTOM;
1849
 
1850
  if (isset($node->CustomOrigin->DNSName)) {
1851
  $dist['origin'] = (string) $node->CustomOrigin->DNSName;
1852
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1853
 
1854
+ $dist['originAccessIdentity'] = isset($node->S3Origin->OriginAccessIdentity) ?
1855
+ (string)$node->S3Origin->OriginAccessIdentity : null;
1856
  }
1857
 
1858
+ $dist['defaultRootObject'] = isset($node->DefaultRootObject) ? (string)$node->DefaultRootObject : null;
1859
+
1860
+ $dist['cnames'] = array();
1861
+ if (isset($node->CNAME))
1862
+ foreach ($node->CNAME as $cname)
1863
+ $dist['cnames'][(string)$cname] = (string)$cname;
1864
+
1865
+ $dist['trustedSigners'] = array();
1866
+ if (isset($node->TrustedSigners))
1867
+ foreach ($node->TrustedSigners as $signer)
1868
+ {
1869
+ if (isset($signer->Self))
1870
+ $dist['trustedSigners'][''] = 'Self';
1871
+ elseif (isset($signer->KeyPairId))
1872
+ $dist['trustedSigners'][(string)$signer->KeyPairId] = 'KeyPairId';
1873
+ elseif (isset($signer->AwsAccountNumber))
1874
+ $dist['trustedSigners'][(string)$signer->AwsAccountNumber] = 'AwsAccountNumber';
1875
+ }
1876
 
1877
+ $dist['comment'] = isset($node->Comment) ? (string)$node->Comment : null;
1878
  return $dist;
1879
  }
1880
 
1881
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1882
  /**
1883
  * Grab CloudFront response
1884
  *
1886
  * @param object &$rest S3Request instance
1887
  * @return object
1888
  */
1889
+ private static function getCloudFrontResponse(&$rest)
1890
+ {
1891
  $rest->getResponse();
1892
  if ($rest->response->error === false && isset($rest->response->body) &&
1893
+ is_string($rest->response->body) && substr($rest->response->body, 0, 5) == '<?xml')
1894
+ {
1895
  $rest->response->body = simplexml_load_string($rest->response->body);
1896
  // Grab CloudFront errors
1897
  if (isset($rest->response->body->Error, $rest->response->body->Error->Code,
1898
+ $rest->response->body->Error->Message))
1899
+ {
1900
  $rest->response->error = array(
1901
  'code' => (string)$rest->response->body->Error->Code,
1902
  'message' => (string)$rest->response->body->Error->Message
1911
  /**
1912
  * Get MIME type for file
1913
  *
1914
+ * To override the putObject() Content-Type, add it to $requestHeaders
1915
+ *
1916
+ * To use fileinfo, ensure the MAGIC environment variable is set
1917
+ *
1918
  * @internal Used to get mime types
1919
  * @param string &$file File path
1920
  * @return string
1921
  */
1922
+ private static function getMIMEType(&$file) {
1923
+ $type = Util_Mime::get_mime_type($file);
1924
+ return $type;
1925
+ }
1926
+
1927
+
1928
+ /**
1929
+ * Get the current time
1930
+ *
1931
+ * @internal Used to apply offsets to sytem time
1932
+ * @return integer
1933
+ */
1934
+ public static function getTime()
1935
+ {
1936
+ self::setTimeCorrectionOffset(); // Set correct offset
1937
+ return time() + self::$__timeOffset;
1938
  }
1939
 
1940
 
1945
  * @param string $string String to sign
1946
  * @return string
1947
  */
1948
+ public static function getSignature($string)
1949
+ {
1950
+ return 'AWS '.self::$__accessKey.':'.self::getHash($string);
1951
  }
1952
 
1953
 
1956
  *
1957
  * This uses the hash extension if loaded
1958
  *
1959
+ * @internal Used by getSignature()
1960
  * @param string $string String to sign
1961
  * @return string
1962
  */
1963
+ private static function getHash($string)
1964
+ {
1965
  return base64_encode(extension_loaded('hash') ?
1966
  hash_hmac('sha1', $string, self::$__secretKey, true) : pack('H*', sha1(
1967
  (str_pad(self::$__secretKey, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
1969
  (str_repeat(chr(0x36), 64))) . $string)))));
1970
  }
1971
 
 
1972
 
1973
+ /**
1974
+ * Generate the headers for AWS Signature V4
1975
+ * @internal Used by S3Request::getResponse()
1976
+ * @param array $aheaders amzHeaders
1977
+ * @param array $headers
1978
+ * @param string $method
1979
+ * @param string $uri
1980
+ * @param string $data
1981
+ * @param array $parameters
1982
+ * @return array $headers
1983
+ */
1984
+ public static function getSignatureV4($aHeaders, $headers, $method='GET', $uri='', $data = '', $parameters=array())
1985
+ {
1986
+ $service = self::ORIGIN_TYPE_S3;
1987
+ $region = S3::getRegion();
1988
+
1989
+ $algorithm = 'AWS4-HMAC-SHA256';
1990
+ $amzHeaders = array();
1991
+ $amzRequests = array();
1992
+
1993
+ $amzDate = gmdate( 'Ymd\THis\Z' );
1994
+ $amzDateStamp = gmdate( 'Ymd' );
1995
+
1996
+ // amz-date ISO8601 format ? for aws request
1997
+ $amzHeaders['x-amz-date'] = $amzDate;
1998
+
1999
+ // CanonicalHeaders
2000
+ foreach ( $headers as $k => $v ) {
2001
+ $amzHeaders[ strtolower( $k ) ] = trim( $v );
2002
+ }
2003
+ foreach ( $aHeaders as $k => $v ) {
2004
+ $amzHeaders[ strtolower( $k ) ] = trim( $v );
2005
+ }
2006
+ uksort( $amzHeaders, 'strcmp' );
2007
+
2008
+ // payload
2009
+ $payloadHash = isset($amzHeaders['x-amz-content-sha256']) ? $amzHeaders['x-amz-content-sha256'] : hash('sha256', $data);
2010
+
2011
+ $uriQmPos = strpos($uri, '?');
2012
+
2013
+ // CanonicalRequests
2014
+ $amzRequests[] = $method;
2015
+ $amzRequests[] = ($uriQmPos === false ? $uri : substr($uri, 0, $uriQmPos));
2016
+ $amzRequests[] = http_build_query($parameters);
2017
+ // add header as string to requests
2018
+ foreach ( $amzHeaders as $k => $v ) {
2019
+ $amzRequests[] = $k . ':' . $v;
2020
+ }
2021
+ // add a blank entry so we end up with an extra line break
2022
+ $amzRequests[] = '';
2023
+ // SignedHeaders
2024
+ $amzRequests[] = implode( ';', array_keys( $amzHeaders ) );
2025
+ // payload hash
2026
+ $amzRequests[] = $payloadHash;
2027
+ // request as string
2028
+ $amzRequestStr = implode("\n", $amzRequests);
2029
+
2030
+ // CredentialScope
2031
+ $credentialScope = array();
2032
+ $credentialScope[] = $amzDateStamp;
2033
+ $credentialScope[] = $region;
2034
+ $credentialScope[] = $service;
2035
+ $credentialScope[] = 'aws4_request';
2036
+
2037
+ // stringToSign
2038
+ $stringToSign = array();
2039
+ $stringToSign[] = $algorithm;
2040
+ $stringToSign[] = $amzDate;
2041
+ $stringToSign[] = implode('/', $credentialScope);
2042
+ $stringToSign[] = hash('sha256', $amzRequestStr);
2043
+ // as string
2044
+ $stringToSignStr = implode("\n", $stringToSign);
2045
+
2046
+ // Make Signature
2047
+ $kSecret = 'AWS4' . self::$__secretKey;
2048
+ $kDate = hash_hmac( 'sha256', $amzDateStamp, $kSecret, true );
2049
+ $kRegion = hash_hmac( 'sha256', $region, $kDate, true );
2050
+ $kService = hash_hmac( 'sha256', $service, $kRegion, true );
2051
+ $kSigning = hash_hmac( 'sha256', 'aws4_request', $kService, true );
2052
+
2053
+ $signature = hash_hmac( 'sha256', $stringToSignStr, $kSigning );
2054
+
2055
+ $authorization = array(
2056
+ 'Credential=' . self::$__accessKey . '/' . implode( '/', $credentialScope ),
2057
+ 'SignedHeaders=' . implode( ';', array_keys( $amzHeaders ) ),
2058
+ 'Signature=' . $signature,
2059
+ );
2060
+
2061
+ $authorizationStr = $algorithm . ' ' . implode( ',', $authorization );
2062
+
2063
+ $resultHeaders = array(
2064
+ 'X-AMZ-DATE' => $amzDate,
2065
+ 'Authorization' => $authorizationStr
2066
+ );
2067
+ if (!isset($aHeaders['x-amz-content-sha256'])) $resultHeaders['x-amz-content-sha256'] = $payloadHash;
2068
+
2069
+ return $resultHeaders;
2070
+ }
2071
+
2072
+
2073
+ }
2074
 
2075
+ /**
2076
+ * S3 Request class
2077
+ *
2078
+ * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
2079
+ * @version 0.5.0-dev
2080
+ */
2081
+ final class S3Request
2082
+ {
2083
+ /**
2084
+ * AWS URI
2085
+ *
2086
+ * @var string
2087
+ * @access private
2088
+ */
2089
+ private $endpoint;
2090
 
2091
+ /**
2092
+ * Verb
2093
+ *
2094
+ * @var string
2095
+ * @access private
2096
+ */
2097
  private $verb;
2098
+
2099
+ /**
2100
+ * S3 bucket name
2101
+ *
2102
+ * @var string
2103
+ * @access private
2104
+ */
2105
+ private $bucket;
2106
+
2107
+ /**
2108
+ * Object URI
2109
+ *
2110
+ * @var string
2111
+ * @access private
2112
+ */
2113
+ private $uri;
2114
+
2115
+ /**
2116
+ * Final object URI
2117
+ *
2118
+ * @var string
2119
+ * @access private
2120
+ */
2121
+ private $resource = '';
2122
+
2123
+ /**
2124
+ * Additional request parameters
2125
+ *
2126
+ * @var array
2127
+ * @access private
2128
+ */
2129
+ private $parameters = array();
2130
+
2131
+ /**
2132
+ * Amazon specific request headers
2133
+ *
2134
+ * @var array
2135
+ * @access private
2136
+ */
2137
+ private $amzHeaders = array();
2138
+
2139
+ /**
2140
+ * HTTP request headers
2141
+ *
2142
+ * @var array
2143
+ * @access private
2144
+ */
2145
+ private $headers = array(
2146
+ 'Host' => '', 'Date' => '', 'Content-MD5' => '', 'Content-Type' => ''
2147
  );
2148
 
2149
+ /**
2150
+ * Use HTTP PUT?
2151
+ *
2152
+ * @var bool
2153
+ * @access public
2154
+ */
2155
+ public $fp = false;
2156
+
2157
+ /**
2158
+ * PUT file size
2159
+ *
2160
+ * @var int
2161
+ * @access public
2162
+ */
2163
+ public $size = 0;
2164
+
2165
+ /**
2166
+ * PUT post fields
2167
+ *
2168
+ * @var array
2169
+ * @access public
2170
+ */
2171
+ public $data = false;
2172
+
2173
+ /**
2174
+ * S3 request respone
2175
+ *
2176
+ * @var object
2177
+ * @access public
2178
+ */
2179
+ public $response;
2180
+
2181
+
2182
  /**
2183
  * Constructor
2184
  *
2185
  * @param string $verb Verb
2186
  * @param string $bucket Bucket name
2187
  * @param string $uri Object URI
2188
+ * @param string $endpoint AWS endpoint URI
2189
  * @return mixed
2190
  */
2191
+ function __construct($verb, $bucket = '', $uri = '', $endpoint = 's3.amazonaws.com')
2192
+ {
2193
+
2194
+ $this->endpoint = $endpoint;
2195
  $this->verb = $verb;
2196
+ $this->bucket = $bucket;
2197
  $this->uri = $uri !== '' ? '/'.str_replace('%2F', '/', rawurlencode($uri)) : '/';
2198
 
2199
+ if ($this->bucket !== '')
2200
+ {
2201
+ if ($this->dnsBucketName($this->bucket))
2202
+ {
2203
+ $this->headers['Host'] = $this->bucket.'.'.$this->endpoint;
2204
+ $this->resource = '/'.$this->bucket.$this->uri;
2205
+ }
2206
+ else
2207
+ {
2208
+ $this->headers['Host'] = $this->endpoint;
2209
+ if ($this->bucket !== '') $this->uri = '/'.$this->bucket.$this->uri;
2210
+ $this->bucket = '';
2211
+ $this->resource = $this->uri;
2212
+ }
2213
+ }
2214
+ else
2215
+ {
2216
+ $this->headers['Host'] = $this->endpoint;
2217
  $this->resource = $this->uri;
2218
  }
 
2219
 
2220
+
2221
+ $this->headers['Date'] = gmdate('D, d M Y H:i:s T');
2222
  $this->response = new STDClass;
2223
  $this->response->error = false;
2224
+ $this->response->body = null;
2225
+ $this->response->headers = array();
2226
  }
2227
 
2228
 
2233
  * @param string $value Value
2234
  * @return void
2235
  */
2236
+ public function setParameter($key, $value)
2237
+ {
2238
  $this->parameters[$key] = $value;
2239
  }
2240
 
2246
  * @param string $value Value
2247
  * @return void
2248
  */
2249
+ public function setHeader($key, $value)
2250
+ {
2251
  $this->headers[$key] = $value;
2252
  }
2253
 
2259
  * @param string $value Value
2260
  * @return void
2261
  */
2262
+ public function setAmzHeader($key, $value)
2263
+ {
2264
  $this->amzHeaders[$key] = $value;
2265
  }
2266
 
2270
  *
2271
  * @return object | false
2272
  */
2273
+ public function getResponse()
2274
+ {
2275
  $query = '';
2276
+ if (sizeof($this->parameters) > 0)
2277
+ {
2278
  $query = substr($this->uri, -1) !== '?' ? '?' : '&';
2279
  foreach ($this->parameters as $var => $value)
2280
  if ($value == null || $value == '') $query .= $var.'&';
 
2281
  else $query .= $var.'='.rawurlencode($value).'&';
2282
  $query = substr($query, 0, -1);
2283
  $this->uri .= $query;
2285
  if (array_key_exists('acl', $this->parameters) ||
2286
  array_key_exists('location', $this->parameters) ||
2287
  array_key_exists('torrent', $this->parameters) ||
2288
+ array_key_exists('website', $this->parameters) ||
2289
  array_key_exists('logging', $this->parameters))
2290
  $this->resource .= $query;
2291
  }
2292
+ $url = (S3::$useSSL ? 'https://' : 'http://') . ($this->headers['Host'] !== '' ? $this->headers['Host'] : $this->endpoint) . $this->uri;
2293
+
2294
+ //var_dump('bucket: ' . $this->bucket, 'uri: ' . $this->uri, 'resource: ' . $this->resource, 'url: ' . $url);
2295
 
2296
  // Basic setup
2297
  $curl = curl_init();
2298
  curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php');
2299
 
2300
+ if (S3::$useSSL)
2301
+ {
2302
+ // Set protocol version
2303
+ curl_setopt($curl, CURLOPT_SSLVERSION, S3::$useSSLVersion);
2304
+
2305
+ // SSL Validation can now be optional for those with broken OpenSSL installations
2306
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, S3::$useSSLValidation ? 2 : 0);
2307
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, S3::$useSSLValidation ? 1 : 0);
2308
+
2309
+ if (S3::$sslKey !== null) curl_setopt($curl, CURLOPT_SSLKEY, S3::$sslKey);
2310
+ if (S3::$sslCert !== null) curl_setopt($curl, CURLOPT_SSLCERT, S3::$sslCert);
2311
+ if (S3::$sslCACert !== null) curl_setopt($curl, CURLOPT_CAINFO, S3::$sslCACert);
2312
  }
2313
 
2314
  curl_setopt($curl, CURLOPT_URL, $url);
2315
 
2316
+ if (S3::$proxy != null && isset(S3::$proxy['host']))
2317
+ {
2318
+ curl_setopt($curl, CURLOPT_PROXY, S3::$proxy['host']);
2319
+ curl_setopt($curl, CURLOPT_PROXYTYPE, S3::$proxy['type']);
2320
+ if (isset(S3::$proxy['user'], S3::$proxy['pass']) && S3::$proxy['user'] != null && S3::$proxy['pass'] != null)
2321
+ curl_setopt($curl, CURLOPT_PROXYUSERPWD, sprintf('%s:%s', S3::$proxy['user'], S3::$proxy['pass']));
2322
+ }
2323
+
2324
  // Headers
2325
  $headers = array(); $amz = array();
2326
  foreach ($this->amzHeaders as $header => $value)
2333
  if (strlen($value) > 0) $amz[] = strtolower($header).':'.$value;
2334
 
2335
  // AMZ headers must be sorted
2336
+ if (sizeof($amz) > 0)
2337
+ {
2338
+ //sort($amz);
2339
+ usort($amz, array(&$this, 'sortMetaHeadersCmp'));
2340
  $amz = "\n".implode("\n", $amz);
2341
  } else $amz = '';
2342
 
2343
+ if (S3::hasAuth())
2344
+ {
2345
+ // Authorization string (CloudFront stringToSign should only contain a date)
2346
+ if ($this->headers['Host'] == 'cloudfront.amazonaws.com')
2347
+ $headers[] = 'Authorization: ' . S3::getSignature($this->headers['Date']);
2348
+ else
2349
+ {
2350
+ if (S3::$signVer == 'v2')
2351
+ {
2352
+ $headers[] = 'Authorization: ' . S3::getSignature(
2353
+ $this->verb."\n".
2354
+ $this->headers['Content-MD5']."\n".
2355
+ $this->headers['Content-Type']."\n".
2356
+ $this->headers['Date'].$amz."\n".
2357
+ $this->resource
2358
+ );
2359
+ } else {
2360
+ $amzHeaders = S3::getSignatureV4(
2361
+ $this->amzHeaders,
2362
+ $this->headers,
2363
+ $this->verb,
2364
+ $this->uri,
2365
+ $this->data,
2366
+ $this->parameters
2367
+ );
2368
+ foreach ($amzHeaders as $k => $v) {
2369
+ $headers[] = $k .': '. $v;
2370
+ }
2371
+ }
2372
+ }
2373
+ }
2374
 
2375
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
2376
  curl_setopt($curl, CURLOPT_HEADER, false);
2377
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
2378
+ curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, 'responseWriteCallback'));
2379
+ curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, 'responseHeaderCallback'));
2380
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
2381
 
2382
  // Request types
2383
+ switch ($this->verb)
2384
+ {
2385
  case 'GET': break;
2386
  case 'PUT': case 'POST': // POST only used for CloudFront
2387
+ if ($this->fp !== false)
2388
+ {
2389
  curl_setopt($curl, CURLOPT_PUT, true);
2390
  curl_setopt($curl, CURLOPT_INFILE, $this->fp);
2391
  if ($this->size >= 0)
2392
  curl_setopt($curl, CURLOPT_INFILESIZE, $this->size);
2393
+ }
2394
+ elseif ($this->data !== false)
2395
+ {
2396
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
2397
  curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
2398
+ }
2399
+ else
 
2400
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
2401
  break;
2402
  case 'HEAD':
2423
 
2424
  // Parse body into XML
2425
  if ($this->response->error === false && isset($this->response->headers['type']) &&
2426
+ $this->response->headers['type'] == 'application/xml' && isset($this->response->body))
2427
+ {
2428
  $this->response->body = simplexml_load_string($this->response->body);
2429
 
2430
  // Grab S3 errors
2431
+ if (!in_array($this->response->code, array(200, 204, 206)) &&
2432
+ isset($this->response->body->Code, $this->response->body->Message))
2433
+ {
2434
  $this->response->error = array(
2435
  'code' => (string)$this->response->body->Code,
2436
  'message' => (string)$this->response->body->Message
2447
  return $this->response;
2448
  }
2449
 
2450
+ /**
2451
+ * Sort compare for meta headers
2452
+ *
2453
+ * @internal Used to sort x-amz meta headers
2454
+ * @param string $a String A
2455
+ * @param string $b String B
2456
+ * @return integer
2457
+ */
2458
+ private function sortMetaHeadersCmp($a, $b)
2459
+ {
2460
+ $lenA = strpos($a, ':');
2461
+ $lenB = strpos($b, ':');
2462
+ $minLen = min($lenA, $lenB);
2463
+ $ncmp = strncmp($a, $b, $minLen);
2464
+ if ($lenA == $lenB) return $ncmp;
2465
+ if (0 == $ncmp) return $lenA < $lenB ? -1 : 1;
2466
+ return $ncmp;
2467
+ }
2468
 
2469
  /**
2470
  * CURL write callback
2473
  * @param string &$data Data
2474
  * @return integer
2475
  */
2476
+ private function responseWriteCallback(&$curl, &$data)
2477
+ {
2478
+ if (in_array($this->response->code, array(200, 206)) && $this->fp !== false)
2479
  return fwrite($this->fp, $data);
2480
  else
2481
+ {
2482
+ if (isset($this->response->body))
2483
+ $this->response->body .= $data;
2484
+ else
2485
+ $this->response->body = $data;
2486
+ }
2487
  return strlen($data);
2488
  }
2489
 
2490
 
2491
+ /**
2492
+ * Check DNS conformity
2493
+ *
2494
+ * @param string $bucket Bucket name
2495
+ * @return boolean
2496
+ */
2497
+ private function dnsBucketName($bucket)
2498
+ {
2499
+ if (strlen($bucket) > 63 || preg_match("/[^a-z0-9\.-]/", $bucket) > 0) return false;
2500
+ if (S3::$useSSL && strstr($bucket, '.') !== false) return false;
2501
+ if (strstr($bucket, '-.') !== false) return false;
2502
+ if (strstr($bucket, '..') !== false) return false;
2503
+ if (!preg_match("/^[0-9a-z]/", $bucket)) return false;
2504
+ if (!preg_match("/[0-9a-z]$/", $bucket)) return false;
2505
+ return true;
2506
+ }
2507
+
2508
+
2509
  /**
2510
  * CURL header callback
2511
  *
2512
+ * @param resource $curl CURL resource
2513
+ * @param string $data Data
2514
  * @return integer
2515
  */
2516
+ private function responseHeaderCallback($curl, $data)
2517
+ {
2518
  if (($strlen = strlen($data)) <= 2) return $strlen;
2519
  if (substr($data, 0, 4) == 'HTTP')
2520
  $this->response->code = (int)substr($data, 9, 3);
2521
+ else
2522
+ {
2523
+ $data = trim($data);
2524
+ if (strpos($data, ': ') === false) return $strlen;
2525
+ list($header, $value) = explode(': ', $data, 2);
2526
+ $header = strtolower($header);
2527
+ if ($header == 'last-modified')
2528
  $this->response->headers['time'] = strtotime($value);
2529
+ elseif ($header == 'date')
2530
+ $this->response->headers['date'] = strtotime($value);
2531
+ elseif ($header == 'content-length')
2532
  $this->response->headers['size'] = (int)$value;
2533
+ elseif ($header == 'content-type')
2534
  $this->response->headers['type'] = $value;
2535
+ elseif ($header == 'etag')
2536
  $this->response->headers['hash'] = $value{0} == '"' ? substr($value, 1, -1) : $value;
2537
  elseif (preg_match('/^x-amz-meta-.*$/', $header))
2538
+ $this->response->headers[$header] = $value;
2539
  }
2540
  return $strlen;
2541
  }
2542
+
2543
+ }
2544
+
2545
+ /**
2546
+ * S3 exception class
2547
+ *
2548
+ * @link http://undesigned.org.za/2007/10/22/amazon-s3-php-class
2549
+ * @version 0.5.0-dev
2550
+ */
2551
+
2552
+ class S3Exception extends Exception {
2553
+ /**
2554
+ * Class constructor
2555
+ *
2556
+ * @param string $message Exception message
2557
+ * @param string $file File in which exception was created
2558
+ * @param string $line Line number on which exception was created
2559
+ * @param int $code Exception code
2560
+ */
2561
+ function __construct($message, $file, $line, $code = 0)
2562
+ {
2563
+ parent::__construct($message, $code);
2564
+ $this->file = $file;
2565
+ $this->line = $line;
2566
+ }
2567
  }
pub/css/lightbox.css CHANGED
@@ -1,3 +1,12 @@
 
 
 
 
 
 
 
 
 
1
  #overlay {
2
  background: #666;
3
  font-size:12px;
1
+ #w3tc_lightbox_content .metabox-holder {
2
+ padding-top: 0;
3
+ }
4
+
5
+ /* make mismatch in popup resizing invisible, border shows them well */
6
+ #w3tc_lightbox_content .postbox {
7
+ border: none;
8
+ }
9
+
10
  #overlay {
11
  background: #666;
12
  font-size:12px;
pub/css/options.css CHANGED
@@ -1,331 +1,338 @@
1
  #w3tc h2.logo {
2
- width: 224px;
3
- height: 44px;
4
- background: url("../img/W3TC_dashboard_logo_title.png") top right no-repeat;
5
- text-indent: -9999px;
6
- margin:5px 0 10px 0;
7
- padding:0;
8
  }
9
 
10
  #icon-w3tc_general {
11
- display: none;
12
  }
13
 
14
  .w3tc-enabled {
15
- color: #090;
16
- font-weight: 700
17
  }
18
 
19
  .w3tc-disabled {
20
- color: #f00;
21
- font-weight: 700
22
  }
23
 
24
  .w3tc-empty {
25
- font-weight: 700;
26
- font-style: italic
27
  }
28
 
29
  .w3tc-success {
30
- background: #bfb
31
  }
32
 
33
  .w3tc-error {
34
- background: #f99
35
  }
36
  div.w3tc-error.inline {
37
- display:inline-block;
38
  }
39
  input.w3tc-error, textarea.w3tc-error {
40
- background: none;
41
- border: 1px solid #f99
42
  }
43
 
44
 
45
  .w3tc-status {
46
- padding: 5px
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
  }
63
 
64
  #w3tc-help a:hover {
65
- text-decoration: underline;
66
  }
67
 
68
  #w3tc acronym {
69
- border-bottom: 1px dotted #666
70
  }
71
 
72
  #w3tc ul {
73
- list-style: disc outside;
74
- margin-left: 15px;
75
- margin-top: 0;
76
- margin-bottom: 0;
77
  }
78
 
79
  #w3tc ul.w3tc-incomp-plugins {
80
- list-style: disc outside;
81
- margin-left: 17px;
82
- margin-top: 0;
83
- margin-bottom: 0;
84
  }
85
 
86
  #w3tc ul.w3tc-incomp-plugins li div{
87
- width: 150px;
88
- display: inline-block;
89
  }
90
 
91
  #w3tc blockquote {
92
- font-style: italic;
93
  }
94
 
95
  #w3tc blockquote cite {
96
- font-weight: 400;
97
  }
98
 
99
  #w3tc optgroup {
100
- font-style: normal;
101
  }
102
 
103
  #w3tc optgroup option {
104
- text-indent: 20px;
105
  }
106
 
107
  #w3tc h5 {
108
- margin: 0
109
  }
110
 
111
  #w3tc hr {
112
- clear: both;
113
- margin-top: 10px
114
  }
115
 
116
  #w3tc #toc a, #qa a {
117
- text-decoration: none
118
  }
119
 
120
  #w3tc #toc a:hover, #qa a:hover {
121
- text-decoration: underline
122
  }
123
 
124
  #w3tc #toc ul {
125
- margin: 0;
126
- padding: 0
127
  }
128
 
129
  #w3tc #toc li {
130
- margin: 0;
131
- padding: 0
132
  }
133
 
134
  #w3tc #qa {
135
- clear: both;
136
- padding: 10px;
137
  }
138
 
139
  #w3tc #qa, #w3tc #about, #w3tc #install {
140
- width: 760px;
141
  }
142
 
143
  #w3tc fieldset {
144
- margin: 1em 0;
145
- background: #fdfdfd;
146
- padding: 0 1em;
147
- border: 1px solid #bbb;
148
- border-radius: 11px;
149
- -webkit-border-radius: 11px;
150
- -moz-border-radius: 11px;
151
  }
152
 
153
  #w3tc fieldset .submit {
154
- margin: 1em 0 0 0;
155
- padding: 0;
156
  }
157
 
158
  #w3tc fieldset legend {
159
- color: #999;
160
- padding: 0 5px;
161
- font-weight: bold;
162
  }
163
 
164
  #w3tc fieldset legend a:hover {
165
- text-decoration: none;
166
  }
167
 
168
  #w3tc pre.code {
169
- color: #000;
170
- margin: 1em 0;
171
- overflow: auto;
172
- background: #eee;
173
- padding: 12px 15px;
174
- border: 1px solid #ccc;
175
  }
176
 
177
  #w3tc pre.console {
178
- color: #ccc;
179
- margin: 1em 0;
180
- overflow: auto;
181
- background: #000;
182
- padding: 12px 15px;
183
- border: 1px solid #ccc;
184
  }
185
 
186
  #w3tc-cdn-general th {
187
- width: 400px;
188
  }
189
 
190
  #cdn_cnames li {
191
- padding: 5px;
192
- cursor: ns-resize;
193
  }
194
 
195
  #cdn_cnames li:hover {
196
- background: #e9e9e9;
197
  }
198
 
199
  #cdn_cnames li span, .w3tc_cdn_cname_comment {
200
- padding-left: 10px;
201
- color: #999;
202
  }
203
 
204
  #mobile_groups th,
205
  #referrer_groups th,
 
206
  #mobile_groups td,
207
- #referrer_groups td {
208
- padding: 10px 10px 10px 15px;
 
 
209
  }
210
 
211
  #mobile_groups li,
212
- #referrer_groups li {
213
- cursor: ns-resize;
214
- list-style: none;
215
- background: #f0f0f0;
216
- margin-bottom: 1em;
217
- border-radius: 8px;
218
- -webkit-border-radius: 8px;
219
- -moz-border-radius: 8px;
 
220
  }
221
 
222
  #mobile_groups li:hover,
223
- #referrer_groups li:hover {
224
- background: #e9e9e9;
 
225
  }
226
 
227
  #mobile_groups li table,
228
- #referrer_groups li table {
229
- margin: 0;
 
230
  }
231
 
232
  .mobile_group,
233
- .referrer_group {
234
- font-weight: bold;
 
235
  }
236
 
237
  .w3tc-rules {
238
- display: none;
239
- margin: 1em 0;
240
- padding: 0;
241
- background: none;
242
  }
243
 
244
  .minify-files {
245
- margin-bottom: 1em;
246
  }
247
 
248
  .minify-files li {
249
- padding: 2px;
250
- list-style: none;
251
- background: #f0f0f0;
252
- cursor: ns-resize;
253
- border-radius: 8px;
254
- -webkit-border-radius: 8px;
255
- -moz-border-radius: 8px;
256
- line-height: 100%;
257
  }
258
 
259
  .minify-files li:hover {
260
- background: #e9e9e9;
261
  }
262
 
263
  .minify-files th,
264
  .minify-files td {
265
- width: auto;
266
- line-height: 100%;
267
- padding: 3px 3px;
268
- font-weight: normal;
269
- text-align: left;
270
  }
271
 
272
  #support_loading, .w3tc-checking {
273
- height: 32px;
274
- background: url(../img/wpspin_light.gif) left center no-repeat;
275
- padding-left: 38px;
276
- line-height: 32px;
277
- margin: 1em 0;
278
- font-weight: bold;
279
  }
280
  #w3tc .postbox .inside {
281
- padding: 0 10px;
282
  }
283
 
284
  #w3tc .postbox .hndle {
285
- cursor: auto;
286
  }
287
 
288
  #pgcache_reject_roles label, #newrelic_accept_roles label, #cdn_reject_roles label {
289
- margin-right: 15px;
290
  }
291
 
292
  #minify_form fieldset{
293
- padding-bottom: 10px;
294
  }
295
 
296
  #minify_form .html-tag{
297
- font-weight: bold;
298
- color: #107e0e;
299
- float: right;
300
  }
301
 
302
  #minify_form fieldset label{
303
- margin-bottom: 5px;
304
- margin-right:10px;
305
  }
306
 
307
  #minify_table td {
308
- padding: 0;
309
  }
310
 
311
  #minify_table table td {
312
- white-space: nowrap;
313
- padding: 0;
314
  }
315
 
316
  #minify_table .placement {
317
- width: 110px;
318
  }
319
 
320
  #minify_table .options {
321
- padding-left: 10px;
322
  }
323
 
324
  .recom_js_type {
325
- width:160px;
326
  }
327
  .w3tc-missing-files ul {
328
- margin-left:5px;
329
  }
330
 
331
  #w3tc .updated p, #w3tc_dashboard p, #w3tc_general p, #w3tc_cdn p { line-height: 30px}
@@ -333,105 +340,105 @@ input.w3tc-error, textarea.w3tc-error {
333
  #w3tc .updated p, #w3tc_general p, #w3tc_cdn p { line-height: 30px}
334
 
335
  #w3tc #application ul {
336
- margin-top:0;
337
  }
338
 
339
  #monitoring td label{
340
- display: block;
341
  }
342
 
343
  #monitoring td label input {
344
- margin-right: 5px;
345
  }
346
 
347
  .w3tc-required-changes strong {
348
- font-weight: bold;
349
- font-family: courier, sans-serif;
350
  }
351
 
352
  .minify_auto_test, .w3tc-loading {
353
- height: 16px;
354
- background: url(../img/wpspin_light.gif) right top no-repeat;
355
- width: 16px;
356
  }
357
  .create-error p {
358
- margin:0;
359
  }
360
  .create-error {
361
- padding: 3px;
362
- display:none;
363
  }
364
 
365
  #cdn_netdna_authorization_key, #cdn_maxcdn_authorization_key, .maxcdn-netdna-widget-base .button-secondary{
366
- margin-bottom: 3px;
367
  }
368
 
369
  #w3tc_extensions table.extensions .column-name {
370
- width:180px;
371
  }
372
  #wpbody-content .metabox-holder.extension-settings {
373
- padding-top: 0;
374
  }
375
 
376
  #w3tc .subsubsub {
377
- margin-left: 0;
378
  }
379
 
380
  #edge-mode.updated p {
381
- line-height: 20px;
382
  }
383
 
384
  td.w3tc-td-with-button {
385
- line-height: 28px;
386
  }
387
 
388
  .w3tc_loading {
389
- position:absolute;
390
- width: 100%;
391
- text-align: center;
392
  }
393
 
394
  .w3tc_hidden {
395
- visibility: hidden;
396
  }
397
 
398
  .w3tc_none {
399
- display: none;
400
  }
401
 
402
  th.w3tc_config_checkbox {
403
- padding-top: 15px;
404
  }
405
  td.w3tc_config_value_text {
406
- padding-top: 20px;
407
  }
408
 
409
  .w3tc_cdn_cnames_readonly {
410
- margin-top: .5em;
411
- margin-right: 20px;
412
- margin-bottom: .5em;
413
  }
414
 
415
  .w3tchelp_loading_outer {
416
- width: 100%;
417
- margin-top: 50px;
418
  }
419
 
420
  .w3tchelp_loading_inner {
421
- margin-left: auto;
422
- margin-right: auto;
423
  }
424
 
425
  .w3tc_menu_item_pro {
426
- color: #0FA9B5;
427
  }
428
 
429
  .w3tc_menu_item_pro:hover {
430
- color: #ddd;
431
  }
432
 
433
  .w3tc_popup_form {
434
- padding: 20px;
435
  }
436
 
437
 
@@ -439,7 +446,7 @@ td.w3tc_config_value_text {
439
  /* js bound to id */
440
 
441
  th.w3tc_extensions_manage_column_check {
442
- padding: 0 0 0 5px;
443
- vertical-align: middle;
444
- width: 2.2em;
445
  }
1
  #w3tc h2.logo {
2
+ width: 224px;
3
+ height: 44px;
4
+ background: url("../img/W3TC_dashboard_logo_title.png") top right no-repeat;
5
+ text-indent: -9999px;
6
+ margin:5px 0 10px 0;
7
+ padding:0;
8
  }
9
 
10
  #icon-w3tc_general {
11
+ display: none;
12
  }
13
 
14
  .w3tc-enabled {
15
+ color: #090;
16
+ font-weight: 700
17
  }
18
 
19
  .w3tc-disabled {
20
+ color: #f00;
21
+ font-weight: 700
22
  }
23
 
24
  .w3tc-empty {
25
+ font-weight: 700;
26
+ font-style: italic
27
  }
28
 
29
  .w3tc-success {
30
+ background: #bfb
31
  }
32
 
33
  .w3tc-error {
34
+ background: #f99
35
  }
36
  div.w3tc-error.inline {
37
+ display:inline-block;
38
  }
39
  input.w3tc-error, textarea.w3tc-error {
40
+ background: none;
41
+ border: 1px solid #f99
42
  }
43
 
44
 
45
  .w3tc-status {
46
+ padding: 5px
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
  }
63
 
64
  #w3tc-help a:hover {
65
+ text-decoration: underline;
66
  }
67
 
68
  #w3tc acronym {
69
+ border-bottom: 1px dotted #666
70
  }
71
 
72
  #w3tc ul {
73
+ list-style: disc outside;
74
+ margin-left: 15px;
75
+ margin-top: 0;
76
+ margin-bottom: 0;
77
  }
78
 
79
  #w3tc ul.w3tc-incomp-plugins {
80
+ list-style: disc outside;
81
+ margin-left: 17px;
82
+ margin-top: 0;
83
+ margin-bottom: 0;
84
  }
85
 
86
  #w3tc ul.w3tc-incomp-plugins li div{
87
+ width: 150px;
88
+ display: inline-block;
89
  }
90
 
91
  #w3tc blockquote {
92
+ font-style: italic;
93
  }
94
 
95
  #w3tc blockquote cite {
96
+ font-weight: 400;
97
  }
98
 
99
  #w3tc optgroup {
100
+ font-style: normal;
101
  }
102
 
103
  #w3tc optgroup option {
104
+ text-indent: 20px;
105
  }
106
 
107
  #w3tc h5 {
108
+ margin: 0
109
  }
110
 
111
  #w3tc hr {
112
+ clear: both;
113
+ margin-top: 10px
114
  }
115
 
116
  #w3tc #toc a, #qa a {
117
+ text-decoration: none
118
  }
119
 
120
  #w3tc #toc a:hover, #qa a:hover {
121
+ text-decoration: underline
122
  }
123
 
124
  #w3tc #toc ul {
125
+ margin: 0;
126
+ padding: 0
127
  }
128
 
129
  #w3tc #toc li {
130
+ margin: 0;
131
+ padding: 0
132
  }
133
 
134
  #w3tc #qa {
135
+ clear: both;
136
+ padding: 10px;
137
  }
138
 
139
  #w3tc #qa, #w3tc #about, #w3tc #install {
140
+ width: 760px;
141
  }
142
 
143
  #w3tc fieldset {
144
+ margin: 1em 0;
145
+ background: #fdfdfd;
146
+ padding: 0 1em;
147
+ border: 1px solid #bbb;
148
+ border-radius: 11px;
149
+ -webkit-border-radius: 11px;
150
+ -moz-border-radius: 11px;
151
  }
152
 
153
  #w3tc fieldset .submit {
154
+ margin: 1em 0 0 0;
155
+ padding: 0;
156
  }
157
 
158
  #w3tc fieldset legend {
159
+ color: #999;
160
+ padding: 0 5px;
161
+ font-weight: bold;
162
  }
163
 
164
  #w3tc fieldset legend a:hover {
165
+ text-decoration: none;
166
  }
167
 
168
  #w3tc pre.code {
169
+ color: #000;
170
+ margin: 1em 0;
171
+ overflow: auto;
172
+ background: #eee;
173
+ padding: 12px 15px;
174
+ border: 1px solid #ccc;
175
  }
176
 
177
  #w3tc pre.console {
178
+ color: #ccc;
179
+ margin: 1em 0;
180
+ overflow: auto;
181
+ background: #000;
182
+ padding: 12px 15px;
183
+ border: 1px solid #ccc;
184
  }
185
 
186
  #w3tc-cdn-general th {
187
+ width: 400px;
188
  }
189
 
190
  #cdn_cnames li {
191
+ padding: 5px;
192
+ cursor: ns-resize;
193
  }
194
 
195
  #cdn_cnames li:hover {
196
+ background: #e9e9e9;
197
  }
198
 
199
  #cdn_cnames li span, .w3tc_cdn_cname_comment {
200
+ padding-left: 10px;
201
+ color: #999;
202
  }
203
 
204
  #mobile_groups th,
205
  #referrer_groups th,
206
+ .w3tc_cachegroups th,
207
  #mobile_groups td,
208
+ #referrer_groups td,
209
+ .w3tc_cachegroups td,
210
+ {
211
+ padding: 10px 10px 10px 15px;
212
  }
213
 
214
  #mobile_groups li,
215
+ #referrer_groups li,
216
+ .w3tc_cachegroups li {
217
+ cursor: ns-resize;
218
+ list-style: none;
219
+ background: #f0f0f0;
220
+ margin-bottom: 1em;
221
+ border-radius: 8px;
222
+ -webkit-border-radius: 8px;
223
+ -moz-border-radius: 8px;
224
  }
225
 
226
  #mobile_groups li:hover,
227
+ #referrer_groups li:hover,
228
+ .w3tc_cachegroups li:hover {
229
+ background: #e9e9e9;
230
  }
231
 
232
  #mobile_groups li table,
233
+ #referrer_groups li table,
234
+ .w3tc_cachegroups li table {
235
+ margin: 0;
236
  }
237
 
238
  .mobile_group,
239
+ .referrer_group,
240
+ .cookiegroup_name {
241
+ font-weight: bold;
242
  }
243
 
244
  .w3tc-rules {
245
+ display: none;
246
+ margin: 1em 0;
247
+ padding: 0;
248
+ background: none;
249
  }
250
 
251
  .minify-files {
252
+ margin-bottom: 1em;
253
  }
254
 
255
  .minify-files li {
256
+ padding: 2px;
257
+ list-style: none;
258
+ background: #f0f0f0;
259
+ cursor: ns-resize;
260
+ border-radius: 8px;
261
+ -webkit-border-radius: 8px;
262
+ -moz-border-radius: 8px;
263
+ line-height: 100%;
264
  }
265
 
266
  .minify-files li:hover {
267
+ background: #e9e9e9;
268
  }
269
 
270
  .minify-files th,
271
  .minify-files td {
272
+ width: auto;
273
+ line-height: 100%;
274
+ padding: 3px 3px;
275
+ font-weight: normal;
276
+ text-align: left;
277
  }
278
 
279
  #support_loading, .w3tc-checking {
280
+ height: 32px;
281
+ background: url(../img/wpspin_light.gif) left center no-repeat;
282
+ padding-left: 38px;
283
+ line-height: 32px;
284
+ margin: 1em 0;
285
+ font-weight: bold;
286
  }
287
  #w3tc .postbox .inside {
288
+ padding: 0 10px;
289
  }
290
 
291
  #w3tc .postbox .hndle {
292
+ cursor: auto;
293
  }
294
 
295
  #pgcache_reject_roles label, #newrelic_accept_roles label, #cdn_reject_roles label {
296
+ margin-right: 15px;
297
  }
298
 
299
  #minify_form fieldset{
300
+ padding-bottom: 10px;
301
  }
302
 
303
  #minify_form .html-tag{
304
+ font-weight: bold;
305
+ color: #107e0e;
306
+ float: right;
307
  }
308
 
309
  #minify_form fieldset label{
310
+ margin-bottom: 5px;
311
+ margin-right:10px;
312
  }
313
 
314
  #minify_table td {
315
+ padding: 0;
316
  }
317
 
318
  #minify_table table td {
319
+ white-space: nowrap;
320
+ padding: 0;
321
  }
322
 
323
  #minify_table .placement {
324
+ width: 110px;
325
  }
326
 
327
  #minify_table .options {
328
+ padding-left: 10px;
329
  }
330
 
331
  .recom_js_type {
332
+ width:160px;
333
  }
334
  .w3tc-missing-files ul {
335
+ margin-left:5px;
336
  }
337
 
338
  #w3tc .updated p, #w3tc_dashboard p, #w3tc_general p, #w3tc_cdn p { line-height: 30px}
340
  #w3tc .updated p, #w3tc_general p, #w3tc_cdn p { line-height: 30px}
341
 
342
  #w3tc #application ul {
343
+ margin-top:0;
344
  }
345
 
346
  #monitoring td label{
347
+ display: block;
348
  }
349
 
350
  #monitoring td label input {
351
+ margin-right: 5px;
352
  }
353
 
354
  .w3tc-required-changes strong {
355
+ font-weight: bold;
356
+ font-family: courier, sans-serif;
357
  }
358
 
359
  .minify_auto_test, .w3tc-loading {
360
+ height: 16px;
361
+ background: url(../img/wpspin_light.gif) right top no-repeat;
362
+ width: 16px;
363
  }
364
  .create-error p {
365
+ margin:0;
366
  }
367
  .create-error {
368
+ padding: 3px;
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
 
376
  #w3tc_extensions table.extensions .column-name {
377
+ width:180px;
378
  }
379
  #wpbody-content .metabox-holder.extension-settings {
380
+ padding-top: 0;
381
  }
382
 
383
  #w3tc .subsubsub {
384
+ margin-left: 0;
385
  }
386
 
387
  #edge-mode.updated p {
388
+ line-height: 20px;
389
  }
390
 
391
  td.w3tc-td-with-button {
392
+ line-height: 28px;
393
  }
394
 
395
  .w3tc_loading {
396
+ position:absolute;
397
+ width: 100%;
398
+ text-align: center;
399
  }
400
 
401
  .w3tc_hidden {
402
+ visibility: hidden;
403
  }
404
 
405
  .w3tc_none {
406
+ display: none;
407
  }
408
 
409
  th.w3tc_config_checkbox {
410
+ padding-top: 15px;
411
  }
412
  td.w3tc_config_value_text {
413
+ padding-top: 20px;
414
  }
415
 
416
  .w3tc_cdn_cnames_readonly {
417
+ margin-top: .5em;
418
+ margin-right: 20px;
419
+ margin-bottom: .5em;
420
  }
421
 
422
  .w3tchelp_loading_outer {
423
+ width: 100%;
424
+ margin-top: 50px;
425
  }
426
 
427
  .w3tchelp_loading_inner {
428
+ margin-left: auto;
429
+ margin-right: auto;
430
  }
431
 
432
  .w3tc_menu_item_pro {
433
+ color: #0FA9B5;
434
  }
435
 
436
  .w3tc_menu_item_pro:hover {
437
+ color: #ddd;
438
  }
439
 
440
  .w3tc_popup_form {
441
+ padding: 20px;
442
  }
443
 
444
 
446
  /* js bound to id */
447
 
448
  th.w3tc_extensions_manage_column_check {
449
+ padding: 0 0 0 5px;
450
+ vertical-align: middle;
451
+ width: 2.2em;
452
  }
pub/js/lightbox.js CHANGED
@@ -6,7 +6,7 @@ var W3tc_Lightbox = {
6
  create: function() {
7
  var me = this;
8
 
9
- this.container = jQuery('<div class="' + this.options.id + '"><div class="lightbox-close">' + this.options.close + '</div><div class="lightbox-content"></div></div>').css({
10
  top: 0,
11
  left: 0,
12
  width: 0,
@@ -145,8 +145,8 @@ var W3tc_Lightbox = {
145
  var v = jQuery(form_selector).find('input').each(function(i) {
146
  var name = jQuery(this).attr('name');
147
  var type = jQuery(this).attr('type');
148
- if (type == 'radio') {
149
- if (!jQuery(this).attr('checked'))
150
  return;
151
  }
152
 
@@ -467,87 +467,6 @@ function w3tc_lightbox_cdn_s3_bucket_location(type, nonce) {
467
  });
468
  }
469
 
470
- function w3tc_lightbox_netdna_maxcdn_pull_zone(type, nonce) {
471
- W3tc_Lightbox.open({
472
- width: 500,
473
- height: 400,
474
- url: 'admin.php?page=w3tc_dashboard&w3tc_cdn_create_netdna_maxcdn_pull_zone_form&type=' + type + '&_wpnonce=' + nonce,
475
- callback: function(lightbox) {
476
- jQuery('#create_pull_zone', lightbox.container).click(function() {
477
- var loader = jQuery('#pull-zone-loading');
478
- loader.addClass('w3tc-loading');
479
- var pull_button = jQuery(this);
480
- pull_button.attr("disabled", "disabled");
481
- jQuery('.create-error').text('');
482
- var name_val = jQuery('#name', lightbox.container).val();
483
- var name_filter = /^[a-zA-Z\d\-]*$/;
484
- if (name_val == '') {
485
- jQuery('#name', lightbox.container).addClass('w3tc-error');
486
- jQuery('.name_message', lightbox.container).text('Cannot be empty.');
487
- } else if(name_val.length < 3) {
488
- jQuery('#name', lightbox.container).addClass('w3tc-error');
489
- jQuery('.name_message', lightbox.container).text('Too short.');
490
- } else if (name_val.length > 32) {
491
- jQuery('#name', lightbox.container).addClass('w3tc-error');
492
- jQuery('.name_message', lightbox.container).text('Too long.');
493
- } else if (!name_filter.test(name_val)) {
494
- jQuery('#name', lightbox.container).addClass('w3tc-error');
495
- jQuery('.name_message', lightbox.container).text('Cannot use unsupported characters.');
496
- } else {
497
- jQuery('#name', lightbox.container).removeClass('w3tc-error');
498
- jQuery('.name_message', lightbox.container).text('');
499
- }
500
-
501
- var label_val = jQuery('#label', lightbox.container).val();
502
- if (label_val == '') {
503
- jQuery('#label', lightbox.container).addClass('w3tc-error');
504
- jQuery('.label_message', lightbox.container).text('Cannot be empty.');
505
- } else if(label_val.length < 1) {
506
- jQuery('#label', lightbox.container).addClass('w3tc-error');
507
- jQuery('.label_message', lightbox.container).text('Too short.');
508
- } else if (label_val.length > 255) {
509
- jQuery('#label', lightbox.container).addClass('w3tc-error');
510
- jQuery('.label_message', lightbox.container).text('Too long.');
511
- } else {
512
- jQuery('#label', lightbox.container).removeClass('w3tc-error');
513
- jQuery('.label_message', lightbox.container).text('');
514
- }
515
- if (!jQuery('#label').hasClass('w3tc-error') && !jQuery('#name').hasClass('w3tc-error')) {
516
- jQuery.post('admin.php?page=w3tc_dashboard&w3tc_cdn_create_netdna_maxcdn_pull_zone', {name:name_val, label: label_val, nonce: jQuery('#_wp_nonce').val(), type: type},function(data) {
517
- loader.removeClass('w3tc-loading');
518
- if (data['status'] == 'error') {
519
- jQuery('.create-error').show();
520
- jQuery('.create-error').html('<p>Something is wrong:<br />' + data['message'] + '</p>');
521
- pull_button.removeAttr("disabled");
522
- } else {
523
- if (jQuery('#cdn_cnames > :first-child > :first-child').val() == '') {
524
- jQuery('#cdn_cnames > :first-child > :first-child').val(data['temporary_url']);
525
- jQuery('.netdna-maxcdn-form').html('<p>Pull zone was successfully created. Following url was added as default "Replace site\'s hostname with:" '
526
- + data['temporary_url']
527
- + '</p><p><input class="button-primary" onclick="window.location = \'admin.php?page=w3tc_dashboard&w3tc_cdn_save_activate&_wpnonce=' + nonce + '\'" value="Save, Activate & Close" />'
528
- + '</p>'
529
- );
530
- } else {
531
- jQuery('.netdna-maxcdn-form').html('<p>Pull zone was successfully created. cnames were already set so "Replace site\'s hostname with:" were not replaced with '
532
- + data['temporary_url']
533
- + '</p><p><input class="button-primary" onclick="window.location = \'admin.php?page=w3tc_dashboard&w3tc_cdn_save_activate&_wpnonce=' + nonce + '\'" value="Save, Activate & Close" />'
534
- + '</p>'
535
- );
536
- }
537
- }
538
- },
539
- 'json');
540
- } else {
541
- loader.removeClass('w3tc-loading');
542
- pull_button.removeAttr("disabled");
543
- }
544
- });
545
- jQuery('.button', lightbox.container).click(function() {
546
- lightbox.close();
547
- });
548
- }
549
- });
550
- }
551
 
552
  jQuery(function() {
553
  jQuery('.button-minify-recommendations').click(function() {
@@ -582,13 +501,6 @@ jQuery(function() {
582
  return false;
583
  });
584
 
585
- jQuery('#netdna-maxcdn-create-pull-zone').click(function() {
586
- var type = jQuery(this).metadata().type;
587
- var nonce = jQuery(this).metadata().nonce;
588
- w3tc_lightbox_netdna_maxcdn_pull_zone(type, nonce);
589
- return false;
590
- });
591
-
592
  jQuery('body').on('click', '.w3tc_lightbox_close', function() {
593
  W3tc_Lightbox.close();
594
  });
6
  create: function() {
7
  var me = this;
8
 
9
+ this.container = jQuery('<div class="' + this.options.id + '"><div class="lightbox-close">' + this.options.close + '</div><div id="w3tc_lightbox_content" class="lightbox-content"></div></div>').css({
10
  top: 0,
11
  left: 0,
12
  width: 0,
145
  var v = jQuery(form_selector).find('input').each(function(i) {
146
  var name = jQuery(this).attr('name');
147
  var type = jQuery(this).attr('type');
148
+ if (type == 'radio' || type == 'checkbox' ) {
149
+ if (!jQuery(this).prop('checked'))
150
  return;
151
  }
152
 
467
  });
468
  }
469
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
470
 
471
  jQuery(function() {
472
  jQuery('.button-minify-recommendations').click(function() {
501
  return false;
502
  });
503
 
 
 
 
 
 
 
 
504
  jQuery('body').on('click', '.w3tc_lightbox_close', function() {
505
  W3tc_Lightbox.close();
506
  });
pub/js/options.js CHANGED
@@ -260,132 +260,6 @@ function w3tc_beforeunload() {
260
  return 'Navigate away from this page without saving your changes?';
261
  }
262
 
263
- /**
264
- *
265
- * @param type
266
- * @param nonce
267
- */
268
- function w3tc_validate_cdn_key_result(type, nonce) {
269
- var key = jQuery('#cdn_' + type + '_authorization_key').val();
270
- jQuery('#cdn_result_message').text('');
271
- var result = jQuery('#validate_cdn_key_result');
272
- if (key.length == 0) {
273
- result.html('').removeClass('w3tc-error').removeClass('w3tc-success').removeClass('w3tc-checking');
274
- return;
275
- }
276
- result.html('Validating ...').addClass('w3tc-checking');
277
-
278
- if (key.split('+').length!=3) {
279
- result.removeClass('w3tc-checking');
280
- result.html('Key is invalid').addClass('w3tc-error');
281
- return;
282
- }
283
- var params = {
284
- w3tc_cdn_validate_authorization_key: 1,
285
- type: type,
286
- authorization_key: key,
287
- _wpnonce: nonce
288
- };
289
- jQuery('#validate_cdn_key').prop('disabled', true);
290
- jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
291
- result.html('').removeClass('w3tc-error').removeClass('w3tc-success').removeClass('w3tc-checking');
292
- var element;
293
- if (data.result == 'create') {
294
- jQuery('#create_zone_area').show();
295
- element = jQuery('#normal-sortables');
296
- if (element.length)
297
- element.masonry('reload');
298
- } else if (data.result == 'single') {
299
- var message = data.cnames.join('<br />');
300
- jQuery('#cdn_result_message').html('Preexisting zone has been selected and saved for the CDN engine. Hostnames used: <br />' + message);
301
- jQuery('#cdn_cnames > :first-child > :first-child').val(data.cnames.shift());
302
- for (var i in data.cnames) {
303
- jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="' + data.cnames[i] + '" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
304
- w3tc_cdn_cnames_assign();
305
- }
306
- } else if (data.result == 'many') {
307
- jQuery('#select_pull_zone').show();
308
- var mySelect = jQuery('#cdn_' + type +'_zone_id');
309
- mySelect.empty();
310
- jQuery.each(data.zones, function(val, zone) {
311
- mySelect.append(
312
- jQuery('<option></option>').val(zone.id).html(zone.name)
313
- );
314
- });
315
- if (data.data.id) {
316
- jQuery("#cdn_maxcdn_zone_id").val(data.data.id);
317
- var message = data.data.cnames.join('<br />');
318
- jQuery('#cdn_result_message').html('Preexisting zone has been selected and saved for the CDN engine. Hostnames used: <br />' + message);
319
- jQuery('#cdn_cnames > :first-child > :first-child').val(data.data.cnames.shift());
320
- for (var x in data.data.cnames) {
321
- jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="' + data.data.cnames[x] + '" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
322
- w3tc_cdn_cnames_assign();
323
- }
324
- }
325
- element = jQuery('#normal-sortables');
326
- if (element.length)
327
- element.masonry('reload');
328
- }
329
- result.removeClass('w3tc-checking');
330
- if (data.result != 'error' && data.result != 'notsupported')
331
- result.html('Key is valid').addClass('w3tc-success');
332
- else
333
- result.html(data.message).addClass('w3tc-error');
334
- jQuery('#validate_cdn_key').prop('disabled', false);
335
- }, 'json');
336
- }
337
-
338
- function w3tc_create_zone(type, nonce) {
339
- var params = {
340
- w3tc_cdn_auto_create_netdna_maxcdn_pull_zone: 1,
341
- type: type,
342
- authorization_key: jQuery('#cdn_' + type + '_authorization_key').val(),
343
- _wpnonce: nonce
344
- };
345
- var result = jQuery('#create_pull_zone_result');
346
- result.html('').removeClass('w3tc-error').removeClass('w3tc-success').removeClass('w3tc-checking');
347
- jQuery("#create_default_zone").prop('disabled', true);
348
- result.html('Creating ... ').addClass('w3tc-checking');
349
-
350
- jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
351
- if (data.cnames && data.cnames.length) {
352
- jQuery('#cdn_cnames > :first-child > :first-child').val(data.cnames.shift());
353
- for (var i in data.cnames) {
354
- jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="' + data.cnames[i] + '" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
355
- w3tc_cdn_cnames_assign();
356
- }
357
- result.text('Created ').removeClass('w3tc-checking').addClass('w3tc-success');
358
- } else {
359
- result.text(data.message).removeClass('w3tc-checking').addClass('w3tc-error');
360
- jQuery("#create_default_zone").prop('disabled', false);
361
-
362
- }
363
- }, 'json');
364
- }
365
-
366
- function w3tc_use_poll_zone(type, nonce) {
367
- var zone_id = jQuery("#cdn_" + type +"_zone_id").val();
368
- var params = {
369
- w3tc_cdn_use_netdna_maxcdn_pull_zone: 1,
370
- type: type,
371
- zone_id: zone_id,
372
- authorization_key: jQuery('#cdn_' + type + '_authorization_key').val(),
373
- _wpnonce: nonce
374
- };
375
- jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
376
- if (data.result == 'valid') {
377
- var message = data.cnames.join('<br />');
378
- jQuery('#cdn_result_message').html('Zone has been selected and saved for the CDN engine. Hostnames used: <br />' + message);
379
- jQuery('#cdn_cnames > :first-child > :first-child').val(data.cnames.shift());
380
- for (var i in data.cnames) {
381
- jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="' + data.cnames[i] + '" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
382
- w3tc_cdn_cnames_assign();
383
- }
384
- } else {
385
- alert(data.message);
386
- }
387
- }, 'json');
388
- }
389
 
390
  function w3tc_starts_with(s, starts_with) {
391
  s = s.replace(/\n/g, '');
@@ -397,8 +271,6 @@ function w3tc_starts_with(s, starts_with) {
397
 
398
  jQuery(function() {
399
  // general page
400
- w3tc_toggle('enabled');
401
-
402
  jQuery('.w3tc_read_technical_info').click(function() {
403
  jQuery('.w3tc_technical_info').toggle();
404
  });
@@ -727,7 +599,8 @@ jQuery(function() {
727
  engine: 's3',
728
  'config[key]': jQuery('#cdn_s3_key').val(),
729
  'config[secret]': jQuery('#cdn_s3_secret').val(),
730
- 'config[bucket]': jQuery('#cdn_s3_bucket').val()
 
731
  });
732
 
733
  if (cnames.length) {
@@ -741,6 +614,7 @@ jQuery(function() {
741
  'config[key]': jQuery('#cdn_cf_key').val(),
742
  'config[secret]': jQuery('#cdn_cf_secret').val(),
743
  'config[bucket]': jQuery('#cdn_cf_bucket').val(),
 
744
  'config[id]': jQuery('#cdn_cf_id').val()
745
  });
746
 
@@ -801,29 +675,6 @@ jQuery(function() {
801
  }
802
  break;
803
 
804
- case 'maxcdn':
805
- jQuery.extend(params, {
806
- engine: 'maxcdn',
807
- 'config[authorization_key]': jQuery('#cdn_maxcdn_authorization_key').val(),
808
- 'config[zone_id]': jQuery('#cdn_maxcdn_zone_id').val()
809
- });
810
-
811
- if (cnames.length) {
812
- params['config[domain][]'] = cnames;
813
- }
814
- break;
815
- case 'netdna':
816
- jQuery.extend(params, {
817
- engine: 'netdna',
818
- 'config[authorization_key]': jQuery('#cdn_netdna_authorization_key').val(),
819
- 'config[zone_id]': jQuery('#cdn_netdna_zone_id').val()
820
- });
821
-
822
- if (cnames.length) {
823
- params['config[domain][]'] = cnames;
824
- }
825
- break;
826
-
827
  case 'cotendo':
828
  var zones = [], zones_val = jQuery('#cdn_cotendo_zones').val();
829
 
@@ -901,6 +752,12 @@ jQuery(function() {
901
  status.removeClass('w3tc-error');
902
  status.removeClass('w3tc-success');
903
  status.addClass('w3tc-process');
 
 
 
 
 
 
904
  status.html('Testing...');
905
 
906
  jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
@@ -1003,6 +860,12 @@ jQuery(function() {
1003
  status.removeClass('w3tc-error');
1004
  status.removeClass('w3tc-success');
1005
  status.addClass('w3tc-process');
 
 
 
 
 
 
1006
  status.html('Creating...');
1007
 
1008
  jQuery.post('admin.php?page=w3tc_dashboard', params, function(data) {
@@ -1047,6 +910,8 @@ jQuery(function() {
1047
  jQuery.post('admin.php?page=w3tc_dashboard', {
1048
  w3tc_test_redis: 1,
1049
  servers: jQuery('#redis_servers').val(),
 
 
1050
  _wpnonce: jQuery(this).metadata().nonce
1051
  }, function(data) {
1052
  status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
@@ -1146,134 +1011,6 @@ jQuery(function() {
1146
  return ret;
1147
  });
1148
 
1149
- // support tabs
1150
- jQuery('#support_more_files').live('click', function() {
1151
- jQuery(this).before('<input type="file" name="files[]" /><br />');
1152
-
1153
- return false;
1154
- });
1155
-
1156
- jQuery('#support_form').live('submit', function() {
1157
- var url = jQuery('.required #support_url');
1158
- var name = jQuery('.required #support_name');
1159
- var email = jQuery('.required #support_email');
1160
- var phone = jQuery('.required #support_phone');
1161
- var subject = jQuery('.required #support_subject');
1162
- var description = jQuery('.required #support_description');
1163
- var wp_login = jQuery('.required #support_wp_login');
1164
- var wp_password = jQuery('.required #support_wp_password');
1165
- var ftp_host = jQuery('.required #support_ftp_host');
1166
- var ftp_login = jQuery('.required #support_ftp_login');
1167
- var ftp_password = jQuery('.required #support_ftp_password');
1168
-
1169
- if (url.size() && url.val() == '') {
1170
- alert('Please enter the address of your site in the Site URL field.');
1171
- url.focus();
1172
- return false;
1173
- }
1174
-
1175
- if (name.size() && name.val() == '') {
1176
- alert('Please enter your name in the Name field.');
1177
- name.focus();
1178
- return false;
1179
- }
1180
-
1181
- if (email.size() && !/^[a-z0-9_\-\.]+@[a-z0-9-\.]+\.[a-z]{2,5}$/.test(email.val().toLowerCase())) {
1182
- alert('Please enter valid email address in the E-Mail field.');
1183
- email.focus();
1184
- return false;
1185
- }
1186
-
1187
- if (phone.size() && !/^[0-9\-\. \(\)\+]+$/.test(phone.val())) {
1188
- alert('Please enter your phone in the phone field.');
1189
- phone.focus();
1190
- return false;
1191
- }
1192
-
1193
- if (subject.size() && subject.val() == '') {
1194
- alert('Please enter subject in the subject field.');
1195
- subject.focus();
1196
- return false;
1197
- }
1198
-
1199
- if (description.size() && description.val() == '') {
1200
- alert('Please describe the issue in the issue description field.');
1201
- description.focus();
1202
- return false;
1203
- }
1204
-
1205
- if (wp_login.size() && wp_login.val() == '') {
1206
- alert('Please enter an administrator login. Remember you can create a temporary one just for this support case.');
1207
- wp_login.focus();
1208
- return false;
1209
- }
1210
-
1211
- if (wp_password.size() && wp_password.val() == '') {
1212
- alert('Please enter WP Admin password, be sure it\'s spelled correctly.');
1213
- wp_password.focus();
1214
- return false;
1215
- }
1216
-
1217
- if (ftp_host.size() && ftp_host.val() == '') {
1218
- alert('Please enter SSH or FTP host for your site.');
1219
- ftp_host.focus();
1220
- return false;
1221
- }
1222
-
1223
- if (ftp_login.size() && ftp_login.val() == '') {
1224
- alert('Please enter SSH or FTP login for your server. Remember you can create a temporary one just for this support case.');
1225
- ftp_login.focus();
1226
- return false;
1227
- }
1228
-
1229
- if (ftp_password.size() && ftp_password.val() == '') {
1230
- alert('Please enter SSH or FTP password for your FTP account.');
1231
- ftp_password.focus();
1232
- return false;
1233
- }
1234
-
1235
- return true;
1236
- });
1237
-
1238
- jQuery('#support_request_type').live('change', function() {
1239
- var request_type = jQuery(this);
1240
-
1241
- if (request_type.val() == '') {
1242
- alert('Please select request type.');
1243
- request_type.focus();
1244
-
1245
- return false;
1246
- }
1247
-
1248
- var type = request_type.val(), action = '';
1249
-
1250
- switch (type) {
1251
- case 'bug_report':
1252
- case 'new_feature':
1253
- action = 'support_form';
1254
- break;
1255
-
1256
- case 'email_support':
1257
- case 'phone_support':
1258
- case 'plugin_config':
1259
- case 'theme_config':
1260
- case 'linux_config':
1261
- action = 'support_payment';
1262
- break;
1263
- }
1264
-
1265
- if (action) {
1266
- jQuery('#support_container').html('<div id="support_loading">Loading...</div>').load('admin.php?page=w3tc_support&w3tc_' + action + '&request_type=' + type + '&_wpnonce=' + request_type.metadata().nonce);
1267
-
1268
- return false;
1269
- }
1270
-
1271
- return true;
1272
- });
1273
-
1274
- jQuery('#support_cancel').live('click', function() {
1275
- jQuery('#support_container').html('<div id="support_loading">Loading...</div>').load('admin.php?page=w3tc_support&w3tc_support_select&_wpnonce=' + jQuery(this).metadata().nonce);
1276
- });
1277
 
1278
  // mobile tab
1279
  jQuery('#mobile_form').submit(function() {
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, '');
271
 
272
  jQuery(function() {
273
  // general page
 
 
274
  jQuery('.w3tc_read_technical_info').click(function() {
275
  jQuery('.w3tc_technical_info').toggle();
276
  });
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) {
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
 
675
  }
676
  break;
677
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
678
  case 'cotendo':
679
  var zones = [], zones_val = jQuery('#cdn_cotendo_zones').val();
680
 
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) {
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) {
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');
1011
  return ret;
1012
  });
1013
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1014
 
1015
  // mobile tab
1016
  jQuery('#mobile_form').submit(function() {
pub/opcache.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /**
3
- * W3 Total Cache APC
4
  */
5
 
6
  if ( !defined( 'ABSPATH' ) ) {
1
  <?php
2
  /**
3
+ * W3 Total Cache OPcache
4
  */
5
 
6
  if ( !defined( 'ABSPATH' ) ) {
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.7.1
6
- Stable tag: 0.9.5.4
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -283,6 +283,33 @@ Please reach out to all of these people and support their projects if you're so
283
 
284
  == Changelog ==
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  = 0.9.5.4 =
287
  * Fixed regression with browser caching and query strings
288
 
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
 
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)
302
+ * Improved handling of timeouts to origin push CDN proviers
303
+ * Added HTTP/2 push headers for disk enhanced page caching (via nigrosimone)
304
+ * Added X-Forwarded-Proto header for use cases like HTTPS recognition behind proxies or load balancers
305
+ * Added multiple CDN support i.e. static file objects and pages, posts, feeds, API responses etc to use different respective CDN providers
306
+ * Added page caching by cookie name or value (sponsored by SQweb)
307
+ * Added toggle for CORS header to improve inter-operatbility with various CDN providers
308
+ * Added support for CDN hosted media to media library (inspired by amiga-500)
309
+ * Added object caching of AJAX calls (via andyexeter)
310
+ * Enterprise features are now available to Pro subscribers! Including reading from multiple databases concurrently and purging caches across multiple hosts via a Message Bus
311
+
312
+
313
  = 0.9.5.4 =
314
  * Fixed regression with browser caching and query strings
315
 
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.5.4' );
9
  define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
10
  define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
11
  define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
@@ -76,6 +76,7 @@ define( 'W3TC_CDN_COMMAND_UPLOAD', 1 );
76
  define( 'W3TC_CDN_COMMAND_DELETE', 2 );
77
  define( 'W3TC_CDN_COMMAND_PURGE', 3 );
78
  define( 'W3TC_CDN_TABLE_QUEUE', 'w3tc_cdn_queue' );
 
79
 
80
  define( 'W3TC_INSTALL_FILE_ADVANCED_CACHE', W3TC_INSTALL_DIR . '/advanced-cache.php' );
81
  define( 'W3TC_INSTALL_FILE_DB', W3TC_INSTALL_DIR . '/db.php' );
@@ -153,6 +154,10 @@ function w3tc_class_autoload( $class ) {
153
  if ( file_exists( $filePath ) )
154
  require $filePath;
155
  return;
 
 
 
 
156
  }
157
 
158
  if ( !is_null( $base ) ) {
@@ -167,8 +172,8 @@ function w3tc_class_autoload( $class ) {
167
  require $filename;
168
  } else {
169
  if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
170
- echo 'Attempt to create object of class ' .
171
- $class . ' has been made, but file ' .
172
  $filename . ' doesnt exists';
173
  debug_print_backtrace();
174
  }
@@ -195,7 +200,7 @@ spl_autoload_register( 'w3tc_class_autoload' );
195
  function w3tc_config() {
196
  /*
197
  * Some plugins make incorrect decisions based on configuration
198
- * and force to disable modules working otherwise or
199
  * adds notices on each wp-admin page without ability to remove it.
200
  * By defining W3TC_CONFIG_HIDE you may still use w3tc configuration you like.
201
  */
@@ -209,33 +214,33 @@ function w3tc_config() {
209
  /**
210
  * Shortcut for url varnish flush
211
  */
212
- function w3tc_flush_all() {
213
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
214
- $o->flush_all();
215
  }
216
 
217
  /**
218
  * Purges/Flushes post page
219
  */
220
- function w3tc_flush_post( $post_id ) {
221
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
222
- $o->flush_post( $post_id );
223
  }
224
 
225
  /**
226
  * Purges/Flushes all posts
227
  */
228
- function w3tc_flush_posts() {
229
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
230
- $o->flush_posts();
231
  }
232
 
233
  /**
234
  * Purges/Flushes url
235
  */
236
- function w3tc_flush_url( $url ) {
237
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
238
- $o->flush_url( $url );
239
  }
240
 
241
 
@@ -532,7 +537,7 @@ function w3tc_opcache_flush_file( $file, $http = false ) {
532
  * Deprecated. Retained for 3rd parties that used it. see w3tc_config()
533
  *
534
  * Some plugins make incorrect decisions based on configuration
535
- * and force to disable modules working otherwise or
536
  * adds notices on each wp-admin page without ability to remove it.
537
  * By defining W3TC_CONFIG_HIDE you may still use w3tc configuration you like.
538
  */
@@ -540,11 +545,11 @@ if ( defined( 'W3TC_CONFIG_HIDE' ) && W3TC_CONFIG_HIDE ) {
540
  class W3_Config {
541
  public function __construct( $master = false, $blog_id = null ) {
542
  }
543
-
544
  public function get_string( $key, $default = '', $trim = true ) {
545
  return '';
546
  }
547
-
548
  public function get_integer( $key, $default = 0 ) {
549
  return 0;
550
  }
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' );
76
  define( 'W3TC_CDN_COMMAND_DELETE', 2 );
77
  define( 'W3TC_CDN_COMMAND_PURGE', 3 );
78
  define( 'W3TC_CDN_TABLE_QUEUE', 'w3tc_cdn_queue' );
79
+ define( 'W3TC_CDN_TABLE_PATHMAP', 'w3tc_cdn_pathmap' );
80
 
81
  define( 'W3TC_INSTALL_FILE_ADVANCED_CACHE', W3TC_INSTALL_DIR . '/advanced-cache.php' );
82
  define( 'W3TC_INSTALL_FILE_DB', W3TC_INSTALL_DIR . '/db.php' );
154
  if ( file_exists( $filePath ) )
155
  require $filePath;
156
  return;
157
+ } elseif ( substr( $class, 0, 24 ) == 'w3tc_tubalmartin\\CssMin\\' ) {
158
+ $base = W3TC_LIB_DIR . DIRECTORY_SEPARATOR . 'Minify' . DIRECTORY_SEPARATOR .
159
+ 'YUI-CSS-compressor-PHP-port-4.1.0' . DIRECTORY_SEPARATOR;
160
+ $class = substr( $class, 24 );
161
  }
162
 
163
  if ( !is_null( $base ) ) {
172
  require $filename;
173
  } else {
174
  if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
175
+ echo 'Attempt to create object of class ' .
176
+ $class . ' has been made, but file ' .
177
  $filename . ' doesnt exists';
178
  debug_print_backtrace();
179
  }
200
  function w3tc_config() {
201
  /*
202
  * Some plugins make incorrect decisions based on configuration
203
+ * and force to disable modules working otherwise or
204
  * adds notices on each wp-admin page without ability to remove it.
205
  * By defining W3TC_CONFIG_HIDE you may still use w3tc configuration you like.
206
  */
214
  /**
215
  * Shortcut for url varnish flush
216
  */
217
+ function w3tc_flush_all( $extras = null ) {
218
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
219
+ $o->flush_all( $extras );
220
  }
221
 
222
  /**
223
  * Purges/Flushes post page
224
  */
225
+ function w3tc_flush_post( $post_id, $extras = null ) {
226
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
227
+ $o->flush_post( $post_id, $extras );
228
  }
229
 
230
  /**
231
  * Purges/Flushes all posts
232
  */
233
+ function w3tc_flush_posts( $extras = null ) {
234
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
235
+ $o->flush_posts( $extras );
236
  }
237
 
238
  /**
239
  * Purges/Flushes url
240
  */
241
+ function w3tc_flush_url( $url, $extras = null ) {
242
  $o = \W3TC\Dispatcher::component( 'CacheFlush' );
243
+ $o->flush_url( $url, $extras );
244
  }
245
 
246
 
537
  * Deprecated. Retained for 3rd parties that used it. see w3tc_config()
538
  *
539
  * Some plugins make incorrect decisions based on configuration
540
+ * and force to disable modules working otherwise or
541
  * adds notices on each wp-admin page without ability to remove it.
542
  * By defining W3TC_CONFIG_HIDE you may still use w3tc configuration you like.
543
  */
545
  class W3_Config {
546
  public function __construct( $master = false, $blog_id = null ) {
547
  }
548
+
549
  public function get_string( $key, $default = '', $trim = true ) {
550
  return '';
551
  }
552
+
553
  public function get_integer( $key, $default = 0 ) {
554
  return 0;
555
  }
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.5.4
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.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