Comet Cache - Version 170220

Version Description

= v160416 =

Requires WordPress v4.2+.

Download this release

Release Info

Developer raamdev
Plugin Icon 128x128 Comet Cache
Version 170220
Comparing to
See all releases

Code changes from version 161221 to 170220

Files changed (34) hide show
  1. comet-cache.php +2 -2
  2. plugin.php +1 -1
  3. readme.txt +30 -2
  4. src/includes/api.php +1 -1
  5. src/includes/classes/Actions.php +13 -10
  6. src/includes/classes/AdvancedCache.php +33 -12
  7. src/includes/classes/MenuPageOptions.php +41 -21
  8. src/includes/classes/Plugin.php +20 -10
  9. src/includes/classes/VsUpgrades.php +5 -10
  10. src/includes/interfaces/Shared/NcDebugConsts.php +24 -6
  11. src/includes/plugin.php +1 -1
  12. src/includes/stub.php +2 -2
  13. src/includes/templates/ac-plugin.txt +1 -1
  14. src/includes/templates/advanced-cache.x-php +13 -1
  15. src/includes/templates/htaccess/canonical-urls-no-ts-enable.txt +3 -0
  16. src/includes/templates/htaccess/canonical-urls-ts-enable.txt +3 -0
  17. src/includes/templates/htaccess/enforce-exact-host-name.txt +15 -0
  18. src/includes/traits/Ac/NcDebugUtils.php +17 -1
  19. src/includes/traits/Ac/ObUtils.php +39 -18
  20. src/includes/traits/Ac/PostloadUtils.php +8 -8
  21. src/includes/traits/Plugin/CronUtils.php +3 -2
  22. src/includes/traits/Plugin/HtaccessUtils.php +61 -56
  23. src/includes/traits/Plugin/InstallUtils.php +8 -4
  24. src/includes/traits/Plugin/OptionUtils.php +26 -27
  25. src/includes/traits/Plugin/UpdateUtils.php +0 -41
  26. src/includes/traits/Plugin/WcpDateArchiveUtils.php +94 -0
  27. src/includes/traits/Plugin/WcpPostUtils.php +1 -0
  28. src/includes/traits/Shared/CacheDirUtils.php +12 -7
  29. src/includes/traits/Shared/ServerUtils.php +15 -8
  30. src/includes/uninstall.php +1 -1
  31. src/vendor/autoload.php +1 -1
  32. src/vendor/composer/autoload_classmap.php +1 -1
  33. src/vendor/composer/autoload_real.php +3 -3
  34. uninstall.php +1 -1
comet-cache.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Version: 161221
4
  Text Domain: comet-cache
5
  Plugin Name: Comet Cache
6
  Network: true
@@ -12,6 +12,6 @@ Plugin URI: http://cometcache.com/
12
  Description: Comet Cache is an advanced WordPress caching plugin inspired by simplicity.
13
  */
14
  if (!defined('WPINC')) {
15
- exit('Do NOT access this file directly: '.basename(__FILE__));
16
  }
17
  require_once dirname(__FILE__).'/plugin.php';
1
  <?php
2
  /*
3
+ Version: 170220
4
  Text Domain: comet-cache
5
  Plugin Name: Comet Cache
6
  Network: true
12
  Description: Comet Cache is an advanced WordPress caching plugin inspired by simplicity.
13
  */
14
  if (!defined('WPINC')) {
15
+ exit('Do NOT access this file directly.');
16
  }
17
  require_once dirname(__FILE__).'/plugin.php';
plugin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  if (!defined('WPINC')) {
3
- exit('Do NOT access this file directly: '.basename(__FILE__));
4
  }
5
  $GLOBALS['wp_php_rv']['rv'] = '5.3.2'; //php-required-version// // Leaving this at v5.3.2 so that we can have more control over Dashboard messages below.
6
  $GLOBALS['wp_php_rv']['re'] = array('mbstring');
1
  <?php
2
  if (!defined('WPINC')) {
3
+ exit('Do NOT access this file directly.');
4
  }
5
  $GLOBALS['wp_php_rv']['rv'] = '5.3.2'; //php-required-version// // Leaving this at v5.3.2 so that we can have more control over Dashboard messages below.
6
  $GLOBALS['wp_php_rv']['re'] = array('mbstring');
readme.txt CHANGED
@@ -1,8 +1,8 @@
1
  === Comet Cache ===
2
 
3
- Stable tag: 161221
4
  Requires at least: 4.2
5
- Tested up to: 4.8-alpha
6
  Text Domain: comet-cache
7
 
8
  License: GPLv2 or later
@@ -340,6 +340,34 @@ Requires WordPress v4.2+.
340
 
341
  == Changelog ==
342
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  = v161221 =
344
 
345
  - **Bug Fix:** Improving PHP OPcache detection. Now considering the INI option `opcache.restrict_api`. Comet Cache is now smart enough to avoid generating the PHP Warning: _PHP Warning: Zend OPcache API is restricted by "restrict_api" configuration directive_. See [Issue #733](https://github.com/websharks/comet-cache/issues/733).
1
  === Comet Cache ===
2
 
3
+ Stable tag: 170220
4
  Requires at least: 4.2
5
+ Tested up to: 4.9.4
6
  Text Domain: comet-cache
7
 
8
  License: GPLv2 or later
340
 
341
  == Changelog ==
342
 
343
+ = v170220 =
344
+
345
+ - **New Feature:** Comet Cache can now be configured to automatically clear the cache for date-based archive views whenever any single post is cleared due to changes in content, title, etc. See: **Dashboard → Comet Cache → Plugin Options → Automatic Cache Clearing → Auto-Clear "Date-Based Archives" Too?**. See also: [Issue #724](https://github.com/websharks/comet-cache/issues/724).
346
+ - **New Pro Feature:** Apache Optimizations now include a new option that allows site owners to enforce an exact host name for all requests. See: **Dashboard → Comet Cache Pro → Plugin Options → Apache Optimizations → Enforce an Exact Host Name?**. See also: [Issue #101](https://github.com/websharks/comet-cache/issues/101).
347
+ - **Bug Fix:** Apache detection sometimes inaccurate. So instead of using default WP core globals for server detection, Comet Cache now uses it's own set of Apache/Nginx/IIS detection functions. And, this release enhances our Apache and Nginx detection routines; making them smart enough to catch additional edge cases; i.e., to further reduce the likelihood of there being a false-positive. See [Issue #748](https://github.com/websharks/comet-cache/issues/748).
348
+ - **Bug Fix:** Some XML-RPC and REST API requests were being cached inadvertently. See [Issue #855](https://github.com/websharks/comet-cache/issues/855).
349
+ - **Bug Fix:** Broken textarea field due to `white-space:nowrap` in Firefox. See [Issue #866](https://github.com/websharks/comet-cache/issues/866).
350
+ - **Bug Fix:** This release resolves empty directories being left in the cache folder, in some scenarios. See [Thread #866](https://forums.wpsharks.com/t/cache-folders-not-removed-during-clean-up-process/866).
351
+ - **Bug Fix** (Pro): Some REST requests were being redirected incorrectly whenever Apache Optimizations were enabled. See [Issue #855](https://github.com/websharks/comet-cache/issues/855).
352
+ - **Compatibility Bug Fix:** Some Jetpack API calls were being cached inadvertently. See [Issue #855](https://github.com/websharks/comet-cache/issues/855).
353
+ - **Enhancement:** Notes in HTML source now indicate fully functional on first load for improved clarity. See [Issue #860](https://github.com/websharks/comet-cache/issues/860).
354
+ - **Enhancement:** Enhancing security by removing `basename(__FILE__)` from direct access notices.
355
+
356
+ = v161227 =
357
+
358
+ _**Note:** This is a Comet Cache Pro maintenance release._
359
+
360
+ - **Bug Fix** (Pro): Resolves an issue with the previous Pro maintenance release (v161226) where `admin-bar.min.css` was missing, which caused issues with the Admin Bar buttons. This was due to a glitch in our build system. See [Issue #864](https://github.com/websharks/comet-cache/issues/864).
361
+
362
+ = v161226 =
363
+
364
+ _**Note:** This is a Comet Cache Pro maintenance release._
365
+
366
+ - **Bug Fix** (Pro): Resolves error `Unable to determine UA info directory location` when upgrading to latest release. See [Issue #862](https://github.com/websharks/comet-cache/issues/862).
367
+ - **Bug Fix** (Pro): Enhancing compatibility with InfiniteWP, ManageWP, and other remote management tools for WordPress. See [Issue #862](https://github.com/websharks/comet-cache/issues/862).
368
+ - **Bug Fix** (Pro): Incorrect time calculations whenever load average checks are enabled in Comet Cache configuration options. See [Issue #853](https://github.com/websharks/comet-cache/issues/853).
369
+ - **Cleanup:** Removed an old API call that checked for a newer lite version. No longer necessary.
370
+
371
  = v161221 =
372
 
373
  - **Bug Fix:** Improving PHP OPcache detection. Now considering the INI option `opcache.restrict_api`. Comet Cache is now smart enough to avoid generating the PHP Warning: _PHP Warning: Zend OPcache API is restricted by "restrict_api" configuration directive_. See [Issue #733](https://github.com/websharks/comet-cache/issues/733).
src/includes/api.php CHANGED
@@ -9,7 +9,7 @@ namespace WebSharks\CometCache;
9
  use WebSharks\CometCache\Classes;
10
 
11
  if (!defined('WPINC')) {
12
- exit('Do NOT access this file directly: '.basename(__FILE__));
13
  }
14
  class_alias(__NAMESPACE__.'\\Classes\\ApiBase', GLOBAL_NS);
15
 
9
  use WebSharks\CometCache\Classes;
10
 
11
  if (!defined('WPINC')) {
12
+ exit('Do NOT access this file directly.');
13
  }
14
  class_alias(__NAMESPACE__.'\\Classes\\ApiBase', GLOBAL_NS);
15
 
src/includes/classes/Actions.php CHANGED
@@ -66,6 +66,7 @@ class Actions extends AbsBase
66
  * @since 150422 Rewrite.
67
  *
68
  * @param mixed Input action argument(s).
 
69
  */
70
  protected function wipeCache($args)
71
  {
@@ -91,6 +92,7 @@ class Actions extends AbsBase
91
  * @since 150422 Rewrite.
92
  *
93
  * @param mixed Input action argument(s).
 
94
  */
95
  protected function clearCache($args)
96
  {
@@ -116,6 +118,7 @@ class Actions extends AbsBase
116
  * @since 150422 Rewrite.
117
  *
118
  * @param mixed Input action argument(s).
 
119
  */
120
  protected function ajaxWipeCache($args)
121
  {
@@ -140,6 +143,7 @@ class Actions extends AbsBase
140
  * @since 150422 Rewrite.
141
  *
142
  * @param mixed Input action argument(s).
 
143
  */
144
  protected function ajaxClearCache($args)
145
  {
@@ -185,11 +189,10 @@ class Actions extends AbsBase
185
  * @since 150422 Rewrite.
186
  *
187
  * @param mixed Input action argument(s).
 
188
  */
189
  protected function saveOptions($args)
190
  {
191
- global $is_apache, $is_nginx;
192
-
193
  if (!current_user_can($this->plugin->cap)) {
194
  return; // Nothing to do.
195
  } elseif (empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) {
@@ -222,10 +225,10 @@ class Actions extends AbsBase
222
  if (!($add_wp_cache_to_wp_config = $this->plugin->addWpCacheToWpConfig())) {
223
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_add_failure'] = '1';
224
  }
225
- if ($is_apache && !($add_wp_htaccess = $this->plugin->addWpHtaccess())) {
226
  $query_args[GLOBAL_NS.'_wp_htaccess_add_failure'] = '1';
227
  }
228
- if ($is_nginx && $this->plugin->applyWpFilters(GLOBAL_NS.'_wp_htaccess_nginx_notice', true)
229
  && (!isset($_SERVER['WP_NGINX_CONFIG']) || $_SERVER['WP_NGINX_CONFIG'] !== 'done')) {
230
  $query_args[GLOBAL_NS.'_wp_htaccess_nginx_notice'] = '1';
231
  }
@@ -246,7 +249,7 @@ class Actions extends AbsBase
246
  if (!($remove_wp_cache_from_wp_config = $this->plugin->removeWpCacheFromWpConfig())) {
247
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_remove_failure'] = '1';
248
  }
249
- if ($is_apache && !($remove_wp_htaccess = $this->plugin->removeWpHtaccess())) {
250
  $query_args[GLOBAL_NS.'_wp_htaccess_remove_failure'] = '1';
251
  }
252
  if (!($remove_advanced_cache = $this->plugin->removeAdvancedCache())) {
@@ -269,11 +272,10 @@ class Actions extends AbsBase
269
  * @since 150422 Rewrite.
270
  *
271
  * @param mixed Input action argument(s).
 
272
  */
273
  protected function restoreDefaultOptions($args)
274
  {
275
- global $is_apache, $is_nginx;
276
-
277
  if (!current_user_can($this->plugin->cap)) {
278
  return; // Nothing to do.
279
  } elseif (is_multisite() && !current_user_can($this->plugin->network_cap)) {
@@ -292,10 +294,10 @@ class Actions extends AbsBase
292
  if (!($add_wp_cache_to_wp_config = $this->plugin->addWpCacheToWpConfig())) {
293
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_add_failure'] = '1';
294
  }
295
- if ($is_apache && !($add_wp_htaccess = $this->plugin->addWpHtaccess())) {
296
  $query_args[GLOBAL_NS.'_wp_htaccess_add_failure'] = '1';
297
  }
298
- if ($is_nginx && $this->plugin->applyWpFilters(GLOBAL_NS.'_wp_htaccess_nginx_notice', true)
299
  && (!isset($_SERVER['WP_NGINX_CONFIG']) || $_SERVER['WP_NGINX_CONFIG'] !== 'done')) {
300
  $query_args[GLOBAL_NS.'_wp_htaccess_nginx_notice'] = '1';
301
  }
@@ -316,7 +318,7 @@ class Actions extends AbsBase
316
  if (!($remove_wp_cache_from_wp_config = $this->plugin->removeWpCacheFromWpConfig())) {
317
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_remove_failure'] = '1';
318
  }
319
- if ($is_apache && !($remove_wp_htaccess = $this->plugin->removeWpHtaccess())) {
320
  $query_args[GLOBAL_NS.'_wp_htaccess_remove_failure'] = '1';
321
  }
322
  if (!($remove_advanced_cache = $this->plugin->removeAdvancedCache())) {
@@ -341,6 +343,7 @@ class Actions extends AbsBase
341
  * @since 150422 Rewrite.
342
  *
343
  * @param mixed Input action argument(s).
 
344
  */
345
  protected function dismissNotice($args)
346
  {
66
  * @since 150422 Rewrite.
67
  *
68
  * @param mixed Input action argument(s).
69
+ * @param mixed $args
70
  */
71
  protected function wipeCache($args)
72
  {
92
  * @since 150422 Rewrite.
93
  *
94
  * @param mixed Input action argument(s).
95
+ * @param mixed $args
96
  */
97
  protected function clearCache($args)
98
  {
118
  * @since 150422 Rewrite.
119
  *
120
  * @param mixed Input action argument(s).
121
+ * @param mixed $args
122
  */
123
  protected function ajaxWipeCache($args)
124
  {
143
  * @since 150422 Rewrite.
144
  *
145
  * @param mixed Input action argument(s).
146
+ * @param mixed $args
147
  */
148
  protected function ajaxClearCache($args)
149
  {
189
  * @since 150422 Rewrite.
190
  *
191
  * @param mixed Input action argument(s).
192
+ * @param mixed $args
193
  */
194
  protected function saveOptions($args)
195
  {
 
 
196
  if (!current_user_can($this->plugin->cap)) {
197
  return; // Nothing to do.
198
  } elseif (empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) {
225
  if (!($add_wp_cache_to_wp_config = $this->plugin->addWpCacheToWpConfig())) {
226
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_add_failure'] = '1';
227
  }
228
+ if ($this->plugin->isApache() && !($add_wp_htaccess = $this->plugin->addWpHtaccess())) {
229
  $query_args[GLOBAL_NS.'_wp_htaccess_add_failure'] = '1';
230
  }
231
+ if ($this->plugin->isNginx() && $this->plugin->applyWpFilters(GLOBAL_NS.'_wp_htaccess_nginx_notice', true)
232
  && (!isset($_SERVER['WP_NGINX_CONFIG']) || $_SERVER['WP_NGINX_CONFIG'] !== 'done')) {
233
  $query_args[GLOBAL_NS.'_wp_htaccess_nginx_notice'] = '1';
234
  }
249
  if (!($remove_wp_cache_from_wp_config = $this->plugin->removeWpCacheFromWpConfig())) {
250
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_remove_failure'] = '1';
251
  }
252
+ if ($this->plugin->isApache() && !($remove_wp_htaccess = $this->plugin->removeWpHtaccess())) {
253
  $query_args[GLOBAL_NS.'_wp_htaccess_remove_failure'] = '1';
254
  }
255
  if (!($remove_advanced_cache = $this->plugin->removeAdvancedCache())) {
272
  * @since 150422 Rewrite.
273
  *
274
  * @param mixed Input action argument(s).
275
+ * @param mixed $args
276
  */
277
  protected function restoreDefaultOptions($args)
278
  {
 
 
279
  if (!current_user_can($this->plugin->cap)) {
280
  return; // Nothing to do.
281
  } elseif (is_multisite() && !current_user_can($this->plugin->network_cap)) {
294
  if (!($add_wp_cache_to_wp_config = $this->plugin->addWpCacheToWpConfig())) {
295
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_add_failure'] = '1';
296
  }
297
+ if ($this->plugin->isApache() && !($add_wp_htaccess = $this->plugin->addWpHtaccess())) {
298
  $query_args[GLOBAL_NS.'_wp_htaccess_add_failure'] = '1';
299
  }
300
+ if ($this->plugin->isNginx() && $this->plugin->applyWpFilters(GLOBAL_NS.'_wp_htaccess_nginx_notice', true)
301
  && (!isset($_SERVER['WP_NGINX_CONFIG']) || $_SERVER['WP_NGINX_CONFIG'] !== 'done')) {
302
  $query_args[GLOBAL_NS.'_wp_htaccess_nginx_notice'] = '1';
303
  }
318
  if (!($remove_wp_cache_from_wp_config = $this->plugin->removeWpCacheFromWpConfig())) {
319
  $query_args[GLOBAL_NS.'_wp_config_wp_cache_remove_failure'] = '1';
320
  }
321
+ if ($this->plugin->isApache() && !($remove_wp_htaccess = $this->plugin->removeWpHtaccess())) {
322
  $query_args[GLOBAL_NS.'_wp_htaccess_remove_failure'] = '1';
323
  }
324
  if (!($remove_advanced_cache = $this->plugin->removeAdvancedCache())) {
343
  * @since 150422 Rewrite.
344
  *
345
  * @param mixed Input action argument(s).
346
+ * @param mixed $args
347
  */
348
  protected function dismissNotice($args)
349
  {
src/includes/classes/AdvancedCache.php CHANGED
@@ -21,38 +21,59 @@ class AdvancedCache extends AbsBaseAp
21
  /*[/.build.php-auto-generate-use-Traits]*/
22
 
23
  /**
24
- * Flagged as `TRUE` if running.
25
  *
26
  * @since 150422 Rewrite.
27
  *
28
- * @type bool `TRUE` if running.
29
  */
30
- public $is_running = false;
31
 
32
  /**
33
- * Microtime; for debugging.
34
  *
35
  * @since 150422 Rewrite.
36
  *
37
- * @type float Microtime; for debugging.
38
  */
39
- public $timer = 0;
40
 
41
  /**
42
- * Class constructor/cache handler.
43
  *
44
  * @since 150422 Rewrite.
 
45
  */
46
  public function __construct()
47
  {
48
  parent::__construct();
49
 
50
- if (!defined('WP_CACHE') || !WP_CACHE || !COMET_CACHE_ENABLE) {
51
- return; // Not enabled.
52
- }
53
- if (defined('WP_INSTALLING') || defined('RELOCATE')) {
54
- return; // N/A; installing|relocating.
 
 
 
 
 
 
 
 
 
55
  }
 
 
 
 
 
 
 
 
 
 
 
56
  $this->is_running = true;
57
  $this->timer = microtime(true);
58
 
21
  /*[/.build.php-auto-generate-use-Traits]*/
22
 
23
  /**
24
+ * Microtime.
25
  *
26
  * @since 150422 Rewrite.
27
  *
28
+ * @type float Microtime.
29
  */
30
+ public $timer = 0;
31
 
32
  /**
33
+ * True if running.
34
  *
35
  * @since 150422 Rewrite.
36
  *
37
+ * @type bool True if running.
38
  */
39
+ public $is_running = false;
40
 
41
  /**
42
+ * Class constructor.
43
  *
44
  * @since 150422 Rewrite.
45
+ * @since 161226 Version check.
46
  */
47
  public function __construct()
48
  {
49
  parent::__construct();
50
 
51
+ if (!defined('COMET_CACHE_AC_FILE_VERSION')) {
52
+ return; // Missing; wait for update.
53
+ } elseif (COMET_CACHE_AC_FILE_VERSION !== VERSION) {
54
+ return; // Version mismatch; wait for update.
55
+ //
56
+ } elseif (!defined('WP_CACHE') || !WP_CACHE || !COMET_CACHE_ENABLE) {
57
+ return; // Not enabled in `wp-config.php` or otherwise.
58
+ } elseif (defined('WP_INSTALLING') || defined('RELOCATE')) {
59
+ return; // Not applicable; installing and/or relocating.
60
+ //
61
+ } elseif (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) {
62
+ return; // Not applicable; bypass API requests.
63
+ } elseif (defined('REST_REQUEST') && REST_REQUEST) {
64
+ return; // Not applicable; bypass API requests.
65
  }
66
+ // Note: `REST_REQUEST` is only here as a way of future-proofing the software.
67
+ // Ideally, we could catch all API requests here to avoid any overhead in processing.
68
+ // I suspect this will be the case in a future release of WordPress.
69
+
70
+ // For now, `REST_REQUEST` is not defined by WP until later in the `parse_request` phase.
71
+ // Therefore, this check by itself is not enough to avoid all REST requests at this time.
72
+ // See: `traits/Ac/ObUtils.php` for additional checks for `REST_REQUEST` API calls.
73
+
74
+ // `XMLRPC_REQUEST` on the other hand, is set very early via `xmlrpc.php`. So no issue.
75
+ // -------------------------------------------------------------------------------------------------------------
76
+
77
  $this->is_running = true;
78
  $this->timer = microtime(true);
79
 
src/includes/classes/MenuPageOptions.php CHANGED
@@ -17,9 +17,6 @@ class MenuPageOptions extends MenuPage
17
  {
18
  parent::__construct(); // Parent constructor.
19
 
20
- global $is_nginx; // WP global for web server checks below.
21
- global $is_apache; // WP global for web server checks below.
22
-
23
  echo '<form id="plugin-menu-page" class="plugin-menu-page" method="post" enctype="multipart/form-data" autocomplete="off"'.
24
  ' action="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, '_wpnonce' => wp_create_nonce()]), self_admin_url('/admin.php'))).'">'."\n";
25
 
@@ -425,6 +422,15 @@ class MenuPageOptions extends MenuPage
425
  echo ' <option value="0"'.selected($this->plugin->options['cache_clear_term_post_tag_enable'], '0', false).'>'.__('No, my site doesn\'t use Tags and/or I don\'t have any Tag archive views.', 'comet-cache').'</option>'."\n";
426
  echo ' </select></p>'."\n";
427
 
 
 
 
 
 
 
 
 
 
428
  echo ' <h4 style="margin-bottom:0;">'.__('Auto-Clear "Custom Term Archives" Too?', 'comet-cache').'</h4>'."\n";
429
  echo ' <p style="margin-top:2px;">'.sprintf(__('Most sites do not use any custom Terms so it should be safe to leave this disabled. However, if your site uses custom Terms and they have their own Term archive views, you may want to clear those when the associated post is cleared. Therefore, if a single Post/Page is changed in some way; and %1$s clears/resets the cache for a single Post/Page, would you like %1$s to also clear any existing cache files for the associated Tag archive views?', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
430
  echo ' <p><select name="'.esc_attr(GLOBAL_NS).'[saveOptions][cache_clear_term_other_enable]" class="-no-if-enabled">'."\n";
@@ -538,7 +544,7 @@ class MenuPageOptions extends MenuPage
538
  echo ' <div class="plugin-menu-page-panel-body clearfix">'."\n";
539
  echo ' <h3>'.__('Base Cache Directory (Must be Writable; i.e., <a href="http://cometcache.com/r/wp-file-permissions/" target="_blank">Permissions</a> <code>755</code> or Higher)', 'comet-cache').'</h3>'."\n";
540
  echo ' <p>'.sprintf(__('This is where %1$s will store the cached version of your site. If you\'re not sure how to deal with directory permissions, don\'t worry too much about this. If there is a problem, %1$s will let you know about it. By default, this directory is created by %1$s and the permissions are setup automatically. In most cases there is nothing more you need to do.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
541
- echo ' <table style="width:100%;"><tr><td style="width:1px; font-weight:bold; white-space:nowrap;">'.esc_html(WP_CONTENT_DIR).'/</td><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][base_dir]" value="'.esc_attr($this->plugin->options['base_dir']).'" /></td><td style="width:1px; font-weight:bold; white-space:nowrap;">/</td></tr></table>'."\n";
542
  echo ' </div>'."\n";
543
 
544
  echo '</div>'."\n";
@@ -866,7 +872,7 @@ class MenuPageOptions extends MenuPage
866
 
867
  echo ' <div class="plugin-menu-page-panel-if-enabled -auto-cache-options">'."\n";
868
  echo ' <h3>'.__('XML Sitemap URL (or an XML Sitemap Index)', 'comet-cache').'</h3>'."\n";
869
- echo ' <table style="width:100%;"><tr><td style="width:1px; font-weight:bold; white-space:nowrap;">'.esc_html(home_url('/')).'</td><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][auto_cache_sitemap_url]" value="'.esc_attr($this->plugin->options['auto_cache_sitemap_url']).'" /></td></tr></table>'."\n";
870
  if (is_multisite()) {
871
  echo ' <p><select name="'.esc_attr(GLOBAL_NS).'[saveOptions][auto_cache_ms_children_too]">'."\n";
872
  echo ' <option value="0"'.selected($this->plugin->options['auto_cache_ms_children_too'], '0', false).'>'.__('All URLs in this network are in the sitemap for the main site.', 'comet-cache').'</option>'."\n";
@@ -889,7 +895,7 @@ class MenuPageOptions extends MenuPage
889
  echo ' <hr />'."\n";
890
 
891
  echo ' <h3>'.__('Auto-Cache User-Agent String', 'comet-cache').'</h3>'."\n";
892
- echo ' <table style="width:100%;"><tr><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][auto_cache_user_agent]" value="'.esc_attr($this->plugin->options['auto_cache_user_agent']).'" /></td><td style="width:1px; font-weight:bold; white-space:nowrap;">; '.esc_html(GLOBAL_NS.' '.VERSION).'</td></tr></table>'."\n";
893
  echo ' <p class="info" style="display:block;">'.__('This is how the Auto-Cache Engine identifies itself when connecting to URLs. See <a href="http://en.wikipedia.org/wiki/User_agent" target="_blank">User Agent</a> in the Wikipedia.', 'comet-cache').'</p>'."\n";
894
  echo ' </div>'."\n";
895
  echo ' </div>'."\n";
@@ -991,9 +997,9 @@ class MenuPageOptions extends MenuPage
991
  echo ' <div class="plugin-menu-page-panel-body clearfix">'."\n";
992
  echo ' <button type="button" class="plugin-menu-page-clear-cdn-cache" style="float:right; margin:0 0 1em 1em;" title="'.esc_attr(__('Clear CDN Cache (Bump CDN Invalidation Counter)', 'comet-cache')).'">'.__('Clear CDN Cache', 'comet-cache').' <img src="'.esc_attr($this->plugin->url('/src/client-s/images/clear.png')).'" style="width:16px; height:16px; display:inline-block;" /></button>'."\n";
993
  echo ' <h3>'.__('Enable Static CDN Filters (e.g., MaxCDN/CloudFront)?', 'comet-cache').'</h3>'."\n";
994
- echo ' <p>'.sprintf(__('This feature allows you to serve some and/or ALL static files on your site from a CDN of your choosing. This is made possible through content/URL filters exposed by WordPress and implemented by %1$s. All it requires is that you setup a CDN host name sourced by your WordPress installation domain. You enter that CDN host name below and %1$s will do the rest! Super easy, and it doesn\'t require any DNS changes either. :-) Please <a href="http://cometcache.com/r/static-cdn-filters-general-instructions/" target="_blank">click here</a> for a general set of instructions.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
995
  echo ' <p>'.__('<strong>What\'s a CDN?</strong> It\'s a Content Delivery Network (i.e., a network of optimized servers) designed to cache static resources served from your site (e.g., JS/CSS/images and other static files) onto it\'s own servers, which are located strategically in various geographic areas around the world. Integrating a CDN for static files can dramatically improve the speed and performance of your site, lower the burden on your own server, and reduce latency associated with visitors attempting to access your site from geographic areas of the world that might be very far away from the primary location of your own web servers.', 'comet-cache').'</p>'."\n";
996
- if ($is_nginx && $this->plugin->applyWpFilters(GLOBAL_NS.'_wp_htaccess_nginx_notice', true) && (!isset($_SERVER['WP_NGINX_CONFIG']) || $_SERVER['WP_NGINX_CONFIG'] !== 'done')) {
997
  echo '<div class="plugin-menu-page-notice error">'."\n";
998
  echo ' <i class="si si-thumbs-down"></i> '.__('It appears that your server is running NGINX and does not support <code>.htaccess</code> rules. Please <a href="http://cometcache.com/r/kb-article-recommended-nginx-server-configuration/" target="_new">update your server configuration manually</a>. Note that updating your NGINX server configuration <em>before</em> enabling Static CDN Filters is recommended to prevent any <a href="http://cometcache.com/r/kb-article-what-are-cross-origin-request-blocked-cors-errors/" target="_new">CORS errors</a> with your CDN. If you\'ve already updated your NGINX configuration, you can safely <a href="http://cometcache.com/r/kb-article-how-do-i-disable-the-nginx-htaccess-notice/" target="_new">ignore this message</a>.', 'comet-cache')."\n";
999
  echo '</div>'."\n";
@@ -1002,29 +1008,29 @@ class MenuPageOptions extends MenuPage
1002
  echo ' <option value="0"'.(!IS_PRO ? '' : selected($this->plugin->options['cdn_enable'], '0', false)).'>'.__('No, I do NOT want CDN filters applied at runtime.', 'comet-cache').'</option>'."\n";
1003
  echo ' <option value="1"'.(!IS_PRO ? ' selected' : selected($this->plugin->options['cdn_enable'], '1', false)).'>'.__('Yes, I want CDN filters applied w/ my configuration below.', 'comet-cache').'</option>'."\n";
1004
  echo ' </select></p>'."\n";
1005
- if ($is_apache && $this->plugin->options['cdn_enable'] && !$this->plugin->options['htaccess_access_control_allow_origin']) {
1006
  echo ' <p class="warning" style="display:block;">'.__('<strong>Warning:</strong> Static CDN Filters are enabled above but the <strong>Comet Cache → Plugin Options → Apache Optimizations → Send Access-Control-Allow-Origin Header</strong> option has been disabled. We recommend sending the <code>Access-Control-Allow-Origin</code> header to avoid <a href="https://cometcache.com/r/kb-article-what-are-cross-origin-request-blocked-cors-errors/" target="_blank">CORS errors</a> when a CDN is configured.', 'comet-cache').'</p>'."\n";
1007
  }
1008
  echo ' <hr />'."\n";
1009
 
1010
  echo ' <div class="plugin-menu-page-panel-if-enabled -static-cdn-filter-options">'."\n";
1011
 
1012
- echo ' <h3>'.__('CDN Host Name (Required)', 'comet-cache').'</h3>'."\n";
1013
 
1014
  echo ' <p class="info" style="display:block;">'.// This note includes three graphics. One for MaxCDN; another for CloudFront, and another for KeyCDN.
1015
  ' <a href="http://cometcache.com/r/keycdn/" target="_blank"><img src="'.esc_attr($this->plugin->url('/src/client-s/images/keycdn-logo.png')).'" style="width:90px; float:right; margin: 18px 10px 0 18px;" /></a>'.
1016
  ' <a href="http://cometcache.com/r/amazon-cloudfront/" target="_blank"><img src="'.esc_attr($this->plugin->url('/src/client-s/images/cloudfront-logo.png')).'" style="width:75px; float:right; margin: 8px 10px 0 25px;" /></a>'.
1017
  ' <a href="http://cometcache.com/r/maxcdn/" target="_blank"><img src="'.esc_attr($this->plugin->url('/src/client-s/images/maxcdn-logo.png')).'" style="width:125px; float:right; margin: 20px 0 0 25px;" /></a>'.
1018
- ' '.__('This field is really all that\'s necessary to get Static CDN Filters working! However, it does requires a little bit of work on your part. You need to setup and configure a CDN before you can fill in this field. Once you configure a CDN, you\'ll receive a host name (provided by your CDN), which you\'ll enter here; e.g., <code>js9dgjsl4llqpp.cloudfront.net</code>. We recommend <a href="http://cometcache.com/r/maxcdn/" target="_blank">MaxCDN</a>, <a href="http://cometcache.com/r/amazon-cloudfront/" target="_blank">Amazon CloudFront</a>, <a href="http://cometcache.com/r/keycdn/" target="_blank">KeyCDN</a>, and/or <a href="http://cometcache.com/r/cdn77/" target="_blank">CDN77</a> but this should work with many of the most popular CDNs. Please read <a href="http://cometcache.com/r/static-cdn-filters-general-instructions/" target="_blank">this article</a> for a general set of instructions. We also have a <a href="http://cometcache.com/r/static-cdn-filters-maxcdn/" target="_blank">MaxCDN tutorial</a>, <a href="http://cometcache.com/r/static-cdn-filters-cloudfront/" target="_blank">CloudFront tutorial</a>, <a href="http://cometcache.com/r/static-cdn-filters-keycdn/" target="_blank">KeyCDN tutorial</a>, and a <a href="http://cometcache.com/r/static-cdn-filters-cdn77/" target="_blank">CDN77 tutorial</a> to walk you through the process.', 'comet-cache').'</p>'."\n";
1019
  echo ' <p><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_host]" value="'.esc_attr($this->plugin->options['cdn_hosts'] ? '' : $this->plugin->options['cdn_host']).'"'.($this->plugin->options['cdn_hosts'] ? ' disabled="disabled"' : '').' /></p>'."\n";
1020
 
1021
  echo ' <hr />'."\n";
1022
 
1023
- echo ' <h3>'.__('Multiple CDN Host Names for Domain Sharding and Multisite Networks (Optional)', 'comet-cache').'</h3>'."\n";
1024
- echo ' <p>'.sprintf(__('%1$s also supports multiple CDN Host Names for any given domain. Using multiple CDN Host Names (instead of just one, as seen above) is referred to as <strong><a href="http://cometcache.com/r/domain-sharding/" target="_blank">Domain Sharding</a></strong> (<a href="http://cometcache.com/r/domain-sharding/" target="_blank">click here to learn more</a>). If you configure multiple CDN Host Names (i.e., if you implement Domain Sharding), %1$s will use the first one that you list for static resources loaded in the HTML <code>&lt;head&gt;</code> section, the last one for static resources loaded in the footer, and it will choose one at random for all other static resource locations. Configuring multiple CDN Host Names can improve speed! This is a way for advanced site owners to work around concurrency limits in popular browsers; i.e., making it possible for browsers to download many more resources simultaneously, resulting in a faster overall completion time. In short, this tells the browser that your website will not be overloaded by concurrent requests, because static resources are in fact being served by a content-delivery network (i.e., multiple CDN host names). If you use this functionality for Domain Sharding, we suggest that you setup one CDN Distribution (aka: Pull Zone), and then create multiple CNAME records pointing to that distribution. You can enter each of your CNAMES in the field below, as instructed.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
1025
- echo ' <p class="info" style="display:block;">'.sprintf(__('<strong>On WordPress Multisite Network installations</strong>, this field also allows you to configure different CDN Host Names for each domain (or sub-domain) that you run from a single installation of WordPress. For more information about configuring Static CDN Filters on a WordPress Multisite Network, see this tutorial: <a href="http://cometcache.com/r/static-cdn-filters-for-wordpress-multisite-networks/" target="_blank">Static CDN Filters for WordPress Multisite Networks</a>.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
1026
- echo ' <p style="margin-bottom:0;"><textarea name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_hosts]" rows="5" spellcheck="false" autocomplete="off" placeholder="'.esc_attr('e.g., '.$this->plugin->hostToken(false, true).' = cdn1.'.$this->plugin->hostToken(false, true).', cdn2.'.$this->plugin->hostToken(false, true).', cdn3.'.$this->plugin->hostToken(false, true)).'" wrap="off" style="white-space:nowrap;">'.esc_textarea($this->plugin->options['cdn_hosts']).'</textarea></p>'."\n";
1027
- echo ' <p style="margin-top:0;">'.sprintf(__('<strong>↑ Syntax:</strong> This is a line-delimited list of domain mappings. Each line should start with your WordPress domain name (e.g., <code>%1$s</code>), followed by an <code>=</code> sign, followed by a comma-delimited list of CDN Host Names associated with the domain in that line. If you\'re running a Multisite Network installation of WordPress, you might have multiple configuration lines. Otherwise, you should only need one line to configure multiple CDN Host Names for a standard WordPress installation.', 'comet-cache'), esc_html($this->plugin->hostToken(false, true))).'</p>'."\n";
1028
 
1029
  echo ' <hr />'."\n";
1030
 
@@ -1060,8 +1066,8 @@ class MenuPageOptions extends MenuPage
1060
  echo ' <h3>'.__('Whitelisted URI Inclusion Patterns (Optional; One Per Line)', 'comet-cache').'</h3>'."\n";
1061
  echo ' <p><textarea name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_whitelisted_uri_patterns]" rows="5" spellcheck="false" class="monospace">'.format_to_edit($this->plugin->options['cdn_whitelisted_uri_patterns']).'</textarea></p>'."\n";
1062
  echo ' <p class="info" style="display:block;">'.__('<strong>Note:</strong> please remember that your entries here should be formatted as a line-delimited list; e.g., one inclusion pattern per line.', 'comet-cache').'</p>'."\n";
1063
- echo ' <p>'.__('If provided, only local URIs matching one of the patterns you list here will be served from your CDN Host Name. URI patterns are caSe-insensitive. A wildcard <code>*</code> will match zero or more characters in any of your patterns. A caret <code>^</code> symbol will match zero or more characters that are NOT the <code>/</code> character. For instance, <code>*/wp-content/*</code> here would indicate that you only want to filter URLs that lead to files located inside the <code>wp-content</code> directory. Adding an additional line with <code>*/wp-includes/*</code> would filter URLs in the <code>wp-includes</code> directory also. <strong>If you leave this empty</strong>, ALL files matching a static file extension will be served from your CDN; i.e., the default behavior.', 'comet-cache').'</p>'."\n";
1064
- echo ' <p>'.__('Please note that URI patterns are tested against a file\'s path (i.e., a file\'s URI, and NOT its full URL). A URI always starts with a leading <code>/</code>. To clarify, a URI is the portion of the URL which comes after the host name. For instance, given the following URL: <code>http://example.com/path/to/style.css?ver=3</code>, the URI you are matching against would be: <code>/path/to/style.css?ver=3</code>. To whitelist this URI, you could use a line that contains something like this: <code>/path/to/*.css*</code>', 'comet-cache').'</p>'."\n";
1065
 
1066
  echo ' <h3>'.__('Blacklisted URI Exclusion Patterns (Optional; One Per Line)', 'comet-cache').'</h3>'."\n";
1067
  echo ' <p><textarea name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_blacklisted_uri_patterns]" rows="5" spellcheck="false" class="monospace">'.format_to_edit($this->plugin->options['cdn_blacklisted_uri_patterns']).'</textarea></p>'."\n";
@@ -1083,7 +1089,7 @@ class MenuPageOptions extends MenuPage
1083
  }
1084
  /* ----------------------------------------------------------------------------------------- */
1085
 
1086
- if ($is_apache || $this->plugin->isProPreview()) {
1087
  echo '<div class="plugin-menu-page-panel'.(!IS_PRO && $this->plugin->isProPreview() ? ' pro-preview' : '').'">'."\n";
1088
 
1089
  echo ' <a href="#" class="plugin-menu-page-panel-heading" data-additional-pro-features="'.(!IS_PRO && $this->plugin->isProPreview() ? __('additional pro features', 'comet-cache') : '').'">'."\n";
@@ -1112,7 +1118,7 @@ class MenuPageOptions extends MenuPage
1112
  echo ' <p class="info" style="display:block;">'.__('<strong>Or</strong>, if your server is missing <code>mod_deflate</code>/<code>mod_filter</code>; open your <code>php.ini</code> file and add this line: <a href="http://php.net/manual/en/zlib.configuration.php" target="_blank" style="text-decoration:none;"><code>zlib.output_compression = on</code></a>', 'comet-cache').'</p>'."\n";
1113
  echo ' </div>'."\n";
1114
 
1115
- if ((!IS_PRO && $is_apache) && !$this->plugin->isProPreview()) {
1116
  echo ' <hr />'."\n";
1117
  echo ' <p class="warning" style="display:block;">'.sprintf(__('<a href="%1$s">Enable the Pro Preview</a> to see <strong>Leverage Browser Caching</strong>, <strong>Enforce Canonical URLs</strong>, and more!', 'comet-cache'), esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, GLOBAL_NS.'_pro_preview' => '1']), self_admin_url('/admin.php')))).'</p>'."\n";
1118
  }
@@ -1131,6 +1137,20 @@ class MenuPageOptions extends MenuPage
1131
  echo ' <pre class="code"><code>'.esc_html($this->plugin->fillReplacementCodes(file_get_contents(dirname(__DIR__).'/templates/htaccess/browser-caching-enable.txt'))).'</code></pre>'."\n";
1132
  echo ' </div>'."\n";
1133
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1134
  if ((IS_PRO && !empty($GLOBALS['wp_rewrite']->permalink_structure)) || $this->plugin->isProPreview()) {
1135
  echo ' <hr />'."\n";
1136
  echo ' <h3 data-pro-version-only="'.(!IS_PRO ? __('pro version only', 'comet-cache') : '').'">'.__('Enforce Canonical URLs?', 'comet-cache').'</h3>'."\n";
@@ -1233,7 +1253,7 @@ class MenuPageOptions extends MenuPage
1233
  echo ' <p>'.__('For more documentation, please see <a href="http://cometcache.com/r/kb-dynamic-version-salts/" target="_blank">Dynamic Version Salts</a>.', 'comet-cache').'</p>'."\n";
1234
  echo ' <hr />'."\n";
1235
  echo ' <h3>'.sprintf(__('Create a Dynamic Version Salt For %1$s? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size:90%%; opacity:0.5;">150%% OPTIONAL</span>', 'comet-cache'), esc_html(NAME)).'</h3>'."\n";
1236
- echo ' <table style="width:100%;"><tr><td style="width:1px; font-weight:bold; white-space:nowrap;">PROTOCOL.HOST.URI.v.</td><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][version_salt]" value="'.esc_attr($this->plugin->options['version_salt']).'" class="monospace" placeholder="$_COOKIE[\'my_cookie\']" /></td><td style="width:1px; font-weight:bold; white-space:nowrap;"></td></tr></table>'."\n";
1237
  echo ' <p class="info" style="display:block;">'.__('<a href="http://php.net/manual/en/language.variables.superglobals.php" target="_blank">Super Globals</a> work here; <a href="http://codex.wordpress.org/Editing_wp-config.php#table_prefix" target="_blank"><code>$GLOBALS[\'table_prefix\']</code></a> is a popular one.<br />Or, perhaps a PHP Constant defined in <code>/wp-config.php</code>; such as <code>WPLANG</code> or <code>DB_HOST</code>.', 'comet-cache').'</p>'."\n";
1238
  echo ' <p class="notice" style="display:block;">'.__('<strong>Important:</strong> your Version Salt is scanned for PHP syntax errors via <a href="http://phpcodechecker.com/" target="_blank"><code>phpCodeChecker.com</code></a>. If errors are found, you\'ll receive a notice in the Dashboard.', 'comet-cache').'</p>'."\n";
1239
  echo ' <p class="info" style="display:block;">'.__('If you\'ve enabled a separate cache for each user (optional) that\'s perfectly OK. A Version Salt works with user caching too.', 'comet-cache').'</p>'."\n";
17
  {
18
  parent::__construct(); // Parent constructor.
19
 
 
 
 
20
  echo '<form id="plugin-menu-page" class="plugin-menu-page" method="post" enctype="multipart/form-data" autocomplete="off"'.
21
  ' action="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, '_wpnonce' => wp_create_nonce()]), self_admin_url('/admin.php'))).'">'."\n";
22
 
422
  echo ' <option value="0"'.selected($this->plugin->options['cache_clear_term_post_tag_enable'], '0', false).'>'.__('No, my site doesn\'t use Tags and/or I don\'t have any Tag archive views.', 'comet-cache').'</option>'."\n";
423
  echo ' </select></p>'."\n";
424
 
425
+ echo ' <h4 style="margin-bottom:0;">'.__('Auto-Clear "Date-Based Archives" Too?', 'comet-cache').'</h4>'."\n";
426
+ echo ' <p style="margin-top:2px;">'.sprintf(__('Date-Based Archives allow visitors to browse Posts by the year, month, or day they were originally published. If a single Post (of any type) is changed in some way; and %1$s clears/resets the cache for that Post, would you like %1$s to also clear any existing cache files for Dated-Based Archives that match the publication time?', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
427
+ echo ' <p><select name="'.esc_attr(GLOBAL_NS).'[saveOptions][cache_clear_date_archives_enable]" class="-no-if-enabled">'."\n";
428
+ echo ' <option value="1"'.selected($this->plugin->options['cache_clear_date_archives_enable'], '1', false).'>'.__('Yes, if any single Post is cleared/reset, also clear the associated Date archive views.', 'comet-cache').'</option>'."\n";
429
+ echo ' <option value="2"'.selected($this->plugin->options['cache_clear_date_archives_enable'], '2', false).'>'.__('Yes, but only clear the associated Day and Month archive views.', 'comet-cache').'</option>'."\n";
430
+ echo ' <option value="3"'.selected($this->plugin->options['cache_clear_date_archives_enable'], '3', false).'>'.__('Yes, but only clear the associated Day archive view.', 'comet-cache').'</option>'."\n";
431
+ echo ' <option value="0"'.selected($this->plugin->options['cache_clear_date_archives_enable'], '0', false).'>'.__('No, don\'t clear any associated Date archive views.', 'comet-cache').'</option>'."\n";
432
+ echo ' </select></p>'."\n";
433
+
434
  echo ' <h4 style="margin-bottom:0;">'.__('Auto-Clear "Custom Term Archives" Too?', 'comet-cache').'</h4>'."\n";
435
  echo ' <p style="margin-top:2px;">'.sprintf(__('Most sites do not use any custom Terms so it should be safe to leave this disabled. However, if your site uses custom Terms and they have their own Term archive views, you may want to clear those when the associated post is cleared. Therefore, if a single Post/Page is changed in some way; and %1$s clears/resets the cache for a single Post/Page, would you like %1$s to also clear any existing cache files for the associated Tag archive views?', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
436
  echo ' <p><select name="'.esc_attr(GLOBAL_NS).'[saveOptions][cache_clear_term_other_enable]" class="-no-if-enabled">'."\n";
544
  echo ' <div class="plugin-menu-page-panel-body clearfix">'."\n";
545
  echo ' <h3>'.__('Base Cache Directory (Must be Writable; i.e., <a href="http://cometcache.com/r/wp-file-permissions/" target="_blank">Permissions</a> <code>755</code> or Higher)', 'comet-cache').'</h3>'."\n";
546
  echo ' <p>'.sprintf(__('This is where %1$s will store the cached version of your site. If you\'re not sure how to deal with directory permissions, don\'t worry too much about this. If there is a problem, %1$s will let you know about it. By default, this directory is created by %1$s and the permissions are setup automatically. In most cases there is nothing more you need to do.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
547
+ echo ' <table style="width:100%;"><tr><td style="width:1px; font-weight:bold; white-space:pre;">'.esc_html(WP_CONTENT_DIR).'/</td><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][base_dir]" value="'.esc_attr($this->plugin->options['base_dir']).'" /></td><td style="width:1px; font-weight:bold; white-space:pre;">/</td></tr></table>'."\n";
548
  echo ' </div>'."\n";
549
 
550
  echo '</div>'."\n";
872
 
873
  echo ' <div class="plugin-menu-page-panel-if-enabled -auto-cache-options">'."\n";
874
  echo ' <h3>'.__('XML Sitemap URL (or an XML Sitemap Index)', 'comet-cache').'</h3>'."\n";
875
+ echo ' <table style="width:100%;"><tr><td style="width:1px; font-weight:bold; white-space:pre;">'.esc_html(home_url('/')).'</td><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][auto_cache_sitemap_url]" value="'.esc_attr($this->plugin->options['auto_cache_sitemap_url']).'" /></td></tr></table>'."\n";
876
  if (is_multisite()) {
877
  echo ' <p><select name="'.esc_attr(GLOBAL_NS).'[saveOptions][auto_cache_ms_children_too]">'."\n";
878
  echo ' <option value="0"'.selected($this->plugin->options['auto_cache_ms_children_too'], '0', false).'>'.__('All URLs in this network are in the sitemap for the main site.', 'comet-cache').'</option>'."\n";
895
  echo ' <hr />'."\n";
896
 
897
  echo ' <h3>'.__('Auto-Cache User-Agent String', 'comet-cache').'</h3>'."\n";
898
+ echo ' <table style="width:100%;"><tr><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][auto_cache_user_agent]" value="'.esc_attr($this->plugin->options['auto_cache_user_agent']).'" /></td><td style="width:1px; font-weight:bold; white-space:pre;">; '.esc_html(GLOBAL_NS.' '.VERSION).'</td></tr></table>'."\n";
899
  echo ' <p class="info" style="display:block;">'.__('This is how the Auto-Cache Engine identifies itself when connecting to URLs. See <a href="http://en.wikipedia.org/wiki/User_agent" target="_blank">User Agent</a> in the Wikipedia.', 'comet-cache').'</p>'."\n";
900
  echo ' </div>'."\n";
901
  echo ' </div>'."\n";
997
  echo ' <div class="plugin-menu-page-panel-body clearfix">'."\n";
998
  echo ' <button type="button" class="plugin-menu-page-clear-cdn-cache" style="float:right; margin:0 0 1em 1em;" title="'.esc_attr(__('Clear CDN Cache (Bump CDN Invalidation Counter)', 'comet-cache')).'">'.__('Clear CDN Cache', 'comet-cache').' <img src="'.esc_attr($this->plugin->url('/src/client-s/images/clear.png')).'" style="width:16px; height:16px; display:inline-block;" /></button>'."\n";
999
  echo ' <h3>'.__('Enable Static CDN Filters (e.g., MaxCDN/CloudFront)?', 'comet-cache').'</h3>'."\n";
1000
+ echo ' <p>'.sprintf(__('This feature allows you to serve some and/or ALL static files on your site from a CDN of your choosing. This is made possible through content/URL filters exposed by WordPress and implemented by %1$s. All it requires is that you setup a CDN hostname sourced by your WordPress installation domain. You enter that CDN hostname below and %1$s will do the rest! Super easy, and it doesn\'t require any DNS changes either. :-) Please <a href="http://cometcache.com/r/static-cdn-filters-general-instructions/" target="_blank">click here</a> for a general set of instructions.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
1001
  echo ' <p>'.__('<strong>What\'s a CDN?</strong> It\'s a Content Delivery Network (i.e., a network of optimized servers) designed to cache static resources served from your site (e.g., JS/CSS/images and other static files) onto it\'s own servers, which are located strategically in various geographic areas around the world. Integrating a CDN for static files can dramatically improve the speed and performance of your site, lower the burden on your own server, and reduce latency associated with visitors attempting to access your site from geographic areas of the world that might be very far away from the primary location of your own web servers.', 'comet-cache').'</p>'."\n";
1002
+ if ($this->plugin->isNginx() && $this->plugin->applyWpFilters(GLOBAL_NS.'_wp_htaccess_nginx_notice', true) && (!isset($_SERVER['WP_NGINX_CONFIG']) || $_SERVER['WP_NGINX_CONFIG'] !== 'done')) {
1003
  echo '<div class="plugin-menu-page-notice error">'."\n";
1004
  echo ' <i class="si si-thumbs-down"></i> '.__('It appears that your server is running NGINX and does not support <code>.htaccess</code> rules. Please <a href="http://cometcache.com/r/kb-article-recommended-nginx-server-configuration/" target="_new">update your server configuration manually</a>. Note that updating your NGINX server configuration <em>before</em> enabling Static CDN Filters is recommended to prevent any <a href="http://cometcache.com/r/kb-article-what-are-cross-origin-request-blocked-cors-errors/" target="_new">CORS errors</a> with your CDN. If you\'ve already updated your NGINX configuration, you can safely <a href="http://cometcache.com/r/kb-article-how-do-i-disable-the-nginx-htaccess-notice/" target="_new">ignore this message</a>.', 'comet-cache')."\n";
1005
  echo '</div>'."\n";
1008
  echo ' <option value="0"'.(!IS_PRO ? '' : selected($this->plugin->options['cdn_enable'], '0', false)).'>'.__('No, I do NOT want CDN filters applied at runtime.', 'comet-cache').'</option>'."\n";
1009
  echo ' <option value="1"'.(!IS_PRO ? ' selected' : selected($this->plugin->options['cdn_enable'], '1', false)).'>'.__('Yes, I want CDN filters applied w/ my configuration below.', 'comet-cache').'</option>'."\n";
1010
  echo ' </select></p>'."\n";
1011
+ if ($this->plugin->isApache() && $this->plugin->options['cdn_enable'] && !$this->plugin->options['htaccess_access_control_allow_origin']) {
1012
  echo ' <p class="warning" style="display:block;">'.__('<strong>Warning:</strong> Static CDN Filters are enabled above but the <strong>Comet Cache → Plugin Options → Apache Optimizations → Send Access-Control-Allow-Origin Header</strong> option has been disabled. We recommend sending the <code>Access-Control-Allow-Origin</code> header to avoid <a href="https://cometcache.com/r/kb-article-what-are-cross-origin-request-blocked-cors-errors/" target="_blank">CORS errors</a> when a CDN is configured.', 'comet-cache').'</p>'."\n";
1013
  }
1014
  echo ' <hr />'."\n";
1015
 
1016
  echo ' <div class="plugin-menu-page-panel-if-enabled -static-cdn-filter-options">'."\n";
1017
 
1018
+ echo ' <h3>'.__('CDN Hostname (Required)', 'comet-cache').'</h3>'."\n";
1019
 
1020
  echo ' <p class="info" style="display:block;">'.// This note includes three graphics. One for MaxCDN; another for CloudFront, and another for KeyCDN.
1021
  ' <a href="http://cometcache.com/r/keycdn/" target="_blank"><img src="'.esc_attr($this->plugin->url('/src/client-s/images/keycdn-logo.png')).'" style="width:90px; float:right; margin: 18px 10px 0 18px;" /></a>'.
1022
  ' <a href="http://cometcache.com/r/amazon-cloudfront/" target="_blank"><img src="'.esc_attr($this->plugin->url('/src/client-s/images/cloudfront-logo.png')).'" style="width:75px; float:right; margin: 8px 10px 0 25px;" /></a>'.
1023
  ' <a href="http://cometcache.com/r/maxcdn/" target="_blank"><img src="'.esc_attr($this->plugin->url('/src/client-s/images/maxcdn-logo.png')).'" style="width:125px; float:right; margin: 20px 0 0 25px;" /></a>'.
1024
+ ' '.__('This field is really all that\'s necessary to get Static CDN Filters working! However, it does requires a little bit of work on your part. You need to setup and configure a CDN before you can fill in this field. Once you configure a CDN, you\'ll receive a hostname (provided by your CDN), which you\'ll enter here; e.g., <code>js9dgjsl4llqpp.cloudfront.net</code>. We recommend <a href="http://cometcache.com/r/maxcdn/" target="_blank">MaxCDN</a>, <a href="http://cometcache.com/r/amazon-cloudfront/" target="_blank">Amazon CloudFront</a>, <a href="http://cometcache.com/r/keycdn/" target="_blank">KeyCDN</a>, and/or <a href="http://cometcache.com/r/cdn77/" target="_blank">CDN77</a> but this should work with many of the most popular CDNs. Please read <a href="http://cometcache.com/r/static-cdn-filters-general-instructions/" target="_blank">this article</a> for a general set of instructions. We also have a <a href="http://cometcache.com/r/static-cdn-filters-maxcdn/" target="_blank">MaxCDN tutorial</a>, <a href="http://cometcache.com/r/static-cdn-filters-cloudfront/" target="_blank">CloudFront tutorial</a>, <a href="http://cometcache.com/r/static-cdn-filters-keycdn/" target="_blank">KeyCDN tutorial</a>, and a <a href="http://cometcache.com/r/static-cdn-filters-cdn77/" target="_blank">CDN77 tutorial</a> to walk you through the process.', 'comet-cache').'</p>'."\n";
1025
  echo ' <p><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_host]" value="'.esc_attr($this->plugin->options['cdn_hosts'] ? '' : $this->plugin->options['cdn_host']).'"'.($this->plugin->options['cdn_hosts'] ? ' disabled="disabled"' : '').' /></p>'."\n";
1026
 
1027
  echo ' <hr />'."\n";
1028
 
1029
+ echo ' <h3>'.__('Multiple CDN Hostnames for Domain Sharding and Multisite Networks (Optional)', 'comet-cache').'</h3>'."\n";
1030
+ echo ' <p>'.sprintf(__('%1$s also supports multiple CDN Hostnames for any given domain. Using multiple CDN Hostnames (instead of just one, as seen above) is referred to as <strong><a href="http://cometcache.com/r/domain-sharding/" target="_blank">Domain Sharding</a></strong> (<a href="http://cometcache.com/r/domain-sharding/" target="_blank">click here to learn more</a>). If you configure multiple CDN Hostnames (i.e., if you implement Domain Sharding), %1$s will use the first one that you list for static resources loaded in the HTML <code>&lt;head&gt;</code> section, the last one for static resources loaded in the footer, and it will choose one at random for all other static resource locations. Configuring multiple CDN Hostnames can improve speed! This is a way for advanced site owners to work around concurrency limits in popular browsers; i.e., making it possible for browsers to download many more resources simultaneously, resulting in a faster overall completion time. In short, this tells the browser that your website will not be overloaded by concurrent requests, because static resources are in fact being served by a content-delivery network (i.e., multiple CDN hostnames). If you use this functionality for Domain Sharding, we suggest that you setup one CDN Distribution (aka: Pull Zone), and then create multiple CNAME records pointing to that distribution. You can enter each of your CNAMES in the field below, as instructed.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
1031
+ echo ' <p class="info" style="display:block;">'.sprintf(__('<strong>On WordPress Multisite Network installations</strong>, this field also allows you to configure different CDN Hostnames for each domain (or sub-domain) that you run from a single installation of WordPress. For more information about configuring Static CDN Filters on a WordPress Multisite Network, see this tutorial: <a href="http://cometcache.com/r/static-cdn-filters-for-wordpress-multisite-networks/" target="_blank">Static CDN Filters for WordPress Multisite Networks</a>.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
1032
+ echo ' <p style="margin-bottom:0;"><textarea name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_hosts]" rows="5" spellcheck="false" autocomplete="off" placeholder="'.esc_attr('e.g., '.$this->plugin->hostToken(false, true).' = cdn1.'.$this->plugin->hostToken(false, true).', cdn2.'.$this->plugin->hostToken(false, true).', cdn3.'.$this->plugin->hostToken(false, true)).'" wrap="off" style="white-space:pre;">'.esc_textarea($this->plugin->options['cdn_hosts']).'</textarea></p>'."\n";
1033
+ echo ' <p style="margin-top:0;">'.sprintf(__('<strong>↑ Syntax:</strong> This is a line-delimited list of domain mappings. Each line should start with your WordPress domain name (e.g., <code>%1$s</code>), followed by an <code>=</code> sign, followed by a comma-delimited list of CDN Hostnames associated with the domain in that line. If you\'re running a Multisite Network installation of WordPress, you might have multiple configuration lines. Otherwise, you should only need one line to configure multiple CDN Hostnames for a standard WordPress installation.', 'comet-cache'), esc_html($this->plugin->hostToken(false, true))).'</p>'."\n";
1034
 
1035
  echo ' <hr />'."\n";
1036
 
1066
  echo ' <h3>'.__('Whitelisted URI Inclusion Patterns (Optional; One Per Line)', 'comet-cache').'</h3>'."\n";
1067
  echo ' <p><textarea name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_whitelisted_uri_patterns]" rows="5" spellcheck="false" class="monospace">'.format_to_edit($this->plugin->options['cdn_whitelisted_uri_patterns']).'</textarea></p>'."\n";
1068
  echo ' <p class="info" style="display:block;">'.__('<strong>Note:</strong> please remember that your entries here should be formatted as a line-delimited list; e.g., one inclusion pattern per line.', 'comet-cache').'</p>'."\n";
1069
+ echo ' <p>'.__('If provided, only local URIs matching one of the patterns you list here will be served from your CDN Hostname. URI patterns are caSe-insensitive. A wildcard <code>*</code> will match zero or more characters in any of your patterns. A caret <code>^</code> symbol will match zero or more characters that are NOT the <code>/</code> character. For instance, <code>*/wp-content/*</code> here would indicate that you only want to filter URLs that lead to files located inside the <code>wp-content</code> directory. Adding an additional line with <code>*/wp-includes/*</code> would filter URLs in the <code>wp-includes</code> directory also. <strong>If you leave this empty</strong>, ALL files matching a static file extension will be served from your CDN; i.e., the default behavior.', 'comet-cache').'</p>'."\n";
1070
+ echo ' <p>'.__('Please note that URI patterns are tested against a file\'s path (i.e., a file\'s URI, and NOT its full URL). A URI always starts with a leading <code>/</code>. To clarify, a URI is the portion of the URL which comes after the hostname. For instance, given the following URL: <code>http://example.com/path/to/style.css?ver=3</code>, the URI you are matching against would be: <code>/path/to/style.css?ver=3</code>. To whitelist this URI, you could use a line that contains something like this: <code>/path/to/*.css*</code>', 'comet-cache').'</p>'."\n";
1071
 
1072
  echo ' <h3>'.__('Blacklisted URI Exclusion Patterns (Optional; One Per Line)', 'comet-cache').'</h3>'."\n";
1073
  echo ' <p><textarea name="'.esc_attr(GLOBAL_NS).'[saveOptions][cdn_blacklisted_uri_patterns]" rows="5" spellcheck="false" class="monospace">'.format_to_edit($this->plugin->options['cdn_blacklisted_uri_patterns']).'</textarea></p>'."\n";
1089
  }
1090
  /* ----------------------------------------------------------------------------------------- */
1091
 
1092
+ if ($this->plugin->isApache() || $this->plugin->isProPreview()) {
1093
  echo '<div class="plugin-menu-page-panel'.(!IS_PRO && $this->plugin->isProPreview() ? ' pro-preview' : '').'">'."\n";
1094
 
1095
  echo ' <a href="#" class="plugin-menu-page-panel-heading" data-additional-pro-features="'.(!IS_PRO && $this->plugin->isProPreview() ? __('additional pro features', 'comet-cache') : '').'">'."\n";
1118
  echo ' <p class="info" style="display:block;">'.__('<strong>Or</strong>, if your server is missing <code>mod_deflate</code>/<code>mod_filter</code>; open your <code>php.ini</code> file and add this line: <a href="http://php.net/manual/en/zlib.configuration.php" target="_blank" style="text-decoration:none;"><code>zlib.output_compression = on</code></a>', 'comet-cache').'</p>'."\n";
1119
  echo ' </div>'."\n";
1120
 
1121
+ if ((!IS_PRO && $this->plugin->isApache()) && !$this->plugin->isProPreview()) {
1122
  echo ' <hr />'."\n";
1123
  echo ' <p class="warning" style="display:block;">'.sprintf(__('<a href="%1$s">Enable the Pro Preview</a> to see <strong>Leverage Browser Caching</strong>, <strong>Enforce Canonical URLs</strong>, and more!', 'comet-cache'), esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, GLOBAL_NS.'_pro_preview' => '1']), self_admin_url('/admin.php')))).'</p>'."\n";
1124
  }
1137
  echo ' <pre class="code"><code>'.esc_html($this->plugin->fillReplacementCodes(file_get_contents(dirname(__DIR__).'/templates/htaccess/browser-caching-enable.txt'))).'</code></pre>'."\n";
1138
  echo ' </div>'."\n";
1139
  }
1140
+ if (IS_PRO || $this->plugin->isProPreview()) {
1141
+ echo ' <hr />'."\n";
1142
+ echo ' <h3 data-pro-version-only="'.(!IS_PRO ? __('pro version only', 'comet-cache') : '').'">'.__('Enforce an Exact Hostname?', 'comet-cache').'</h3>'."\n";
1143
+ echo ' <p>'.sprintf(__('By enforcing an exact hostname you avoid duplicate cache files, which saves disk space and improves cache performance. For example, if a bot or crawler accesses your site using your server\'s IP address instead of using your domain name (e.g., <code>http://123.456.789/path</code>), this results in duplicate cache files, because the host was an IP address. The \'host\' being an important factor in any cache storage system. The same would be true if a visitor attempted to access your site using a made-up sub-domain; e.g., <code>http://foo.bar.%1$s/path</code>. This sort of thing can be avoided by explicitly enforcing an exact hostname in the request. One that matches exactly what you\'ve configured in <strong>WordPress Settings → General</strong>.', 'comet-cache'), esc_html(parse_url(network_home_url(), PHP_URL_HOST))).'</p>'."\n";
1144
+ echo ' <p><select name="'.esc_attr(GLOBAL_NS).'[saveOptions][htaccess_enforce_exact_host_name]" data-target=".-htaccess-enforce-exact-host-name-options">'."\n";
1145
+ echo ' <option value="0"'.(!IS_PRO ? '' : selected($this->plugin->options['htaccess_enforce_exact_host_name'], '0', false)).'>'.__('No, do NOT enforce an exact hostname (or I\'ll update my configuration manually; see below)', 'comet-cache').'</option>'."\n";
1146
+ echo ' <option value="1"'.(!IS_PRO ? 'selected' : selected($this->plugin->options['htaccess_enforce_exact_host_name'], '1', false)).'>'.sprintf(__('Yes, enforce the exact hostname: %1$s', 'comet-cache'), esc_html(parse_url(network_home_url(), PHP_URL_HOST))).'</option>'."\n";
1147
+ echo ' </select></p>'."\n";
1148
+ echo ' <p>'.__('Or, you can update your configuration manually: [<a href="#" data-toggle-target=".'.esc_attr(GLOBAL_NS.'-apache-optimizations--enforce-exact-host-name').'"><i class="si si-eye"></i> .htaccess configuration <i class="si si-eye"></i></a>]', 'comet-cache').'</p>'."\n";
1149
+ echo ' <div class="'.esc_attr(GLOBAL_NS.'-apache-optimizations--enforce-exact-host-name').'" style="display:none; margin-top:1em;">'."\n";
1150
+ echo ' <p>'.__('<strong>To enforce an exact hostname:</strong> Create or edit the <code>.htaccess</code> file in your WordPress installation directory and add the following lines to the top:', 'comet-cache').'</p>'."\n";
1151
+ echo ' <pre class="code"><code>'.esc_html($this->plugin->fillReplacementCodes(file_get_contents(dirname(__DIR__).'/templates/htaccess/enforce-exact-host-name.txt'))).'</code></pre>'."\n";
1152
+ echo ' </div>'."\n";
1153
+ }
1154
  if ((IS_PRO && !empty($GLOBALS['wp_rewrite']->permalink_structure)) || $this->plugin->isProPreview()) {
1155
  echo ' <hr />'."\n";
1156
  echo ' <h3 data-pro-version-only="'.(!IS_PRO ? __('pro version only', 'comet-cache') : '').'">'.__('Enforce Canonical URLs?', 'comet-cache').'</h3>'."\n";
1253
  echo ' <p>'.__('For more documentation, please see <a href="http://cometcache.com/r/kb-dynamic-version-salts/" target="_blank">Dynamic Version Salts</a>.', 'comet-cache').'</p>'."\n";
1254
  echo ' <hr />'."\n";
1255
  echo ' <h3>'.sprintf(__('Create a Dynamic Version Salt For %1$s? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size:90%%; opacity:0.5;">150%% OPTIONAL</span>', 'comet-cache'), esc_html(NAME)).'</h3>'."\n";
1256
+ echo ' <table style="width:100%;"><tr><td style="width:1px; font-weight:bold; white-space:pre;">PROTOCOL.HOST.URI.v.</td><td><input type="text" name="'.esc_attr(GLOBAL_NS).'[saveOptions][version_salt]" value="'.esc_attr($this->plugin->options['version_salt']).'" class="monospace" placeholder="$_COOKIE[\'my_cookie\']" /></td><td style="width:1px; font-weight:bold; white-space:pre;"></td></tr></table>'."\n";
1257
  echo ' <p class="info" style="display:block;">'.__('<a href="http://php.net/manual/en/language.variables.superglobals.php" target="_blank">Super Globals</a> work here; <a href="http://codex.wordpress.org/Editing_wp-config.php#table_prefix" target="_blank"><code>$GLOBALS[\'table_prefix\']</code></a> is a popular one.<br />Or, perhaps a PHP Constant defined in <code>/wp-config.php</code>; such as <code>WPLANG</code> or <code>DB_HOST</code>.', 'comet-cache').'</p>'."\n";
1258
  echo ' <p class="notice" style="display:block;">'.__('<strong>Important:</strong> your Version Salt is scanned for PHP syntax errors via <a href="http://phpcodechecker.com/" target="_blank"><code>phpCodeChecker.com</code></a>. If errors are found, you\'ll receive a notice in the Dashboard.', 'comet-cache').'</p>'."\n";
1259
  echo ' <p class="info" style="display:block;">'.__('If you\'ve enabled a separate cache for each user (optional) that\'s perfectly OK. A Version Salt works with user caching too.', 'comet-cache').'</p>'."\n";
src/includes/classes/Plugin.php CHANGED
@@ -26,11 +26,11 @@ class Plugin extends AbsBaseAp
26
  use Traits\Plugin\NoticeUtils;
27
  use Traits\Plugin\OptionUtils;
28
  use Traits\Plugin\PostUtils;
29
- use Traits\Plugin\UpdateUtils;
30
  use Traits\Plugin\UrlUtils;
31
  use Traits\Plugin\UserUtils;
32
  use Traits\Plugin\WcpAuthorUtils;
33
  use Traits\Plugin\WcpCommentUtils;
 
34
  use Traits\Plugin\WcpFeedUtils;
35
  use Traits\Plugin\WcpHomeBlogUtils;
36
  use Traits\Plugin\WcpJetpackUtils;
@@ -227,6 +227,7 @@ class Plugin extends AbsBaseAp
227
  'auto_cache_user_agent',
228
 
229
  'htaccess_browser_caching_enable',
 
230
  'htaccess_enforce_canonical_urls',
231
  'htaccess_access_control_allow_origin',
232
 
@@ -322,6 +323,12 @@ class Plugin extends AbsBaseAp
322
  'cache_clear_term_post_tag_enable' => '1', // `0|1`.
323
  'cache_clear_term_other_enable' => '1', // `0|1`.
324
 
 
 
 
 
 
 
325
  /* Misc. cache behaviors. */
326
 
327
  'allow_client_side_cache' => '0', // `0|1`.
@@ -388,6 +395,7 @@ class Plugin extends AbsBaseAp
388
 
389
  'htaccess_browser_caching_enable' => '0', // `0|1`; enable browser caching?
390
  'htaccess_gzip_enable' => '0', // `0|1`; enable GZIP compression?
 
391
  'htaccess_enforce_canonical_urls' => '0', // `0|1`; enforce canonical URLs?
392
  'htaccess_access_control_allow_origin' => '0', // `0|1`; send Access-Control-Allow-Origin header?
393
 
@@ -429,12 +437,8 @@ class Plugin extends AbsBaseAp
429
 
430
  /* Related to automatic pro updates. */
431
 
432
- 'lite_update_check' => '0', // `0|1`; enable?
433
- 'latest_lite_version' => VERSION, // Latest version.
434
- 'last_lite_update_check' => '0', // Timestamp.
435
-
436
  'pro_update_check' => '1', // `0|1`; enable?
437
- 'pro_update_check_stable' => '1', // `0` for beta/RC checks; defaults to `1`
438
  'last_pro_update_check' => '0', // Timestamp.
439
 
440
  'latest_pro_version' => VERSION, // Latest version.
@@ -468,13 +472,16 @@ class Plugin extends AbsBaseAp
468
  }
469
  /* -------------------------------------------------------------- */
470
 
 
471
  add_action('init', [$this, 'checkAdvancedCache']);
472
  add_action('init', [$this, 'checkBlogPaths']);
473
  add_action('init', [$this, 'checkCronSetup'], PHP_INT_MAX);
 
474
  add_action('wp_loaded', [$this, 'actions']);
475
 
476
- add_action('admin_init', [$this, 'checkVersion']);
477
- add_action('admin_init', [$this, 'maybeCheckLatestLiteVersion']);
 
478
 
479
 
480
 
@@ -501,10 +508,13 @@ class Plugin extends AbsBaseAp
501
 
502
  add_filter('enable_live_network_counts', [$this, 'updateBlogPaths']);
503
 
504
- add_action('activated_plugin', [$this, 'autoClearOnPluginActivationDeactivation'], 10, 2);
505
- add_action('deactivated_plugin', [$this, 'autoClearOnPluginActivationDeactivation'], 10, 2);
506
  add_action('admin_init', [$this, 'autoClearCacheOnSettingChanges']);
 
507
  add_action('safecss_save_pre', [$this, 'autoClearCacheOnJetpackCustomCss'], 10, 1);
 
 
 
 
508
  add_action('upgrader_process_complete', [$this, 'autoClearOnUpgraderProcessComplete'], 10, 2);
509
  add_action('upgrader_process_complete', [$this, 'wipeOpcacheByForce'], PHP_INT_MAX);
510
 
26
  use Traits\Plugin\NoticeUtils;
27
  use Traits\Plugin\OptionUtils;
28
  use Traits\Plugin\PostUtils;
 
29
  use Traits\Plugin\UrlUtils;
30
  use Traits\Plugin\UserUtils;
31
  use Traits\Plugin\WcpAuthorUtils;
32
  use Traits\Plugin\WcpCommentUtils;
33
+ use Traits\Plugin\WcpDateArchiveUtils;
34
  use Traits\Plugin\WcpFeedUtils;
35
  use Traits\Plugin\WcpHomeBlogUtils;
36
  use Traits\Plugin\WcpJetpackUtils;
227
  'auto_cache_user_agent',
228
 
229
  'htaccess_browser_caching_enable',
230
+ 'htaccess_enforce_exact_host_name',
231
  'htaccess_enforce_canonical_urls',
232
  'htaccess_access_control_allow_origin',
233
 
323
  'cache_clear_term_post_tag_enable' => '1', // `0|1`.
324
  'cache_clear_term_other_enable' => '1', // `0|1`.
325
 
326
+ 'cache_clear_date_archives_enable' => '1', // `0|1|2|3`.
327
+ // 0 = No, don't clear any associated Date archive views.
328
+ // 1 = Yes, if any single Post is cleared/reset, also clear the associated Date archive views.
329
+ // 2 = Yes, but only clear the associated Day and Month Date archive views.
330
+ // 3 = Yes, but only clear the associated Day Date archive view.
331
+
332
  /* Misc. cache behaviors. */
333
 
334
  'allow_client_side_cache' => '0', // `0|1`.
395
 
396
  'htaccess_browser_caching_enable' => '0', // `0|1`; enable browser caching?
397
  'htaccess_gzip_enable' => '0', // `0|1`; enable GZIP compression?
398
+ 'htaccess_enforce_exact_host_name' => '0', // `0|1`; enforce exact hostname?
399
  'htaccess_enforce_canonical_urls' => '0', // `0|1`; enforce canonical URLs?
400
  'htaccess_access_control_allow_origin' => '0', // `0|1`; send Access-Control-Allow-Origin header?
401
 
437
 
438
  /* Related to automatic pro updates. */
439
 
 
 
 
 
440
  'pro_update_check' => '1', // `0|1`; enable?
441
+ 'pro_update_check_stable' => '1', // `0` for beta/RC checks.
442
  'last_pro_update_check' => '0', // Timestamp.
443
 
444
  'latest_pro_version' => VERSION, // Latest version.
472
  }
473
  /* -------------------------------------------------------------- */
474
 
475
+ add_action('init', [$this, 'checkVersion']);
476
  add_action('init', [$this, 'checkAdvancedCache']);
477
  add_action('init', [$this, 'checkBlogPaths']);
478
  add_action('init', [$this, 'checkCronSetup'], PHP_INT_MAX);
479
+
480
  add_action('wp_loaded', [$this, 'actions']);
481
 
482
+
483
+
484
+
485
 
486
 
487
 
508
 
509
  add_filter('enable_live_network_counts', [$this, 'updateBlogPaths']);
510
 
 
 
511
  add_action('admin_init', [$this, 'autoClearCacheOnSettingChanges']);
512
+
513
  add_action('safecss_save_pre', [$this, 'autoClearCacheOnJetpackCustomCss'], 10, 1);
514
+
515
+ add_action('activated_plugin', [$this, 'autoClearOnPluginActivationDeactivation'], 10, 2);
516
+ add_action('deactivated_plugin', [$this, 'autoClearOnPluginActivationDeactivation'], 10, 2);
517
+
518
  add_action('upgrader_process_complete', [$this, 'autoClearOnUpgraderProcessComplete'], 10, 2);
519
  add_action('upgrader_process_complete', [$this, 'wipeOpcacheByForce'], PHP_INT_MAX);
520
 
src/includes/classes/VsUpgrades.php CHANGED
@@ -9,7 +9,7 @@ namespace WebSharks\CometCache\Classes;
9
  class VsUpgrades extends AbsBase
10
  {
11
  /**
12
- * @var string Version they are upgrading from.
13
  *
14
  * @since 150422 Rewrite.
15
  */
@@ -132,9 +132,7 @@ class VsUpgrades extends AbsBase
132
  protected function fromLte151114()
133
  {
134
  if (version_compare($this->prev_version, '151114', '<=')) {
135
- global $is_apache;
136
-
137
- if (!$is_apache) {
138
  return; // Not running the Apache web server.
139
  }
140
  if (!($htaccess_file = $this->plugin->findHtaccessFile())) {
@@ -187,8 +185,8 @@ class VsUpgrades extends AbsBase
187
  }
188
  $this->plugin->deleteBaseDir(); // Let's be extra sure that the old base directory is gone.
189
 
190
- global $is_apache; // Remove htaccess rules added by ZenCache so that they can be re-added by Comet Cache
191
- if ($is_apache && $this->plugin->findHtaccessMarker('WmVuQ2FjaGU') && ($htaccess = $this->plugin->readHtaccessFile())) {
192
  $regex = '/#\s*BEGIN\s+ZenCache\s+WmVuQ2FjaGU.*?#\s*END\s+ZenCache\s+WmVuQ2FjaGU\s*/uis';
193
  $htaccess['file_contents'] = preg_replace($regex, '', $htaccess['file_contents']);
194
 
@@ -238,8 +236,6 @@ class VsUpgrades extends AbsBase
238
  protected function fromLte160521()
239
  {
240
  if (version_compare($this->prev_version, '160521', '<=')) {
241
- global $is_apache; // WP global for web server checks below.
242
-
243
  $this->plugin->dismissMainNotice('allow_url_fopen_disabled');
244
  $this->plugin->removeAdvancedCache();
245
 
@@ -255,8 +251,7 @@ class VsUpgrades extends AbsBase
255
  $this->plugin->activate(); // Reactivate plugin w/ new options.
256
  }
257
  }
258
-
259
- if ($is_apache) {
260
  $this->plugin->enqueueMainNotice(sprintf(__('<strong>New %1$s Feature!</strong> This release of %1$s includes a whole new panel for Apache Performance Tuning. Visit the <a href="%2$s">settings</a> and see the new options in <strong>Comet Cache → Plugin Options → Apache Optimizations</strong>.', 'comet-cache'), esc_html(NAME), esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS]), self_admin_url('/admin.php')))));
261
  }
262
  }
9
  class VsUpgrades extends AbsBase
10
  {
11
  /**
12
+ * @type string Version they are upgrading from.
13
  *
14
  * @since 150422 Rewrite.
15
  */
132
  protected function fromLte151114()
133
  {
134
  if (version_compare($this->prev_version, '151114', '<=')) {
135
+ if (!$this->plugin->isApache()) {
 
 
136
  return; // Not running the Apache web server.
137
  }
138
  if (!($htaccess_file = $this->plugin->findHtaccessFile())) {
185
  }
186
  $this->plugin->deleteBaseDir(); // Let's be extra sure that the old base directory is gone.
187
 
188
+ // Remove htaccess rules added by ZenCache so that they can be re-added by Comet Cache
189
+ if ($this->plugin->isApache() && $this->plugin->findHtaccessMarker('WmVuQ2FjaGU') && ($htaccess = $this->plugin->readHtaccessFile())) {
190
  $regex = '/#\s*BEGIN\s+ZenCache\s+WmVuQ2FjaGU.*?#\s*END\s+ZenCache\s+WmVuQ2FjaGU\s*/uis';
191
  $htaccess['file_contents'] = preg_replace($regex, '', $htaccess['file_contents']);
192
 
236
  protected function fromLte160521()
237
  {
238
  if (version_compare($this->prev_version, '160521', '<=')) {
 
 
239
  $this->plugin->dismissMainNotice('allow_url_fopen_disabled');
240
  $this->plugin->removeAdvancedCache();
241
 
251
  $this->plugin->activate(); // Reactivate plugin w/ new options.
252
  }
253
  }
254
+ if ($this->plugin->isApache()) {
 
255
  $this->plugin->enqueueMainNotice(sprintf(__('<strong>New %1$s Feature!</strong> This release of %1$s includes a whole new panel for Apache Performance Tuning. Visit the <a href="%2$s">settings</a> and see the new options in <strong>Comet Cache → Plugin Options → Apache Optimizations</strong>.', 'comet-cache'), esc_html(NAME), esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS]), self_admin_url('/admin.php')))));
256
  }
257
  }
src/includes/interfaces/Shared/NcDebugConsts.php CHANGED
@@ -66,6 +66,24 @@ interface NcDebugConsts
66
  */
67
  const NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR = 'nc_debug_donotcachepage_server_var';
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  /**
70
  * No-cache because the current request includes the `?[SHORT_NAME]AC=0` parameter.
71
  *
@@ -193,12 +211,12 @@ interface NcDebugConsts
193
  const NC_DEBUG_PREVIEW = 'nc_debug_preview';
194
 
195
  /**
196
- * No-cache because the current request is excluded by its host name.
197
- *
198
- * @since 160706 Host exclusions.
199
- *
200
- * @type string A unique string identifier in the set of `NC_DEBUG_` constants.
201
- */
202
  const NC_DEBUG_EXCLUDED_HOSTS = 'nc_debug_excluded_hosts';
203
 
204
  /**
66
  */
67
  const NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR = 'nc_debug_donotcachepage_server_var';
68
 
69
+ /**
70
+ * No-cache because it's an `XMLRPC_REQUEST`.
71
+ *
72
+ * @since 170220 Enhancing compatibility with API requests.
73
+ *
74
+ * @type string A unique string identifier in the set of `NC_DEBUG_` constants.
75
+ */
76
+ const NC_DEBUG_XMLRPC_REQUEST_CONSTANT = 'nc_debug_xmlrpc_request_constant';
77
+
78
+ /**
79
+ * No-cache because it's a `REST_REQUEST`.
80
+ *
81
+ * @since 170220 Enhancing compatibility with API requests.
82
+ *
83
+ * @type string A unique string identifier in the set of `NC_DEBUG_` constants.
84
+ */
85
+ const NC_DEBUG_REST_REQUEST_CONSTANT = 'nc_debug_rest_request_constant';
86
+
87
  /**
88
  * No-cache because the current request includes the `?[SHORT_NAME]AC=0` parameter.
89
  *
211
  const NC_DEBUG_PREVIEW = 'nc_debug_preview';
212
 
213
  /**
214
+ * No-cache because the current request is excluded by its hostname.
215
+ *
216
+ * @since 160706 Host exclusions.
217
+ *
218
+ * @type string A unique string identifier in the set of `NC_DEBUG_` constants.
219
+ */
220
  const NC_DEBUG_EXCLUDED_HOSTS = 'nc_debug_excluded_hosts';
221
 
222
  /**
src/includes/plugin.php CHANGED
@@ -9,7 +9,7 @@ namespace WebSharks\CometCache;
9
  use WebSharks\CometCache\Classes;
10
 
11
  if (!defined('WPINC')) {
12
- exit('Do NOT access this file directly: '.basename(__FILE__));
13
  }
14
  require_once __DIR__.'/stub.php';
15
 
9
  use WebSharks\CometCache\Classes;
10
 
11
  if (!defined('WPINC')) {
12
+ exit('Do NOT access this file directly.');
13
  }
14
  require_once __DIR__.'/stub.php';
15
 
src/includes/stub.php CHANGED
@@ -8,12 +8,12 @@
8
  namespace WebSharks\CometCache;
9
 
10
  if (!defined('WPINC')) {
11
- exit('Do NOT access this file directly: '.basename(__FILE__));
12
  }
13
  require_once dirname(__DIR__).'/vendor/autoload.php';
14
  require_once __DIR__.'/functions/i18n-utils.php';
15
 
16
- ${__FILE__}['version'] = '161221'; //version//
17
  ${__FILE__}['plugin'] = dirname(dirname(__DIR__));
18
  ${__FILE__}['plugin'] .= '/'.basename(${__FILE__}['plugin']).'.php';
19
  ${__FILE__}['ns_path'] = str_replace('\\', '/', __NAMESPACE__); // To dir/path.
8
  namespace WebSharks\CometCache;
9
 
10
  if (!defined('WPINC')) {
11
+ exit('Do NOT access this file directly.');
12
  }
13
  require_once dirname(__DIR__).'/vendor/autoload.php';
14
  require_once __DIR__.'/functions/i18n-utils.php';
15
 
16
+ ${__FILE__}['version'] = '170220'; //version//
17
  ${__FILE__}['plugin'] = dirname(dirname(__DIR__));
18
  ${__FILE__}['plugin'] .= '/'.basename(${__FILE__}['plugin']).'.php';
19
  ${__FILE__}['ns_path'] = str_replace('\\', '/', __NAMESPACE__); // To dir/path.
src/includes/templates/ac-plugin.txt CHANGED
@@ -6,7 +6,7 @@
6
  * `/wp-content/ac-plugins/my-ac-plugin.php`
7
  */
8
  if (!defined('WPINC')) {
9
- exit('Do NOT access this file directly: '.basename(__FILE__));
10
  }
11
  function my_ac_plugin() // Example plugin.
12
  {
6
  * `/wp-content/ac-plugins/my-ac-plugin.php`
7
  */
8
  if (!defined('WPINC')) {
9
+ exit('Do NOT access this file directly.');
10
  }
11
  function my_ac_plugin() // Example plugin.
12
  {
src/includes/templates/advanced-cache.x-php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * Advanced cache stub.
4
  *
@@ -9,7 +10,7 @@ namespace WebSharks\CometCache;
9
  use WebSharks\CometCache\Classes;
10
 
11
  if (!defined('WPINC')) {
12
- exit('Do NOT access this file directly: '.basename(__FILE__));
13
  }
14
  if (!defined('COMET_CACHE_PLUGIN_FILE')) {
15
  /*
@@ -21,6 +22,16 @@ if (!defined('COMET_CACHE_PLUGIN_FILE')) {
21
  */
22
  define('COMET_CACHE_PLUGIN_FILE', '%%COMET_CACHE_PLUGIN_FILE%%');
23
  }
 
 
 
 
 
 
 
 
 
 
24
  if (defined('WP_DEBUG') && WP_DEBUG) {
25
  if ((include_once(dirname(COMET_CACHE_PLUGIN_FILE).'/src/includes/stub.php')) === false) {
26
  return; // Unable to find stub. Fail softly w/ PHP warning.
@@ -247,6 +258,7 @@ if (!defined('COMET_CACHE_404_CACHE_FILENAME')) {
247
 
248
  $GLOBALS[GLOBAL_NS.'_advanced_cache'] = new Classes\AdvancedCache();
249
  $GLOBALS[GLOBAL_NS.'__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
 
250
  if (!isset($GLOBALS['zencache__advanced_cache'])) {
251
  $GLOBALS['zencache_advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
252
  $GLOBALS['zencache__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
1
  <?php
2
+ // @codingStandardsIgnoreFile
3
  /**
4
  * Advanced cache stub.
5
  *
10
  use WebSharks\CometCache\Classes;
11
 
12
  if (!defined('WPINC')) {
13
+ exit('Do NOT access this file directly.');
14
  }
15
  if (!defined('COMET_CACHE_PLUGIN_FILE')) {
16
  /*
22
  */
23
  define('COMET_CACHE_PLUGIN_FILE', '%%COMET_CACHE_PLUGIN_FILE%%');
24
  }
25
+ if (!defined('COMET_CACHE_AC_FILE_VERSION')) {
26
+ /*
27
+ * Comet Cache AC file version.
28
+ *
29
+ * @since 161226 Adding AC file version.
30
+ *
31
+ * @var string Plugin version when AC file was built.
32
+ */
33
+ define('COMET_CACHE_AC_FILE_VERSION', '%%COMET_CACHE_AC_FILE_VERSION%%');
34
+ }
35
  if (defined('WP_DEBUG') && WP_DEBUG) {
36
  if ((include_once(dirname(COMET_CACHE_PLUGIN_FILE).'/src/includes/stub.php')) === false) {
37
  return; // Unable to find stub. Fail softly w/ PHP warning.
258
 
259
  $GLOBALS[GLOBAL_NS.'_advanced_cache'] = new Classes\AdvancedCache();
260
  $GLOBALS[GLOBAL_NS.'__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
261
+
262
  if (!isset($GLOBALS['zencache__advanced_cache'])) {
263
  $GLOBALS['zencache_advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
264
  $GLOBALS['zencache__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
src/includes/templates/htaccess/canonical-urls-no-ts-enable.txt CHANGED
@@ -10,6 +10,9 @@
10
  # Not a part of the WP admin area.
11
  RewriteCond %{REQUEST_URI} !(?:^|/)wp\-admin(?:/|$)
12
 
 
 
 
13
  # If there is a trailing slash.
14
  RewriteCond %{REQUEST_URI} /$
15
 
10
  # Not a part of the WP admin area.
11
  RewriteCond %{REQUEST_URI} !(?:^|/)wp\-admin(?:/|$)
12
 
13
+ # Not a REST request, which never redirects.
14
+ RewriteCond %{REQUEST_URI} !(?:^|/)%%REST_REQUEST_PREFIX_AS_REGEX_FRAG%%(?:/|$)
15
+
16
  # If there is a trailing slash.
17
  RewriteCond %{REQUEST_URI} /$
18
 
src/includes/templates/htaccess/canonical-urls-ts-enable.txt CHANGED
@@ -10,6 +10,9 @@
10
  # Not a part of the WP admin area.
11
  RewriteCond %{REQUEST_URI} !(?:^|/)wp\-admin(?:/|$)
12
 
 
 
 
13
  # If there is no trailing slash.
14
  RewriteCond %{REQUEST_URI} !/$
15
 
10
  # Not a part of the WP admin area.
11
  RewriteCond %{REQUEST_URI} !(?:^|/)wp\-admin(?:/|$)
12
 
13
+ # Not a REST request, which never redirects.
14
+ RewriteCond %{REQUEST_URI} !(?:^|/)%%REST_REQUEST_PREFIX_AS_REGEX_FRAG%%(?:/|$)
15
+
16
  # If there is no trailing slash.
17
  RewriteCond %{REQUEST_URI} !/$
18
 
src/includes/templates/htaccess/enforce-exact-host-name.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Enforce exact host name.
2
+ <IfModule rewrite_module>
3
+ RewriteEngine on
4
+ RewriteBase %%REWRITE_BASE%%
5
+
6
+ RewriteCond %{HTTP_HOST} !^%%HOST_NAME_AS_REGEX_FRAG%%$
7
+ RewriteCond %{HTTPS} !^on$ [NC]
8
+ RewriteCond %{HTTP:X-Forwarded-Proto} !^https$ [NC]
9
+ RewriteRule .* http://%%HOST_NAME_AS_REGEX_FRAG%%%{REQUEST_URI} [R=301,L]
10
+
11
+ RewriteCond %{HTTP_HOST} !^%%HOST_NAME_AS_REGEX_FRAG%%$
12
+ RewriteCond %{HTTPS} ^on$ [NC,OR]
13
+ RewriteCond %{HTTP:X-Forwarded-Proto} ^https$ [NC]
14
+ RewriteRule .* https://%%HOST_NAME_AS_REGEX_FRAG%%%{REQUEST_URI} [R=301,L]
15
+ </IfModule>
src/includes/traits/Ac/NcDebugUtils.php CHANGED
@@ -10,7 +10,7 @@ trait NcDebugUtils
10
  *
11
  * @since 150422 Rewrite.
12
  *
13
- * @var array An array of debug info; i.e. `reason_code` and `reason` (optional).
14
  */
15
  public $debug_info = ['reason_code' => '', 'reason' => ''];
16
 
@@ -38,6 +38,7 @@ trait NcDebugUtils
38
  * Echoes `NC_DEBUG_` info in the WordPress `shutdown` phase (if applicable).
39
  *
40
  * @since 150422 Rewrite.
 
41
  *
42
  * @attaches-to `shutdown` hook in WordPress w/ a late priority.
43
  */
@@ -52,6 +53,12 @@ trait NcDebugUtils
52
  if (strcasecmp(PHP_SAPI, 'cli') === 0) {
53
  return; // Let's not run the risk here.
54
  }
 
 
 
 
 
 
55
  if ($this->debug_info && $this->hasACacheableContentType() && $this->is_a_wp_content_type) {
56
  echo (string) $this->maybeGetNcDebugInfo($this->debug_info['reason_code'], $this->debug_info['reason']);
57
  }
@@ -61,6 +68,7 @@ trait NcDebugUtils
61
  * Gets `NC_DEBUG_` info (if applicable).
62
  *
63
  * @since 150422 Rewrite.
 
64
  *
65
  * @param string $reason_code One of the `NC_DEBUG_` constants.
66
  * @param string $reason Optional; to override the default description with a custom message.
@@ -110,6 +118,14 @@ trait NcDebugUtils
110
  $reason = __('because the environment variable `$_SERVER[\'DONOTCACHEPAGE\']` has been set at runtime. Perhaps by WordPress itself, or by one of your themes/plugins. This usually means that you have a theme/plugin intentionally disabling the cache on this page; and it\'s usually for a very good reason.', 'comet-cache');
111
  break; // Break switch handler.
112
 
 
 
 
 
 
 
 
 
113
  case $this::NC_DEBUG_AC_GET_VAR:
114
  $reason = sprintf(__('because `$_GET[\'%1$sAC\']` is set to a boolean-ish FALSE value.', 'comet-cache'), mb_strtolower(SHORT_NAME));
115
  break; // Break switch handler.
10
  *
11
  * @since 150422 Rewrite.
12
  *
13
+ * @type array An array of debug info; i.e. `reason_code` and `reason` (optional).
14
  */
15
  public $debug_info = ['reason_code' => '', 'reason' => ''];
16
 
38
  * Echoes `NC_DEBUG_` info in the WordPress `shutdown` phase (if applicable).
39
  *
40
  * @since 150422 Rewrite.
41
+ * @since 170220 Do not display for API requests.
42
  *
43
  * @attaches-to `shutdown` hook in WordPress w/ a late priority.
44
  */
53
  if (strcasecmp(PHP_SAPI, 'cli') === 0) {
54
  return; // Let's not run the risk here.
55
  }
56
+ if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) {
57
+ return; // Let's not run the risk here.
58
+ }
59
+ if (defined('REST_REQUEST') && REST_REQUEST) {
60
+ return; // Let's not run the risk here.
61
+ }
62
  if ($this->debug_info && $this->hasACacheableContentType() && $this->is_a_wp_content_type) {
63
  echo (string) $this->maybeGetNcDebugInfo($this->debug_info['reason_code'], $this->debug_info['reason']);
64
  }
68
  * Gets `NC_DEBUG_` info (if applicable).
69
  *
70
  * @since 150422 Rewrite.
71
+ * @since 170220 Adding API request constants.
72
  *
73
  * @param string $reason_code One of the `NC_DEBUG_` constants.
74
  * @param string $reason Optional; to override the default description with a custom message.
118
  $reason = __('because the environment variable `$_SERVER[\'DONOTCACHEPAGE\']` has been set at runtime. Perhaps by WordPress itself, or by one of your themes/plugins. This usually means that you have a theme/plugin intentionally disabling the cache on this page; and it\'s usually for a very good reason.', 'comet-cache');
119
  break; // Break switch handler.
120
 
121
+ case $this::NC_DEBUG_XMLRPC_REQUEST_CONSTANT:
122
+ $reason = __('because the PHP constant `XMLRPC_REQUEST` has been set to a boolean-ish `TRUE` value at runtime. XML-RPC requests are never cached, as they are often very dynamic in nature.', 'comet-cache');
123
+ break; // Break switch handler.
124
+
125
+ case $this::NC_DEBUG_REST_REQUEST_CONSTANT:
126
+ $reason = __('because the PHP constant `REST_REQUEST` has been set to a boolean-ish `TRUE` value at runtime. REST requests are never cached, as they are often very dynamic in nature.', 'comet-cache');
127
+ break; // Break switch handler.
128
+
129
  case $this::NC_DEBUG_AC_GET_VAR:
130
  $reason = sprintf(__('because `$_GET[\'%1$sAC\']` is set to a boolean-ish FALSE value.', 'comet-cache'), mb_strtolower(SHORT_NAME));
131
  break; // Break switch handler.
src/includes/traits/Ac/ObUtils.php CHANGED
@@ -97,6 +97,15 @@ trait ObUtils
97
  */
98
  public $cache_max_age = 0;
99
 
 
 
 
 
 
 
 
 
 
100
  /**
101
  * Calculated 12 hour expiration time.
102
  *
@@ -109,9 +118,12 @@ trait ObUtils
109
  /**
110
  * Start output buffering or serve cache.
111
  *
112
- * @since 150422 Rewrite. This is a vital part of Comet Cache.
113
- * This method serves existing (fresh) cache files. It is also responsible
114
- * for beginning the process of collecting the output buffer.
 
 
 
115
  */
116
  public function maybeStartOutputBuffering()
117
  {
@@ -136,6 +148,12 @@ trait ObUtils
136
  if (isset($_SERVER['DONOTCACHEPAGE'])) {
137
  return $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
138
  }
 
 
 
 
 
 
139
  if (isset($_GET[mb_strtolower(SHORT_NAME).'AC']) && !filter_var($_GET[mb_strtolower(SHORT_NAME).'AC'], FILTER_VALIDATE_BOOLEAN)) {
140
  return $this->maybeSetDebugInfo($this::NC_DEBUG_AC_GET_VAR);
141
  }
@@ -215,25 +233,22 @@ trait ObUtils
215
 
216
  if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN === 'postload' && $this->isLikeUserLoggedIn()) {
217
  $this->postload['when_logged_in'] = true; // Enable postload check.
218
- } elseif (is_file($this->cache_file) && (!$this->cache_max_age || filemtime($this->cache_file) >= $this->cache_max_age)) {
219
  list($headers, $cache) = explode('<!--headers-->', file_get_contents($this->cache_file), 2);
220
 
221
- $headers_list = $this->headersList();
 
222
  foreach (unserialize($headers) as $_header) {
223
  if (!in_array($_header, $headers_list, true) && mb_stripos($_header, 'Last-Modified:') !== 0) {
224
  header($_header); // Only cacheable/safe headers are stored in the cache.
225
  }
226
- }
227
- unset($_header); // Just a little housekeeping.
228
 
229
  if (COMET_CACHE_DEBUGGING_ENABLE && $this->isHtmlXmlDoc($cache)) {
230
  $total_time = number_format(microtime(true) - $this->timer, 5, '.', '');
231
 
232
  $DebugNotes = new Classes\Notes();
233
 
234
- $DebugNotes->addAsciiArt(sprintf(__('%1$s is Fully Functional', 'comet-cache'), NAME));
235
- $DebugNotes->addLineBreak();
236
-
237
  $DebugNotes->add(__('Loaded via Cache On', 'comet-cache'), date('M jS, Y @ g:i a T'));
238
  $DebugNotes->add(__('Loaded via Cache In', 'comet-cache'), sprintf(__('%1$s seconds', 'comet-cache'), $total_time));
239
 
@@ -249,10 +264,8 @@ trait ObUtils
249
  /**
250
  * Output buffer handler; i.e. the cache file generator.
251
  *
252
- * @note We CANNOT depend on any WP functionality here; it will cause problems.
253
- * Anything we need from WP should be saved in the postload phase as a scalar value.
254
- *
255
  * @since 150422 Rewrite.
 
256
  *
257
  * @param string $buffer The buffer from {@link \ob_start()}.
258
  * @param int $phase A set of bitmask flags.
@@ -261,6 +274,9 @@ trait ObUtils
261
  *
262
  * @return string|bool The output buffer, or `FALSE` to indicate no change.
263
  *
 
 
 
264
  * @attaches-to {@link \ob_start()}
265
  */
266
  public function outputBufferCallbackHandler($buffer, $phase)
@@ -290,6 +306,12 @@ trait ObUtils
290
  if (isset($_SERVER['DONOTCACHEPAGE'])) {
291
  return (bool) $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
292
  }
 
 
 
 
 
 
293
  if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $this->is_user_logged_in) {
294
  return (bool) $this->maybeSetDebugInfo($this::NC_DEBUG_IS_LOGGED_IN_USER);
295
  }
@@ -362,7 +384,7 @@ trait ObUtils
362
  $time = time(); // Needed below for expiration calculation.
363
 
364
  $DebugNotes = new Classes\Notes();
365
- $DebugNotes->addAsciiArt(sprintf(__('%1$s Notes', 'comet-cache'), NAME));
366
  $DebugNotes->addLineBreak();
367
 
368
  if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $this->user_token) {
@@ -387,8 +409,7 @@ trait ObUtils
387
 
388
  $DebugNotes->addLineBreak();
389
 
390
- if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $this->cache_max_age < $this->nonce_cache_max_age
391
- && preg_match('/\b(?:_wpnonce|akismet_comment_nonce)\b/u', $cache)) {
392
  $DebugNotes->add(__('Cache File Expires Early', 'comet-cache'), __('yes, due to nonce in markup', 'comet-cache'));
393
  $DebugNotes->add(__('Cache File Expires On', 'comet-cache'), date('M jS, Y @ g:i a T', $time + ($time - $this->nonce_cache_max_age)));
394
  $DebugNotes->add(__('Cache File Auto-Rebuild On', 'comet-cache'), date('M jS, Y @ g:i a T', $time + ($time - $this->nonce_cache_max_age)));
@@ -404,11 +425,11 @@ trait ObUtils
404
  throw new \Exception(sprintf(__('Unable to create symlink: `%1$s` » `%2$s`. Possible permissions issue (or race condition), please check your cache directory: `%3$s`.', 'comet-cache'), $this->cache_file, $this->cache_file_404, COMET_CACHE_DIR));
405
  }
406
  $this->cacheUnlock($cache_lock); // Release.
407
- return $cache; // Return the newly built cache; with possible debug information also.
408
  }
409
  } elseif (file_put_contents($cache_file_tmp, serialize($this->cacheableHeadersList()).'<!--headers-->'.$cache) && rename($cache_file_tmp, $this->cache_file)) {
410
  $this->cacheUnlock($cache_lock); // Release.
411
- return $cache; // Return the newly built cache; with possible debug information also.
412
  }
413
  @unlink($cache_file_tmp); // Clean this up (if it exists); and throw an exception with information for the site owner.
414
  throw new \Exception(sprintf(__('%1$s: failed to write cache file for: `%2$s`; possible permissions issue (or race condition), please check your cache directory: `%3$s`.', 'comet-cache'), NAME, $_SERVER['REQUEST_URI'], COMET_CACHE_DIR));
97
  */
98
  public $cache_max_age = 0;
99
 
100
+ /**
101
+ * Max age has been disabled?
102
+ *
103
+ * @since 161226 Load average checks.
104
+ *
105
+ * @type bool Max age disabled?
106
+ */
107
+ public $cache_max_age_disabled = false;
108
+
109
  /**
110
  * Calculated 12 hour expiration time.
111
  *
118
  /**
119
  * Start output buffering or serve cache.
120
  *
121
+ * @since 150422 Rewrite.
122
+ * @since 170220 Adding API request constants.
123
+ *
124
+ * @note This is a vital part of Comet Cache.
125
+ * This method serves existing (fresh) cache files. It is also responsible
126
+ * for beginning the process of collecting the output buffer.
127
  */
128
  public function maybeStartOutputBuffering()
129
  {
148
  if (isset($_SERVER['DONOTCACHEPAGE'])) {
149
  return $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
150
  }
151
+ if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) {
152
+ return $this->maybeSetDebugInfo($this::NC_DEBUG_XMLRPC_REQUEST_CONSTANT);
153
+ }
154
+ if (defined('REST_REQUEST') && REST_REQUEST) {
155
+ return $this->maybeSetDebugInfo($this::NC_DEBUG_REST_REQUEST_CONSTANT);
156
+ }
157
  if (isset($_GET[mb_strtolower(SHORT_NAME).'AC']) && !filter_var($_GET[mb_strtolower(SHORT_NAME).'AC'], FILTER_VALIDATE_BOOLEAN)) {
158
  return $this->maybeSetDebugInfo($this::NC_DEBUG_AC_GET_VAR);
159
  }
233
 
234
  if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN === 'postload' && $this->isLikeUserLoggedIn()) {
235
  $this->postload['when_logged_in'] = true; // Enable postload check.
236
+ } elseif (is_file($this->cache_file) && ($this->cache_max_age_disabled || filemtime($this->cache_file) >= $this->cache_max_age)) {
237
  list($headers, $cache) = explode('<!--headers-->', file_get_contents($this->cache_file), 2);
238
 
239
+ $headers_list = $this->headersList(); // Headers that are enqueued already.
240
+
241
  foreach (unserialize($headers) as $_header) {
242
  if (!in_array($_header, $headers_list, true) && mb_stripos($_header, 'Last-Modified:') !== 0) {
243
  header($_header); // Only cacheable/safe headers are stored in the cache.
244
  }
245
+ } // unset($_header); // Just a little housekeeping.
 
246
 
247
  if (COMET_CACHE_DEBUGGING_ENABLE && $this->isHtmlXmlDoc($cache)) {
248
  $total_time = number_format(microtime(true) - $this->timer, 5, '.', '');
249
 
250
  $DebugNotes = new Classes\Notes();
251
 
 
 
 
252
  $DebugNotes->add(__('Loaded via Cache On', 'comet-cache'), date('M jS, Y @ g:i a T'));
253
  $DebugNotes->add(__('Loaded via Cache In', 'comet-cache'), sprintf(__('%1$s seconds', 'comet-cache'), $total_time));
254
 
264
  /**
265
  * Output buffer handler; i.e. the cache file generator.
266
  *
 
 
 
267
  * @since 150422 Rewrite.
268
+ * @since 170220 Adding API request constants.
269
  *
270
  * @param string $buffer The buffer from {@link \ob_start()}.
271
  * @param int $phase A set of bitmask flags.
274
  *
275
  * @return string|bool The output buffer, or `FALSE` to indicate no change.
276
  *
277
+ * @note We CANNOT depend on any WP functionality here; it will cause problems.
278
+ * Anything we need from WP should be saved in the postload phase as a scalar value.
279
+ *
280
  * @attaches-to {@link \ob_start()}
281
  */
282
  public function outputBufferCallbackHandler($buffer, $phase)
306
  if (isset($_SERVER['DONOTCACHEPAGE'])) {
307
  return (bool) $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
308
  }
309
+ if (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) {
310
+ return (bool) $this->maybeSetDebugInfo($this::NC_DEBUG_XMLRPC_REQUEST_CONSTANT);
311
+ }
312
+ if (defined('REST_REQUEST') && REST_REQUEST) {
313
+ return (bool) $this->maybeSetDebugInfo($this::NC_DEBUG_REST_REQUEST_CONSTANT);
314
+ }
315
  if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $this->is_user_logged_in) {
316
  return (bool) $this->maybeSetDebugInfo($this::NC_DEBUG_IS_LOGGED_IN_USER);
317
  }
384
  $time = time(); // Needed below for expiration calculation.
385
 
386
  $DebugNotes = new Classes\Notes();
387
+ $DebugNotes->addAsciiArt(sprintf(__('%1$s is Fully Functional', 'comet-cache'), NAME));
388
  $DebugNotes->addLineBreak();
389
 
390
  if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $this->user_token) {
409
 
410
  $DebugNotes->addLineBreak();
411
 
412
+ if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $this->cache_max_age < $this->nonce_cache_max_age && preg_match('/\b(?:_wpnonce|akismet_comment_nonce)\b/u', $cache)) {
 
413
  $DebugNotes->add(__('Cache File Expires Early', 'comet-cache'), __('yes, due to nonce in markup', 'comet-cache'));
414
  $DebugNotes->add(__('Cache File Expires On', 'comet-cache'), date('M jS, Y @ g:i a T', $time + ($time - $this->nonce_cache_max_age)));
415
  $DebugNotes->add(__('Cache File Auto-Rebuild On', 'comet-cache'), date('M jS, Y @ g:i a T', $time + ($time - $this->nonce_cache_max_age)));
425
  throw new \Exception(sprintf(__('Unable to create symlink: `%1$s` » `%2$s`. Possible permissions issue (or race condition), please check your cache directory: `%3$s`.', 'comet-cache'), $this->cache_file, $this->cache_file_404, COMET_CACHE_DIR));
426
  }
427
  $this->cacheUnlock($cache_lock); // Release.
428
+ return $cache; // Return the newly built cache; with possible debug info.
429
  }
430
  } elseif (file_put_contents($cache_file_tmp, serialize($this->cacheableHeadersList()).'<!--headers-->'.$cache) && rename($cache_file_tmp, $this->cache_file)) {
431
  $this->cacheUnlock($cache_lock); // Release.
432
+ return $cache; // Return the newly built cache; with possible debug info.
433
  }
434
  @unlink($cache_file_tmp); // Clean this up (if it exists); and throw an exception with information for the site owner.
435
  throw new \Exception(sprintf(__('%1$s: failed to write cache file for: `%2$s`; possible permissions issue (or race condition), please check your cache directory: `%3$s`.', 'comet-cache'), NAME, $_SERVER['REQUEST_URI'], COMET_CACHE_DIR));
src/includes/traits/Ac/PostloadUtils.php CHANGED
@@ -10,7 +10,7 @@ trait PostloadUtils
10
  *
11
  * @since 150422 Rewrite.
12
  *
13
- * @var bool `TRUE` if main query has been loaded; else `FALSE`.
14
  *
15
  * @see wpMainQueryPostload()
16
  */
@@ -21,7 +21,7 @@ trait PostloadUtils
21
  *
22
  * @since 150422 Rewrite.
23
  *
24
- * @var bool `TRUE` if is a 404 error; else `FALSE`.
25
  *
26
  * @see wpMainQueryPostload()
27
  */
@@ -32,7 +32,7 @@ trait PostloadUtils
32
  *
33
  * @since 150422 Rewrite.
34
  *
35
- * @var int Last HTTP status code (if applicable).
36
  *
37
  * @see maybeFilterStatusHeaderPostload()
38
  */
@@ -43,7 +43,7 @@ trait PostloadUtils
43
  *
44
  * @since 150422 Rewrite.
45
  *
46
- * @var bool `TRUE` if is a WP content type.
47
  *
48
  * @see wpMainQueryPostload()
49
  */
@@ -54,7 +54,7 @@ trait PostloadUtils
54
  *
55
  * @since 150422 Rewrite.
56
  *
57
- * @var string Current WordPress {@link \content_url()}.
58
  *
59
  * @see wpMainQueryPostload()
60
  */
@@ -65,7 +65,7 @@ trait PostloadUtils
65
  *
66
  * @since 150422 Rewrite.
67
  *
68
- * @var bool `TRUE` if {@link \is_user_loged_in()} else `FALSE`.
69
  *
70
  * @see wpMainQueryPostload()
71
  */
@@ -76,7 +76,7 @@ trait PostloadUtils
76
  *
77
  * @since 150422 Rewrite.
78
  *
79
- * @var bool `TRUE` if {@link \is_maintenance()} else `FALSE`.
80
  *
81
  * @see wpMainQueryPostload()
82
  */
@@ -87,7 +87,7 @@ trait PostloadUtils
87
  *
88
  * @since 150422 Rewrite.
89
  *
90
- * @var array Data and/or flags that work with various postload handlers.
91
  */
92
  public $postload = [
93
 
10
  *
11
  * @since 150422 Rewrite.
12
  *
13
+ * @type bool `TRUE` if main query has been loaded; else `FALSE`.
14
  *
15
  * @see wpMainQueryPostload()
16
  */
21
  *
22
  * @since 150422 Rewrite.
23
  *
24
+ * @type bool `TRUE` if is a 404 error; else `FALSE`.
25
  *
26
  * @see wpMainQueryPostload()
27
  */
32
  *
33
  * @since 150422 Rewrite.
34
  *
35
+ * @type int Last HTTP status code (if applicable).
36
  *
37
  * @see maybeFilterStatusHeaderPostload()
38
  */
43
  *
44
  * @since 150422 Rewrite.
45
  *
46
+ * @type bool `TRUE` if is a WP content type.
47
  *
48
  * @see wpMainQueryPostload()
49
  */
54
  *
55
  * @since 150422 Rewrite.
56
  *
57
+ * @type string Current WordPress {@link \content_url()}.
58
  *
59
  * @see wpMainQueryPostload()
60
  */
65
  *
66
  * @since 150422 Rewrite.
67
  *
68
+ * @type bool `TRUE` if {@link \is_user_loged_in()} else `FALSE`.
69
  *
70
  * @see wpMainQueryPostload()
71
  */
76
  *
77
  * @since 150422 Rewrite.
78
  *
79
+ * @type bool `TRUE` if {@link \is_maintenance()} else `FALSE`.
80
  *
81
  * @see wpMainQueryPostload()
82
  */
87
  *
88
  * @since 150422 Rewrite.
89
  *
90
+ * @type array Data and/or flags that work with various postload handlers.
91
  */
92
  public $postload = [
93
 
src/includes/traits/Plugin/CronUtils.php CHANGED
@@ -26,7 +26,7 @@ trait CronUtils
26
  }
27
 
28
  /**
29
- * Checks Cron setup, validates schedules, and reschedules events if necessary.
30
  *
31
  * @attaches-to `init` hook.
32
  *
@@ -62,7 +62,8 @@ trait CronUtils
62
  *
63
  * @since 151220 Fixing bug with Auto-Cache Engine cron disappearing in some scenarios
64
  *
65
- * @note This MUST happen upon uninstall and deactivation due to buggy WP_Cron behavior. Events with a custom schedule will disappear when plugin is not active (see http://bit.ly/1lGdr78).
 
66
  */
67
  public function resetCronSetup()
68
  {
26
  }
27
 
28
  /**
29
+ * Checks cron setup, validates schedules, and reschedules events if necessary.
30
  *
31
  * @attaches-to `init` hook.
32
  *
62
  *
63
  * @since 151220 Fixing bug with Auto-Cache Engine cron disappearing in some scenarios
64
  *
65
+ * @note This MUST happen upon uninstall and deactivation due to buggy WP_Cron behavior.
66
+ * Events with a custom schedule will disappear when plugin is not active (see http://bit.ly/1lGdr78).
67
  */
68
  public function resetCronSetup()
69
  {
src/includes/traits/Plugin/HtaccessUtils.php CHANGED
@@ -15,15 +15,20 @@ trait HtaccessUtils
15
  public $htaccess_marker = 'WmVuQ2FjaGU';
16
 
17
  /**
18
- * Plugin options that have associated htaccess rules.
19
  *
20
  * @since 160103 Improving `.htaccess` tweaks.
21
  *
22
- * @return array Plugin options that have associated htaccess rules
23
  *
24
- * @note We keep track of this to avoid the issue described here: http://git.io/vEFIH
25
  */
26
- public $options_with_htaccess_rules = ['cdn_enable', 'htaccess_browser_caching_enable', 'htaccess_gzip_enable', 'htaccess_enforce_canonical_urls',];
 
 
 
 
 
27
 
28
  /**
29
  * Add template blocks to `/.htaccess` file.
@@ -32,14 +37,13 @@ trait HtaccessUtils
32
  *
33
  * @return bool True if added successfully.
34
  *
35
- * @TODO Improve error reporting detail to better catch unexpected failures; see http://git.io/vEFLT
 
36
  */
37
  public function addWpHtaccess()
38
  {
39
- global $is_apache; // WP global for web server checks below.
40
-
41
- if (!$is_apache) {
42
- return false; // Not running the Apache web server.
43
  }
44
  if (!$this->options['enable']) {
45
  return true; // Nothing to do.
@@ -54,16 +58,23 @@ trait HtaccessUtils
54
  return false; // Unable to remove.
55
  }
56
  if (!($htaccess = $this->readHtaccessFile())) {
57
- return false; // Failure; could not read file or invalid UTF8 encountered, file may be corrupt.
58
  }
59
-
60
  $template_blocks = ''; // Initialize.
61
 
62
- foreach (array('gzip-enable.txt', 'access-control-allow-origin-enable.txt', 'browser-caching-enable.txt', 'canonical-urls-ts-enable.txt', 'canonical-urls-no-ts-enable.txt') as $_template) {
 
 
 
 
 
 
 
 
63
  if (!is_file($_template_file = dirname(dirname(dirname(__FILE__))).'/templates/htaccess/'.$_template)) {
64
  continue; // Template file missing; bypass.
65
- } // ↑ Some files might be missing in the lite version.
66
- elseif (!($_template_file_contents = trim(file_get_contents($_template_file)))) {
67
  continue; // Template file empty; bypass.
68
  } // ↑ Some files might be empty in the lite version.
69
 
@@ -73,16 +84,15 @@ trait HtaccessUtils
73
  $template_blocks .= $_template_file_contents."\n\n";
74
  } // ↑ Only if GZIP is enabled at this time.
75
  break;
 
76
 
77
  }
78
- }
79
- unset($_template_file); // Housekeeping
80
 
81
  if (empty($template_blocks)) { // Do we need to add anything to htaccess?
82
  $this->closeHtaccessFile($htaccess); // No need to write to htaccess file in this case.
83
  return true; // Nothing to do, but no failures either.
84
  }
85
-
86
  $template_blocks = $this->fillReplacementCodes($template_blocks);
87
  $template_header = '# BEGIN '.NAME.' '.$this->htaccess_marker.' (the '.$this->htaccess_marker.' marker is required for '.NAME.'; do not remove)';
88
  $template_footer = '# END '.NAME.' '.$this->htaccess_marker;
@@ -91,7 +101,6 @@ trait HtaccessUtils
91
  if (!$this->writeHtaccessFile($htaccess, true)) {
92
  return false; // Failure; could not write changes.
93
  }
94
-
95
  return true; // Added successfully.
96
  }
97
 
@@ -102,32 +111,29 @@ trait HtaccessUtils
102
  *
103
  * @return bool True if removed successfully.
104
  *
105
- * @TODO Improve error reporting detail to better catch unexpected failures; see http://git.io/vEFLT
 
106
  */
107
  public function removeWpHtaccess()
108
  {
109
- global $is_apache;
110
-
111
- if (!$is_apache) {
112
- return false; // Not running the Apache web server.
113
  }
114
  if (!($htaccess_file = $this->findHtaccessFile())) {
115
  return true; // File does not exist.
116
  }
117
  if (!$this->findHtaccessMarker()) {
118
- return true; // Template blocks are already gone.
119
  }
120
  if (!($htaccess = $this->readHtaccessFile())) {
121
- return false; // Failure; could not read file, create file, or invalid UTF8 encountered, file may be corrupt.
122
  }
123
-
124
  $regex = '/#\s*BEGIN\s+'.preg_quote(NAME, '/').'\s+'.$this->htaccess_marker.'.*?#\s*END\s+'.preg_quote(NAME, '/').'\s+'.$this->htaccess_marker.'\s*/uis';
125
  $htaccess['file_contents'] = preg_replace($regex, '', $htaccess['file_contents']);
126
 
127
  if (!$this->writeHtaccessFile($htaccess, false)) {
128
- return false; // Failure; could not write changes.
129
  }
130
-
131
  return true; // Removed successfully.
132
  }
133
 
@@ -136,8 +142,7 @@ trait HtaccessUtils
136
  *
137
  * @since 151114 Adding `.htaccess` tweaks.
138
  *
139
- * @return string Absolute server path to `/.htaccess` file;
140
- * else an empty string if unable to locate the file.
141
  */
142
  public function findHtaccessFile()
143
  {
@@ -155,29 +160,30 @@ trait HtaccessUtils
155
  *
156
  * @since 160103 Improving `.htaccess` tweaks.
157
  *
158
- * @return bool True when an option is enabled that requires htaccess rules, false otherwise.
159
  */
160
  public function needHtaccessRules()
161
  {
162
  if (!is_array($this->options_with_htaccess_rules)) {
163
- return false; // Nothing to do.
164
  }
165
- foreach ($this->options_with_htaccess_rules as $option) {
166
- if ($this->options[$option]) {
167
- return true; // Yes, there are options enabled that require htaccess rules.
168
  }
169
- }
170
- return false; // No, there are no options enabled that require htaccess rules.
 
171
  }
172
 
173
  /**
174
- * Utility method used to check if htaccess file contains $htaccess_marker.
175
  *
176
  * @since 151114 Adding `.htaccess` tweaks.
177
  *
178
  * @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
179
  *
180
- * @return bool False on failure or when marker does not exist in htaccess, true otherwise.
181
  */
182
  public function findHtaccessMarker($htaccess_marker = '')
183
  {
@@ -194,14 +200,13 @@ trait HtaccessUtils
194
  $htaccess_marker = $this->htaccess_marker;
195
  }
196
  if (mb_stripos($htaccess_file_contents, $htaccess_marker) === false) {
197
- return false; // Htaccess marker is missing
198
  }
199
-
200
- return true; // Htaccess has the marker
201
  }
202
 
203
  /**
204
- * Utility method used to update replacement codes in .htaccess templates
205
  *
206
  * @since 160706 Adding Apache Optimizations
207
  *
@@ -212,16 +217,16 @@ trait HtaccessUtils
212
  public function fillReplacementCodes($template_blocks)
213
  {
214
  if (mb_stripos($template_blocks, '%%') === false) {
215
- return $template_blocks; // No replacement codes to fill
216
  }
217
-
218
- $home_url = is_multisite() ? network_home_url() : home_url();
219
- $replacement_codes = ['%%REWRITE_BASE%%' => trailingslashit(parse_url($home_url, PHP_URL_PATH))];
220
-
 
221
  foreach ($replacement_codes as $_code => $_replacement) {
222
  $template_blocks = preg_replace('/'.preg_quote($_code, '/').'/ui', $_replacement, $template_blocks);
223
- }
224
- unset($_code, $_replacement);
225
 
226
  return $template_blocks;
227
  }
@@ -257,7 +262,7 @@ trait HtaccessUtils
257
  if (($file_contents = fread($fp, filesize($htaccess_file))) && ($file_contents === wp_check_invalid_utf8($file_contents))) {
258
  rewind($fp); // Rewind pointer to beginning of file.
259
  return compact('fp', 'file_contents');
260
- } else { // Failure; could not read file or invalid UTF8 encountered, file may be corrupt.
261
  flock($fp, LOCK_UN);
262
  fclose($fp);
263
  return false;
@@ -273,7 +278,7 @@ trait HtaccessUtils
273
  * @param bool $require_marker Whether or not to require the marker be present in contents before writing.
274
  * @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
275
  *
276
- * @return bool True on success, false on failure.
277
  */
278
  public function writeHtaccessFile(array $htaccess, $require_marker = true, $htaccess_marker = '')
279
  {
@@ -291,7 +296,7 @@ trait HtaccessUtils
291
  if (($require_marker && $_have_marker === false) || !rewind($htaccess['fp']) || !ftruncate($htaccess['fp'], 0) || !fwrite($htaccess['fp'], $htaccess['file_contents'])) {
292
  flock($htaccess['fp'], LOCK_UN);
293
  fclose($htaccess['fp']);
294
- return false; // Failure; could not write changes.
295
  }
296
  fflush($htaccess['fp']);
297
  flock($htaccess['fp'], LOCK_UN);
@@ -305,14 +310,14 @@ trait HtaccessUtils
305
  *
306
  * @since 151114 Adding `.htaccess` tweaks.
307
  *
308
- * @param array $htaccess Array containing at least an `fp` file resource pointing to htaccess file.
309
  *
310
- * @return bool False on failure, true otherwise.
311
  */
312
  public function closeHtaccessFile(array $htaccess)
313
  {
314
  if (!is_resource($htaccess['fp'])) {
315
- return false; // Failure; requires a valid file resource.
316
  }
317
  flock($htaccess['fp'], LOCK_UN);
318
  fclose($htaccess['fp']);
15
  public $htaccess_marker = 'WmVuQ2FjaGU';
16
 
17
  /**
18
+ * Plugin options that have htaccess rules.
19
  *
20
  * @since 160103 Improving `.htaccess` tweaks.
21
  *
22
+ * @return array Plugin options that have htaccess rules.
23
  *
24
+ * @note This avoids: <http://git.io/vEFIH>
25
  */
26
+ public $options_with_htaccess_rules = [
27
+ 'cdn_enable',
28
+ 'htaccess_browser_caching_enable',
29
+ 'htaccess_gzip_enable',
30
+ 'htaccess_enforce_canonical_urls',
31
+ ];
32
 
33
  /**
34
  * Add template blocks to `/.htaccess` file.
37
  *
38
  * @return bool True if added successfully.
39
  *
40
+ * @TODO Improve error reporting detail to better
41
+ * catch unexpected failures. See: <http://git.io/vEFLT>
42
  */
43
  public function addWpHtaccess()
44
  {
45
+ if (!$this->isApache()) {
46
+ return false; // Not Apache.
 
 
47
  }
48
  if (!$this->options['enable']) {
49
  return true; // Nothing to do.
58
  return false; // Unable to remove.
59
  }
60
  if (!($htaccess = $this->readHtaccessFile())) {
61
+ return false; // Failure; could not read file.
62
  }
 
63
  $template_blocks = ''; // Initialize.
64
 
65
+ foreach ([
66
+ 'gzip-enable.txt',
67
+ 'access-control-allow-origin-enable.txt',
68
+ 'browser-caching-enable.txt',
69
+ 'enforce-exact-host-name.txt',
70
+ 'canonical-urls-ts-enable.txt',
71
+ 'canonical-urls-no-ts-enable.txt',
72
+ ] as $_template) {
73
+ //
74
  if (!is_file($_template_file = dirname(dirname(dirname(__FILE__))).'/templates/htaccess/'.$_template)) {
75
  continue; // Template file missing; bypass.
76
+ // ↑ Some files might be missing in the lite version.
77
+ } elseif (!($_template_file_contents = trim(file_get_contents($_template_file)))) {
78
  continue; // Template file empty; bypass.
79
  } // ↑ Some files might be empty in the lite version.
80
 
84
  $template_blocks .= $_template_file_contents."\n\n";
85
  } // ↑ Only if GZIP is enabled at this time.
86
  break;
87
+
88
 
89
  }
90
+ } // unset($_template_file); // Housekeeping.
 
91
 
92
  if (empty($template_blocks)) { // Do we need to add anything to htaccess?
93
  $this->closeHtaccessFile($htaccess); // No need to write to htaccess file in this case.
94
  return true; // Nothing to do, but no failures either.
95
  }
 
96
  $template_blocks = $this->fillReplacementCodes($template_blocks);
97
  $template_header = '# BEGIN '.NAME.' '.$this->htaccess_marker.' (the '.$this->htaccess_marker.' marker is required for '.NAME.'; do not remove)';
98
  $template_footer = '# END '.NAME.' '.$this->htaccess_marker;
101
  if (!$this->writeHtaccessFile($htaccess, true)) {
102
  return false; // Failure; could not write changes.
103
  }
 
104
  return true; // Added successfully.
105
  }
106
 
111
  *
112
  * @return bool True if removed successfully.
113
  *
114
+ * @TODO Improve error reporting detail to better
115
+ * catch unexpected failures. See: <http://git.io/vEFLT>
116
  */
117
  public function removeWpHtaccess()
118
  {
119
+ if (!$this->isApache()) {
120
+ return false; // Not running Apache.
 
 
121
  }
122
  if (!($htaccess_file = $this->findHtaccessFile())) {
123
  return true; // File does not exist.
124
  }
125
  if (!$this->findHtaccessMarker()) {
126
+ return true; // Template blocks are gone.
127
  }
128
  if (!($htaccess = $this->readHtaccessFile())) {
129
+ return false; // Failure; could not read file.
130
  }
 
131
  $regex = '/#\s*BEGIN\s+'.preg_quote(NAME, '/').'\s+'.$this->htaccess_marker.'.*?#\s*END\s+'.preg_quote(NAME, '/').'\s+'.$this->htaccess_marker.'\s*/uis';
132
  $htaccess['file_contents'] = preg_replace($regex, '', $htaccess['file_contents']);
133
 
134
  if (!$this->writeHtaccessFile($htaccess, false)) {
135
+ return false; // Failure; could not write.
136
  }
 
137
  return true; // Removed successfully.
138
  }
139
 
142
  *
143
  * @since 151114 Adding `.htaccess` tweaks.
144
  *
145
+ * @return string Absolute server path to `/.htaccess` file.
 
146
  */
147
  public function findHtaccessFile()
148
  {
160
  *
161
  * @since 160103 Improving `.htaccess` tweaks.
162
  *
163
+ * @return bool True when an option is enabled that requires htaccess rules.
164
  */
165
  public function needHtaccessRules()
166
  {
167
  if (!is_array($this->options_with_htaccess_rules)) {
168
+ return false; // Not even possible.
169
  }
170
+ foreach ($this->options_with_htaccess_rules as $_option) {
171
+ if ($this->options[$_option]) {
172
+ return true; // Yes.
173
  }
174
+ } // unset($_option); // Housekeeping.
175
+
176
+ return false;
177
  }
178
 
179
  /**
180
+ * Utility method used to check if htaccess file contains `$htaccess_marker`.
181
  *
182
  * @since 151114 Adding `.htaccess` tweaks.
183
  *
184
  * @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
185
  *
186
+ * @return bool False on failure or when marker does not exist in htaccess.
187
  */
188
  public function findHtaccessMarker($htaccess_marker = '')
189
  {
200
  $htaccess_marker = $this->htaccess_marker;
201
  }
202
  if (mb_stripos($htaccess_file_contents, $htaccess_marker) === false) {
203
+ return false; // Htaccess marker is missing.
204
  }
205
+ return true; // Htaccess has the marker.
 
206
  }
207
 
208
  /**
209
+ * Utility method used to update replacement codes in .htaccess templates.
210
  *
211
  * @since 160706 Adding Apache Optimizations
212
  *
217
  public function fillReplacementCodes($template_blocks)
218
  {
219
  if (mb_stripos($template_blocks, '%%') === false) {
220
+ return $template_blocks; // No replacement codes to fill.
221
  }
222
+ $replacement_codes = [
223
+ '%%REWRITE_BASE%%' => trailingslashit(parse_url(network_home_url(), PHP_URL_PATH)),
224
+ '%%HOST_NAME_AS_REGEX_FRAG%%' => mb_strtolower(parse_url(network_home_url(), PHP_URL_HOST)),
225
+ '%%REST_REQUEST_PREFIX_AS_REGEX_FRAG%%' => rest_get_url_prefix(),
226
+ ];
227
  foreach ($replacement_codes as $_code => $_replacement) {
228
  $template_blocks = preg_replace('/'.preg_quote($_code, '/').'/ui', $_replacement, $template_blocks);
229
+ } // unset($_code, $_replacement);
 
230
 
231
  return $template_blocks;
232
  }
262
  if (($file_contents = fread($fp, filesize($htaccess_file))) && ($file_contents === wp_check_invalid_utf8($file_contents))) {
263
  rewind($fp); // Rewind pointer to beginning of file.
264
  return compact('fp', 'file_contents');
265
+ } else { // Failure; could not read file.
266
  flock($fp, LOCK_UN);
267
  fclose($fp);
268
  return false;
278
  * @param bool $require_marker Whether or not to require the marker be present in contents before writing.
279
  * @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
280
  *
281
+ * @return bool True on success.
282
  */
283
  public function writeHtaccessFile(array $htaccess, $require_marker = true, $htaccess_marker = '')
284
  {
296
  if (($require_marker && $_have_marker === false) || !rewind($htaccess['fp']) || !ftruncate($htaccess['fp'], 0) || !fwrite($htaccess['fp'], $htaccess['file_contents'])) {
297
  flock($htaccess['fp'], LOCK_UN);
298
  fclose($htaccess['fp']);
299
+ return false; // Failure.
300
  }
301
  fflush($htaccess['fp']);
302
  flock($htaccess['fp'], LOCK_UN);
310
  *
311
  * @since 151114 Adding `.htaccess` tweaks.
312
  *
313
+ * @param array $htaccess Array containing at least an `fp` file resource.
314
  *
315
+ * @return bool False on failure.
316
  */
317
  public function closeHtaccessFile(array $htaccess)
318
  {
319
  if (!is_resource($htaccess['fp'])) {
320
+ return false; // Failure.
321
  }
322
  flock($htaccess['fp'], LOCK_UN);
323
  fclose($htaccess['fp']);
src/includes/traits/Plugin/InstallUtils.php CHANGED
@@ -40,11 +40,12 @@ trait InstallUtils
40
  }
41
 
42
  /**
43
- * Check current plugin version that is installed in WP.
44
  *
45
  * @since 150422 Rewrite.
 
46
  *
47
- * @attaches-to `admin_init` hook.
48
  */
49
  public function checkVersion()
50
  {
@@ -74,8 +75,9 @@ trait InstallUtils
74
  }
75
  $this->wipeCache(); // Fresh start now.
76
 
77
- $this->enqueueMainNotice(sprintf(__('<strong>%1$s:</strong> detected a new version of itself. Recompiling w/ latest version... wiping the cache... all done :-)', 'comet-cache'), esc_html(NAME)), ['push_to_top' => true]);
78
-
 
79
  $this->dismissMainNotice('pro_update_error');
80
  $this->dismissMainNotice('new-lite-version-available');
81
  $this->dismissMainNotice('new-pro-version-available');
@@ -292,6 +294,8 @@ trait InstallUtils
292
 
293
 
294
 
 
 
295
  ]
296
  );
297
  if ($this->applyWpFilters(GLOBAL_NS.'_exclude_uris_client_side_too', true)) {
40
  }
41
 
42
  /**
43
+ * Check current version.
44
  *
45
  * @since 150422 Rewrite.
46
+ * @since 161226 Moved to `init` hook.
47
  *
48
+ * @attaches-to `init` hook.
49
  */
50
  public function checkVersion()
51
  {
75
  }
76
  $this->wipeCache(); // Fresh start now.
77
 
78
+ if (is_admin()) { // Only if in an admin area.
79
+ $this->enqueueMainNotice(sprintf(__('<strong>%1$s:</strong> detected a new version of itself. Recompiling w/ latest version... wiping the cache... all done :-)', 'comet-cache'), esc_html(NAME)), ['push_to_top' => true]);
80
+ }
81
  $this->dismissMainNotice('pro_update_error');
82
  $this->dismissMainNotice('new-lite-version-available');
83
  $this->dismissMainNotice('new-pro-version-available');
294
 
295
 
296
 
297
+
298
+ 'ac_file_version' => VERSION, // Version when AC file was built.
299
  ]
300
  );
301
  if ($this->applyWpFilters(GLOBAL_NS.'_exclude_uris_client_side_too', true)) {
src/includes/traits/Plugin/OptionUtils.php CHANGED
@@ -5,6 +5,20 @@ use WebSharks\CometCache\Classes;
5
 
6
  trait OptionUtils
7
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  /**
9
  * Get plugin options.
10
  *
@@ -15,29 +29,26 @@ trait OptionUtils
15
  *
16
  * @return array Plugin options.
17
  *
18
- * @note $intersect should be `false` when this method is called via a VS upgrade routine or during inital startup on when upgrading. See https://git.io/viGIK
 
19
  */
20
  public function getOptions($intersect = true, $refresh = false)
21
  {
22
- if (!($options = $this->options) || $refresh) { // If not defined yet, or if we're forcing a refresh via get_site_option()
23
  if (!is_array($options = get_site_option(GLOBAL_NS.'_options'))) {
24
- $options = []; // Force array.
25
  }
26
  if (!$options && is_array($zencache_options = get_site_option('zencache_options'))) {
27
- $options = $zencache_options; // Old ZenCache options.
28
- $options['crons_setup'] = $this->default_options['crons_setup'];
29
- $options['latest_lite_version'] = $this->default_options['latest_lite_version'];
30
- $options['latest_pro_version'] = $this->default_options['latest_pro_version'];
31
  }
32
- }
 
33
  $this->options = array_merge($this->default_options, $options);
34
  $this->options = $this->applyWpFilters(GLOBAL_NS.'_options', $this->options);
35
  $this->options = $intersect ? array_intersect_key($this->options, $this->default_options) : $this->options;
36
-
37
- foreach ($this->options as $_key => &$_value) {
38
- $_value = trim((string) $_value); // Force strings.
39
- }
40
- unset($_key, $_value); // Housekeeping.
41
 
42
  $this->options['base_dir'] = trim($this->options['base_dir'], '\\/'." \t\n\r\0\x0B");
43
  if (!$this->options['base_dir'] || mb_strpos(basename($this->options['base_dir']), 'wp-') === 0) {
@@ -71,22 +82,10 @@ trait OptionUtils
71
  }
72
  $this->options = array_merge($this->default_options, $this->options, $options);
73
  $this->options = $intersect ? array_intersect_key($this->options, $this->default_options) : $this->options;
 
 
74
  update_site_option(GLOBAL_NS.'_options', $this->options);
75
 
76
  return $this->getOptions($intersect);
77
  }
78
-
79
- /**
80
- * Restore default plugin options.
81
- *
82
- * @since 151002 Improving multisite compat.
83
- *
84
- * @return array Plugin options after update.
85
- */
86
- public function restoreDefaultOptions()
87
- {
88
- delete_site_option(GLOBAL_NS.'_options'); // Force restore.
89
- $this->options = $this->default_options; // In real-time.
90
- return $this->getOptions();
91
- }
92
  }
5
 
6
  trait OptionUtils
7
  {
8
+ /**
9
+ * Restore default plugin options.
10
+ *
11
+ * @since 151002 Improving multisite compat.
12
+ *
13
+ * @return array Plugin options after update.
14
+ */
15
+ public function restoreDefaultOptions()
16
+ {
17
+ delete_site_option(GLOBAL_NS.'_options');
18
+ $this->options = $this->default_options;
19
+ return $this->getOptions();
20
+ }
21
+
22
  /**
23
  * Get plugin options.
24
  *
29
  *
30
  * @return array Plugin options.
31
  *
32
+ * @note The `$intersect` param should be `false` when this method is called by a VS upgrade routine.
33
+ * Also `false` during inital startup or when upgrading. See: <https://git.io/viGIK>
34
  */
35
  public function getOptions($intersect = true, $refresh = false)
36
  {
37
+ if (!($options = $this->options) || $refresh) {
38
  if (!is_array($options = get_site_option(GLOBAL_NS.'_options'))) {
39
+ $options = []; // Force an array of options.
40
  }
41
  if (!$options && is_array($zencache_options = get_site_option('zencache_options'))) {
42
+ $options = $zencache_options;
43
+ $options['crons_setup'] = $this->default_options['crons_setup'];
44
+ $options['latest_pro_version'] = $this->default_options['latest_pro_version'];
 
45
  }
46
+ } // End the collection of all plugin options.
47
+
48
  $this->options = array_merge($this->default_options, $options);
49
  $this->options = $this->applyWpFilters(GLOBAL_NS.'_options', $this->options);
50
  $this->options = $intersect ? array_intersect_key($this->options, $this->default_options) : $this->options;
51
+ $this->options = array_map('trim', array_map('strval', $this->options));
 
 
 
 
52
 
53
  $this->options['base_dir'] = trim($this->options['base_dir'], '\\/'." \t\n\r\0\x0B");
54
  if (!$this->options['base_dir'] || mb_strpos(basename($this->options['base_dir']), 'wp-') === 0) {
82
  }
83
  $this->options = array_merge($this->default_options, $this->options, $options);
84
  $this->options = $intersect ? array_intersect_key($this->options, $this->default_options) : $this->options;
85
+ $this->options = array_map('trim', array_map('strval', $this->options));
86
+
87
  update_site_option(GLOBAL_NS.'_options', $this->options);
88
 
89
  return $this->getOptions($intersect);
90
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  }
src/includes/traits/Plugin/UpdateUtils.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
- namespace WebSharks\CometCache\Traits\Plugin;
3
-
4
- use WebSharks\CometCache\Classes;
5
-
6
- trait UpdateUtils
7
- {
8
- /**
9
- * Checks for a new lite release.
10
- *
11
- * @since 151220 Show version number in plugin options.
12
- * @since 160917 Don't check current user.
13
- *
14
- * @attaches-to `admin_init` hook.
15
- */
16
- public function maybeCheckLatestLiteVersion()
17
- {
18
- if (IS_PRO) {
19
- return; // Not applicable.
20
- } elseif (!$this->options['lite_update_check']) {
21
- return; // Nothing to do.
22
- } elseif ($this->options['last_lite_update_check'] >= strtotime('-1 hour')) {
23
- if (empty($_REQUEST['force-check'])) {
24
- return; // Nothing to do.
25
- }
26
- }
27
- $this->updateOptions(['last_lite_update_check' => time()]);
28
-
29
- $product_api_url = 'https://'.urlencode(DOMAIN).'/';
30
- $product_api_input_vars = ['product_api' => ['action' => 'latest_lite_version']];
31
-
32
- $product_api_response = wp_remote_post($product_api_url, ['body' => $product_api_input_vars]);
33
- $product_api_response = json_decode(wp_remote_retrieve_body($product_api_response));
34
-
35
- if (is_object($product_api_response) && !empty($product_api_response->lite_version)) {
36
- $this->updateOptions(['latest_lite_version' => $product_api_response->lite_version]);
37
- }
38
- }
39
-
40
-
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/includes/traits/Plugin/WcpDateArchiveUtils.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace WebSharks\CometCache\Traits\Plugin;
3
+
4
+ use WebSharks\CometCache\Classes;
5
+
6
+ trait WcpDateArchiveUtils
7
+ {
8
+ /**
9
+ * Automatically clears date archives.
10
+ *
11
+ * @since 170220 Date archive clearing.
12
+ *
13
+ * @param int $post_id A WordPress post ID.
14
+ * @param bool $force Defaults to a `FALSE` value.
15
+ * Pass as TRUE if clearing should be done for `draft`, `pending`,
16
+ * `future`, or `trash` post statuses.
17
+ *
18
+ * @throws \Exception If a clear failure occurs.
19
+ *
20
+ * @return int Total files cleared by this routine (if any).
21
+ *
22
+ * @note This is only called upon by other routines which listen for
23
+ * events that are indirectly associated with a post ID.
24
+ */
25
+ public function autoClearDateArchiveCache($post_id, $force = false)
26
+ {
27
+ $counter = 0; // Initialize.
28
+ $enqueued_notices = 0; // Initialize.
29
+
30
+ if (!($post_id = (int) $post_id)) {
31
+ return $counter; // Nothing to do.
32
+ }
33
+ if (!is_null($done = &$this->cacheKey('autoClearDateArchiveCache', [$post_id, $force]))) {
34
+ return $counter; // Already did this.
35
+ }
36
+ $done = true; // Flag as having been done.
37
+
38
+ if (!$this->options['enable']) {
39
+ return $counter; // Nothing to do.
40
+ }
41
+ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
42
+ return $counter; // Nothing to do.
43
+ }
44
+ if (!$this->options['cache_clear_date_archives_enable']) {
45
+ return $counter; // Nothing to do.
46
+ }
47
+ if (!is_dir($cache_dir = $this->cacheDir())) {
48
+ return $counter; // Nothing to do.
49
+ }
50
+ $post_status = get_post_status($post_id); // Cache this.
51
+
52
+ if ($post_status === 'draft' && isset($GLOBALS['pagenow'], $_POST['publish'])
53
+ && is_admin() && $GLOBALS['pagenow'] === 'post.php' && current_user_can('publish_posts')
54
+ && mb_strpos(wp_get_referer(), '/post-new.php') !== false
55
+ ) {
56
+ $post_status = 'publish'; // A new post being published now.
57
+ }
58
+ if (in_array($post_status, ['inherit', 'auto-draft'], true)) {
59
+ return $counter; // Nothing to do. Note: `inherit` = revision.
60
+ }
61
+ if (in_array($post_status, ['draft', 'pending', 'future'], true) && !$force) {
62
+ return $counter; // Nothing to do; i.e., NOT forcing in this case.
63
+ }
64
+ $date_archive_urls = []; // Initialize archive urls.
65
+ $publish_time = get_post_time('U', true, $post_id);
66
+
67
+ $Y = date('Y', $publish_time);
68
+ $m = date('m', $publish_time);
69
+ $j = date('j', $publish_time);
70
+
71
+ if ($this->options['cache_clear_date_archives_enable'] === '1') {
72
+ $date_archive_urls[sprintf(__('%1$s Date Archive', 'comet-cache'), $Y)] = get_year_link($Y);
73
+ $date_archive_urls[sprintf(__('%1$s/%2$s Date Archive', 'comet-cache'), $Y, $m)] = get_month_link($Y, $m);
74
+ $date_archive_urls[sprintf(__('%1$s/%2$s/%3$s Date Archive', 'comet-cache'), $Y, $m, $j)] = get_day_link($Y, $m, $j);
75
+ } elseif ($this->options['cache_clear_date_archives_enable'] === '2') {
76
+ $date_archive_urls[sprintf(__('%1$s/%2$s Date Archive', 'comet-cache'), $Y, $m)] = get_month_link($Y, $m);
77
+ $date_archive_urls[sprintf(__('%1$s/%2$s/%3$s Date Archive', 'comet-cache'), $Y, $m, $j)] = get_day_link($Y, $m, $j);
78
+ } else { // Assume $this->options['cache_clear_date_archives_enable'] === '3'
79
+ $date_archive_urls[sprintf(__('%1$s/%2$s/%3$s Date Archive', 'comet-cache'), $Y, $m, $j)] = get_day_link($Y, $m, $j);
80
+ }
81
+ foreach ($date_archive_urls as $_label => $_url) {
82
+ $_url_regex = $this->buildHostCachePathRegex($_url);
83
+ $_url_counter = $this->clearFilesFromHostCacheDir($_url_regex);
84
+ $counter += $_url_counter; // Add to overall counter.
85
+
86
+ if ($_url_counter && $enqueued_notices < 100 && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
87
+ $this->enqueueNotice(sprintf(__('Found %1$s in the cache for %2$s; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($_url_counter)), esc_html($_label)), ['combinable' => true]);
88
+ ++$enqueued_notices; // Increment enqueued notices counter.
89
+ }
90
+ } // unset($_label, $_url, $_url_regex, $_url_counter); // Housekeeping.
91
+
92
+ return $counter;
93
+ }
94
+ }
src/includes/traits/Plugin/WcpPostUtils.php CHANGED
@@ -100,6 +100,7 @@ trait WcpPostUtils
100
  $counter += $this->autoClearHomePageCache();
101
  $counter += $this->autoClearPostsPageCache();
102
  $counter += $this->autoClearPostTermsCache($post_id, $force);
 
103
  $counter += $this->autoClearCustomPostTypeArchiveCache($post_id);
104
 
105
 
100
  $counter += $this->autoClearHomePageCache();
101
  $counter += $this->autoClearPostsPageCache();
102
  $counter += $this->autoClearPostTermsCache($post_id, $force);
103
+ $counter += $this->autoClearDateArchiveCache($post_id, $force);
104
  $counter += $this->autoClearCustomPostTypeArchiveCache($post_id);
105
 
106
 
src/includes/traits/Shared/CacheDirUtils.php CHANGED
@@ -272,14 +272,19 @@ trait CacheDirUtils
272
  // On a standard installation delete from all hosts.
273
  // See: <https://github.com/websharks/comet-cache/issues/608>
274
  if (!is_multisite() && !$___considering_domain_mapping) {
275
- $regex = ltrim($regex, '^\\/');
276
-
277
- if (mb_strpos($regex, '(?:\/') === 0 || mb_strpos($regex, '(\/') === 0) {
278
- $regex = '/^https?\/[^\/]+'.$regex;
279
- } else {
280
- $regex = '/^https?\/[^\/]+\/'.$regex;
 
 
 
 
 
 
281
  }
282
- return $this->deleteFilesFromCacheDir($regex, $check_max_age);
283
  }
284
  $cache_dir = $this->nDirSeps($cache_dir); // Normalize.
285
  $host_token = $current_host_token = $this->hostToken();
272
  // On a standard installation delete from all hosts.
273
  // See: <https://github.com/websharks/comet-cache/issues/608>
274
  if (!is_multisite() && !$___considering_domain_mapping) {
275
+ if (in_array(rtrim(str_replace(['^', '$'], '', $regex), 'ui'), ['/.*/', '/.+/'], true)) {
276
+ return $this->deleteFilesFromCacheDir($regex, $check_max_age);
277
+ //
278
+ } else { // Clearing specifics.
279
+ $regex = ltrim($regex, '^\\/');
280
+
281
+ if (mb_strpos($regex, '(?:\/') === 0 || mb_strpos($regex, '(\/') === 0) {
282
+ $regex = '/^https?\/[^\/]+'.$regex;
283
+ } else {
284
+ $regex = '/^https?\/[^\/]+\/'.$regex;
285
+ }
286
+ return $this->deleteFilesFromCacheDir($regex, $check_max_age);
287
  }
 
288
  }
289
  $cache_dir = $this->nDirSeps($cache_dir); // Normalize.
290
  $host_token = $current_host_token = $this->hostToken();
src/includes/traits/Shared/ServerUtils.php CHANGED
@@ -14,16 +14,19 @@ trait ServerUtils
14
  */
15
  public function isApache()
16
  {
17
- if (!is_null($is = &$this->staticKey('isApache'))) {
18
  return $is; // Already cached this.
19
  }
20
  if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
21
  if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false) {
22
  return $is = true;
23
- }
24
- if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'litespeed') !== false) {
25
  return $is = true;
26
  }
 
 
 
 
27
  }
28
  return $is = false;
29
  }
@@ -37,13 +40,17 @@ trait ServerUtils
37
  */
38
  public function isNginx()
39
  {
40
- if (!is_null($is = &$this->staticKey('isNginx'))) {
41
  return $is; // Already cached this.
42
  }
43
  if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
44
  if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false) {
45
  return $is = true;
46
  }
 
 
 
 
47
  }
48
  return $is = false;
49
  }
@@ -57,17 +64,17 @@ trait ServerUtils
57
  */
58
  public function isIis()
59
  {
60
- if (!is_null($is = &$this->staticKey('isIis'))) {
61
  return $is; // Already cached this.
62
  }
63
  if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
64
  if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'microsoft-iis') !== false) {
65
  return $is = true;
66
- }
67
- if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'expressiondevserver') !== false) {
68
  return $is = true;
69
  }
70
- }
 
71
  return $is = false;
72
  }
73
  }
14
  */
15
  public function isApache()
16
  {
17
+ if (!is_null($is = &$this->staticKey(__FUNCTION__))) {
18
  return $is; // Already cached this.
19
  }
20
  if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
21
  if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false) {
22
  return $is = true;
23
+ } elseif (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'litespeed') !== false) {
 
24
  return $is = true;
25
  }
26
+ } // Checking `SERVER_SOFTWARE` is faster.
27
+
28
+ if ($this->functionIsPossible('apache_get_version')) {
29
+ return $is = true;
30
  }
31
  return $is = false;
32
  }
40
  */
41
  public function isNginx()
42
  {
43
+ if (!is_null($is = &$this->staticKey(__FUNCTION__))) {
44
  return $is; // Already cached this.
45
  }
46
  if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
47
  if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false) {
48
  return $is = true;
49
  }
50
+ } // Checking `SERVER_SOFTWARE` is faster.
51
+
52
+ if (!empty($_SERVER['WP_NGINX_CONFIG'])) {
53
+ return $is = true; // See: <http://jas.xyz/2jnfXOF>
54
  }
55
  return $is = false;
56
  }
64
  */
65
  public function isIis()
66
  {
67
+ if (!is_null($is = &$this->staticKey(__FUNCTION__))) {
68
  return $is; // Already cached this.
69
  }
70
  if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
71
  if (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'microsoft-iis') !== false) {
72
  return $is = true;
73
+ } elseif (mb_stripos($_SERVER['SERVER_SOFTWARE'], 'expressiondevserver') !== false) {
 
74
  return $is = true;
75
  }
76
+ } // Checking `SERVER_SOFTWARE` is faster.
77
+
78
  return $is = false;
79
  }
80
  }
src/includes/uninstall.php CHANGED
@@ -9,7 +9,7 @@ namespace WebSharks\CometCache;
9
  use WebSharks\CometCache\Classes;
10
 
11
  if (!defined('WPINC')) {
12
- exit('Do NOT access this file directly: '.basename(__FILE__));
13
  }
14
  require_once __DIR__.'/stub.php';
15
 
9
  use WebSharks\CometCache\Classes;
10
 
11
  if (!defined('WPINC')) {
12
+ exit('Do NOT access this file directly.');
13
  }
14
  require_once __DIR__.'/stub.php';
15
 
src/vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit958f5164d6bdff050048118f7698d0e4::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit4d8e53cc26ab733f873f9cb1326d3af2::getLoader();
src/vendor/composer/autoload_classmap.php CHANGED
@@ -42,11 +42,11 @@ return array(
42
  'WebSharks\\CometCache\\Traits\\Plugin\\NoticeUtils' => $baseDir . '/src/includes/traits/Plugin/NoticeUtils.php',
43
  'WebSharks\\CometCache\\Traits\\Plugin\\OptionUtils' => $baseDir . '/src/includes/traits/Plugin/OptionUtils.php',
44
  'WebSharks\\CometCache\\Traits\\Plugin\\PostUtils' => $baseDir . '/src/includes/traits/Plugin/PostUtils.php',
45
- 'WebSharks\\CometCache\\Traits\\Plugin\\UpdateUtils' => $baseDir . '/src/includes/traits/Plugin/UpdateUtils.php',
46
  'WebSharks\\CometCache\\Traits\\Plugin\\UrlUtils' => $baseDir . '/src/includes/traits/Plugin/UrlUtils.php',
47
  'WebSharks\\CometCache\\Traits\\Plugin\\UserUtils' => $baseDir . '/src/includes/traits/Plugin/UserUtils.php',
48
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpAuthorUtils' => $baseDir . '/src/includes/traits/Plugin/WcpAuthorUtils.php',
49
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpCommentUtils' => $baseDir . '/src/includes/traits/Plugin/WcpCommentUtils.php',
 
50
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpFeedUtils' => $baseDir . '/src/includes/traits/Plugin/WcpFeedUtils.php',
51
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpHomeBlogUtils' => $baseDir . '/src/includes/traits/Plugin/WcpHomeBlogUtils.php',
52
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpJetpackUtils' => $baseDir . '/src/includes/traits/Plugin/WcpJetpackUtils.php',
42
  'WebSharks\\CometCache\\Traits\\Plugin\\NoticeUtils' => $baseDir . '/src/includes/traits/Plugin/NoticeUtils.php',
43
  'WebSharks\\CometCache\\Traits\\Plugin\\OptionUtils' => $baseDir . '/src/includes/traits/Plugin/OptionUtils.php',
44
  'WebSharks\\CometCache\\Traits\\Plugin\\PostUtils' => $baseDir . '/src/includes/traits/Plugin/PostUtils.php',
 
45
  'WebSharks\\CometCache\\Traits\\Plugin\\UrlUtils' => $baseDir . '/src/includes/traits/Plugin/UrlUtils.php',
46
  'WebSharks\\CometCache\\Traits\\Plugin\\UserUtils' => $baseDir . '/src/includes/traits/Plugin/UserUtils.php',
47
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpAuthorUtils' => $baseDir . '/src/includes/traits/Plugin/WcpAuthorUtils.php',
48
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpCommentUtils' => $baseDir . '/src/includes/traits/Plugin/WcpCommentUtils.php',
49
+ 'WebSharks\\CometCache\\Traits\\Plugin\\WcpDateArchiveUtils' => $baseDir . '/src/includes/traits/Plugin/WcpDateArchiveUtils.php',
50
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpFeedUtils' => $baseDir . '/src/includes/traits/Plugin/WcpFeedUtils.php',
51
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpHomeBlogUtils' => $baseDir . '/src/includes/traits/Plugin/WcpHomeBlogUtils.php',
52
  'WebSharks\\CometCache\\Traits\\Plugin\\WcpJetpackUtils' => $baseDir . '/src/includes/traits/Plugin/WcpJetpackUtils.php',
src/vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit958f5164d6bdff050048118f7698d0e4
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit958f5164d6bdff050048118f7698d0e4
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit958f5164d6bdff050048118f7698d0e4', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit958f5164d6bdff050048118f7698d0e4', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit4d8e53cc26ab733f873f9cb1326d3af2
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit4d8e53cc26ab733f873f9cb1326d3af2', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit4d8e53cc26ab733f873f9cb1326d3af2', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
uninstall.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  if (!defined('WPINC')) {
3
- exit('Do NOT access this file directly: '.basename(__FILE__));
4
  }
5
  $GLOBALS['wp_php_rv'] = '5.4'; //php-required-version//
6
  if (require(__DIR__.'/src/vendor/websharks/wp-php-rv/src/includes/check.php')) {
1
  <?php
2
  if (!defined('WPINC')) {
3
+ exit('Do NOT access this file directly.');
4
  }
5
  $GLOBALS['wp_php_rv'] = '5.4'; //php-required-version//
6
  if (require(__DIR__.'/src/vendor/websharks/wp-php-rv/src/includes/check.php')) {