Version Description
= v160416 =
Requires WordPress v4.2+.
Download this release
Release Info
Developer | raamdev |
Plugin | Comet Cache |
Version | 160416 |
Comparing to | |
See all releases |
Code changes from version 160227 to 160416
- CHANGELOG.md +18 -0
- comet-cache.php +2 -2
- plugin.php +17 -11
- readme.txt +24 -64
- src/client-s/css/admin-bar.min.css +1 -1
- src/client-s/css/menu-pages.min.css +1 -1
- src/includes/api.php +4 -2
- src/includes/classes/AbsBase.php +10 -8
- src/includes/classes/AbsBaseAp.php +28 -12
- src/includes/classes/Actions.php +7 -7
- src/includes/classes/AdvCacheBackCompat.php +4 -4
- src/includes/classes/AdvancedCache.php +13 -11
- src/includes/classes/ApiBase.php +2 -1
- src/includes/classes/Conflicts.php +11 -9
- src/includes/classes/FeedUtils.php +15 -15
- src/includes/classes/MenuPage.php +4 -2
- src/includes/classes/MenuPageOptions.php +13 -13
- src/includes/classes/Plugin.php +93 -67
- src/includes/classes/VsUpgrades.php +6 -7
- src/includes/closures/Ac/AbortUtils.php +0 -11
- src/includes/closures/Ac/AcPluginUtils.php +0 -25
- src/includes/closures/Ac/BrowserUtils.php +0 -34
- src/includes/closures/Ac/NcDebugConsts.php +0 -293
- src/includes/closures/Ac/NcDebugUtils.php +0 -209
- src/includes/closures/Ac/ObUtils.php +0 -353
- src/includes/closures/Ac/PostloadUtils.php +0 -187
- src/includes/closures/Ac/ShutdownUtils.php +0 -18
- src/includes/closures/Plugin/ActionUtils.php +0 -16
- src/includes/closures/Plugin/BbPressUtils.php +0 -61
- src/includes/closures/Plugin/CleanupUtils.php +0 -19
- src/includes/closures/Plugin/CondUtils.php +0 -13
- src/includes/closures/Plugin/CronUtils.php +0 -80
- src/includes/closures/Plugin/DbUtils.php +0 -13
- src/includes/closures/Plugin/DirUtils.php +0 -79
- src/includes/closures/Plugin/HtaccessUtils.php +0 -273
- src/includes/closures/Plugin/InstallUtils.php +0 -535
- src/includes/closures/Plugin/MenuPageUtils.php +0 -219
- src/includes/closures/Plugin/NoticeUtils.php +0 -296
- src/includes/closures/Plugin/OptionUtils.php +0 -70
- src/includes/closures/Plugin/PostUtils.php +0 -42
- src/includes/closures/Plugin/UpdateUtils.php +0 -46
- src/includes/closures/Plugin/UrlUtils.php +0 -22
- src/includes/closures/Plugin/UserUtils.php +0 -118
- src/includes/closures/Plugin/WcpAuthorUtils.php +0 -92
- src/includes/closures/Plugin/WcpCommentUtils.php +0 -96
- src/includes/closures/Plugin/WcpFeedUtils.php +0 -116
- src/includes/closures/Plugin/WcpHomeBlogUtils.php +0 -101
- src/includes/closures/Plugin/WcpJetpackUtils.php +0 -24
- src/includes/closures/Plugin/WcpOpcacheUtils.php +0 -69
- src/includes/closures/Plugin/WcpPluginUtils.php +0 -22
- src/includes/closures/Plugin/WcpPostTypeUtils.php +0 -66
- src/includes/closures/Plugin/WcpPostUtils.php +0 -176
- src/includes/closures/Plugin/WcpSettingUtils.php +0 -31
- src/includes/closures/Plugin/WcpSitemapUtils.php +0 -47
- src/includes/closures/Plugin/WcpTermUtils.php +0 -139
- src/includes/closures/Plugin/WcpUpdaterUtils.php +0 -99
- src/includes/closures/Plugin/WcpUtils.php +0 -341
- src/includes/closures/Plugin/WcpWooCommerceUtils.php +0 -24
- src/includes/closures/Shared/BlogUtils.php +0 -31
- src/includes/closures/Shared/CacheDirUtils.php +0 -643
- src/includes/closures/Shared/CacheLockUtils.php +0 -80
- src/includes/closures/Shared/CachePathConsts.php +0 -140
- src/includes/closures/Shared/CachePathUtils.php +0 -351
- src/includes/closures/Shared/ConditionalUtils.php +0 -358
- src/includes/closures/Shared/DomainMappingUtils.php +0 -264
- src/includes/closures/Shared/EscapeUtils.php +0 -17
- src/includes/closures/Shared/FsUtils.php +0 -323
- src/includes/closures/Shared/HookUtils.php +0 -249
- src/includes/closures/Shared/HttpUtils.php +0 -166
- src/includes/closures/Shared/I18nUtils.php +0 -44
- src/includes/closures/Shared/IpAddrUtils.php +0 -83
- src/includes/closures/Shared/PatternUtils.php +0 -48
- src/includes/closures/Shared/ReplaceUtils.php +0 -43
- src/includes/closures/Shared/ServerUtils.php +0 -65
- src/includes/closures/Shared/StringUtils.php +0 -87
- src/includes/closures/Shared/SysUtils.php +0 -92
- src/includes/closures/Shared/TokenUtils.php +0 -300
- src/includes/closures/Shared/TrimUtils.php +0 -36
- src/includes/closures/Shared/UrlUtils.php +0 -131
- src/includes/functions/i18n-utils.php +32 -17
- src/includes/functions/wp-cache-postload.php +1 -1
- src/includes/interfaces/Shared/CachePathConsts.php +140 -0
- src/includes/interfaces/Shared/NcDebugConsts.php +293 -0
- src/includes/plugin.php +8 -6
- src/includes/stub.php +22 -6
- src/includes/templates/advanced-cache.txt +9 -3
- src/includes/traits/Ac/AbortUtils.php +17 -0
- src/includes/traits/Ac/AcPluginUtils.php +31 -0
- src/includes/traits/Ac/BrowserUtils.php +40 -0
- src/includes/traits/Ac/NcDebugUtils.php +217 -0
- src/includes/traits/Ac/ObUtils.php +356 -0
- src/includes/traits/Ac/PostloadUtils.php +193 -0
- src/includes/traits/Ac/ShutdownUtils.php +26 -0
- src/includes/traits/Plugin/ActionUtils.php +22 -0
- src/includes/traits/Plugin/BbPressUtils.php +69 -0
- src/includes/traits/Plugin/CleanupUtils.php +25 -0
- src/includes/traits/Plugin/CondUtils.php +19 -0
- src/includes/traits/Plugin/CronUtils.php +87 -0
- src/includes/traits/Plugin/DbUtils.php +19 -0
- src/includes/traits/Plugin/DirUtils.php +87 -0
- src/includes/traits/Plugin/HtaccessUtils.php +284 -0
- src/includes/traits/Plugin/InstallUtils.php +553 -0
- src/includes/traits/Plugin/MenuPageUtils.php +236 -0
- src/includes/traits/Plugin/NoticeUtils.php +337 -0
- src/includes/traits/Plugin/OptionUtils.php +81 -0
- src/includes/traits/Plugin/PostUtils.php +49 -0
- src/includes/traits/Plugin/UpdateUtils.php +52 -0
- src/includes/traits/Plugin/UrlUtils.php +52 -0
- src/includes/traits/Plugin/UserUtils.php +172 -0
- src/includes/traits/Plugin/WcpAuthorUtils.php +97 -0
- src/includes/traits/Plugin/WcpCommentUtils.php +103 -0
- src/includes/traits/Plugin/WcpFeedUtils.php +121 -0
- src/includes/traits/Plugin/WcpHomeBlogUtils.php +106 -0
- src/includes/traits/Plugin/WcpJetpackUtils.php +30 -0
- src/includes/traits/Plugin/WcpOpcacheUtils.php +77 -0
- src/includes/traits/Plugin/WcpPluginUtils.php +28 -0
- src/includes/traits/Plugin/WcpPostTypeUtils.php +71 -0
- src/includes/traits/Plugin/WcpPostUtils.php +190 -0
- src/includes/traits/Plugin/WcpSettingUtils.php +37 -0
- src/includes/traits/Plugin/WcpSitemapUtils.php +52 -0
- src/includes/traits/Plugin/WcpTermUtils.php +144 -0
- src/includes/traits/Plugin/WcpUpdaterUtils.php +103 -0
- src/includes/traits/Plugin/WcpUtils.php +383 -0
- src/includes/traits/Plugin/WcpWooCommerceUtils.php +30 -0
- src/includes/traits/Shared/BlogUtils.php +37 -0
- src/includes/traits/Shared/CacheDirUtils.php +651 -0
- src/includes/traits/Shared/CacheLockUtils.php +87 -0
- src/includes/traits/Shared/CachePathUtils.php +358 -0
- src/includes/traits/Shared/ConditionalUtils.php +380 -0
- src/includes/traits/Shared/DomainMappingUtils.php +277 -0
- src/includes/traits/Shared/EscapeUtils.php +23 -0
- src/includes/traits/Shared/FsUtils.php +335 -0
- src/includes/traits/Shared/HookUtils.php +281 -0
- src/includes/traits/Shared/HttpUtils.php +177 -0
- src/includes/traits/Shared/I18nUtils.php +52 -0
- src/includes/traits/Shared/IpAddrUtils.php +90 -0
- src/includes/traits/Shared/PatternUtils.php +55 -0
- src/includes/traits/Shared/ReplaceUtils.php +49 -0
- src/includes/traits/Shared/ServerUtils.php +73 -0
- src/includes/traits/Shared/StringUtils.php +94 -0
- src/includes/traits/Shared/SysUtils.php +100 -0
- src/includes/traits/Shared/TokenUtils.php +297 -0
- src/includes/traits/Shared/TrimUtils.php +40 -0
- src/includes/traits/Shared/UrlUtils.php +140 -0
- src/includes/translations/comet-cache.pot +0 -1927
- src/includes/uninstall.php +5 -3
- src/vendor/autoload.php +1 -1
- src/vendor/composer/ClassLoader.php +4 -4
- src/vendor/composer/LICENSE +1 -1
- src/vendor/composer/autoload_psr4.php +3 -1
- src/vendor/composer/autoload_real.php +3 -8
- src/vendor/composer/installed.json +70 -70
- src/vendor/websharks/sharkicons/src/long-classes.min.css +0 -1
- src/vendor/websharks/sharkicons/src/short-classes.min.css +0 -1
- src/vendor/websharks/wp-i18n-tools/CHANGELOG.md +3 -0
- src/vendor/websharks/wp-i18n-tools/README.md +14 -0
- src/vendor/websharks/wp-i18n-tools/add-textdomain.php +110 -0
- src/vendor/websharks/wp-i18n-tools/cron-svn-pots.php +117 -0
- src/vendor/websharks/wp-i18n-tools/extract/ExtractTest.php +160 -0
- src/vendor/websharks/wp-i18n-tools/extract/TODO +1 -0
- src/vendor/websharks/wp-i18n-tools/extract/extract.php +163 -0
CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= v160227 =
|
2 |
|
3 |
- **Bug Fix**: Fixed a ZenCache Backwards Compatibility bug that was preventing calls to `$GLOBALS['zencache']` from working properly with Comet Cache. See [Issue #689](https://github.com/websharks/comet-cache/issues/689)
|
1 |
+
= v160416 =
|
2 |
+
|
3 |
+
- **Enhancement**: Several PHP 5.4+ enhancements, most notably a conversion from PHP Closures to PHP Traits. See [Issue #635](https://github.com/websharks/comet-cache/issues/635).
|
4 |
+
- **Enhancement**: Dashboard notices generated by Comet Cache now use the WordPress-style dismiss button to keep things consistent. See [Issue #719](https://github.com/websharks/comet-cache/issues/719).
|
5 |
+
- **Enhancement**: Dashboard notices generated by Comet Cache are now compacted into a single notice that can be expanded to view details. This helps reduce the number of messages that appear when, for example, a Post is published or updated and several cache files are automatically cleared. Instead of showing a separate notice for each type of cache file that was cleared, a single notice is shown with a link to toggle the details. See [Issue #118](https://github.com/websharks/comet-cache/issues/118).
|
6 |
+
- **Enhancement** (Pro): Improved the way the Auto-Cache Engine figures out the URL scheme (`http` vs `https`) that should be used when fetching the XML Sitemap. Instead of forcing `http`, whatever scheme is configured with the Home URL is now used. See [Issue #715](https://github.com/websharks/comet-cache/issues/715).
|
7 |
+
- **Enhancement** (Pro): The Pro Plugin Updater page now includes a "Save All Changes" button at the bottom, allowing you to save changes to the updater configuration without actually running the plugin updater. Props @bridgeport @NoahjChampion @1wdtv. See [Issue #681](https://github.com/websharks/comet-cache/issues/681).
|
8 |
+
- **Bug Fix**: Fixed a duplicated row of links on the Pro Plugin Updater page. See [Issue #696](https://github.com/websharks/comet-cache/issues/696).
|
9 |
+
- **Bug Fix**: Fixed an issue where some browsers would report "Failed to parse SourceMap" errors in their console when browsing the Comet Cache Options page. This was related to `sourceMappingURL` comments in the minified JS/CSS files that were intended for development purposes. Props to @1wdtv for reporting. See [#732](https://github.com/websharks/comet-cache/issues/732).
|
10 |
+
- **Bug Fix**: Fixed a UI bug in the Pro Preview that was causing the Manual Cache Clearing panel to not appear as part of the Pro Preview. Props @renzms. See [Issue #711](https://github.com/websharks/comet-cache/issues/711).
|
11 |
+
- **Bug Fix** (Pro): Fixed a bug related to the Pro Updater where some users who had migrated from ZenCache Pro to Comet Cache Pro were seeing an invalid new version message. Props @renzms @jaswsinc. See [Issue #727](https://github.com/websharks/comet-cache/issues/727)
|
12 |
+
- **Bug Fix** (Pro): Fixed a bug with the Pro Plugin Updater that resulted in "Unknown error. Please wait 15 minutes and try again." when attempting to update Comet Cache Pro. The issue affected sites on servers running an old version of cURL (< v7.36) and/or an old version of OpenSSL, which made them unable to connect to the Comet Cache Pro update server. The Pro Plugin Updater now attempts to connect to a secondary update server that is more compatible with older versions of cURL and OpenSSL. See [Issue #678](https://github.com/websharks/comet-cache/issues/678).
|
13 |
+
- **Hooks/Filters**: Comet Cache now hooks into `plugins_loaded` instead of `after_setup_theme` when calling its own setup routine. This improves integration with other plugins that may be expecting the Comet Cache API functions to be available after `plugins_loaded`. Props to Frank Goossens (@futtta) from Autoptimize for helping with this. See [Issue #716](https://github.com/websharks/comet-cache/issues/716).
|
14 |
+
- **Compatibility**: Fixed a compatibility issue for some themes and plugins that were using old AC Plugin code designed to work with Quick Cache. This fix adds some backwards compatibility support for Quick Cache, but note that the first release of Comet Cache dropped support for Quick Cache backwards compatibility in favor of ZenCache backwards compatibility. See [Issue #710](https://github.com/websharks/comet-cache/issues/710).
|
15 |
+
- **Compatibility: Query Monitor.** The Query Monitor plugin was reporting false-positive errors indicating that many Comet Cache methods did not exist. This was due to how the Comet Cache codebase was utilizing PHP Closures, which Query Monitor had a hard time handling. The codebase has been refactored to use PHP Traits instead of Closures and now the Query Monitor plugin has no problem recognizing Comet Cache methods. Props to @NoahjChampion for reporting. See [Issue #686](https://github.com/websharks/comet-cache/issues/686).
|
16 |
+
- **Compatibility: WP-CLI.** When installing Comet Cache via WP-CLI, Comet Cache is now automatically enabled. There's no need to manually enable Comet Cache from within the plugin options after installing. Props @jaswsinc. See [Issue #464](https://github.com/websharks/comet-cache/issues/464).
|
17 |
+
- **Required WordPress Version is now v4.2.** The minimum required WordPress version has been bumped from v4.1 to v4.2. See [Issue #706](https://github.com/websharks/comet-cache/issues/706).
|
18 |
+
|
19 |
= v160227 =
|
20 |
|
21 |
- **Bug Fix**: Fixed a ZenCache Backwards Compatibility bug that was preventing calls to `$GLOBALS['zencache']` from working properly with Comet Cache. See [Issue #689](https://github.com/websharks/comet-cache/issues/689)
|
comet-cache.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
-
Version:
|
4 |
Text Domain: comet-cache
|
5 |
Plugin Name: Comet Cache
|
6 |
Network: true
|
@@ -14,4 +14,4 @@ Description: Comet Cache is an advanced WordPress caching plugin inspired by sim
|
|
14 |
if (!defined('WPINC')) {
|
15 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
16 |
}
|
17 |
-
require_once
|
1 |
<?php
|
2 |
/*
|
3 |
+
Version: 160416
|
4 |
Text Domain: comet-cache
|
5 |
Plugin Name: Comet Cache
|
6 |
Network: true
|
14 |
if (!defined('WPINC')) {
|
15 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
16 |
}
|
17 |
+
require_once __DIR__.'/plugin.php';
|
plugin.php
CHANGED
@@ -4,12 +4,12 @@ if (!defined('WPINC')) {
|
|
4 |
}
|
5 |
$GLOBALS['wp_php_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 |
|
7 |
-
if (require(
|
8 |
if (!empty($_REQUEST['comet_cache_mbstring_deprecated_warning_bypass']) && is_admin()) {
|
9 |
update_site_option('comet_cache_mbstring_deprecated_warning_bypass', time());
|
10 |
}
|
11 |
|
12 |
-
${__FILE__}['apc_enabled'] = (extension_loaded('apc') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) && filter_var(ini_get('apc.cache_by_default'), FILTER_VALIDATE_BOOLEAN) && stripos((string)ini_get('apc.filters'), 'comet-cache') === false) ? true : false;
|
13 |
|
14 |
if ((!version_compare(PHP_VERSION, '5.4', '>=') || ${__FILE__}['apc_enabled'])) { // If PHP <= 5.4 or APC is enabled
|
15 |
|
@@ -22,8 +22,10 @@ if (require(dirname(__FILE__).'/src/vendor/websharks/wp-php-rv/src/includes/chec
|
|
22 |
}
|
23 |
|
24 |
add_action(
|
25 |
-
|
26 |
-
|
|
|
|
|
27 |
' return;'."\n".// User missing capability.
|
28 |
|
29 |
'echo \''.// Wrap `$notice` inside a WordPress error.
|
@@ -33,7 +35,7 @@ if (require(dirname(__FILE__).'/src/vendor/websharks/wp-php-rv/src/includes/chec
|
|
33 |
'</div>'.
|
34 |
|
35 |
'\';'
|
36 |
-
|
37 |
);
|
38 |
} elseif (${__FILE__}['apc_enabled'] && is_admin()) {
|
39 |
${__FILE__}['apc_deprecated_notice'] = '<h3 style="margin:.5em 0 .25em 0;">'.__('<strong>NOTICE: Comet Cache + PHP APC Extension</strong></h3>', 'comet-cache');
|
@@ -46,8 +48,10 @@ if (require(dirname(__FILE__).'/src/vendor/websharks/wp-php-rv/src/includes/chec
|
|
46 |
${__FILE__}['apc_deprecated_notice'] .= '<p style="margin-top:0;">'.__('To learn more about this change, please see the announcement: <a href="http://cometcache.com/r/php-apc-extension-no-longer-supported/" target="_blank">PHP APC Extension No Longer Supported</a>', 'comet-cache').'</p>';
|
47 |
|
48 |
add_action(
|
49 |
-
|
50 |
-
|
|
|
|
|
51 |
' return;'."\n".// User missing capability.
|
52 |
|
53 |
'echo \''.// Wrap `$notice` inside a WordPress error.
|
@@ -57,7 +61,7 @@ if (require(dirname(__FILE__).'/src/vendor/websharks/wp-php-rv/src/includes/chec
|
|
57 |
'</div>'.
|
58 |
|
59 |
'\';'
|
60 |
-
|
61 |
);
|
62 |
}
|
63 |
} else { // Load the plugin
|
@@ -68,8 +72,10 @@ if (require(dirname(__FILE__).'/src/vendor/websharks/wp-php-rv/src/includes/chec
|
|
68 |
${__FILE__}['mbstring_deprecated_warning'] .= '<p style="margin-top:0;">'.__('The <code>mbstring</code> extension provides Multibyte String support to PHP and is required to properly handle UTF-8 characters, which many sites now use. Without Multibyte String support, Comet Cache will be unstable. For that reason we are requiring the <code>mbstring</code> extension to improve reliablity when caching and to prevent your site from experiencing unforeseen issues in the future.', 'comet-cache').'</p>';
|
69 |
${__FILE__}['mbstring_deprecated_warning'] .= '<p style="margin-bottom:.5em;">'.__('<a href="'.esc_attr(add_query_arg('comet_cache_mbstring_deprecated_warning_bypass', '1')).'" onclick="if(!confirm(\'Are you sure? Press OK to continue, or Cancel to stop and read carefully.\')) return false;">Dismiss this notice.</a>', 'comet-cache').'</p>';
|
70 |
add_action(
|
71 |
-
'all_admin_notices',
|
72 |
-
|
|
|
|
|
73 |
' return;'."\n".// User missing capability.
|
74 |
'echo \''.// Wrap `$notice` inside a WordPress error.
|
75 |
'<div class="notice notice-warning">'.
|
@@ -80,7 +86,7 @@ if (require(dirname(__FILE__).'/src/vendor/websharks/wp-php-rv/src/includes/chec
|
|
80 |
);
|
81 |
}
|
82 |
|
83 |
-
require_once
|
84 |
}
|
85 |
} else {
|
86 |
wp_php_rv_notice('Comet Cache');
|
4 |
}
|
5 |
$GLOBALS['wp_php_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 |
|
7 |
+
if (require(__DIR__.'/src/vendor/websharks/wp-php-rv/src/includes/check.php')) {
|
8 |
if (!empty($_REQUEST['comet_cache_mbstring_deprecated_warning_bypass']) && is_admin()) {
|
9 |
update_site_option('comet_cache_mbstring_deprecated_warning_bypass', time());
|
10 |
}
|
11 |
|
12 |
+
${__FILE__}['apc_enabled'] = (extension_loaded('apc') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) && filter_var(ini_get('apc.cache_by_default'), FILTER_VALIDATE_BOOLEAN) && stripos((string) ini_get('apc.filters'), 'comet-cache') === false) ? true : false;
|
13 |
|
14 |
if ((!version_compare(PHP_VERSION, '5.4', '>=') || ${__FILE__}['apc_enabled'])) { // If PHP <= 5.4 or APC is enabled
|
15 |
|
22 |
}
|
23 |
|
24 |
add_action(
|
25 |
+
'all_admin_notices',
|
26 |
+
create_function(
|
27 |
+
'',
|
28 |
+
'if(!current_user_can(\'activate_plugins\'))'.
|
29 |
' return;'."\n".// User missing capability.
|
30 |
|
31 |
'echo \''.// Wrap `$notice` inside a WordPress error.
|
35 |
'</div>'.
|
36 |
|
37 |
'\';'
|
38 |
+
)
|
39 |
);
|
40 |
} elseif (${__FILE__}['apc_enabled'] && is_admin()) {
|
41 |
${__FILE__}['apc_deprecated_notice'] = '<h3 style="margin:.5em 0 .25em 0;">'.__('<strong>NOTICE: Comet Cache + PHP APC Extension</strong></h3>', 'comet-cache');
|
48 |
${__FILE__}['apc_deprecated_notice'] .= '<p style="margin-top:0;">'.__('To learn more about this change, please see the announcement: <a href="http://cometcache.com/r/php-apc-extension-no-longer-supported/" target="_blank">PHP APC Extension No Longer Supported</a>', 'comet-cache').'</p>';
|
49 |
|
50 |
add_action(
|
51 |
+
'all_admin_notices',
|
52 |
+
create_function(
|
53 |
+
'',
|
54 |
+
'if(!current_user_can(\'activate_plugins\'))'.
|
55 |
' return;'."\n".// User missing capability.
|
56 |
|
57 |
'echo \''.// Wrap `$notice` inside a WordPress error.
|
61 |
'</div>'.
|
62 |
|
63 |
'\';'
|
64 |
+
)
|
65 |
);
|
66 |
}
|
67 |
} else { // Load the plugin
|
72 |
${__FILE__}['mbstring_deprecated_warning'] .= '<p style="margin-top:0;">'.__('The <code>mbstring</code> extension provides Multibyte String support to PHP and is required to properly handle UTF-8 characters, which many sites now use. Without Multibyte String support, Comet Cache will be unstable. For that reason we are requiring the <code>mbstring</code> extension to improve reliablity when caching and to prevent your site from experiencing unforeseen issues in the future.', 'comet-cache').'</p>';
|
73 |
${__FILE__}['mbstring_deprecated_warning'] .= '<p style="margin-bottom:.5em;">'.__('<a href="'.esc_attr(add_query_arg('comet_cache_mbstring_deprecated_warning_bypass', '1')).'" onclick="if(!confirm(\'Are you sure? Press OK to continue, or Cancel to stop and read carefully.\')) return false;">Dismiss this notice.</a>', 'comet-cache').'</p>';
|
74 |
add_action(
|
75 |
+
'all_admin_notices',
|
76 |
+
create_function(
|
77 |
+
'',
|
78 |
+
'if(!current_user_can(\'activate_plugins\'))'.
|
79 |
' return;'."\n".// User missing capability.
|
80 |
'echo \''.// Wrap `$notice` inside a WordPress error.
|
81 |
'<div class="notice notice-warning">'.
|
86 |
);
|
87 |
}
|
88 |
|
89 |
+
require_once __DIR__.'/src/includes/plugin.php';
|
90 |
}
|
91 |
} else {
|
92 |
wp_php_rv_notice('Comet Cache');
|
readme.txt
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
=== Comet Cache ===
|
2 |
|
3 |
-
Stable tag:
|
4 |
-
Requires at least: 4.
|
5 |
-
Tested up to: 4.
|
6 |
Text Domain: comet-cache
|
7 |
|
8 |
License: GPLv2 or later
|
@@ -330,12 +330,30 @@ Released under the terms of the [GNU General Public License](http://www.gnu.org/
|
|
330 |
|
331 |
== Upgrade Notice ==
|
332 |
|
333 |
-
=
|
334 |
|
335 |
-
Requires
|
336 |
|
337 |
== Changelog ==
|
338 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
= v160227 =
|
340 |
|
341 |
- **Bug Fix**: Fixed a ZenCache Backwards Compatibility bug that was preventing calls to `$GLOBALS['zencache']` from working properly with Comet Cache. See [Issue #689](https://github.com/websharks/comet-cache/issues/689)
|
@@ -356,62 +374,4 @@ Requires PHP v5.4+. The latest version of Comet Cache is a complete rewrite (OOP
|
|
356 |
- **Bug Fix (Multisite)**: Fixed a bug where when Comet Cache was Network Activated the plugin settings link would show up in the plugins list for the Main Site and would lead to a 404 error. The settings link is now only shown when viewing the plugins list from the Network Admin. Props @jaswsinc. See [Issue #675](https://github.com/websharks/zencache/issues/675).
|
357 |
- **Enhancement**: Added support-related links to the plugin options page. Props @renzms. See [Issue #612](https://github.com/websharks/zencache/issues/612#issuecomment-186827661).
|
358 |
|
359 |
-
|
360 |
-
|
361 |
-
- **Announcement: ZenCache is changing its name to Comet Cache!** Learn more about this upcoming change [here](https://cometcache.com/r/announcing-comet-cache-formerly-zencache/).
|
362 |
-
- **Announcement: This version of ZenCache requires PHP 5.4+.** As announced in the previous release, the minimum PHP version required to run ZenCache / Comet Cache has changed to PHP 5.4+ as of December 1st, 2015. Please see announcement with further details: [New Minimum PHP Version: PHP 5.4](http://zencache.com/r/new-minimum-php-version-php-5-4/)
|
363 |
-
- **Announcement: This version of ZenCache does not support the PHP APC Extension**. As announced in the previous release, ZenCache / Comet Cache no longer runs with the PHP APC extension enabled as of December 1st, 2015. Please see announcement with further details: [PHP APC Extension No Longer Supported](http://zencache.com/r/php-apc-extension-no-longer-supported/)
|
364 |
-
- **Announcement: After March 1st, 2016 ZenCache / Comet Cache will require PHP Multibyte String support.** The `mbstring` extension provides Multibyte String support to PHP and is required to properly handle UTF-8 characters, which many sites now use. Without Multibyte String support, caching will be unstable. For that reason we are requiring the `mbstring` extension to improve reliability when caching and to prevent your site from experiencing unforeseen issues in the future.
|
365 |
-
- **Announcement: Restructured Codebase**. The entire ZenCache Lite codebase has been restructured to improve performance, enhance flexibility, and make it easier to build in new features! This release of ZenCache Lite has been built from the ZenCache Pro codebase, which is more polished and up-to-date. This release includes many changes and improvements that were released as part of ZenCache Pro releases over the past 6 months and are now being included in the Lite version. See the full changelog below for a complete list of changes.
|
366 |
-
- **New Feature!** A new watered-down Regular Expression syntax is now supported in several existing ZenCache features, including XML Sitemap Patterns, URI Exclusion Patterns, HTTP Referrer Exclusion Patterns, and User-Agent Exclusion Patterns. (It is also supported in the Pro-only Custom URLs to Auto-Clear, and the HTML Compressor CSS Exclusion Patterns and JavaScript Exclusion Patterns.) This new syntax greatly increases the power and flexibility of each of these features and makes things possible like the much-requested ability to Auto-Clear the Home Page or Posts Page of a site whenever a post cache is cleared. For more information on this new watered-down Regular Expression syntax, [this KB Article](http://zencache.com/r/watered-down-regex-syntax/). Props @kristineds @jaswsinc. See [Issue #191](https://github.com/websharks/zencache/issues/191).
|
367 |
-
- **Bug Fix**: Fixed a bug with clearing cache files for paginated pages where the `pagination_base` had been changed from the default `page` to something else (e.g., a translated string). The WP Rewrite API is now used to include `pagination_base` and `comments_pagination_base` when building paths to cache files to determine which cache files should be cleared. Props @renzms. See [Issue #607](https://github.com/websharks/zencache/issues/607).
|
368 |
-
- **Bug Fix**: This release attempts to resolve reports of Error 500 and Internal Server Error issues when running with PHP 5.6 + OPcache. Instead of clearing the entire Opcode cache whenever the plugin options are saved, we only invalidate the `advanced-cache.php` file, which is rebuilt each time you update your configuration options. Props @jaswsinc. Also props to @MarioKnight and @CotswoldPhoto for helping us narrow this down. See [Issue #624](https://github.com/websharks/zencache/issues/624).
|
369 |
-
- **Bug Fix**: Fixed an issue where a PHP Notice was generated when an inactive WordPress component was being upgraded. This issue did not have any adverse affect on the site, but this fix resolves the issue so that the notice won't appear in PHP logs. See [Issue #589](https://github.com/websharks/zencache/issues/589).
|
370 |
-
- **Bug Fix**: Fixed a bug where a commented-out `WP_CACHE` definition in `wp-config.php` (such as what WP Super Cache leaves behind) was being incorrectly ignored and resulted in caching being silently disabled. Props @davidfavor. See [Issue #591](https://github.com/websharks/zencache/issues/591).
|
371 |
-
- **Bug Fix**: Fixed a bug where in some scenarios a page might not be cached due to a stray `AUTH_COOKIE` or `SECURE_AUTH_COOKIE` cookie, even when the user is not logged in. Props @jaswsinc @renzms. See [Issue #592](https://github.com/websharks/zencache/issues/592).
|
372 |
-
- **Bug Fix**: Fixed an issue related to a popular NGINX server configuration (`try_files $uri $uri/ /index.php?q=$uri&$args;`) that was preventing the entire site from being cached. ZenCache disables caching by default for all requests that include a query string (see _Dashboard → ZenCache → Plugin Options → GET Requests_) and this particular NGINX configuration passes _all_ requests to WordPress with a `?q=` query variable, which was resulting in ZenCache disabling caching on all pages. This release implements better detection for NGINX and works around this scenario. Props @jaswsinc. See [Issue #561](https://github.com/websharks/zencache/issues/561).
|
373 |
-
- **Bug Fix**: Fixed a bug where, in some rare cases, `wp-config.php` would end up with two `WP_CACHE` definitions. Props @jaswsinc. See [Issue #509](https://github.com/websharks/zencache/issues/509).
|
374 |
-
- **Bug Fix**: Saving a Post as a Draft was incorrectly purging XML Sitemap cache files. Props @jaswsinc. See [Issue #368](https://github.com/websharks/zencache/issues/368).
|
375 |
-
- **Bug Fix**: Fixed a bug in the Dynamic Version Salt filter that was generating PHP notices and warnings. See [Issue #522](https://github.com/websharks/zencache/issues/522).
|
376 |
-
- **Bug Fix**: Fixed an issue with backwards compatibility that was preventing some AC Plugins from working properly. See [Issue #514](https://github.com/websharks/zencache/issues/514).
|
377 |
-
- **Bug Fix**: Fixed a bug where saving a Post/Page as a Draft as a user with an Editor role would unnecessarily clear the Home Page cache. See [Issue #625](https://github.com/websharks/zencache/issues/625).
|
378 |
-
- **Multisite Bug Fix**: Fixed a bug where the Clear Cache button wouldn't clear Child-Site Logged-In User Home Page cache files on WordPress Multisite Networks. Props @jaswsinc. See [Issue #409](https://github.com/websharks/zencache/issues/409)
|
379 |
-
- **Multisite Bug Fix**: Fixed a bug where the Home Page cache was not clearing on Child Sites in a Multisite Network. Props @jaswsinc. See [Issue #409](https://github.com/websharks/zencache/issues/409)
|
380 |
-
- **Multisite Bug Fix**: Fixed a bug with 404 Request caching on Multisite Networks where ZenCache Pro was not considering that each child blog in a multisite network will have its own 404 error page. Props @jaswsinc. See [Issue #539](https://github.com/websharks/zencache/issues/539).
|
381 |
-
- **Multisite Bug Fix**: Fixed a bug where clearing the cache from the main site of a multisite network, when there are child blogs in sub-directories, resulted in all child blogs being cleared from the cache, not just the main site as would be expected. This has been resolved and only the main site is cleared when clicking the Clear Cache button. Note that the Wipe Cache button can still be used to clear the cache for all sites in a Multisite Network. Props @jaswsinc. See [Issue #540](https://github.com/websharks/zencache/issues/540).
|
382 |
-
- **Multisite Bug Fix**: Fixed a bug where Wiping the cache on a multisite network resulted in the very next page view being cached incorrectly. Props @jaswsinc. See [Issue #541](https://github.com/websharks/zencache/issues/541).
|
383 |
-
- **Multisite Bug Fix**: Fixed a bug where when ZenCache was Network Activated the plugin settings link would show up in the plugins list for the Main Site and would lead to a 404 error. The settings link is now only shown when viewing the plugins list from the Network Admin. Props @jaswsinc. See [Issue #675](https://github.com/websharks/zencache/issues/675).
|
384 |
-
- **Enhancement**: Added support-related links to the plugin options page. Props @renzms. See [Issue #612](https://github.com/websharks/zencache/issues/612#issuecomment-186827661).
|
385 |
-
- **Enhancement**: It's now possible to override the ZenCache Nonce exclusion globally (dangerous) or only for Logged-In Users (safer). Please see [this article](http://zencache.com/r/kb-article-what-are-wordpress-nonces-and-why-are-they-not-cache-compatible/) for full details. [Issue #637](https://github.com/websharks/zencache/issues/637).
|
386 |
-
- **Enhancement**: Improved WP Cron-related configuration and validation of custom cron schedules. See [PR #197](https://github.com/websharks/zencache-pro/pull/197).
|
387 |
-
- **Enhancement**: ZenCache now clears the cache whenever a WordPress plugin is activated or deactivated. Many WordPress plugins change content on the front-end of the site, so this enhancement ensures that an old cache file is never served to visitors. If you want to disable this automatic behavior, see [this article](http://zencache.com/kb-article/how-do-i-prevent-zencache-from-clearing-the-cache-upon-plugin-activation-or-deactivation/). Props @renzms. See [Issue #424](https://github.com/websharks/zencache/issues/424).
|
388 |
-
- **Enhancement**: When activating ZenCache for the first time, a new Dashboard message now includes a helpful link to the options page to enable caching and review the options. Props @kristineds. See [Issue #112](https://github.com/websharks/zencache/issues/112).
|
389 |
-
- **Enhancement**: The automatic Cache Cleanup schedule that cleans up (deletes) expired/stale cache files has been changed from once every day to once every hour. Running the cleanup hourly makes ZenCache smarter when configured in certain ways and saves disk space. Props @kristineds. See [Issue #472](https://github.com/websharks/zencache/issues/472).
|
390 |
-
- **Enhancement**: When the Cache Directory location is changed, ZenCache now cleans up the old Cache Directory and any old cache files instead of leaving them behind. Props @clavaque @renzms. See [Issue #580](https://github.com/websharks/zencache/issues/580).
|
391 |
-
- **Enhancement**: Added a new API Function that allows a site owner to clear the cache for a specific URL via `zencache::clearUrl($url);`. See [this article](http://zencache.com/kb-article/clearing-the-cache-dynamically/#toc-988085ad) for further details. Props @kristineds. See [Issue #590](https://github.com/websharks/zencache/issues/590).
|
392 |
-
- **Enhancement**: Improved the HTML Notes generated by ZenCache when s2Member (a membership plugin for WordPress) is specifically disabling caching. s2Member automatically disables caching on certain pages that are required to remain dynamic. The HTML Notes generated by ZenCache now explain when this is happening. Props @renzms. See [Issue #504](https://github.com/websharks/zencache/issues/504).
|
393 |
-
- **Enhancement**: Manual Cache Clearing options have now been separated from Automatic Cache Clearing options inside the ZenCache Plugin Options to improve the differentiation between these.
|
394 |
-
- **Enhancement**: New icons in the ZenCache Plugin Options help improve the visual representation of each panel.
|
395 |
-
- **Enhancement**: The installed plugin version is now shown at the top of the ZenCache Options Page. Props @renzms. See [Issue #502](https://github.com/websharks/zencache/issues/502).
|
396 |
-
- **Enhancement**: New transition in/out effects on the Cache Cleared Dashboard notifications. Props @jaswsinc. See [Issue #538](https://github.com/websharks/zencache/issues/538).
|
397 |
-
- **Enhancement**: Improved compatibility with any Custom Post Type that uses hierarchies. Props @jaswsinc.
|
398 |
-
- **Akismet Compatibility:** ZenCache no longer caches pages that contain `akismet_comment_nonce` in the markup. This ensures that a page that contains a time-sensitive `nonce` value does not get cached. Props @kristineds and @jaswsinc. See [Issue #601](https://github.com/websharks/zencache/issues/601).
|
399 |
-
- **Akismet Compatibility:** ZenCache now automatically disables the Akismet Comment Nonce using [the `akismet_comment_nonce` filter](https://github.com/git-mirror/wordpress-akismet/blob/2.5.6/akismet.php#L333), which improves compatibility between Akismet and the page caching functionality provided by ZenCache. This ensures that pages do not contain time-sensitive `nonce` values that should not be cached. If you'd like to revert this behavior, please see [this article](http://zencache.com/kb-article/how-do-i-prevent-zencache-from-disabling-the-akismet-comment-nonce/). Props @kristineds and @jaswsinc. See [Issue #601](https://github.com/websharks/zencache/issues/601).
|
400 |
-
- **Akismet Compatibility**: Fixed a bug with Akismet compatibility where ZenCache was not properly disabling the Akismet Comment Nonce, which resulted in pages being unnecessarily excluded from the cache due to the presence of the `akismet_comment_nonce` in the markup. Props @Kalfer. See [Issue #642](https://github.com/websharks/zencache/issues/642).
|
401 |
-
- **WooCommerce Compatibility:** This release improves compatibility with the WooCommerce Product Stock feature. When the Product Stock changes, ZenCache will now clear the cache file for the associated Product to ensure that the stock quantity that appears on the site remains up-to-date. See [Issue #597](https://github.com/websharks/zencache/issues/597).
|
402 |
-
- **Multisite Domain Mapping Compatibility**: ZenCache is now fully compatible with the [WordPress MU Domain Mapping plugin](https://wordpress.org/plugins/wordpress-mu-domain-mapping/), including Multisite Networks using domain mapping on top-level domains, sub-domains, and sub-directories. Multiple variations of each site spread across an unlimited number of domain mappings and/or the original blog domain/path is also supported. All Pro-only features, including the Auto-Cache Engine, Static CDN Filters, and HTML Compression, are also now compatible with domain mapping. Props @jaswsinc. See [Issue #339](https://github.com/websharks/zencache/issues/339).
|
403 |
-
- **bbPress Compatibility**: This release greatly improves compatibility with bbPress. Events like creating a new Forum, creating a new Topic, and posting a reply to a Topic (including threaded replies), now properly clear the necessary cache files to ensure that cached bbPress pages remain up-to-date. Props @jaswsinc. See [Issue #168](https://github.com/websharks/zencache/issues/168).
|
404 |
-
- **bbPress Compatibility:** This release improves compatibility with bbPress when ZenCache Logged-In User caching is enabled. In this scenario, bbPress may generate links for Admins that contain time-sensitive `_wpnonce` values which could expire if cached and result in certain admin-related actions failing. ZenCache no longer caches pages that contain `_wpnonce` in the markup. This ensures that pages containing time-sensitive `nonce` values are not cached. Props @kristineds, @jaswsinc, and @clavaque. See [Issue #601](https://github.com/websharks/zencache/issues/601).
|
405 |
-
- **New Pro Features:** This release updates the Pro Preview to include several new Pro features that have been added over the past 6 months, including the ability to clear the PHP OPCache whenever manually clearing the cache (_ZenCache Options → Manual Cache Clearing → Clear the PHP OPCache Too?_), clear the CDN Cache whenever manually clearing the cache (_ZenCache Options → Manual Cache Clearing → CDN Cache Clear the CDN Cache Too?_), disable cache expiration if the server load average is high (_ZenCache Options → Cache Expiration Time → Disable Cache Expiration If Server Load Average is High_), the ability to specify which WordPress Roles/Capabilities are allowed to clear the cache from the WordPress Admin bar (_ZenCache Options → Manual Cache Clearing → Also allow others to clear the cache from their Admin Bar?_), a completely new Cache Statistics feature that allows you to monitor the health and status of your cache (_ZenCache → Stats / Charts_), the ability to specify a list of Custom URLs whose cache files should be cleared whenever ZenCache detects that a Post/Page cache should be cleared (_ZenCache Options → Automatic Cache Clearing → Misc. Auto-Clear Options → Auto-Clear a List of Custom URLs Too?_), a new menu of Clear Cache options in the Admin Bar that allows you to clear the cache for just the Home Page, the Current URL, a Specific URL, PHP's OPCache, or the CDN Cache (_ZenCache Options → Plugin Options → Manual Cache Clearing_), the ability to customize the Cache Cleanup Schedule and set your own schedule (_ZenCache Options → Manual Cache Clearing → Cache Cleanup Schedule_), the ability to configure the Pro Plugin Updater to check for Beta versions, an option to clear Expired WordPress Transients, and URI Exclusion Patterns for Client-Side Caching.
|
406 |
-
|
407 |
-
= v160211.2 =
|
408 |
-
|
409 |
-
- **Minor Fix**: Remove unnecessary `src/client-s/css/.sass-cache` directory.
|
410 |
-
|
411 |
-
= v160211 =
|
412 |
-
|
413 |
-
**Announcing Comet Cache, formerly ZenCache!**
|
414 |
-
|
415 |
-
We are very excited to announce the release of [Comet Cache](http://cometcache.com), an advanced WordPress caching plugin inspired by simplicity. Comet Cache is the successor to ZenCache (and Quick Cache before that), a very popular WordPress caching plugin that has been downloaded over 1 million times and has won acclaim for its speed, simplicity, and ease of configuration. [Read the full announcement here](https://cometcache.com/r/announcing-comet-cache-formerly-zencache/).
|
416 |
-
|
417 |
-
For older Changelog entries, please see the `CHANGELOG.md` file.
|
1 |
=== Comet Cache ===
|
2 |
|
3 |
+
Stable tag: 160416
|
4 |
+
Requires at least: 4.2
|
5 |
+
Tested up to: 4.6-alpha
|
6 |
Text Domain: comet-cache
|
7 |
|
8 |
License: GPLv2 or later
|
330 |
|
331 |
== Upgrade Notice ==
|
332 |
|
333 |
+
= v160416 =
|
334 |
|
335 |
+
Requires WordPress v4.2+.
|
336 |
|
337 |
== Changelog ==
|
338 |
|
339 |
+
= v160416 =
|
340 |
+
|
341 |
+
- **Enhancement**: Several PHP 5.4+ enhancements, most notably a conversion from PHP Closures to PHP Traits. See [Issue #635](https://github.com/websharks/comet-cache/issues/635).
|
342 |
+
- **Enhancement**: Dashboard notices generated by Comet Cache now use the WordPress-style dismiss button to keep things consistent. See [Issue #719](https://github.com/websharks/comet-cache/issues/719).
|
343 |
+
- **Enhancement**: Dashboard notices generated by Comet Cache are now compacted into a single notice that can be expanded to view details. This helps reduce the number of messages that appear when, for example, a Post is published or updated and several cache files are automatically cleared. Instead of showing a separate notice for each type of cache file that was cleared, a single notice is shown with a link to toggle the details. See [Issue #118](https://github.com/websharks/comet-cache/issues/118).
|
344 |
+
- **Enhancement** (Pro): Improved the way the Auto-Cache Engine figures out the URL scheme (`http` vs `https`) that should be used when fetching the XML Sitemap. Instead of forcing `http`, whatever scheme is configured with the Home URL is now used. See [Issue #715](https://github.com/websharks/comet-cache/issues/715).
|
345 |
+
- **Enhancement** (Pro): The Pro Plugin Updater page now includes a "Save All Changes" button at the bottom, allowing you to save changes to the updater configuration without actually running the plugin updater. Props @bridgeport @NoahjChampion @1wdtv. See [Issue #681](https://github.com/websharks/comet-cache/issues/681).
|
346 |
+
- **Bug Fix**: Fixed a duplicated row of links on the Pro Plugin Updater page. See [Issue #696](https://github.com/websharks/comet-cache/issues/696).
|
347 |
+
- **Bug Fix**: Fixed an issue where some browsers would report "Failed to parse SourceMap" errors in their console when browsing the Comet Cache Options page. This was related to `sourceMappingURL` comments in the minified JS/CSS files that were intended for development purposes. Props to @1wdtv for reporting. See [#732](https://github.com/websharks/comet-cache/issues/732).
|
348 |
+
- **Bug Fix**: Fixed a UI bug in the Pro Preview that was causing the Manual Cache Clearing panel to not appear as part of the Pro Preview. Props @renzms. See [Issue #711](https://github.com/websharks/comet-cache/issues/711).
|
349 |
+
- **Bug Fix** (Pro): Fixed a bug related to the Pro Updater where some users who had migrated from ZenCache Pro to Comet Cache Pro were seeing an invalid new version message. Props @renzms @jaswsinc. See [Issue #727](https://github.com/websharks/comet-cache/issues/727)
|
350 |
+
- **Bug Fix** (Pro): Fixed a bug with the Pro Plugin Updater that resulted in "Unknown error. Please wait 15 minutes and try again." when attempting to update Comet Cache Pro. The issue affected sites on servers running an old version of cURL (< v7.36) and/or an old version of OpenSSL, which made them unable to connect to the Comet Cache Pro update server. The Pro Plugin Updater now attempts to connect to a secondary update server that is more compatible with older versions of cURL and OpenSSL. See [Issue #678](https://github.com/websharks/comet-cache/issues/678).
|
351 |
+
- **Hooks/Filters**: Comet Cache now hooks into `plugins_loaded` instead of `after_setup_theme` when calling its own setup routine. This improves integration with other plugins that may be expecting the Comet Cache API functions to be available after `plugins_loaded`. Props to Frank Goossens (@futtta) from Autoptimize for helping with this. See [Issue #716](https://github.com/websharks/comet-cache/issues/716).
|
352 |
+
- **Compatibility**: Fixed a compatibility issue for some themes and plugins that were using old AC Plugin code designed to work with Quick Cache. This fix adds some backwards compatibility support for Quick Cache, but note that the first release of Comet Cache dropped support for Quick Cache backwards compatibility in favor of ZenCache backwards compatibility. See [Issue #710](https://github.com/websharks/comet-cache/issues/710).
|
353 |
+
- **Compatibility: Query Monitor.** The Query Monitor plugin was reporting false-positive errors indicating that many Comet Cache methods did not exist. This was due to how the Comet Cache codebase was utilizing PHP Closures, which Query Monitor had a hard time handling. The codebase has been refactored to use PHP Traits instead of Closures and now the Query Monitor plugin has no problem recognizing Comet Cache methods. Props to @NoahjChampion for reporting. See [Issue #686](https://github.com/websharks/comet-cache/issues/686).
|
354 |
+
- **Compatibility: WP-CLI.** When installing Comet Cache via WP-CLI, Comet Cache is now automatically enabled. There's no need to manually enable Comet Cache from within the plugin options after installing. Props @jaswsinc. See [Issue #464](https://github.com/websharks/comet-cache/issues/464).
|
355 |
+
- **Required WordPress Version is now v4.2.** The minimum required WordPress version has been bumped from v4.1 to v4.2. See [Issue #706](https://github.com/websharks/comet-cache/issues/706).
|
356 |
+
|
357 |
= v160227 =
|
358 |
|
359 |
- **Bug Fix**: Fixed a ZenCache Backwards Compatibility bug that was preventing calls to `$GLOBALS['zencache']` from working properly with Comet Cache. See [Issue #689](https://github.com/websharks/comet-cache/issues/689)
|
374 |
- **Bug Fix (Multisite)**: Fixed a bug where when Comet Cache was Network Activated the plugin settings link would show up in the plugins list for the Main Site and would lead to a 404 error. The settings link is now only shown when viewing the plugins list from the Network Admin. Props @jaswsinc. See [Issue #675](https://github.com/websharks/zencache/issues/675).
|
375 |
- **Enhancement**: Added support-related links to the plugin options page. Props @renzms. See [Issue #612](https://github.com/websharks/zencache/issues/612#issuecomment-186827661).
|
376 |
|
377 |
+
For older Changelog entries going back to 2009, please see the `CHANGELOG.md` file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/client-s/css/admin-bar.min.css
CHANGED
@@ -1,2 +1,2 @@
|
|
1 |
|
2 |
-
|
1 |
|
2 |
+
|
src/client-s/css/menu-pages.min.css
CHANGED
@@ -1,2 +1,2 @@
|
|
1 |
@font-face{font-family:sharkicons;src:url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.eot?v160221");src:url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.eot?#iefix&v160221") format("embedded-opentype"),url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.ttf?v160221") format("truetype"),url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.woff?v160221") format("woff"),url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.svg?v160221#sharkicons") format("svg");font-weight:normal;font-style:normal}.si::before{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none}.si-broom::before{content:""}.si-comment-mail-one::before{content:""}.si-comment-mail::before{content:""}.si-s2member::before{content:""}.si-websharks::before{content:""}.si-wp-kb-articles::before{content:""}.si-zencache-logo::before{content:""}.si-zencache::before{content:""}.si-wp-sharks::before{content:""}.si-wp-sharks-fin::before{content:""}.si-comet-cache::before{content:""}.si-comet-cache-logo::before{content:""}.si-comet-cache-comet::before{content:""}.si-feat-watch::before{content:""}.si-feat-server::before{content:""}.si-feat-layers::before{content:""}.si-feat-box::before{content:""}.si-feat-ellipsis::before{content:""}.si-typi-group::before{content:""}.si-enty-bookmark::before{content:""}.si-enty-bookmarks::before{content:""}.si-enty-open-book::before{content:""}.si-enty-archive::before{content:""}.si-enty-area-graph::before{content:""}.si-enty-bucket::before{content:""}.si-enty-colors::before{content:""}.si-enty-copy::before{content:""}.si-enty-drive::before{content:""}.si-enty-feather::before{content:""}.si-enty-gauge::before{content:""}.si-enty-hand::before{content:""}.si-enty-lab-flask::before{content:""}.si-enty-mask::before{content:""}.si-enty-medal::before{content:""}.si-enty-exclamation::before{content:""}.si-enty-palette::before{content:""}.si-enty-ruler::before{content:""}.si-enty-shop::before{content:""}.si-enty-basket::before{content:""}.si-enty-cart::before{content:""}.si-enty-traffic-cone::before{content:""}.si-enty-tree::before{content:""}.si-enty-trophy::before{content:""}.si-enty-v-card::before{content:""}.si-enty-google-hangouts::before{content:""}.si-eleg-line-graph::before{content:""}.si-eleg-male::before{content:""}.si-eleg-female::before{content:""}.si-eleg-atom::before{content:""}.si-broc-cart::before{content:""}.si-broc-crap::before{content:""}.si-broc-atom::before{content:""}.si-icom-headphones::before{content:""}.si-icom-barcode::before{content:""}.si-icom-user::before{content:""}.si-icom-users::before{content:""}.si-icom-user-plus::before{content:""}.si-icom-user-minus::before{content:""}.si-icom-user-check::before{content:""}.si-icom-user-tie::before{content:""}.si-icom-key::before{content:""}.si-icom-key2::before{content:""}.si-icom-happy::before{content:""}.si-icom-happy2::before{content:""}.si-icom-smile::before{content:""}.si-icom-smile2::before{content:""}.si-icom-tongue::before{content:""}.si-icom-tongue2::before{content:""}.si-icom-sad::before{content:""}.si-icom-sad2::before{content:""}.si-icom-wink::before{content:""}.si-icom-wink2::before{content:""}.si-icom-grin::before{content:""}.si-icom-grin2::before{content:""}.si-icom-cool::before{content:""}.si-icom-cool2::before{content:""}.si-icom-angry::before{content:""}.si-icom-angry2::before{content:""}.si-icom-evil::before{content:""}.si-icom-evil2::before{content:""}.si-icom-shocked::before{content:""}.si-icom-shocked2::before{content:""}.si-icom-baffled::before{content:""}.si-icom-baffled2::before{content:""}.si-icom-confused::before{content:""}.si-icom-confused2::before{content:""}.si-icom-neutral::before{content:""}.si-icom-neutral2::before{content:""}.si-icom-hipster::before{content:""}.si-icom-hipster2::before{content:""}.si-icom-wondering::before{content:""}.si-icom-wondering2::before{content:""}.si-icom-sleepy::before{content:""}.si-icom-sleepy2::before{content:""}.si-icom-frustrated::before{content:""}.si-icom-frustrated2::before{content:""}.si-icom-crying::before{content:""}.si-icom-crying2::before{content:""}.si-icom-spell-check::before{content:""}.si-icom-command-key::before{content:""}.si-icom-shift-key::before{content:""}.si-icom-control-key::before{content:""}.si-icom-option-key::before{content:""}.si-icom-wordpress::before{content:""}.si-icom-wordpress-square::before{content:""}.si-icom-yahoo::before{content:""}.si-icom-linux::before{content:""}.si-icom-finder::before{content:""}.si-icom-android::before{content:""}.si-icom-reddit::before{content:""}.si-icom-paypal::before{content:""}.si-icom-git::before{content:""}.si-octi-alignment-align::before{content:""}.si-octi-alignment-aligned-to::before{content:""}.si-octi-alignment-unalign::before{content:""}.si-octi-bookmark::before{content:""}.si-octi-broadcast::before{content:""}.si-octi-browser::before{content:""}.si-octi-checklist::before{content:""}.si-octi-circuit-board::before{content:""}.si-octi-clippy::before{content:""}.si-octi-cloud-download::before{content:""}.si-octi-cloud-upload::before{content:""}.si-octi-comment::before{content:""}.si-octi-comments::before{content:""}.si-octi-tach::before{content:""}.si-octi-device-camera::before{content:""}.si-octi-device-camera-video::before{content:""}.si-octi-device-desktop::before{content:""}.si-octi-diff::before{content:""}.si-octi-file-binary::before{content:""}.si-octi-file-media::before{content:""}.si-octi-file-submodule::before{content:""}.si-octi-file-symlink-directory::before{content:""}.si-octi-file-symlink-file::before{content:""}.si-octi-fold::before{content:""}.si-octi-git-branch::before{content:""}.si-octi-git-commit::before{content:""}.si-octi-git-compare::before{content:""}.si-octi-git-merge::before{content:""}.si-octi-git-pull-request::before{content:""}.si-octi-graph::before{content:""}.si-octi-home::before{content:""}.si-octi-horizontal-rule::before{content:""}.si-octi-key::before{content:""}.si-octi-light-bulb::before{content:""}.si-octi-link-external::before{content:""}.si-octi-lock::before{content:""}.si-octi-markdown::before{content:""}.si-octi-microscope::before{content:""}.si-octi-mirror::before{content:""}.si-octi-move-down::before{content:""}.si-octi-move-left::before{content:""}.si-octi-move-right::before{content:""}.si-octi-move-up::before{content:""}.si-octi-mute::before{content:""}.si-octi-organization::before{content:""}.si-octi-package::before{content:""}.si-octi-paintcan::before{content:""}.si-octi-person::before{content:""}.si-octi-plug::before{content:""}.si-octi-podium::before{content:""}.si-octi-pulse::before{content:""}.si-octi-puzzle::before{content:""}.si-octi-repo::before{content:""}.si-octi-repo-clone::before{content:""}.si-octi-repo-force-push::before{content:""}.si-octi-repo-forked::before{content:""}.si-octi-repo-pull::before{content:""}.si-octi-repo-push::before{content:""}.si-octi-rocket::before{content:""}.si-octi-ruby::before{content:""}.si-octi-screen-full::before{content:""}.si-octi-screen-normal::before{content:""}.si-octi-sign-in::before{content:""}.si-octi-sign-out::before{content:""}.si-octi-split::before{content:""}.si-octi-squirrel::before{content:""}.si-octi-steps::before{content:""}.si-octi-tag::before{content:""}.si-octi-telescope::before{content:""}.si-octi-terminal::before{content:""}.si-octi-unfold::before{content:""}.si-octi-versions::before{content:""}.si-glass::before{content:""}.si-music::before{content:""}.si-search::before{content:""}.si-envelope-o::before{content:""}.si-heart::before{content:""}.si-star::before{content:""}.si-star-o::before{content:""}.si-user::before{content:""}.si-film::before{content:""}.si-th-large::before{content:""}.si-th::before{content:""}.si-th-list::before{content:""}.si-check::before{content:""}.si-close::before{content:""}.si-search-plus::before{content:""}.si-search-minus::before{content:""}.si-power-off::before{content:""}.si-signal::before{content:""}.si-cog::before{content:""}.si-trash-o::before{content:""}.si-home::before{content:""}.si-file-o::before{content:""}.si-clock-o::before{content:""}.si-road::before{content:""}.si-download::before{content:""}.si-arrow-circle-o-down::before{content:""}.si-arrow-circle-o-up::before{content:""}.si-inbox::before{content:""}.si-play-circle-o::before{content:""}.si-repeat::before{content:""}.si-refresh::before{content:""}.si-list-alt::before{content:""}.si-lock::before{content:""}.si-flag::before{content:""}.si-headphones::before{content:""}.si-volume-off::before{content:""}.si-volume-down::before{content:""}.si-volume-up::before{content:""}.si-qrcode::before{content:""}.si-barcode::before{content:""}.si-tag::before{content:""}.si-tags::before{content:""}.si-book::before{content:""}.si-bookmark::before{content:""}.si-print::before{content:""}.si-camera::before{content:""}.si-font::before{content:""}.si-bold::before{content:""}.si-italic::before{content:""}.si-text-height::before{content:""}.si-text-width::before{content:""}.si-align-left::before{content:""}.si-align-center::before{content:""}.si-align-right::before{content:""}.si-align-justify::before{content:""}.si-list::before{content:""}.si-dedent::before{content:""}.si-indent::before{content:""}.si-video-camera::before{content:""}.si-image::before{content:""}.si-pencil::before{content:""}.si-map-marker::before{content:""}.si-adjust::before{content:""}.si-tint::before{content:""}.si-edit::before{content:""}.si-share-square-o::before{content:""}.si-check-square-o::before{content:""}.si-arrows::before{content:""}.si-step-backward::before{content:""}.si-fast-backward::before{content:""}.si-backward::before{content:""}.si-play::before{content:""}.si-pause::before{content:""}.si-stop::before{content:""}.si-forward::before{content:""}.si-fast-forward::before{content:""}.si-step-forward::before{content:""}.si-eject::before{content:""}.si-chevron-left::before{content:""}.si-chevron-right::before{content:""}.si-plus-circle::before{content:""}.si-minus-circle::before{content:""}.si-times-circle::before{content:""}.si-check-circle::before{content:""}.si-question-circle::before{content:""}.si-info-circle::before{content:""}.si-crosshairs::before{content:""}.si-times-circle-o::before{content:""}.si-check-circle-o::before{content:""}.si-ban::before{content:""}.si-arrow-left::before{content:""}.si-arrow-right::before{content:""}.si-arrow-up::before{content:""}.si-arrow-down::before{content:""}.si-mail-forward::before{content:""}.si-expand::before{content:""}.si-compress::before{content:""}.si-plus::before{content:""}.si-minus::before{content:""}.si-asterisk::before{content:""}.si-exclamation-circle::before{content:""}.si-gift::before{content:""}.si-leaf::before{content:""}.si-fire::before{content:""}.si-eye::before{content:""}.si-eye-slash::before{content:""}.si-exclamation-triangle::before{content:""}.si-plane::before{content:""}.si-calendar::before{content:""}.si-random::before{content:""}.si-comment::before{content:""}.si-magnet::before{content:""}.si-chevron-up::before{content:""}.si-chevron-down::before{content:""}.si-retweet::before{content:""}.si-shopping-cart::before{content:""}.si-folder::before{content:""}.si-folder-open::before{content:""}.si-arrows-v::before{content:""}.si-arrows-h::before{content:""}.si-bar-chart::before{content:""}.si-twitter-square::before{content:""}.si-facebook-square::before{content:""}.si-camera-retro::before{content:""}.si-key::before{content:""}.si-cogs::before{content:""}.si-comments::before{content:""}.si-thumbs-o-up::before{content:""}.si-thumbs-o-down::before{content:""}.si-star-half::before{content:""}.si-heart-o::before{content:""}.si-sign-out::before{content:""}.si-linkedin-square::before{content:""}.si-thumb-tack::before{content:""}.si-external-link::before{content:""}.si-sign-in::before{content:""}.si-trophy::before{content:""}.si-github-square::before{content:""}.si-upload::before{content:""}.si-lemon-o::before{content:""}.si-phone::before{content:""}.si-square-o::before{content:""}.si-bookmark-o::before{content:""}.si-phone-square::before{content:""}.si-twitter::before{content:""}.si-facebook::before{content:""}.si-github::before{content:""}.si-unlock::before{content:""}.si-credit-card::before{content:""}.si-feed::before{content:""}.si-hdd-o::before{content:""}.si-bullhorn::before{content:""}.si-bell-o::before{content:""}.si-certificate::before{content:""}.si-hand-o-right::before{content:""}.si-hand-o-left::before{content:""}.si-hand-o-up::before{content:""}.si-hand-o-down::before{content:""}.si-arrow-circle-left::before{content:""}.si-arrow-circle-right::before{content:""}.si-arrow-circle-up::before{content:""}.si-arrow-circle-down::before{content:""}.si-globe::before{content:""}.si-wrench::before{content:""}.si-tasks::before{content:""}.si-filter::before{content:""}.si-briefcase::before{content:""}.si-arrows-alt::before{content:""}.si-group::before{content:""}.si-chain::before{content:""}.si-cloud::before{content:""}.si-flask::before{content:""}.si-cut::before{content:""}.si-copy::before{content:""}.si-paperclip::before{content:""}.si-floppy-o::before{content:""}.si-square::before{content:""}.si-bars::before{content:""}.si-list-ul::before{content:""}.si-list-ol::before{content:""}.si-strikethrough::before{content:""}.si-underline::before{content:""}.si-table::before{content:""}.si-magic::before{content:""}.si-truck::before{content:""}.si-pinterest::before{content:""}.si-pinterest-square::before{content:""}.si-google-plus-square::before{content:""}.si-google-plus::before{content:""}.si-money::before{content:""}.si-caret-down::before{content:""}.si-caret-up::before{content:""}.si-caret-left::before{content:""}.si-caret-right::before{content:""}.si-columns::before{content:""}.si-sort::before{content:""}.si-sort-desc::before{content:""}.si-sort-asc::before{content:""}.si-envelope::before{content:""}.si-linkedin::before{content:""}.si-rotate-left::before{content:""}.si-gavel::before{content:""}.si-dashboard::before{content:""}.si-comment-o::before{content:""}.si-comments-o::before{content:""}.si-bolt::before{content:""}.si-sitemap::before{content:""}.si-umbrella::before{content:""}.si-clipboard::before{content:""}.si-lightbulb-o::before{content:""}.si-exchange::before{content:""}.si-cloud-download::before{content:""}.si-cloud-upload::before{content:""}.si-user-md::before{content:""}.si-stethoscope::before{content:""}.si-suitcase::before{content:""}.si-bell::before{content:""}.si-coffee::before{content:""}.si-cutlery::before{content:""}.si-file-text-o::before{content:""}.si-building-o::before{content:""}.si-hospital-o::before{content:""}.si-ambulance::before{content:""}.si-medkit::before{content:""}.si-fighter-jet::before{content:""}.si-beer::before{content:""}.si-h-square::before{content:""}.si-plus-square::before{content:""}.si-angle-double-left::before{content:""}.si-angle-double-right::before{content:""}.si-angle-double-up::before{content:""}.si-angle-double-down::before{content:""}.si-angle-left::before{content:""}.si-angle-right::before{content:""}.si-angle-up::before{content:""}.si-angle-down::before{content:""}.si-desktop::before{content:""}.si-laptop::before{content:""}.si-tablet::before{content:""}.si-mobile::before{content:""}.si-circle-o::before{content:""}.si-quote-left::before{content:""}.si-quote-right::before{content:""}.si-spinner::before{content:""}.si-circle::before{content:""}.si-mail-reply::before{content:""}.si-github-alt::before{content:""}.si-folder-o::before{content:""}.si-folder-open-o::before{content:""}.si-smile-o::before{content:""}.si-frown-o::before{content:""}.si-meh-o::before{content:""}.si-gamepad::before{content:""}.si-keyboard-o::before{content:""}.si-flag-o::before{content:""}.si-flag-checkered::before{content:""}.si-terminal::before{content:""}.si-code::before{content:""}.si-mail-reply-all::before{content:""}.si-star-half-empty::before{content:""}.si-location-arrow::before{content:""}.si-crop::before{content:""}.si-code-fork::before{content:""}.si-chain-broken::before{content:""}.si-question::before{content:""}.si-info::before{content:""}.si-exclamation::before{content:""}.si-superscript::before{content:""}.si-subscript::before{content:""}.si-eraser::before{content:""}.si-puzzle-piece::before{content:""}.si-microphone::before{content:""}.si-microphone-slash::before{content:""}.si-shield::before{content:""}.si-calendar-o::before{content:""}.si-fire-extinguisher::before{content:""}.si-rocket::before{content:""}.si-maxcdn::before{content:""}.si-chevron-circle-left::before{content:""}.si-chevron-circle-right::before{content:""}.si-chevron-circle-up::before{content:""}.si-chevron-circle-down::before{content:""}.si-html5::before{content:""}.si-css3::before{content:""}.si-anchor::before{content:""}.si-unlock-alt::before{content:""}.si-bullseye::before{content:""}.si-ellipsis-h::before{content:""}.si-ellipsis-v::before{content:""}.si-rss-square::before{content:""}.si-play-circle::before{content:""}.si-ticket::before{content:""}.si-minus-square::before{content:""}.si-minus-square-o::before{content:""}.si-level-up::before{content:""}.si-level-down::before{content:""}.si-check-square::before{content:""}.si-pencil-square::before{content:""}.si-external-link-square::before{content:""}.si-share-square::before{content:""}.si-compass::before{content:""}.si-caret-square-o-down::before{content:""}.si-caret-square-o-up::before{content:""}.si-caret-square-o-right::before{content:""}.si-eur::before{content:""}.si-gbp::before{content:""}.si-dollar::before{content:""}.si-inr::before{content:""}.si-cny::before{content:""}.si-rouble::before{content:""}.si-krw::before{content:""}.si-bitcoin::before{content:""}.si-file::before{content:""}.si-file-text::before{content:""}.si-sort-alpha-asc::before{content:""}.si-sort-alpha-desc::before{content:""}.si-sort-amount-asc::before{content:""}.si-sort-amount-desc::before{content:""}.si-sort-numeric-asc::before{content:""}.si-sort-numeric-desc::before{content:""}.si-thumbs-up::before{content:""}.si-thumbs-down::before{content:""}.si-youtube-square::before{content:""}.si-youtube::before{content:""}.si-xing::before{content:""}.si-xing-square::before{content:""}.si-youtube-play::before{content:""}.si-dropbox::before{content:""}.si-stack-overflow::before{content:""}.si-instagram::before{content:""}.si-flickr::before{content:""}.si-adn::before{content:""}.si-bitbucket::before{content:""}.si-bitbucket-square::before{content:""}.si-tumblr::before{content:""}.si-tumblr-square::before{content:""}.si-long-arrow-down::before{content:""}.si-long-arrow-up::before{content:""}.si-long-arrow-left::before{content:""}.si-long-arrow-right::before{content:""}.si-apple::before{content:""}.si-windows::before{content:""}.si-android::before{content:""}.si-linux::before{content:""}.si-dribbble::before{content:""}.si-skype::before{content:""}.si-foursquare::before{content:""}.si-trello::before{content:""}.si-female::before{content:""}.si-male::before{content:""}.si-gittip::before{content:""}.si-sun-o::before{content:""}.si-moon-o::before{content:""}.si-archive::before{content:""}.si-bug::before{content:""}.si-vk::before{content:""}.si-weibo::before{content:""}.si-renren::before{content:""}.si-pagelines::before{content:""}.si-stack-exchange::before{content:""}.si-arrow-circle-o-right::before{content:""}.si-arrow-circle-o-left::before{content:""}.si-caret-square-o-left::before{content:""}.si-dot-circle-o::before{content:""}.si-wheelchair::before{content:""}.si-vimeo-square::before{content:""}.si-try::before{content:""}.si-plus-square-o::before{content:""}.si-space-shuttle::before{content:""}.si-slack::before{content:""}.si-envelope-square::before{content:""}.si-wordpress::before{content:""}.si-openid::before{content:""}.si-bank::before{content:""}.si-graduation-cap::before{content:""}.si-yahoo::before{content:""}.si-google::before{content:""}.si-reddit::before{content:""}.si-reddit-square::before{content:""}.si-stumbleupon-circle::before{content:""}.si-stumbleupon::before{content:""}.si-delicious::before{content:""}.si-digg::before{content:""}.si-pied-piper::before{content:""}.si-pied-piper-alt::before{content:""}.si-drupal::before{content:""}.si-joomla::before{content:""}.si-language::before{content:""}.si-fax::before{content:""}.si-building::before{content:""}.si-child::before{content:""}.si-paw::before{content:""}.si-spoon::before{content:""}.si-cube::before{content:""}.si-cubes::before{content:""}.si-behance::before{content:""}.si-behance-square::before{content:""}.si-steam::before{content:""}.si-steam-square::before{content:""}.si-recycle::before{content:""}.si-automobile::before{content:""}.si-cab::before{content:""}.si-tree::before{content:""}.si-spotify::before{content:""}.si-deviantart::before{content:""}.si-soundcloud::before{content:""}.si-database::before{content:""}.si-file-pdf-o::before{content:""}.si-file-word-o::before{content:""}.si-file-excel-o::before{content:""}.si-file-powerpoint-o::before{content:""}.si-file-image-o::before{content:""}.si-file-archive-o::before{content:""}.si-file-audio-o::before{content:""}.si-file-movie-o::before{content:""}.si-file-code-o::before{content:""}.si-vine::before{content:""}.si-codepen::before{content:""}.si-jsfiddle::before{content:""}.si-life-bouy::before{content:""}.si-circle-o-notch::before{content:""}.si-ra::before{content:""}.si-empire::before{content:""}.si-git-square::before{content:""}.si-git::before{content:""}.si-hacker-news::before{content:""}.si-tencent-weibo::before{content:""}.si-qq::before{content:""}.si-wechat::before{content:""}.si-paper-plane::before{content:""}.si-paper-plane-o::before{content:""}.si-history::before{content:""}.si-circle-thin::before{content:""}.si-header::before{content:""}.si-paragraph::before{content:""}.si-sliders::before{content:""}.si-share-alt::before{content:""}.si-share-alt-square::before{content:""}.si-bomb::before{content:""}.si-futbol-o::before{content:""}.si-tty::before{content:""}.si-binoculars::before{content:""}.si-plug::before{content:""}.si-slideshare::before{content:""}.si-twitch::before{content:""}.si-yelp::before{content:""}.si-newspaper-o::before{content:""}.si-wifi::before{content:""}.si-calculator::before{content:""}.si-paypal::before{content:""}.si-google-wallet::before{content:""}.si-cc-visa::before{content:""}.si-cc-mastercard::before{content:""}.si-cc-discover::before{content:""}.si-cc-amex::before{content:""}.si-cc-paypal::before{content:""}.si-cc-stripe::before{content:""}.si-bell-slash::before{content:""}.si-bell-slash-o::before{content:""}.si-trash::before{content:""}.si-copyright::before{content:""}.si-at::before{content:""}.si-eyedropper::before{content:""}.si-paint-brush::before{content:""}.si-birthday-cake::before{content:""}.si-area-chart::before{content:""}.si-pie-chart::before{content:""}.si-line-chart::before{content:""}.si-lastfm::before{content:""}.si-lastfm-square::before{content:""}.si-toggle-off::before{content:""}.si-toggle-on::before{content:""}.si-bicycle::before{content:""}.si-bus::before{content:""}.si-ioxhost::before{content:""}.si-angellist::before{content:""}.si-cc::before{content:""}.si-ils::before{content:""}.si-meanpath::before{content:""}.si-buysellads::before{content:""}.si-connectdevelop::before{content:""}.si-dashcube::before{content:""}.si-forumbee::before{content:""}.si-leanpub::before{content:""}.si-sellsy::before{content:""}.si-shirtsinbulk::before{content:""}.si-simplybuilt::before{content:""}.si-skyatlas::before{content:""}.si-cart-plus::before{content:""}.si-cart-arrow-down::before{content:""}.si-diamond::before{content:""}.si-ship::before{content:""}.si-user-secret::before{content:""}.si-motorcycle::before{content:""}.si-street-view::before{content:""}.si-heartbeat::before{content:""}.si-venus::before{content:""}.si-mars::before{content:""}.si-mercury::before{content:""}.si-intersex::before{content:""}.si-transgender-alt::before{content:""}.si-venus-double::before{content:""}.si-mars-double::before{content:""}.si-venus-mars::before{content:""}.si-mars-stroke::before{content:""}.si-mars-stroke-v::before{content:""}.si-mars-stroke-h::before{content:""}.si-neuter::before{content:""}.si-genderless::before{content:""}.si-facebook-official::before{content:""}.si-pinterest-p::before{content:""}.si-whatsapp::before{content:""}.si-server::before{content:""}.si-user-plus::before{content:""}.si-user-times::before{content:""}.si-bed::before{content:""}.si-viacoin::before{content:""}.si-train::before{content:""}.si-subway::before{content:""}.si-medium::before{content:""}.si-y-combinator::before{content:""}.si-optin-monster::before{content:""}.si-opencart::before{content:""}.si-expeditedssl::before{content:""}.si-battery-4::before{content:""}.si-battery-3::before{content:""}.si-battery-2::before{content:""}.si-battery-1::before{content:""}.si-battery-0::before{content:""}.si-mouse-pointer::before{content:""}.si-i-cursor::before{content:""}.si-object-group::before{content:""}.si-object-ungroup::before{content:""}.si-sticky-note::before{content:""}.si-sticky-note-o::before{content:""}.si-cc-jcb::before{content:""}.si-cc-diners-club::before{content:""}.si-clone::before{content:""}.si-balance-scale::before{content:""}.si-hourglass-o::before{content:""}.si-hourglass-1::before{content:""}.si-hourglass-2::before{content:""}.si-hourglass-3::before{content:""}.si-hourglass::before{content:""}.si-hand-grab-o::before{content:""}.si-hand-paper-o::before{content:""}.si-hand-scissors-o::before{content:""}.si-hand-lizard-o::before{content:""}.si-hand-spock-o::before{content:""}.si-hand-pointer-o::before{content:""}.si-hand-peace-o::before{content:""}.si-trademark::before{content:""}.si-registered::before{content:""}.si-creative-commons::before{content:""}.si-gg::before{content:""}.si-gg-circle::before{content:""}.si-tripadvisor::before{content:""}.si-odnoklassniki::before{content:""}.si-odnoklassniki-square::before{content:""}.si-get-pocket::before{content:""}.si-wikipedia-w::before{content:""}.si-safari::before{content:""}.si-chrome::before{content:""}.si-firefox::before{content:""}.si-opera::before{content:""}.si-internet-explorer::before{content:""}.si-television::before{content:""}.si-contao::before{content:""}.si-500px::before{content:""}.si-amazon::before{content:""}.si-calendar-plus-o::before{content:""}.si-calendar-minus-o::before{content:""}.si-calendar-times-o::before{content:""}.si-calendar-check-o::before{content:""}.si-industry::before{content:""}.si-map-pin::before{content:""}.si-map-signs::before{content:""}.si-map-o::before{content:""}.si-map::before{content:""}.si-commenting::before{content:""}.si-commenting-o::before{content:""}.si-houzz::before{content:""}.si-vimeo::before{content:""}.si-black-tie::before{content:""}.si-fonticons::before{content:""}.si-lg{font-size:1.33333333em;line-height:0.75em;vertical-align:-15%}.si-2x{font-size:2em}.si-3x{font-size:3em}.si-4x{font-size:4em}.si-5x{font-size:5em}.si-fw{text-align:center;width:1.28571429em}.si-border{border-radius:.1em;padding:.2em .25em .15em;border:solid 0.08em}.si-pull-left{float:left;margin-right:.3em}.si-pull-right{float:right;margin-left:.3em}.si-rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.si-rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.si-rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.si-flip-horizontal{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.si-flip-vertical{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.si-inverse{-webkit-filter:invert(100%);filter:invert(100%)}.si-spin{-webkit-animation:si-animation-spin 2s infinite linear;-moz-animation:si-animation-spin 2s infinite linear;animation:si-animation-spin 2s infinite linear}.si-pulse{-webkit-animation:si-animation-spin 1s infinite steps(8);-moz-animation:si-animation-spin 1s infinite steps(8);animation:si-animation-spin 1s infinite steps(8)}.si-ul{padding-left:0;list-style-type:none;margin-left:2.14285714em}.si-ul>li{position:relative}.si-ul>li .si-li{text-align:center;position:absolute;left:-2.14285714em;width:2.14285714em;top:0.14285714em}.si-ul>li .si-li .si-lg{left:-1.85714286em}.si-stack{width:2em;height:2em;line-height:2em;vertical-align:middle;position:relative;display:inline-block}.si-stack .si-stack-1x,.si-stack .si-stack-2x{left:0;width:100%;text-align:center;position:absolute}.si-stack .si-stack-1x{line-height:inherit}.si-stack .si-stack-2x{font-size:2em}@-webkit-keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-moz-keyframes si-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}.plugin-menu-page-animation-spin{-webkit-animation-duration:0.75s;-moz-animation-duration:0.75s;animation-duration:0.75s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:linear;-moz-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:plugin-menu-page-animation-spin;-moz-animation-name:plugin-menu-page-animation-spin;animation-name:plugin-menu-page-animation-spin}@-webkit-keyframes plugin-menu-page-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@-moz-keyframes plugin-menu-page-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(360deg)}}@keyframes plugin-menu-page-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-ms-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}html{overflow-y:scroll}#wpwrap{position:relative}#wpwrap::after{top:0;right:0;bottom:0;left:0;z-index:-1;position:absolute;content:'';opacity:0.25;background:url("../images/bg.png")}#wpwrap .updated,#wpwrap .error{margin:1.25em 1.25em 1.25em 0.25em}.plugin-menu-page{min-width:800px;margin:1.25em 1.25em 1.25em 0.25em}.plugin-menu-page,.plugin-menu-page p{font-size:14px}.plugin-menu-page a{color:#033A63}.plugin-menu-page a:hover,.plugin-menu-page a:active{color:#467629}.plugin-menu-page p:first-child,.plugin-menu-page pre:first-child{margin-top:0}.plugin-menu-page p:last-child,.plugin-menu-page pre:last-child{margin-bottom:0}.plugin-menu-page code{border-radius:3px;padding:0.1em 0.25em;background:rgba(178,178,178,0.25);font-family:'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace}.plugin-menu-page pre.code{padding:0;background:none}.plugin-menu-page pre.code>code{font-size:90%;overflow-x:auto;max-width:100%;border-radius:4px;padding:1em;display:block;color:#eee;background:#222;box-shadow:0 0 5px 1px #000 inset}.plugin-menu-page img{border:0}.plugin-menu-page img.screenshot{float:right;border-radius:4px;padding:0.5em;margin:0 0 2em 2em;background:#fff;border:1px solid #afafaf;box-shadow:0 0 5px 0 rgba(0,0,0,0.2) inset}.plugin-menu-page hr{border:0;padding:0;height:1px;margin:1em 0;background:linear-gradient(to left, transparent, rgba(0,0,0,0.75), transparent)}.plugin-menu-page label{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.plugin-menu-page label.switch-primary{font-size:130%;margin:0;padding:0.5em;border-radius:4px;display:inline;color:#000;background:#f1e982;border:1px solid rgba(0,0,0,0.07);box-shadow:-1px -1px 0 0 rgba(0,0,0,0.25) inset,1px 1px 0 0 #fff inset}.plugin-menu-page select,.plugin-menu-page textarea,.plugin-menu-page select:focus,.plugin-menu-page textarea:focus,.plugin-menu-page input:not([type='radio']):not([type='checkbox']),.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus{width:100%;line-height:1.3em;margin:0;padding:0.25em 0.5em;border-radius:4px;box-sizing:border-box;color:#333;background:#e8e8e8;border:1px solid #848484;box-shadow:0 0 2px 0 rgba(132,132,132,0.5) inset}.plugin-menu-page select,.plugin-menu-page select:focus{box-shadow:0 1px 0 0 #fff inset,0 -2px 3px 0 rgba(132,132,132,0.25) inset}.plugin-menu-page select,.plugin-menu-page select:focus,.plugin-menu-page input:not([type='radio']):not([type='checkbox']),.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus{height:2em}.plugin-menu-page select:focus,.plugin-menu-page textarea:focus,.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus{color:#000;background:#e2e2e2}.plugin-menu-page input[disabled],.plugin-menu-page select[disabled],.plugin-menu-page textarea[disabled]{opacity:0.5}.plugin-menu-page input::-webkit-input-placeholder,.plugin-menu-page textarea::-webkit-input-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input::-moz-placeholder,.plugin-menu-page textarea::-moz-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input:-moz-placeholder,.plugin-menu-page textarea:-moz-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input:-ms-input-placeholder,.plugin-menu-page textarea:-ms-input-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page table{margin:1em 0}.plugin-menu-page button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:150%;font-weight:bold;line-height:1em;outline:none;cursor:pointer;border-radius:4px;margin:0;padding:0.25em 0.5em;box-sizing:border-box;color:#fff;background:#033A63;border:1px solid rgba(0,0,0,0.5);box-shadow:0 1px 1px 0 rgba(0,0,0,0.25),-1px -1px 0 0 rgba(0,0,0,0.2) inset,1px 1px 0 0 rgba(255,255,255,0.1) inset}.plugin-menu-page button:hover{background:#467629}.plugin-menu-page button[type='submit']{background:#467629}.plugin-menu-page button[type='submit']:hover{background:#033A63}.plugin-menu-page button:active{-webkit-transform:scale(0.98, 0.98);-moz-transform:scale(0.98, 0.98);-ms-transform:scale(0.98, 0.98);-o-transform:scale(0.98, 0.98);transform:scale(0.98, 0.98)}.plugin-menu-page .info,.plugin-menu-page .notice,.plugin-menu-page .warning,.plugin-menu-page .error{border-radius:4px;padding:0.5em;margin:1em 0}.plugin-menu-page .info{background:#cadfed;border:1px solid #216095}.plugin-menu-page .notice{background:#fffde8;border:1px solid #e6db55}.plugin-menu-page .warning{background:#ffefd3;border:1px solid #e6db55}.plugin-menu-page .error{background:pink;border:1px solid #711e1e}.plugin-menu-page .monospace{font-family:'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace}.plugin-menu-page textarea.monospace{white-space:pre}.plugin-menu-page .clearfix::before,.plugin-menu-page .clearfix::after{display:table;content:' '}.plugin-menu-page .clearfix::after{clear:both}.plugin-menu-page-heading .plugin-menu-page-restore-defaults,.plugin-menu-page-heading .plugin-menu-page-panel-togglers{float:right;margin:0 1em 0 0}.plugin-menu-page-heading .plugin-menu-page-panel-togglers button{background:#033A63 !important}.plugin-menu-page-heading .plugin-menu-page-upsells{float:right;clear:right;text-align:right;max-width:350px;margin:1em 0 0}.plugin-menu-page-heading .plugin-menu-page-upsells a{text-decoration:none;line-height:1.5em;margin:0 0.5em;display:inline-block}.plugin-menu-page-heading .plugin-menu-page-support-links,.plugin-menu-page-heading .plugin-menu-page-mailing-list-links{float:right;clear:right;text-align:right;max-width:400px;margin:.5em 0 0}.plugin-menu-page-heading .plugin-menu-page-support-links a,.plugin-menu-page-heading .plugin-menu-page-mailing-list-links a{text-decoration:none;margin:0 0.5em;display:inline-block}.plugin-menu-page-heading .plugin-menu-page-version{float:right;clear:right;min-width:350px;margin:0.5em 0 0 0;text-align:right}.plugin-menu-page-body{position:relative}.plugin-menu-page-section-heading{margin:1em 0}.plugin-menu-page-section-heading>small{font-size:65%;font-style:italic;margin:0;display:block;opacity:0.5}.plugin-menu-page-panel{margin:1em 0}.plugin-menu-page-panel:first-child{margin-top:0}.plugin-menu-page-panel .plugin-menu-page-panel-heading{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;padding:10px;font-size:150%;line-height:1.125em;font-weight:bold;border-radius:4px;display:block;cursor:pointer;background:#033A63;background:linear-gradient(to right, #033A63, #20669A);color:#eee !important;box-shadow:0 2px 2px 0 rgba(0,0,0,0.25)}.plugin-menu-page-panel .plugin-menu-page-panel-heading::after{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none;content:""}.plugin-menu-page-panel .plugin-menu-page-panel-heading:hover,.plugin-menu-page-panel .plugin-menu-page-panel-heading.open{color:#fff !important}.plugin-menu-page-panel .plugin-menu-page-panel-heading::after{font-size:80%;float:right;margin:0 0 0 5px}.plugin-menu-page-panel .plugin-menu-page-panel-heading.open::after{content:""}.plugin-menu-page-panel-heading.pro-preview-feature{background:#216095}.pro-preview-feature::after{font-variant:small-caps !important;font-family:sans-serif !important;content:'pro version only' !important;margin-left:15px;background:#216095;color:#FFFFFF;padding:0 5px 2px 5px;font-weight:normal}.plugin-menu-page-panel-heading.pro-preview-additional-features{background:#216095}.pro-preview-additional-features::after{font-variant:small-caps !important;font-family:sans-serif !important;content:'additional pro version only features' !important;margin-left:15px;background:#216095;color:#FFFFFF;padding:0 5px 2px 5px;font-weight:normal}.plugin-menu-page-panel .plugin-menu-page-panel-heading>.si{text-align:center;width:1.28571429em;margin-right:.25em}.plugin-menu-page-panel .plugin-menu-page-panel-body{width:99%;margin:0 auto;display:none;padding:1.2em;border-bottom-left-radius:4px;border-bottom-right-radius:4px;box-sizing:border-box;color:#222;border:1px solid #848484;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,0.25),0 3px 1px -1px rgba(0,0,0,0.25) inset}.plugin-menu-page-panel .plugin-menu-page-panel-body.open{display:block}.plugin-menu-page-panel .plugin-menu-page-panel-body p{font-size:90%;color:#666}.plugin-menu-page-panel .plugin-menu-page-panel-body p.notice,.plugin-menu-page-panel .plugin-menu-page-panel-body p.info,.plugin-menu-page-panel .plugin-menu-page-panel-body p.warning,.plugin-menu-page-panel .plugin-menu-page-panel-body p.error{color:#000}.plugin-menu-page-panel .plugin-menu-page-panel-body h3{margin:0 0 0.5em}.plugin-menu-page-panel .plugin-menu-page-panel-body h3:first-child{margin-top:0}.plugin-menu-page-panel .plugin-menu-page-panel-body h3+p{margin-top:0}.plugin-menu-page-panel .plugin-menu-page-panel-body a.dotted{text-decoration:none;border-bottom:1px dotted}.plugin-menu-page-panel .plugin-menu-page-panel-body.pro-preview,.plugin-menu-page-panel .plugin-menu-page-panel-body .pro-preview{opacity:0.5}.plugin-menu-page-save{margin-top:2em}.plugin-menu-page-save button{line-height:1.3em;width:100%}
|
2 |
-
|
1 |
@font-face{font-family:sharkicons;src:url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.eot?v160221");src:url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.eot?#iefix&v160221") format("embedded-opentype"),url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.ttf?v160221") format("truetype"),url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.woff?v160221") format("woff"),url("../../vendor/websharks/sharkicons/src/fonts/sharkicons.svg?v160221#sharkicons") format("svg");font-weight:normal;font-style:normal}.si::before{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none}.si-broom::before{content:""}.si-comment-mail-one::before{content:""}.si-comment-mail::before{content:""}.si-s2member::before{content:""}.si-websharks::before{content:""}.si-wp-kb-articles::before{content:""}.si-zencache-logo::before{content:""}.si-zencache::before{content:""}.si-wp-sharks::before{content:""}.si-wp-sharks-fin::before{content:""}.si-comet-cache::before{content:""}.si-comet-cache-logo::before{content:""}.si-comet-cache-comet::before{content:""}.si-feat-watch::before{content:""}.si-feat-server::before{content:""}.si-feat-layers::before{content:""}.si-feat-box::before{content:""}.si-feat-ellipsis::before{content:""}.si-typi-group::before{content:""}.si-enty-bookmark::before{content:""}.si-enty-bookmarks::before{content:""}.si-enty-open-book::before{content:""}.si-enty-archive::before{content:""}.si-enty-area-graph::before{content:""}.si-enty-bucket::before{content:""}.si-enty-colors::before{content:""}.si-enty-copy::before{content:""}.si-enty-drive::before{content:""}.si-enty-feather::before{content:""}.si-enty-gauge::before{content:""}.si-enty-hand::before{content:""}.si-enty-lab-flask::before{content:""}.si-enty-mask::before{content:""}.si-enty-medal::before{content:""}.si-enty-exclamation::before{content:""}.si-enty-palette::before{content:""}.si-enty-ruler::before{content:""}.si-enty-shop::before{content:""}.si-enty-basket::before{content:""}.si-enty-cart::before{content:""}.si-enty-traffic-cone::before{content:""}.si-enty-tree::before{content:""}.si-enty-trophy::before{content:""}.si-enty-v-card::before{content:""}.si-enty-google-hangouts::before{content:""}.si-eleg-line-graph::before{content:""}.si-eleg-male::before{content:""}.si-eleg-female::before{content:""}.si-eleg-atom::before{content:""}.si-broc-cart::before{content:""}.si-broc-crap::before{content:""}.si-broc-atom::before{content:""}.si-icom-headphones::before{content:""}.si-icom-barcode::before{content:""}.si-icom-user::before{content:""}.si-icom-users::before{content:""}.si-icom-user-plus::before{content:""}.si-icom-user-minus::before{content:""}.si-icom-user-check::before{content:""}.si-icom-user-tie::before{content:""}.si-icom-key::before{content:""}.si-icom-key2::before{content:""}.si-icom-happy::before{content:""}.si-icom-happy2::before{content:""}.si-icom-smile::before{content:""}.si-icom-smile2::before{content:""}.si-icom-tongue::before{content:""}.si-icom-tongue2::before{content:""}.si-icom-sad::before{content:""}.si-icom-sad2::before{content:""}.si-icom-wink::before{content:""}.si-icom-wink2::before{content:""}.si-icom-grin::before{content:""}.si-icom-grin2::before{content:""}.si-icom-cool::before{content:""}.si-icom-cool2::before{content:""}.si-icom-angry::before{content:""}.si-icom-angry2::before{content:""}.si-icom-evil::before{content:""}.si-icom-evil2::before{content:""}.si-icom-shocked::before{content:""}.si-icom-shocked2::before{content:""}.si-icom-baffled::before{content:""}.si-icom-baffled2::before{content:""}.si-icom-confused::before{content:""}.si-icom-confused2::before{content:""}.si-icom-neutral::before{content:""}.si-icom-neutral2::before{content:""}.si-icom-hipster::before{content:""}.si-icom-hipster2::before{content:""}.si-icom-wondering::before{content:""}.si-icom-wondering2::before{content:""}.si-icom-sleepy::before{content:""}.si-icom-sleepy2::before{content:""}.si-icom-frustrated::before{content:""}.si-icom-frustrated2::before{content:""}.si-icom-crying::before{content:""}.si-icom-crying2::before{content:""}.si-icom-spell-check::before{content:""}.si-icom-command-key::before{content:""}.si-icom-shift-key::before{content:""}.si-icom-control-key::before{content:""}.si-icom-option-key::before{content:""}.si-icom-wordpress::before{content:""}.si-icom-wordpress-square::before{content:""}.si-icom-yahoo::before{content:""}.si-icom-linux::before{content:""}.si-icom-finder::before{content:""}.si-icom-android::before{content:""}.si-icom-reddit::before{content:""}.si-icom-paypal::before{content:""}.si-icom-git::before{content:""}.si-octi-alignment-align::before{content:""}.si-octi-alignment-aligned-to::before{content:""}.si-octi-alignment-unalign::before{content:""}.si-octi-bookmark::before{content:""}.si-octi-broadcast::before{content:""}.si-octi-browser::before{content:""}.si-octi-checklist::before{content:""}.si-octi-circuit-board::before{content:""}.si-octi-clippy::before{content:""}.si-octi-cloud-download::before{content:""}.si-octi-cloud-upload::before{content:""}.si-octi-comment::before{content:""}.si-octi-comments::before{content:""}.si-octi-tach::before{content:""}.si-octi-device-camera::before{content:""}.si-octi-device-camera-video::before{content:""}.si-octi-device-desktop::before{content:""}.si-octi-diff::before{content:""}.si-octi-file-binary::before{content:""}.si-octi-file-media::before{content:""}.si-octi-file-submodule::before{content:""}.si-octi-file-symlink-directory::before{content:""}.si-octi-file-symlink-file::before{content:""}.si-octi-fold::before{content:""}.si-octi-git-branch::before{content:""}.si-octi-git-commit::before{content:""}.si-octi-git-compare::before{content:""}.si-octi-git-merge::before{content:""}.si-octi-git-pull-request::before{content:""}.si-octi-graph::before{content:""}.si-octi-home::before{content:""}.si-octi-horizontal-rule::before{content:""}.si-octi-key::before{content:""}.si-octi-light-bulb::before{content:""}.si-octi-link-external::before{content:""}.si-octi-lock::before{content:""}.si-octi-markdown::before{content:""}.si-octi-microscope::before{content:""}.si-octi-mirror::before{content:""}.si-octi-move-down::before{content:""}.si-octi-move-left::before{content:""}.si-octi-move-right::before{content:""}.si-octi-move-up::before{content:""}.si-octi-mute::before{content:""}.si-octi-organization::before{content:""}.si-octi-package::before{content:""}.si-octi-paintcan::before{content:""}.si-octi-person::before{content:""}.si-octi-plug::before{content:""}.si-octi-podium::before{content:""}.si-octi-pulse::before{content:""}.si-octi-puzzle::before{content:""}.si-octi-repo::before{content:""}.si-octi-repo-clone::before{content:""}.si-octi-repo-force-push::before{content:""}.si-octi-repo-forked::before{content:""}.si-octi-repo-pull::before{content:""}.si-octi-repo-push::before{content:""}.si-octi-rocket::before{content:""}.si-octi-ruby::before{content:""}.si-octi-screen-full::before{content:""}.si-octi-screen-normal::before{content:""}.si-octi-sign-in::before{content:""}.si-octi-sign-out::before{content:""}.si-octi-split::before{content:""}.si-octi-squirrel::before{content:""}.si-octi-steps::before{content:""}.si-octi-tag::before{content:""}.si-octi-telescope::before{content:""}.si-octi-terminal::before{content:""}.si-octi-unfold::before{content:""}.si-octi-versions::before{content:""}.si-glass::before{content:""}.si-music::before{content:""}.si-search::before{content:""}.si-envelope-o::before{content:""}.si-heart::before{content:""}.si-star::before{content:""}.si-star-o::before{content:""}.si-user::before{content:""}.si-film::before{content:""}.si-th-large::before{content:""}.si-th::before{content:""}.si-th-list::before{content:""}.si-check::before{content:""}.si-close::before{content:""}.si-search-plus::before{content:""}.si-search-minus::before{content:""}.si-power-off::before{content:""}.si-signal::before{content:""}.si-cog::before{content:""}.si-trash-o::before{content:""}.si-home::before{content:""}.si-file-o::before{content:""}.si-clock-o::before{content:""}.si-road::before{content:""}.si-download::before{content:""}.si-arrow-circle-o-down::before{content:""}.si-arrow-circle-o-up::before{content:""}.si-inbox::before{content:""}.si-play-circle-o::before{content:""}.si-repeat::before{content:""}.si-refresh::before{content:""}.si-list-alt::before{content:""}.si-lock::before{content:""}.si-flag::before{content:""}.si-headphones::before{content:""}.si-volume-off::before{content:""}.si-volume-down::before{content:""}.si-volume-up::before{content:""}.si-qrcode::before{content:""}.si-barcode::before{content:""}.si-tag::before{content:""}.si-tags::before{content:""}.si-book::before{content:""}.si-bookmark::before{content:""}.si-print::before{content:""}.si-camera::before{content:""}.si-font::before{content:""}.si-bold::before{content:""}.si-italic::before{content:""}.si-text-height::before{content:""}.si-text-width::before{content:""}.si-align-left::before{content:""}.si-align-center::before{content:""}.si-align-right::before{content:""}.si-align-justify::before{content:""}.si-list::before{content:""}.si-dedent::before{content:""}.si-indent::before{content:""}.si-video-camera::before{content:""}.si-image::before{content:""}.si-pencil::before{content:""}.si-map-marker::before{content:""}.si-adjust::before{content:""}.si-tint::before{content:""}.si-edit::before{content:""}.si-share-square-o::before{content:""}.si-check-square-o::before{content:""}.si-arrows::before{content:""}.si-step-backward::before{content:""}.si-fast-backward::before{content:""}.si-backward::before{content:""}.si-play::before{content:""}.si-pause::before{content:""}.si-stop::before{content:""}.si-forward::before{content:""}.si-fast-forward::before{content:""}.si-step-forward::before{content:""}.si-eject::before{content:""}.si-chevron-left::before{content:""}.si-chevron-right::before{content:""}.si-plus-circle::before{content:""}.si-minus-circle::before{content:""}.si-times-circle::before{content:""}.si-check-circle::before{content:""}.si-question-circle::before{content:""}.si-info-circle::before{content:""}.si-crosshairs::before{content:""}.si-times-circle-o::before{content:""}.si-check-circle-o::before{content:""}.si-ban::before{content:""}.si-arrow-left::before{content:""}.si-arrow-right::before{content:""}.si-arrow-up::before{content:""}.si-arrow-down::before{content:""}.si-mail-forward::before{content:""}.si-expand::before{content:""}.si-compress::before{content:""}.si-plus::before{content:""}.si-minus::before{content:""}.si-asterisk::before{content:""}.si-exclamation-circle::before{content:""}.si-gift::before{content:""}.si-leaf::before{content:""}.si-fire::before{content:""}.si-eye::before{content:""}.si-eye-slash::before{content:""}.si-exclamation-triangle::before{content:""}.si-plane::before{content:""}.si-calendar::before{content:""}.si-random::before{content:""}.si-comment::before{content:""}.si-magnet::before{content:""}.si-chevron-up::before{content:""}.si-chevron-down::before{content:""}.si-retweet::before{content:""}.si-shopping-cart::before{content:""}.si-folder::before{content:""}.si-folder-open::before{content:""}.si-arrows-v::before{content:""}.si-arrows-h::before{content:""}.si-bar-chart::before{content:""}.si-twitter-square::before{content:""}.si-facebook-square::before{content:""}.si-camera-retro::before{content:""}.si-key::before{content:""}.si-cogs::before{content:""}.si-comments::before{content:""}.si-thumbs-o-up::before{content:""}.si-thumbs-o-down::before{content:""}.si-star-half::before{content:""}.si-heart-o::before{content:""}.si-sign-out::before{content:""}.si-linkedin-square::before{content:""}.si-thumb-tack::before{content:""}.si-external-link::before{content:""}.si-sign-in::before{content:""}.si-trophy::before{content:""}.si-github-square::before{content:""}.si-upload::before{content:""}.si-lemon-o::before{content:""}.si-phone::before{content:""}.si-square-o::before{content:""}.si-bookmark-o::before{content:""}.si-phone-square::before{content:""}.si-twitter::before{content:""}.si-facebook::before{content:""}.si-github::before{content:""}.si-unlock::before{content:""}.si-credit-card::before{content:""}.si-feed::before{content:""}.si-hdd-o::before{content:""}.si-bullhorn::before{content:""}.si-bell-o::before{content:""}.si-certificate::before{content:""}.si-hand-o-right::before{content:""}.si-hand-o-left::before{content:""}.si-hand-o-up::before{content:""}.si-hand-o-down::before{content:""}.si-arrow-circle-left::before{content:""}.si-arrow-circle-right::before{content:""}.si-arrow-circle-up::before{content:""}.si-arrow-circle-down::before{content:""}.si-globe::before{content:""}.si-wrench::before{content:""}.si-tasks::before{content:""}.si-filter::before{content:""}.si-briefcase::before{content:""}.si-arrows-alt::before{content:""}.si-group::before{content:""}.si-chain::before{content:""}.si-cloud::before{content:""}.si-flask::before{content:""}.si-cut::before{content:""}.si-copy::before{content:""}.si-paperclip::before{content:""}.si-floppy-o::before{content:""}.si-square::before{content:""}.si-bars::before{content:""}.si-list-ul::before{content:""}.si-list-ol::before{content:""}.si-strikethrough::before{content:""}.si-underline::before{content:""}.si-table::before{content:""}.si-magic::before{content:""}.si-truck::before{content:""}.si-pinterest::before{content:""}.si-pinterest-square::before{content:""}.si-google-plus-square::before{content:""}.si-google-plus::before{content:""}.si-money::before{content:""}.si-caret-down::before{content:""}.si-caret-up::before{content:""}.si-caret-left::before{content:""}.si-caret-right::before{content:""}.si-columns::before{content:""}.si-sort::before{content:""}.si-sort-desc::before{content:""}.si-sort-asc::before{content:""}.si-envelope::before{content:""}.si-linkedin::before{content:""}.si-rotate-left::before{content:""}.si-gavel::before{content:""}.si-dashboard::before{content:""}.si-comment-o::before{content:""}.si-comments-o::before{content:""}.si-bolt::before{content:""}.si-sitemap::before{content:""}.si-umbrella::before{content:""}.si-clipboard::before{content:""}.si-lightbulb-o::before{content:""}.si-exchange::before{content:""}.si-cloud-download::before{content:""}.si-cloud-upload::before{content:""}.si-user-md::before{content:""}.si-stethoscope::before{content:""}.si-suitcase::before{content:""}.si-bell::before{content:""}.si-coffee::before{content:""}.si-cutlery::before{content:""}.si-file-text-o::before{content:""}.si-building-o::before{content:""}.si-hospital-o::before{content:""}.si-ambulance::before{content:""}.si-medkit::before{content:""}.si-fighter-jet::before{content:""}.si-beer::before{content:""}.si-h-square::before{content:""}.si-plus-square::before{content:""}.si-angle-double-left::before{content:""}.si-angle-double-right::before{content:""}.si-angle-double-up::before{content:""}.si-angle-double-down::before{content:""}.si-angle-left::before{content:""}.si-angle-right::before{content:""}.si-angle-up::before{content:""}.si-angle-down::before{content:""}.si-desktop::before{content:""}.si-laptop::before{content:""}.si-tablet::before{content:""}.si-mobile::before{content:""}.si-circle-o::before{content:""}.si-quote-left::before{content:""}.si-quote-right::before{content:""}.si-spinner::before{content:""}.si-circle::before{content:""}.si-mail-reply::before{content:""}.si-github-alt::before{content:""}.si-folder-o::before{content:""}.si-folder-open-o::before{content:""}.si-smile-o::before{content:""}.si-frown-o::before{content:""}.si-meh-o::before{content:""}.si-gamepad::before{content:""}.si-keyboard-o::before{content:""}.si-flag-o::before{content:""}.si-flag-checkered::before{content:""}.si-terminal::before{content:""}.si-code::before{content:""}.si-mail-reply-all::before{content:""}.si-star-half-empty::before{content:""}.si-location-arrow::before{content:""}.si-crop::before{content:""}.si-code-fork::before{content:""}.si-chain-broken::before{content:""}.si-question::before{content:""}.si-info::before{content:""}.si-exclamation::before{content:""}.si-superscript::before{content:""}.si-subscript::before{content:""}.si-eraser::before{content:""}.si-puzzle-piece::before{content:""}.si-microphone::before{content:""}.si-microphone-slash::before{content:""}.si-shield::before{content:""}.si-calendar-o::before{content:""}.si-fire-extinguisher::before{content:""}.si-rocket::before{content:""}.si-maxcdn::before{content:""}.si-chevron-circle-left::before{content:""}.si-chevron-circle-right::before{content:""}.si-chevron-circle-up::before{content:""}.si-chevron-circle-down::before{content:""}.si-html5::before{content:""}.si-css3::before{content:""}.si-anchor::before{content:""}.si-unlock-alt::before{content:""}.si-bullseye::before{content:""}.si-ellipsis-h::before{content:""}.si-ellipsis-v::before{content:""}.si-rss-square::before{content:""}.si-play-circle::before{content:""}.si-ticket::before{content:""}.si-minus-square::before{content:""}.si-minus-square-o::before{content:""}.si-level-up::before{content:""}.si-level-down::before{content:""}.si-check-square::before{content:""}.si-pencil-square::before{content:""}.si-external-link-square::before{content:""}.si-share-square::before{content:""}.si-compass::before{content:""}.si-caret-square-o-down::before{content:""}.si-caret-square-o-up::before{content:""}.si-caret-square-o-right::before{content:""}.si-eur::before{content:""}.si-gbp::before{content:""}.si-dollar::before{content:""}.si-inr::before{content:""}.si-cny::before{content:""}.si-rouble::before{content:""}.si-krw::before{content:""}.si-bitcoin::before{content:""}.si-file::before{content:""}.si-file-text::before{content:""}.si-sort-alpha-asc::before{content:""}.si-sort-alpha-desc::before{content:""}.si-sort-amount-asc::before{content:""}.si-sort-amount-desc::before{content:""}.si-sort-numeric-asc::before{content:""}.si-sort-numeric-desc::before{content:""}.si-thumbs-up::before{content:""}.si-thumbs-down::before{content:""}.si-youtube-square::before{content:""}.si-youtube::before{content:""}.si-xing::before{content:""}.si-xing-square::before{content:""}.si-youtube-play::before{content:""}.si-dropbox::before{content:""}.si-stack-overflow::before{content:""}.si-instagram::before{content:""}.si-flickr::before{content:""}.si-adn::before{content:""}.si-bitbucket::before{content:""}.si-bitbucket-square::before{content:""}.si-tumblr::before{content:""}.si-tumblr-square::before{content:""}.si-long-arrow-down::before{content:""}.si-long-arrow-up::before{content:""}.si-long-arrow-left::before{content:""}.si-long-arrow-right::before{content:""}.si-apple::before{content:""}.si-windows::before{content:""}.si-android::before{content:""}.si-linux::before{content:""}.si-dribbble::before{content:""}.si-skype::before{content:""}.si-foursquare::before{content:""}.si-trello::before{content:""}.si-female::before{content:""}.si-male::before{content:""}.si-gittip::before{content:""}.si-sun-o::before{content:""}.si-moon-o::before{content:""}.si-archive::before{content:""}.si-bug::before{content:""}.si-vk::before{content:""}.si-weibo::before{content:""}.si-renren::before{content:""}.si-pagelines::before{content:""}.si-stack-exchange::before{content:""}.si-arrow-circle-o-right::before{content:""}.si-arrow-circle-o-left::before{content:""}.si-caret-square-o-left::before{content:""}.si-dot-circle-o::before{content:""}.si-wheelchair::before{content:""}.si-vimeo-square::before{content:""}.si-try::before{content:""}.si-plus-square-o::before{content:""}.si-space-shuttle::before{content:""}.si-slack::before{content:""}.si-envelope-square::before{content:""}.si-wordpress::before{content:""}.si-openid::before{content:""}.si-bank::before{content:""}.si-graduation-cap::before{content:""}.si-yahoo::before{content:""}.si-google::before{content:""}.si-reddit::before{content:""}.si-reddit-square::before{content:""}.si-stumbleupon-circle::before{content:""}.si-stumbleupon::before{content:""}.si-delicious::before{content:""}.si-digg::before{content:""}.si-pied-piper::before{content:""}.si-pied-piper-alt::before{content:""}.si-drupal::before{content:""}.si-joomla::before{content:""}.si-language::before{content:""}.si-fax::before{content:""}.si-building::before{content:""}.si-child::before{content:""}.si-paw::before{content:""}.si-spoon::before{content:""}.si-cube::before{content:""}.si-cubes::before{content:""}.si-behance::before{content:""}.si-behance-square::before{content:""}.si-steam::before{content:""}.si-steam-square::before{content:""}.si-recycle::before{content:""}.si-automobile::before{content:""}.si-cab::before{content:""}.si-tree::before{content:""}.si-spotify::before{content:""}.si-deviantart::before{content:""}.si-soundcloud::before{content:""}.si-database::before{content:""}.si-file-pdf-o::before{content:""}.si-file-word-o::before{content:""}.si-file-excel-o::before{content:""}.si-file-powerpoint-o::before{content:""}.si-file-image-o::before{content:""}.si-file-archive-o::before{content:""}.si-file-audio-o::before{content:""}.si-file-movie-o::before{content:""}.si-file-code-o::before{content:""}.si-vine::before{content:""}.si-codepen::before{content:""}.si-jsfiddle::before{content:""}.si-life-bouy::before{content:""}.si-circle-o-notch::before{content:""}.si-ra::before{content:""}.si-empire::before{content:""}.si-git-square::before{content:""}.si-git::before{content:""}.si-hacker-news::before{content:""}.si-tencent-weibo::before{content:""}.si-qq::before{content:""}.si-wechat::before{content:""}.si-paper-plane::before{content:""}.si-paper-plane-o::before{content:""}.si-history::before{content:""}.si-circle-thin::before{content:""}.si-header::before{content:""}.si-paragraph::before{content:""}.si-sliders::before{content:""}.si-share-alt::before{content:""}.si-share-alt-square::before{content:""}.si-bomb::before{content:""}.si-futbol-o::before{content:""}.si-tty::before{content:""}.si-binoculars::before{content:""}.si-plug::before{content:""}.si-slideshare::before{content:""}.si-twitch::before{content:""}.si-yelp::before{content:""}.si-newspaper-o::before{content:""}.si-wifi::before{content:""}.si-calculator::before{content:""}.si-paypal::before{content:""}.si-google-wallet::before{content:""}.si-cc-visa::before{content:""}.si-cc-mastercard::before{content:""}.si-cc-discover::before{content:""}.si-cc-amex::before{content:""}.si-cc-paypal::before{content:""}.si-cc-stripe::before{content:""}.si-bell-slash::before{content:""}.si-bell-slash-o::before{content:""}.si-trash::before{content:""}.si-copyright::before{content:""}.si-at::before{content:""}.si-eyedropper::before{content:""}.si-paint-brush::before{content:""}.si-birthday-cake::before{content:""}.si-area-chart::before{content:""}.si-pie-chart::before{content:""}.si-line-chart::before{content:""}.si-lastfm::before{content:""}.si-lastfm-square::before{content:""}.si-toggle-off::before{content:""}.si-toggle-on::before{content:""}.si-bicycle::before{content:""}.si-bus::before{content:""}.si-ioxhost::before{content:""}.si-angellist::before{content:""}.si-cc::before{content:""}.si-ils::before{content:""}.si-meanpath::before{content:""}.si-buysellads::before{content:""}.si-connectdevelop::before{content:""}.si-dashcube::before{content:""}.si-forumbee::before{content:""}.si-leanpub::before{content:""}.si-sellsy::before{content:""}.si-shirtsinbulk::before{content:""}.si-simplybuilt::before{content:""}.si-skyatlas::before{content:""}.si-cart-plus::before{content:""}.si-cart-arrow-down::before{content:""}.si-diamond::before{content:""}.si-ship::before{content:""}.si-user-secret::before{content:""}.si-motorcycle::before{content:""}.si-street-view::before{content:""}.si-heartbeat::before{content:""}.si-venus::before{content:""}.si-mars::before{content:""}.si-mercury::before{content:""}.si-intersex::before{content:""}.si-transgender-alt::before{content:""}.si-venus-double::before{content:""}.si-mars-double::before{content:""}.si-venus-mars::before{content:""}.si-mars-stroke::before{content:""}.si-mars-stroke-v::before{content:""}.si-mars-stroke-h::before{content:""}.si-neuter::before{content:""}.si-genderless::before{content:""}.si-facebook-official::before{content:""}.si-pinterest-p::before{content:""}.si-whatsapp::before{content:""}.si-server::before{content:""}.si-user-plus::before{content:""}.si-user-times::before{content:""}.si-bed::before{content:""}.si-viacoin::before{content:""}.si-train::before{content:""}.si-subway::before{content:""}.si-medium::before{content:""}.si-y-combinator::before{content:""}.si-optin-monster::before{content:""}.si-opencart::before{content:""}.si-expeditedssl::before{content:""}.si-battery-4::before{content:""}.si-battery-3::before{content:""}.si-battery-2::before{content:""}.si-battery-1::before{content:""}.si-battery-0::before{content:""}.si-mouse-pointer::before{content:""}.si-i-cursor::before{content:""}.si-object-group::before{content:""}.si-object-ungroup::before{content:""}.si-sticky-note::before{content:""}.si-sticky-note-o::before{content:""}.si-cc-jcb::before{content:""}.si-cc-diners-club::before{content:""}.si-clone::before{content:""}.si-balance-scale::before{content:""}.si-hourglass-o::before{content:""}.si-hourglass-1::before{content:""}.si-hourglass-2::before{content:""}.si-hourglass-3::before{content:""}.si-hourglass::before{content:""}.si-hand-grab-o::before{content:""}.si-hand-paper-o::before{content:""}.si-hand-scissors-o::before{content:""}.si-hand-lizard-o::before{content:""}.si-hand-spock-o::before{content:""}.si-hand-pointer-o::before{content:""}.si-hand-peace-o::before{content:""}.si-trademark::before{content:""}.si-registered::before{content:""}.si-creative-commons::before{content:""}.si-gg::before{content:""}.si-gg-circle::before{content:""}.si-tripadvisor::before{content:""}.si-odnoklassniki::before{content:""}.si-odnoklassniki-square::before{content:""}.si-get-pocket::before{content:""}.si-wikipedia-w::before{content:""}.si-safari::before{content:""}.si-chrome::before{content:""}.si-firefox::before{content:""}.si-opera::before{content:""}.si-internet-explorer::before{content:""}.si-television::before{content:""}.si-contao::before{content:""}.si-500px::before{content:""}.si-amazon::before{content:""}.si-calendar-plus-o::before{content:""}.si-calendar-minus-o::before{content:""}.si-calendar-times-o::before{content:""}.si-calendar-check-o::before{content:""}.si-industry::before{content:""}.si-map-pin::before{content:""}.si-map-signs::before{content:""}.si-map-o::before{content:""}.si-map::before{content:""}.si-commenting::before{content:""}.si-commenting-o::before{content:""}.si-houzz::before{content:""}.si-vimeo::before{content:""}.si-black-tie::before{content:""}.si-fonticons::before{content:""}.si-lg{font-size:1.33333333em;line-height:0.75em;vertical-align:-15%}.si-2x{font-size:2em}.si-3x{font-size:3em}.si-4x{font-size:4em}.si-5x{font-size:5em}.si-fw{text-align:center;width:1.28571429em}.si-border{border-radius:.1em;padding:.2em .25em .15em;border:solid 0.08em}.si-pull-left{float:left;margin-right:.3em}.si-pull-right{float:right;margin-left:.3em}.si-rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.si-rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.si-rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.si-flip-horizontal{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.si-flip-vertical{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.si-inverse{-webkit-filter:invert(100%);filter:invert(100%)}.si-spin{-webkit-animation:si-animation-spin 2s infinite linear;-moz-animation:si-animation-spin 2s infinite linear;animation:si-animation-spin 2s infinite linear}.si-pulse{-webkit-animation:si-animation-spin 1s infinite steps(8);-moz-animation:si-animation-spin 1s infinite steps(8);animation:si-animation-spin 1s infinite steps(8)}.si-ul{padding-left:0;list-style-type:none;margin-left:2.14285714em}.si-ul>li{position:relative}.si-ul>li .si-li{text-align:center;position:absolute;left:-2.14285714em;width:2.14285714em;top:0.14285714em}.si-ul>li .si-li .si-lg{left:-1.85714286em}.si-stack{width:2em;height:2em;line-height:2em;vertical-align:middle;position:relative;display:inline-block}.si-stack .si-stack-1x,.si-stack .si-stack-2x{left:0;width:100%;text-align:center;position:absolute}.si-stack .si-stack-1x{line-height:inherit}.si-stack .si-stack-2x{font-size:2em}@-webkit-keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-moz-keyframes si-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}.plugin-menu-page-animation-spin{-webkit-animation-duration:0.75s;-moz-animation-duration:0.75s;animation-duration:0.75s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:linear;-moz-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:plugin-menu-page-animation-spin;-moz-animation-name:plugin-menu-page-animation-spin;animation-name:plugin-menu-page-animation-spin}@-webkit-keyframes plugin-menu-page-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@-moz-keyframes plugin-menu-page-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(360deg)}}@keyframes plugin-menu-page-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-ms-transform:rotate(360deg);-o-transform:rotate(360deg);transform:rotate(360deg)}}html{overflow-y:scroll}#wpwrap{position:relative}#wpwrap::after{top:0;right:0;bottom:0;left:0;z-index:-1;position:absolute;content:'';opacity:0.25;background:url("../images/bg.png")}#wpwrap .updated,#wpwrap .error{margin:1.25em 1.25em 1.25em 0.25em}.plugin-menu-page{min-width:800px;margin:1.25em 1.25em 1.25em 0.25em}.plugin-menu-page,.plugin-menu-page p{font-size:14px}.plugin-menu-page a{color:#033A63}.plugin-menu-page a:hover,.plugin-menu-page a:active{color:#467629}.plugin-menu-page p:first-child,.plugin-menu-page pre:first-child{margin-top:0}.plugin-menu-page p:last-child,.plugin-menu-page pre:last-child{margin-bottom:0}.plugin-menu-page code{border-radius:3px;padding:0.1em 0.25em;background:rgba(178,178,178,0.25);font-family:'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace}.plugin-menu-page pre.code{padding:0;background:none}.plugin-menu-page pre.code>code{font-size:90%;overflow-x:auto;max-width:100%;border-radius:4px;padding:1em;display:block;color:#eee;background:#222;box-shadow:0 0 5px 1px #000 inset}.plugin-menu-page img{border:0}.plugin-menu-page img.screenshot{float:right;border-radius:4px;padding:0.5em;margin:0 0 2em 2em;background:#fff;border:1px solid #afafaf;box-shadow:0 0 5px 0 rgba(0,0,0,0.2) inset}.plugin-menu-page hr{border:0;padding:0;height:1px;margin:1em 0;background:linear-gradient(to left, transparent, rgba(0,0,0,0.75), transparent)}.plugin-menu-page label{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.plugin-menu-page label.switch-primary{font-size:130%;margin:0;padding:0.5em;border-radius:4px;display:inline;color:#000;background:#f1e982;border:1px solid rgba(0,0,0,0.07);box-shadow:-1px -1px 0 0 rgba(0,0,0,0.25) inset,1px 1px 0 0 #fff inset}.plugin-menu-page select,.plugin-menu-page textarea,.plugin-menu-page select:focus,.plugin-menu-page textarea:focus,.plugin-menu-page input:not([type='radio']):not([type='checkbox']),.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus{width:100%;line-height:1.3em;margin:0;padding:0.25em 0.5em;border-radius:4px;box-sizing:border-box;color:#333;background:#e8e8e8;border:1px solid #848484;box-shadow:0 0 2px 0 rgba(132,132,132,0.5) inset}.plugin-menu-page select,.plugin-menu-page select:focus{box-shadow:0 1px 0 0 #fff inset,0 -2px 3px 0 rgba(132,132,132,0.25) inset}.plugin-menu-page select,.plugin-menu-page select:focus,.plugin-menu-page input:not([type='radio']):not([type='checkbox']),.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus{height:2em}.plugin-menu-page select:focus,.plugin-menu-page textarea:focus,.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus{color:#000;background:#e2e2e2}.plugin-menu-page input[disabled],.plugin-menu-page select[disabled],.plugin-menu-page textarea[disabled]{opacity:0.5}.plugin-menu-page input::-webkit-input-placeholder,.plugin-menu-page textarea::-webkit-input-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input::-moz-placeholder,.plugin-menu-page textarea::-moz-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input:-moz-placeholder,.plugin-menu-page textarea:-moz-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input:-ms-input-placeholder,.plugin-menu-page textarea:-ms-input-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page table{margin:1em 0}.plugin-menu-page button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:150%;font-weight:bold;line-height:1em;outline:none;cursor:pointer;border-radius:4px;margin:0;padding:0.25em 0.5em;box-sizing:border-box;color:#fff;background:#033A63;border:1px solid rgba(0,0,0,0.5);box-shadow:0 1px 1px 0 rgba(0,0,0,0.25),-1px -1px 0 0 rgba(0,0,0,0.2) inset,1px 1px 0 0 rgba(255,255,255,0.1) inset}.plugin-menu-page button:hover{background:#467629}.plugin-menu-page button[type='submit']{background:#467629}.plugin-menu-page button[type='submit']:hover{background:#033A63}.plugin-menu-page button:active{-webkit-transform:scale(0.98, 0.98);-moz-transform:scale(0.98, 0.98);-ms-transform:scale(0.98, 0.98);-o-transform:scale(0.98, 0.98);transform:scale(0.98, 0.98)}.plugin-menu-page .info,.plugin-menu-page .notice,.plugin-menu-page .warning,.plugin-menu-page .error{border-radius:4px;padding:0.5em;margin:1em 0}.plugin-menu-page .info{background:#cadfed;border:1px solid #216095}.plugin-menu-page .notice{background:#fffde8;border:1px solid #e6db55}.plugin-menu-page .warning{background:#ffefd3;border:1px solid #e6db55}.plugin-menu-page .error{background:pink;border:1px solid #711e1e}.plugin-menu-page .monospace{font-family:'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace}.plugin-menu-page textarea.monospace{white-space:pre}.plugin-menu-page .clearfix::before,.plugin-menu-page .clearfix::after{display:table;content:' '}.plugin-menu-page .clearfix::after{clear:both}.plugin-menu-page-heading .plugin-menu-page-restore-defaults,.plugin-menu-page-heading .plugin-menu-page-panel-togglers{float:right;margin:0 1em 0 0}.plugin-menu-page-heading .plugin-menu-page-panel-togglers button{background:#033A63 !important}.plugin-menu-page-heading .plugin-menu-page-upsells{float:right;clear:right;text-align:right;max-width:350px;margin:1em 0 0}.plugin-menu-page-heading .plugin-menu-page-upsells a{text-decoration:none;line-height:1.5em;margin:0 0.5em;display:inline-block}.plugin-menu-page-heading .plugin-menu-page-support-links,.plugin-menu-page-heading .plugin-menu-page-mailing-list-links{float:right;clear:right;text-align:right;max-width:400px;margin:.5em 0 0}.plugin-menu-page-heading .plugin-menu-page-support-links a,.plugin-menu-page-heading .plugin-menu-page-mailing-list-links a{text-decoration:none;margin:0 0.5em;display:inline-block}.plugin-menu-page-heading .plugin-menu-page-version{float:right;clear:right;min-width:350px;margin:0.5em 0 0 0;text-align:right}.plugin-menu-page-body{position:relative}.plugin-menu-page-section-heading{margin:1em 0}.plugin-menu-page-section-heading>small{font-size:65%;font-style:italic;margin:0;display:block;opacity:0.5}.plugin-menu-page-panel{margin:1em 0}.plugin-menu-page-panel:first-child{margin-top:0}.plugin-menu-page-panel .plugin-menu-page-panel-heading{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;padding:10px;font-size:150%;line-height:1.125em;font-weight:bold;border-radius:4px;display:block;cursor:pointer;background:#033A63;background:linear-gradient(to right, #033A63, #20669A);color:#eee !important;box-shadow:0 2px 2px 0 rgba(0,0,0,0.25)}.plugin-menu-page-panel .plugin-menu-page-panel-heading::after{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none;content:""}.plugin-menu-page-panel .plugin-menu-page-panel-heading:hover,.plugin-menu-page-panel .plugin-menu-page-panel-heading.open{color:#fff !important}.plugin-menu-page-panel .plugin-menu-page-panel-heading::after{font-size:80%;float:right;margin:0 0 0 5px}.plugin-menu-page-panel .plugin-menu-page-panel-heading.open::after{content:""}.plugin-menu-page-panel-heading.pro-preview-feature{background:#216095}.pro-preview-feature::after{font-variant:small-caps !important;font-family:sans-serif !important;content:'pro version only' !important;margin-left:15px;background:#216095;color:#FFFFFF;padding:0 5px 2px 5px;font-weight:normal}.plugin-menu-page-panel-heading.pro-preview-additional-features{background:#216095}.pro-preview-additional-features::after{font-variant:small-caps !important;font-family:sans-serif !important;content:'additional pro version only features' !important;margin-left:15px;background:#216095;color:#FFFFFF;padding:0 5px 2px 5px;font-weight:normal}.plugin-menu-page-panel .plugin-menu-page-panel-heading>.si{text-align:center;width:1.28571429em;margin-right:.25em}.plugin-menu-page-panel .plugin-menu-page-panel-body{width:99%;margin:0 auto;display:none;padding:1.2em;border-bottom-left-radius:4px;border-bottom-right-radius:4px;box-sizing:border-box;color:#222;border:1px solid #848484;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,0.25),0 3px 1px -1px rgba(0,0,0,0.25) inset}.plugin-menu-page-panel .plugin-menu-page-panel-body.open{display:block}.plugin-menu-page-panel .plugin-menu-page-panel-body p{font-size:90%;color:#666}.plugin-menu-page-panel .plugin-menu-page-panel-body p.notice,.plugin-menu-page-panel .plugin-menu-page-panel-body p.info,.plugin-menu-page-panel .plugin-menu-page-panel-body p.warning,.plugin-menu-page-panel .plugin-menu-page-panel-body p.error{color:#000}.plugin-menu-page-panel .plugin-menu-page-panel-body h3{margin:0 0 0.5em}.plugin-menu-page-panel .plugin-menu-page-panel-body h3:first-child{margin-top:0}.plugin-menu-page-panel .plugin-menu-page-panel-body h3+p{margin-top:0}.plugin-menu-page-panel .plugin-menu-page-panel-body a.dotted{text-decoration:none;border-bottom:1px dotted}.plugin-menu-page-panel .plugin-menu-page-panel-body.pro-preview,.plugin-menu-page-panel .plugin-menu-page-panel-body .pro-preview{opacity:0.5}.plugin-menu-page-save{margin-top:2em}.plugin-menu-page-save button{line-height:1.3em;width:100%}
|
2 |
+
|
src/includes/api.php
CHANGED
@@ -6,11 +6,13 @@
|
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
|
|
|
|
9 |
if (!defined('WPINC')) {
|
10 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
11 |
}
|
12 |
-
class_alias(__NAMESPACE__.'\\ApiBase', GLOBAL_NS);
|
13 |
|
14 |
if (!class_exists('zencache')) {
|
15 |
-
class_alias(__NAMESPACE__.'\\ApiBase', 'zencache');
|
16 |
}
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
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 |
|
16 |
if (!class_exists('zencache')) {
|
17 |
+
class_alias(__NAMESPACE__.'\\Classes\\ApiBase', 'zencache');
|
18 |
}
|
src/includes/classes/AbsBase.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* Abstract Base.
|
@@ -20,21 +20,21 @@ abstract class AbsBase
|
|
20 |
*
|
21 |
* @since 150422 Rewrite.
|
22 |
*/
|
23 |
-
protected $cache =
|
24 |
|
25 |
/**
|
26 |
* @type array Global static cache ref.
|
27 |
*
|
28 |
* @since 150422 Rewrite.
|
29 |
*/
|
30 |
-
protected $static =
|
31 |
|
32 |
/**
|
33 |
* @type array Global static cache.
|
34 |
*
|
35 |
* @since 150422 Rewrite.
|
36 |
*/
|
37 |
-
protected static $global_static =
|
38 |
|
39 |
/**
|
40 |
* @type \stdClass Overload properties.
|
@@ -55,7 +55,7 @@ abstract class AbsBase
|
|
55 |
$class = get_called_class();
|
56 |
|
57 |
if (empty(static::$global_static[$class])) {
|
58 |
-
static::$global_static[$class] =
|
59 |
}
|
60 |
$this->static = &static::$global_static[$class];
|
61 |
|
@@ -76,7 +76,8 @@ abstract class AbsBase
|
|
76 |
if (isset($instance)) {
|
77 |
return $instance;
|
78 |
}
|
79 |
-
|
|
|
80 |
}
|
81 |
|
82 |
/**
|
@@ -167,7 +168,7 @@ abstract class AbsBase
|
|
167 |
* @note This function returns by reference. The use of `&` is highly recommended when calling this utility.
|
168 |
* See also: <http://php.net/manual/en/language.references.return.php>
|
169 |
*/
|
170 |
-
public function &cacheKey($function, $args =
|
171 |
{
|
172 |
$function = (string) $function;
|
173 |
$args = (array) $args;
|
@@ -210,6 +211,7 @@ abstract class AbsBase
|
|
210 |
}
|
211 |
$cache_key = &$cache_key[$_key];
|
212 |
}
|
|
|
213 |
return $cache_key;
|
214 |
}
|
215 |
|
@@ -224,7 +226,7 @@ abstract class AbsBase
|
|
224 |
* @note This function returns by reference. The use of `&` is highly recommended when calling this utility.
|
225 |
* See also: <http://php.net/manual/en/language.references.return.php>
|
226 |
*/
|
227 |
-
public function &staticKey($function, $args =
|
228 |
{
|
229 |
$key = &$this->cacheKey($function, $args, 'static');
|
230 |
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* Abstract Base.
|
20 |
*
|
21 |
* @since 150422 Rewrite.
|
22 |
*/
|
23 |
+
protected $cache = [];
|
24 |
|
25 |
/**
|
26 |
* @type array Global static cache ref.
|
27 |
*
|
28 |
* @since 150422 Rewrite.
|
29 |
*/
|
30 |
+
protected $static = [];
|
31 |
|
32 |
/**
|
33 |
* @type array Global static cache.
|
34 |
*
|
35 |
* @since 150422 Rewrite.
|
36 |
*/
|
37 |
+
protected static $global_static = [];
|
38 |
|
39 |
/**
|
40 |
* @type \stdClass Overload properties.
|
55 |
$class = get_called_class();
|
56 |
|
57 |
if (empty(static::$global_static[$class])) {
|
58 |
+
static::$global_static[$class] = [];
|
59 |
}
|
60 |
$this->static = &static::$global_static[$class];
|
61 |
|
76 |
if (isset($instance)) {
|
77 |
return $instance;
|
78 |
}
|
79 |
+
|
80 |
+
return $instance = new static();
|
81 |
}
|
82 |
|
83 |
/**
|
168 |
* @note This function returns by reference. The use of `&` is highly recommended when calling this utility.
|
169 |
* See also: <http://php.net/manual/en/language.references.return.php>
|
170 |
*/
|
171 |
+
public function &cacheKey($function, $args = [], $___prop = 'cache')
|
172 |
{
|
173 |
$function = (string) $function;
|
174 |
$args = (array) $args;
|
211 |
}
|
212 |
$cache_key = &$cache_key[$_key];
|
213 |
}
|
214 |
+
|
215 |
return $cache_key;
|
216 |
}
|
217 |
|
226 |
* @note This function returns by reference. The use of `&` is highly recommended when calling this utility.
|
227 |
* See also: <http://php.net/manual/en/language.references.return.php>
|
228 |
*/
|
229 |
+
public function &staticKey($function, $args = [])
|
230 |
{
|
231 |
$key = &$this->cacheKey($function, $args, 'static');
|
232 |
|
src/includes/classes/AbsBaseAp.php
CHANGED
@@ -1,13 +1,39 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
|
|
|
|
|
|
3 |
|
4 |
/**
|
5 |
* Abstract Base for Advanced Cache and Plugin.
|
6 |
*
|
7 |
* @since 150422 Rewrite.
|
8 |
*/
|
9 |
-
abstract class AbsBaseAp extends AbsBase
|
10 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* Class constructor.
|
13 |
*
|
@@ -16,16 +42,6 @@ abstract class AbsBaseAp extends AbsBase
|
|
16 |
public function __construct()
|
17 |
{
|
18 |
parent::__construct();
|
19 |
-
|
20 |
-
$closures_dir = dirname(dirname(__FILE__)).'/closures/Shared';
|
21 |
-
$self = $this; // Reference for closures.
|
22 |
-
|
23 |
-
foreach (scandir($closures_dir) as $_closure) {
|
24 |
-
if (substr($_closure, -4) === '.php') {
|
25 |
-
require $closures_dir.'/'.$_closure;
|
26 |
-
}
|
27 |
-
}
|
28 |
-
unset($_closure); // Housekeeping.
|
29 |
}
|
30 |
|
31 |
/**
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Traits;
|
5 |
+
use WebSharks\CometCache\Interfaces;
|
6 |
|
7 |
/**
|
8 |
* Abstract Base for Advanced Cache and Plugin.
|
9 |
*
|
10 |
* @since 150422 Rewrite.
|
11 |
*/
|
12 |
+
abstract class AbsBaseAp extends AbsBase implements Interfaces\Shared\NcDebugConsts, Interfaces\Shared\CachePathConsts
|
13 |
{
|
14 |
+
/*[.build.php-auto-generate-use-Traits]*/
|
15 |
+
use Traits\Shared\BlogUtils;
|
16 |
+
use Traits\Shared\CacheDirUtils;
|
17 |
+
use Traits\Shared\CacheLockUtils;
|
18 |
+
use Traits\Shared\CachePathUtils;
|
19 |
+
use Traits\Shared\ConditionalUtils;
|
20 |
+
use Traits\Shared\DomainMappingUtils;
|
21 |
+
use Traits\Shared\EscapeUtils;
|
22 |
+
use Traits\Shared\FsUtils;
|
23 |
+
use Traits\Shared\HookUtils;
|
24 |
+
use Traits\Shared\HttpUtils;
|
25 |
+
use Traits\Shared\I18nUtils;
|
26 |
+
use Traits\Shared\IpAddrUtils;
|
27 |
+
use Traits\Shared\PatternUtils;
|
28 |
+
use Traits\Shared\ReplaceUtils;
|
29 |
+
use Traits\Shared\ServerUtils;
|
30 |
+
use Traits\Shared\StringUtils;
|
31 |
+
use Traits\Shared\SysUtils;
|
32 |
+
use Traits\Shared\TokenUtils;
|
33 |
+
use Traits\Shared\TrimUtils;
|
34 |
+
use Traits\Shared\UrlUtils;
|
35 |
+
/*[/.build.php-auto-generate-use-Traits]*/
|
36 |
+
|
37 |
/**
|
38 |
* Class constructor.
|
39 |
*
|
42 |
public function __construct()
|
43 |
{
|
44 |
parent::__construct();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
}
|
46 |
|
47 |
/**
|
src/includes/classes/Actions.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* Actions.
|
@@ -13,7 +13,7 @@ class Actions extends AbsBase
|
|
13 |
*
|
14 |
* @since 150422 Rewrite.
|
15 |
*/
|
16 |
-
protected $allowed_actions =
|
17 |
'wipeCache',
|
18 |
'clearCache',
|
19 |
|
@@ -37,7 +37,7 @@ class Actions extends AbsBase
|
|
37 |
|
38 |
|
39 |
'dismissNotice',
|
40 |
-
|
41 |
|
42 |
/**
|
43 |
* Class constructor.
|
@@ -81,7 +81,7 @@ class Actions extends AbsBase
|
|
81 |
|
82 |
|
83 |
$redirect_to = self_admin_url('/admin.php');
|
84 |
-
$query_args =
|
85 |
$redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to);
|
86 |
|
87 |
wp_redirect($redirect_to).exit();
|
@@ -107,7 +107,7 @@ class Actions extends AbsBase
|
|
107 |
|
108 |
|
109 |
$redirect_to = self_admin_url('/admin.php'); // Redirect preparations.
|
110 |
-
$query_args =
|
111 |
$redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to);
|
112 |
|
113 |
wp_redirect($redirect_to).exit();
|
@@ -167,7 +167,7 @@ class Actions extends AbsBase
|
|
167 |
delete_transient(GLOBAL_NS.'-'.md5($this->plugin->options['auto_cache_sitemap_url']));
|
168 |
|
169 |
$redirect_to = self_admin_url('/admin.php'); // Redirect preparations.
|
170 |
-
$query_args =
|
171 |
|
172 |
$this->plugin->autoWipeCache(); // May produce a notice.
|
173 |
|
@@ -232,7 +232,7 @@ class Actions extends AbsBase
|
|
232 |
$this->plugin->restoreDefaultOptions(); // Restore defaults.
|
233 |
|
234 |
$redirect_to = self_admin_url('/admin.php'); // Redirect preparations.
|
235 |
-
$query_args =
|
236 |
|
237 |
$this->plugin->autoWipeCache(); // May produce a notice.
|
238 |
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* Actions.
|
13 |
*
|
14 |
* @since 150422 Rewrite.
|
15 |
*/
|
16 |
+
protected $allowed_actions = [
|
17 |
'wipeCache',
|
18 |
'clearCache',
|
19 |
|
37 |
|
38 |
|
39 |
'dismissNotice',
|
40 |
+
];
|
41 |
|
42 |
/**
|
43 |
* Class constructor.
|
81 |
|
82 |
|
83 |
$redirect_to = self_admin_url('/admin.php');
|
84 |
+
$query_args = ['page' => GLOBAL_NS, GLOBAL_NS.'_cache_wiped' => '1'];
|
85 |
$redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to);
|
86 |
|
87 |
wp_redirect($redirect_to).exit();
|
107 |
|
108 |
|
109 |
$redirect_to = self_admin_url('/admin.php'); // Redirect preparations.
|
110 |
+
$query_args = ['page' => GLOBAL_NS, GLOBAL_NS.'_cache_cleared' => '1'];
|
111 |
$redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to);
|
112 |
|
113 |
wp_redirect($redirect_to).exit();
|
167 |
delete_transient(GLOBAL_NS.'-'.md5($this->plugin->options['auto_cache_sitemap_url']));
|
168 |
|
169 |
$redirect_to = self_admin_url('/admin.php'); // Redirect preparations.
|
170 |
+
$query_args = ['page' => GLOBAL_NS, GLOBAL_NS.'_updated' => '1'];
|
171 |
|
172 |
$this->plugin->autoWipeCache(); // May produce a notice.
|
173 |
|
232 |
$this->plugin->restoreDefaultOptions(); // Restore defaults.
|
233 |
|
234 |
$redirect_to = self_admin_url('/admin.php'); // Redirect preparations.
|
235 |
+
$query_args = ['page' => GLOBAL_NS, GLOBAL_NS.'_restored' => '1'];
|
236 |
|
237 |
$this->plugin->autoWipeCache(); // May produce a notice.
|
238 |
|
src/includes/classes/AdvCacheBackCompat.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* AC back compat.
|
@@ -15,11 +15,11 @@ class AdvCacheBackCompat
|
|
15 |
*/
|
16 |
public static function zcRequestVars()
|
17 |
{
|
18 |
-
$super_gs
|
19 |
'_GET' => &$_GET,
|
20 |
'_REQUEST' => &$_REQUEST,
|
21 |
-
|
22 |
-
$zc_suffixes =
|
23 |
|
24 |
foreach ($super_gs as $_super_g_key => &$_super_g_value) {
|
25 |
foreach ($zc_suffixes as $_zc_suffix) {
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* AC back compat.
|
15 |
*/
|
16 |
public static function zcRequestVars()
|
17 |
{
|
18 |
+
$super_gs = [
|
19 |
'_GET' => &$_GET,
|
20 |
'_REQUEST' => &$_REQUEST,
|
21 |
+
];
|
22 |
+
$zc_suffixes = ['AC', 'ABC'];
|
23 |
|
24 |
foreach ($super_gs as $_super_g_key => &$_super_g_value) {
|
25 |
foreach ($zc_suffixes as $_zc_suffix) {
|
src/includes/classes/AdvancedCache.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
|
|
|
|
3 |
|
4 |
/**
|
5 |
* Advanced cache.
|
@@ -8,6 +10,16 @@ namespace WebSharks\CometCache;
|
|
8 |
*/
|
9 |
class AdvancedCache extends AbsBaseAp
|
10 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* Flagged as `TRUE` if running.
|
13 |
*
|
@@ -35,16 +47,6 @@ class AdvancedCache extends AbsBaseAp
|
|
35 |
{
|
36 |
parent::__construct();
|
37 |
|
38 |
-
$closures_dir = dirname(dirname(__FILE__)).'/closures/Ac';
|
39 |
-
$self = $this; // Reference for closures.
|
40 |
-
|
41 |
-
foreach (scandir($closures_dir) as $_closure) {
|
42 |
-
if (substr($_closure, -4) === '.php') {
|
43 |
-
require $closures_dir.'/'.$_closure;
|
44 |
-
}
|
45 |
-
}
|
46 |
-
unset($_closure); // Housekeeping.
|
47 |
-
|
48 |
if (!defined('WP_CACHE') || !WP_CACHE || !COMET_CACHE_ENABLE) {
|
49 |
return; // Not enabled.
|
50 |
}
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Traits;
|
5 |
|
6 |
/**
|
7 |
* Advanced cache.
|
10 |
*/
|
11 |
class AdvancedCache extends AbsBaseAp
|
12 |
{
|
13 |
+
/*[.build.php-auto-generate-use-Traits]*/
|
14 |
+
use Traits\Ac\AbortUtils;
|
15 |
+
use Traits\Ac\AcPluginUtils;
|
16 |
+
use Traits\Ac\BrowserUtils;
|
17 |
+
use Traits\Ac\NcDebugUtils;
|
18 |
+
use Traits\Ac\ObUtils;
|
19 |
+
use Traits\Ac\PostloadUtils;
|
20 |
+
use Traits\Ac\ShutdownUtils;
|
21 |
+
/*[/.build.php-auto-generate-use-Traits]*/
|
22 |
+
|
23 |
/**
|
24 |
* Flagged as `TRUE` if running.
|
25 |
*
|
47 |
{
|
48 |
parent::__construct();
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
if (!defined('WP_CACHE') || !WP_CACHE || !COMET_CACHE_ENABLE) {
|
51 |
return; // Not enabled.
|
52 |
}
|
src/includes/classes/ApiBase.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* API Base Class.
|
@@ -100,6 +100,7 @@ class ApiBase
|
|
100 |
public static function clearUrl($url)
|
101 |
{
|
102 |
$regex = $GLOBALS[GLOBAL_NS]->buildCachePathRegexFromWcUrl($url);
|
|
|
103 |
return $GLOBALS[GLOBAL_NS]->deleteFilesFromCacheDir($regex);
|
104 |
}
|
105 |
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* API Base Class.
|
100 |
public static function clearUrl($url)
|
101 |
{
|
102 |
$regex = $GLOBALS[GLOBAL_NS]->buildCachePathRegexFromWcUrl($url);
|
103 |
+
|
104 |
return $GLOBALS[GLOBAL_NS]->deleteFilesFromCacheDir($regex);
|
105 |
}
|
106 |
|
src/includes/classes/Conflicts.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* Conflicts.
|
@@ -18,6 +18,7 @@ class Conflicts
|
|
18 |
if (static::doCheck()) {
|
19 |
static::maybeEnqueueNotice();
|
20 |
}
|
|
|
21 |
return $GLOBALS[GLOBAL_NS.'_conflicting_plugin'];
|
22 |
}
|
23 |
|
@@ -31,13 +32,13 @@ class Conflicts
|
|
31 |
if (!empty($GLOBALS[GLOBAL_NS.'_conflicting_plugin'])) {
|
32 |
return $GLOBALS[GLOBAL_NS.'_conflicting_plugin'];
|
33 |
}
|
34 |
-
$conflicting_plugin_slugs =
|
35 |
'zencache', 'zencache-pro', 'quick-cache', 'quick-cache-pro',
|
36 |
str_replace('_', '-', GLOBAL_NS).(IS_PRO ? '' : '-pro'),
|
37 |
'wp-super-cache', 'w3-total-cache', 'hyper-cache', 'wp-rocket',
|
38 |
-
|
39 |
-
$active_plugins = (array) get_option('active_plugins',
|
40 |
-
$active_sitewide_plugins = is_multisite() ? array_keys((array) get_site_option('active_sitewide_plugins',
|
41 |
$active_plugins = array_unique(array_merge($active_plugins, $active_sitewide_plugins));
|
42 |
|
43 |
foreach ($active_plugins as $_active_plugin_basename) {
|
@@ -45,16 +46,17 @@ class Conflicts
|
|
45 |
continue; // Nothing to check in this case.
|
46 |
}
|
47 |
if (in_array($_active_plugin_slug, $conflicting_plugin_slugs, true)) {
|
48 |
-
if (empty($GLOBALS[GLOBAL_NS.'_uninstalling']) && is_admin() && in_array($_active_plugin_slug,
|
49 |
add_action('admin_init', function () use ($_active_plugin_basename) {
|
50 |
deactivate_plugins($_active_plugin_basename, true);
|
51 |
-
|
52 |
} else {
|
53 |
-
return
|
54 |
}
|
55 |
}
|
56 |
}
|
57 |
-
|
|
|
58 |
}
|
59 |
|
60 |
/**
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* Conflicts.
|
18 |
if (static::doCheck()) {
|
19 |
static::maybeEnqueueNotice();
|
20 |
}
|
21 |
+
|
22 |
return $GLOBALS[GLOBAL_NS.'_conflicting_plugin'];
|
23 |
}
|
24 |
|
32 |
if (!empty($GLOBALS[GLOBAL_NS.'_conflicting_plugin'])) {
|
33 |
return $GLOBALS[GLOBAL_NS.'_conflicting_plugin'];
|
34 |
}
|
35 |
+
$conflicting_plugin_slugs = [
|
36 |
'zencache', 'zencache-pro', 'quick-cache', 'quick-cache-pro',
|
37 |
str_replace('_', '-', GLOBAL_NS).(IS_PRO ? '' : '-pro'),
|
38 |
'wp-super-cache', 'w3-total-cache', 'hyper-cache', 'wp-rocket',
|
39 |
+
];
|
40 |
+
$active_plugins = (array) get_option('active_plugins', []);
|
41 |
+
$active_sitewide_plugins = is_multisite() ? array_keys((array) get_site_option('active_sitewide_plugins', [])) : [];
|
42 |
$active_plugins = array_unique(array_merge($active_plugins, $active_sitewide_plugins));
|
43 |
|
44 |
foreach ($active_plugins as $_active_plugin_basename) {
|
46 |
continue; // Nothing to check in this case.
|
47 |
}
|
48 |
if (in_array($_active_plugin_slug, $conflicting_plugin_slugs, true)) {
|
49 |
+
if (empty($GLOBALS[GLOBAL_NS.'_uninstalling']) && is_admin() && in_array($_active_plugin_slug, ['comet-cache', 'comet-cache-pro', 'zencache', 'zencache-pro', 'quick-cache', 'quick-cache-pro'], true)) {
|
50 |
add_action('admin_init', function () use ($_active_plugin_basename) {
|
51 |
deactivate_plugins($_active_plugin_basename, true);
|
52 |
+
}, -1000);
|
53 |
} else {
|
54 |
+
return $GLOBALS[GLOBAL_NS.'_conflicting_plugin'] = $_active_plugin_slug;
|
55 |
}
|
56 |
}
|
57 |
}
|
58 |
+
|
59 |
+
return $GLOBALS[GLOBAL_NS.'_conflicting_plugin'] = ''; // i.e. No conflicting plugins.
|
60 |
}
|
61 |
|
62 |
/**
|
src/includes/classes/FeedUtils.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* Feed Utils.
|
@@ -48,7 +48,7 @@ class FeedUtils extends AbsBase
|
|
48 |
$this->home_url = rtrim(home_url(), '/');
|
49 |
$this->default_feed = get_default_feed(); // Default feed type.
|
50 |
$this->seo_friendly_permalinks = (boolean) get_option('permalink_structure');
|
51 |
-
$this->feed_types = array_unique(
|
52 |
}
|
53 |
|
54 |
/**
|
@@ -62,7 +62,7 @@ class FeedUtils extends AbsBase
|
|
62 |
*/
|
63 |
public function feedLinkVariations($type_prefix = '')
|
64 |
{
|
65 |
-
$variations =
|
66 |
|
67 |
foreach ($this->feed_types as $_feed_type) {
|
68 |
$variations[] = get_feed_link((string) $type_prefix.$_feed_type);
|
@@ -83,7 +83,7 @@ class FeedUtils extends AbsBase
|
|
83 |
*/
|
84 |
public function postCommentsFeedLinkVariations(\WP_Post $post)
|
85 |
{
|
86 |
-
$variations =
|
87 |
|
88 |
foreach ($this->feed_types as $_feed_type) {
|
89 |
$variations[] = get_post_comments_feed_link($post->ID, $_feed_type);
|
@@ -104,15 +104,15 @@ class FeedUtils extends AbsBase
|
|
104 |
*/
|
105 |
public function postAuthorFeedLinkVariations(\WP_Post $post)
|
106 |
{
|
107 |
-
$variations =
|
108 |
|
109 |
foreach ($this->feed_types as $_feed_type) {
|
110 |
$variations[] = get_author_feed_link($post->post_author, $_feed_type);
|
111 |
}
|
112 |
if ($this->seo_friendly_permalinks && ($post_author = get_userdata($post->post_author))) {
|
113 |
foreach ($this->feed_types as $_feed_type) {
|
114 |
-
$variations[] = add_query_arg(urlencode_deep(
|
115 |
-
$variations[] = add_query_arg(urlencode_deep(
|
116 |
}
|
117 |
}
|
118 |
unset($_feed_type); // Housekeeping.
|
@@ -131,7 +131,7 @@ class FeedUtils extends AbsBase
|
|
131 |
*/
|
132 |
public function postTypeArchiveFeedLinkVariations(\WP_Post $post)
|
133 |
{
|
134 |
-
$variations =
|
135 |
|
136 |
foreach ($this->feed_types as $_feed_type) {
|
137 |
$variations[] = get_post_type_archive_feed_link($post->post_type, $_feed_type);
|
@@ -158,7 +158,7 @@ class FeedUtils extends AbsBase
|
|
158 |
*/
|
159 |
public function postTermFeedLinkVariations(\WP_Post $post, $include_regex_wildcard_keys = false)
|
160 |
{
|
161 |
-
$variations = $post_terms =
|
162 |
|
163 |
if (!is_array($post_taxonomies = get_object_taxonomies($post, 'objects')) || !$post_taxonomies) {
|
164 |
return $variations; // Nothing to do here; post has no terms.
|
@@ -202,10 +202,10 @@ class FeedUtils extends AbsBase
|
|
202 |
$_taxonomy_query_var = $_taxonomy->query_var;
|
203 |
}
|
204 |
foreach ($this->feed_types as $_feed_type) {
|
205 |
-
$variations[] = add_query_arg(urlencode_deep(
|
206 |
}
|
207 |
foreach ($this->feed_types as $_feed_type) {
|
208 |
-
$variations[] = add_query_arg(urlencode_deep(
|
209 |
}
|
210 |
}
|
211 |
unset($_taxonomy, $_taxonomy_query_var, $_feed_type); // Housekeeping.
|
@@ -226,11 +226,11 @@ class FeedUtils extends AbsBase
|
|
226 |
*/
|
227 |
public function convertVariationsToHostCachePathRegexFrags(array $variations)
|
228 |
{
|
229 |
-
$regex_frags =
|
230 |
$is_multisite = is_multisite();
|
231 |
$can_consider_domain_mapping = $is_multisite && $this->plugin->canConsiderDomainMapping();
|
232 |
-
$flags = CACHE_PATH_NO_SCHEME | CACHE_PATH_NO_HOST // Default flags.
|
233 |
-
| CACHE_PATH_NO_USER | CACHE_PATH_NO_VSALT | CACHE_PATH_NO_EXT;
|
234 |
// Flags: note that we DO allow for query string data in these regex fragments.
|
235 |
|
236 |
foreach ($variations as $_key => $_url) {
|
@@ -252,7 +252,7 @@ class FeedUtils extends AbsBase
|
|
252 |
|
253 |
if (is_string($_key) && strpos($_key, '::') !== false && strpos($_url, '*') !== false) {
|
254 |
list($_feed_type, $_wildcard_regex) = explode('::', $_key, 2); // This regex replaces wildcards.
|
255 |
-
$_cache_path = $this->plugin->buildCachePath($_url, '', '', $flags | CACHE_PATH_ALLOW_WILDCARDS);
|
256 |
$_relative_cache_path = preg_replace('/^'.preg_quote($_host_cache_path, '/').'(?:\/|$)/i', '', $_cache_path);
|
257 |
$_relative_cache_path_regex = preg_replace('/\\\\\*/', $_wildcard_regex, preg_quote($_relative_cache_path, '/'));
|
258 |
} else {
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* Feed Utils.
|
48 |
$this->home_url = rtrim(home_url(), '/');
|
49 |
$this->default_feed = get_default_feed(); // Default feed type.
|
50 |
$this->seo_friendly_permalinks = (boolean) get_option('permalink_structure');
|
51 |
+
$this->feed_types = array_unique([$this->default_feed, 'rdf', 'rss', 'rss2', 'atom']);
|
52 |
}
|
53 |
|
54 |
/**
|
62 |
*/
|
63 |
public function feedLinkVariations($type_prefix = '')
|
64 |
{
|
65 |
+
$variations = []; // Initialize.
|
66 |
|
67 |
foreach ($this->feed_types as $_feed_type) {
|
68 |
$variations[] = get_feed_link((string) $type_prefix.$_feed_type);
|
83 |
*/
|
84 |
public function postCommentsFeedLinkVariations(\WP_Post $post)
|
85 |
{
|
86 |
+
$variations = []; // Initialize.
|
87 |
|
88 |
foreach ($this->feed_types as $_feed_type) {
|
89 |
$variations[] = get_post_comments_feed_link($post->ID, $_feed_type);
|
104 |
*/
|
105 |
public function postAuthorFeedLinkVariations(\WP_Post $post)
|
106 |
{
|
107 |
+
$variations = []; // Initialize.
|
108 |
|
109 |
foreach ($this->feed_types as $_feed_type) {
|
110 |
$variations[] = get_author_feed_link($post->post_author, $_feed_type);
|
111 |
}
|
112 |
if ($this->seo_friendly_permalinks && ($post_author = get_userdata($post->post_author))) {
|
113 |
foreach ($this->feed_types as $_feed_type) {
|
114 |
+
$variations[] = add_query_arg(urlencode_deep(['author' => $post->post_author]), $this->home_url.'/feed/'.urlencode($_feed_type).'/');
|
115 |
+
$variations[] = add_query_arg(urlencode_deep(['author' => $post_author->user_nicename]), $this->home_url.'/feed/'.urlencode($_feed_type).'/');
|
116 |
}
|
117 |
}
|
118 |
unset($_feed_type); // Housekeeping.
|
131 |
*/
|
132 |
public function postTypeArchiveFeedLinkVariations(\WP_Post $post)
|
133 |
{
|
134 |
+
$variations = []; // Initialize.
|
135 |
|
136 |
foreach ($this->feed_types as $_feed_type) {
|
137 |
$variations[] = get_post_type_archive_feed_link($post->post_type, $_feed_type);
|
158 |
*/
|
159 |
public function postTermFeedLinkVariations(\WP_Post $post, $include_regex_wildcard_keys = false)
|
160 |
{
|
161 |
+
$variations = $post_terms = []; // Initialize.
|
162 |
|
163 |
if (!is_array($post_taxonomies = get_object_taxonomies($post, 'objects')) || !$post_taxonomies) {
|
164 |
return $variations; // Nothing to do here; post has no terms.
|
202 |
$_taxonomy_query_var = $_taxonomy->query_var;
|
203 |
}
|
204 |
foreach ($this->feed_types as $_feed_type) {
|
205 |
+
$variations[] = add_query_arg(urlencode_deep([$_taxonomy_query_var => $_post_term->term_id]), $this->home_url.'/feed/'.urlencode($_feed_type).'/');
|
206 |
}
|
207 |
foreach ($this->feed_types as $_feed_type) {
|
208 |
+
$variations[] = add_query_arg(urlencode_deep([$_taxonomy_query_var => $_post_term->slug]), $this->home_url.'/feed/'.urlencode($_feed_type).'/');
|
209 |
}
|
210 |
}
|
211 |
unset($_taxonomy, $_taxonomy_query_var, $_feed_type); // Housekeeping.
|
226 |
*/
|
227 |
public function convertVariationsToHostCachePathRegexFrags(array $variations)
|
228 |
{
|
229 |
+
$regex_frags = [];
|
230 |
$is_multisite = is_multisite();
|
231 |
$can_consider_domain_mapping = $is_multisite && $this->plugin->canConsiderDomainMapping();
|
232 |
+
$flags = $this::CACHE_PATH_NO_SCHEME | $this::CACHE_PATH_NO_HOST // Default flags.
|
233 |
+
| $this::CACHE_PATH_NO_USER | $this::CACHE_PATH_NO_VSALT | $this::CACHE_PATH_NO_EXT;
|
234 |
// Flags: note that we DO allow for query string data in these regex fragments.
|
235 |
|
236 |
foreach ($variations as $_key => $_url) {
|
252 |
|
253 |
if (is_string($_key) && strpos($_key, '::') !== false && strpos($_url, '*') !== false) {
|
254 |
list($_feed_type, $_wildcard_regex) = explode('::', $_key, 2); // This regex replaces wildcards.
|
255 |
+
$_cache_path = $this->plugin->buildCachePath($_url, '', '', $flags | $this::CACHE_PATH_ALLOW_WILDCARDS);
|
256 |
$_relative_cache_path = preg_replace('/^'.preg_quote($_host_cache_path, '/').'(?:\/|$)/i', '', $_cache_path);
|
257 |
$_relative_cache_path_regex = preg_replace('/\\\\\*/', $_wildcard_regex, preg_quote($_relative_cache_path, '/'));
|
258 |
} else {
|
src/includes/classes/MenuPage.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
|
|
|
|
3 |
|
4 |
/**
|
5 |
* Menu Page.
|
@@ -22,7 +24,7 @@ class MenuPage extends AbsBase
|
|
22 |
if ($menu_page) {
|
23 |
switch ($menu_page) {
|
24 |
case 'options':
|
25 |
-
new MenuPageOptions();
|
26 |
break;
|
27 |
|
28 |
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
|
6 |
/**
|
7 |
* Menu Page.
|
24 |
if ($menu_page) {
|
25 |
switch ($menu_page) {
|
26 |
case 'options':
|
27 |
+
new Classes\MenuPageOptions();
|
28 |
break;
|
29 |
|
30 |
|
src/includes/classes/MenuPageOptions.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* Options Page.
|
@@ -20,7 +20,7 @@ class MenuPageOptions extends MenuPage
|
|
20 |
global $is_nginx; // WP global for web server checks below.
|
21 |
|
22 |
echo '<form id="plugin-menu-page" class="plugin-menu-page" method="post" enctype="multipart/form-data"'.
|
23 |
-
' action="'.esc_attr(add_query_arg(urlencode_deep(
|
24 |
|
25 |
/* ----------------------------------------------------------------------------------------- */
|
26 |
|
@@ -28,16 +28,16 @@ class MenuPageOptions extends MenuPage
|
|
28 |
|
29 |
if (is_multisite()) {
|
30 |
echo '<button type="button" class="plugin-menu-page-wipe-cache" style="float:right; margin-left:15px;" title="'.esc_attr(__('Wipe Cache (Start Fresh); clears the cache for all sites in this network at once!', 'comet-cache')).'"'.
|
31 |
-
' data-action="'.esc_attr(add_query_arg(urlencode_deep(
|
32 |
' '.__('Wipe', 'comet-cache').' <img src="'.esc_attr($this->plugin->url('/src/client-s/images/wipe.png')).'" style="width:16px; height:16px;" /></button>'."\n";
|
33 |
}
|
34 |
echo ' <button type="button" class="plugin-menu-page-clear-cache" style="float:right;" title="'.esc_attr(__('Clear Cache (Start Fresh)', 'comet-cache').((is_multisite()) ? __('; affects the current site only.', 'comet-cache') : '')).'"'.
|
35 |
-
' data-action="'.esc_attr(add_query_arg(urlencode_deep(
|
36 |
' '.__('Clear', 'comet-cache').' <img src="'.esc_attr($this->plugin->url('/src/client-s/images/clear.png')).'" style="width:16px; height:16px;" /></button>'."\n";
|
37 |
|
38 |
echo ' <button type="button" class="plugin-menu-page-restore-defaults"'.// Restores default options.
|
39 |
' data-confirmation="'.esc_attr(__('Restore default plugin options? You will lose all of your current settings! Are you absolutely sure about this?', 'comet-cache')).'"'.
|
40 |
-
' data-action="'.esc_attr(add_query_arg(urlencode_deep(
|
41 |
' '.__('Restore', 'comet-cache').' <i class="si si-ambulance"></i></button>'."\n";
|
42 |
|
43 |
echo ' <div class="plugin-menu-page-panel-togglers" title="'.esc_attr(__('All Panels', 'comet-cache')).'">'."\n";
|
@@ -47,12 +47,12 @@ class MenuPageOptions extends MenuPage
|
|
47 |
|
48 |
echo ' <div class="plugin-menu-page-upsells">'."\n";
|
49 |
if (IS_PRO && current_user_can($this->plugin->update_cap)) {
|
50 |
-
echo '<a href="'.esc_attr(add_query_arg(urlencode_deep(
|
51 |
echo '<a href="'.esc_attr('http://cometcache.com/r/comet-cache-subscribe/').'" target="_blank"><i class="si si-envelope"></i> '.__('Newsletter', 'comet-cache').'</a>'."\n";
|
52 |
echo '<a href="'.esc_attr('http://cometcache.com/r/comet-cache-beta-testers-list/').'" target="_blank"><i class="si si-envelope"></i> '.__('Beta Testers', 'comet-cache').'</a>'."\n";
|
53 |
}
|
54 |
if (!IS_PRO) {
|
55 |
-
echo ' <a href="'.esc_attr(add_query_arg(urlencode_deep(
|
56 |
echo ' <a href="'.esc_attr('http://cometcache.com/prices/').'" target="_blank"><i class="si si-heart-o"></i> '.__('Pro Upgrade', 'comet-cache').'</a>'."\n";
|
57 |
}
|
58 |
echo ' </div>'."\n";
|
@@ -80,7 +80,7 @@ class MenuPageOptions extends MenuPage
|
|
80 |
echo ' '.sprintf(__('%1$s™ Pro v%2$s', 'comet-cache'), esc_html(NAME), esc_html(VERSION))."\n";
|
81 |
|
82 |
if ($this->plugin->options['latest_pro_version'] && version_compare(VERSION, $this->plugin->options['latest_pro_version'], '<')) {
|
83 |
-
echo '(<a href="'.esc_attr(add_query_arg(urlencode_deep(
|
84 |
} else {
|
85 |
echo '(<a href="'.esc_attr('https://cometcache.com/changelog/').'" target="_blank">'.__('changelog', 'comet-cache').'</a>)'."\n";
|
86 |
}
|
@@ -173,7 +173,7 @@ class MenuPageOptions extends MenuPage
|
|
173 |
}
|
174 |
if (!IS_PRO && $this->plugin->isProPreview()) {
|
175 |
echo '<div class="plugin-menu-page-notice info">'."\n";
|
176 |
-
echo '<a href="'.add_query_arg(urlencode_deep(
|
177 |
echo ' <i class="si si-eye"></i> '.sprintf(__('<strong>Pro Features (Preview)</strong> ~ New option panels below. Please explore before <a href="http://cometcache.com/prices/" target="_blank">upgrading <i class="si si-heart-o"></i></a>.<br /><small>NOTE: the free version of %1$s (this lite version) is more-than-adequate for most sites. Please upgrade only if you desire advanced features or would like to support the developer.</small>', 'comet-cache'), esc_html(NAME))."\n";
|
178 |
echo '</div>'."\n";
|
179 |
}
|
@@ -251,9 +251,9 @@ class MenuPageOptions extends MenuPage
|
|
251 |
/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
|
252 |
|
253 |
if (IS_PRO || $this->plugin->isProPreview()) {
|
254 |
-
echo '<div class="plugin-menu-page-panel
|
255 |
|
256 |
-
echo ' <a href="#" class="plugin-menu-page-panel-heading">'."\n";
|
257 |
echo ' <i class="si si-broom"></i> '.__('Manual Cache Clearing', 'comet-cache')."\n";
|
258 |
echo ' </a>'."\n";
|
259 |
|
@@ -891,7 +891,7 @@ class MenuPageOptions extends MenuPage
|
|
891 |
echo ' <p>'.__('You don\'t have to use an <code>.htaccess</code> file to enjoy the performance enhancements provided by this plugin; caching is handled automatically by WordPress/PHP alone. That being said, if you want to take advantage of the additional speed enhancements associated w/ GZIP compression (and we do recommend this), then you WILL need an <code>.htaccess</code> file to accomplish that part.', 'comet-cache').'</p>'."\n";
|
892 |
echo ' <p>'.sprintf(__('%1$s fully supports GZIP compression on its output. However, it does not handle GZIP compression directly. We purposely left GZIP compression out of this plugin, because GZIP compression is something that should really be enabled at the Apache level or inside your <code>php.ini</code> file. GZIP compression can be used for things like JavaScript and CSS files as well, so why bother turning it on for only WordPress-generated pages when you can enable GZIP at the server level and cover all the bases!', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
|
893 |
echo ' <p>'.__('If you want to enable GZIP, create an <code>.htaccess</code> file in your WordPress® installation directory, and put the following few lines in it. Alternatively, if you already have an <code>.htaccess</code> file, just add these lines to it, and that is all there is to it. GZIP is now enabled in the recommended way! See also: <a href="https://developers.google.com/speed/articles/gzip" target="_blank"><i class="si si-youtube-play"></i> video about GZIP Compression</a>.', 'comet-cache').'</p>'."\n";
|
894 |
-
echo ' <pre class="code"><code>'.esc_html(file_get_contents(dirname(
|
895 |
echo ' <hr />'."\n";
|
896 |
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 <strong>php.ini</strong> 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></p>'."\n";
|
897 |
echo ' </div>'."\n";
|
@@ -1062,7 +1062,7 @@ class MenuPageOptions extends MenuPage
|
|
1062 |
echo ' <hr />'."\n";
|
1063 |
echo ' <h3>'.sprintf(__('Export Existing Options from this %1$s Installation?', 'comet-cache'), esc_html(NAME)).'</h3>'."\n";
|
1064 |
echo ' <button type="button" class="plugin-menu-page-export-options" style="float:right; margin: 0 0 0 25px;"'.// Exports existing options from this installation.
|
1065 |
-
' data-action="'.esc_attr(add_query_arg(urlencode_deep(
|
1066 |
' '.sprintf(__('%1$s-options.json', 'comet-cache'), GLOBAL_NS).' <i class="si si-arrow-circle-o-down"></i></button>'."\n";
|
1067 |
echo ' <p>'.sprintf(__('Download your existing options and import them all into another %1$s installation; saves time on future installs.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
|
1068 |
echo ' </div>'."\n";
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* Options Page.
|
20 |
global $is_nginx; // WP global for web server checks below.
|
21 |
|
22 |
echo '<form id="plugin-menu-page" class="plugin-menu-page" method="post" enctype="multipart/form-data"'.
|
23 |
+
' action="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, '_wpnonce' => wp_create_nonce()]), self_admin_url('/admin.php'))).'">'."\n";
|
24 |
|
25 |
/* ----------------------------------------------------------------------------------------- */
|
26 |
|
28 |
|
29 |
if (is_multisite()) {
|
30 |
echo '<button type="button" class="plugin-menu-page-wipe-cache" style="float:right; margin-left:15px;" title="'.esc_attr(__('Wipe Cache (Start Fresh); clears the cache for all sites in this network at once!', 'comet-cache')).'"'.
|
31 |
+
' data-action="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, '_wpnonce' => wp_create_nonce(), GLOBAL_NS => ['wipeCache' => '1']]), self_admin_url('/admin.php'))).'">'.
|
32 |
' '.__('Wipe', 'comet-cache').' <img src="'.esc_attr($this->plugin->url('/src/client-s/images/wipe.png')).'" style="width:16px; height:16px;" /></button>'."\n";
|
33 |
}
|
34 |
echo ' <button type="button" class="plugin-menu-page-clear-cache" style="float:right;" title="'.esc_attr(__('Clear Cache (Start Fresh)', 'comet-cache').((is_multisite()) ? __('; affects the current site only.', 'comet-cache') : '')).'"'.
|
35 |
+
' data-action="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, '_wpnonce' => wp_create_nonce(), GLOBAL_NS => ['clearCache' => '1']]), self_admin_url('/admin.php'))).'">'.
|
36 |
' '.__('Clear', 'comet-cache').' <img src="'.esc_attr($this->plugin->url('/src/client-s/images/clear.png')).'" style="width:16px; height:16px;" /></button>'."\n";
|
37 |
|
38 |
echo ' <button type="button" class="plugin-menu-page-restore-defaults"'.// Restores default options.
|
39 |
' data-confirmation="'.esc_attr(__('Restore default plugin options? You will lose all of your current settings! Are you absolutely sure about this?', 'comet-cache')).'"'.
|
40 |
+
' data-action="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, '_wpnonce' => wp_create_nonce(), GLOBAL_NS => ['restoreDefaultOptions' => '1']]), self_admin_url('/admin.php'))).'">'.
|
41 |
' '.__('Restore', 'comet-cache').' <i class="si si-ambulance"></i></button>'."\n";
|
42 |
|
43 |
echo ' <div class="plugin-menu-page-panel-togglers" title="'.esc_attr(__('All Panels', 'comet-cache')).'">'."\n";
|
47 |
|
48 |
echo ' <div class="plugin-menu-page-upsells">'."\n";
|
49 |
if (IS_PRO && current_user_can($this->plugin->update_cap)) {
|
50 |
+
echo '<a href="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS.'-pro-updater']), self_admin_url('/admin.php'))).'"><i class="si si-magic"></i> '.__('Pro Updater', 'comet-cache').'</a>'."\n";
|
51 |
echo '<a href="'.esc_attr('http://cometcache.com/r/comet-cache-subscribe/').'" target="_blank"><i class="si si-envelope"></i> '.__('Newsletter', 'comet-cache').'</a>'."\n";
|
52 |
echo '<a href="'.esc_attr('http://cometcache.com/r/comet-cache-beta-testers-list/').'" target="_blank"><i class="si si-envelope"></i> '.__('Beta Testers', 'comet-cache').'</a>'."\n";
|
53 |
}
|
54 |
if (!IS_PRO) {
|
55 |
+
echo ' <a href="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, GLOBAL_NS.'_pro_preview' => '1']), self_admin_url('/admin.php'))).'"><i class="si si-eye"></i> '.__('Preview Pro Features', 'comet-cache').'</a>'."\n";
|
56 |
echo ' <a href="'.esc_attr('http://cometcache.com/prices/').'" target="_blank"><i class="si si-heart-o"></i> '.__('Pro Upgrade', 'comet-cache').'</a>'."\n";
|
57 |
}
|
58 |
echo ' </div>'."\n";
|
80 |
echo ' '.sprintf(__('%1$s™ Pro v%2$s', 'comet-cache'), esc_html(NAME), esc_html(VERSION))."\n";
|
81 |
|
82 |
if ($this->plugin->options['latest_pro_version'] && version_compare(VERSION, $this->plugin->options['latest_pro_version'], '<')) {
|
83 |
+
echo '(<a href="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS.'-pro-updater']), self_admin_url('/admin.php'))).'" style="font-weight:bold;">'.__('update available', 'comet-cache').'</a>)'."\n";
|
84 |
} else {
|
85 |
echo '(<a href="'.esc_attr('https://cometcache.com/changelog/').'" target="_blank">'.__('changelog', 'comet-cache').'</a>)'."\n";
|
86 |
}
|
173 |
}
|
174 |
if (!IS_PRO && $this->plugin->isProPreview()) {
|
175 |
echo '<div class="plugin-menu-page-notice info">'."\n";
|
176 |
+
echo '<a href="'.add_query_arg(urlencode_deep(['page' => GLOBAL_NS]), self_admin_url('/admin.php')).'" class="pull-right" style="margin:0 0 15px 25px; float:right; font-variant:small-caps; text-decoration:none;">'.__('close', 'comet-cache').' <i class="si si-eye-slash"></i></a>'."\n";
|
177 |
echo ' <i class="si si-eye"></i> '.sprintf(__('<strong>Pro Features (Preview)</strong> ~ New option panels below. Please explore before <a href="http://cometcache.com/prices/" target="_blank">upgrading <i class="si si-heart-o"></i></a>.<br /><small>NOTE: the free version of %1$s (this lite version) is more-than-adequate for most sites. Please upgrade only if you desire advanced features or would like to support the developer.</small>', 'comet-cache'), esc_html(NAME))."\n";
|
178 |
echo '</div>'."\n";
|
179 |
}
|
251 |
/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
|
252 |
|
253 |
if (IS_PRO || $this->plugin->isProPreview()) {
|
254 |
+
echo '<div class="plugin-menu-page-panel">'."\n";
|
255 |
|
256 |
+
echo ' <a href="#" class="plugin-menu-page-panel-heading'.(!IS_PRO ? ' pro-preview-feature' : '').'">'."\n";
|
257 |
echo ' <i class="si si-broom"></i> '.__('Manual Cache Clearing', 'comet-cache')."\n";
|
258 |
echo ' </a>'."\n";
|
259 |
|
891 |
echo ' <p>'.__('You don\'t have to use an <code>.htaccess</code> file to enjoy the performance enhancements provided by this plugin; caching is handled automatically by WordPress/PHP alone. That being said, if you want to take advantage of the additional speed enhancements associated w/ GZIP compression (and we do recommend this), then you WILL need an <code>.htaccess</code> file to accomplish that part.', 'comet-cache').'</p>'."\n";
|
892 |
echo ' <p>'.sprintf(__('%1$s fully supports GZIP compression on its output. However, it does not handle GZIP compression directly. We purposely left GZIP compression out of this plugin, because GZIP compression is something that should really be enabled at the Apache level or inside your <code>php.ini</code> file. GZIP compression can be used for things like JavaScript and CSS files as well, so why bother turning it on for only WordPress-generated pages when you can enable GZIP at the server level and cover all the bases!', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
|
893 |
echo ' <p>'.__('If you want to enable GZIP, create an <code>.htaccess</code> file in your WordPress® installation directory, and put the following few lines in it. Alternatively, if you already have an <code>.htaccess</code> file, just add these lines to it, and that is all there is to it. GZIP is now enabled in the recommended way! See also: <a href="https://developers.google.com/speed/articles/gzip" target="_blank"><i class="si si-youtube-play"></i> video about GZIP Compression</a>.', 'comet-cache').'</p>'."\n";
|
894 |
+
echo ' <pre class="code"><code>'.esc_html(file_get_contents(dirname(__DIR__).'/templates/gzip-htaccess.txt')).'</code></pre>'."\n";
|
895 |
echo ' <hr />'."\n";
|
896 |
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 <strong>php.ini</strong> 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></p>'."\n";
|
897 |
echo ' </div>'."\n";
|
1062 |
echo ' <hr />'."\n";
|
1063 |
echo ' <h3>'.sprintf(__('Export Existing Options from this %1$s Installation?', 'comet-cache'), esc_html(NAME)).'</h3>'."\n";
|
1064 |
echo ' <button type="button" class="plugin-menu-page-export-options" style="float:right; margin: 0 0 0 25px;"'.// Exports existing options from this installation.
|
1065 |
+
' data-action="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, '_wpnonce' => wp_create_nonce(), GLOBAL_NS => ['exportOptions' => '1']]), self_admin_url('/admin.php'))).'">'.
|
1066 |
' '.sprintf(__('%1$s-options.json', 'comet-cache'), GLOBAL_NS).' <i class="si si-arrow-circle-o-down"></i></button>'."\n";
|
1067 |
echo ' <p>'.sprintf(__('Download your existing options and import them all into another %1$s installation; saves time on future installs.', 'comet-cache'), esc_html(NAME)).'</p>'."\n";
|
1068 |
echo ' </div>'."\n";
|
src/includes/classes/Plugin.php
CHANGED
@@ -1,5 +1,8 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
|
|
|
|
|
|
3 |
|
4 |
/**
|
5 |
* Comet Cache Plugin.
|
@@ -8,6 +11,40 @@ namespace WebSharks\CometCache;
|
|
8 |
*/
|
9 |
class Plugin extends AbsBaseAp
|
10 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
/**
|
12 |
* Enable plugin hooks?
|
13 |
*
|
@@ -24,7 +61,7 @@ class Plugin extends AbsBaseAp
|
|
24 |
*
|
25 |
* @type array Pro-only option keys.
|
26 |
*/
|
27 |
-
public $pro_only_option_keys =
|
28 |
|
29 |
/**
|
30 |
* Default options.
|
@@ -33,7 +70,7 @@ class Plugin extends AbsBaseAp
|
|
33 |
*
|
34 |
* @type array Default options.
|
35 |
*/
|
36 |
-
public $default_options =
|
37 |
|
38 |
/**
|
39 |
* Configured options.
|
@@ -42,7 +79,7 @@ class Plugin extends AbsBaseAp
|
|
42 |
*
|
43 |
* @type array Configured options.
|
44 |
*/
|
45 |
-
public $options =
|
46 |
|
47 |
/**
|
48 |
* WordPress capability.
|
@@ -108,25 +145,15 @@ class Plugin extends AbsBaseAp
|
|
108 |
{
|
109 |
parent::__construct();
|
110 |
|
111 |
-
$closures_dir = dirname(dirname(__FILE__)).'/closures/Plugin';
|
112 |
-
$self = $this; // Reference for closures.
|
113 |
-
|
114 |
-
foreach (scandir($closures_dir) as $_closure) {
|
115 |
-
if (substr($_closure, -4) === '.php') {
|
116 |
-
require $closures_dir.'/'.$_closure;
|
117 |
-
}
|
118 |
-
}
|
119 |
-
unset($_closure); // Housekeeping.
|
120 |
/* -------------------------------------------------------------- */
|
121 |
-
|
122 |
if (!($this->enable_hooks = (boolean) $enable_hooks)) {
|
123 |
return; // Stop here; construct without hooks.
|
124 |
}
|
125 |
/* -------------------------------------------------------------- */
|
126 |
|
127 |
-
add_action('
|
128 |
-
register_activation_hook(PLUGIN_FILE,
|
129 |
-
register_deactivation_hook(PLUGIN_FILE,
|
130 |
}
|
131 |
|
132 |
/**
|
@@ -148,7 +175,7 @@ class Plugin extends AbsBaseAp
|
|
148 |
|
149 |
load_plugin_textdomain(SLUG_TD); // Text domain.
|
150 |
|
151 |
-
$this->pro_only_option_keys =
|
152 |
'cache_max_age_disable_if_load_average_is_gte',
|
153 |
|
154 |
'change_notifications_enable',
|
@@ -216,13 +243,12 @@ class Plugin extends AbsBaseAp
|
|
216 |
'pro_update_username',
|
217 |
'pro_update_password',
|
218 |
'last_pro_stats_log',
|
219 |
-
|
220 |
-
$this->default_options =
|
221 |
/* Core/systematic plugin options. */
|
222 |
|
223 |
-
'version'
|
224 |
-
'welcomed'
|
225 |
-
'comet_cache_notice1_enqueued' => '0', // `0|1` announced Comet Cache yet?
|
226 |
|
227 |
'crons_setup' => '0', // A timestamp when last set up.
|
228 |
'crons_setup_on_namespace' => '', // The namespace on which they were set up.
|
@@ -382,7 +408,7 @@ class Plugin extends AbsBaseAp
|
|
382 |
/* Related to uninstallation routines. */
|
383 |
|
384 |
'uninstall_on_deletion' => '0', // `0|1`.
|
385 |
-
|
386 |
$this->default_options = $this->applyWpFilters(GLOBAL_NS.'_default_options', $this->default_options);
|
387 |
$this->options = $this->getOptions(); // Filters, validates, and returns plugin options.
|
388 |
|
@@ -398,13 +424,13 @@ class Plugin extends AbsBaseAp
|
|
398 |
}
|
399 |
/* -------------------------------------------------------------- */
|
400 |
|
401 |
-
add_action('init',
|
402 |
-
add_action('init',
|
403 |
-
add_action('init',
|
404 |
-
add_action('wp_loaded',
|
405 |
|
406 |
-
add_action('admin_init',
|
407 |
-
add_action('admin_init',
|
408 |
|
409 |
|
410 |
|
@@ -414,56 +440,56 @@ class Plugin extends AbsBaseAp
|
|
414 |
|
415 |
|
416 |
|
417 |
-
add_action('admin_enqueue_scripts',
|
418 |
-
add_action('admin_enqueue_scripts',
|
419 |
|
420 |
-
add_action('admin_menu',
|
421 |
-
add_action('network_admin_menu',
|
422 |
|
423 |
-
add_action('all_admin_notices',
|
424 |
|
425 |
-
add_filter('plugin_action_links_'.plugin_basename(PLUGIN_FILE),
|
426 |
|
427 |
-
add_filter('enable_live_network_counts',
|
428 |
|
429 |
-
add_action('activated_plugin',
|
430 |
-
add_action('deactivated_plugin',
|
431 |
-
add_action('admin_init',
|
432 |
-
add_action('safecss_save_pre',
|
433 |
-
add_action('upgrader_process_complete',
|
434 |
|
435 |
-
add_action('switch_theme',
|
436 |
-
add_action('wp_create_nav_menu',
|
437 |
-
add_action('wp_update_nav_menu',
|
438 |
-
add_action('wp_delete_nav_menu',
|
439 |
|
440 |
-
add_action('save_post',
|
441 |
-
add_action('delete_post',
|
442 |
-
add_action('clean_post_cache',
|
443 |
-
add_action('post_updated',
|
444 |
-
add_action('pre_post_update',
|
445 |
-
add_action('woocommerce_product_set_stock',
|
446 |
|
447 |
-
add_action('added_term_relationship',
|
448 |
-
add_action('delete_term_relationships',
|
449 |
|
450 |
-
add_action('trackback_post',
|
451 |
-
add_action('pingback_post',
|
452 |
-
add_action('comment_post',
|
453 |
-
add_action('transition_comment_status',
|
454 |
|
455 |
-
add_action('create_term',
|
456 |
-
add_action('edit_terms',
|
457 |
-
add_action('delete_term',
|
458 |
|
459 |
-
add_action('add_link',
|
460 |
-
add_action('edit_link',
|
461 |
-
add_action('delete_link',
|
462 |
|
463 |
|
464 |
|
465 |
if ($this->options['enable'] && $this->applyWpFilters(GLOBAL_NS.'_disable_akismet_comment_nonce', true)) {
|
466 |
-
add_filter('akismet_comment_nonce', function() {
|
467 |
return 'disabled-by-'.SLUG_TD; // MUST return a string literal that is not 'true' or '' (an empty string). See <http://bit.ly/1YItpdE>
|
468 |
}); // See also why the Akismet nonce should be disabled: <http://jas.xyz/1R23f5c>
|
469 |
}
|
@@ -476,8 +502,8 @@ class Plugin extends AbsBaseAp
|
|
476 |
/* -------------------------------------------------------------- */
|
477 |
|
478 |
if (!is_multisite() || is_main_site()) { // Main site only.
|
479 |
-
add_filter('cron_schedules',
|
480 |
-
add_action('_cron_'.GLOBAL_NS.'_cleanup',
|
481 |
|
482 |
|
483 |
}
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
use WebSharks\CometCache\Traits;
|
6 |
|
7 |
/**
|
8 |
* Comet Cache Plugin.
|
11 |
*/
|
12 |
class Plugin extends AbsBaseAp
|
13 |
{
|
14 |
+
/*[.build.php-auto-generate-use-Traits]*/
|
15 |
+
use Traits\Plugin\ActionUtils;
|
16 |
+
use Traits\Plugin\BbPressUtils;
|
17 |
+
use Traits\Plugin\CleanupUtils;
|
18 |
+
use Traits\Plugin\CondUtils;
|
19 |
+
use Traits\Plugin\CronUtils;
|
20 |
+
use Traits\Plugin\DbUtils;
|
21 |
+
use Traits\Plugin\DirUtils;
|
22 |
+
use Traits\Plugin\HtaccessUtils;
|
23 |
+
use Traits\Plugin\InstallUtils;
|
24 |
+
use Traits\Plugin\MenuPageUtils;
|
25 |
+
use Traits\Plugin\NoticeUtils;
|
26 |
+
use Traits\Plugin\OptionUtils;
|
27 |
+
use Traits\Plugin\PostUtils;
|
28 |
+
use Traits\Plugin\UpdateUtils;
|
29 |
+
use Traits\Plugin\UrlUtils;
|
30 |
+
use Traits\Plugin\UserUtils;
|
31 |
+
use Traits\Plugin\WcpAuthorUtils;
|
32 |
+
use Traits\Plugin\WcpCommentUtils;
|
33 |
+
use Traits\Plugin\WcpFeedUtils;
|
34 |
+
use Traits\Plugin\WcpHomeBlogUtils;
|
35 |
+
use Traits\Plugin\WcpJetpackUtils;
|
36 |
+
use Traits\Plugin\WcpOpcacheUtils;
|
37 |
+
use Traits\Plugin\WcpPluginUtils;
|
38 |
+
use Traits\Plugin\WcpPostTypeUtils;
|
39 |
+
use Traits\Plugin\WcpPostUtils;
|
40 |
+
use Traits\Plugin\WcpSettingUtils;
|
41 |
+
use Traits\Plugin\WcpSitemapUtils;
|
42 |
+
use Traits\Plugin\WcpTermUtils;
|
43 |
+
use Traits\Plugin\WcpUpdaterUtils;
|
44 |
+
use Traits\Plugin\WcpUtils;
|
45 |
+
use Traits\Plugin\WcpWooCommerceUtils;
|
46 |
+
/*[/.build.php-auto-generate-use-Traits]*/
|
47 |
+
|
48 |
/**
|
49 |
* Enable plugin hooks?
|
50 |
*
|
61 |
*
|
62 |
* @type array Pro-only option keys.
|
63 |
*/
|
64 |
+
public $pro_only_option_keys = [];
|
65 |
|
66 |
/**
|
67 |
* Default options.
|
70 |
*
|
71 |
* @type array Default options.
|
72 |
*/
|
73 |
+
public $default_options = [];
|
74 |
|
75 |
/**
|
76 |
* Configured options.
|
79 |
*
|
80 |
* @type array Configured options.
|
81 |
*/
|
82 |
+
public $options = [];
|
83 |
|
84 |
/**
|
85 |
* WordPress capability.
|
145 |
{
|
146 |
parent::__construct();
|
147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
/* -------------------------------------------------------------- */
|
|
|
149 |
if (!($this->enable_hooks = (boolean) $enable_hooks)) {
|
150 |
return; // Stop here; construct without hooks.
|
151 |
}
|
152 |
/* -------------------------------------------------------------- */
|
153 |
|
154 |
+
add_action('plugins_loaded', [$this, 'setup']);
|
155 |
+
register_activation_hook(PLUGIN_FILE, [$this, 'activate']);
|
156 |
+
register_deactivation_hook(PLUGIN_FILE, [$this, 'deactivate']);
|
157 |
}
|
158 |
|
159 |
/**
|
175 |
|
176 |
load_plugin_textdomain(SLUG_TD); // Text domain.
|
177 |
|
178 |
+
$this->pro_only_option_keys = [
|
179 |
'cache_max_age_disable_if_load_average_is_gte',
|
180 |
|
181 |
'change_notifications_enable',
|
243 |
'pro_update_username',
|
244 |
'pro_update_password',
|
245 |
'last_pro_stats_log',
|
246 |
+
];
|
247 |
+
$this->default_options = [
|
248 |
/* Core/systematic plugin options. */
|
249 |
|
250 |
+
'version' => VERSION,
|
251 |
+
'welcomed' => '0', // `0|1` welcomed yet?
|
|
|
252 |
|
253 |
'crons_setup' => '0', // A timestamp when last set up.
|
254 |
'crons_setup_on_namespace' => '', // The namespace on which they were set up.
|
408 |
/* Related to uninstallation routines. */
|
409 |
|
410 |
'uninstall_on_deletion' => '0', // `0|1`.
|
411 |
+
];
|
412 |
$this->default_options = $this->applyWpFilters(GLOBAL_NS.'_default_options', $this->default_options);
|
413 |
$this->options = $this->getOptions(); // Filters, validates, and returns plugin options.
|
414 |
|
424 |
}
|
425 |
/* -------------------------------------------------------------- */
|
426 |
|
427 |
+
add_action('init', [$this, 'checkAdvancedCache']);
|
428 |
+
add_action('init', [$this, 'checkBlogPaths']);
|
429 |
+
add_action('init', [$this, 'checkCronSetup'], PHP_INT_MAX);
|
430 |
+
add_action('wp_loaded', [$this, 'actions']);
|
431 |
|
432 |
+
add_action('admin_init', [$this, 'checkVersion']);
|
433 |
+
add_action('admin_init', [$this, 'maybeCheckLatestLiteVersion']);
|
434 |
|
435 |
|
436 |
|
440 |
|
441 |
|
442 |
|
443 |
+
add_action('admin_enqueue_scripts', [$this, 'enqueueAdminStyles']);
|
444 |
+
add_action('admin_enqueue_scripts', [$this, 'enqueueAdminScripts']);
|
445 |
|
446 |
+
add_action('admin_menu', [$this, 'addMenuPages']);
|
447 |
+
add_action('network_admin_menu', [$this, 'addNetworkMenuPages']);
|
448 |
|
449 |
+
add_action('all_admin_notices', [$this, 'allAdminNotices']);
|
450 |
|
451 |
+
add_filter('plugin_action_links_'.plugin_basename(PLUGIN_FILE), [$this, 'addSettingsLink']);
|
452 |
|
453 |
+
add_filter('enable_live_network_counts', [$this, 'updateBlogPaths']);
|
454 |
|
455 |
+
add_action('activated_plugin', [$this, 'autoClearOnPluginActivationDeactivation'], 10, 2);
|
456 |
+
add_action('deactivated_plugin', [$this, 'autoClearOnPluginActivationDeactivation'], 10, 2);
|
457 |
+
add_action('admin_init', [$this, 'autoClearCacheOnSettingChanges']);
|
458 |
+
add_action('safecss_save_pre', [$this, 'autoClearCacheOnJetpackCustomCss'], 10, 1);
|
459 |
+
add_action('upgrader_process_complete', [$this, 'autoClearOnUpgraderProcessComplete'], 10, 2);
|
460 |
|
461 |
+
add_action('switch_theme', [$this, 'autoClearCache']);
|
462 |
+
add_action('wp_create_nav_menu', [$this, 'autoClearCache']);
|
463 |
+
add_action('wp_update_nav_menu', [$this, 'autoClearCache']);
|
464 |
+
add_action('wp_delete_nav_menu', [$this, 'autoClearCache']);
|
465 |
|
466 |
+
add_action('save_post', [$this, 'autoClearPostCache']);
|
467 |
+
add_action('delete_post', [$this, 'autoClearPostCache']);
|
468 |
+
add_action('clean_post_cache', [$this, 'autoClearPostCache']);
|
469 |
+
add_action('post_updated', [$this, 'autoClearAuthorPageCache'], 10, 3);
|
470 |
+
add_action('pre_post_update', [$this, 'autoClearPostCacheTransition'], 10, 2);
|
471 |
+
add_action('woocommerce_product_set_stock', [$this, 'autoClearPostCacheOnWooCommerceSetStock'], 10, 1);
|
472 |
|
473 |
+
add_action('added_term_relationship', [$this, 'autoClearPostTermsCache'], 10, 1);
|
474 |
+
add_action('delete_term_relationships', [$this, 'autoClearPostTermsCache'], 10, 1);
|
475 |
|
476 |
+
add_action('trackback_post', [$this, 'autoClearCommentPostCache']);
|
477 |
+
add_action('pingback_post', [$this, 'autoClearCommentPostCache']);
|
478 |
+
add_action('comment_post', [$this, 'autoClearCommentPostCache']);
|
479 |
+
add_action('transition_comment_status', [$this, 'autoClearCommentPostCacheTransition'], 10, 3);
|
480 |
|
481 |
+
add_action('create_term', [$this, 'autoClearCache']);
|
482 |
+
add_action('edit_terms', [$this, 'autoClearCache']);
|
483 |
+
add_action('delete_term', [$this, 'autoClearCache']);
|
484 |
|
485 |
+
add_action('add_link', [$this, 'autoClearCache']);
|
486 |
+
add_action('edit_link', [$this, 'autoClearCache']);
|
487 |
+
add_action('delete_link', [$this, 'autoClearCache']);
|
488 |
|
489 |
|
490 |
|
491 |
if ($this->options['enable'] && $this->applyWpFilters(GLOBAL_NS.'_disable_akismet_comment_nonce', true)) {
|
492 |
+
add_filter('akismet_comment_nonce', function () {
|
493 |
return 'disabled-by-'.SLUG_TD; // MUST return a string literal that is not 'true' or '' (an empty string). See <http://bit.ly/1YItpdE>
|
494 |
}); // See also why the Akismet nonce should be disabled: <http://jas.xyz/1R23f5c>
|
495 |
}
|
502 |
/* -------------------------------------------------------------- */
|
503 |
|
504 |
if (!is_multisite() || is_main_site()) { // Main site only.
|
505 |
+
add_filter('cron_schedules', [$this, 'extendCronSchedules']);
|
506 |
+
add_action('_cron_'.GLOBAL_NS.'_cleanup', [$this, 'cleanupCache']);
|
507 |
|
508 |
|
509 |
}
|
src/includes/classes/VsUpgrades.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
|
4 |
/**
|
5 |
* Version-Specific Upgrades.
|
@@ -140,7 +140,7 @@ class VsUpgrades extends AbsBase
|
|
140 |
return; // Template blocks are already gone.
|
141 |
}
|
142 |
if ($htaccess = $this->plugin->readHtaccessFile($htaccess_file)) {
|
143 |
-
if (is_dir($templates_dir = dirname(
|
144 |
$htaccess['file_contents'] = str_replace(file_get_contents($templates_dir.'/v151114.txt'), '', $htaccess['file_contents']);
|
145 |
$htaccess['file_contents'] = str_replace(file_get_contents($templates_dir.'/v151114-2.txt'), '', $htaccess['file_contents']);
|
146 |
$htaccess['file_contents'] = trim($htaccess['file_contents']);
|
@@ -176,7 +176,7 @@ class VsUpgrades extends AbsBase
|
|
176 |
wp_clear_scheduled_hook('_cron_zencache_auto_cache');
|
177 |
wp_clear_scheduled_hook('_cron_zencache_cleanup');
|
178 |
}
|
179 |
-
deactivate_plugins(
|
180 |
|
181 |
if (!empty($zencache_options['base_dir'])) {
|
182 |
$this->plugin->deleteAllFilesDirsIn(WP_CONTENT_DIR.'/'.trim($zencache_options['base_dir'], '/'), true);
|
@@ -198,11 +198,10 @@ class VsUpgrades extends AbsBase
|
|
198 |
$this->plugin->activate(); // Reactivate plugin w/ new options.
|
199 |
|
200 |
$this->plugin->enqueueMainNotice(
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
);
|
205 |
}
|
206 |
}
|
207 |
-
|
208 |
}
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache\Classes;
|
3 |
|
4 |
/**
|
5 |
* Version-Specific Upgrades.
|
140 |
return; // Template blocks are already gone.
|
141 |
}
|
142 |
if ($htaccess = $this->plugin->readHtaccessFile($htaccess_file)) {
|
143 |
+
if (is_dir($templates_dir = dirname(__DIR__).'/templates/htaccess/back-compat')) {
|
144 |
$htaccess['file_contents'] = str_replace(file_get_contents($templates_dir.'/v151114.txt'), '', $htaccess['file_contents']);
|
145 |
$htaccess['file_contents'] = str_replace(file_get_contents($templates_dir.'/v151114-2.txt'), '', $htaccess['file_contents']);
|
146 |
$htaccess['file_contents'] = trim($htaccess['file_contents']);
|
176 |
wp_clear_scheduled_hook('_cron_zencache_auto_cache');
|
177 |
wp_clear_scheduled_hook('_cron_zencache_cleanup');
|
178 |
}
|
179 |
+
deactivate_plugins(['zencache/zencache.php', 'zencache-pro/zencache-pro.php'], true);
|
180 |
|
181 |
if (!empty($zencache_options['base_dir'])) {
|
182 |
$this->plugin->deleteAllFilesDirsIn(WP_CONTENT_DIR.'/'.trim($zencache_options['base_dir'], '/'), true);
|
198 |
$this->plugin->activate(); // Reactivate plugin w/ new options.
|
199 |
|
200 |
$this->plugin->enqueueMainNotice(
|
201 |
+
'<p>'.sprintf(__('<strong>Woohoo! %1$s activated.</strong> :-)', 'comet-cache'), esc_html(NAME)).'</p>'.
|
202 |
+
'<p>'.sprintf(__('NOTE: Your ZenCache options were preserved by %1$s (for more details, visit the <a href="%2$s" target="_blank">Migration FAQ</a>).'.'', 'comet-cache'), esc_html(NAME), esc_attr(IS_PRO ? 'http://cometcache.com/r/zencache-pro-migration-faq/' : 'https://cometcache.com/r/zencache-migration-faq/')).'</p>'.
|
203 |
+
'<p>'.sprintf(__('To review your configuration, please see: <a href="%2$s">%1$s → Plugin Options</a>.'.'', 'comet-cache'), esc_html(NAME), esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS]), self_admin_url('/admin.php')))).'</p>'
|
204 |
);
|
205 |
}
|
206 |
}
|
|
|
207 |
}
|
src/includes/closures/Ac/AbortUtils.php
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Ignores user aborts; when/if the Auto-Cache Engine is running.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*/
|
9 |
-
$self->maybeIgnoreUserAbort = function () use ($self) {
|
10 |
-
|
11 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Ac/AcPluginUtils.php
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Loads any advanced cache plugin files found inside `/wp-content/ac-plugins`.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*/
|
9 |
-
$self->loadAcPlugins = function () use ($self) {
|
10 |
-
if (!is_dir(WP_CONTENT_DIR.'/ac-plugins')) {
|
11 |
-
return; // Nothing to do here.
|
12 |
-
}
|
13 |
-
$GLOBALS[GLOBAL_NS.'_advanced_cache'] = $self; // Self reference.
|
14 |
-
$GLOBALS[GLOBAL_NS.'__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
15 |
-
if (!isset($GLOBALS['zencache__advanced_cache'])) {
|
16 |
-
$GLOBALS['zencache_advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
17 |
-
$GLOBALS['zencache__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
18 |
-
}
|
19 |
-
foreach ((array) glob(WP_CONTENT_DIR.'/ac-plugins/*.php') as $_ac_plugin) {
|
20 |
-
if (is_file($_ac_plugin)) {
|
21 |
-
include_once $_ac_plugin;
|
22 |
-
}
|
23 |
-
}
|
24 |
-
unset($_ac_plugin); // Houskeeping.
|
25 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Ac/BrowserUtils.php
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Sends no-cache headers (if applicable).
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite. Enhanced/altered 151220.
|
8 |
-
*/
|
9 |
-
$self->maybeStopBrowserCaching = function () use ($self) {
|
10 |
-
switch ((bool) COMET_CACHE_ALLOW_BROWSER_CACHE) {
|
11 |
-
|
12 |
-
case true: // If global config allows, check exclusions.
|
13 |
-
|
14 |
-
if (isset($_GET[strtolower(SHORT_NAME).'ABC'])) {
|
15 |
-
if (!filter_var($_GET[strtolower(SHORT_NAME).'ABC'], FILTER_VALIDATE_BOOLEAN)) {
|
16 |
-
return $self->sendNoCacheHeaders(); // Disallow.
|
17 |
-
} // Else, allow client-side caching; because `ABC` is a true-ish value.
|
18 |
-
// ↑ Note that exclusion patterns are ignored in this case, in favor of `ABC`.
|
19 |
-
} elseif (COMET_CACHE_EXCLUDE_CLIENT_SIDE_URIS && preg_match(COMET_CACHE_EXCLUDE_CLIENT_SIDE_URIS, $_SERVER['REQUEST_URI'])) {
|
20 |
-
return $self->sendNoCacheHeaders(); // Disallow.
|
21 |
-
}
|
22 |
-
return; // Allow browser caching; default behavior in this mode.
|
23 |
-
|
24 |
-
case false: // Global config disallows; check inclusions.
|
25 |
-
|
26 |
-
if (isset($_GET[strtolower(SHORT_NAME).'ABC'])) {
|
27 |
-
if (filter_var($_GET[strtolower(SHORT_NAME).'ABC'], FILTER_VALIDATE_BOOLEAN)) {
|
28 |
-
return; // Allow, because `ABC` is a false-ish value.
|
29 |
-
} // Else, disallow client-side caching; because `ABC` is a true-ish value.
|
30 |
-
// ↑ Note that inclusion patterns are ignored in this case, in favor of `ABC`.
|
31 |
-
}
|
32 |
-
return $self->sendNoCacheHeaders(); // Disallow; default behavior in this mode.
|
33 |
-
}
|
34 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Ac/NcDebugConsts.php
DELETED
@@ -1,293 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
if (defined(__NAMESPACE__.'\\NC_DEBUG_PHP_SAPI_CLI')) {
|
5 |
-
return; // Already defined these.
|
6 |
-
}
|
7 |
-
/**
|
8 |
-
* No-cache because of the current {@link \PHP_SAPI}.
|
9 |
-
*
|
10 |
-
* @since 140422 First documented version.
|
11 |
-
*
|
12 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
13 |
-
*/
|
14 |
-
const NC_DEBUG_PHP_SAPI_CLI = 'nc_debug_php_sapi_cli';
|
15 |
-
|
16 |
-
/**
|
17 |
-
* No-cache because of a missing http host.
|
18 |
-
*
|
19 |
-
* @since 140422 First documented version.
|
20 |
-
*
|
21 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
22 |
-
*/
|
23 |
-
const NC_DEBUG_NO_SERVER_HTTP_HOST = 'nc_debug_no_server_http_host';
|
24 |
-
|
25 |
-
/**
|
26 |
-
* No-cache because of a missing `$_SERVER['REQUEST_URI']`.
|
27 |
-
*
|
28 |
-
* @since 140422 First documented version.
|
29 |
-
*
|
30 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
31 |
-
*/
|
32 |
-
const NC_DEBUG_NO_SERVER_REQUEST_URI = 'nc_debug_no_server_request_uri';
|
33 |
-
|
34 |
-
/**
|
35 |
-
* No-cache because the {@link \COMET_CACHE_ALLOWED} constant says not to.
|
36 |
-
*
|
37 |
-
* @since 140422 First documented version.
|
38 |
-
*
|
39 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
40 |
-
*/
|
41 |
-
const NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT = 'nc_debug_comet_cache_allowed_constant';
|
42 |
-
|
43 |
-
/**
|
44 |
-
* No-cache because the `$_SERVER['COMET_CACHE_ALLOWED']` environment variable says not to.
|
45 |
-
*
|
46 |
-
* @since 140422 First documented version.
|
47 |
-
*
|
48 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
49 |
-
*/
|
50 |
-
const NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR = 'nc_debug_comet_cache_allowed_server_var';
|
51 |
-
|
52 |
-
/**
|
53 |
-
* No-cache because the {@link \DONOTCACHEPAGE} constant says not to.
|
54 |
-
*
|
55 |
-
* @since 140422 First documented version.
|
56 |
-
*
|
57 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
58 |
-
*/
|
59 |
-
const NC_DEBUG_DONOTCACHEPAGE_CONSTANT = 'nc_debug_donotcachepage_constant';
|
60 |
-
|
61 |
-
/**
|
62 |
-
* No-cache because the `$_SERVER['DONOTCACHEPAGE']` environment variable says not to.
|
63 |
-
*
|
64 |
-
* @since 140422 First documented version.
|
65 |
-
*
|
66 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
67 |
-
*/
|
68 |
-
const NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR = 'nc_debug_donotcachepage_server_var';
|
69 |
-
|
70 |
-
/**
|
71 |
-
* No-cache because the current request includes the `?[SHORT_NAME]AC=0` parameter.
|
72 |
-
*
|
73 |
-
* @since 140422 First documented version.
|
74 |
-
*
|
75 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
76 |
-
*/
|
77 |
-
const NC_DEBUG_AC_GET_VAR = 'nc_debug_ac_get_var';
|
78 |
-
|
79 |
-
/**
|
80 |
-
* No-cache because the current request method is `POST|PUT|DELETE`.
|
81 |
-
*
|
82 |
-
* @since 140422 First documented version.
|
83 |
-
*
|
84 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
85 |
-
*/
|
86 |
-
const NC_DEBUG_UNCACHEABLE_REQUEST = 'nc_debug_post_put_del_request';
|
87 |
-
|
88 |
-
/**
|
89 |
-
* No-cache because the current request originated from the server itself.
|
90 |
-
*
|
91 |
-
* @since 140422 First documented version.
|
92 |
-
*
|
93 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
94 |
-
*/
|
95 |
-
const NC_DEBUG_SELF_SERVE_REQUEST = 'nc_debug_self_serve_request';
|
96 |
-
|
97 |
-
/**
|
98 |
-
* No-cache because the current request is for a feed.
|
99 |
-
*
|
100 |
-
* @since 140422 First documented version.
|
101 |
-
*
|
102 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
103 |
-
*/
|
104 |
-
const NC_DEBUG_FEED_REQUEST = 'nc_debug_feed_request';
|
105 |
-
|
106 |
-
/**
|
107 |
-
* No-cache because the current request is systematic.
|
108 |
-
*
|
109 |
-
* @since 140422 First documented version.
|
110 |
-
*
|
111 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
112 |
-
*/
|
113 |
-
const NC_DEBUG_WP_SYSTEMATICS = 'nc_debug_wp_systematics';
|
114 |
-
|
115 |
-
/**
|
116 |
-
* No-cache because the current request is for an administrative area.
|
117 |
-
*
|
118 |
-
* @since 140422 First documented version.
|
119 |
-
*
|
120 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
121 |
-
*/
|
122 |
-
const NC_DEBUG_WP_ADMIN = 'nc_debug_wp_admin';
|
123 |
-
|
124 |
-
/**
|
125 |
-
* No-cache because the current request is multisite `/files/`.
|
126 |
-
*
|
127 |
-
* @since 140422 First documented version.
|
128 |
-
*
|
129 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
130 |
-
*/
|
131 |
-
const NC_DEBUG_MS_FILES = 'nc_debug_ms_files';
|
132 |
-
|
133 |
-
/**
|
134 |
-
* No-cache because the current user is like a logged-in user.
|
135 |
-
*
|
136 |
-
* @since 140422 First documented version.
|
137 |
-
*
|
138 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
139 |
-
*/
|
140 |
-
const NC_DEBUG_IS_LIKE_LOGGED_IN_USER = 'nc_debug_is_like_logged_in_user';
|
141 |
-
|
142 |
-
/**
|
143 |
-
* No-cache because the current user is logged into the site.
|
144 |
-
*
|
145 |
-
* @since 140422 First documented version.
|
146 |
-
*
|
147 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
148 |
-
*/
|
149 |
-
const NC_DEBUG_IS_LOGGED_IN_USER = 'nc_debug_is_logged_in_user';
|
150 |
-
|
151 |
-
/**
|
152 |
-
* No-cache because the current user is logged into the site and the current page contains an `nonce`.
|
153 |
-
*
|
154 |
-
* @since 151220 Enhancing logged-in user caching support.
|
155 |
-
*
|
156 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
157 |
-
*/
|
158 |
-
const NC_DEBUG_IS_LOGGED_IN_USER_NONCE = 'nc_debug_is_logged_in_user_nonce';
|
159 |
-
|
160 |
-
/**
|
161 |
-
* No-cache because the current page contains an `nonce`.
|
162 |
-
*
|
163 |
-
* @since 151220 Enhancing `nonce` detection.
|
164 |
-
*
|
165 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
166 |
-
*/
|
167 |
-
const NC_DEBUG_PAGE_CONTAINS_NONCE = 'nc_debug_page_contains_nonce';
|
168 |
-
|
169 |
-
/**
|
170 |
-
* No-cache because it was not possible to acquire a user token.
|
171 |
-
*
|
172 |
-
* @since 140422 First documented version.
|
173 |
-
*
|
174 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
175 |
-
*/
|
176 |
-
const NC_DEBUG_NO_USER_TOKEN = 'nc_debug_no_user_token';
|
177 |
-
|
178 |
-
/**
|
179 |
-
* No-cache because the current request contains a query string.
|
180 |
-
*
|
181 |
-
* @since 140422 First documented version.
|
182 |
-
*
|
183 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
184 |
-
*/
|
185 |
-
const NC_DEBUG_GET_REQUEST_QUERIES = 'nc_debug_get_request_queries';
|
186 |
-
|
187 |
-
/**
|
188 |
-
* No-cache because it's a preview.
|
189 |
-
*
|
190 |
-
* @since 151114 Adding support for preview detection.
|
191 |
-
*
|
192 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
193 |
-
*/
|
194 |
-
const NC_DEBUG_PREVIEW = 'nc_debug_preview';
|
195 |
-
|
196 |
-
/**
|
197 |
-
* No-cache because the current request excluded by its URI.
|
198 |
-
*
|
199 |
-
* @since 140422 First documented version.
|
200 |
-
*
|
201 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
202 |
-
*/
|
203 |
-
const NC_DEBUG_EXCLUDED_URIS = 'nc_debug_excluded_uris';
|
204 |
-
|
205 |
-
/**
|
206 |
-
* No-cache because the current user-agent is excluded.
|
207 |
-
*
|
208 |
-
* @since 140422 First documented version.
|
209 |
-
*
|
210 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
211 |
-
*/
|
212 |
-
const NC_DEBUG_EXCLUDED_AGENTS = 'nc_debug_excluded_agents';
|
213 |
-
|
214 |
-
/**
|
215 |
-
* No-cache because the current HTTP referrer is excluded.
|
216 |
-
*
|
217 |
-
* @since 140422 First documented version.
|
218 |
-
*
|
219 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
220 |
-
*/
|
221 |
-
const NC_DEBUG_EXCLUDED_REFS = 'nc_debug_excluded_refs';
|
222 |
-
|
223 |
-
/**
|
224 |
-
* No-cache because the current request is a 404 error.
|
225 |
-
*
|
226 |
-
* @since 140422 First documented version.
|
227 |
-
*
|
228 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
229 |
-
*/
|
230 |
-
const NC_DEBUG_404_REQUEST = 'nc_debug_404_request';
|
231 |
-
|
232 |
-
/**
|
233 |
-
* No-cache because the requested page is currently in maintenance mode.
|
234 |
-
*
|
235 |
-
* @since 140422 First documented version.
|
236 |
-
*
|
237 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
238 |
-
*/
|
239 |
-
const NC_DEBUG_MAINTENANCE_PLUGIN = 'nc_debug_maintenance_plugin';
|
240 |
-
|
241 |
-
/**
|
242 |
-
* No-cache because the current request is being compressed by an incompatible ZLIB coding type.
|
243 |
-
*
|
244 |
-
* @since 140422 First documented version.
|
245 |
-
*
|
246 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
247 |
-
*/
|
248 |
-
const NC_DEBUG_OB_ZLIB_CODING_TYPE = 'nc_debug_ob_zlib_coding_type';
|
249 |
-
|
250 |
-
/**
|
251 |
-
* No-cache because the current request resulted in a WP error message.
|
252 |
-
*
|
253 |
-
* @since 140422 First documented version.
|
254 |
-
*
|
255 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
256 |
-
*/
|
257 |
-
const NC_DEBUG_WP_ERROR_PAGE = 'nc_debug_wp_error_page';
|
258 |
-
|
259 |
-
/**
|
260 |
-
* No-cache because the current request is serving an uncacheable content type.
|
261 |
-
*
|
262 |
-
* @since 140422 First documented version.
|
263 |
-
*
|
264 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
265 |
-
*/
|
266 |
-
const NC_DEBUG_UNCACHEABLE_CONTENT_TYPE = 'nc_debug_uncacheable_content_type';
|
267 |
-
|
268 |
-
/**
|
269 |
-
* No-cache because the current request sent a non-2xx & non-404 status code.
|
270 |
-
*
|
271 |
-
* @since 140422 First documented version.
|
272 |
-
*
|
273 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
274 |
-
*/
|
275 |
-
const NC_DEBUG_UNCACHEABLE_STATUS = 'nc_debug_uncacheable_status';
|
276 |
-
|
277 |
-
/**
|
278 |
-
* No-cache because this is a new 404 error that we are symlinking.
|
279 |
-
*
|
280 |
-
* @since 140422 First documented version.
|
281 |
-
*
|
282 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
283 |
-
*/
|
284 |
-
const NC_DEBUG_1ST_TIME_404_SYMLINK = 'nc_debug_1st_time_404_symlink';
|
285 |
-
|
286 |
-
/**
|
287 |
-
* No-cache because we detected an early buffer termination.
|
288 |
-
*
|
289 |
-
* @since 140605 Improving output buffer.
|
290 |
-
*
|
291 |
-
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
292 |
-
*/
|
293 |
-
const NC_DEBUG_EARLY_BUFFER_TERMINATION = 'nc_debug_early_buffer_termination';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Ac/NcDebugUtils.php
DELETED
@@ -1,209 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* An array of debug info.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @type array An array of debug info; i.e. `reason_code` and `reason` (optional).
|
10 |
-
*/
|
11 |
-
$self->debug_info = array('reason_code' => '', 'reason' => '');
|
12 |
-
|
13 |
-
/*
|
14 |
-
* Used to setup debug info (if enabled).
|
15 |
-
*
|
16 |
-
* @since 150422 Rewrite.
|
17 |
-
*
|
18 |
-
* @param string $reason_code One of the `NC_DEBUG_` constants.
|
19 |
-
* @param string $reason Optionally override the built-in description with a custom message.
|
20 |
-
*/
|
21 |
-
$self->maybeSetDebugInfo = function ($reason_code, $reason = '') use ($self) {
|
22 |
-
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
23 |
-
return; // Nothing to do.
|
24 |
-
}
|
25 |
-
$reason = (string) $reason;
|
26 |
-
if (!($reason_code = (string) $reason_code)) {
|
27 |
-
return; // Not applicable.
|
28 |
-
}
|
29 |
-
$self->debug_info = array('reason_code' => $reason_code, 'reason' => $reason);
|
30 |
-
};
|
31 |
-
|
32 |
-
/*
|
33 |
-
* Echoes `NC_DEBUG_` info in the WordPress `shutdown` phase (if applicable).
|
34 |
-
*
|
35 |
-
* @since 150422 Rewrite.
|
36 |
-
*
|
37 |
-
* @attaches-to `shutdown` hook in WordPress w/ a late priority.
|
38 |
-
*/
|
39 |
-
$self->maybeEchoNcDebugInfo = function () use ($self) {
|
40 |
-
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
41 |
-
return; // Nothing to do.
|
42 |
-
}
|
43 |
-
if (is_admin()) {
|
44 |
-
return; // Not applicable.
|
45 |
-
}
|
46 |
-
if (strcasecmp(PHP_SAPI, 'cli') === 0) {
|
47 |
-
return; // Let's not run the risk here.
|
48 |
-
}
|
49 |
-
if ($self->debug_info && $self->hasACacheableContentType() && $self->is_a_wp_content_type) {
|
50 |
-
echo (string) $self->maybeGetNcDebugInfo($self->debug_info['reason_code'], $self->debug_info['reason']);
|
51 |
-
}
|
52 |
-
};
|
53 |
-
|
54 |
-
/*
|
55 |
-
* Gets `NC_DEBUG_` info (if applicable).
|
56 |
-
*
|
57 |
-
* @since 150422 Rewrite.
|
58 |
-
*
|
59 |
-
* @param string $reason_code One of the `NC_DEBUG_` constants.
|
60 |
-
* @param string $reason Optional; to override the default description with a custom message.
|
61 |
-
*
|
62 |
-
* @return string The debug info; i.e. full description (if applicable).
|
63 |
-
*/
|
64 |
-
$self->maybeGetNcDebugInfo = function ($reason_code = '', $reason = '') use ($self) {
|
65 |
-
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
66 |
-
return ''; // Not applicable.
|
67 |
-
}
|
68 |
-
$reason = (string) $reason;
|
69 |
-
if (!($reason_code = (string) $reason_code)) {
|
70 |
-
return ''; // Not applicable.
|
71 |
-
}
|
72 |
-
if (!$reason) {
|
73 |
-
switch ($reason_code) {
|
74 |
-
case NC_DEBUG_PHP_SAPI_CLI:
|
75 |
-
$reason = __('because `PHP_SAPI` reports that you are currently running from the command line.', 'comet-cache');
|
76 |
-
break; // Break switch handler.
|
77 |
-
|
78 |
-
case NC_DEBUG_NO_SERVER_HTTP_HOST:
|
79 |
-
$reason = __('because `$_SERVER[\'HTTP_HOST\']` is missing from your server configuration.', 'comet-cache');
|
80 |
-
break; // Break switch handler.
|
81 |
-
|
82 |
-
case NC_DEBUG_NO_SERVER_REQUEST_URI:
|
83 |
-
$reason = __('because `$_SERVER[\'REQUEST_URI\']` is missing from your server configuration.', 'comet-cache');
|
84 |
-
break; // Break switch handler.
|
85 |
-
|
86 |
-
case NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT:
|
87 |
-
if ($self->functionIsPossible('did_action') && did_action('ws_plugin__s2member_during_no_cache_constants')) {
|
88 |
-
$reason = __('because the s2Member plugin set the PHP constant `COMET_CACHE_ALLOWED` to a boolean-ish `FALSE` value at runtime. The s2Member plugin is serving content that must remain dynamic on this particular page, and therefore this page was intentionally not cached for a very good reason.', 'comet-cache');
|
89 |
-
} else {
|
90 |
-
$reason = __('because the PHP constant `COMET_CACHE_ALLOWED` has been set to a boolean-ish `FALSE` value 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');
|
91 |
-
}
|
92 |
-
break; // Break switch handler.
|
93 |
-
|
94 |
-
case NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR:
|
95 |
-
$reason = __('because the environment variable `$_SERVER[\'COMET_CACHE_ALLOWED\']` has been set to a boolean-ish `FALSE` value 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');
|
96 |
-
break; // Break switch handler.
|
97 |
-
|
98 |
-
case NC_DEBUG_DONOTCACHEPAGE_CONSTANT:
|
99 |
-
$reason = __('because the PHP constant `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');
|
100 |
-
break; // Break switch handler.
|
101 |
-
|
102 |
-
case NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR:
|
103 |
-
$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');
|
104 |
-
break; // Break switch handler.
|
105 |
-
|
106 |
-
case NC_DEBUG_AC_GET_VAR:
|
107 |
-
$reason = sprintf(__('because `$_GET[\'%1$sAC\']` is set to a boolean-ish FALSE value.', 'comet-cache'), strtolower(SHORT_NAME));
|
108 |
-
break; // Break switch handler.
|
109 |
-
|
110 |
-
case NC_DEBUG_UNCACHEABLE_REQUEST:
|
111 |
-
$reason = __('because `$_SERVER[\'REQUEST_METHOD\']` is `POST`, `PUT`, `DELETE`, `HEAD`, `OPTIONS`, `TRACE` or `CONNECT`. These request methods should never (ever) be cached in any way.', 'comet-cache');
|
112 |
-
break; // Break switch handler.
|
113 |
-
|
114 |
-
case NC_DEBUG_SELF_SERVE_REQUEST:
|
115 |
-
$reason = __('because `[current IP address]` === `$_SERVER[\'SERVER_ADDR\']`; i.e. a self-serve request. DEVELOPER TIP: if you are testing on a localhost installation, please add `define(\'LOCALHOST\', TRUE);` to your `/wp-config.php` file while you run tests :-) Remove it (or set it to a `FALSE` value) once you go live on the web.', 'comet-cache');
|
116 |
-
break; // Break switch handler.
|
117 |
-
|
118 |
-
case NC_DEBUG_FEED_REQUEST:
|
119 |
-
$reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a `/feed`; and the configuration of this site says not to cache XML-based feeds.', 'comet-cache');
|
120 |
-
break; // Break switch handler.
|
121 |
-
|
122 |
-
case NC_DEBUG_WP_SYSTEMATICS:
|
123 |
-
$reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a `wp-` or `xmlrpc` file; i.e. a WordPress systematic file. WordPress systematics are never (ever) cached in any way.', 'comet-cache');
|
124 |
-
break; // Break switch handler.
|
125 |
-
|
126 |
-
case NC_DEBUG_WP_ADMIN:
|
127 |
-
$reason = __('because `$_SERVER[\'REQUEST_URI\']` or the `is_admin()` function indicates this is an administrative area of the site.', 'comet-cache');
|
128 |
-
break; // Break switch handler.
|
129 |
-
|
130 |
-
case NC_DEBUG_MS_FILES:
|
131 |
-
$reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a Multisite Network; and this was a request for `/files/*`, not a page.', 'comet-cache');
|
132 |
-
break; // Break switch handler.
|
133 |
-
|
134 |
-
case NC_DEBUG_IS_LOGGED_IN_USER:
|
135 |
-
case NC_DEBUG_IS_LIKE_LOGGED_IN_USER:
|
136 |
-
$reason = __('because the current user visiting this page (usually YOU), appears to be logged-in. The current configuration says NOT to cache pages for logged-in visitors. This message may also appear if you have an active PHP session on this site, or if you\'ve left (or replied to) a comment recently. If this message continues, please clear your cookies and try again.', 'comet-cache');
|
137 |
-
break; // Break switch handler.
|
138 |
-
|
139 |
-
case NC_DEBUG_IS_LOGGED_IN_USER_NONCE:
|
140 |
-
$reason = __('because the current page contains `_wpnonce` or `akismet_comment_nonce`. While your current configuration states that pages SHOULD be cache for logged-in visitors, `*nonce*` values in the markup are not cache-compatible. See http://wsharks.com/1O1Kudy for further details.', 'comet-cache');
|
141 |
-
break; // Break switch handler.
|
142 |
-
|
143 |
-
case NC_DEBUG_PAGE_CONTAINS_NONCE:
|
144 |
-
$reason = __('because the current page contains `_wpnonce` or `akismet_comment_nonce`. Note that `*nonce*` values in the markup are not cache-compatible. See http://wsharks.com/1O1Kudy for further details.', 'comet-cache');
|
145 |
-
break; // Break switch handler.
|
146 |
-
|
147 |
-
case NC_DEBUG_NO_USER_TOKEN:
|
148 |
-
$reason = sprintf(__('because the current user appeared to be logged into the site (in one way or another); but %1$s was unable to formulate a User Token for them. Please report this as a possible bug.', 'comet-cache'), NAME);
|
149 |
-
break; // Break switch handler.
|
150 |
-
|
151 |
-
case NC_DEBUG_GET_REQUEST_QUERIES:
|
152 |
-
$reason = __('because `$_GET` contains query string data. The current configuration says NOT to cache GET requests with a query string.', 'comet-cache');
|
153 |
-
break; // Break switch handler.
|
154 |
-
|
155 |
-
case NC_DEBUG_PREVIEW:
|
156 |
-
$reason = __('because `$_REQUEST` indicates this is simply a preview of something to come.', 'comet-cache');
|
157 |
-
break; // Break switch handler.
|
158 |
-
|
159 |
-
case NC_DEBUG_EXCLUDED_URIS:
|
160 |
-
$reason = __('because `$_SERVER[\'REQUEST_URI\']` matches a configured URI Exclusion Pattern on this installation.', 'comet-cache');
|
161 |
-
break; // Break switch handler.
|
162 |
-
|
163 |
-
case NC_DEBUG_EXCLUDED_AGENTS:
|
164 |
-
$reason = __('because `$_SERVER[\'HTTP_USER_AGENT\']` matches a configured User-Agent Exclusion Pattern on this installation.', 'comet-cache');
|
165 |
-
break; // Break switch handler.
|
166 |
-
|
167 |
-
case NC_DEBUG_EXCLUDED_REFS:
|
168 |
-
$reason = __('because `$_SERVER[\'HTTP_REFERER\']` and/or `$_GET[\'_wp_http_referer\']` matches a configured HTTP Referrer Exclusion Pattern on this installation.', 'comet-cache');
|
169 |
-
break; // Break switch handler.
|
170 |
-
|
171 |
-
case NC_DEBUG_404_REQUEST:
|
172 |
-
$reason = __('because the WordPress `is_404()` Conditional Tag says the current page is a 404 error. The current configuration says NOT to cache 404 errors.', 'comet-cache');
|
173 |
-
break; // Break switch handler.
|
174 |
-
|
175 |
-
case NC_DEBUG_MAINTENANCE_PLUGIN:
|
176 |
-
$reason = __('because a plugin running on this installation says this page is in Maintenance Mode; i.e. is not available publicly at this time.', 'comet-cache');
|
177 |
-
break; // Break switch handler.
|
178 |
-
|
179 |
-
case NC_DEBUG_OB_ZLIB_CODING_TYPE:
|
180 |
-
$reason = sprintf(__('because %1$s is unable to cache already-compressed output. Please use `mod_deflate` w/ Apache; or use `zlib.output_compression` in your `php.ini` file. %1$s is NOT compatible with `ob_gzhandler()` and others like this.', 'comet-cache'), NAME);
|
181 |
-
break; // Break switch handler.
|
182 |
-
|
183 |
-
case NC_DEBUG_WP_ERROR_PAGE:
|
184 |
-
$reason = __('because the contents of this document contain `<body id="error-page">`, which indicates this is an auto-generated WordPress error message.', 'comet-cache');
|
185 |
-
break; // Break switch handler.
|
186 |
-
|
187 |
-
case NC_DEBUG_UNCACHEABLE_CONTENT_TYPE:
|
188 |
-
$reason = __('because a `Content-Type:` header was set via PHP at runtime. The header contains a MIME type which is NOT a variation of HTML or XML. This header might have been set by your hosting company, by WordPress itself; or by one of your themes/plugins.', 'comet-cache');
|
189 |
-
break; // Break switch handler.
|
190 |
-
|
191 |
-
case NC_DEBUG_UNCACHEABLE_STATUS:
|
192 |
-
$reason = __('because a `Status:` header (or an `HTTP/` header) was set via PHP at runtime. The header contains a non-`2xx` status code. This indicates the current page was not loaded successfully. This header might have been set by your hosting company, by WordPress itself; or by one of your themes/plugins.', 'comet-cache');
|
193 |
-
break; // Break switch handler.
|
194 |
-
|
195 |
-
case NC_DEBUG_1ST_TIME_404_SYMLINK:
|
196 |
-
$reason = sprintf(__('because the WordPress `is_404()` Conditional Tag says the current page is a 404 error; and this is the first time it\'s happened on this page. Your current configuration says that 404 errors SHOULD be cached, so %1$s built a cached symlink which points future requests for this location to your already-cached 404 error document. If you reload this page (assuming you don\'t clear the cache before you do so); you should get a cached version of your 404 error document. This message occurs ONCE for each new/unique 404 error request.', 'comet-cache'), NAME);
|
197 |
-
break; // Break switch handler.
|
198 |
-
|
199 |
-
case NC_DEBUG_EARLY_BUFFER_TERMINATION:
|
200 |
-
$reason = sprintf(__('because %1$s detected an early output buffer termination. This may happen when a theme/plugin ends, cleans, or flushes all output buffers before reaching the PHP shutdown phase. It\'s not always a bad thing. Sometimes it is necessary for a theme/plugin to do this. However, in this scenario it is NOT possible to cache the output; since %1$s is effectively disabled at runtime when this occurs.', 'comet-cache'), NAME);
|
201 |
-
break; // Break switch handler.
|
202 |
-
|
203 |
-
default: // Default case handler.
|
204 |
-
$reason = __('due to an unexpected behavior in the application. Please report this as a bug!', 'comet-cache');
|
205 |
-
break; // Break switch handler.
|
206 |
-
}
|
207 |
-
}
|
208 |
-
return "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s is NOT caching this page, %2$s', 'comet-cache'), NAME, $reason)).' -->';
|
209 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Ac/ObUtils.php
DELETED
@@ -1,353 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Calculated protocol; one of `http://` or `https://`.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @type float One of `http://` or `https://`.
|
10 |
-
*/
|
11 |
-
$self->protocol = '';
|
12 |
-
|
13 |
-
/*
|
14 |
-
* Host token for this request.
|
15 |
-
*
|
16 |
-
* @since 150821 Improving multisite compat.
|
17 |
-
*
|
18 |
-
* @type string Host token for this request.
|
19 |
-
*/
|
20 |
-
$self->host_token = '';
|
21 |
-
|
22 |
-
/*
|
23 |
-
* Host base/dir tokens for this request.
|
24 |
-
*
|
25 |
-
* @since 150821 Improving multisite compat.
|
26 |
-
*
|
27 |
-
* @type string Host base/dir tokens for this request.
|
28 |
-
*/
|
29 |
-
$self->host_base_dir_tokens = '';
|
30 |
-
|
31 |
-
/*
|
32 |
-
* Calculated version salt; set by site configuration data.
|
33 |
-
*
|
34 |
-
* @since 150422 Rewrite.
|
35 |
-
*
|
36 |
-
* @type string|mixed Any scalar value does fine.
|
37 |
-
*/
|
38 |
-
$self->version_salt = '';
|
39 |
-
|
40 |
-
/*
|
41 |
-
* Relative cache path for the current request.
|
42 |
-
*
|
43 |
-
* @since 150422 Rewrite.
|
44 |
-
*
|
45 |
-
* @type string Cache path for the current request.
|
46 |
-
*/
|
47 |
-
$self->cache_path = '';
|
48 |
-
|
49 |
-
/*
|
50 |
-
* Absolute cache file path for the current request.
|
51 |
-
*
|
52 |
-
* @since 150422 Rewrite.
|
53 |
-
*
|
54 |
-
* @type string Absolute cache file path for the current request.
|
55 |
-
*/
|
56 |
-
$self->cache_file = '';
|
57 |
-
|
58 |
-
/*
|
59 |
-
* Relative 404 cache path for the current request.
|
60 |
-
*
|
61 |
-
* @since 150422 Rewrite.
|
62 |
-
*
|
63 |
-
* @type string 404 cache path for the current request.
|
64 |
-
*/
|
65 |
-
$self->cache_path_404 = '';
|
66 |
-
|
67 |
-
/*
|
68 |
-
* Absolute 404 cache file path for the current request.
|
69 |
-
*
|
70 |
-
* @since 150422 Rewrite.
|
71 |
-
*
|
72 |
-
* @type string Absolute 404 cache file path for the current request.
|
73 |
-
*/
|
74 |
-
$self->cache_file_404 = '';
|
75 |
-
|
76 |
-
/*
|
77 |
-
* Version salt followed by the current request location.
|
78 |
-
*
|
79 |
-
* @since 150422 Rewrite.
|
80 |
-
*
|
81 |
-
* @type string Version salt followed by the current request location.
|
82 |
-
*/
|
83 |
-
$self->salt_location = '';
|
84 |
-
|
85 |
-
/*
|
86 |
-
* Calculated max age; i.e., before expiration.
|
87 |
-
*
|
88 |
-
* @since 151002 Load average checks in pro version.
|
89 |
-
*
|
90 |
-
* @type integer Calculated max age; i.e., before expiration.
|
91 |
-
*/
|
92 |
-
$self->cache_max_age = 0;
|
93 |
-
|
94 |
-
/*
|
95 |
-
* Start output buffering (if applicable); or serve a cache file (if possible).
|
96 |
-
*
|
97 |
-
* @since 150422 Rewrite.
|
98 |
-
*
|
99 |
-
* @note This is a vital part of Comet Cache. This method serves existing (fresh) cache files.
|
100 |
-
* It is also responsible for beginning the process of collecting the output buffer.
|
101 |
-
*/
|
102 |
-
$self->maybeStartOutputBuffering = function () use ($self) {
|
103 |
-
if (strcasecmp(PHP_SAPI, 'cli') === 0) {
|
104 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_PHP_SAPI_CLI);
|
105 |
-
}
|
106 |
-
if (empty($_SERVER['HTTP_HOST']) || !$self->hostToken()) {
|
107 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_NO_SERVER_HTTP_HOST);
|
108 |
-
}
|
109 |
-
if (empty($_SERVER['REQUEST_URI'])) {
|
110 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_NO_SERVER_REQUEST_URI);
|
111 |
-
}
|
112 |
-
if (defined('COMET_CACHE_ALLOWED') && !COMET_CACHE_ALLOWED) {
|
113 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT);
|
114 |
-
}
|
115 |
-
if (isset($_SERVER['COMET_CACHE_ALLOWED']) && !$_SERVER['COMET_CACHE_ALLOWED']) {
|
116 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR);
|
117 |
-
}
|
118 |
-
if (defined('DONOTCACHEPAGE')) {
|
119 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_DONOTCACHEPAGE_CONSTANT);
|
120 |
-
}
|
121 |
-
if (isset($_SERVER['DONOTCACHEPAGE'])) {
|
122 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
|
123 |
-
}
|
124 |
-
if (isset($_GET[strtolower(SHORT_NAME).'AC']) && !filter_var($_GET[strtolower(SHORT_NAME).'AC'], FILTER_VALIDATE_BOOLEAN)) {
|
125 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_AC_GET_VAR);
|
126 |
-
}
|
127 |
-
if ($self->isUncacheableRequestMethod()) {
|
128 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_UNCACHEABLE_REQUEST);
|
129 |
-
}
|
130 |
-
if (isset($_SERVER['SERVER_ADDR']) && $self->currentIp() === $_SERVER['SERVER_ADDR']) {
|
131 |
-
if ((!IS_PRO || !$self->isAutoCacheEngine()) && !$self->isLocalhost()) {
|
132 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_SELF_SERVE_REQUEST);
|
133 |
-
}
|
134 |
-
}
|
135 |
-
if (!COMET_CACHE_FEEDS_ENABLE && $self->isFeed()) {
|
136 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_FEED_REQUEST);
|
137 |
-
}
|
138 |
-
if (preg_match('/\/(?:wp\-[^\/]+|xmlrpc)\.php(?:[?]|$)/i', $_SERVER['REQUEST_URI'])) {
|
139 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_WP_SYSTEMATICS);
|
140 |
-
}
|
141 |
-
if (is_admin() || preg_match('/\/wp-admin(?:[\/?]|$)/i', $_SERVER['REQUEST_URI'])) {
|
142 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_WP_ADMIN);
|
143 |
-
}
|
144 |
-
if (is_multisite() && preg_match('/\/files(?:[\/?]|$)/i', $_SERVER['REQUEST_URI'])) {
|
145 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_MS_FILES);
|
146 |
-
}
|
147 |
-
if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $self->isLikeUserLoggedIn()) {
|
148 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_IS_LIKE_LOGGED_IN_USER);
|
149 |
-
}
|
150 |
-
if (!COMET_CACHE_GET_REQUESTS && $self->requestContainsUncacheableQueryVars()) {
|
151 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_GET_REQUEST_QUERIES);
|
152 |
-
}
|
153 |
-
if (!empty($_REQUEST['preview'])) {
|
154 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_PREVIEW);
|
155 |
-
}
|
156 |
-
if (COMET_CACHE_EXCLUDE_URIS && preg_match(COMET_CACHE_EXCLUDE_URIS, $_SERVER['REQUEST_URI'])) {
|
157 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_EXCLUDED_URIS);
|
158 |
-
}
|
159 |
-
if (COMET_CACHE_EXCLUDE_AGENTS && !empty($_SERVER['HTTP_USER_AGENT']) && (!IS_PRO || !$self->isAutoCacheEngine())) {
|
160 |
-
if (preg_match(COMET_CACHE_EXCLUDE_AGENTS, $_SERVER['HTTP_USER_AGENT'])) {
|
161 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_EXCLUDED_AGENTS);
|
162 |
-
}
|
163 |
-
}
|
164 |
-
if (COMET_CACHE_EXCLUDE_REFS && !empty($_REQUEST['_wp_http_referer'])) {
|
165 |
-
if (preg_match(COMET_CACHE_EXCLUDE_REFS, stripslashes($_REQUEST['_wp_http_referer']))) {
|
166 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_EXCLUDED_REFS);
|
167 |
-
}
|
168 |
-
}
|
169 |
-
if (COMET_CACHE_EXCLUDE_REFS && !empty($_SERVER['HTTP_REFERER'])) {
|
170 |
-
if (preg_match(COMET_CACHE_EXCLUDE_REFS, $_SERVER['HTTP_REFERER'])) {
|
171 |
-
return $self->maybeSetDebugInfo(NC_DEBUG_EXCLUDED_REFS);
|
172 |
-
}
|
173 |
-
}
|
174 |
-
$self->protocol = $self->isSsl() ? 'https://' : 'http://';
|
175 |
-
$self->host_token = $self->hostToken();
|
176 |
-
$self->host_base_dir_tokens = $self->hostBaseDirTokens();
|
177 |
-
|
178 |
-
$self->version_salt = ''; // Initialize the version salt.
|
179 |
-
|
180 |
-
$self->version_salt = $self->applyFilters(get_class($self).'__version_salt', $self->version_salt);
|
181 |
-
$self->version_salt = $self->applyFilters(GLOBAL_NS.'_version_salt', $self->version_salt);
|
182 |
-
|
183 |
-
$self->cache_path = $self->buildCachePath($self->protocol.$self->host_token.$_SERVER['REQUEST_URI'], '', $self->version_salt);
|
184 |
-
$self->cache_file = COMET_CACHE_DIR.'/'.$self->cache_path; // Not considering a user cache. That's done in the postload phase.
|
185 |
-
|
186 |
-
$self->cache_path_404 = $self->buildCachePath($self->protocol.$self->host_token.rtrim($self->host_base_dir_tokens, '/').'/'.COMET_CACHE_404_CACHE_FILENAME);
|
187 |
-
$self->cache_file_404 = COMET_CACHE_DIR.'/'.$self->cache_path_404; // Not considering a user cache at all here--ever.
|
188 |
-
|
189 |
-
$self->salt_location = ltrim($self->version_salt.' '.$self->protocol.$self->host_token.$_SERVER['REQUEST_URI']);
|
190 |
-
|
191 |
-
$self->cache_max_age = strtotime('-'.COMET_CACHE_MAX_AGE);
|
192 |
-
|
193 |
-
if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN === 'postload' && $self->isLikeUserLoggedIn()) {
|
194 |
-
$self->postload['when_logged_in'] = true; // Enable postload check.
|
195 |
-
} elseif (is_file($self->cache_file) && (!$self->cache_max_age || filemtime($self->cache_file) >= $self->cache_max_age)) {
|
196 |
-
list($headers, $cache) = explode('<!--headers-->', file_get_contents($self->cache_file), 2);
|
197 |
-
|
198 |
-
$headers_list = $self->headersList();
|
199 |
-
foreach (unserialize($headers) as $_header) {
|
200 |
-
if (!in_array($_header, $headers_list, true) && stripos($_header, 'Last-Modified:') !== 0) {
|
201 |
-
header($_header); // Only cacheable/safe headers are stored in the cache.
|
202 |
-
}
|
203 |
-
}
|
204 |
-
unset($_header); // Just a little housekeeping.
|
205 |
-
|
206 |
-
if (COMET_CACHE_DEBUGGING_ENABLE && $self->isHtmlXmlDoc($cache)) {
|
207 |
-
$total_time = number_format(microtime(true) - $self->timer, 5, '.', '');
|
208 |
-
$cache .= "\n".'<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->';
|
209 |
-
// translators: This string is actually NOT translatable because the `__()` function is not available at this point in the processing.
|
210 |
-
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s fully functional :-) Cache file served for (%2$s) in %3$s seconds, on: %4$s.', 'comet-cache'), NAME, $self->salt_location, $total_time, date('M jS, Y @ g:i a T'))).' -->';
|
211 |
-
}
|
212 |
-
exit($cache); // Exit with cache contents.
|
213 |
-
} else {
|
214 |
-
ob_start(array($self, 'outputBufferCallbackHandler'));
|
215 |
-
}
|
216 |
-
return; // Return value not applicable.
|
217 |
-
};
|
218 |
-
|
219 |
-
/*
|
220 |
-
* Output buffer handler; i.e. the cache file generator.
|
221 |
-
*
|
222 |
-
* @note We CANNOT depend on any WP functionality here; it will cause problems.
|
223 |
-
* Anything we need from WP should be saved in the postload phase as a scalar value.
|
224 |
-
*
|
225 |
-
* @since 150422 Rewrite.
|
226 |
-
*
|
227 |
-
* @param string $buffer The buffer from {@link \ob_start()}.
|
228 |
-
* @param int $phase A set of bitmask flags.
|
229 |
-
*
|
230 |
-
* @throws \Exception If unable to handle output buffering for any reason.
|
231 |
-
*
|
232 |
-
* @return string|bool The output buffer, or `FALSE` to indicate no change.
|
233 |
-
*
|
234 |
-
* @attaches-to {@link \ob_start()}
|
235 |
-
*/
|
236 |
-
$self->outputBufferCallbackHandler = function ($buffer, $phase) use ($self) {
|
237 |
-
if (!($phase & PHP_OUTPUT_HANDLER_END)) {
|
238 |
-
throw new \Exception(sprintf(__('Unexpected OB phase: `%1$s`.', 'comet-cache'), $phase));
|
239 |
-
}
|
240 |
-
AdvCacheBackCompat::zenCacheConstants();
|
241 |
-
|
242 |
-
$cache = trim((string) $buffer);
|
243 |
-
|
244 |
-
if (!isset($cache[0])) {
|
245 |
-
return false; // Don't cache an empty buffer.
|
246 |
-
}
|
247 |
-
if (!isset($GLOBALS[GLOBAL_NS.'_shutdown_flag'])) {
|
248 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_EARLY_BUFFER_TERMINATION);
|
249 |
-
}
|
250 |
-
if (defined('COMET_CACHE_ALLOWED') && !COMET_CACHE_ALLOWED) {
|
251 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT);
|
252 |
-
}
|
253 |
-
if (isset($_SERVER['COMET_CACHE_ALLOWED']) && !$_SERVER['COMET_CACHE_ALLOWED']) {
|
254 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR);
|
255 |
-
}
|
256 |
-
if (defined('DONOTCACHEPAGE')) {
|
257 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_DONOTCACHEPAGE_CONSTANT);
|
258 |
-
}
|
259 |
-
if (isset($_SERVER['DONOTCACHEPAGE'])) {
|
260 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
|
261 |
-
}
|
262 |
-
if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $self->is_user_logged_in) {
|
263 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_IS_LOGGED_IN_USER);
|
264 |
-
}
|
265 |
-
if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $self->isLikeUserLoggedIn()) {
|
266 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_IS_LIKE_LOGGED_IN_USER);
|
267 |
-
}
|
268 |
-
if (!COMET_CACHE_CACHE_NONCE_VALUES && preg_match('/\b(?:_wpnonce|akismet_comment_nonce)\b/', $cache)) {
|
269 |
-
if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $self->isLikeUserLoggedIn()) {
|
270 |
-
if (!COMET_CACHE_CACHE_NONCE_VALUES_WHEN_LOGGED_IN) {
|
271 |
-
return (boolean)$self->maybeSetDebugInfo(NC_DEBUG_IS_LOGGED_IN_USER_NONCE);
|
272 |
-
}
|
273 |
-
} else { // Use the default debug notice for nonce conflicts.
|
274 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_PAGE_CONTAINS_NONCE);
|
275 |
-
} // An nonce makes the page dynamic; i.e., NOT cache compatible.
|
276 |
-
}
|
277 |
-
if ($self->is_404 && !COMET_CACHE_CACHE_404_REQUESTS) {
|
278 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_404_REQUEST);
|
279 |
-
}
|
280 |
-
if (stripos($cache, '<body id="error-page">') !== false) {
|
281 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_WP_ERROR_PAGE);
|
282 |
-
}
|
283 |
-
if (!$self->functionIsPossible('http_response_code')) {
|
284 |
-
if (stripos($cache, '<title>database error</title>') !== false) {
|
285 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_WP_ERROR_PAGE);
|
286 |
-
}
|
287 |
-
}
|
288 |
-
if (!$self->hasACacheableContentType()) {
|
289 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_UNCACHEABLE_CONTENT_TYPE);
|
290 |
-
}
|
291 |
-
if (!$self->hasACacheableStatus()) {
|
292 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_UNCACHEABLE_STATUS);
|
293 |
-
}
|
294 |
-
if ($self->is_maintenance) {
|
295 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_MAINTENANCE_PLUGIN);
|
296 |
-
}
|
297 |
-
if ($self->functionIsPossible('zlib_get_coding_type') && zlib_get_coding_type()
|
298 |
-
&& (!($zlib_oc = ini_get('zlib.output_compression')) || !filter_var($zlib_oc, FILTER_VALIDATE_BOOLEAN))) {
|
299 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_OB_ZLIB_CODING_TYPE);
|
300 |
-
}
|
301 |
-
# Lock the cache directory while writes take place here.
|
302 |
-
|
303 |
-
$cache_lock = $self->cacheLock(); // Lock cache directory.
|
304 |
-
|
305 |
-
# Construct a temp file for atomic cache writes.
|
306 |
-
|
307 |
-
$cache_file_tmp = $self->addTmpSuffix($self->cache_file);
|
308 |
-
|
309 |
-
# Cache directory checks. The cache file directory is created here if necessary.
|
310 |
-
|
311 |
-
if (!is_dir(COMET_CACHE_DIR) && mkdir(COMET_CACHE_DIR, 0775, true) && !is_file(COMET_CACHE_DIR.'/.htaccess')) {
|
312 |
-
file_put_contents(COMET_CACHE_DIR.'/.htaccess', $self->htaccess_deny);
|
313 |
-
}
|
314 |
-
if (!is_dir($cache_file_dir = dirname($self->cache_file))) {
|
315 |
-
$cache_file_dir_writable = mkdir($cache_file_dir, 0775, true);
|
316 |
-
}
|
317 |
-
if (empty($cache_file_dir_writable) && !is_writable($cache_file_dir)) {
|
318 |
-
throw new \Exception(sprintf(__('Cache directory not writable. %1$s needs this directory please: `%2$s`. Set permissions to `755` or higher; `777` might be needed in some cases.', 'comet-cache'), NAME, $cache_file_dir));
|
319 |
-
}
|
320 |
-
# This is where a new 404 request might be detected for the first time.
|
321 |
-
|
322 |
-
if ($self->is_404 && is_file($self->cache_file_404)) {
|
323 |
-
if (!(symlink($self->cache_file_404, $cache_file_tmp) && rename($cache_file_tmp, $self->cache_file))) {
|
324 |
-
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'), $self->cache_file, $self->cache_file_404, COMET_CACHE_DIR));
|
325 |
-
}
|
326 |
-
$self->cacheUnlock($cache_lock); // Release.
|
327 |
-
return (boolean) $self->maybeSetDebugInfo(NC_DEBUG_1ST_TIME_404_SYMLINK);
|
328 |
-
}
|
329 |
-
/* ------- Otherwise, we need to construct & store a new cache file. ----------------------------------------------- */
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
if (COMET_CACHE_DEBUGGING_ENABLE && $self->isHtmlXmlDoc($cache)) {
|
334 |
-
$total_time = number_format(microtime(true) - $self->timer, 5, '.', ''); // Based on the original timer.
|
335 |
-
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s file path: %2$s', 'comet-cache'), NAME, str_replace(WP_CONTENT_DIR, '', $self->is_404 ? $self->cache_file_404 : $self->cache_file))).' -->';
|
336 |
-
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s file built for (%2$s%3$s) in %4$s seconds, on: %5$s.', 'comet-cache'), NAME, $self->is_404 ? '404 [error document]' : $self->salt_location, (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $self->user_token ? '; '.sprintf(__('user token: %1$s', 'comet-cache'), $self->user_token) : ''), $total_time, date('M jS, Y @ g:i a T'))).' -->';
|
337 |
-
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('This %1$s file will auto-expire (and be rebuilt) on: %2$s (based on your configured expiration time).', 'comet-cache'), NAME, date('M jS, Y @ g:i a T', strtotime('+'.COMET_CACHE_MAX_AGE)))).' -->';
|
338 |
-
}
|
339 |
-
if ($self->is_404) {
|
340 |
-
if (file_put_contents($cache_file_tmp, serialize($self->cacheableHeadersList()).'<!--headers-->'.$cache) && rename($cache_file_tmp, $self->cache_file_404)) {
|
341 |
-
if (!(symlink($self->cache_file_404, $cache_file_tmp) && rename($cache_file_tmp, $self->cache_file))) {
|
342 |
-
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'), $self->cache_file, $self->cache_file_404, COMET_CACHE_DIR));
|
343 |
-
}
|
344 |
-
$self->cacheUnlock($cache_lock); // Release.
|
345 |
-
return $cache; // Return the newly built cache; with possible debug information also.
|
346 |
-
}
|
347 |
-
} elseif (file_put_contents($cache_file_tmp, serialize($self->cacheableHeadersList()).'<!--headers-->'.$cache) && rename($cache_file_tmp, $self->cache_file)) {
|
348 |
-
$self->cacheUnlock($cache_lock); // Release.
|
349 |
-
return $cache; // Return the newly built cache; with possible debug information also.
|
350 |
-
}
|
351 |
-
@unlink($cache_file_tmp); // Clean this up (if it exists); and throw an exception with information for the site owner.
|
352 |
-
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));
|
353 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Ac/PostloadUtils.php
DELETED
@@ -1,187 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Have we caught the main WP loaded being loaded yet?
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @type bool `TRUE` if main query has been loaded; else `FALSE`.
|
10 |
-
*
|
11 |
-
* @see wpMainQueryPostload()
|
12 |
-
*/
|
13 |
-
$self->is_wp_loaded_query = false;
|
14 |
-
|
15 |
-
/*
|
16 |
-
* Is the current request a WordPress 404 error?
|
17 |
-
*
|
18 |
-
* @since 150422 Rewrite.
|
19 |
-
*
|
20 |
-
* @type bool `TRUE` if is a 404 error; else `FALSE`.
|
21 |
-
*
|
22 |
-
* @see wpMainQueryPostload()
|
23 |
-
*/
|
24 |
-
$self->is_404 = false;
|
25 |
-
|
26 |
-
/*
|
27 |
-
* Last HTTP status code passed through {@link \status_header}.
|
28 |
-
*
|
29 |
-
* @since 150422 Rewrite.
|
30 |
-
*
|
31 |
-
* @type int Last HTTP status code (if applicable).
|
32 |
-
*
|
33 |
-
* @see maybeFilterStatusHeaderPostload()
|
34 |
-
*/
|
35 |
-
$self->http_status = 0;
|
36 |
-
|
37 |
-
/*
|
38 |
-
* Is the current request a WordPress content type?
|
39 |
-
*
|
40 |
-
* @since 150422 Rewrite.
|
41 |
-
*
|
42 |
-
* @type bool `TRUE` if is a WP content type.
|
43 |
-
*
|
44 |
-
* @see wpMainQueryPostload()
|
45 |
-
*/
|
46 |
-
$self->is_a_wp_content_type = false;
|
47 |
-
|
48 |
-
/*
|
49 |
-
* Current WordPress {@link \content_url()}.
|
50 |
-
*
|
51 |
-
* @since 150422 Rewrite.
|
52 |
-
*
|
53 |
-
* @type string Current WordPress {@link \content_url()}.
|
54 |
-
*
|
55 |
-
* @see wpMainQueryPostload()
|
56 |
-
*/
|
57 |
-
$self->content_url = '';
|
58 |
-
|
59 |
-
/*
|
60 |
-
* Flag for {@link \is_user_loged_in()}.
|
61 |
-
*
|
62 |
-
* @since 150422 Rewrite.
|
63 |
-
*
|
64 |
-
* @type bool `TRUE` if {@link \is_user_loged_in()}; else `FALSE`.
|
65 |
-
*
|
66 |
-
* @see wpMainQueryPostload()
|
67 |
-
*/
|
68 |
-
$self->is_user_logged_in = false;
|
69 |
-
|
70 |
-
/*
|
71 |
-
* Flag for {@link \is_maintenance()}.
|
72 |
-
*
|
73 |
-
* @since 150422 Rewrite.
|
74 |
-
*
|
75 |
-
* @type bool `TRUE` if {@link \is_maintenance()}; else `FALSE`.
|
76 |
-
*
|
77 |
-
* @see wpMainQueryPostload()
|
78 |
-
*/
|
79 |
-
$self->is_maintenance = false;
|
80 |
-
|
81 |
-
/*
|
82 |
-
* Array of data targeted at the postload phase.
|
83 |
-
*
|
84 |
-
* @since 150422 Rewrite.
|
85 |
-
*
|
86 |
-
* @type array Data and/or flags that work with various postload handlers.
|
87 |
-
*/
|
88 |
-
$self->postload = array(
|
89 |
-
|
90 |
-
'filter_status_header' => true,
|
91 |
-
'wp_main_query' => true,
|
92 |
-
'set_debug_info' => COMET_CACHE_DEBUGGING_ENABLE,
|
93 |
-
);
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
/*
|
104 |
-
* Filters WP {@link \status_header()} (if applicable).
|
105 |
-
*
|
106 |
-
* @since 150422 Rewrite.
|
107 |
-
*/
|
108 |
-
$self->maybeFilterStatusHeaderPostload = function () use ($self) {
|
109 |
-
if (empty($self->postload['filter_status_header'])) {
|
110 |
-
return; // Nothing to do in this case.
|
111 |
-
}
|
112 |
-
$_self = $self; // Reference needed below.
|
113 |
-
|
114 |
-
add_filter(
|
115 |
-
'status_header',
|
116 |
-
function ($status_header, $status_code) use ($_self) {
|
117 |
-
if ($status_code > 0) {
|
118 |
-
$_self->http_status = (integer) $status_code;
|
119 |
-
}
|
120 |
-
return $status_header;
|
121 |
-
},
|
122 |
-
PHP_INT_MAX,
|
123 |
-
2
|
124 |
-
);
|
125 |
-
};
|
126 |
-
|
127 |
-
/*
|
128 |
-
* Hooks `NC_DEBUG_` info into the WordPress `shutdown` phase (if applicable).
|
129 |
-
*
|
130 |
-
* @since 150422 Rewrite.
|
131 |
-
*/
|
132 |
-
$self->maybeSetDebugInfoPostload = function () use ($self) {
|
133 |
-
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
134 |
-
return; // Nothing to do.
|
135 |
-
}
|
136 |
-
if (empty($self->postload['set_debug_info'])) {
|
137 |
-
return; // Nothing to do in this case.
|
138 |
-
}
|
139 |
-
if (is_admin()) {
|
140 |
-
return; // Not applicable.
|
141 |
-
}
|
142 |
-
if (strcasecmp(PHP_SAPI, 'cli') === 0) {
|
143 |
-
return; // Let's not run the risk here.
|
144 |
-
}
|
145 |
-
add_action('shutdown', array($self, 'maybeEchoNcDebugInfo'), PHP_INT_MAX - 10);
|
146 |
-
};
|
147 |
-
|
148 |
-
/*
|
149 |
-
* Grab details from WP and the Comet Cache plugin itself,
|
150 |
-
* after the main query is loaded (if at all possible).
|
151 |
-
*
|
152 |
-
* This is where we have a chance to grab any values we need from WordPress; or from the CC plugin.
|
153 |
-
* It is EXTREMEMLY important that we NOT attempt to grab any object references here.
|
154 |
-
* Anything acquired in this phase should be stored as a scalar value.
|
155 |
-
* See {@link outputBufferCallbackHandler()} for further details.
|
156 |
-
*
|
157 |
-
* @since 150422 Rewrite.
|
158 |
-
*
|
159 |
-
* @attaches-to `wp` hook.
|
160 |
-
*/
|
161 |
-
$self->wpMainQueryPostload = function () use ($self) {
|
162 |
-
if (empty($self->postload['wp_main_query'])) {
|
163 |
-
return; // Nothing to do in this case.
|
164 |
-
}
|
165 |
-
if ($self->is_wp_loaded_query || is_admin()) {
|
166 |
-
return; // Nothing to do.
|
167 |
-
}
|
168 |
-
if (!is_main_query()) {
|
169 |
-
return; // Not main query.
|
170 |
-
}
|
171 |
-
$self->is_wp_loaded_query = true;
|
172 |
-
$self->is_404 = is_404();
|
173 |
-
$self->is_user_logged_in = is_user_logged_in();
|
174 |
-
$self->content_url = rtrim(content_url(), '/');
|
175 |
-
$self->is_maintenance = $self->functionIsPossible('is_maintenance') && is_maintenance();
|
176 |
-
$_self = $self; // Reference for the closure below.
|
177 |
-
|
178 |
-
add_action(
|
179 |
-
'template_redirect',
|
180 |
-
function () use ($_self) {
|
181 |
-
$_self->is_a_wp_content_type = $_self->is_404 || $_self->is_maintenance
|
182 |
-
|| is_front_page() // See <https://core.trac.wordpress.org/ticket/21602#comment:7>
|
183 |
-
|| is_home() || is_singular() || is_archive() || is_post_type_archive() || is_tax() || is_search() || is_feed();
|
184 |
-
},
|
185 |
-
11
|
186 |
-
);
|
187 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Ac/ShutdownUtils.php
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Registers a shutdown flag.
|
6 |
-
*
|
7 |
-
* @since 140605 Improving output buffer.
|
8 |
-
*
|
9 |
-
* @note In `/wp-settings.php`, Comet Cache is loaded before WP registers its own shutdown function.
|
10 |
-
* Therefore, this flag is set before {@link shutdown_action_hook()} fires, and thus before {@link wp_ob_end_flush_all()}.
|
11 |
-
*
|
12 |
-
* @see http://www.php.net/manual/en/function.register-shutdown-function.php
|
13 |
-
*/
|
14 |
-
$self->registerShutdownFlag = function () use ($self) {
|
15 |
-
register_shutdown_function(function () {
|
16 |
-
$GLOBALS[GLOBAL_NS.'_shutdown_flag'] = -1;
|
17 |
-
});
|
18 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/ActionUtils.php
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Plugin action handler.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @attaches-to `wp_loaded` hook.
|
10 |
-
*/
|
11 |
-
$self->actions = function () use ($self) {
|
12 |
-
if (!empty($_REQUEST[GLOBAL_NS])) {
|
13 |
-
new Actions();
|
14 |
-
}
|
15 |
-
|
16 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/BbPressUtils.php
DELETED
@@ -1,61 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Is bbPress active?
|
6 |
-
*
|
7 |
-
* @since 150821 Improving bbPress support.
|
8 |
-
*
|
9 |
-
* @return bool `TRUE` if bbPress is active.
|
10 |
-
*/
|
11 |
-
$self->isBbPressActive = function () use ($self) {
|
12 |
-
return class_exists('bbPress');
|
13 |
-
};
|
14 |
-
|
15 |
-
/*
|
16 |
-
* bbPress post types.
|
17 |
-
*
|
18 |
-
* @since 150821 Improving bbPress support.
|
19 |
-
*
|
20 |
-
* @return array All bbPress post types.
|
21 |
-
*/
|
22 |
-
$self->bbPressPostTypes = function () use ($self) {
|
23 |
-
if (!$self->isBbPressActive()) {
|
24 |
-
return array();
|
25 |
-
}
|
26 |
-
if (!is_null($types = &$self->cacheKey('bbPressPostTypes'))) {
|
27 |
-
return $types; // Already did this.
|
28 |
-
}
|
29 |
-
$types = array(); // Initialize.
|
30 |
-
$types[] = bbp_get_forum_post_type();
|
31 |
-
$types[] = bbp_get_topic_post_type();
|
32 |
-
$types[] = bbp_get_reply_post_type();
|
33 |
-
|
34 |
-
return $types;
|
35 |
-
};
|
36 |
-
|
37 |
-
/*
|
38 |
-
* bbPress post statuses.
|
39 |
-
*
|
40 |
-
* @since 150821 Improving bbPress support.
|
41 |
-
*
|
42 |
-
* @return array All bbPress post statuses.
|
43 |
-
*/
|
44 |
-
$self->bbPressStatuses = function () use ($self) {
|
45 |
-
if (!$self->isBbPressActive()) {
|
46 |
-
return array();
|
47 |
-
}
|
48 |
-
if (!is_null($statuses = &$self->cacheKey('bbPressStatuses'))) {
|
49 |
-
return $statuses; // Already did this.
|
50 |
-
}
|
51 |
-
$statuses = array(); // Initialize.
|
52 |
-
|
53 |
-
foreach (get_post_stati(array(), 'objects') as $_key => $_status) {
|
54 |
-
if (isset($_status->label_count['domain']) && $_status->label_count['domain'] === 'bbpress') {
|
55 |
-
$statuses[] = $_status->name;
|
56 |
-
}
|
57 |
-
}
|
58 |
-
unset($_key, $_status); // Housekeeping.
|
59 |
-
|
60 |
-
return $statuses;
|
61 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/CleanupUtils.php
DELETED
@@ -1,19 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Runs cleanup routine via CRON job.
|
6 |
-
*
|
7 |
-
* @since 151002 While working on directory stats.
|
8 |
-
*
|
9 |
-
* @attaches-to `'_cron_'.__GLOBAL_NS__.'_cleanup'`
|
10 |
-
*/
|
11 |
-
$self->cleanupCache = function () use ($self) {
|
12 |
-
if (!$self->options['enable']) {
|
13 |
-
return; // Nothing to do.
|
14 |
-
}
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
$self->wurgeCache(); // Purge now.
|
19 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/CondUtils.php
DELETED
@@ -1,13 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Is pro preview?
|
6 |
-
*
|
7 |
-
* @since 150511 Rewrite.
|
8 |
-
*
|
9 |
-
* @return bool `TRUE` if it's a pro preview.
|
10 |
-
*/
|
11 |
-
$self->isProPreview = function () use ($self) {
|
12 |
-
return !empty($_REQUEST[GLOBAL_NS.'_pro_preview']);
|
13 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/CronUtils.php
DELETED
@@ -1,80 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Extends WP-Cron schedules.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @attaches-to `cron_schedules` filter.
|
10 |
-
*
|
11 |
-
* @param array $schedules An array of the current schedules.
|
12 |
-
*
|
13 |
-
* @return array Revised array of WP-Cron schedules.
|
14 |
-
*/
|
15 |
-
$self->extendCronSchedules = function ($schedules) use ($self) {
|
16 |
-
$schedules['every15m'] = array(
|
17 |
-
'interval' => 900,
|
18 |
-
'display' => __('Every 15 Minutes', 'comet-cache'),
|
19 |
-
);
|
20 |
-
return $schedules;
|
21 |
-
};
|
22 |
-
|
23 |
-
/*
|
24 |
-
* Checks Cron setup, validates schedules, and reschedules events if necessary.
|
25 |
-
*
|
26 |
-
* @attaches-to `init` hook.
|
27 |
-
*
|
28 |
-
* @since 151220 Improving WP Cron setup and validation of schedules
|
29 |
-
*/
|
30 |
-
$self->checkCronSetup = function () use ($self) {
|
31 |
-
if ($self->options['crons_setup'] < 1439005906
|
32 |
-
|| $self->options['crons_setup_on_namespace'] !== __NAMESPACE__
|
33 |
-
|| $self->options['crons_setup_with_cache_cleanup_schedule'] !== $self->options['cache_cleanup_schedule']
|
34 |
-
|| $self->options['crons_setup_on_wp_with_schedules'] !== sha1(serialize(wp_get_schedules()))
|
35 |
-
|| !wp_next_scheduled('_cron_'.GLOBAL_NS.'_cleanup')
|
36 |
-
|
37 |
-
) {
|
38 |
-
|
39 |
-
wp_clear_scheduled_hook('_cron_'.GLOBAL_NS.'_cleanup');
|
40 |
-
wp_schedule_event(time() + 60, $self->options['cache_cleanup_schedule'], '_cron_'.GLOBAL_NS.'_cleanup');
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
$self->updateOptions(
|
45 |
-
array(
|
46 |
-
'crons_setup' => time(),
|
47 |
-
'crons_setup_on_namespace' => __NAMESPACE__,
|
48 |
-
'crons_setup_with_cache_cleanup_schedule' => $self->options['cache_cleanup_schedule'],
|
49 |
-
'crons_setup_on_wp_with_schedules' => sha1(serialize(wp_get_schedules()))
|
50 |
-
)
|
51 |
-
);
|
52 |
-
}
|
53 |
-
};
|
54 |
-
|
55 |
-
/*
|
56 |
-
* Resets `crons_setup` and clears WP-Cron schedules.
|
57 |
-
*
|
58 |
-
* @since 151220 Fixing bug with Auto-Cache Engine cron disappearing in some scenarios
|
59 |
-
*
|
60 |
-
* @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).
|
61 |
-
*/
|
62 |
-
$self->resetCronSetup = function ( ) use ($self) {
|
63 |
-
if (is_multisite()) { // Main site CRON jobs.
|
64 |
-
switch_to_blog(get_current_site()->blog_id);
|
65 |
-
|
66 |
-
wp_clear_scheduled_hook('_cron_'.GLOBAL_NS.'_cleanup');
|
67 |
-
restore_current_blog(); // Restore current blog.
|
68 |
-
} else { // Standard WP installation.
|
69 |
-
|
70 |
-
wp_clear_scheduled_hook('_cron_'.GLOBAL_NS.'_cleanup');
|
71 |
-
}
|
72 |
-
$self->updateOptions(
|
73 |
-
array( // Reset so that crons are rescheduled upon next activation
|
74 |
-
'crons_setup' => $self->default_options['crons_setup'],
|
75 |
-
'crons_setup_on_namespace' => $self->default_options['crons_setup_on_namespace'],
|
76 |
-
'crons_setup_with_cache_cleanup_schedule' => $self->default_options['crons_setup_with_cache_cleanup_schedule'],
|
77 |
-
'crons_setup_on_wp_with_schedules' => $self->default_options['crons_setup_on_wp_with_schedules']
|
78 |
-
)
|
79 |
-
);
|
80 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/DbUtils.php
DELETED
@@ -1,13 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* WordPress database instance.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @return \wpdb Reference for IDEs.
|
10 |
-
*/
|
11 |
-
$self->wpdb = function () use ($self) {
|
12 |
-
return $GLOBALS['wpdb'];
|
13 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/DirUtils.php
DELETED
@@ -1,79 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* This constructs an absolute server directory path (no trailing slashes);
|
6 |
-
* which is always nested into {@link \WP_CONTENT_DIR} and the configured `base_dir` option value.
|
7 |
-
*
|
8 |
-
* @since 150422 Rewrite.
|
9 |
-
*
|
10 |
-
* @param string $rel_dir_file A sub-directory or file; relative location please.
|
11 |
-
*
|
12 |
-
* @throws \Exception If `base_dir` is empty when this method is called upon;
|
13 |
-
* i.e. if you attempt to call upon this method before {@link setup()} runs.
|
14 |
-
*
|
15 |
-
* @return string The full absolute server path to `$rel_dir_file`.
|
16 |
-
*/
|
17 |
-
$self->wpContentBaseDirTo = function ($rel_dir_file) use ($self) {
|
18 |
-
$rel_dir_file = trim((string) $rel_dir_file, '\\/'." \t\n\r\0\x0B");
|
19 |
-
|
20 |
-
if (empty($self->options['base_dir'])) {
|
21 |
-
throw new \Exception(__('Missing `base_dir` option value.', 'comet-cache'));
|
22 |
-
}
|
23 |
-
$wp_content_base_dir_to = WP_CONTENT_DIR.'/'.$self->options['base_dir'];
|
24 |
-
|
25 |
-
if (isset($rel_dir_file[0])) {
|
26 |
-
$wp_content_base_dir_to .= '/'.$rel_dir_file;
|
27 |
-
}
|
28 |
-
return $wp_content_base_dir_to;
|
29 |
-
};
|
30 |
-
|
31 |
-
/*
|
32 |
-
* This constructs a relative/base directory path (no leading/trailing slashes).
|
33 |
-
* Always relative to {@link \WP_CONTENT_DIR}. Depends on the configured `base_dir` option value.
|
34 |
-
*
|
35 |
-
* @since 150422 Rewrite.
|
36 |
-
*
|
37 |
-
* @param string $rel_dir_file A sub-directory or file; relative location please.
|
38 |
-
*
|
39 |
-
* @throws \Exception If `base_dir` is empty when this method is called upon;
|
40 |
-
* i.e. if you attempt to call upon this method before {@link setup()} runs.
|
41 |
-
*
|
42 |
-
* @return string The relative/base directory path to `$rel_dir_file`.
|
43 |
-
*/
|
44 |
-
$self->basePathTo = function ($rel_dir_file) use ($self) {
|
45 |
-
$rel_dir_file = trim((string) $rel_dir_file, '\\/'." \t\n\r\0\x0B");
|
46 |
-
|
47 |
-
if (empty($self->options['base_dir'])) {
|
48 |
-
throw new \Exception(__('Missing `base_dir` option value.', 'comet-cache'));
|
49 |
-
}
|
50 |
-
$base_path_to = $self->options['base_dir'];
|
51 |
-
|
52 |
-
if (isset($rel_dir_file[0])) {
|
53 |
-
$base_path_to .= '/'.$rel_dir_file;
|
54 |
-
}
|
55 |
-
return $base_path_to;
|
56 |
-
};
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Get the absolute filesystem path to the root of the WordPress installation
|
60 |
-
*
|
61 |
-
* Copied verbatim from get_home_path() in wp-admin/includes/file.php
|
62 |
-
*
|
63 |
-
* @since 151114 Adding `.htaccess` tweaks.
|
64 |
-
*
|
65 |
-
* @return string Full filesystem path to the root of the WordPress installation
|
66 |
-
*/
|
67 |
-
$self->wpHomePath = function () use ($self) {
|
68 |
-
$home = set_url_scheme( get_option( 'home' ), 'http' );
|
69 |
-
$siteurl = set_url_scheme( get_option( 'siteurl' ), 'http' );
|
70 |
-
if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
|
71 |
-
$wp_path_rel_to_home = str_ireplace( $home, '', $siteurl ); /* $siteurl - $home */
|
72 |
-
$pos = strripos( str_replace( '\\', '/', $_SERVER['SCRIPT_FILENAME'] ), trailingslashit( $wp_path_rel_to_home ) );
|
73 |
-
$home_path = substr( $_SERVER['SCRIPT_FILENAME'], 0, $pos );
|
74 |
-
$home_path = trailingslashit( $home_path );
|
75 |
-
} else {
|
76 |
-
$home_path = ABSPATH;
|
77 |
-
}
|
78 |
-
return str_replace( '\\', '/', $home_path );
|
79 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/HtaccessUtils.php
DELETED
@@ -1,273 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Unique comment marker.
|
6 |
-
*
|
7 |
-
* @since 151220 Enhancing `.htaccess` tweaks.
|
8 |
-
*
|
9 |
-
* @return string Used in `.htaccess` parsing.
|
10 |
-
*/
|
11 |
-
$self->htaccess_marker = 'WmVuQ2FjaGU';
|
12 |
-
|
13 |
-
/*
|
14 |
-
* Plugin options that have associated htaccess rules.
|
15 |
-
*
|
16 |
-
* @since 160103 Improving `.htaccess` tweaks.
|
17 |
-
*
|
18 |
-
* @return array Plugin options that have associated htaccess rules
|
19 |
-
*
|
20 |
-
* @note We keep track of this to avoid the issue described here: http://git.io/vEFIH
|
21 |
-
*/
|
22 |
-
$self->options_with_htaccess_rules = array('cdn_enable');
|
23 |
-
|
24 |
-
/*
|
25 |
-
* Add template blocks to `/.htaccess` file.
|
26 |
-
*
|
27 |
-
* @since 151114 Adding `.htaccess` tweaks.
|
28 |
-
*
|
29 |
-
* @return boolean True if added successfully.
|
30 |
-
*
|
31 |
-
* @TODO Improve error reporting detail to better catch unexpected failures; see http://git.io/vEFLT
|
32 |
-
*/
|
33 |
-
$self->addWpHtaccess = function () use ($self) {
|
34 |
-
global $is_apache;
|
35 |
-
|
36 |
-
if (!$is_apache) {
|
37 |
-
return false; // Not running the Apache web server.
|
38 |
-
}
|
39 |
-
if (!$self->options['enable']) {
|
40 |
-
return true; // Nothing to do.
|
41 |
-
}
|
42 |
-
if (!$self->needHtaccessRules()) {
|
43 |
-
if($self->findHtaccessMarker()) { // Do we need to clean up previously added rules?
|
44 |
-
$self->removeWpHtaccess(); // Fail silently since we don't need rules in place.
|
45 |
-
}
|
46 |
-
return true; // Nothing to do; no options enabled that require htaccess rules.
|
47 |
-
}
|
48 |
-
if (!$self->removeWpHtaccess()) {
|
49 |
-
return false; // Unable to remove.
|
50 |
-
}
|
51 |
-
if (!($htaccess = $self->readHtaccessFile())) {
|
52 |
-
return false; // Failure; could not read file or invalid UTF8 encountered, file may be corrupt.
|
53 |
-
}
|
54 |
-
|
55 |
-
$template_blocks = ''; // Initialize.
|
56 |
-
if (is_dir($templates_dir = dirname(dirname(dirname(__FILE__))).'/templates/htaccess')) {
|
57 |
-
foreach (scandir($templates_dir) as $_template_file) {
|
58 |
-
switch ($_template_file) {
|
59 |
-
|
60 |
-
}
|
61 |
-
}
|
62 |
-
unset($_template_file); // Housekeeping.
|
63 |
-
}
|
64 |
-
|
65 |
-
if(empty($template_blocks)) { // Do we need to add anything to htaccess?
|
66 |
-
$self->closeHtaccessFile($htaccess); // No need to write to htaccess file in this case.
|
67 |
-
return true; // Nothing to do, but no failures either.
|
68 |
-
}
|
69 |
-
|
70 |
-
$template_header = '# BEGIN '.NAME.' '.$self->htaccess_marker.' (the '.$self->htaccess_marker.' marker is required for '.NAME.'; do not remove)'."\n";
|
71 |
-
$template_footer = '# END '.NAME.' '.$self->htaccess_marker;
|
72 |
-
$htaccess['file_contents'] = $template_header.trim($template_blocks)."\n".$template_footer."\n\n".$htaccess['file_contents'];
|
73 |
-
|
74 |
-
if (!$self->writeHtaccessFile($htaccess, true)) {
|
75 |
-
return false; // Failure; could not write changes.
|
76 |
-
}
|
77 |
-
|
78 |
-
return true; // Added successfully.
|
79 |
-
};
|
80 |
-
|
81 |
-
/*
|
82 |
-
* Remove template blocks from `/.htaccess` file.
|
83 |
-
*
|
84 |
-
* @since 151114 Adding `.htaccess` tweaks.
|
85 |
-
*
|
86 |
-
* @return boolean True if removed successfully.
|
87 |
-
*
|
88 |
-
* @TODO Improve error reporting detail to better catch unexpected failures; see http://git.io/vEFLT
|
89 |
-
*/
|
90 |
-
$self->removeWpHtaccess = function () use ($self) {
|
91 |
-
global $is_apache;
|
92 |
-
|
93 |
-
if (!$is_apache) {
|
94 |
-
return false; // Not running the Apache web server.
|
95 |
-
}
|
96 |
-
if (!($htaccess_file = $self->findHtaccessFile())) {
|
97 |
-
return true; // File does not exist.
|
98 |
-
}
|
99 |
-
if (!$self->findHtaccessMarker()) {
|
100 |
-
return true; // Template blocks are already gone.
|
101 |
-
}
|
102 |
-
if (!($htaccess = $self->readHtaccessFile())) {
|
103 |
-
return false; // Failure; could not read file, create file, or invalid UTF8 encountered, file may be corrupt.
|
104 |
-
}
|
105 |
-
|
106 |
-
$regex = '/#\s*BEGIN\s+'.preg_quote(NAME, '/').'\s+'.$self->htaccess_marker.'.*?#\s*END\s+'.preg_quote(NAME, '/').'\s+'.$self->htaccess_marker.'\s*/is';
|
107 |
-
$htaccess['file_contents'] = preg_replace($regex, '', $htaccess['file_contents']);
|
108 |
-
|
109 |
-
if (!$self->writeHtaccessFile($htaccess, false)) {
|
110 |
-
return false; // Failure; could not write changes.
|
111 |
-
}
|
112 |
-
|
113 |
-
return true; // Removed successfully.
|
114 |
-
};
|
115 |
-
|
116 |
-
/*
|
117 |
-
* Finds absolute server path to `/.htaccess` file.
|
118 |
-
*
|
119 |
-
* @since 151114 Adding `.htaccess` tweaks.
|
120 |
-
*
|
121 |
-
* @return string Absolute server path to `/.htaccess` file;
|
122 |
-
* else an empty string if unable to locate the file.
|
123 |
-
*/
|
124 |
-
$self->findHtaccessFile = function () use ($self) {
|
125 |
-
$file = ''; // Initialize.
|
126 |
-
$home_path = $self->wpHomePath();
|
127 |
-
|
128 |
-
if (is_file($htaccess_file = $home_path.'.htaccess')) {
|
129 |
-
$file = $htaccess_file;
|
130 |
-
}
|
131 |
-
return $file;
|
132 |
-
};
|
133 |
-
|
134 |
-
/*
|
135 |
-
* Determines if there are any plugin options enabled that require htaccess rules to be added.
|
136 |
-
*
|
137 |
-
* @since 160103 Improving `.htaccess` tweaks.
|
138 |
-
*
|
139 |
-
* @return bool True when an option is enabled that requires htaccess rules, false otherwise.
|
140 |
-
*/
|
141 |
-
$self->needHtaccessRules = function () use ($self) {
|
142 |
-
if(!is_array($self->options_with_htaccess_rules)) {
|
143 |
-
return false; // Nothing to do.
|
144 |
-
}
|
145 |
-
foreach ($self->options_with_htaccess_rules as $option) {
|
146 |
-
if ($self->options[$option]) {
|
147 |
-
return true; // Yes, there are options enabled that require htaccess rules.
|
148 |
-
}
|
149 |
-
}
|
150 |
-
return false; // No, there are no options enabled that require htaccess rules.
|
151 |
-
};
|
152 |
-
|
153 |
-
/*
|
154 |
-
* Utility method used to check if htaccess file contains $htaccess_marker
|
155 |
-
*
|
156 |
-
* @since 151114 Adding `.htaccess` tweaks.
|
157 |
-
*
|
158 |
-
* @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
|
159 |
-
*
|
160 |
-
* @return bool False on failure or when marker does not exist in htaccess, true otherwise.
|
161 |
-
*/
|
162 |
-
$self->findHtaccessMarker = function ($htaccess_marker = '') use ($self) {
|
163 |
-
if (!($htaccess_file = $self->findHtaccessFile())) {
|
164 |
-
return false; // File does not exist.
|
165 |
-
}
|
166 |
-
if (!is_readable($htaccess_file)) {
|
167 |
-
return false; // Not possible.
|
168 |
-
}
|
169 |
-
if (($htaccess_file_contents = file_get_contents($htaccess_file)) === false) {
|
170 |
-
return false; // Failure; could not read file.
|
171 |
-
}
|
172 |
-
if (empty($htaccess_marker)) {
|
173 |
-
$htaccess_marker = $self->htaccess_marker;
|
174 |
-
}
|
175 |
-
if (stripos($htaccess_file_contents, $htaccess_marker) === false) {
|
176 |
-
return false; // Htaccess marker is missing
|
177 |
-
}
|
178 |
-
|
179 |
-
return true; // Htaccess has the marker
|
180 |
-
};
|
181 |
-
|
182 |
-
/*
|
183 |
-
* Gets contents of `/.htaccess` file with exclusive lock to read+write. If file doesn't exist, we attempt to create it.
|
184 |
-
*
|
185 |
-
* @since 151220 Improving `.htaccess` utils.
|
186 |
-
*
|
187 |
-
* @param string $htaccess_file Absolute path to the htaccess file. Optional.
|
188 |
-
* If not provided, we attempt to find it or create it if it doesn't exist.
|
189 |
-
*
|
190 |
-
* @return array|bool Returns an array with data necessary to call $self->writeHtaccessFile():
|
191 |
-
* `fp` a file pointer resource, `file_contents` a string. Returns `false` on failure.
|
192 |
-
*
|
193 |
-
* @note If a call to this method is not followed by a call to $self->writeHtaccessFile(),
|
194 |
-
* you must make sure that you unlock and close the `fp` resource yourself.
|
195 |
-
*/
|
196 |
-
$self->readHtaccessFile = function ($htaccess_file = '') use ($self) {
|
197 |
-
|
198 |
-
if (empty($htaccess_file) && !($htaccess_file = $self->findHtaccessFile())) {
|
199 |
-
if (!is_writable($self->wpHomePath()) || file_put_contents($htaccess_file = $self->wpHomePath().'.htaccess', '') === false) {
|
200 |
-
return false; // Unable to find and/or create `.htaccess`.
|
201 |
-
} // If it doesn't exist, we create the `.htaccess` file here.
|
202 |
-
}
|
203 |
-
if (!is_readable($htaccess_file) || !is_writable($htaccess_file) || (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS)) {
|
204 |
-
return false; // Not possible.
|
205 |
-
}
|
206 |
-
if (!($fp = fopen($htaccess_file, 'rb+')) || !flock($fp, LOCK_EX)) {
|
207 |
-
fclose($fp); // Just in case we opened it before failing to obtain a lock.
|
208 |
-
return false; // Failure; could not open file and obtain an exclusive lock.
|
209 |
-
}
|
210 |
-
if (($file_contents = fread($fp, filesize($htaccess_file))) && ($file_contents === wp_check_invalid_utf8($file_contents))) {
|
211 |
-
rewind($fp); // Rewind pointer to beginning of file.
|
212 |
-
return compact('fp', 'file_contents');
|
213 |
-
} else { // Failure; could not read file or invalid UTF8 encountered, file may be corrupt.
|
214 |
-
flock($fp, LOCK_UN);
|
215 |
-
fclose($fp);
|
216 |
-
return false;
|
217 |
-
}
|
218 |
-
};
|
219 |
-
|
220 |
-
/*
|
221 |
-
* Writes to `/.htaccess` file using provided file pointer.
|
222 |
-
*
|
223 |
-
* @since 151220 Improving `.htaccess` utils.
|
224 |
-
*
|
225 |
-
* @param array $htaccess Array containing `fp` file resource pointing to htaccess file and `file_contents` to write to file.
|
226 |
-
* @param bool $require_marker Whether or not to require the marker be present in contents before writing.
|
227 |
-
* @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
|
228 |
-
*
|
229 |
-
* @return bool True on success, false on failure.
|
230 |
-
*/
|
231 |
-
$self->writeHtaccessFile = function (array $htaccess, $require_marker = true, $htaccess_marker = '') use ($self) {
|
232 |
-
|
233 |
-
if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
|
234 |
-
return false; // Not possible.
|
235 |
-
}
|
236 |
-
if (!is_resource($htaccess['fp'])) {
|
237 |
-
return false;
|
238 |
-
}
|
239 |
-
$htaccess_marker = $htaccess_marker ?: $self->htaccess_marker;
|
240 |
-
|
241 |
-
$_have_marker = stripos($htaccess['file_contents'], $htaccess_marker);
|
242 |
-
|
243 |
-
// Note: rewind() necessary here because we fread() above.
|
244 |
-
if (($require_marker && $_have_marker === false) || !rewind($htaccess['fp']) || !ftruncate($htaccess['fp'], 0) || !fwrite($htaccess['fp'], $htaccess['file_contents'])) {
|
245 |
-
flock($htaccess['fp'], LOCK_UN);
|
246 |
-
fclose($htaccess['fp']);
|
247 |
-
return false; // Failure; could not write changes.
|
248 |
-
}
|
249 |
-
fflush($htaccess['fp']);
|
250 |
-
flock($htaccess['fp'], LOCK_UN);
|
251 |
-
fclose($htaccess['fp']);
|
252 |
-
|
253 |
-
return true;
|
254 |
-
};
|
255 |
-
|
256 |
-
/*
|
257 |
-
* Utility method used to unlock and close htaccess file resource.
|
258 |
-
*
|
259 |
-
* @since 151114 Adding `.htaccess` tweaks.
|
260 |
-
*
|
261 |
-
* @param array $htaccess Array containing at least an `fp` file resource pointing to htaccess file.
|
262 |
-
*
|
263 |
-
* @return bool False on failure, true otherwise.
|
264 |
-
*/
|
265 |
-
$self->closeHtaccessFile = function (array $htaccess) use ($self) {
|
266 |
-
if (!is_resource($htaccess['fp'])) {
|
267 |
-
return false; // Failure; requires a valid file resource.
|
268 |
-
}
|
269 |
-
flock($htaccess['fp'], LOCK_UN);
|
270 |
-
fclose($htaccess['fp']);
|
271 |
-
|
272 |
-
return true;
|
273 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/InstallUtils.php
DELETED
@@ -1,535 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Plugin activation hook.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @attaches-to {@link \register_activation_hook()}
|
10 |
-
*/
|
11 |
-
$self->activate = function () use ($self) {
|
12 |
-
$self->setup(); // Ensure setup is complete.
|
13 |
-
|
14 |
-
if (!$self->options['welcomed'] && !$self->options['enable']) {
|
15 |
-
$settings_url = add_query_arg(urlencode_deep(array('page' => GLOBAL_NS)), network_admin_url('/admin.php'));
|
16 |
-
$self->enqueueMainNotice(sprintf(__('<strong>%1$s</strong> successfully installed! :-) <strong>Please <a href="%2$s">enable caching and review options</a>.</strong>', 'comet-cache'), esc_html(NAME), esc_attr($settings_url)), array('push_to_top' => true));
|
17 |
-
$self->updateOptions(array('welcomed' => '1'));
|
18 |
-
}
|
19 |
-
|
20 |
-
if (!$self->options['enable']) {
|
21 |
-
return; // Nothing to do.
|
22 |
-
}
|
23 |
-
|
24 |
-
$self->addWpCacheToWpConfig();
|
25 |
-
$self->addWpHtaccess();
|
26 |
-
$self->addAdvancedCache();
|
27 |
-
$self->updateBlogPaths();
|
28 |
-
$self->autoClearCache();
|
29 |
-
};
|
30 |
-
|
31 |
-
/*
|
32 |
-
* Check current plugin version that is installed in WP.
|
33 |
-
*
|
34 |
-
* @since 150422 Rewrite.
|
35 |
-
*
|
36 |
-
* @attaches-to `admin_init` hook.
|
37 |
-
*/
|
38 |
-
$self->checkVersion = function () use ($self) {
|
39 |
-
$prev_version = $self->options['version'];
|
40 |
-
if (version_compare($prev_version, VERSION, '>=')) {
|
41 |
-
return; // Nothing to do; up-to-date.
|
42 |
-
}
|
43 |
-
$self->updateOptions(array('version' => VERSION));
|
44 |
-
|
45 |
-
new VsUpgrades($prev_version);
|
46 |
-
|
47 |
-
if ($self->options['enable']) {
|
48 |
-
$self->addWpCacheToWpConfig();
|
49 |
-
$self->addWpHtaccess();
|
50 |
-
$self->addAdvancedCache();
|
51 |
-
$self->updateBlogPaths();
|
52 |
-
}
|
53 |
-
$self->wipeCache(); // Fresh start now.
|
54 |
-
|
55 |
-
$self->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)), array('push_to_top' => true));
|
56 |
-
};
|
57 |
-
|
58 |
-
/*
|
59 |
-
* Plugin deactivation hook.
|
60 |
-
*
|
61 |
-
* @since 150422 Rewrite.
|
62 |
-
*
|
63 |
-
* @attaches-to {@link \register_deactivation_hook()}
|
64 |
-
*/
|
65 |
-
$self->deactivate = function () use ($self) {
|
66 |
-
$self->setup(); // Ensure setup is complete.
|
67 |
-
|
68 |
-
$self->removeWpCacheFromWpConfig();
|
69 |
-
$self->removeWpHtaccess();
|
70 |
-
$self->removeAdvancedCache();
|
71 |
-
$self->clearCache();
|
72 |
-
$self->resetCronSetup();
|
73 |
-
};
|
74 |
-
|
75 |
-
/*
|
76 |
-
* Plugin uninstall hook.
|
77 |
-
*
|
78 |
-
* @since 150422 Rewrite.
|
79 |
-
*/
|
80 |
-
$self->uninstall = function () use ($self) {
|
81 |
-
$self->setup(); // Ensure setup is complete.
|
82 |
-
|
83 |
-
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
84 |
-
return; // Disallow.
|
85 |
-
}
|
86 |
-
if (empty($GLOBALS[GLOBAL_NS.'_uninstalling'])) {
|
87 |
-
return; // Not uninstalling.
|
88 |
-
}
|
89 |
-
if (!current_user_can($self->uninstall_cap)) {
|
90 |
-
return; // Extra layer of security.
|
91 |
-
}
|
92 |
-
$self->removeWpCacheFromWpConfig();
|
93 |
-
$self->removeWpHtaccess();
|
94 |
-
$self->removeAdvancedCache();
|
95 |
-
$self->wipeCache();
|
96 |
-
$self->resetCronSetup();
|
97 |
-
|
98 |
-
if (!$self->options['uninstall_on_deletion']) {
|
99 |
-
return; // Nothing to do here.
|
100 |
-
}
|
101 |
-
$self->deleteAdvancedCache();
|
102 |
-
$self->deleteBaseDir();
|
103 |
-
|
104 |
-
$wpdb = $self->wpdb(); // WordPress DB.
|
105 |
-
$like = '%'.$wpdb->esc_like(GLOBAL_NS).'%';
|
106 |
-
|
107 |
-
if (is_multisite()) { // Site options for a network installation.
|
108 |
-
$wpdb->query('DELETE FROM `'.esc_sql($wpdb->sitemeta).'` WHERE `meta_key` LIKE \''.esc_sql($like).'\'');
|
109 |
-
|
110 |
-
switch_to_blog(get_current_site()->blog_id); // In case it started as a standard WP installation.
|
111 |
-
$wpdb->query('DELETE FROM `'.esc_sql($wpdb->options).'` WHERE `option_name` LIKE \''.esc_sql($like).'\'');
|
112 |
-
restore_current_blog(); // Restore current blog.
|
113 |
-
//
|
114 |
-
} else { // Standard WP installation.
|
115 |
-
$wpdb->query('DELETE FROM `'.esc_sql($wpdb->options).'` WHERE `option_name` LIKE \''.esc_sql($like).'\'');
|
116 |
-
}
|
117 |
-
};
|
118 |
-
|
119 |
-
/*
|
120 |
-
* Adds `define('WP_CACHE', TRUE);` to the `/wp-config.php` file.
|
121 |
-
*
|
122 |
-
* @since 150422 Rewrite.
|
123 |
-
*
|
124 |
-
* @return string The new contents of the updated `/wp-config.php` file;
|
125 |
-
* else an empty string if unable to add the `WP_CACHE` constant.
|
126 |
-
*/
|
127 |
-
$self->addWpCacheToWpConfig = function () use ($self) {
|
128 |
-
if (!$self->options['enable']) {
|
129 |
-
return ''; // Nothing to do.
|
130 |
-
}
|
131 |
-
if (!($wp_config_file = $self->findWpConfigFile())) {
|
132 |
-
return ''; // Unable to find `/wp-config.php`.
|
133 |
-
}
|
134 |
-
if (!is_readable($wp_config_file)) {
|
135 |
-
return ''; // Not possible.
|
136 |
-
}
|
137 |
-
if (!($wp_config_file_contents = file_get_contents($wp_config_file))) {
|
138 |
-
return ''; // Failure; could not read file.
|
139 |
-
}
|
140 |
-
if (!($wp_config_file_contents_no_whitespace = php_strip_whitespace($wp_config_file))) {
|
141 |
-
return ''; // Failure; file empty
|
142 |
-
}
|
143 |
-
if (preg_match('/\bdefine\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:\-?[1-9][0-9\.]*|TRUE|([\'"])(?:[^0\'"]|[^\'"]{2,})\\2)\s*\)\s*;/i', $wp_config_file_contents_no_whitespace)) {
|
144 |
-
return $wp_config_file_contents; // It's already in there; no need to modify this file.
|
145 |
-
}
|
146 |
-
if (!($wp_config_file_contents = $self->removeWpCacheFromWpConfig())) {
|
147 |
-
return ''; // Unable to remove previous value.
|
148 |
-
}
|
149 |
-
if (!($wp_config_file_contents = preg_replace('/^\s*(\<\?php|\<\?)\s+/i', '${1}'."\n"."define('WP_CACHE', TRUE);"."\n", $wp_config_file_contents, 1))) {
|
150 |
-
return ''; // Failure; something went terribly wrong here.
|
151 |
-
}
|
152 |
-
if (strpos($wp_config_file_contents, "define('WP_CACHE', TRUE);") === false) {
|
153 |
-
return ''; // Failure; unable to add; unexpected PHP code.
|
154 |
-
}
|
155 |
-
if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
|
156 |
-
return ''; // We may NOT edit any files.
|
157 |
-
}
|
158 |
-
if (!is_writable($wp_config_file)) {
|
159 |
-
return ''; // Not possible.
|
160 |
-
}
|
161 |
-
if (!file_put_contents($wp_config_file, $wp_config_file_contents)) {
|
162 |
-
return ''; // Failure; could not write changes.
|
163 |
-
}
|
164 |
-
return $wp_config_file_contents;
|
165 |
-
};
|
166 |
-
|
167 |
-
/*
|
168 |
-
* Removes `define('WP_CACHE', TRUE);` from the `/wp-config.php` file.
|
169 |
-
*
|
170 |
-
* @since 150422 Rewrite.
|
171 |
-
*
|
172 |
-
* @return string The new contents of the updated `/wp-config.php` file;
|
173 |
-
* else an empty string if unable to remove the `WP_CACHE` constant.
|
174 |
-
*/
|
175 |
-
$self->removeWpCacheFromWpConfig = function () use ($self) {
|
176 |
-
if (!($wp_config_file = $self->findWpConfigFile())) {
|
177 |
-
return ''; // Unable to find `/wp-config.php`.
|
178 |
-
}
|
179 |
-
if (!is_readable($wp_config_file)) {
|
180 |
-
return ''; // Not possible.
|
181 |
-
}
|
182 |
-
if (!($wp_config_file_contents = file_get_contents($wp_config_file))) {
|
183 |
-
return ''; // Failure; could not read file.
|
184 |
-
}
|
185 |
-
if (!($wp_config_file_contents_no_whitespace = php_strip_whitespace($wp_config_file))) {
|
186 |
-
return ''; // Failure; file empty
|
187 |
-
}
|
188 |
-
if (!preg_match('/([\'"])WP_CACHE\\1/i', $wp_config_file_contents_no_whitespace)) {
|
189 |
-
return $wp_config_file_contents; // Already gone.
|
190 |
-
}
|
191 |
-
if (preg_match('/\bdefine\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:0|FALSE|NULL|([\'"])0?\\2)\s*\)\s*;/i', $wp_config_file_contents_no_whitespace) && !is_writable($wp_config_file)) {
|
192 |
-
return $wp_config_file_contents; // It's already disabled, and since we can't write to this file let's let this slide.
|
193 |
-
}
|
194 |
-
if (!($wp_config_file_contents = preg_replace('/\bdefine\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:\-?[0-9\.]+|TRUE|FALSE|NULL|([\'"])[^\'"]*\\2)\s*\)\s*;/i', '', $wp_config_file_contents))) {
|
195 |
-
return ''; // Failure; something went terribly wrong here.
|
196 |
-
}
|
197 |
-
if (preg_match('/([\'"])WP_CACHE\\1/i', $wp_config_file_contents)) {
|
198 |
-
return ''; // Failure; perhaps the `/wp-config.php` file contains syntax we cannot remove safely.
|
199 |
-
}
|
200 |
-
if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
|
201 |
-
return ''; // We may NOT edit any files.
|
202 |
-
}
|
203 |
-
if (!is_writable($wp_config_file)) {
|
204 |
-
return ''; // Not possible.
|
205 |
-
}
|
206 |
-
if (!file_put_contents($wp_config_file, $wp_config_file_contents)) {
|
207 |
-
return ''; // Failure; could not write changes.
|
208 |
-
}
|
209 |
-
return $wp_config_file_contents;
|
210 |
-
};
|
211 |
-
|
212 |
-
/*
|
213 |
-
* Checks to make sure the `advanced-cache.php` file still exists;
|
214 |
-
* and if it doesn't, the `advanced-cache.php` is regenerated automatically.
|
215 |
-
*
|
216 |
-
* @since 150422 Rewrite.
|
217 |
-
*
|
218 |
-
* @attaches-to `init` hook.
|
219 |
-
*
|
220 |
-
* @note This runs so that remote deployments which completely wipe out an
|
221 |
-
* existing set of website files (like the AWS Elastic Beanstalk does) will NOT cause Comet Cache
|
222 |
-
* to stop functioning due to the lack of an `advanced-cache.php` file, which is generated by Comet Cache.
|
223 |
-
*
|
224 |
-
* For instance, if you have a Git repo with all of your site files; when you push those files
|
225 |
-
* to your website to deploy them, you most likely do NOT have the `advanced-cache.php` file.
|
226 |
-
* Comet Cache creates this file on its own. Thus, if it's missing (and CC is active)
|
227 |
-
* we simply regenerate the file automatically to keep Comet Cache running.
|
228 |
-
*/
|
229 |
-
$self->checkAdvancedCache = function () use ($self) {
|
230 |
-
if (!$self->options['enable']) {
|
231 |
-
return; // Nothing to do.
|
232 |
-
}
|
233 |
-
if (!empty($_REQUEST[GLOBAL_NS])) {
|
234 |
-
return; // Skip on plugin actions.
|
235 |
-
}
|
236 |
-
$cache_dir = $self->cacheDir();
|
237 |
-
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
238 |
-
$advanced_cache_check_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-advanced-cache';
|
239 |
-
|
240 |
-
// Fixes zero-byte advanced-cache.php bug related to migrating from ZenCache
|
241 |
-
// See: <https://github.com/websharks/zencache/issues/432>
|
242 |
-
|
243 |
-
// Also fixes a missing `define('WP_CACHE', TRUE)` bug related to migrating from ZenCache
|
244 |
-
// See <https://github.com/websharks/zencache/issues/450>
|
245 |
-
|
246 |
-
if (!is_file($advanced_cache_check_file) || !is_file($advanced_cache_file) || filesize($advanced_cache_file) === 0) {
|
247 |
-
$self->addAdvancedCache();
|
248 |
-
$self->addWpCacheToWpConfig();
|
249 |
-
}
|
250 |
-
};
|
251 |
-
|
252 |
-
/*
|
253 |
-
* Creates and adds the `advanced-cache.php` file.
|
254 |
-
*
|
255 |
-
* @since 150422 Rewrite.
|
256 |
-
*
|
257 |
-
* @return bool|null `TRUE` on success. `FALSE` or `NULL` on failure.
|
258 |
-
* A special `NULL` return value indicates success with a single failure
|
259 |
-
* that is specifically related to the `[SHORT_NAME]-advanced-cache` file.
|
260 |
-
*/
|
261 |
-
$self->addAdvancedCache = function () use ($self) {
|
262 |
-
if (!$self->removeAdvancedCache()) {
|
263 |
-
return false; // Still exists.
|
264 |
-
}
|
265 |
-
$cache_dir = $self->cacheDir();
|
266 |
-
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
267 |
-
$advanced_cache_check_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-advanced-cache';
|
268 |
-
$advanced_cache_template = dirname(dirname(dirname(__FILE__))).'/templates/advanced-cache.txt';
|
269 |
-
|
270 |
-
if (is_file($advanced_cache_file) && !is_writable($advanced_cache_file)) {
|
271 |
-
return false; // Not possible to create.
|
272 |
-
}
|
273 |
-
if (!is_file($advanced_cache_file) && !is_writable(dirname($advanced_cache_file))) {
|
274 |
-
return false; // Not possible to create.
|
275 |
-
}
|
276 |
-
if (!is_file($advanced_cache_template) || !is_readable($advanced_cache_template)) {
|
277 |
-
return false; // Template file is missing; or not readable.
|
278 |
-
}
|
279 |
-
if (!($advanced_cache_contents = file_get_contents($advanced_cache_template))) {
|
280 |
-
return false; // Template file is missing; or is not readable.
|
281 |
-
}
|
282 |
-
$possible_advanced_cache_constant_key_values = array_merge(
|
283 |
-
$self->options, // The following additional keys are dynamic.
|
284 |
-
array('cache_dir' => $self->basePathTo($self->cache_sub_dir),
|
285 |
-
|
286 |
-
)
|
287 |
-
);
|
288 |
-
if ($self->applyWpFilters(GLOBAL_NS.'_exclude_uris_client_side_too', true)) {
|
289 |
-
$possible_advanced_cache_constant_key_values['exclude_client_side_uris'] .= "\n".$self->options['exclude_uris'];
|
290 |
-
}
|
291 |
-
foreach ($possible_advanced_cache_constant_key_values as $_option => $_value) {
|
292 |
-
$_value = (string) $_value; // Force string.
|
293 |
-
|
294 |
-
switch ($_option) {
|
295 |
-
case 'exclude_uris': // Converts to regex (caSe insensitive).
|
296 |
-
case 'exclude_client_side_uris': // Converts to regex (caSe insensitive).
|
297 |
-
case 'exclude_refs': // Converts to regex (caSe insensitive).
|
298 |
-
case 'exclude_agents': // Converts to regex (caSe insensitive).
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
$_value = "'".$self->escSq($self->lineDelimitedPatternsToRegex($_value))."'";
|
303 |
-
|
304 |
-
break; // Break switch handler.
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
default: // Default case handler.
|
309 |
-
|
310 |
-
$_value = "'".$self->escSq($_value)."'";
|
311 |
-
|
312 |
-
break; // Break switch handler.
|
313 |
-
}
|
314 |
-
$advanced_cache_contents = // Fill replacement codes.
|
315 |
-
str_ireplace(
|
316 |
-
array(
|
317 |
-
"'%%".GLOBAL_NS.'_'.$_option."%%'",
|
318 |
-
"'%%".GLOBAL_NS.'_'.preg_replace('/^cache_/i', '', $_option)."%%'",
|
319 |
-
),
|
320 |
-
$_value,
|
321 |
-
$advanced_cache_contents
|
322 |
-
);
|
323 |
-
}
|
324 |
-
unset($_option, $_value, $_values, $_response); // Housekeeping.
|
325 |
-
|
326 |
-
if (strpos(PLUGIN_FILE, WP_CONTENT_DIR) === 0) {
|
327 |
-
$plugin_file = "WP_CONTENT_DIR.'".$self->escSq(str_replace(WP_CONTENT_DIR, '', PLUGIN_FILE))."'";
|
328 |
-
} else {
|
329 |
-
$plugin_file = "'".$self->escSq(PLUGIN_FILE)."'"; // Full absolute path.
|
330 |
-
}
|
331 |
-
// Make it possible for the `advanced-cache.php` handler to find the plugin directory reliably.
|
332 |
-
$advanced_cache_contents = str_ireplace("'%%".GLOBAL_NS."_PLUGIN_FILE%%'", $plugin_file, $advanced_cache_contents);
|
333 |
-
|
334 |
-
// Ignore; this is created by Comet Cache; and we don't need to obey in this case.
|
335 |
-
#if(defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS)
|
336 |
-
# return FALSE; // We may NOT edit any files.
|
337 |
-
|
338 |
-
if (!file_put_contents($advanced_cache_file, $advanced_cache_contents)) {
|
339 |
-
return false; // Failure; could not write file.
|
340 |
-
}
|
341 |
-
$cache_lock = $self->cacheLock(); // Lock cache.
|
342 |
-
|
343 |
-
if (!is_dir($cache_dir)) {
|
344 |
-
mkdir($cache_dir, 0775, true);
|
345 |
-
}
|
346 |
-
if (is_writable($cache_dir) && !is_file($cache_dir.'/.htaccess')) {
|
347 |
-
file_put_contents($cache_dir.'/.htaccess', $self->htaccess_deny);
|
348 |
-
}
|
349 |
-
if (!is_dir($cache_dir) || !is_writable($cache_dir) || !is_file($cache_dir.'/.htaccess') || !file_put_contents($advanced_cache_check_file, time())) {
|
350 |
-
$self->cacheUnlock($cache_lock); // Release.
|
351 |
-
return; // Special return value (NULL).
|
352 |
-
}
|
353 |
-
$self->cacheUnlock($cache_lock); // Release.
|
354 |
-
|
355 |
-
$self->clearAcDropinFromOpcacheByForce();
|
356 |
-
|
357 |
-
return true;
|
358 |
-
};
|
359 |
-
|
360 |
-
/*
|
361 |
-
* Removes the `advanced-cache.php` file.
|
362 |
-
*
|
363 |
-
* @since 150422 Rewrite.
|
364 |
-
*
|
365 |
-
* @return bool `TRUE` on success. `FALSE` on failure.
|
366 |
-
*
|
367 |
-
* @note The `advanced-cache.php` file is NOT actually deleted by this routine.
|
368 |
-
* Instead of deleting the file, we simply empty it out so that it's `0` bytes in size.
|
369 |
-
*
|
370 |
-
* The reason for this is to preserve any file permissions set by the site owner.
|
371 |
-
* If the site owner previously allowed this specific file to become writable, we don't want to
|
372 |
-
* lose that permission by deleting the file; forcing the site owner to do it all over again later.
|
373 |
-
*
|
374 |
-
* An example of where this is useful is when a site owner deactivates the CC plugin,
|
375 |
-
* but later they decide that CC really is the most awesome plugin in the world and they turn it back on.
|
376 |
-
*/
|
377 |
-
$self->removeAdvancedCache = function () use ($self) {
|
378 |
-
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
379 |
-
|
380 |
-
if (!is_file($advanced_cache_file)) {
|
381 |
-
return true; // Already gone.
|
382 |
-
}
|
383 |
-
if (is_readable($advanced_cache_file) && filesize($advanced_cache_file) === 0) {
|
384 |
-
return true; // Already gone; i.e. it's empty already.
|
385 |
-
}
|
386 |
-
if (!is_writable($advanced_cache_file)) {
|
387 |
-
return false; // Not possible.
|
388 |
-
}
|
389 |
-
/* Empty the file only. This way permissions are NOT lost in cases where
|
390 |
-
a site owner makes this specific file writable for Comet Cache. */
|
391 |
-
if (file_put_contents($advanced_cache_file, '') !== 0) {
|
392 |
-
return false; // Failure.
|
393 |
-
}
|
394 |
-
$self->clearAcDropinFromOpcacheByForce();
|
395 |
-
|
396 |
-
return true;
|
397 |
-
};
|
398 |
-
|
399 |
-
/*
|
400 |
-
* Deletes the `advanced-cache.php` file.
|
401 |
-
*
|
402 |
-
* @since 150422 Rewrite.
|
403 |
-
*
|
404 |
-
* @return bool `TRUE` on success. `FALSE` on failure.
|
405 |
-
*
|
406 |
-
* @note The `advanced-cache.php` file is deleted by this routine.
|
407 |
-
*/
|
408 |
-
$self->deleteAdvancedCache = function () use ($self) {
|
409 |
-
$cache_dir = $self->cacheDir();
|
410 |
-
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
411 |
-
$advanced_cache_check_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-advanced-cache';
|
412 |
-
|
413 |
-
if (is_file($advanced_cache_file)) {
|
414 |
-
if (!is_writable($advanced_cache_file) || !unlink($advanced_cache_file)) {
|
415 |
-
return false; // Not possible; or outright failure.
|
416 |
-
}
|
417 |
-
}
|
418 |
-
if (is_file($advanced_cache_check_file)) {
|
419 |
-
if (!is_writable($advanced_cache_check_file) || !unlink($advanced_cache_check_file)) {
|
420 |
-
return false; // Not possible; or outright failure.
|
421 |
-
}
|
422 |
-
}
|
423 |
-
$self->clearAcDropinFromOpcacheByForce();
|
424 |
-
|
425 |
-
return true; // Deletion success.
|
426 |
-
};
|
427 |
-
|
428 |
-
/*
|
429 |
-
* Checks to make sure the `[SHORT_NAME]-blog-paths` file still exists;
|
430 |
-
* and if it doesn't, the `[SHORT_NAME]-blog-paths` file is regenerated automatically.
|
431 |
-
*
|
432 |
-
* @since 150422 Rewrite.
|
433 |
-
*
|
434 |
-
* @attaches-to `init` hook.
|
435 |
-
*
|
436 |
-
* @note This runs so that remote deployments which completely wipe out an
|
437 |
-
* existing set of website files (like the AWS Elastic Beanstalk does) will NOT cause Comet Cache
|
438 |
-
* to stop functioning due to the lack of a `[SHORT_NAME]-blog-paths` file, which is generated by Comet Cache.
|
439 |
-
*
|
440 |
-
* For instance, if you have a Git repo with all of your site files; when you push those files
|
441 |
-
* to your website to deploy them, you most likely do NOT have the `[SHORT_NAME]-blog-paths` file.
|
442 |
-
* Comet Cache creates this file on its own. Thus, if it's missing (and CC is active)
|
443 |
-
* we simply regenerate the file automatically to keep Comet Cache running.
|
444 |
-
*/
|
445 |
-
$self->checkBlogPaths = function () use ($self) {
|
446 |
-
if (!$self->options['enable']) {
|
447 |
-
return; // Nothing to do.
|
448 |
-
}
|
449 |
-
if (!is_multisite()) {
|
450 |
-
return; // N/A.
|
451 |
-
}
|
452 |
-
if (!empty($_REQUEST[GLOBAL_NS])) {
|
453 |
-
return; // Skip on plugin actions.
|
454 |
-
}
|
455 |
-
$cache_dir = $self->cacheDir();
|
456 |
-
$blog_paths_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-blog-paths';
|
457 |
-
|
458 |
-
if (!is_file($blog_paths_file)) {
|
459 |
-
$self->updateBlogPaths();
|
460 |
-
}
|
461 |
-
};
|
462 |
-
|
463 |
-
/*
|
464 |
-
* Creates and/or updates the `[SHORT_NAME]-blog-paths` file.
|
465 |
-
*
|
466 |
-
* @since 150422 Rewrite.
|
467 |
-
*
|
468 |
-
* @attaches-to `enable_live_network_counts` filter.
|
469 |
-
*
|
470 |
-
* @param mixed $enable_live_network_counts Optional, defaults to a `NULL` value.
|
471 |
-
*
|
472 |
-
* @return mixed The value of `$enable_live_network_counts` (passes through).
|
473 |
-
*
|
474 |
-
* @note While this routine is attached to a WP filter, we also call upon it directly at times.
|
475 |
-
*/
|
476 |
-
$self->updateBlogPaths = function ($enable_live_network_counts = null) use ($self) {
|
477 |
-
$value = $enable_live_network_counts; // This hook actually rides on a filter.
|
478 |
-
|
479 |
-
if (!$self->options['enable']) {
|
480 |
-
return $value; // Nothing to do.
|
481 |
-
}
|
482 |
-
if (!is_multisite()) {
|
483 |
-
return $value; // N/A.
|
484 |
-
}
|
485 |
-
$cache_dir = $self->cacheDir();
|
486 |
-
$blog_paths_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-blog-paths';
|
487 |
-
|
488 |
-
$cache_lock = $self->cacheLock();
|
489 |
-
|
490 |
-
if (!is_dir($cache_dir)) {
|
491 |
-
mkdir($cache_dir, 0775, true);
|
492 |
-
}
|
493 |
-
if (is_writable($cache_dir) && !is_file($cache_dir.'/.htaccess')) {
|
494 |
-
file_put_contents($cache_dir.'/.htaccess', $self->htaccess_deny);
|
495 |
-
}
|
496 |
-
if (is_dir($cache_dir) && is_writable($cache_dir)) {
|
497 |
-
$paths = // Collect child `[/base]/path/`s from the WordPress database.
|
498 |
-
$self->wpdb()->get_col('SELECT `path` FROM `'.esc_sql($self->wpdb()->blogs)."` WHERE `deleted` <= '0'");
|
499 |
-
|
500 |
-
$host_base_token = $self->hostBaseToken(); // Pull this once only.
|
501 |
-
|
502 |
-
foreach ($paths as $_key => &$_path) {
|
503 |
-
if ($_path && $_path !== '/' && $host_base_token && $host_base_token !== '/') {
|
504 |
-
// Note that each `path` in the DB looks like: `[/base]/path/` (i.e., it includes base).
|
505 |
-
$_path = '/'.ltrim(preg_replace('/^'.preg_quote($host_base_token, '/').'/', '', $_path), '/');
|
506 |
-
}
|
507 |
-
if (!$_path || $_path === '/') {
|
508 |
-
unset($paths[$_key]); // Exclude main site.
|
509 |
-
}
|
510 |
-
}
|
511 |
-
unset($_key, $_path); // Housekeeping.
|
512 |
-
|
513 |
-
file_put_contents($blog_paths_file, serialize($paths));
|
514 |
-
}
|
515 |
-
$self->cacheUnlock($cache_lock); // Release.
|
516 |
-
|
517 |
-
return $value; // Pass through untouched (always).
|
518 |
-
};
|
519 |
-
|
520 |
-
/*
|
521 |
-
* Deletes base directory.
|
522 |
-
*
|
523 |
-
* @since 151002 Improving multisite compat.
|
524 |
-
*
|
525 |
-
* @return int Total files removed by this routine (if any).
|
526 |
-
*/
|
527 |
-
$self->deleteBaseDir = function () use ($self) {
|
528 |
-
$counter = 0; // Initialize.
|
529 |
-
|
530 |
-
@set_time_limit(1800); // @TODO Display a warning.
|
531 |
-
|
532 |
-
$counter += $self->deleteAllFilesDirsIn($self->wpContentBaseDirTo(''), true);
|
533 |
-
|
534 |
-
return $counter;
|
535 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/MenuPageUtils.php
DELETED
@@ -1,219 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Adds CSS for administrative menu pages.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @attaches-to `admin_enqueue_scripts` hook.
|
10 |
-
*/
|
11 |
-
$self->enqueueAdminStyles = function () use ($self) {
|
12 |
-
if (empty($_GET['page']) || strpos($_GET['page'], GLOBAL_NS) !== 0) {
|
13 |
-
return; // NOT a plugin page in the administrative area.
|
14 |
-
}
|
15 |
-
$deps = array(); // Plugin dependencies.
|
16 |
-
|
17 |
-
wp_enqueue_style(GLOBAL_NS, $self->url('/src/client-s/css/menu-pages.min.css'), $deps, VERSION, 'all');
|
18 |
-
};
|
19 |
-
|
20 |
-
/*
|
21 |
-
* Adds JS for administrative menu pages.
|
22 |
-
*
|
23 |
-
* @since 150422 Rewrite.
|
24 |
-
*
|
25 |
-
* @attaches-to `admin_enqueue_scripts` hook.
|
26 |
-
*/
|
27 |
-
$self->enqueueAdminScripts = function () use ($self) {
|
28 |
-
if (empty($_GET['page']) || strpos($_GET['page'], GLOBAL_NS) !== 0) {
|
29 |
-
return; // NOT a plugin page in the administrative area.
|
30 |
-
}
|
31 |
-
$deps = array('jquery', 'chartjs'); // Plugin dependencies.
|
32 |
-
|
33 |
-
wp_enqueue_script('chartjs', set_url_scheme('//cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js'), array(), null, true);
|
34 |
-
wp_enqueue_script(GLOBAL_NS, $self->url('/src/client-s/js/menu-pages.min.js'), $deps, VERSION, true);
|
35 |
-
wp_localize_script(GLOBAL_NS, GLOBAL_NS.'_menu_page_vars', array(
|
36 |
-
'_wpnonce' => wp_create_nonce(),
|
37 |
-
'isMultisite' => is_multisite(), // Network?
|
38 |
-
'currentUserHasCap' => current_user_can($self->cap),
|
39 |
-
'currentUserHasNetworkCap' => current_user_can($self->network_cap),
|
40 |
-
'htmlCompressorEnabled' => (boolean) $self->options['htmlc_enable'],
|
41 |
-
'ajaxURL' => site_url('/wp-load.php', is_ssl() ? 'https' : 'http'),
|
42 |
-
'emptyStatsCountsImageUrl' => $self->url('/src/client-s/images/stats-fc-empty.png'),
|
43 |
-
'emptyStatsFilesImageUrl' => $self->url('/src/client-s/images/stats-fs-empty.png'),
|
44 |
-
'i18n' => array(
|
45 |
-
'name' => NAME,
|
46 |
-
'perSymbol' => __('%', 'comet-cache'),
|
47 |
-
'file' => __('file', 'comet-cache'),
|
48 |
-
'files' => __('files', 'comet-cache'),
|
49 |
-
'pageCache' => __('Page Cache', 'comet-cache'),
|
50 |
-
'htmlCompressor' => __('HTML Compressor', 'comet-cache'),
|
51 |
-
'currentTotal' => __('Current Total', 'comet-cache'),
|
52 |
-
'currentSite' => __('Current Site', 'comet-cache'),
|
53 |
-
'xDayHigh' => __('%s Day High', 'comet-cache'),
|
54 |
-
),
|
55 |
-
));
|
56 |
-
};
|
57 |
-
|
58 |
-
/*
|
59 |
-
* Creates network admin menu pages.
|
60 |
-
*
|
61 |
-
* @since 150422 Rewrite.
|
62 |
-
*
|
63 |
-
* @attaches-to `network_admin_menu` hook.
|
64 |
-
*/
|
65 |
-
$self->addNetworkMenuPages = function () use ($self) {
|
66 |
-
if (!is_multisite()) {
|
67 |
-
return; // Not applicable.
|
68 |
-
}
|
69 |
-
$icon = file_get_contents(dirname(dirname(dirname(dirname(__FILE__)))).'/client-s/images/inline-icon.svg');
|
70 |
-
$icon = 'data:image/svg+xml;base64,'.base64_encode($self->colorSvgMenuIcon($icon));
|
71 |
-
|
72 |
-
add_menu_page(NAME . (IS_PRO ? ' Pro' : ''), NAME . (IS_PRO ? ' Pro' : ''), $self->network_cap, GLOBAL_NS, array($self, 'menuPageOptions'), $icon);
|
73 |
-
add_submenu_page(GLOBAL_NS, __('Plugin Options', 'comet-cache'), __('Plugin Options', 'comet-cache'), $self->network_cap, GLOBAL_NS, array($self, 'menuPageOptions'));
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
};
|
79 |
-
|
80 |
-
/*
|
81 |
-
* Creates admin menu pages.
|
82 |
-
*
|
83 |
-
* @since 150422 Rewrite.
|
84 |
-
*
|
85 |
-
* @attaches-to `admin_menu` hook.
|
86 |
-
*/
|
87 |
-
$self->addMenuPages = function () use ($self) {
|
88 |
-
if (is_multisite()) {
|
89 |
-
return; // Multisite networks MUST use network admin area.
|
90 |
-
}
|
91 |
-
$icon = file_get_contents(dirname(dirname(dirname(dirname(__FILE__)))).'/client-s/images/inline-icon.svg');
|
92 |
-
$icon = 'data:image/svg+xml;base64,'.base64_encode($self->colorSvgMenuIcon($icon));
|
93 |
-
|
94 |
-
add_menu_page(NAME . (IS_PRO ? ' Pro' : ''), NAME . (IS_PRO ? ' Pro' : ''), $self->cap, GLOBAL_NS, array($self, 'menuPageOptions'), $icon);
|
95 |
-
add_submenu_page(GLOBAL_NS, __('Plugin Options', 'comet-cache'), __('Plugin Options', 'comet-cache'), $self->cap, GLOBAL_NS, array($self, 'menuPageOptions'));
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
};
|
101 |
-
|
102 |
-
/*
|
103 |
-
* Adds link(s) to Comet Cache row on the WP plugins page.
|
104 |
-
*
|
105 |
-
* @since 150422 Rewrite.
|
106 |
-
*
|
107 |
-
* @attaches-to `plugin_action_links_'.plugin_basename(PLUGIN_FILE)` filter.
|
108 |
-
*
|
109 |
-
* @param array $links An array of the existing links provided by WordPress.
|
110 |
-
*
|
111 |
-
* @return array Revised array of links.
|
112 |
-
*/
|
113 |
-
$self->addSettingsLink = function ($links) use ($self) {
|
114 |
-
if (is_multisite() && !is_network_admin()) {
|
115 |
-
return $links;
|
116 |
-
}
|
117 |
-
|
118 |
-
$links[] = '<a href="'.esc_attr(add_query_arg(urlencode_deep(array('page' => GLOBAL_NS)), self_admin_url('/admin.php'))).'">'.__('Settings', 'comet-cache').'</a>';
|
119 |
-
if (!IS_PRO) {
|
120 |
-
$links[] = '<br/><a href="'.esc_attr(add_query_arg(urlencode_deep(array('page' => GLOBAL_NS, GLOBAL_NS.'_pro_preview' => '1')), self_admin_url('/admin.php'))).'">'.__('Preview Pro Features', 'comet-cache').'</a>';
|
121 |
-
$links[] = '<a href="'.esc_attr('http://cometcache.com/prices/').'" target="_blank">'.__('Upgrade', 'comet-cache').'</a>';
|
122 |
-
}
|
123 |
-
return $links;
|
124 |
-
};
|
125 |
-
|
126 |
-
/*
|
127 |
-
* Fills menu page inline SVG icon color.
|
128 |
-
*
|
129 |
-
* @since 150422 Rewrite.
|
130 |
-
*
|
131 |
-
* @param string $svg Inline SVG icon markup.
|
132 |
-
*
|
133 |
-
* @return string Inline SVG icon markup.
|
134 |
-
*/
|
135 |
-
$self->colorSvgMenuIcon = function ($svg) use ($self) {
|
136 |
-
if (!($color = get_user_option('admin_color'))) {
|
137 |
-
$color = 'fresh'; // Default color scheme.
|
138 |
-
}
|
139 |
-
if (empty($self->wp_admin_icon_colors[$color])) {
|
140 |
-
return $svg; // Not possible.
|
141 |
-
}
|
142 |
-
$icon_colors = $self->wp_admin_icon_colors[$color];
|
143 |
-
$use_icon_fill_color = $icon_colors['base']; // Default base.
|
144 |
-
|
145 |
-
$current_pagenow = !empty($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : '';
|
146 |
-
$current_page = !empty($_REQUEST['page']) ? $_REQUEST['page'] : '';
|
147 |
-
|
148 |
-
if (strpos($current_pagenow, GLOBAL_NS) === 0 || strpos($current_page, GLOBAL_NS) === 0) {
|
149 |
-
$use_icon_fill_color = $icon_colors['current'];
|
150 |
-
}
|
151 |
-
return str_replace(' fill="currentColor"', ' fill="'.esc_attr($use_icon_fill_color).'"', $svg);
|
152 |
-
};
|
153 |
-
|
154 |
-
/*
|
155 |
-
* Loads the admin menu page options.
|
156 |
-
*
|
157 |
-
* @since 150422 Rewrite.
|
158 |
-
*/
|
159 |
-
$self->menuPageOptions = function () use ($self) {
|
160 |
-
new MenuPage('options');
|
161 |
-
};
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
/*
|
168 |
-
* WordPress admin icon color schemes.
|
169 |
-
*
|
170 |
-
* @since 150422 Rewrite.
|
171 |
-
*
|
172 |
-
* @type array WP admin icon colors.
|
173 |
-
*
|
174 |
-
* @note These must be hard-coded, because they don't become available
|
175 |
-
* in core until `admin_init`; i.e., too late for `admin_menu`.
|
176 |
-
*/
|
177 |
-
$self->wp_admin_icon_colors = array(
|
178 |
-
'fresh' => array('base' => '#999999', 'focus' => '#2EA2CC', 'current' => '#FFFFFF'),
|
179 |
-
'light' => array('base' => '#999999', 'focus' => '#CCCCCC', 'current' => '#CCCCCC'),
|
180 |
-
'blue' => array('base' => '#E5F8FF', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'),
|
181 |
-
'midnight' => array('base' => '#F1F2F3', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'),
|
182 |
-
'sunrise' => array('base' => '#F3F1F1', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'),
|
183 |
-
'ectoplasm' => array('base' => '#ECE6F6', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'),
|
184 |
-
'ocean' => array('base' => '#F2FCFF', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'),
|
185 |
-
'coffee' => array('base' => '#F3F2F1', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'),
|
186 |
-
);
|
187 |
-
|
188 |
-
/*
|
189 |
-
* On a specific menu page?
|
190 |
-
*
|
191 |
-
* @since 151002 Improving multisite compat.
|
192 |
-
*
|
193 |
-
* @param string $which Which page to check; may contain wildcards.
|
194 |
-
*
|
195 |
-
* @return boolean True if is the menu page.
|
196 |
-
*/
|
197 |
-
$self->isMenuPage = function ($which) use ($self) {
|
198 |
-
if (!($which = trim((string) $which))) {
|
199 |
-
return false; // Empty.
|
200 |
-
}
|
201 |
-
if (!is_admin()) {
|
202 |
-
return false;
|
203 |
-
}
|
204 |
-
$page = $pagenow = ''; // Initialize.
|
205 |
-
|
206 |
-
if (!empty($_REQUEST['page'])) {
|
207 |
-
$page = (string) $_REQUEST['page'];
|
208 |
-
}
|
209 |
-
if (!empty($GLOBALS['pagenow'])) {
|
210 |
-
$pagenow = (string) $GLOBALS['pagenow'];
|
211 |
-
}
|
212 |
-
if ($page && fnmatch($which, $page, FNM_CASEFOLD)) {
|
213 |
-
return true; // Wildcard match.
|
214 |
-
}
|
215 |
-
if ($pagenow && fnmatch($which, $pagenow, FNM_CASEFOLD)) {
|
216 |
-
return true; // Wildcard match.
|
217 |
-
}
|
218 |
-
return false; // Nope.
|
219 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/NoticeUtils.php
DELETED
@@ -1,296 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Notice queue handlers.
|
6 |
-
*/
|
7 |
-
|
8 |
-
/*
|
9 |
-
* Enqueue an administrative notice.
|
10 |
-
*
|
11 |
-
* @since 150422 Rewrite. Improved 151002.
|
12 |
-
*
|
13 |
-
* @param string $notice HTML markup containing the notice itself.
|
14 |
-
* @param string $args Any additional arguments supported by the notice API in this plugin.
|
15 |
-
* @param integer $blog_id Optional. Defaults to the current blog ID. Use any value `< 0` to indicate the main site.
|
16 |
-
*
|
17 |
-
* @return string A unique key generated for this notice.
|
18 |
-
*/
|
19 |
-
$self->enqueueNotice = function ($notice, array $args = array(), $blog_id = 0) use ($self) {
|
20 |
-
$notice = trim((string) $notice);
|
21 |
-
$blog_id = (integer) $blog_id;
|
22 |
-
|
23 |
-
if (!$notice) {
|
24 |
-
return; // Nothing to do.
|
25 |
-
}
|
26 |
-
$notice = array('notice' => $notice);
|
27 |
-
$notice = $self->normalizeNotice($notice, $args);
|
28 |
-
$key = sha1(serialize($notice)); // Prevent dupes.
|
29 |
-
|
30 |
-
$notices = $self->getNotices($blog_id);
|
31 |
-
|
32 |
-
if ($notice['push_to_top']) {
|
33 |
-
$notices = array($key => $notice) + $notices;
|
34 |
-
} else {
|
35 |
-
$notices[$key] = $notice; // Default behavior.
|
36 |
-
}
|
37 |
-
$self->updateNotices($notices, $blog_id);
|
38 |
-
|
39 |
-
return $key; // For dismissals.
|
40 |
-
};
|
41 |
-
|
42 |
-
/*
|
43 |
-
* Dismiss an administrative notice.
|
44 |
-
*
|
45 |
-
* @since 151002 Improving multisite compat.
|
46 |
-
*
|
47 |
-
* @param string $key_to_dismiss A unique key which identifies a particular notice.
|
48 |
-
* Or, a persistent key which identifies one or more persistent notices.
|
49 |
-
*
|
50 |
-
* @param integer $blog_id The blog ID from which to dismiss the notice.
|
51 |
-
*
|
52 |
-
* @return array All remaining notices.
|
53 |
-
*/
|
54 |
-
$self->dismissNotice = function ($key_to_dismiss, $blog_id = 0) use ($self) {
|
55 |
-
$key_to_dismiss = trim((string) $key_to_dismiss);
|
56 |
-
$blog_id = (integer) $blog_id; // For multisite compat.
|
57 |
-
$notices = $enqueued_notices = $self->getNotices($blog_id);
|
58 |
-
|
59 |
-
if (!$key_to_dismiss) {
|
60 |
-
return $notices; // Nothing to do.
|
61 |
-
}
|
62 |
-
foreach ($notices as $_key => $_notice) {
|
63 |
-
if ($_key === $key_to_dismiss) {
|
64 |
-
unset($notices[$_key]); // A specific key.
|
65 |
-
} elseif ($_notice['persistent_key'] === $key_to_dismiss) {
|
66 |
-
unset($notices[$_key]); // All matching keys.
|
67 |
-
}
|
68 |
-
} // ↑ Dismisses all matching keys.
|
69 |
-
unset($_key, $_notice); // Housekeeping.
|
70 |
-
|
71 |
-
if ($notices !== $enqueued_notices) { // Something changed?
|
72 |
-
$self->updateNotices($notices, $blog_id); // Update.
|
73 |
-
}
|
74 |
-
return $notices; // All remaining notices.
|
75 |
-
};
|
76 |
-
|
77 |
-
/*
|
78 |
-
* Enqueue an administrative error notice.
|
79 |
-
*
|
80 |
-
* @since 150422 Rewrite. Improved 151002.
|
81 |
-
*/
|
82 |
-
$self->enqueueError = function ($notice, array $args = array(), $blog_id = 0) use ($self) {
|
83 |
-
return $self->enqueueNotice($notice, array_merge($args, array('class' => 'error')), $blog_id);
|
84 |
-
};
|
85 |
-
|
86 |
-
/*
|
87 |
-
* Enqueue an administrative notice (main site).
|
88 |
-
*
|
89 |
-
* @since 151002. Improving multisite compat.
|
90 |
-
*/
|
91 |
-
$self->enqueueMainNotice = function ($notice, array $args = array()) use ($self) {
|
92 |
-
return $self->enqueueNotice($notice, $args, -1);
|
93 |
-
};
|
94 |
-
|
95 |
-
/*
|
96 |
-
* Enqueue an administrative error notice (main site).
|
97 |
-
*
|
98 |
-
* @since 151002. Improving multisite compat.
|
99 |
-
*/
|
100 |
-
$self->enqueueMainError = function ($notice, array $args = array()) use ($self) {
|
101 |
-
return $self->enqueueNotice($notice, array_merge($args, array('class' => 'error')), -1);
|
102 |
-
};
|
103 |
-
|
104 |
-
/*
|
105 |
-
* Dismiss an administrative notice (main site).
|
106 |
-
*
|
107 |
-
* @since 151002 Improving multisite compat.
|
108 |
-
*/
|
109 |
-
$self->dismissMainNotice = function ($key_to_dismiss) use ($self) {
|
110 |
-
return $self->dismissNotice($key_to_dismiss, -1);
|
111 |
-
};
|
112 |
-
|
113 |
-
/*
|
114 |
-
* Notice display handler.
|
115 |
-
*/
|
116 |
-
|
117 |
-
/*
|
118 |
-
* Render admin notices.
|
119 |
-
*
|
120 |
-
* @since 150422 Rewrite. Improved 151002.
|
121 |
-
*
|
122 |
-
* @attaches-to `all_admin_notices` hook.
|
123 |
-
*/
|
124 |
-
$self->allAdminNotices = function () use ($self) {
|
125 |
-
$notices = $enqueued_notices = $self->getNotices();
|
126 |
-
|
127 |
-
foreach ($notices as $_key => $_notice) {
|
128 |
-
# Always dismiss all non-persistent transients.
|
129 |
-
|
130 |
-
if ($_notice['is_transient'] && !$_notice['persistent_key']) {
|
131 |
-
unset($notices[$_key]); // Dismiss.
|
132 |
-
}
|
133 |
-
# Current user can see this notice?
|
134 |
-
|
135 |
-
if (!current_user_can($self->cap)) {
|
136 |
-
continue; // Current user unable to see.
|
137 |
-
}
|
138 |
-
if ($_notice['cap_required'] && !current_user_can($_notice['cap_required'])) {
|
139 |
-
continue; // Current user unable to see this notice.
|
140 |
-
}
|
141 |
-
# Current URI matches a limited scope/context for this notice?
|
142 |
-
|
143 |
-
if ($_notice['only_on_uris'] && !@preg_match($_notice['only_on_uris'], $_SERVER['REQUEST_URI'])) {
|
144 |
-
continue; // Not in the right context at the moment; i.e., does not regex.
|
145 |
-
}
|
146 |
-
# If persistent, allow a site owner to dismiss.
|
147 |
-
|
148 |
-
$_dismiss = ''; // Reset this to its default state.
|
149 |
-
if ($_notice['persistent_key'] && $_notice['dismissable']) { // See above. The `dismissNotice()` action requires `$self->cap` always.
|
150 |
-
$_dismiss = add_query_arg(urlencode_deep(array(GLOBAL_NS => array('dismissNotice' => array('key' => $_key)), '_wpnonce' => wp_create_nonce())));
|
151 |
-
$_dismiss = '<a style="display:inline-block; float:right; margin:0 0 0 15px; text-decoration:none; font-weight:bold;" href="'.esc_attr($_dismiss).'">'.__('dismiss ×', 'comet-cache').'</a>';
|
152 |
-
}
|
153 |
-
# Display this notice. If not persistent, we can dismiss it too.
|
154 |
-
|
155 |
-
echo '<div class="'.esc_attr($_notice['class']).'"><p>'.$_notice['notice'].$_dismiss.'</p></div>';
|
156 |
-
|
157 |
-
if (!$_notice['persistent_key']) { // If not persistent, dismiss.
|
158 |
-
unset($notices[$_key]); // Dismiss; this notice has been displayed now.
|
159 |
-
}
|
160 |
-
}
|
161 |
-
unset($_key, $_notice, $_dismiss); // Housekeeping.
|
162 |
-
|
163 |
-
# Update notices if something changed above.
|
164 |
-
|
165 |
-
if ($notices !== $enqueued_notices) { // Something changed?
|
166 |
-
$self->updateNotices($notices); // Update.
|
167 |
-
}
|
168 |
-
};
|
169 |
-
|
170 |
-
/*
|
171 |
-
* Notice getter/setter.
|
172 |
-
*/
|
173 |
-
|
174 |
-
/*
|
175 |
-
* Get admin notices.
|
176 |
-
*
|
177 |
-
* @since 151002 Improving multisite compat.
|
178 |
-
*
|
179 |
-
* @param integer $blog_id Optional. Defaults to the current blog ID.
|
180 |
-
* Use any value `< 0` to indicate the main site.
|
181 |
-
*
|
182 |
-
* @return array All notices.
|
183 |
-
*/
|
184 |
-
$self->getNotices = function ($blog_id = 0) use ($self) {
|
185 |
-
if (is_multisite()) {
|
186 |
-
if (!($blog_id = (integer) $blog_id)) {
|
187 |
-
$blog_id = (integer) get_current_blog_id();
|
188 |
-
}
|
189 |
-
if ($blog_id < 0) { // Blog for main site.
|
190 |
-
$blog_id = (integer) get_current_site()->blog_id;
|
191 |
-
}
|
192 |
-
$blog_suffix = '_'.$blog_id; // Site option suffix.
|
193 |
-
$notices = get_site_option(GLOBAL_NS.$blog_suffix.'_notices');
|
194 |
-
} else {
|
195 |
-
$notices = get_site_option(GLOBAL_NS.'_notices');
|
196 |
-
}
|
197 |
-
if (!is_array($notices)) {
|
198 |
-
$notices = array(); // Force array.
|
199 |
-
// Prevent multiple DB queries by adding this key.
|
200 |
-
$self->updateNotices($notices, $blog_id);
|
201 |
-
}
|
202 |
-
foreach ($notices as $_key => &$_notice) {
|
203 |
-
if (!is_string($_key) || !is_array($_notice) || empty($_notice['notice'])) {
|
204 |
-
unset($notices[$_key]); // Old notice.
|
205 |
-
continue; // Bypass; i.e., do not normalize.
|
206 |
-
}
|
207 |
-
$_notice = $self->normalizeNotice($_notice);
|
208 |
-
} // ↑ Typecast/normalized each of the array elements.
|
209 |
-
unset($_key, $_notice); // Housekeeping.
|
210 |
-
|
211 |
-
return $notices;
|
212 |
-
};
|
213 |
-
|
214 |
-
/*
|
215 |
-
* Update admin notices.
|
216 |
-
*
|
217 |
-
* @since 151002 Improving multisite compat.
|
218 |
-
*
|
219 |
-
* @param array $notices New array of notices.
|
220 |
-
*
|
221 |
-
* @param integer $blog_id Optional. Defaults to the current blog ID.
|
222 |
-
* Use any value `< 0` to indicate the main site.
|
223 |
-
*
|
224 |
-
* @return array All notices.
|
225 |
-
*/
|
226 |
-
$self->updateNotices = function (array $notices, $blog_id = 0) use ($self) {
|
227 |
-
if (is_multisite()) {
|
228 |
-
if (!($blog_id = (integer) $blog_id)) {
|
229 |
-
$blog_id = (integer) get_current_blog_id();
|
230 |
-
}
|
231 |
-
if ($blog_id < 0) { // Blog for main site.
|
232 |
-
$blog_id = (integer) get_current_site()->blog_id;
|
233 |
-
}
|
234 |
-
$blog_suffix = '_'.$blog_id; // Site option suffix.
|
235 |
-
update_site_option(GLOBAL_NS.$blog_suffix.'_notices', $notices);
|
236 |
-
} else {
|
237 |
-
update_site_option(GLOBAL_NS.'_notices', $notices);
|
238 |
-
}
|
239 |
-
return $notices;
|
240 |
-
};
|
241 |
-
|
242 |
-
/*
|
243 |
-
* Notice property utilities.
|
244 |
-
*/
|
245 |
-
|
246 |
-
/*
|
247 |
-
* Normalize notice elements.
|
248 |
-
*
|
249 |
-
* @since 151002 Improving multisite compat.
|
250 |
-
*
|
251 |
-
* @param array $notice Notice array elements.
|
252 |
-
* @param array $args Any additional array elements.
|
253 |
-
*
|
254 |
-
* @return array Normalized notice array elements.
|
255 |
-
*/
|
256 |
-
$self->normalizeNotice = function (array $notice, array $args = array()) use ($self) {
|
257 |
-
$notice_defaults = array(
|
258 |
-
'notice' => '',
|
259 |
-
'only_on_uris' => '',
|
260 |
-
'persistent_key' => '',
|
261 |
-
'dismissable' => true,
|
262 |
-
'is_transient' => true,
|
263 |
-
'push_to_top' => false,
|
264 |
-
'class' => 'updated',
|
265 |
-
'cap_required' => '', // `$self->cap` always.
|
266 |
-
// i.e., this cap is in addition to `$self->cap`.
|
267 |
-
);
|
268 |
-
$notice = array_merge($notice_defaults, $notice, $args);
|
269 |
-
$notice = array_intersect_key($notice, $notice_defaults);
|
270 |
-
|
271 |
-
foreach ($notice as $_key => &$_value) {
|
272 |
-
switch ($_key) {
|
273 |
-
case 'notice':
|
274 |
-
case 'only_on_uris':
|
275 |
-
case 'persistent_key':
|
276 |
-
$_value = trim((string) $_value);
|
277 |
-
break; // Stop here.
|
278 |
-
|
279 |
-
case 'is_transient':
|
280 |
-
case 'push_to_top':
|
281 |
-
case 'dismissable':
|
282 |
-
$_value = (boolean) $_value;
|
283 |
-
break; // Stop here.
|
284 |
-
|
285 |
-
case 'class':
|
286 |
-
case 'cap_required':
|
287 |
-
$_value = trim((string) $_value);
|
288 |
-
break; // Stop here.
|
289 |
-
}
|
290 |
-
} // ↑ Typecast each of the array elements.
|
291 |
-
unset($_key, $_value); // A little housekeeping.
|
292 |
-
|
293 |
-
ksort($notice); // For more accurate comparison in other routines.
|
294 |
-
|
295 |
-
return $notice; // Normalized.
|
296 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/OptionUtils.php
DELETED
@@ -1,70 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Get plugin options.
|
6 |
-
*
|
7 |
-
* @since 151002 Improving multisite compat.
|
8 |
-
*
|
9 |
-
* @return array Plugin options.
|
10 |
-
*/
|
11 |
-
$self->getOptions = function () use ($self) {
|
12 |
-
if (!($options = $self->options)) { // Not defined yet?
|
13 |
-
if (!is_array($options = get_site_option(GLOBAL_NS.'_options'))) {
|
14 |
-
$options = array(); // Force array.
|
15 |
-
}
|
16 |
-
if (!$options && is_array($zencache_options = get_site_option('zencache_options'))) {
|
17 |
-
$options = $zencache_options; // Old ZenCache options.
|
18 |
-
$options['crons_setup'] = $this->default_options['crons_setup'];
|
19 |
-
}
|
20 |
-
}
|
21 |
-
$self->options = array_merge($self->default_options, $options);
|
22 |
-
$self->options = $self->applyWpFilters(GLOBAL_NS.'_options', $self->options);
|
23 |
-
$self->options = array_intersect_key($self->options, $self->default_options);
|
24 |
-
|
25 |
-
foreach ($self->options as $_key => &$_value) {
|
26 |
-
$_value = trim((string) $_value); // Force strings.
|
27 |
-
} unset($_key, $_value); // Housekeeping.
|
28 |
-
|
29 |
-
$self->options['base_dir'] = trim($self->options['base_dir'], '\\/'." \t\n\r\0\x0B");
|
30 |
-
if (!$self->options['base_dir'] || strpos(basename($self->options['base_dir']), 'wp-') === 0) {
|
31 |
-
$self->options['base_dir'] = $self->default_options['base_dir'];
|
32 |
-
}
|
33 |
-
return $self->options; // Plugin options.
|
34 |
-
};
|
35 |
-
|
36 |
-
/*
|
37 |
-
* Update plugin options.
|
38 |
-
*
|
39 |
-
* @since 151002 Improving multisite compat.
|
40 |
-
*
|
41 |
-
* @param array $options One or more new options.
|
42 |
-
*
|
43 |
-
* @return array Plugin options after update.
|
44 |
-
*/
|
45 |
-
$self->updateOptions = function (array $options) use ($self) {
|
46 |
-
if (!IS_PRO) { // Do not save Pro option keys.
|
47 |
-
$options = array_diff_key($options, $self->pro_only_option_keys);
|
48 |
-
}
|
49 |
-
if (!empty($options['base_dir']) && $options['base_dir'] !== $self->options['base_dir']) {
|
50 |
-
$self->tryErasingAllFilesDirsIn($self->wpContentBaseDirTo(''));
|
51 |
-
}
|
52 |
-
$self->options = array_merge($self->default_options, $self->options, $options);
|
53 |
-
$self->options = array_intersect_key($self->options, $self->default_options);
|
54 |
-
update_site_option(GLOBAL_NS.'_options', $self->options);
|
55 |
-
|
56 |
-
return $self->getOptions();
|
57 |
-
};
|
58 |
-
|
59 |
-
/*
|
60 |
-
* Restore default plugin options.
|
61 |
-
*
|
62 |
-
* @since 151002 Improving multisite compat.
|
63 |
-
*
|
64 |
-
* @return array Plugin options after update.
|
65 |
-
*/
|
66 |
-
$self->restoreDefaultOptions = function () use ($self) {
|
67 |
-
delete_site_option(GLOBAL_NS.'_options'); // Force restore.
|
68 |
-
$self->options = $self->default_options; // In real-time.
|
69 |
-
return $self->getOptions();
|
70 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/PostUtils.php
DELETED
@@ -1,42 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* All post statuses.
|
6 |
-
*
|
7 |
-
* @since 150821 Improving bbPress support.
|
8 |
-
*
|
9 |
-
* @return array All post statuses.
|
10 |
-
*/
|
11 |
-
$self->postStatuses = function () use ($self) {
|
12 |
-
if (!is_null($statuses = &$self->cacheKey('postStatuses'))) {
|
13 |
-
return $statuses; // Already did this.
|
14 |
-
}
|
15 |
-
$statuses = get_post_stati();
|
16 |
-
$statuses = array_keys($statuses);
|
17 |
-
|
18 |
-
return $statuses;
|
19 |
-
};
|
20 |
-
|
21 |
-
/*
|
22 |
-
* All built-in post statuses.
|
23 |
-
*
|
24 |
-
* @since 150821 Improving bbPress support.
|
25 |
-
*
|
26 |
-
* @return array All built-in post statuses.
|
27 |
-
*/
|
28 |
-
$self->builtInPostStatuses = function () use ($self) {
|
29 |
-
if (!is_null($statuses = &$self->cacheKey('builtInPostStatuses'))) {
|
30 |
-
return $statuses; // Already did this.
|
31 |
-
}
|
32 |
-
$statuses = array(); // Initialize.
|
33 |
-
|
34 |
-
foreach (get_post_stati(array(), 'objects') as $_key => $_status) {
|
35 |
-
if (!empty($_status->_builtin)) {
|
36 |
-
$statuses[] = $_status->name;
|
37 |
-
}
|
38 |
-
}
|
39 |
-
unset($_key, $_status); // Housekeeping.
|
40 |
-
|
41 |
-
return $statuses;
|
42 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/UpdateUtils.php
DELETED
@@ -1,46 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Checks for a new lite release.
|
6 |
-
*
|
7 |
-
* @since 151220 Show version number in plugin options.
|
8 |
-
*
|
9 |
-
* @attaches-to `admin_init` hook.
|
10 |
-
*/
|
11 |
-
$self->maybeCheckLatestLiteVersion = function () use ($self) {
|
12 |
-
if (IS_PRO) {
|
13 |
-
return; // Not applicable.
|
14 |
-
}
|
15 |
-
if (!$self->options['lite_update_check']) {
|
16 |
-
return; // Nothing to do.
|
17 |
-
}
|
18 |
-
if (!current_user_can($self->update_cap)) {
|
19 |
-
return; // Nothing to do.
|
20 |
-
}
|
21 |
-
if (is_multisite() && !current_user_can($self->network_cap)) {
|
22 |
-
return; // Nothing to do.
|
23 |
-
}
|
24 |
-
if ($self->options['last_lite_update_check'] >= strtotime('-1 hour')) {
|
25 |
-
return; // No reason to keep checking on this.
|
26 |
-
}
|
27 |
-
$self->updateOptions(array('last_lite_update_check' => time()));
|
28 |
-
|
29 |
-
$product_api_url = 'https://'.urlencode(DOMAIN).'/';
|
30 |
-
$product_api_input_vars = array('product_api' => array('action' => 'latest_lite_version'));
|
31 |
-
|
32 |
-
$product_api_response = wp_remote_post($product_api_url, array('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 |
-
$self->updateOptions(array('latest_lite_version' => $product_api_response->lite_version));
|
37 |
-
}
|
38 |
-
// Disabling the notice for now. We only run this check to collect the latest version number.
|
39 |
-
#if ($self->options['latest_lite_version'] && version_compare(VERSION, $self->options['latest_lite_version'], '<')) {
|
40 |
-
# $self->dismissMainNotice('new-lite-version-available'); // Dismiss any existing notices like this.
|
41 |
-
# $lite_updater_page = network_admin_url('/plugins.php'); // In a network this points to the master plugins list.
|
42 |
-
# $self->enqueueMainNotice(sprintf(__('<strong>%1$s:</strong> a new version is now available. Please <a href="%2$s">upgrade to v%3$s</a>.', 'comet-cache'), esc_html(NAME), esc_attr($lite_updater_page), esc_html($self->options['latest_lite_version'])), array('persistent_key' => 'new-lite-version-available'));
|
43 |
-
#}
|
44 |
-
};
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/UrlUtils.php
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* URL to a Comet Cache plugin file.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param string $file Optional file path; relative to plugin directory.
|
10 |
-
* @param string $scheme Optional URL scheme; defaults to the current scheme.
|
11 |
-
*
|
12 |
-
* @return string URL to plugin directory; or to the specified `$file` if applicable.
|
13 |
-
*/
|
14 |
-
$self->url = function ($file = '', $scheme = '') use ($self) {
|
15 |
-
$url = rtrim(plugin_dir_url(PLUGIN_FILE), '/');
|
16 |
-
$url .= (string) $file;
|
17 |
-
|
18 |
-
if ($scheme) {
|
19 |
-
$url = set_url_scheme($url, (string) $scheme);
|
20 |
-
}
|
21 |
-
return $url;
|
22 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/UserUtils.php
DELETED
@@ -1,118 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Current user can clear the cache?
|
6 |
-
*
|
7 |
-
* @since 151002 Enhancing user permissions.
|
8 |
-
*
|
9 |
-
* @return boolean Current user can clear the cache?
|
10 |
-
*/
|
11 |
-
$self->currentUserCanClearCache = function () use ($self) {
|
12 |
-
if (!is_null($can = &$self->cacheKey('currentUserCanClearCache'))) {
|
13 |
-
return $can; // Already cached this.
|
14 |
-
}
|
15 |
-
$is_multisite = is_multisite();
|
16 |
-
|
17 |
-
if (!$is_multisite && current_user_can($self->cap)) {
|
18 |
-
return ($can = true); // Plugin admin.
|
19 |
-
}
|
20 |
-
if ($is_multisite && current_user_can($self->network_cap)) {
|
21 |
-
return ($can = true); // Plugin admin.
|
22 |
-
}
|
23 |
-
|
24 |
-
return ($can = false);
|
25 |
-
};
|
26 |
-
$self->currentUserCanWipeCache = $self->currentUserCanClearCache;
|
27 |
-
|
28 |
-
/*
|
29 |
-
* Current user can clear the opcache?
|
30 |
-
*
|
31 |
-
* @since 151114 Enhancing user permissions.
|
32 |
-
*
|
33 |
-
* @return boolean Current user can clear the opcache?
|
34 |
-
*/
|
35 |
-
$self->currentUserCanClearOpCache = function () use ($self) {
|
36 |
-
if (!is_null($can = &$self->cacheKey('currentUserCanClearOpCache'))) {
|
37 |
-
return $can; // Already cached this.
|
38 |
-
}
|
39 |
-
$is_multisite = is_multisite();
|
40 |
-
|
41 |
-
if (!$is_multisite && current_user_can($self->cap)) {
|
42 |
-
return ($can = true); // Plugin admin.
|
43 |
-
}
|
44 |
-
if ($is_multisite && current_user_can($self->network_cap)) {
|
45 |
-
return ($can = true); // Plugin admin.
|
46 |
-
}
|
47 |
-
return ($can = false);
|
48 |
-
};
|
49 |
-
$self->currentUserCanWipeOpCache = $self->currentUserCanClearOpCache;
|
50 |
-
|
51 |
-
/*
|
52 |
-
* Current user can clear the CDN cache?
|
53 |
-
*
|
54 |
-
* @since 151114 Enhancing user permissions.
|
55 |
-
*
|
56 |
-
* @return boolean Current user can clear the CDN cache?
|
57 |
-
*/
|
58 |
-
$self->currentUserCanClearCdnCache = function () use ($self) {
|
59 |
-
if (!is_null($can = &$self->cacheKey('currentUserCanClearCdnCache'))) {
|
60 |
-
return $can; // Already cached this.
|
61 |
-
}
|
62 |
-
$is_multisite = is_multisite();
|
63 |
-
|
64 |
-
if (!$is_multisite && current_user_can($self->cap)) {
|
65 |
-
return ($can = true); // Plugin admin.
|
66 |
-
}
|
67 |
-
if ($is_multisite && current_user_can($self->network_cap)) {
|
68 |
-
return ($can = true); // Plugin admin.
|
69 |
-
}
|
70 |
-
return ($can = false);
|
71 |
-
};
|
72 |
-
$self->currentUserCanWipeCdnCache = $self->currentUserCanClearCdnCache;
|
73 |
-
|
74 |
-
/*
|
75 |
-
* Current user can clear expired transients?
|
76 |
-
*
|
77 |
-
* @since 151220 Enhancing user permissions.
|
78 |
-
*
|
79 |
-
* @return boolean Current user can clear expired transients?
|
80 |
-
*/
|
81 |
-
$self->currentUserCanClearExpiredTransients = function () use ($self) {
|
82 |
-
if (!is_null($can = &$self->cacheKey('currentUserCanClearExpiredTransients'))) {
|
83 |
-
return $can; // Already cached this.
|
84 |
-
}
|
85 |
-
$is_multisite = is_multisite();
|
86 |
-
|
87 |
-
if (!$is_multisite && current_user_can($self->cap)) {
|
88 |
-
return ($can = true); // Plugin admin.
|
89 |
-
}
|
90 |
-
if ($is_multisite && current_user_can($self->network_cap)) {
|
91 |
-
return ($can = true); // Plugin admin.
|
92 |
-
}
|
93 |
-
return ($can = false);
|
94 |
-
};
|
95 |
-
$self->currentUserCanWipeExpiredTransients = $self->currentUserCanClearExpiredTransients;
|
96 |
-
|
97 |
-
/*
|
98 |
-
* Current user can see stats?
|
99 |
-
*
|
100 |
-
* @since 151002 Enhancing user permissions.
|
101 |
-
*
|
102 |
-
* @return boolean Current user can see stats?
|
103 |
-
*/
|
104 |
-
$self->currentUserCanSeeStats = function () use ($self) {
|
105 |
-
if (!is_null($can = &$self->cacheKey('currentUserCanSeeStats'))) {
|
106 |
-
return $can; // Already cached this.
|
107 |
-
}
|
108 |
-
$is_multisite = is_multisite();
|
109 |
-
|
110 |
-
if (!$is_multisite && current_user_can($self->cap)) {
|
111 |
-
return ($can = true); // Plugin admin.
|
112 |
-
}
|
113 |
-
if ($is_multisite && current_user_can($self->network_cap)) {
|
114 |
-
return ($can = true); // Plugin admin.
|
115 |
-
}
|
116 |
-
|
117 |
-
return ($can = false);
|
118 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpAuthorUtils.php
DELETED
@@ -1,92 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files for the author page(s).
|
6 |
-
*
|
7 |
-
* @attaches-to `post_updated` hook.
|
8 |
-
*
|
9 |
-
* @since 150422 Rewrite.
|
10 |
-
*
|
11 |
-
* @param int $post_id A WordPress post ID.
|
12 |
-
* @param \WP_Post $post_after WP_Post object following the update.
|
13 |
-
* @param \WP_Post $post_before WP_Post object before the update.
|
14 |
-
*
|
15 |
-
* @throws \Exception If a clear failure occurs.
|
16 |
-
*
|
17 |
-
* @return int Total files cleared by this routine (if any).
|
18 |
-
*
|
19 |
-
* @note If the author for the post is being changed, both the previous author
|
20 |
-
* and current author pages are cleared, if the post status is applicable.
|
21 |
-
*/
|
22 |
-
$self->autoClearAuthorPageCache = function ($post_id, \WP_Post $post_after, \WP_Post $post_before) use ($self) {
|
23 |
-
$counter = 0; // Initialize.
|
24 |
-
$enqueued_notices = 0; // Initialize.
|
25 |
-
$authors = array(); // Initialize.
|
26 |
-
$authors_to_clear = array(); // Initialize.
|
27 |
-
|
28 |
-
if (!($post_id = (integer) $post_id)) {
|
29 |
-
return $counter; // Nothing to do.
|
30 |
-
}
|
31 |
-
if (!is_null($done = &$self->cacheKey('autoClearAuthorPageCache', array($post_id, $post_after->ID, $post_before->ID)))) {
|
32 |
-
return $counter; // Already did this.
|
33 |
-
}
|
34 |
-
$done = true; // Flag as having been done.
|
35 |
-
|
36 |
-
if (!$self->options['enable']) {
|
37 |
-
return $counter; // Nothing to do.
|
38 |
-
}
|
39 |
-
if (!$self->options['cache_clear_author_page_enable']) {
|
40 |
-
return $counter; // Nothing to do.
|
41 |
-
}
|
42 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
43 |
-
return $counter; // Nothing to do.
|
44 |
-
}
|
45 |
-
/*
|
46 |
-
* If we're changing the post author AND
|
47 |
-
* the previous post status was either 'published' or 'private'
|
48 |
-
* then clear the author page for both authors.
|
49 |
-
*
|
50 |
-
* Else if the old post status was 'published' or 'private' OR
|
51 |
-
* the new post status is 'published' or 'private'
|
52 |
-
* then clear the author page for the current author.
|
53 |
-
*
|
54 |
-
* Else return the counter; post status does not warrant clearing author page cache.
|
55 |
-
*/
|
56 |
-
if ($post_after->post_author !== $post_before->post_author &&
|
57 |
-
($post_before->post_status === 'publish' || $post_before->post_status === 'private')
|
58 |
-
) {
|
59 |
-
$authors[] = (integer) $post_before->post_author;
|
60 |
-
$authors[] = (integer) $post_after->post_author;
|
61 |
-
} elseif (($post_before->post_status === 'publish' || $post_before->post_status === 'private') ||
|
62 |
-
($post_after->post_status === 'publish' || $post_after->post_status === 'private')
|
63 |
-
) {
|
64 |
-
$authors[] = (integer) $post_after->post_author;
|
65 |
-
}
|
66 |
-
if (!$authors) {
|
67 |
-
return $counter; // Nothing to do.
|
68 |
-
}
|
69 |
-
foreach ($authors as $_author_id) {
|
70 |
-
$authors_to_clear[$_author_id]['posts_url'] = get_author_posts_url($_author_id);
|
71 |
-
$authors_to_clear[$_author_id]['display_name'] = get_the_author_meta('display_name', $_author_id);
|
72 |
-
}
|
73 |
-
unset($_author_id); // Housekeeping.
|
74 |
-
|
75 |
-
foreach ($authors_to_clear as $_author) {
|
76 |
-
$_author_regex = $self->buildHostCachePathRegex($_author['posts_url']);
|
77 |
-
$_author_counter = $self->clearFilesFromHostCacheDir($_author_regex);
|
78 |
-
$counter += $_author_counter; // Add to overall counter.
|
79 |
-
|
80 |
-
if ($_author_counter && $enqueued_notices < 100 && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
81 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
82 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache for Author Page: <code>%3$s</code>; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($_author_counter)), esc_html($_author['display_name'])));
|
83 |
-
$enqueued_notices++; // Increment enqueued notices counter.
|
84 |
-
}
|
85 |
-
}
|
86 |
-
unset($_author, $_author_regex, $_author_counter); // Housekeeping.
|
87 |
-
|
88 |
-
$counter += $self->autoClearXmlFeedsCache('blog');
|
89 |
-
$counter += $self->autoClearXmlFeedsCache('post-authors', $post_id);
|
90 |
-
|
91 |
-
return $counter;
|
92 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpCommentUtils.php
DELETED
@@ -1,96 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files for a post associated with a particular comment.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @attaches-to `trackback_post` hook.
|
10 |
-
* @attaches-to `pingback_post` hook.
|
11 |
-
* @attaches-to `comment_post` hook.
|
12 |
-
*
|
13 |
-
* @param int $comment_id A WordPress comment ID.
|
14 |
-
*
|
15 |
-
* @return int Total files cleared by this routine (if any).
|
16 |
-
*/
|
17 |
-
$self->autoClearCommentPostCache = function ($comment_id) use ($self) {
|
18 |
-
$counter = 0; // Initialize.
|
19 |
-
|
20 |
-
if (!($comment_id = (integer) $comment_id)) {
|
21 |
-
return $counter; // Nothing to do.
|
22 |
-
}
|
23 |
-
if (!is_null($done = &$self->cacheKey('autoClearCommentPostCache', $comment_id))) {
|
24 |
-
return $counter; // Already did this.
|
25 |
-
}
|
26 |
-
$done = true; // Flag as having been done.
|
27 |
-
|
28 |
-
if (!$self->options['enable']) {
|
29 |
-
return $counter; // Nothing to do.
|
30 |
-
}
|
31 |
-
if (!is_object($comment = get_comment($comment_id))) {
|
32 |
-
return $counter; // Nothing we can do.
|
33 |
-
}
|
34 |
-
if (empty($comment->comment_post_ID)) {
|
35 |
-
return $counter; // Nothing we can do.
|
36 |
-
}
|
37 |
-
if ($comment->comment_approved === 'spam' || $comment->comment_approved === '0') {
|
38 |
-
// Don't allow next `autoClearPostCache()` call to clear post cache.
|
39 |
-
$allow = &$self->cacheKey('autoClearPostCache_allow');
|
40 |
-
$allow = false; // Flag as false; i.e., disallow.
|
41 |
-
return $counter;
|
42 |
-
}
|
43 |
-
$counter += $self->autoClearXmlFeedsCache('blog-comments');
|
44 |
-
$counter += $self->autoClearXmlFeedsCache('post-comments', $comment->comment_post_ID);
|
45 |
-
$counter += $self->autoClearPostCache($comment->comment_post_ID);
|
46 |
-
|
47 |
-
return $counter;
|
48 |
-
};
|
49 |
-
|
50 |
-
/*
|
51 |
-
* Automatically clears cache files for a post associated with a particular comment.
|
52 |
-
*
|
53 |
-
* @since 150422 Rewrite.
|
54 |
-
*
|
55 |
-
* @attaches-to `transition_comment_status` hook.
|
56 |
-
*
|
57 |
-
* @param string $new_status New comment status.
|
58 |
-
* @param string $old_status Old comment status.
|
59 |
-
* @param \stdClass $comment Comment object.
|
60 |
-
*
|
61 |
-
* @throws \Exception If a clear failure occurs.
|
62 |
-
*
|
63 |
-
* @return int Total files cleared by this routine (if any).
|
64 |
-
*
|
65 |
-
* @note This is also called upon by other routines which listen for
|
66 |
-
* events that are indirectly associated with a comment ID.
|
67 |
-
*/
|
68 |
-
$self->autoClearCommentPostCacheTransition = function ($new_status, $old_status, $comment) use ($self) {
|
69 |
-
$counter = 0; // Initialize.
|
70 |
-
|
71 |
-
if (!is_object($comment)) {
|
72 |
-
return $counter; // Nothing we can do.
|
73 |
-
}
|
74 |
-
if (empty($comment->comment_post_ID)) {
|
75 |
-
return $counter; // Nothing we can do.
|
76 |
-
}
|
77 |
-
if (!is_null($done = &$self->cacheKey('autoClearCommentPostCacheTransition', array($new_status, $old_status, $comment->comment_post_ID)))) {
|
78 |
-
return $counter; // Already did this.
|
79 |
-
}
|
80 |
-
$done = true; // Flag as having been done.
|
81 |
-
|
82 |
-
if (!$self->options['enable']) {
|
83 |
-
return $counter; // Nothing to do.
|
84 |
-
}
|
85 |
-
if (!($old_status === 'approved' || ($old_status === 'unapproved' && $new_status === 'approved'))) {
|
86 |
-
// If excluded here, don't allow next `autoClearPostCache()` call to clear post cache.
|
87 |
-
$allow = &$self->cacheKey('autoClearPostCache_allow');
|
88 |
-
$allow = false; // Flag as false; i.e., disallow.
|
89 |
-
return $counter;
|
90 |
-
}
|
91 |
-
$counter += $self->autoClearXmlFeedsCache('blog-comments');
|
92 |
-
$counter += $self->autoClearXmlFeedsCache('post-comments', $comment->comment_post_ID);
|
93 |
-
$counter += $self->autoClearPostCache($comment->comment_post_ID);
|
94 |
-
|
95 |
-
return $counter;
|
96 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpFeedUtils.php
DELETED
@@ -1,116 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files related to XML feeds.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param string $type Type of feed(s) to auto-clear.
|
10 |
-
* @param int $post_id A Post ID (when applicable).
|
11 |
-
*
|
12 |
-
* @throws \Exception If a clear failure occurs.
|
13 |
-
*
|
14 |
-
* @return int Total files cleared by this routine (if any).
|
15 |
-
*
|
16 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
17 |
-
* attached to any hooks. However, it is called upon by other routines attached to hooks.
|
18 |
-
*/
|
19 |
-
$self->autoClearXmlFeedsCache = function ($type, $post_id = 0) use ($self) {
|
20 |
-
$counter = 0; // Initialize.
|
21 |
-
|
22 |
-
if (!($type = (string) $type)) {
|
23 |
-
return $counter; // Nothing we can do.
|
24 |
-
}
|
25 |
-
$post_id = (integer) $post_id; // Force integer.
|
26 |
-
|
27 |
-
if (!is_null($done = &$self->cacheKey('autoClearXmlFeedsCache', array($type, $post_id)))) {
|
28 |
-
return $counter; // Already did this.
|
29 |
-
}
|
30 |
-
$done = true; // Flag as having been done.
|
31 |
-
|
32 |
-
if (!$self->options['enable']) {
|
33 |
-
return $counter; // Nothing to do.
|
34 |
-
}
|
35 |
-
if (!$self->options['feeds_enable']) {
|
36 |
-
return $counter; // Nothing to do.
|
37 |
-
}
|
38 |
-
if (!$self->options['cache_clear_xml_feeds_enable']) {
|
39 |
-
return $counter; // Nothing to do.
|
40 |
-
}
|
41 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
42 |
-
return $counter; // Nothing to do.
|
43 |
-
}
|
44 |
-
$utils = new FeedUtils(); // Feed utilities.
|
45 |
-
$variations = $variation_regex_frags = array(); // Initialize.
|
46 |
-
|
47 |
-
switch ($type) { // Handle clearing based on the `$type`.
|
48 |
-
|
49 |
-
case 'blog': // The blog feed; i.e. `/feed/` on most WP installs.
|
50 |
-
$variations = array_merge($variations, $utils->feedLinkVariations());
|
51 |
-
break; // Break switch handler.
|
52 |
-
|
53 |
-
case 'blog-comments': // The blog comments feed; i.e. `/comments/feed/` on most WP installs.
|
54 |
-
$variations = array_merge($variations, $utils->feedLinkVariations('comments_'));
|
55 |
-
break; // Break switch handler.
|
56 |
-
|
57 |
-
case 'post-comments': // Feeds related to comments that a post has.
|
58 |
-
if (!$post_id) {
|
59 |
-
break; // Break switch handler.
|
60 |
-
}
|
61 |
-
if (!($post = get_post($post_id))) {
|
62 |
-
break; // Break switch handler.
|
63 |
-
}
|
64 |
-
$variations = array_merge($variations, $utils->postCommentsFeedLinkVariations($post));
|
65 |
-
break; // Break switch handler.
|
66 |
-
|
67 |
-
case 'post-authors': // Feeds related to authors that a post has.
|
68 |
-
if (!$post_id) {
|
69 |
-
break; // Break switch handler.
|
70 |
-
}
|
71 |
-
if (!($post = get_post($post_id))) {
|
72 |
-
break; // Break switch handler.
|
73 |
-
}
|
74 |
-
$variations = array_merge($variations, $utils->postAuthorFeedLinkVariations($post));
|
75 |
-
break; // Break switch handler.
|
76 |
-
|
77 |
-
case 'post-terms': // Feeds related to terms that a post has.
|
78 |
-
if (!$post_id) {
|
79 |
-
break; // Break switch handler.
|
80 |
-
}
|
81 |
-
if (!($post = get_post($post_id))) {
|
82 |
-
break; // Break switch handler.
|
83 |
-
}
|
84 |
-
$variations = array_merge($variations, $utils->postTermFeedLinkVariations($post, true));
|
85 |
-
break; // Break switch handler.
|
86 |
-
|
87 |
-
case 'custom-post-type': // Feeds related to a custom post type archive view.
|
88 |
-
if (!$post_id) {
|
89 |
-
break; // Break switch handler.
|
90 |
-
}
|
91 |
-
if (!($post = get_post($post_id))) {
|
92 |
-
break; // Break switch handler.
|
93 |
-
}
|
94 |
-
$variations = array_merge($variations, $utils->postTypeArchiveFeedLinkVariations($post));
|
95 |
-
break; // Break switch handler.
|
96 |
-
|
97 |
-
// @TODO Possibly consider search-related feeds in the future.
|
98 |
-
// See: <http://codex.wordpress.org/WordPress_Feeds#Categories_and_Tags>
|
99 |
-
}
|
100 |
-
if (!($variation_regex_frags = $utils->convertVariationsToHostCachePathRegexFrags($variations))) {
|
101 |
-
return $counter; // Nothing to do here.
|
102 |
-
}
|
103 |
-
$in_sets_of = $self->applyWpFilters(GLOBAL_NS.'_autoClearXmlFeedsCache_in_sets_of', 10, get_defined_vars());
|
104 |
-
for ($_i = 0; $_i < count($variation_regex_frags); $_i = $_i + $in_sets_of) {
|
105 |
-
$_variation_regex_frags = array_slice($variation_regex_frags, $_i, $in_sets_of);
|
106 |
-
$_regex = '/^\/(?:'.implode('|', $_variation_regex_frags).')\./i';
|
107 |
-
$counter += $self->clearFilesFromHostCacheDir($_regex);
|
108 |
-
}
|
109 |
-
unset($_i, $_variation_regex_frags, $_regex); // Housekeeping.
|
110 |
-
|
111 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
112 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
113 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache, for XML feeds of type: <code>%3$s</code>; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter)), esc_html($type)));
|
114 |
-
}
|
115 |
-
return $counter;
|
116 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpHomeBlogUtils.php
DELETED
@@ -1,101 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files for the home page.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @throws \Exception If a clear failure occurs.
|
10 |
-
*
|
11 |
-
* @return int Total files cleared by this routine (if any).
|
12 |
-
*
|
13 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
14 |
-
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
15 |
-
*/
|
16 |
-
$self->autoClearHomePageCache = function () use ($self) {
|
17 |
-
$counter = 0; // Initialize.
|
18 |
-
|
19 |
-
if (!is_null($done = &$self->cacheKey('autoClearHomePageCache'))) {
|
20 |
-
return $counter; // Already did this.
|
21 |
-
}
|
22 |
-
$done = true; // Flag as having been done.
|
23 |
-
|
24 |
-
if (!$self->options['enable']) {
|
25 |
-
return $counter; // Nothing to do.
|
26 |
-
}
|
27 |
-
if (!$self->options['cache_clear_home_page_enable']) {
|
28 |
-
return $counter; // Nothing to do.
|
29 |
-
}
|
30 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
31 |
-
return $counter; // Nothing to do.
|
32 |
-
}
|
33 |
-
$regex = $self->buildHostCachePathRegex(home_url('/'));
|
34 |
-
$counter += $self->clearFilesFromHostCacheDir($regex);
|
35 |
-
|
36 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
37 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
38 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache for the designated "Home Page"; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter))));
|
39 |
-
}
|
40 |
-
$counter += $self->autoClearXmlFeedsCache('blog');
|
41 |
-
|
42 |
-
return $counter;
|
43 |
-
};
|
44 |
-
|
45 |
-
/*
|
46 |
-
* Automatically clears cache files for the posts page.
|
47 |
-
*
|
48 |
-
* @since 150422 Rewrite.
|
49 |
-
*
|
50 |
-
* @throws \Exception If a clear failure occurs.
|
51 |
-
*
|
52 |
-
* @return int Total files cleared by this routine (if any).
|
53 |
-
*
|
54 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
55 |
-
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
56 |
-
*/
|
57 |
-
$self->autoClearPostsPageCache = function () use ($self) {
|
58 |
-
$counter = 0; // Initialize.
|
59 |
-
|
60 |
-
if (!is_null($done = &$self->cacheKey('autoClearPostsPageCache'))) {
|
61 |
-
return $counter; // Already did this.
|
62 |
-
}
|
63 |
-
$done = true; // Flag as having been done.
|
64 |
-
|
65 |
-
if (!$self->options['enable']) {
|
66 |
-
return $counter; // Nothing to do.
|
67 |
-
}
|
68 |
-
if (!$self->options['cache_clear_posts_page_enable']) {
|
69 |
-
return $counter; // Nothing to do.
|
70 |
-
}
|
71 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
72 |
-
return $counter; // Nothing to do.
|
73 |
-
}
|
74 |
-
$show_on_front = get_option('show_on_front');
|
75 |
-
$page_for_posts = get_option('page_for_posts');
|
76 |
-
|
77 |
-
if (!in_array($show_on_front, array('posts', 'page'), true)) {
|
78 |
-
return $counter; // Nothing we can do in this case.
|
79 |
-
}
|
80 |
-
if ($show_on_front === 'page' && !$page_for_posts) {
|
81 |
-
return $counter; // Nothing we can do.
|
82 |
-
}
|
83 |
-
if ($show_on_front === 'posts') {
|
84 |
-
$posts_page = home_url('/');
|
85 |
-
} elseif ($show_on_front === 'page') {
|
86 |
-
$posts_page = get_permalink($page_for_posts);
|
87 |
-
}
|
88 |
-
if (empty($posts_page)) {
|
89 |
-
return $counter; // Nothing we can do.
|
90 |
-
}
|
91 |
-
$regex = $self->buildHostCachePathRegex($posts_page);
|
92 |
-
$counter += $self->clearFilesFromHostCacheDir($regex);
|
93 |
-
|
94 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
95 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
96 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache for the designated "Posts Page"; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter))));
|
97 |
-
}
|
98 |
-
$counter += $self->autoClearXmlFeedsCache('blog');
|
99 |
-
|
100 |
-
return $counter;
|
101 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpJetpackUtils.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears all cache files for current blog when JetPack Custom CSS is saved.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @attaches-to `safecss_save_pre` hook.
|
10 |
-
*
|
11 |
-
* @param array $args Args passed in by hook.
|
12 |
-
*/
|
13 |
-
$self->autoClearCacheOnJetpackCustomCss = function ($args) use ($self) {
|
14 |
-
$counter = 0; // Initialize.
|
15 |
-
|
16 |
-
if (!is_null($done = &$self->cacheKey('autoClearCacheOnJetpackCustomCss', $args))) {
|
17 |
-
return $counter; // Already did this.
|
18 |
-
}
|
19 |
-
$done = true; // Flag as having been done.
|
20 |
-
|
21 |
-
if (empty($args['is_preview']) && class_exists('\\Jetpack')) {
|
22 |
-
$counter += $self->autoClearCache();
|
23 |
-
}
|
24 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpOpcacheUtils.php
DELETED
@@ -1,69 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Wipe (i.e., reset) OPCache.
|
6 |
-
*
|
7 |
-
* @since 151002 Adding OPCache support.
|
8 |
-
*
|
9 |
-
* @param bool $manually True if wiping is done manually.
|
10 |
-
* @param boolean $maybe Defaults to a true value.
|
11 |
-
* @param array $files Optional; wipe only specific files?
|
12 |
-
*
|
13 |
-
* @return integer Total keys wiped.
|
14 |
-
*/
|
15 |
-
$self->wipeOpcache = function ($manually = false, $maybe = true, $files = array()) use ($self) {
|
16 |
-
$counter = 0; // Initialize counter.
|
17 |
-
|
18 |
-
if ($maybe && !$self->options['cache_clear_opcache_enable']) {
|
19 |
-
return $counter; // Not enabled at this time.
|
20 |
-
}
|
21 |
-
if (!$self->functionIsPossible('opcache_reset')) {
|
22 |
-
return $counter; // Not possible.
|
23 |
-
}
|
24 |
-
if (!($status = $self->sysOpcacheStatus())) {
|
25 |
-
return $counter; // Not possible.
|
26 |
-
}
|
27 |
-
if (empty($status->opcache_enabled)) {
|
28 |
-
return $counter; // Not necessary.
|
29 |
-
}
|
30 |
-
if (empty($status->opcache_statistics->num_cached_keys)) {
|
31 |
-
return $counter; // Not possible.
|
32 |
-
}
|
33 |
-
if ($files) { // Specific files?
|
34 |
-
foreach ($files as $_file) {
|
35 |
-
$counter += (int) opcache_invalidate($_file, true);
|
36 |
-
} // unset($_file); // Housekeeping.
|
37 |
-
} elseif (opcache_reset()) { // True if a reset occurs.
|
38 |
-
$counter += $status->opcache_statistics->num_cached_keys;
|
39 |
-
}
|
40 |
-
return $counter;
|
41 |
-
};
|
42 |
-
|
43 |
-
/*
|
44 |
-
* Clear (i.e., reset) OPCache.
|
45 |
-
*
|
46 |
-
* @since 151002 Adding OPCache support.
|
47 |
-
*
|
48 |
-
* @param bool $manually True if clearing is done manually.
|
49 |
-
* @param boolean $maybe Defaults to a true value.
|
50 |
-
*
|
51 |
-
* @return integer Total keys cleared.
|
52 |
-
*/
|
53 |
-
$self->clearOpcache = function ($manually = false, $maybe = true) use ($self) {
|
54 |
-
if (!is_multisite() || is_main_site() || current_user_can($self->network_cap)) {
|
55 |
-
return $self->wipeOpcache($manually, $maybe);
|
56 |
-
}
|
57 |
-
return 0; // Not applicable.
|
58 |
-
};
|
59 |
-
|
60 |
-
/*
|
61 |
-
* Clear AC class file from Opcache (by force).
|
62 |
-
*
|
63 |
-
* @since 151215 Adding OPCache support.
|
64 |
-
*
|
65 |
-
* @return integer Total keys cleared.
|
66 |
-
*/
|
67 |
-
$self->clearAcDropinFromOpcacheByForce = function () use ($self) {
|
68 |
-
return $self->wipeOpcache(false, false, array(WP_CONTENT_DIR.'/advanced-cache.php'));
|
69 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpPluginUtils.php
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically wipes/clears on plugin activation/deactivation.
|
6 |
-
*
|
7 |
-
* @since 151220 Adding auto-wipe|clear on plugin activations/deactivations.
|
8 |
-
*
|
9 |
-
* @attaches-to `activated_plugin` hook.
|
10 |
-
* @attaches-to `deactivated_plugin` hook.
|
11 |
-
*
|
12 |
-
* @param string $plugin Plugin basename.
|
13 |
-
* @param bool True if activating|deactivating network-wide. Defaults to boolean `FALSE` in case parameter is not passed to hook.
|
14 |
-
*
|
15 |
-
* @return int Total files wiped|cleared by this routine (if any).
|
16 |
-
*/
|
17 |
-
$self->autoClearOnPluginActivationDeactivation = function ($plugin, $network_wide = false) use ($self) {
|
18 |
-
if (!$self->applyWpFilters(GLOBAL_NS.'_auto_clear_on_plugin_activation_deactivation', true)) {
|
19 |
-
return 0; // Nothing to do here.
|
20 |
-
}
|
21 |
-
return $self->{($network_wide ? 'autoWipeCache' : 'autoClearCache')}();
|
22 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpPostTypeUtils.php
DELETED
@@ -1,66 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files for a custom post type archive view.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param int $post_id A WordPress post ID.
|
10 |
-
*
|
11 |
-
* @throws \Exception If a clear failure occurs.
|
12 |
-
*
|
13 |
-
* @return int Total files cleared by this routine (if any).
|
14 |
-
*
|
15 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
16 |
-
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
17 |
-
*/
|
18 |
-
$self->autoClearCustomPostTypeArchiveCache = function ($post_id) use ($self) {
|
19 |
-
$counter = 0; // Initialize.
|
20 |
-
|
21 |
-
if (!($post_id = (integer) $post_id)) {
|
22 |
-
return $counter; // Nothing to do.
|
23 |
-
}
|
24 |
-
if (!is_null($done = &$self->cacheKey('autoClearCustomPostTypeArchiveCache', $post_id))) {
|
25 |
-
return $counter; // Already did this.
|
26 |
-
}
|
27 |
-
$done = true; // Flag as having been done.
|
28 |
-
|
29 |
-
if (!$self->options['enable']) {
|
30 |
-
return $counter; // Nothing to do.
|
31 |
-
}
|
32 |
-
if (!$self->options['cache_clear_custom_post_type_enable']) {
|
33 |
-
return $counter; // Nothing to do.
|
34 |
-
}
|
35 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
36 |
-
return $counter; // Nothing to do.
|
37 |
-
}
|
38 |
-
if (!($post_type = get_post_type($post_id))) {
|
39 |
-
return $counter; // Nothing to do.
|
40 |
-
}
|
41 |
-
if (!($all_custom_post_types = get_post_types(array('_builtin' => false)))) {
|
42 |
-
return $counter; // No custom post types.
|
43 |
-
}
|
44 |
-
if (!in_array($post_type, array_keys($all_custom_post_types), true)) {
|
45 |
-
return $counter; // This is NOT a custom post type.
|
46 |
-
}
|
47 |
-
if (!($custom_post_type = get_post_type_object($post_type))) {
|
48 |
-
return $counter; // Unable to retrieve post type.
|
49 |
-
}
|
50 |
-
if (empty($custom_post_type->labels->name) || !($custom_post_type_name = $custom_post_type->labels->name)) {
|
51 |
-
$custom_post_type_name = __('Untitled', 'comet-cache');
|
52 |
-
}
|
53 |
-
if (!($custom_post_type_archive_link = get_post_type_archive_link($post_type))) {
|
54 |
-
return $counter; // Nothing to do; no link to work from in this case.
|
55 |
-
}
|
56 |
-
$regex = $self->buildHostCachePathRegex($custom_post_type_archive_link);
|
57 |
-
$counter += $self->clearFilesFromHostCacheDir($regex);
|
58 |
-
|
59 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
60 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
61 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache for Custom Post Type: <code>%3$s</code>; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter)), esc_html($custom_post_type_name)));
|
62 |
-
}
|
63 |
-
$counter += $self->autoClearXmlFeedsCache('custom-post-type', $post_id);
|
64 |
-
|
65 |
-
return $counter;
|
66 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpPostUtils.php
DELETED
@@ -1,176 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files for a particular post.
|
6 |
-
*
|
7 |
-
* @attaches-to `save_post` hook.
|
8 |
-
* @attaches-to `delete_post` hook.
|
9 |
-
* @attaches-to `clean_post_cache` hook.
|
10 |
-
*
|
11 |
-
* @since 150422 Rewrite.
|
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 also called upon by other routines which listen for
|
23 |
-
* events that are indirectly associated with a post ID.
|
24 |
-
*/
|
25 |
-
$self->autoClearPostCache = function ($post_id, $force = false) use ($self) {
|
26 |
-
$counter = 0; // Initialize.
|
27 |
-
|
28 |
-
if (!is_null($allow = &$self->cacheKey('autoClearPostCache_allow'))) {
|
29 |
-
if ($allow === false) { // Disallow?
|
30 |
-
$allow = true; // Reset flag.
|
31 |
-
return $counter;
|
32 |
-
}
|
33 |
-
}
|
34 |
-
if (!($post_id = (integer) $post_id)) {
|
35 |
-
return $counter; // Nothing to do.
|
36 |
-
}
|
37 |
-
if (!is_null($done = &$self->cacheKey('autoClearPostCache', array($post_id, $force)))) {
|
38 |
-
return $counter; // Already did this.
|
39 |
-
}
|
40 |
-
$done = true; // Flag as having been done.
|
41 |
-
|
42 |
-
if (!$self->options['enable']) {
|
43 |
-
return $counter; // Nothing to do.
|
44 |
-
}
|
45 |
-
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
46 |
-
return $counter; // Nothing to do.
|
47 |
-
}
|
48 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
49 |
-
return $counter; // Nothing to do.
|
50 |
-
}
|
51 |
-
if (!($post_type = get_post_type($post_id))) {
|
52 |
-
return $counter; // Nothing to do.
|
53 |
-
}
|
54 |
-
$post_statuses = $self->postStatuses();
|
55 |
-
$unpublished_post_statuses = array_diff($post_statuses, array('publish'));
|
56 |
-
$is_bbpress_post_type = in_array($post_type, $self->bbPressPostTypes(), true);
|
57 |
-
|
58 |
-
if (!empty($self->pre_post_update_post_permalink[$post_id])) {
|
59 |
-
$permalink = $self->pre_post_update_post_permalink[$post_id];
|
60 |
-
$self->pre_post_update_post_permalink[$post_id] = ''; // Reset; only used for post status transitions.
|
61 |
-
} elseif (!($permalink = get_permalink($post_id))) {
|
62 |
-
return $counter; // Nothing we can do.
|
63 |
-
}
|
64 |
-
if (!($post_status = get_post_status($post_id))) {
|
65 |
-
return $counter; // Nothing to do.
|
66 |
-
}
|
67 |
-
if ($post_status === 'draft' && isset($GLOBALS['pagenow'], $_POST['publish'])
|
68 |
-
&& is_admin() && $GLOBALS['pagenow'] === 'post.php' && current_user_can('publish_posts')
|
69 |
-
&& strpos(wp_get_referer(), '/post-new.php') !== false
|
70 |
-
) {
|
71 |
-
$post_status = 'publish'; // A new post being published now.
|
72 |
-
}
|
73 |
-
if (in_array($post_status, array('inherit', 'auto-draft'), true)) {
|
74 |
-
return $counter; // Nothing to do. Note: `inherit` = revision.
|
75 |
-
}
|
76 |
-
if (in_array($post_status, array('draft', 'pending', 'future', 'trash'), true) && !$force) {
|
77 |
-
return $counter; // Nothing to do; i.e., NOT forcing in this case.
|
78 |
-
}
|
79 |
-
if (($post_type_obj = get_post_type_object($post_type)) && !empty($post_type_obj->labels->singular_name)) {
|
80 |
-
$post_type_singular_name = $post_type_obj->labels->singular_name; // Singular name for the post type.
|
81 |
-
} else {
|
82 |
-
$post_type_singular_name = __('Post', 'comet-cache'); // Default value.
|
83 |
-
}
|
84 |
-
$regex = $self->buildHostCachePathRegex($permalink);
|
85 |
-
$counter += $self->clearFilesFromHostCacheDir($regex);
|
86 |
-
|
87 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
88 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
89 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache for %3$s ID: <code>%4$s</code>; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter)), esc_html($post_type_singular_name), esc_html($post_id)));
|
90 |
-
}
|
91 |
-
$counter += $self->autoClearXmlFeedsCache('blog');
|
92 |
-
$counter += $self->autoClearXmlFeedsCache('post-terms', $post_id);
|
93 |
-
$counter += $self->autoClearXmlFeedsCache('post-authors', $post_id);
|
94 |
-
|
95 |
-
$counter += $self->autoClearXmlSitemapsCache();
|
96 |
-
$counter += $self->autoClearHomePageCache();
|
97 |
-
$counter += $self->autoClearPostsPageCache();
|
98 |
-
$counter += $self->autoClearPostTermsCache($post_id, $force);
|
99 |
-
$counter += $self->autoClearCustomPostTypeArchiveCache($post_id);
|
100 |
-
|
101 |
-
|
102 |
-
if ($post_type !== 'page' && ($parent_post_id = wp_get_post_parent_id($post_id))) {
|
103 |
-
// Recursion: i.e., nested post types like bbPress forums/topic/replies.
|
104 |
-
$counter += $self->autoClearPostCache($parent_post_id, $force);
|
105 |
-
}
|
106 |
-
return $counter;
|
107 |
-
};
|
108 |
-
$self->auto_clear_post_cache = $self->autoClearPostCache; // Back compat.
|
109 |
-
|
110 |
-
/*
|
111 |
-
* Handles post status transitioning.
|
112 |
-
*
|
113 |
-
* @attaches-to `pre_post_update` hook.
|
114 |
-
*
|
115 |
-
* @since 150422 Rewrite.
|
116 |
-
*
|
117 |
-
* @param int $post_id Post ID.
|
118 |
-
* @param array $data Array of unslashed post data.
|
119 |
-
*
|
120 |
-
* @throws \Exception If a clear failure occurs.
|
121 |
-
*
|
122 |
-
* @return int Total files cleared by this routine (if any).
|
123 |
-
*
|
124 |
-
* @note This is also called upon by other routines which listen for
|
125 |
-
* events that are indirectly associated with a post ID.
|
126 |
-
*/
|
127 |
-
$self->autoClearPostCacheTransition = function ($post_id, $data) use ($self) {
|
128 |
-
$counter = 0; // Initialize.
|
129 |
-
|
130 |
-
$old_status = (string) get_post_status($post_id);
|
131 |
-
$new_status = (string) $data['post_status'];
|
132 |
-
/*
|
133 |
-
* When a post has a status of `pending` or `draft`, the `get_permalink()` function
|
134 |
-
* does not return a friendly permalink and therefore `autoClearPostCache()` will
|
135 |
-
* have no way of building a path to the cache file that should be cleared as part of
|
136 |
-
* this post status transition. To get around this, we temporarily store the permalink
|
137 |
-
* in $self->pre_post_update_post_permalink for `autoClearPostCache()` to use.
|
138 |
-
*
|
139 |
-
* See also: <https://github.com/websharks/zencache/issues/441>
|
140 |
-
*/
|
141 |
-
if (in_array($new_status, array('pending', 'draft'), true)) {
|
142 |
-
$self->pre_post_update_post_permalink[$post_id] = get_permalink($post_id);
|
143 |
-
}
|
144 |
-
// Begin post status transition sub-routine now.
|
145 |
-
|
146 |
-
if (!is_null($done = &$self->cacheKey('autoClearPostCacheTransition', array($old_status, $new_status, $post_id)))) {
|
147 |
-
return $counter; // Already did this.
|
148 |
-
}
|
149 |
-
$done = true; // Flag as having been done.
|
150 |
-
|
151 |
-
if (!$self->options['enable']) {
|
152 |
-
return $counter; // Nothing to do.
|
153 |
-
}
|
154 |
-
if ($new_status === $old_status) {
|
155 |
-
return $counter; // Nothing to do.
|
156 |
-
}
|
157 |
-
if (!($post_type = get_post_type($post_id))) {
|
158 |
-
return $counter; // Nothing to do.
|
159 |
-
}
|
160 |
-
$post_statuses = $self->postStatuses();
|
161 |
-
$unpublished_post_statuses = array_diff($post_statuses, array('publish'));
|
162 |
-
$is_bbpress_post_type = in_array($post_type, $self->bbPressPostTypes(), true);
|
163 |
-
|
164 |
-
if ($is_bbpress_post_type) {
|
165 |
-
if (in_array($old_status, array('publish', 'private', 'closed', 'spam', 'hidden'), true)) {
|
166 |
-
if (in_array($new_status, $unpublished_post_statuses, true)) {
|
167 |
-
$counter += $self->autoClearPostCache($post_id, true);
|
168 |
-
}
|
169 |
-
}
|
170 |
-
} elseif (in_array($old_status, array('publish', 'private'), true)) {
|
171 |
-
if (in_array($new_status, $unpublished_post_statuses, true)) {
|
172 |
-
$counter += $self->autoClearPostCache($post_id, true);
|
173 |
-
}
|
174 |
-
}
|
175 |
-
return $counter;
|
176 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpSettingUtils.php
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears all cache files for current blog under various conditions;
|
6 |
-
* used to check for conditions that don't have a hook that we can attach to.
|
7 |
-
*
|
8 |
-
* @since 150422 Rewrite.
|
9 |
-
*
|
10 |
-
* @attaches-to `admin_init` hook.
|
11 |
-
*/
|
12 |
-
$self->autoClearCacheOnSettingChanges = function () use ($self) {
|
13 |
-
$counter = 0; // Initialize.
|
14 |
-
$pagenow = !empty($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : '';
|
15 |
-
$settings_updated = !empty($_REQUEST['settings-updated']);
|
16 |
-
|
17 |
-
if (!is_null($done = &$self->cacheKey('autoClearCacheOnSettingChanges', array($pagenow, $settings_updated)))) {
|
18 |
-
return $counter; // Already did this.
|
19 |
-
}
|
20 |
-
$done = true; // Flag as having been done.
|
21 |
-
|
22 |
-
if ($pagenow === 'options-general.php' && $settings_updated) {
|
23 |
-
$counter += $self->autoClearCache();
|
24 |
-
} elseif ($pagenow === 'options-reading.php' && $settings_updated) {
|
25 |
-
$counter += $self->autoClearCache();
|
26 |
-
} elseif ($pagenow === 'options-discussion.php' && $settings_updated) {
|
27 |
-
$counter += $self->autoClearCache();
|
28 |
-
} elseif ($pagenow === 'options-permalink.php' && $settings_updated) {
|
29 |
-
$counter += $self->autoClearCache();
|
30 |
-
}
|
31 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpSitemapUtils.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files related to XML sitemaps.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @throws \Exception If a clear failure occurs.
|
10 |
-
*
|
11 |
-
* @return int Total files cleared by this routine (if any).
|
12 |
-
*
|
13 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
14 |
-
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
15 |
-
*/
|
16 |
-
$self->autoClearXmlSitemapsCache = function () use ($self) {
|
17 |
-
$counter = 0; // Initialize.
|
18 |
-
|
19 |
-
if (!is_null($done = &$self->cacheKey('autoClearXmlSitemapsCache'))) {
|
20 |
-
return $counter; // Already did this.
|
21 |
-
}
|
22 |
-
$done = true; // Flag as having been done.
|
23 |
-
|
24 |
-
if (!$self->options['enable']) {
|
25 |
-
return $counter; // Nothing to do.
|
26 |
-
}
|
27 |
-
if (!$self->options['cache_clear_xml_sitemaps_enable']) {
|
28 |
-
return $counter; // Nothing to do.
|
29 |
-
}
|
30 |
-
if (!$self->options['cache_clear_xml_sitemap_patterns']) {
|
31 |
-
return $counter; // Nothing to do.
|
32 |
-
}
|
33 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
34 |
-
return $counter; // Nothing to do.
|
35 |
-
}
|
36 |
-
if (!($regex_frags = $self->buildHostCachePathRegexFragsFromWcUris($self->options['cache_clear_xml_sitemap_patterns'], ''))) {
|
37 |
-
return $counter; // There are no patterns to look for.
|
38 |
-
}
|
39 |
-
$regex = $self->buildHostCachePathRegex('', '\/'.$regex_frags.'\.');
|
40 |
-
$counter += $self->clearFilesFromHostCacheDir($regex);
|
41 |
-
|
42 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
43 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
44 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache for XML sitemaps; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter))));
|
45 |
-
}
|
46 |
-
return $counter;
|
47 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpTermUtils.php
DELETED
@@ -1,139 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache files for terms associated with a post.
|
6 |
-
*
|
7 |
-
* @attaches-to `added_term_relationship` hook.
|
8 |
-
* @attaches-to `delete_term_relationships` hook.
|
9 |
-
*
|
10 |
-
* @since 150422 Rewrite.
|
11 |
-
*
|
12 |
-
* @param int $post_id A WordPress post ID.
|
13 |
-
* @param bool $force Defaults to a `FALSE` value.
|
14 |
-
* Pass as TRUE if clearing should be done for `draft`, `pending`,
|
15 |
-
* or `future` post statuses.
|
16 |
-
*
|
17 |
-
* @throws \Exception If a clear failure occurs.
|
18 |
-
*
|
19 |
-
* @return int Total files cleared by this routine (if any).
|
20 |
-
*
|
21 |
-
* @note In addition to the hooks this is attached to, it is also
|
22 |
-
* called upon by {@link autoClearPostCache()}.
|
23 |
-
*/
|
24 |
-
$self->autoClearPostTermsCache = function ($post_id, $force = false) use ($self) {
|
25 |
-
$counter = 0; // Initialize.
|
26 |
-
$enqueued_notices = 0; // Initialize.
|
27 |
-
|
28 |
-
if (!($post_id = (integer) $post_id)) {
|
29 |
-
return $counter; // Nothing to do.
|
30 |
-
}
|
31 |
-
if (!is_null($done = &$self->cacheKey('autoClearPostTermsCache', array($post_id, $force)))) {
|
32 |
-
return $counter; // Already did this.
|
33 |
-
}
|
34 |
-
$done = true; // Flag as having been done.
|
35 |
-
|
36 |
-
if (!$self->options['enable']) {
|
37 |
-
return $counter; // Nothing to do.
|
38 |
-
}
|
39 |
-
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
40 |
-
return $counter; // Nothing to do.
|
41 |
-
}
|
42 |
-
if (!$self->options['cache_clear_term_category_enable'] && !$self->options['cache_clear_term_post_tag_enable'] && !$self->options['cache_clear_term_other_enable']) {
|
43 |
-
return $counter; // Nothing to do.
|
44 |
-
}
|
45 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
46 |
-
return $counter; // Nothing to do.
|
47 |
-
}
|
48 |
-
$post_status = get_post_status($post_id); // Cache this.
|
49 |
-
|
50 |
-
if ($post_status === 'draft' && isset($GLOBALS['pagenow'], $_POST['publish'])
|
51 |
-
&& is_admin() && $GLOBALS['pagenow'] === 'post.php' && current_user_can('publish_posts')
|
52 |
-
&& strpos(wp_get_referer(), '/post-new.php') !== false
|
53 |
-
) {
|
54 |
-
$post_status = 'publish'; // A new post being published now.
|
55 |
-
}
|
56 |
-
if (in_array($post_status, array('inherit', 'auto-draft'), true)) {
|
57 |
-
return $counter; // Nothing to do. Note: `inherit` = revision.
|
58 |
-
}
|
59 |
-
if (in_array($post_status, array('draft', 'pending', 'future'), true) && !$force) {
|
60 |
-
return $counter; // Nothing to do; i.e., NOT forcing in this case.
|
61 |
-
}
|
62 |
-
/*
|
63 |
-
* Build an array of available taxonomies for this post (as taxonomy objects).
|
64 |
-
*/
|
65 |
-
$taxonomies = get_object_taxonomies(get_post($post_id), 'objects');
|
66 |
-
|
67 |
-
if (!is_array($taxonomies)) {
|
68 |
-
return $counter; // Nothing to do.
|
69 |
-
}
|
70 |
-
/*
|
71 |
-
* Build an array of terms associated with this post for each taxonomy.
|
72 |
-
* Also save taxonomy label information for Dashboard messaging later.
|
73 |
-
*/
|
74 |
-
$terms = array();
|
75 |
-
$taxonomy_labels = array();
|
76 |
-
|
77 |
-
foreach ($taxonomies as $_taxonomy) {
|
78 |
-
if (// Check if this is a taxonomy/term that we should clear.
|
79 |
-
($_taxonomy->name === 'category' && !$self->options['cache_clear_term_category_enable'])
|
80 |
-
|| ($_taxonomy->name === 'post_tag' && !$self->options['cache_clear_term_post_tag_enable'])
|
81 |
-
|| ($_taxonomy->name !== 'category' && $_taxonomy->name !== 'post_tag' && !$self->options['cache_clear_term_other_enable'])
|
82 |
-
) {
|
83 |
-
continue; // Continue; nothing to do for this taxonomy.
|
84 |
-
}
|
85 |
-
if (is_array($_terms = wp_get_post_terms($post_id, $_taxonomy->name))) {
|
86 |
-
$terms = array_merge($terms, $_terms);
|
87 |
-
if (empty($_taxonomy->labels->singular_name) || $_taxonomy->labels->singular_name === '') {
|
88 |
-
$taxonomy_labels[$_taxonomy->name] = $_taxonomy->name;
|
89 |
-
} else {
|
90 |
-
$taxonomy_labels[$_taxonomy->name] = $_taxonomy->labels->singular_name;
|
91 |
-
}
|
92 |
-
}
|
93 |
-
}
|
94 |
-
unset($_taxonomy, $_terms);
|
95 |
-
|
96 |
-
if (empty($terms)) {
|
97 |
-
return $counter; // Nothing to do.
|
98 |
-
}
|
99 |
-
/*
|
100 |
-
* Build an array of terms with term names,
|
101 |
-
* permalinks, and associated taxonomy labels.
|
102 |
-
*/
|
103 |
-
$terms_to_clear = array();
|
104 |
-
$_i = 0;
|
105 |
-
|
106 |
-
foreach ($terms as $_term) {
|
107 |
-
if (($_link = get_term_link($_term))) {
|
108 |
-
$terms_to_clear[$_i]['permalink'] = $_link;
|
109 |
-
$terms_to_clear[$_i]['term_name'] = $_term->name;
|
110 |
-
if (!empty($taxonomy_labels[$_term->taxonomy])) {
|
111 |
-
$terms_to_clear[$_i]['taxonomy_label'] = $taxonomy_labels[$_term->taxonomy];
|
112 |
-
} else {
|
113 |
-
$terms_to_clear[$_i]['taxonomy_label'] = $_term->taxonomy;
|
114 |
-
}
|
115 |
-
}
|
116 |
-
++$_i; // Array index counter.
|
117 |
-
}
|
118 |
-
unset($_term, $_link, $_i);
|
119 |
-
|
120 |
-
if (empty($terms_to_clear)) {
|
121 |
-
return $counter; // Nothing to do.
|
122 |
-
}
|
123 |
-
foreach ($terms_to_clear as $_term) {
|
124 |
-
$_term_regex = $self->buildHostCachePathRegex($_term['permalink']);
|
125 |
-
$_term_counter = $self->clearFilesFromHostCacheDir($_term_regex);
|
126 |
-
$counter += $_term_counter; // Add to overall counter.
|
127 |
-
|
128 |
-
if ($_term_counter && $enqueued_notices < 100 && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
129 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
130 |
-
sprintf(__('<strong>%1$s:</strong> detected changes. Found %2$s in the cache for %3$s: <code>%4$s</code>; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($_term_counter)), esc_html($_term['taxonomy_label']), esc_html($_term['term_name'])));
|
131 |
-
++$enqueued_notices; // Increment enqueued notices counter.
|
132 |
-
}
|
133 |
-
}
|
134 |
-
unset($_term, $_term_regex, $_term_counter); // Housekeeping.
|
135 |
-
|
136 |
-
$counter += $self->autoClearXmlFeedsCache('post-terms', $post_id);
|
137 |
-
|
138 |
-
return $counter;
|
139 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpUpdaterUtils.php
DELETED
@@ -1,99 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears all cache files for current blog when WordPress core, or an active component, is upgraded.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @attaches-to `upgrader_process_complete` hook.
|
10 |
-
*
|
11 |
-
* @param \WP_Upgrader $upgrader_instance An instance of \WP_Upgrader.
|
12 |
-
* Or, any class that extends \WP_Upgrader.
|
13 |
-
* @param array $data Array of bulk item update data.
|
14 |
-
*
|
15 |
-
* This array may include one or more of the following keys:
|
16 |
-
*
|
17 |
-
* - `string` `$action` Type of action. Default 'update'.
|
18 |
-
* - `string` `$type` Type of update process; e.g. 'plugin', 'theme', 'core'.
|
19 |
-
* - `boolean` `$bulk` Whether the update process is a bulk update. Default true.
|
20 |
-
* - `array` `$packages` Array of plugin, theme, or core packages to update.
|
21 |
-
*/
|
22 |
-
$self->autoClearOnUpgraderProcessComplete = function (\WP_Upgrader $upgrader_instance, array $data) use ($self) {
|
23 |
-
$counter = 0; // Initialize.
|
24 |
-
|
25 |
-
switch (!empty($data['type']) ? $data['type'] : '') {
|
26 |
-
case 'plugin': // Plugin upgrade.
|
27 |
-
|
28 |
-
$multi_plugin_update = $single_plugin_update = false;
|
29 |
-
$upgrading_active_plugin = false; // Initialize.
|
30 |
-
|
31 |
-
if (!empty($data['bulk']) && !empty($data['plugins']) && is_array($data['plugins'])) {
|
32 |
-
$multi_plugin_update = true;
|
33 |
-
} elseif (!empty($data['plugin']) && is_string($data['plugin'])) {
|
34 |
-
$single_plugin_update = true;
|
35 |
-
}
|
36 |
-
if ($multi_plugin_update) {
|
37 |
-
foreach ($data['plugins'] as $_plugin) {
|
38 |
-
if ($_plugin && is_string($_plugin) && is_plugin_active($_plugin)) {
|
39 |
-
$upgrading_active_plugin = true;
|
40 |
-
break; // Got what we need here.
|
41 |
-
}
|
42 |
-
}
|
43 |
-
unset($_plugin); // Housekeeping.
|
44 |
-
} elseif ($single_plugin_update && is_plugin_active($data['plugin'])) {
|
45 |
-
$upgrading_active_plugin = true;
|
46 |
-
}
|
47 |
-
if ($upgrading_active_plugin) {
|
48 |
-
$counter += $self->autoClearCache();
|
49 |
-
}
|
50 |
-
break; // Break switch.
|
51 |
-
|
52 |
-
case 'theme': // Theme upgrade.
|
53 |
-
|
54 |
-
$current_active_theme = wp_get_theme();
|
55 |
-
$current_active_theme_parent = $current_active_theme->parent();
|
56 |
-
$multi_theme_update = $single_theme_update = false;
|
57 |
-
$upgrading_active_parent_theme = $upgrading_active_theme = false;
|
58 |
-
|
59 |
-
if (!empty($data['bulk']) && !empty($data['themes']) && is_array($data['themes'])) {
|
60 |
-
$multi_theme_update = true;
|
61 |
-
} elseif (!empty($data['theme']) && is_string($data['theme'])) {
|
62 |
-
$single_theme_update = true;
|
63 |
-
}
|
64 |
-
if ($multi_theme_update) {
|
65 |
-
foreach ($data['themes'] as $_theme) {
|
66 |
-
if (!$_theme || !is_string($_theme) || !($_theme_obj = wp_get_theme($_theme))) {
|
67 |
-
continue; // Unable to acquire theme object instance.
|
68 |
-
}
|
69 |
-
if ($current_active_theme_parent && $current_active_theme_parent->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
70 |
-
$upgrading_active_parent_theme = true;
|
71 |
-
break; // Got what we needed here.
|
72 |
-
} elseif ($current_active_theme->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
73 |
-
$upgrading_active_theme = true;
|
74 |
-
break; // Got what we needed here.
|
75 |
-
}
|
76 |
-
}
|
77 |
-
unset($_theme, $_theme_obj); // Housekeeping.
|
78 |
-
} elseif ($single_theme_update && ($_theme_obj = wp_get_theme($data['theme']))) {
|
79 |
-
if ($current_active_theme_parent && $current_active_theme_parent->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
80 |
-
$upgrading_active_parent_theme = true;
|
81 |
-
} elseif ($current_active_theme->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
82 |
-
$upgrading_active_theme = true;
|
83 |
-
}
|
84 |
-
}
|
85 |
-
unset($_theme_obj); // Housekeeping.
|
86 |
-
|
87 |
-
if ($upgrading_active_theme || $upgrading_active_parent_theme) {
|
88 |
-
$counter += $self->autoClearCache();
|
89 |
-
}
|
90 |
-
break; // Break switch.
|
91 |
-
|
92 |
-
case 'core': // Core upgrade.
|
93 |
-
default: // Or any other sort of upgrade.
|
94 |
-
|
95 |
-
$counter += $self->autoClearCache();
|
96 |
-
|
97 |
-
break; // Break switch.
|
98 |
-
}
|
99 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpUtils.php
DELETED
@@ -1,341 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Used for temporarily storing the permalink for posts transitioning from
|
6 |
-
* `publish` or `private` post status to `pending` or `draft` post status.
|
7 |
-
*
|
8 |
-
* @since 150422 Rewrite.
|
9 |
-
*
|
10 |
-
* @type array An associative array with the Post ID as the named key containing
|
11 |
-
* the post permalink before the post has been transitioned.
|
12 |
-
*/
|
13 |
-
$self->pre_post_update_post_permalink = array();
|
14 |
-
|
15 |
-
/*
|
16 |
-
* Wipes out all cache files.
|
17 |
-
*
|
18 |
-
* @since 150422 Rewrite.
|
19 |
-
*
|
20 |
-
* @param bool $manually TRUE if wiping is done manually.
|
21 |
-
*
|
22 |
-
* @throws \Exception If a wipe failure occurs.
|
23 |
-
*
|
24 |
-
* @return int Total files wiped by this routine.
|
25 |
-
*/
|
26 |
-
$self->wipeCache = function ($manually = false) use ($self) {
|
27 |
-
$counter = 0; // Initialize.
|
28 |
-
|
29 |
-
if (!$manually && $self->disableAutoWipeCacheRoutines()) {
|
30 |
-
return $counter; // Nothing to do.
|
31 |
-
}
|
32 |
-
@set_time_limit(1800); // @TODO Display a warning.
|
33 |
-
|
34 |
-
if (is_dir($cache_dir = $self->cacheDir())) {
|
35 |
-
$regex = $self->assembleCachePathRegex('', '.+');
|
36 |
-
$counter += $self->wipeFilesFromCacheDir($regex);
|
37 |
-
}
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
return $counter;
|
44 |
-
};
|
45 |
-
$self->wipe_cache = $self->wipeCache; // Back compat.
|
46 |
-
|
47 |
-
/*
|
48 |
-
* Clears cache files (current blog).
|
49 |
-
*
|
50 |
-
* @since 150422 Rewrite.
|
51 |
-
*
|
52 |
-
* @param bool $manually TRUE if clearing is done manually.
|
53 |
-
*
|
54 |
-
* @throws \Exception If a clearing failure occurs.
|
55 |
-
*
|
56 |
-
* @return int Total files cleared by this routine.
|
57 |
-
*/
|
58 |
-
$self->clearCache = function ($manually = false) use ($self) {
|
59 |
-
$counter = 0; // Initialize.
|
60 |
-
|
61 |
-
if (!$manually && $self->disableAutoClearCacheRoutines()) {
|
62 |
-
return $counter; // Nothing to do.
|
63 |
-
}
|
64 |
-
@set_time_limit(1800); // @TODO Display a warning.
|
65 |
-
|
66 |
-
if (is_dir($cache_dir = $self->cacheDir())) {
|
67 |
-
$regex = $self->buildHostCachePathRegex('', '.+');
|
68 |
-
$counter += $self->clearFilesFromHostCacheDir($regex);
|
69 |
-
}
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
return $counter;
|
76 |
-
};
|
77 |
-
$self->clear_cache = $self->clearCache; // Back compat.
|
78 |
-
|
79 |
-
/*
|
80 |
-
* Purges expired cache files (current blog).
|
81 |
-
*
|
82 |
-
* @since 150422 Rewrite.
|
83 |
-
*
|
84 |
-
* @param bool $manually TRUE if purging is done manually.
|
85 |
-
*
|
86 |
-
* @throws \Exception If a purge failure occurs.
|
87 |
-
*
|
88 |
-
* @return int Total files purged by this routine.
|
89 |
-
*/
|
90 |
-
$self->purgeCache = function ($manually = false) use ($self) {
|
91 |
-
$counter = 0; // Initialize.
|
92 |
-
|
93 |
-
if (!$manually && $self->disableAutoPurgeCacheRoutines()) {
|
94 |
-
return $counter; // Nothing to do.
|
95 |
-
}
|
96 |
-
@set_time_limit(1800); // @TODO Display a warning.
|
97 |
-
|
98 |
-
if (is_dir($cache_dir = $self->cacheDir())) {
|
99 |
-
$regex = $self->buildHostCachePathRegex('', '.+');
|
100 |
-
$counter += $self->purgeFilesFromHostCacheDir($regex);
|
101 |
-
}
|
102 |
-
|
103 |
-
return $counter;
|
104 |
-
};
|
105 |
-
$self->purge_cache = $self->purgeCache; // Back compat.
|
106 |
-
|
107 |
-
/*
|
108 |
-
* Wurges (purges) all expired cache files; like wipe, but expired files only.
|
109 |
-
*
|
110 |
-
* @since 151002 Look at entire cache directory.
|
111 |
-
*
|
112 |
-
* @param bool $manually TRUE if wurging is done manually.
|
113 |
-
*
|
114 |
-
* @throws \Exception If a wurge failure occurs.
|
115 |
-
*
|
116 |
-
* @return int Total files wurged by this routine.
|
117 |
-
*/
|
118 |
-
$self->wurgeCache = function ($manually = false) use ($self) {
|
119 |
-
$counter = 0; // Initialize.
|
120 |
-
|
121 |
-
if (!$manually && $self->disableAutoPurgeCacheRoutines()) {
|
122 |
-
return $counter; // Nothing to do.
|
123 |
-
}
|
124 |
-
@set_time_limit(1800); // @TODO Display a warning.
|
125 |
-
|
126 |
-
if (is_dir($cache_dir = $self->cacheDir())) {
|
127 |
-
$regex = $self->assembleCachePathRegex('', '.+');
|
128 |
-
$counter += $self->wurgeFilesFromCacheDir($regex);
|
129 |
-
}
|
130 |
-
|
131 |
-
return $counter;
|
132 |
-
};
|
133 |
-
|
134 |
-
/*
|
135 |
-
* Automatically wipes out all cache files.
|
136 |
-
*
|
137 |
-
* @attaches-to Nothing at this time.
|
138 |
-
*
|
139 |
-
* @since 150422 Rewrite.
|
140 |
-
*
|
141 |
-
* @return int Total files wiped by this routine (if any).
|
142 |
-
*
|
143 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently attached to any hooks.
|
144 |
-
* This is called upon whenever options are saved and/or restored though.
|
145 |
-
*/
|
146 |
-
$self->autoWipeCache = function () use ($self) {
|
147 |
-
$counter = 0; // Initialize.
|
148 |
-
|
149 |
-
if (!is_null($done = &$self->cacheKey('autoWipeCache'))) {
|
150 |
-
return $counter; // Already did this.
|
151 |
-
}
|
152 |
-
$done = true; // Flag as having been done.
|
153 |
-
|
154 |
-
if (!$self->options['enable']) {
|
155 |
-
return $counter; // Nothing to do.
|
156 |
-
}
|
157 |
-
if ($self->disableAutoWipeCacheRoutines()) {
|
158 |
-
return $counter; // Nothing to do.
|
159 |
-
}
|
160 |
-
$counter += $self->wipeCache();
|
161 |
-
|
162 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
163 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/wipe.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
164 |
-
sprintf(__('<strong>%1$s:</strong> detected significant changes. Found %2$s in the cache; auto-wiping.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter))));
|
165 |
-
}
|
166 |
-
return $counter;
|
167 |
-
};
|
168 |
-
|
169 |
-
/*
|
170 |
-
* Automatically clears all cache files (current host).
|
171 |
-
*
|
172 |
-
* @attaches-to `switch_theme` hook.
|
173 |
-
*
|
174 |
-
* @attaches-to `wp_create_nav_menu` hook.
|
175 |
-
* @attaches-to `wp_update_nav_menu` hook.
|
176 |
-
* @attaches-to `wp_delete_nav_menu` hook.
|
177 |
-
*
|
178 |
-
* @attaches-to `create_term` hook.
|
179 |
-
* @attaches-to `edit_terms` hook.
|
180 |
-
* @attaches-to `delete_term` hook.
|
181 |
-
*
|
182 |
-
* @attaches-to `add_link` hook.
|
183 |
-
* @attaches-to `edit_link` hook.
|
184 |
-
* @attaches-to `delete_link` hook.
|
185 |
-
*
|
186 |
-
* @since 150422 Rewrite.
|
187 |
-
*
|
188 |
-
* @return int Total files cleared by this routine (if any).
|
189 |
-
*
|
190 |
-
* @note This is also called upon during plugin activation.
|
191 |
-
*/
|
192 |
-
$self->autoClearCache = function () use ($self) {
|
193 |
-
$counter = 0; // Initialize.
|
194 |
-
|
195 |
-
if (!is_null($done = &$self->cacheKey('autoClearCache'))) {
|
196 |
-
return $counter; // Already did this.
|
197 |
-
}
|
198 |
-
$done = true; // Flag as having been done.
|
199 |
-
|
200 |
-
if (!$self->options['enable']) {
|
201 |
-
return $counter; // Nothing to do.
|
202 |
-
}
|
203 |
-
if ($self->disableAutoClearCacheRoutines()) {
|
204 |
-
return $counter; // Nothing to do.
|
205 |
-
}
|
206 |
-
$counter += $self->clearCache();
|
207 |
-
|
208 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
209 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
210 |
-
sprintf(__('<strong>%1$s:</strong> detected important site changes. Found %2$s in the cache for this site; auto-clearing.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter))));
|
211 |
-
}
|
212 |
-
return $counter;
|
213 |
-
};
|
214 |
-
|
215 |
-
/*
|
216 |
-
* Automatically purges all cache files (current host).
|
217 |
-
*
|
218 |
-
* @attaches-to Nothing at this time.
|
219 |
-
*
|
220 |
-
* @since 151002 While working on directory stats.
|
221 |
-
*
|
222 |
-
* @return int Total files purged by this routine.
|
223 |
-
*
|
224 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently attached to any hooks.
|
225 |
-
*/
|
226 |
-
$self->autoPurgeCache = function () use ($self) {
|
227 |
-
$counter = 0; // Initialize.
|
228 |
-
|
229 |
-
if (!is_null($done = &$self->cacheKey('autoPurgeCache'))) {
|
230 |
-
return $counter; // Already did this.
|
231 |
-
}
|
232 |
-
$done = true; // Flag as having been done.
|
233 |
-
|
234 |
-
if (!$self->options['enable']) {
|
235 |
-
return $counter; // Nothing to do.
|
236 |
-
}
|
237 |
-
if ($self->disableAutoPurgeCacheRoutines()) {
|
238 |
-
return $counter; // Nothing to do.
|
239 |
-
}
|
240 |
-
$counter += $self->purgeCache();
|
241 |
-
|
242 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
243 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
244 |
-
sprintf(__('<strong>%1$s:</strong> detected important site changes. Found %2$s in the cache for this site that were expired; auto-purging.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter))));
|
245 |
-
}
|
246 |
-
return $counter;
|
247 |
-
};
|
248 |
-
|
249 |
-
/*
|
250 |
-
* Automatically wurges all cache files.
|
251 |
-
*
|
252 |
-
* @attaches-to Nothing at this time.
|
253 |
-
*
|
254 |
-
* @since 151002 While working on directory stats.
|
255 |
-
*
|
256 |
-
* @return int Total files wurged by this routine.
|
257 |
-
*
|
258 |
-
* @note Unlike many of the other `auto_` methods, this one is NOT currently attached to any hooks.
|
259 |
-
*/
|
260 |
-
$self->autoWurgeCache = function () use ($self) {
|
261 |
-
$counter = 0; // Initialize.
|
262 |
-
|
263 |
-
if (!is_null($done = &$self->cacheKey('autoWurgeCache'))) {
|
264 |
-
return $counter; // Already did this.
|
265 |
-
}
|
266 |
-
$done = true; // Flag as having been done.
|
267 |
-
|
268 |
-
if (!$self->options['enable']) {
|
269 |
-
return $counter; // Nothing to do.
|
270 |
-
}
|
271 |
-
if ($self->disableAutoPurgeCacheRoutines()) {
|
272 |
-
return $counter; // Nothing to do.
|
273 |
-
}
|
274 |
-
$counter += $self->wurgeCache();
|
275 |
-
|
276 |
-
if ($counter && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
277 |
-
$self->enqueueNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
278 |
-
sprintf(__('<strong>%1$s:</strong> detected important site changes. Found %2$s in the cache that were expired; auto-purging.', 'comet-cache'), esc_html(NAME), esc_html($self->i18nFiles($counter))));
|
279 |
-
}
|
280 |
-
return $counter;
|
281 |
-
};
|
282 |
-
|
283 |
-
/*
|
284 |
-
* Allows a site owner to disable the automatic cache wiping routines.
|
285 |
-
*
|
286 |
-
* This is done by filtering `'.__GLOBAL_NS__.'_disable_auto_wipe_cache_routines` to return TRUE,
|
287 |
-
* in which case this method returns TRUE, otherwise it returns FALSE.
|
288 |
-
*
|
289 |
-
* @since 150422 Rewrite.
|
290 |
-
*
|
291 |
-
* @return bool `TRUE` if disabled; and this also creates a dashboard notice in some cases.
|
292 |
-
*/
|
293 |
-
$self->disableAutoWipeCacheRoutines = function () use ($self) {
|
294 |
-
$is_disabled = (boolean) $self->applyWpFilters(GLOBAL_NS.'_disable_auto_wipe_cache_routines', false);
|
295 |
-
|
296 |
-
if ($is_disabled && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
297 |
-
$self->enqueueMainNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
298 |
-
sprintf(__('<strong>%1$s:</strong> detected significant changes that would normally trigger cache wiping routines. However, cache wiping routines have been disabled by a site administrator. [<a href="http://cometcache.com/r/kb-clear-and-wipe-cache-routines/" target="_blank">?</a>]', 'comet-cache'), esc_html(NAME)));
|
299 |
-
}
|
300 |
-
return $is_disabled;
|
301 |
-
};
|
302 |
-
|
303 |
-
/*
|
304 |
-
* Allows a site owner to disable the automatic cache clearing routines.
|
305 |
-
*
|
306 |
-
* This is done by filtering `'.__GLOBAL_NS__.'_disable_auto_clear_cache_routines` to return TRUE,
|
307 |
-
* in which case this method returns TRUE, otherwise it returns FALSE.
|
308 |
-
*
|
309 |
-
* @since 150422 Rewrite.
|
310 |
-
*
|
311 |
-
* @return bool `TRUE` if disabled; and this also creates a dashboard notice in some cases.
|
312 |
-
*/
|
313 |
-
$self->disableAutoClearCacheRoutines = function () use ($self) {
|
314 |
-
$is_disabled = (boolean) $self->applyWpFilters(GLOBAL_NS.'_disable_auto_clear_cache_routines', false);
|
315 |
-
|
316 |
-
if ($is_disabled && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
317 |
-
$self->enqueueMainNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
318 |
-
sprintf(__('<strong>%1$s:</strong> detected important site changes that would normally trigger cache clearing routines. However, cache clearing routines have been disabled by a site administrator. [<a href="http://cometcache.com/r/kb-clear-and-wipe-cache-routines/" target="_blank">?</a>]', 'comet-cache'), esc_html(NAME)));
|
319 |
-
}
|
320 |
-
return $is_disabled;
|
321 |
-
};
|
322 |
-
|
323 |
-
/*
|
324 |
-
* Allows a site owner to disable the automatic cache purging routines.
|
325 |
-
*
|
326 |
-
* This is done by filtering `'.__GLOBAL_NS__.'_disable_auto_purge_cache_routines` to return TRUE,
|
327 |
-
* in which case this method returns TRUE, otherwise it returns FALSE.
|
328 |
-
*
|
329 |
-
* @since 151002 While working on directory stats.
|
330 |
-
*
|
331 |
-
* @return bool `TRUE` if disabled; and this also creates a dashboard notice in some cases.
|
332 |
-
*/
|
333 |
-
$self->disableAutoPurgeCacheRoutines = function () use ($self) {
|
334 |
-
$is_disabled = (boolean) $self->applyWpFilters(GLOBAL_NS.'_disable_auto_purge_cache_routines', false);
|
335 |
-
|
336 |
-
if ($is_disabled && is_admin() && (!IS_PRO || $self->options['change_notifications_enable'])) {
|
337 |
-
$self->enqueueMainNotice('<img src="'.esc_attr($self->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
338 |
-
sprintf(__('<strong>%1$s:</strong> detected important site changes that would normally trigger cache purging routines. However, cache purging routines have been disabled by a site administrator. [<a href="http://cometcache.com/r/kb-clear-and-wipe-cache-routines/" target="_blank">?</a>]', 'comet-cache'), esc_html(NAME)));
|
339 |
-
}
|
340 |
-
return $is_disabled;
|
341 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Plugin/WcpWooCommerceUtils.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Automatically clears cache file for a WooCommerce Product when its stock is changed.
|
6 |
-
*
|
7 |
-
* @since 151220 Improving WooCommerce Compatibility.
|
8 |
-
*
|
9 |
-
* @attaches-to `woocommerce_product_set_stock` hook.
|
10 |
-
*
|
11 |
-
* @param \WC_Product $product A WooCommerce WC_Product object
|
12 |
-
*/
|
13 |
-
$self->autoClearPostCacheOnWooCommerceSetStock = function ($product) use ($self) {
|
14 |
-
$counter = 0; // Initialize.
|
15 |
-
|
16 |
-
if (!is_null($done = &$self->cacheKey('autoClearPostCacheOnWooCommerceSetStock'))) {
|
17 |
-
return $counter; // Already did this.
|
18 |
-
}
|
19 |
-
$done = true; // Flag as having been done.
|
20 |
-
|
21 |
-
if(class_exists('\\WooCommerce')) {
|
22 |
-
$counter += $self->autoClearPostCache($product->id);
|
23 |
-
}
|
24 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/BlogUtils.php
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Get blog details.
|
6 |
-
*
|
7 |
-
* @since 150821 Improving multisite compat.
|
8 |
-
*
|
9 |
-
* @param integer $blog_id For which blog ID?
|
10 |
-
*
|
11 |
-
* @return \stdClass|null Blog details if possible.
|
12 |
-
*
|
13 |
-
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
14 |
-
*/
|
15 |
-
$self->blogDetails = function ($blog_id = 0) use ($self) {
|
16 |
-
if (!is_multisite() || $self->isAdvancedCache()) {
|
17 |
-
return null; // Not possible.
|
18 |
-
}
|
19 |
-
if (($blog_id = (integer) $blog_id) < 0) {
|
20 |
-
$blog_id = (integer) get_current_site()->blog_id;
|
21 |
-
}
|
22 |
-
if (!$blog_id) {
|
23 |
-
$blog_id = (integer) get_current_blog_id();
|
24 |
-
}
|
25 |
-
if (!$blog_id || $blog_id < 0) {
|
26 |
-
return null; // Not possible.
|
27 |
-
}
|
28 |
-
$details = get_blog_details($blog_id);
|
29 |
-
|
30 |
-
return is_object($details) ? $details : null;
|
31 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/CacheDirUtils.php
DELETED
@@ -1,643 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Cache directory path.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param string $rel_path Relative path inside cache directory.
|
10 |
-
*
|
11 |
-
* @throws \Exception If unable to get cache directory.
|
12 |
-
*
|
13 |
-
* @return string Absolute path to cache directory.
|
14 |
-
*/
|
15 |
-
$self->cacheDir = function ($rel_path = '') use ($self) {
|
16 |
-
$rel_path = (string) $rel_path;
|
17 |
-
|
18 |
-
if ($self->isAdvancedCache()) {
|
19 |
-
$cache_dir = defined('COMET_CACHE_DIR') ? COMET_CACHE_DIR : '';
|
20 |
-
} elseif (!empty($self->cache_sub_dir)) {
|
21 |
-
$cache_dir = $self->wpContentBaseDirTo($self->cache_sub_dir);
|
22 |
-
}
|
23 |
-
if (empty($cache_dir)) {
|
24 |
-
throw new \Exception(__('Unable to determine cache directory location.', 'comet-cache'));
|
25 |
-
}
|
26 |
-
return rtrim($cache_dir, '/').($rel_path ? '/'.ltrim($rel_path) : '');
|
27 |
-
};
|
28 |
-
|
29 |
-
/*
|
30 |
-
* Wipe files from the cache directory (for all hosts/blogs);
|
31 |
-
* i.e., those that match a specific regex pattern.
|
32 |
-
*
|
33 |
-
* @since 151002 While working on directory stats.
|
34 |
-
*
|
35 |
-
* @param string $regex A regex pattern; see {@link deleteFilesFromCacheDir()}.
|
36 |
-
*
|
37 |
-
* @return integer Total files wiped by this routine.
|
38 |
-
*/
|
39 |
-
$self->wipeFilesFromCacheDir = function ($regex) use ($self) {
|
40 |
-
return $self->deleteFilesFromCacheDir($regex);
|
41 |
-
};
|
42 |
-
|
43 |
-
/*
|
44 |
-
* Clear files from the cache directory (for the current host);
|
45 |
-
* i.e., those that match a specific regex pattern.
|
46 |
-
*
|
47 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
48 |
-
*
|
49 |
-
* @param string $regex A regex pattern; see {@link deleteFilesFromHostCacheDir()}.
|
50 |
-
*
|
51 |
-
* @return integer Total files cleared by this routine (if any).
|
52 |
-
*/
|
53 |
-
$self->clearFilesFromHostCacheDir = function ($regex) use ($self) {
|
54 |
-
return $self->deleteFilesFromHostCacheDir($regex);
|
55 |
-
};
|
56 |
-
|
57 |
-
/*
|
58 |
-
* Wurge (purge) files from the cache directory (for all hosts/blogs);
|
59 |
-
* i.e., those that match a specific regex pattern.
|
60 |
-
*
|
61 |
-
* @since 151002 While working on directory stats.
|
62 |
-
*
|
63 |
-
* @param string $regex A regex pattern; see {@link deleteFilesFromCacheDir()}.
|
64 |
-
*
|
65 |
-
* @return integer Total files wurged by this routine.
|
66 |
-
*/
|
67 |
-
$self->wurgeFilesFromCacheDir = function ($regex) use ($self) {
|
68 |
-
return $self->deleteFilesFromCacheDir($regex, true);
|
69 |
-
};
|
70 |
-
|
71 |
-
/*
|
72 |
-
* Purge files from the cache directory (for the current host);
|
73 |
-
* i.e., those that match a specific regex pattern.
|
74 |
-
*
|
75 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
76 |
-
*
|
77 |
-
* @param string $regex A regex pattern; see {@link deleteFilesFromHostCacheDir()}.
|
78 |
-
*
|
79 |
-
* @return integer Total files purged by this routine (if any).
|
80 |
-
*/
|
81 |
-
$self->purgeFilesFromHostCacheDir = function ($regex) use ($self) {
|
82 |
-
return $self->deleteFilesFromHostCacheDir($regex, true);
|
83 |
-
};
|
84 |
-
|
85 |
-
/*
|
86 |
-
* Delete files from the cache directory (for all hosts/blogs);
|
87 |
-
* i.e., those that match a specific regex pattern.
|
88 |
-
*
|
89 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
90 |
-
*
|
91 |
-
* @param string $regex A `/[regex pattern]/`; relative to the cache directory.
|
92 |
-
* e.g. `/^http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
93 |
-
*
|
94 |
-
* Or, this can also be a full/absolute regex pattern against an absolute path;
|
95 |
-
* provided that it always starts with `/^`; including the full absolute cache/host directory path.
|
96 |
-
* e.g. `/^\/cache\/dir\/http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
97 |
-
*
|
98 |
-
* @param boolean $check_max_age Check max age? i.e., use purge behavior?
|
99 |
-
*
|
100 |
-
* @return integer Total files deleted by this routine (if any).
|
101 |
-
*
|
102 |
-
* @throws \Exception If unable to delete a file for any reason.
|
103 |
-
*
|
104 |
-
* @TODO Optimize this for multisite networks w/ a LOT of child blogs.
|
105 |
-
* @TODO Optimize this for extremely large sites. A LOT of files here could slow things down.
|
106 |
-
* This class member is currently used in wiping and purging for a network. So there is the potential for a LOT of files in a single scan.
|
107 |
-
* See also: <https://codex.wordpress.org/Function_Reference/wp_is_large_network>
|
108 |
-
*/
|
109 |
-
$self->deleteFilesFromCacheDir = function ($regex, $check_max_age = false) use ($self) {
|
110 |
-
$counter = 0; // Initialize.
|
111 |
-
|
112 |
-
if (!($regex = (string) $regex)) {
|
113 |
-
return $counter; // Nothing to do.
|
114 |
-
}
|
115 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
116 |
-
return $counter; // Nothing to do.
|
117 |
-
}
|
118 |
-
$cache_dir = $self->nDirSeps($cache_dir);
|
119 |
-
|
120 |
-
if ($check_max_age && $self->isAdvancedCache()) {
|
121 |
-
throw new \Exception(__('Invalid argument; isAdvancedCache!', 'comet-cache'));
|
122 |
-
}
|
123 |
-
if ($check_max_age && !($max_age = strtotime('-'.$self->options['cache_max_age']))) {
|
124 |
-
return $counter; // Invalid cache expiration time.
|
125 |
-
}
|
126 |
-
/* ------- Begin lock state... ----------- */
|
127 |
-
|
128 |
-
$cache_lock = $self->cacheLock(); // Lock cache writes.
|
129 |
-
|
130 |
-
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
131 |
-
|
132 |
-
$cache_dir_tmp = $self->addTmpSuffix($cache_dir); // Temporary directory.
|
133 |
-
|
134 |
-
$cache_dir_tmp_regex = $regex; // Initialize host-specific regex pattern for the tmp directory.
|
135 |
-
$cache_dir_tmp_regex = '\\/'.ltrim($cache_dir_tmp_regex, '^\\/'); // Make sure it begins with an escaped `/`.
|
136 |
-
$cache_dir_tmp_regex = $self->strIreplaceOnce(preg_quote($cache_dir.'/', '/'), '', $cache_dir_tmp_regex);
|
137 |
-
|
138 |
-
$cache_dir_tmp_regex = ltrim($cache_dir_tmp_regex, '^\\/');
|
139 |
-
if (strpos($cache_dir_tmp_regex, '(?:\/') === 0 || strpos($cache_dir_tmp_regex, '(\/') === 0) {
|
140 |
-
$cache_dir_tmp_regex = '/^'.preg_quote($cache_dir_tmp, '/').$cache_dir_tmp_regex;
|
141 |
-
} else {
|
142 |
-
$cache_dir_tmp_regex = '/^'.preg_quote($cache_dir_tmp.'/', '/').$cache_dir_tmp_regex;
|
143 |
-
}
|
144 |
-
# if(WP_DEBUG) file_put_contents(WP_CONTENT_DIR.'/'.strtolower(SHORT_NAME).'-debug.log', print_r($regex, TRUE)."\n".print_r($cache_dir_tmp_regex, TRUE)."\n\n", FILE_APPEND);
|
145 |
-
// Uncomment the above line to debug regex pattern matching used by this routine; and others that call upon it.
|
146 |
-
|
147 |
-
if (!rename($cache_dir, $cache_dir_tmp)) {
|
148 |
-
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on directory: `%1$s`.', 'comet-cache'), $cache_dir));
|
149 |
-
}
|
150 |
-
foreach (($_dir_regex_iteration = $self->dirRegexIteration($cache_dir_tmp, $cache_dir_tmp_regex)) as $_resource) {
|
151 |
-
$_resource_type = $_resource->getType();
|
152 |
-
$_sub_path_name = $_resource->getSubpathname();
|
153 |
-
$_path_name = $_resource->getPathname();
|
154 |
-
|
155 |
-
if ($_resource_type !== 'dir' && strpos($_sub_path_name, '/') === false) {
|
156 |
-
continue; // Don't delete links/files in the immediate directory; e.g. `[SHORT_NAME]-advanced-cache` or `.htaccess`, etc.
|
157 |
-
// Actual `http|https/...` cache links/files are nested. Links/files in the immediate directory are for other purposes.
|
158 |
-
}
|
159 |
-
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
160 |
-
|
161 |
-
case 'link': // Symbolic links; i.e., 404 errors.
|
162 |
-
|
163 |
-
if ($check_max_age && !empty($max_age) && is_file($_resource->getLinkTarget())) {
|
164 |
-
if (($_lstat = lstat($_path_name)) && !empty($_lstat['mtime'])) {
|
165 |
-
if ($_lstat['mtime'] >= $max_age) {
|
166 |
-
break; // Break switch.
|
167 |
-
}
|
168 |
-
}
|
169 |
-
}
|
170 |
-
if (!unlink($_path_name)) {
|
171 |
-
$self->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
172 |
-
throw new \Exception(sprintf(__('Unable to delete symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
173 |
-
}
|
174 |
-
++$counter; // Increment counter for each link we delete.
|
175 |
-
|
176 |
-
break; // Break switch handler.
|
177 |
-
|
178 |
-
case 'file': // Regular files; i.e., not symlinks.
|
179 |
-
|
180 |
-
if ($check_max_age && !empty($max_age)) {
|
181 |
-
if ($_resource->getMTime() >= $max_age) {
|
182 |
-
break; // Break switch.
|
183 |
-
}
|
184 |
-
}
|
185 |
-
if (!unlink($_path_name)) {
|
186 |
-
$self->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
187 |
-
throw new \Exception(sprintf(__('Unable to delete file: `%1$s`.', 'comet-cache'), $_path_name));
|
188 |
-
}
|
189 |
-
++$counter; // Increment counter for each file we delete.
|
190 |
-
|
191 |
-
break; // Break switch handler.
|
192 |
-
|
193 |
-
case 'dir': // A regular directory; i.e., not a symlink.
|
194 |
-
|
195 |
-
if ($regex !== '/^.+/i') {
|
196 |
-
break; // Not deleting everything.
|
197 |
-
}
|
198 |
-
if ($check_max_age && !empty($max_age)) {
|
199 |
-
break; // Not deleting everything.
|
200 |
-
}
|
201 |
-
if (!rmdir($_path_name)) {
|
202 |
-
$self->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
203 |
-
throw new \Exception(sprintf(__('Unable to delete dir: `%1$s`.', 'comet-cache'), $_path_name));
|
204 |
-
}
|
205 |
-
# $counter++; // Increment counter for each directory we delete. ~ NO don't do that here.
|
206 |
-
|
207 |
-
break; // Break switch handler.
|
208 |
-
|
209 |
-
default: // Something else that is totally unexpected here.
|
210 |
-
$self->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
211 |
-
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
212 |
-
}
|
213 |
-
}
|
214 |
-
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name, $_lstat); // Housekeeping.
|
215 |
-
|
216 |
-
if (!rename($cache_dir_tmp, $cache_dir)) {
|
217 |
-
$self->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
218 |
-
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $cache_dir_tmp));
|
219 |
-
}
|
220 |
-
/* ------- End lock state... ------------- */
|
221 |
-
|
222 |
-
$self->cacheUnlock($cache_lock); // Release.
|
223 |
-
|
224 |
-
return $counter;
|
225 |
-
};
|
226 |
-
|
227 |
-
/*
|
228 |
-
* Delete files from the cache directory (for the current host);
|
229 |
-
* i.e., those that match a specific regex pattern.
|
230 |
-
*
|
231 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
232 |
-
*
|
233 |
-
* @param string $regex A `/[regex pattern]/`; relative to the host cache directory.
|
234 |
-
* e.g. `/^my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
235 |
-
*
|
236 |
-
* Or, this can also be a full/absolute regex pattern against an absolute path;
|
237 |
-
* provided that it always starts with `/^`; including the full absolute cache/host directory path.
|
238 |
-
* e.g. `/^\/cache\/dir\/http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
239 |
-
*
|
240 |
-
* @param boolean $check_max_age Check max age? i.e., use purge behavior?
|
241 |
-
*
|
242 |
-
* @param boolean $___considering_domain_mapping For internal use only.
|
243 |
-
* @param boolean $___consider_domain_mapping_host_token For internal use only.
|
244 |
-
* @param boolean $___consider_domain_mapping_host_base_dir_tokens For internal use only.
|
245 |
-
*
|
246 |
-
* @return integer Total files deleted by this routine (if any).
|
247 |
-
*
|
248 |
-
* @throws \Exception If unable to delete a file for any reason.
|
249 |
-
*/
|
250 |
-
$self->deleteFilesFromHostCacheDir = function (
|
251 |
-
$regex,
|
252 |
-
$check_max_age = false,
|
253 |
-
$___considering_domain_mapping = false,
|
254 |
-
$___consider_domain_mapping_host_token = null,
|
255 |
-
$___consider_domain_mapping_host_base_dir_tokens = null
|
256 |
-
) use ($self) {
|
257 |
-
$counter = 0; // Initialize.
|
258 |
-
|
259 |
-
if (!($regex = (string) $regex)) {
|
260 |
-
return $counter; // Nothing to do.
|
261 |
-
}
|
262 |
-
if (!is_dir($cache_dir = $self->cacheDir())) {
|
263 |
-
return $counter; // Nothing to do.
|
264 |
-
}
|
265 |
-
$cache_dir = $self->nDirSeps($cache_dir); // Normalize.
|
266 |
-
$host_token = $current_host_token = $self->hostToken();
|
267 |
-
$host_base_dir_tokens = $current_host_base_dir_tokens = $self->hostBaseDirTokens();
|
268 |
-
|
269 |
-
if ($___considering_domain_mapping && isset($___consider_domain_mapping_host_token, $___consider_domain_mapping_host_base_dir_tokens)) {
|
270 |
-
$host_token = (string) $___consider_domain_mapping_host_token;
|
271 |
-
$host_base_dir_tokens = (string) $___consider_domain_mapping_host_base_dir_tokens;
|
272 |
-
}
|
273 |
-
if (!$host_token) { // Must have a host in the sub-routine below.
|
274 |
-
throw new \Exception(__('Invalid argument; host token empty!', 'comet-cache'));
|
275 |
-
}
|
276 |
-
if ($check_max_age && $self->isAdvancedCache()) {
|
277 |
-
throw new \Exception(__('Invalid argument; isAdvancedCache!', 'comet-cache'));
|
278 |
-
}
|
279 |
-
if ($check_max_age && !($max_age = strtotime('-'.$self->options['cache_max_age']))) {
|
280 |
-
return $counter; // Invalid cache expiration time.
|
281 |
-
}
|
282 |
-
/* ------- Begin lock state... ----------- */
|
283 |
-
|
284 |
-
$cache_lock = $self->cacheLock(); // Lock cache writes.
|
285 |
-
|
286 |
-
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
287 |
-
|
288 |
-
foreach (array('http', 'https') as $_host_scheme) {
|
289 |
-
$_host_url = $_host_scheme.'://'.$host_token.$host_base_dir_tokens;
|
290 |
-
$_host_cache_path_flags = CACHE_PATH_NO_PATH_INDEX | CACHE_PATH_NO_QUV | CACHE_PATH_NO_EXT;
|
291 |
-
$_host_cache_path = $self->buildCachePath($_host_url, '', '', $_host_cache_path_flags);
|
292 |
-
$_host_cache_dir = $self->nDirSeps($cache_dir.'/'.$_host_cache_path); // Normalize.
|
293 |
-
|
294 |
-
if (!$_host_cache_dir || !is_dir($_host_cache_dir)) {
|
295 |
-
// On a multisite install this may have a cache sub-directory.
|
296 |
-
// e.g., `http/example-com[[-base]-child1][[/base]/child1]` instead of `http/example-com`.
|
297 |
-
continue; // Nothing to do.
|
298 |
-
}
|
299 |
-
$_host_cache_dir_tmp = $self->addTmpSuffix($_host_cache_dir); // Temporary directory.
|
300 |
-
|
301 |
-
$_host_cache_dir_tmp_regex = $regex; // Initialize host-specific regex pattern for the tmp directory.
|
302 |
-
$_host_cache_dir_tmp_regex = '\\/'.ltrim($_host_cache_dir_tmp_regex, '^\\/'); // Make sure it begins with an escaped `/`.
|
303 |
-
$_host_cache_dir_tmp_regex = $self->strIreplaceOnce(preg_quote($_host_cache_path.'/', '/'), '', $_host_cache_dir_tmp_regex);
|
304 |
-
$_host_cache_dir_tmp_regex = $self->strIreplaceOnce(preg_quote($_host_cache_dir.'/', '/'), '', $_host_cache_dir_tmp_regex);
|
305 |
-
|
306 |
-
$_host_cache_dir_tmp_regex = ltrim($_host_cache_dir_tmp_regex, '^\\/');
|
307 |
-
if (strpos($_host_cache_dir_tmp_regex, '(?:\/') === 0 || strpos($_host_cache_dir_tmp_regex, '(\/') === 0) {
|
308 |
-
$_host_cache_dir_tmp_regex = '/^'.preg_quote($_host_cache_dir_tmp, '/').$_host_cache_dir_tmp_regex;
|
309 |
-
} else {
|
310 |
-
$_host_cache_dir_tmp_regex = '/^'.preg_quote($_host_cache_dir_tmp.'/', '/').$_host_cache_dir_tmp_regex;
|
311 |
-
}
|
312 |
-
#if(WP_DEBUG) file_put_contents(WP_CONTENT_DIR.'/'.strtolower(SHORT_NAME).'-debug.log', print_r($regex, TRUE)."\n".print_r($_host_cache_dir_tmp_regex, TRUE)."\n\n", FILE_APPEND);
|
313 |
-
// Uncomment the above line to debug regex pattern matching used by this routine; and others that call upon it.
|
314 |
-
|
315 |
-
if (!rename($_host_cache_dir, $_host_cache_dir_tmp)) {
|
316 |
-
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $_host_cache_dir));
|
317 |
-
}
|
318 |
-
foreach (($_dir_regex_iteration = $self->dirRegexIteration($_host_cache_dir_tmp, $_host_cache_dir_tmp_regex)) as $_resource) {
|
319 |
-
$_resource_type = $_resource->getType();
|
320 |
-
$_sub_path_name = $_resource->getSubpathname();
|
321 |
-
$_path_name = $_resource->getPathname();
|
322 |
-
|
323 |
-
if ($_host_cache_dir === $cache_dir && $_resource_type !== 'dir' && strpos($_sub_path_name, '/') === false) {
|
324 |
-
continue; // Don't delete links/files in the immediate directory; e.g. `[SHORT_NAME]-advanced-cache` or `.htaccess`, etc.
|
325 |
-
// Actual `http|https/...` cache links/files are nested. Links/files in the immediate directory are for other purposes.
|
326 |
-
}
|
327 |
-
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
328 |
-
|
329 |
-
case 'link': // Symbolic links; i.e., 404 errors.
|
330 |
-
|
331 |
-
if ($check_max_age && !empty($max_age) && is_file($_resource->getLinkTarget())) {
|
332 |
-
if (($_lstat = lstat($_path_name)) && !empty($_lstat['mtime'])) {
|
333 |
-
if ($_lstat['mtime'] >= $max_age) {
|
334 |
-
break; // Break switch.
|
335 |
-
}
|
336 |
-
}
|
337 |
-
}
|
338 |
-
if (!unlink($_path_name)) {
|
339 |
-
$self->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
340 |
-
throw new \Exception(sprintf(__('Unable to delete symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
341 |
-
}
|
342 |
-
++$counter; // Increment counter for each link we delete.
|
343 |
-
|
344 |
-
break; // Break switch handler.
|
345 |
-
|
346 |
-
case 'file': // Regular files; i.e., not symlinks.
|
347 |
-
|
348 |
-
if ($check_max_age && !empty($max_age)) {
|
349 |
-
if ($_resource->getMTime() >= $max_age) {
|
350 |
-
break; // Break switch handler.
|
351 |
-
}
|
352 |
-
}
|
353 |
-
if (!unlink($_path_name)) {
|
354 |
-
$self->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
355 |
-
throw new \Exception(sprintf(__('Unable to delete file: `%1$s`.', 'comet-cache'), $_path_name));
|
356 |
-
}
|
357 |
-
++$counter; // Increment counter for each file we delete.
|
358 |
-
|
359 |
-
break; // Break switch handler.
|
360 |
-
|
361 |
-
case 'dir': // A regular directory; i.e., not a symlink.
|
362 |
-
|
363 |
-
if ($regex !== '/^.+/i') {
|
364 |
-
break; // Not deleting everything.
|
365 |
-
}
|
366 |
-
if ($check_max_age && !empty($max_age)) {
|
367 |
-
break; // Not deleting everything.
|
368 |
-
}
|
369 |
-
if (!rmdir($_path_name)) {
|
370 |
-
$self->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
371 |
-
throw new \Exception(sprintf(__('Unable to delete dir: `%1$s`.', 'comet-cache'), $_path_name));
|
372 |
-
}
|
373 |
-
# $counter++; // Increment counter for each directory we delete. ~ NO don't do that here.
|
374 |
-
|
375 |
-
break; // Break switch handler.
|
376 |
-
|
377 |
-
default: // Something else that is totally unexpected here.
|
378 |
-
$self->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
379 |
-
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
380 |
-
}
|
381 |
-
}
|
382 |
-
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name, $_lstat); // Housekeeping.
|
383 |
-
|
384 |
-
if (!rename($_host_cache_dir_tmp, $_host_cache_dir)) {
|
385 |
-
$self->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
386 |
-
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $_host_cache_dir_tmp));
|
387 |
-
}
|
388 |
-
}
|
389 |
-
unset($_host_scheme, $_host_url, $_host_cache_path_flags, $_host_cache_path, $_host_cache_dir, $_host_cache_dir_tmp, $_host_cache_dir_tmp_regex);
|
390 |
-
|
391 |
-
/* ------- End lock state... ------------- */
|
392 |
-
|
393 |
-
$self->cacheUnlock($cache_lock); // Release.
|
394 |
-
|
395 |
-
/* ------- Include domain mapping variations also. ------- */
|
396 |
-
|
397 |
-
if (!$___considering_domain_mapping && is_multisite() && $self->canConsiderDomainMapping()) {
|
398 |
-
$domain_mapping_variations = array(); // Initialize array of domain variations.
|
399 |
-
|
400 |
-
if (($_host_token_for_blog = $self->hostTokenForBlog())) {
|
401 |
-
$_host_base_dir_tokens_for_blog = $self->hostBaseDirTokensForBlog();
|
402 |
-
$domain_mapping_variations[] = array('host_token' => $_host_token_for_blog, 'host_base_dir_tokens' => $_host_base_dir_tokens_for_blog);
|
403 |
-
} // The original blog host; i.e., without domain mapping.
|
404 |
-
unset($_host_token_for_blog, $_host_base_dir_tokens_for_blog); // Housekeeping.
|
405 |
-
|
406 |
-
foreach ($self->domainMappingBlogDomains() as $_domain_mapping_blog_domain) {
|
407 |
-
if (($_domain_host_token_for_blog = $self->hostTokenForBlog(false, true, $_domain_mapping_blog_domain))) {
|
408 |
-
$_domain_host_base_dir_tokens_for_blog = $self->hostBaseDirTokensForBlog(false, true); // This is only a formality.
|
409 |
-
$domain_mapping_variations[] = array('host_token' => $_domain_host_token_for_blog, 'host_base_dir_tokens' => $_domain_host_base_dir_tokens_for_blog);
|
410 |
-
}
|
411 |
-
} // This includes all of the domain mappings configured for the current blog ID.
|
412 |
-
unset($_domain_mapping_blog_domain, $_domain_host_token_for_blog, $_domain_host_base_dir_tokens_for_blog); // Housekeeping.
|
413 |
-
|
414 |
-
foreach ($domain_mapping_variations as $_domain_mapping_variation) {
|
415 |
-
if ($_domain_mapping_variation['host_token'] === $current_host_token && $_domain_mapping_variation['host_base_dir_tokens'] === $current_host_base_dir_tokens) {
|
416 |
-
continue; // Exclude current tokens. They were already iterated above.
|
417 |
-
}
|
418 |
-
$counter += $self->deleteFilesFromHostCacheDir($regex, $check_max_age, true, $_domain_mapping_variation['host_token'], $_domain_mapping_variation['host_base_dir_tokens']);
|
419 |
-
}
|
420 |
-
unset($_domain_mapping_variation); // Housekeeping.
|
421 |
-
}
|
422 |
-
return $counter;
|
423 |
-
};
|
424 |
-
|
425 |
-
/*
|
426 |
-
* Delete all files/dirs from a directory (for all schemes/hosts);
|
427 |
-
* including `[SHORT_NAME]-` prefixed files; or anything else for that matter.
|
428 |
-
*
|
429 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
430 |
-
*
|
431 |
-
* @param string $dir The directory from which to delete files/dirs.
|
432 |
-
*
|
433 |
-
* SECURITY: This directory MUST be located inside the `/wp-content/` directory.
|
434 |
-
* Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself.
|
435 |
-
* Also, it cannot be: `mu-plugins`, `themes`, or `plugins`.
|
436 |
-
*
|
437 |
-
* @param boolean $delete_dir_too Delete parent? i.e., delete the `$dir` itself also?
|
438 |
-
*
|
439 |
-
* @return integer Total files/directories deleted by this routine (if any).
|
440 |
-
*
|
441 |
-
* @throws \Exception If unable to delete a file/directory for any reason.
|
442 |
-
*/
|
443 |
-
$self->deleteAllFilesDirsIn = function ($dir, $delete_dir_too = false) use ($self) {
|
444 |
-
$counter = 0; // Initialize.
|
445 |
-
|
446 |
-
if (!($dir = trim((string) $dir)) || !is_dir($dir)) {
|
447 |
-
return $counter; // Nothing to do.
|
448 |
-
}
|
449 |
-
$dir = $self->nDirSeps($dir);
|
450 |
-
$dir_temp = $self->addTmpSuffix($dir);
|
451 |
-
$wp_content_dir = $self->nDirSeps(WP_CONTENT_DIR);
|
452 |
-
$wp_content_dir_regex = preg_quote($wp_content_dir, '/');
|
453 |
-
|
454 |
-
if (!preg_match('/^'.$wp_content_dir_regex.'\/[^\/]+/i', $dir)) {
|
455 |
-
return $counter; // Security flag; do nothing in this case.
|
456 |
-
}
|
457 |
-
if (preg_match('/^'.$wp_content_dir_regex.'\/(?:mu\-plugins|themes|plugins)(?:\/|$)/i', $dir)) {
|
458 |
-
return $counter; // Security flag; do nothing in this case.
|
459 |
-
}
|
460 |
-
/* ------- Begin lock state... ----------- */
|
461 |
-
|
462 |
-
$cache_lock = $self->cacheLock(); // Lock cache writes.
|
463 |
-
|
464 |
-
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
465 |
-
|
466 |
-
if (!rename($dir, $dir_temp)) {
|
467 |
-
throw new \Exception(sprintf(__('Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $dir));
|
468 |
-
}
|
469 |
-
foreach (($_dir_regex_iteration = $self->dirRegexIteration($dir_temp, '/.+/')) as $_resource) {
|
470 |
-
$_resource_type = $_resource->getType();
|
471 |
-
$_sub_path_name = $_resource->getSubpathname();
|
472 |
-
$_path_name = $_resource->getPathname();
|
473 |
-
|
474 |
-
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
475 |
-
|
476 |
-
case 'link': // Symbolic links; i.e., 404 errors.
|
477 |
-
|
478 |
-
if (!unlink($_path_name)) {
|
479 |
-
$self->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
480 |
-
throw new \Exception(sprintf(__('Unable to delete symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
481 |
-
}
|
482 |
-
++$counter; // Increment counter for each link we delete.
|
483 |
-
|
484 |
-
break; // Break switch handler.
|
485 |
-
|
486 |
-
case 'file': // Regular files; i.e., not symlinks.
|
487 |
-
|
488 |
-
if (!unlink($_path_name)) {
|
489 |
-
$self->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
490 |
-
throw new \Exception(sprintf(__('Unable to delete file: `%1$s`.', 'comet-cache'), $_path_name));
|
491 |
-
}
|
492 |
-
++$counter; // Increment counter for each file we delete.
|
493 |
-
|
494 |
-
break; // Break switch handler.
|
495 |
-
|
496 |
-
case 'dir': // A regular directory; i.e., not a symlink.
|
497 |
-
|
498 |
-
if (!rmdir($_path_name)) {
|
499 |
-
$self->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
500 |
-
throw new \Exception(sprintf(__('Unable to delete dir: `%1$s`.', 'comet-cache'), $_path_name));
|
501 |
-
}
|
502 |
-
# ++$counter; // Increment counter for each directory we delete. ~ NO don't do that here.
|
503 |
-
|
504 |
-
break; // Break switch handler.
|
505 |
-
|
506 |
-
default: // Something else that is totally unexpected here.
|
507 |
-
$self->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
508 |
-
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
509 |
-
}
|
510 |
-
}
|
511 |
-
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name); // Housekeeping.
|
512 |
-
|
513 |
-
if (!rename($dir_temp, $dir)) {
|
514 |
-
$self->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
515 |
-
throw new \Exception(sprintf(__('Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $dir_temp));
|
516 |
-
}
|
517 |
-
if ($delete_dir_too) {
|
518 |
-
if (!rmdir($dir)) {
|
519 |
-
throw new \Exception(sprintf(__('Unable to delete directory: `%1$s`.', 'comet-cache'), $dir));
|
520 |
-
}
|
521 |
-
++$counter; // Increment counter for each directory we delete.
|
522 |
-
}
|
523 |
-
/* ------- End lock state... ------------- */
|
524 |
-
|
525 |
-
$self->cacheUnlock($cache_lock); // Release.
|
526 |
-
|
527 |
-
return $counter;
|
528 |
-
};
|
529 |
-
|
530 |
-
/*
|
531 |
-
* Erase all files/dirs from a directory (for all schemes/hosts);
|
532 |
-
* including `[SHORT_NAME]-` prefixed files; or anything else for that matter.
|
533 |
-
*
|
534 |
-
* WARNING: This does NO LOCKING and NO ATOMIC deletions.
|
535 |
-
*
|
536 |
-
* @since 150821 Improving recovery under stress.
|
537 |
-
*
|
538 |
-
* @param string $dir The directory from which to erase files/dirs.
|
539 |
-
*
|
540 |
-
* SECURITY: This directory MUST be located inside the `/wp-content/` directory.
|
541 |
-
* Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself.
|
542 |
-
* Also, it cannot be: `mu-plugins`, `themes`, or `plugins`.
|
543 |
-
*
|
544 |
-
* @param boolean $erase_dir_too Erase parent? i.e., erase the `$dir` itself also?
|
545 |
-
*
|
546 |
-
* @return integer Total files/directories erased by this routine (if any).
|
547 |
-
*
|
548 |
-
* @throws \Exception If unable to erase a file/directory for any reason.
|
549 |
-
*/
|
550 |
-
$self->eraseAllFilesDirsIn = function ($dir, $erase_dir_too = false) use ($self) {
|
551 |
-
$counter = 0; // Initialize.
|
552 |
-
|
553 |
-
if (!($dir = trim((string) $dir)) || !is_dir($dir)) {
|
554 |
-
return $counter; // Nothing to do.
|
555 |
-
}
|
556 |
-
$dir = $self->nDirSeps($dir);
|
557 |
-
$wp_content_dir = $self->nDirSeps(WP_CONTENT_DIR);
|
558 |
-
$wp_content_dir_regex = preg_quote($wp_content_dir, '/');
|
559 |
-
|
560 |
-
if (!preg_match('/^'.$wp_content_dir_regex.'\/[^\/]+/i', $dir)) {
|
561 |
-
return $counter; // Security flag; do nothing in this case.
|
562 |
-
}
|
563 |
-
if (preg_match('/^'.$wp_content_dir_regex.'\/(?:mu\-plugins|themes|plugins)(?:\/|$)/i', $dir)) {
|
564 |
-
return $counter; // Security flag; do nothing in this case.
|
565 |
-
}
|
566 |
-
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
567 |
-
|
568 |
-
foreach (($_dir_regex_iteration = $self->dirRegexIteration($dir, '/.+/')) as $_resource) {
|
569 |
-
$_resource_type = $_resource->getType();
|
570 |
-
$_sub_path_name = $_resource->getSubpathname();
|
571 |
-
$_path_name = $_resource->getPathname();
|
572 |
-
|
573 |
-
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
574 |
-
|
575 |
-
case 'link': // Symbolic links; i.e., 404 errors.
|
576 |
-
|
577 |
-
if (!unlink($_path_name)) {
|
578 |
-
throw new \Exception(sprintf(__('Unable to erase symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
579 |
-
}
|
580 |
-
++$counter; // Increment counter for each link we erase.
|
581 |
-
|
582 |
-
break; // Break switch handler.
|
583 |
-
|
584 |
-
case 'file': // Regular files; i.e., not symlinks.
|
585 |
-
|
586 |
-
if (!unlink($_path_name)) {
|
587 |
-
throw new \Exception(sprintf(__('Unable to erase file: `%1$s`.', 'comet-cache'), $_path_name));
|
588 |
-
}
|
589 |
-
++$counter; // Increment counter for each file we erase.
|
590 |
-
|
591 |
-
break; // Break switch handler.
|
592 |
-
|
593 |
-
case 'dir': // A regular directory; i.e., not a symlink.
|
594 |
-
|
595 |
-
if (!rmdir($_path_name)) {
|
596 |
-
throw new \Exception(sprintf(__('Unable to erase dir: `%1$s`.', 'comet-cache'), $_path_name));
|
597 |
-
}
|
598 |
-
# ++$counter; // Increment counter for each directory we erase. ~ NO don't do that here.
|
599 |
-
|
600 |
-
break; // Break switch handler.
|
601 |
-
|
602 |
-
default: // Something else that is totally unexpected here.
|
603 |
-
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
604 |
-
}
|
605 |
-
}
|
606 |
-
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name); // Housekeeping.
|
607 |
-
|
608 |
-
if ($erase_dir_too) {
|
609 |
-
if (!rmdir($dir)) {
|
610 |
-
throw new \Exception(sprintf(__('Unable to erase directory: `%1$s`.', 'comet-cache'), $dir));
|
611 |
-
}
|
612 |
-
++$counter; // Increment counter for each directory we erase.
|
613 |
-
}
|
614 |
-
return $counter;
|
615 |
-
};
|
616 |
-
|
617 |
-
/*
|
618 |
-
* Try to erase all files/dirs from a directory (for all schemes/hosts);
|
619 |
-
* including `[SHORT_NAME]-` prefixed files; or anything else for that matter.
|
620 |
-
*
|
621 |
-
* WARNING: This does NO LOCKING and NO ATOMIC deletions.
|
622 |
-
*
|
623 |
-
* @since 150821 Improving recovery under stress.
|
624 |
-
*
|
625 |
-
* @param string $dir The directory from which to erase files/dirs.
|
626 |
-
*
|
627 |
-
* SECURITY: This directory MUST be located inside the `/wp-content/` directory.
|
628 |
-
* Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself.
|
629 |
-
* Also, it cannot be: `mu-plugins`, `themes`, or `plugins`.
|
630 |
-
*
|
631 |
-
* @param boolean $erase_dir_too Erase parent? i.e., erase the `$dir` itself also?
|
632 |
-
*
|
633 |
-
* @return integer Total files/directories erased by this routine (if any).
|
634 |
-
*/
|
635 |
-
$self->tryErasingAllFilesDirsIn = function ($dir, $erase_dir_too = false) use ($self) {
|
636 |
-
$counter = 0; // Initialize counter.
|
637 |
-
try {
|
638 |
-
$counter += $self->eraseAllFilesDirsIn($dir, $erase_dir_too);
|
639 |
-
} catch (\Exception $exception) {
|
640 |
-
// Fail softly.
|
641 |
-
}
|
642 |
-
return $counter;
|
643 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/CacheLockUtils.php
DELETED
@@ -1,80 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Get an exclusive lock on the cache directory.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @return array Lock type & resource handle needed to unlock later or FALSE if disabled by filter.
|
10 |
-
*
|
11 |
-
* @throws \Exception If {@link \sem_get()} not available and there's
|
12 |
-
* no writable tmp directory for {@link \flock()} either.
|
13 |
-
*
|
14 |
-
* @throws \Exception If unable to obtain an exclusive lock by any available means.
|
15 |
-
*
|
16 |
-
* @note This call is blocking; i.e. it will not return a lock until a lock becomes possible.
|
17 |
-
* In short, this will block the caller until such time as write access becomes possible.
|
18 |
-
*/
|
19 |
-
$self->cacheLock = function () use ($self) {
|
20 |
-
if ($self->applyWpFilters(GLOBAL_NS.'\\share::disable_cache_locking', false)
|
21 |
-
|| $self->applyWpFilters(GLOBAL_NS.'_disable_cache_locking', false)) {
|
22 |
-
return false; // Disabled cache locking.
|
23 |
-
}
|
24 |
-
if (!($wp_config_file = $self->findWpConfigFile())) {
|
25 |
-
throw new \Exception(__('Unable to find the wp-config.php file.', 'comet-cache'));
|
26 |
-
}
|
27 |
-
$lock_type = 'flock'; // Default lock type.
|
28 |
-
$lock_type = $self->applyWpFilters(GLOBAL_NS.'\\share::cache_lock_lock_type', $lock_type);
|
29 |
-
$lock_type = $self->applyWpFilters(GLOBAL_NS.'_cache_lock_type', $lock_type);
|
30 |
-
|
31 |
-
if (!in_array($lock_type, array('flock', 'sem'), true)) {
|
32 |
-
$lock_type = 'flock'; // Default lock type.
|
33 |
-
}
|
34 |
-
if ($lock_type === 'sem' && $self->functionIsPossible('sem_get')) {
|
35 |
-
if (($ipc_key = ftok($wp_config_file, 'w'))) {
|
36 |
-
if (($resource = sem_get($ipc_key, 1)) && sem_acquire($resource)) {
|
37 |
-
return array('type' => 'sem', 'resource' => $resource);
|
38 |
-
}
|
39 |
-
}
|
40 |
-
}
|
41 |
-
if (!($tmp_dir = $self->getTmpDir())) {
|
42 |
-
throw new \Exception(__('No writable tmp directory.', 'comet-cache'));
|
43 |
-
}
|
44 |
-
$inode_key = fileinode($wp_config_file);
|
45 |
-
$mutex = $tmp_dir.'/'.SLUG_TD.'-'.$inode_key.'.lock';
|
46 |
-
|
47 |
-
if (!($resource = fopen($mutex, 'wb')) || !flock($resource, LOCK_EX)) {
|
48 |
-
throw new \Exception(__('Unable to obtain an exclusive lock.', 'comet-cache'));
|
49 |
-
}
|
50 |
-
|
51 |
-
@chmod($mutex, 0666); // See https://git.io/v2WAt
|
52 |
-
|
53 |
-
return array('type' => 'flock', 'resource' => $resource);
|
54 |
-
};
|
55 |
-
|
56 |
-
/*
|
57 |
-
* Release an exclusive lock on the cache directory.
|
58 |
-
*
|
59 |
-
* @since 150422 Rewrite. Updated 151002 to remove the `array` typecast.
|
60 |
-
*
|
61 |
-
* @param array|mixed $lock Type & resource.
|
62 |
-
*/
|
63 |
-
$self->cacheUnlock = function ($lock) use ($self) {
|
64 |
-
if (!is_array($lock)) {
|
65 |
-
return; // Not possible.
|
66 |
-
// Or, they disabled cache locking.
|
67 |
-
}
|
68 |
-
if (empty($lock['type']) || empty($lock['resource'])) {
|
69 |
-
return; // Not possible.
|
70 |
-
}
|
71 |
-
if (!is_resource($lock['resource'])) {
|
72 |
-
return; // Not possible.
|
73 |
-
}
|
74 |
-
if ($lock['type'] === 'sem') {
|
75 |
-
sem_release($lock['resource']);
|
76 |
-
} elseif ($lock['type'] === 'flock') {
|
77 |
-
flock($lock['resource'], LOCK_UN);
|
78 |
-
fclose($lock['resource']);
|
79 |
-
}
|
80 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/CachePathConsts.php
DELETED
@@ -1,140 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
if (defined(__NAMESPACE__.'\\CACHE_PATH_DEFAULT')) {
|
5 |
-
return; // Already defined these.
|
6 |
-
}
|
7 |
-
/**
|
8 |
-
* Default cache path flags.
|
9 |
-
*
|
10 |
-
* @since 150422 Rewrite.
|
11 |
-
*
|
12 |
-
* @type int A bitmask.
|
13 |
-
*/
|
14 |
-
const CACHE_PATH_DEFAULT = 0;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Use a domain-mapped cache path.
|
18 |
-
*
|
19 |
-
* @since 150821 Improving multisite compat.
|
20 |
-
*
|
21 |
-
* @type int Part of a bitmask.
|
22 |
-
*/
|
23 |
-
const CACHE_PATH_CONSIDER_DOMAIN_MAPPING = 1;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Generate an unmapped cache path?
|
27 |
-
*
|
28 |
-
* @since 150821 Improving multisite compat.
|
29 |
-
*
|
30 |
-
* @type int Part of a bitmask.
|
31 |
-
*/
|
32 |
-
const CACHE_PATH_REVERSE_DOMAIN_MAPPING = 2;
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Exclude scheme from cache path.
|
36 |
-
*
|
37 |
-
* @since 150422 Rewrite.
|
38 |
-
*
|
39 |
-
* @type int Part of a bitmask.
|
40 |
-
*/
|
41 |
-
const CACHE_PATH_NO_SCHEME = 4;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Exclude host (i.e. domain name) from cache path.
|
45 |
-
*
|
46 |
-
* @since 150422 Rewrite.
|
47 |
-
*
|
48 |
-
* @type int Part of a bitmask.
|
49 |
-
*/
|
50 |
-
const CACHE_PATH_NO_HOST = 8;
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Exclude path from cache path.
|
54 |
-
*
|
55 |
-
* @since 150422 Rewrite.
|
56 |
-
*
|
57 |
-
* @type int Part of a bitmask.
|
58 |
-
*/
|
59 |
-
const CACHE_PATH_NO_PATH = 16;
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Exclude path index (i.e. no default `index`) from cache path.
|
63 |
-
*
|
64 |
-
* @since 150422 Rewrite.
|
65 |
-
*
|
66 |
-
* @type int Part of a bitmask.
|
67 |
-
*/
|
68 |
-
const CACHE_PATH_NO_PATH_INDEX = 32;
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Exclude query, user & version salt from cache path.
|
72 |
-
*
|
73 |
-
* @since 150422 Rewrite.
|
74 |
-
*
|
75 |
-
* @type int Part of a bitmask.
|
76 |
-
*/
|
77 |
-
const CACHE_PATH_NO_QUV = 64;
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Exclude query string from cache path.
|
81 |
-
*
|
82 |
-
* @since 150422 Rewrite.
|
83 |
-
*
|
84 |
-
* @type int Part of a bitmask.
|
85 |
-
*/
|
86 |
-
const CACHE_PATH_NO_QUERY = 128;
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Exclude user token from cache path.
|
90 |
-
*
|
91 |
-
* @since 150422 Rewrite.
|
92 |
-
*
|
93 |
-
* @type int Part of a bitmask.
|
94 |
-
*/
|
95 |
-
const CACHE_PATH_NO_USER = 256;
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Exclude version salt from cache path.
|
99 |
-
*
|
100 |
-
* @since 150422 Rewrite.
|
101 |
-
*
|
102 |
-
* @type int Part of a bitmask.
|
103 |
-
*/
|
104 |
-
const CACHE_PATH_NO_VSALT = 512;
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Exclude extension from cache path.
|
108 |
-
*
|
109 |
-
* @since 150422 Rewrite.
|
110 |
-
*
|
111 |
-
* @type int Part of a bitmask.
|
112 |
-
*/
|
113 |
-
const CACHE_PATH_NO_EXT = 1024;
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Allow wildcards in the cache path.
|
117 |
-
*
|
118 |
-
* @since 150422 Rewrite.
|
119 |
-
*
|
120 |
-
* @type int Part of a bitmask.
|
121 |
-
*/
|
122 |
-
const CACHE_PATH_ALLOW_WILDCARDS = 2048;
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Allow watered-down regex in the cache path.
|
126 |
-
*
|
127 |
-
* @since 151114 Improving regex syntax.
|
128 |
-
*
|
129 |
-
* @type int Part of a bitmask.
|
130 |
-
*/
|
131 |
-
const CACHE_PATH_ALLOW_WD_REGEX = 4096;
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Default cache path regex suffix frag.
|
135 |
-
*
|
136 |
-
* @since 150422 Rewrite.
|
137 |
-
*
|
138 |
-
* @type string Default regex suffix frag used in cache path patterns.
|
139 |
-
*/
|
140 |
-
const CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/CachePathUtils.php
DELETED
@@ -1,351 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Cache-path suffix frag (regex).
|
6 |
-
*
|
7 |
-
* @since 151220 Enhancing translation support.
|
8 |
-
*
|
9 |
-
* @param string $regex_suffix_frag Existing regex suffix frag?
|
10 |
-
*
|
11 |
-
* @return string Cache-path suffix frag (regex).
|
12 |
-
*/
|
13 |
-
$self->cachePathRegexSuffixFrag = function ($regex_suffix_frag = CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) use ($self) {
|
14 |
-
if ($regex_suffix_frag === CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) {
|
15 |
-
return $self->cachePathRegexDefaultSuffixFrag();
|
16 |
-
}
|
17 |
-
return (string) $regex_suffix_frag;
|
18 |
-
};
|
19 |
-
|
20 |
-
/*
|
21 |
-
* Default cache-path suffix frag (regex).
|
22 |
-
*
|
23 |
-
* @since 151220 Enhancing translation support.
|
24 |
-
*
|
25 |
-
* @return string Default cache-path suffix frag (regex).
|
26 |
-
*
|
27 |
-
* @TODO Use conditional to detect the AMP plugin (e.g., `isAmpInstalled()`) to avoid edge cases with the `|\/amp` regex here
|
28 |
-
*/
|
29 |
-
$self->cachePathRegexDefaultSuffixFrag = function () use ($self) {
|
30 |
-
if ($self->isPlugin() && !empty($GLOBALS['wp_rewrite'])){
|
31 |
-
$pagination_base = $GLOBALS['wp_rewrite']->pagination_base;
|
32 |
-
$comments_pagination_base = $GLOBALS['wp_rewrite']->comments_pagination_base;
|
33 |
-
return '(?:\/index|\/amp)?(?:\.|\/(?:'.preg_quote($pagination_base, '/').'\/[0-9]+|'.preg_quote($comments_pagination_base, '/').'\-[0-9]+)[.\/])';
|
34 |
-
} else {
|
35 |
-
return '(?:\/index|\/amp)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])';
|
36 |
-
}
|
37 |
-
};
|
38 |
-
|
39 |
-
/*
|
40 |
-
* Converts a URL into a `cache/path` based on input `$flags`.
|
41 |
-
*
|
42 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
43 |
-
*
|
44 |
-
* @param string $url The input URL to convert.
|
45 |
-
* @param string $with_user_token Optional user token (if applicable).
|
46 |
-
* @param string $with_version_salt Optional version salt (if applicable).
|
47 |
-
* @param int $flags Optional flags. A bitmask via `CACHE_PATH_*` constants.
|
48 |
-
*
|
49 |
-
* @return string The resulting `cache/path` based on the input `$url` & `$flags`.
|
50 |
-
*/
|
51 |
-
$self->buildCachePath = function ($url, $with_user_token = '', $with_version_salt = '', $flags = CACHE_PATH_DEFAULT) use ($self) {
|
52 |
-
# Force parameter types.
|
53 |
-
|
54 |
-
$url = trim((string) $url);
|
55 |
-
$with_user_token = trim((string) $with_user_token);
|
56 |
-
$with_version_salt = trim((string) $with_version_salt);
|
57 |
-
|
58 |
-
# Initialize variables.
|
59 |
-
|
60 |
-
$is_multisite = is_multisite();
|
61 |
-
$can_consider_domain_mapping = $is_multisite && $self->canConsiderDomainMapping();
|
62 |
-
$cache_path = ''; // Initialize cache path being built here.
|
63 |
-
|
64 |
-
# Deal w/ domain mapping considerations.
|
65 |
-
|
66 |
-
if ($flags & CACHE_PATH_CONSIDER_DOMAIN_MAPPING && $is_multisite && $can_consider_domain_mapping) {
|
67 |
-
if ($flags & CACHE_PATH_REVERSE_DOMAIN_MAPPING) {
|
68 |
-
$url = $self->domainMappingReverseUrlFilter($url);
|
69 |
-
} else {
|
70 |
-
$url = $self->domainMappingUrlFilter($url);
|
71 |
-
}
|
72 |
-
}
|
73 |
-
# Validate the URL we have now.
|
74 |
-
|
75 |
-
if (!$url || !($url_parts = $self->parseUrl($url))) {
|
76 |
-
return ($cache_path = ''); // Not possible.
|
77 |
-
}
|
78 |
-
if (empty($url_parts['scheme']) || $url_parts['scheme'] === '//') {
|
79 |
-
return ($cache_path = ''); // Not possible.
|
80 |
-
}
|
81 |
-
if (empty($url_parts['host'])) {
|
82 |
-
return ($cache_path = ''); // Not possible.
|
83 |
-
}
|
84 |
-
# Initialize additional variables; based on the parsed URL.
|
85 |
-
|
86 |
-
$is_url_domain_mapped = $is_multisite && $can_consider_domain_mapping && $self->domainMappingBlogId($url);
|
87 |
-
$host_base_dir_tokens = $self->hostBaseDirTokens(false, $is_url_domain_mapped, !empty($url_parts['path']) ? $url_parts['path'] : '/');
|
88 |
-
|
89 |
-
$is_a_multisite_base_dir = $is_multisite && $host_base_dir_tokens && $host_base_dir_tokens !== '/' // Check?
|
90 |
-
&& stripos(!empty($url_parts['path']) ? rtrim($url_parts['path'], '/').'/' : '/', $host_base_dir_tokens) === 0;
|
91 |
-
|
92 |
-
$is_a_multisite_base_dir_root = $is_multisite && $is_a_multisite_base_dir // Save time by using the previous check here.
|
93 |
-
&& strcasecmp(trim($host_base_dir_tokens, '/'), trim(!empty($url_parts['path']) ? $url_parts['path'] : '/', '/')) === 0;
|
94 |
-
|
95 |
-
# Build and return the cache path.
|
96 |
-
|
97 |
-
if (!($flags & CACHE_PATH_NO_SCHEME)) {
|
98 |
-
$cache_path .= $url_parts['scheme'].'/';
|
99 |
-
}
|
100 |
-
if (!($flags & CACHE_PATH_NO_HOST)) {
|
101 |
-
$cache_path .= $url_parts['host'].'/';
|
102 |
-
|
103 |
-
// Put multisite sub-roots into a host directory of their own.
|
104 |
-
// e.g., `example-com[[-base]-child1]` instead of `example-com`.
|
105 |
-
if ($is_a_multisite_base_dir && $host_base_dir_tokens && $host_base_dir_tokens !== '/') {
|
106 |
-
$host_base_dir_suffix = preg_replace('/[^a-z0-9.]/i', '-', rtrim($host_base_dir_tokens, '/'));
|
107 |
-
$cache_path = rtrim($cache_path, '/').$host_base_dir_suffix.'/';
|
108 |
-
}
|
109 |
-
}
|
110 |
-
if (!($flags & CACHE_PATH_NO_PATH)) {
|
111 |
-
if (isset($url_parts['path'][201])) {
|
112 |
-
$_path_tmp = '/'; // Initialize tmp path.
|
113 |
-
foreach (explode('/', $url_parts['path']) as $_path_component) {
|
114 |
-
if (!isset($_path_component[0])) {
|
115 |
-
continue; // Empty.
|
116 |
-
}
|
117 |
-
if (isset($_path_component[201])) {
|
118 |
-
$_path_component = 'lpc-'.sha1($_path_component);
|
119 |
-
}
|
120 |
-
$_path_tmp .= $_path_component.'/';
|
121 |
-
}
|
122 |
-
$url_parts['path'] = $_path_tmp; // Shorter components.
|
123 |
-
unset($_path_component, $_path_tmp); // Housekeeping.
|
124 |
-
|
125 |
-
if (isset($url_parts['path'][2001])) {
|
126 |
-
$url_parts['path'] = '/lp-'.sha1($url_parts['path']).'/';
|
127 |
-
}
|
128 |
-
} // Now add the path and check for a possible root `index/` suffix.
|
129 |
-
if (!empty($url_parts['path']) && strlen($url_parts['path'] = trim($url_parts['path'], '\\/'." \t\n\r\0\x0B"))) {
|
130 |
-
$cache_path .= $url_parts['path'].'/'; // Add the path as it exists.
|
131 |
-
|
132 |
-
if (!($flags & CACHE_PATH_NO_PATH_INDEX) && $is_multisite && $is_a_multisite_base_dir_root) {
|
133 |
-
// We should build an `index/` when this ends with a multisite [[/base]/child1] root.
|
134 |
-
// e.g., `http/example-com[[-base]-child1][[/base]/child1]` is a root directory.
|
135 |
-
$cache_path .= 'index/'; // Use an index suffix.
|
136 |
-
}
|
137 |
-
} elseif (!($flags & CACHE_PATH_NO_PATH_INDEX)) {
|
138 |
-
$cache_path .= 'index/';
|
139 |
-
}
|
140 |
-
}
|
141 |
-
if ($self->isExtensionLoaded('mbstring') && mb_check_encoding($cache_path, 'UTF-8')) {
|
142 |
-
$cache_path = mb_strtolower($cache_path, 'UTF-8');
|
143 |
-
}
|
144 |
-
$cache_path = str_replace('.', '-', strtolower($cache_path));
|
145 |
-
|
146 |
-
if (!($flags & CACHE_PATH_NO_QUV)) {
|
147 |
-
if (!($flags & CACHE_PATH_NO_QUERY)) {
|
148 |
-
if (isset($url_parts['query']) && $url_parts['query'] !== '') {
|
149 |
-
$cache_path = rtrim($cache_path, '/').'.q/'.md5($url_parts['query']).'/';
|
150 |
-
}
|
151 |
-
}
|
152 |
-
if (!($flags & CACHE_PATH_NO_USER)) {
|
153 |
-
if ($with_user_token !== '') {
|
154 |
-
$cache_path = rtrim($cache_path, '/').'.u/'.str_replace(array('/', '\\'), '-', $with_user_token).'/';
|
155 |
-
}
|
156 |
-
}
|
157 |
-
if (!($flags & CACHE_PATH_NO_VSALT)) {
|
158 |
-
if ($with_version_salt !== '') {
|
159 |
-
$cache_path = rtrim($cache_path, '/').'.v/'.str_replace(array('/', '\\'), '-', $with_version_salt).'/';
|
160 |
-
}
|
161 |
-
}
|
162 |
-
}
|
163 |
-
$cache_path = trim(preg_replace(array('/\/+/', '/\.+/'), array('/', '.'), $cache_path), '/');
|
164 |
-
|
165 |
-
if ($flags & CACHE_PATH_ALLOW_WD_REGEX) {
|
166 |
-
$cache_path = preg_replace('/[^a-z0-9\/.*\^$]/i', '-', $cache_path);
|
167 |
-
} elseif ($flags & CACHE_PATH_ALLOW_WILDCARDS) {
|
168 |
-
$cache_path = preg_replace('/[^a-z0-9\/.*]/i', '-', $cache_path);
|
169 |
-
} else {
|
170 |
-
$cache_path = preg_replace('/[^a-z0-9\/.]/i', '-', $cache_path);
|
171 |
-
}
|
172 |
-
if (!($flags & CACHE_PATH_NO_EXT)) {
|
173 |
-
$cache_path .= '.html';
|
174 |
-
}
|
175 |
-
return $cache_path;
|
176 |
-
};
|
177 |
-
|
178 |
-
/*
|
179 |
-
* Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
180 |
-
*
|
181 |
-
* @since 151114 Updated to support an arbitrary URL instead of a regex frag.
|
182 |
-
*
|
183 |
-
* @param string $url The input URL to convert. This CAN be left empty when necessary.
|
184 |
-
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
185 |
-
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
186 |
-
*
|
187 |
-
* @param string $regex_suffix_frag Regex fragment to come after the `$regex_frag`.
|
188 |
-
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
189 |
-
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
190 |
-
* See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
191 |
-
*
|
192 |
-
* @return string Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
193 |
-
*/
|
194 |
-
$self->buildCachePathRegex = function ($url, $regex_suffix_frag = CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) use ($self) {
|
195 |
-
$url = trim((string) $url);
|
196 |
-
$regex_suffix_frag = $self->cachePathRegexSuffixFrag($regex_suffix_frag);
|
197 |
-
$cache_path_regex = ''; // Initialize regex.
|
198 |
-
|
199 |
-
if ($url) {
|
200 |
-
$flags = CACHE_PATH_NO_SCHEME // Scheme added below.
|
201 |
-
| CACHE_PATH_NO_PATH_INDEX | CACHE_PATH_NO_QUV | CACHE_PATH_NO_EXT;
|
202 |
-
$cache_path = $self->buildCachePath($url, '', '', $flags); // Without the scheme.
|
203 |
-
$cache_path_regex = isset($cache_path[0]) ? '\/https?\/'.preg_quote($cache_path, '/') : '';
|
204 |
-
}
|
205 |
-
return '/^'.$cache_path_regex.$regex_suffix_frag.'/i';
|
206 |
-
};
|
207 |
-
|
208 |
-
/*
|
209 |
-
* Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
210 |
-
*
|
211 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
212 |
-
*
|
213 |
-
* @param string $url The input URL to convert. This CAN be left empty when necessary.
|
214 |
-
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
215 |
-
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
216 |
-
*
|
217 |
-
* @param string $regex_suffix_frag Regex fragment to come after the relative cache/path regex frag.
|
218 |
-
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
219 |
-
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
220 |
-
* See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
221 |
-
*
|
222 |
-
* @return string Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
223 |
-
*/
|
224 |
-
$self->buildHostCachePathRegex = function ($url, $regex_suffix_frag = CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) use ($self) {
|
225 |
-
$url = trim((string) $url);
|
226 |
-
$regex_suffix_frag = $self->cachePathRegexSuffixFrag($regex_suffix_frag);
|
227 |
-
$abs_relative_cache_path_regex = ''; // Initialize regex.
|
228 |
-
$is_url_domain_mapped = false; // Initialize.
|
229 |
-
|
230 |
-
if ($url) {
|
231 |
-
if (is_multisite() && $self->canConsiderDomainMapping()) {
|
232 |
-
// Shortest possible URI; i.e., consider domain mapping.
|
233 |
-
$url = $self->domainMappingUrlFilter($url);
|
234 |
-
$is_url_domain_mapped = $url && $self->domainMappingBlogId($url);
|
235 |
-
}
|
236 |
-
if ($url && ($url_parts = $self->parseUrl($url)) && !empty($url_parts['host'])) {
|
237 |
-
$flags = CACHE_PATH_NO_SCHEME | CACHE_PATH_NO_HOST
|
238 |
-
| CACHE_PATH_NO_PATH_INDEX | CACHE_PATH_NO_QUV | CACHE_PATH_NO_EXT;
|
239 |
-
|
240 |
-
$host_base_dir_tokens = $self->hostBaseDirTokens(false, $is_url_domain_mapped, !empty($url_parts['path']) ? $url_parts['path'] : '/');
|
241 |
-
$host_url = rtrim('http://'.$url_parts['host'].$host_base_dir_tokens, '/');
|
242 |
-
$host_cache_path = $self->buildCachePath($host_url, '', '', $flags);
|
243 |
-
|
244 |
-
$cache_path = $self->buildCachePath($url, '', '', $flags);
|
245 |
-
$relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $cache_path);
|
246 |
-
|
247 |
-
$abs_relative_cache_path = isset($relative_cache_path[0]) ? '/'.$relative_cache_path : '';
|
248 |
-
$abs_relative_cache_path_regex = isset($abs_relative_cache_path[0]) ? preg_quote($abs_relative_cache_path, '/') : '';
|
249 |
-
}
|
250 |
-
}
|
251 |
-
return '/^'.$abs_relative_cache_path_regex.$regex_suffix_frag.'/i';
|
252 |
-
};
|
253 |
-
|
254 |
-
/*
|
255 |
-
* Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
256 |
-
*
|
257 |
-
* @since 151114 Improving watered-down regex syntax.
|
258 |
-
*
|
259 |
-
* @param string $url The input URL to convert. This CAN be left empty when necessary.
|
260 |
-
* This may also contain watered-down regex; i.e., `*^$` characters are OK here.
|
261 |
-
* However, `^$` are discarded, as they are unnecessary in this context.
|
262 |
-
*
|
263 |
-
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
264 |
-
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
265 |
-
*
|
266 |
-
* @param string $regex_suffix_frag Regex fragment to come after the `$regex_frag`.
|
267 |
-
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
268 |
-
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
269 |
-
* See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
270 |
-
*
|
271 |
-
* @return string Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
272 |
-
*/
|
273 |
-
$self->buildCachePathRegexFromWcUrl = function ($url, $regex_suffix_frag = CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) use ($self) {
|
274 |
-
$url = trim((string) $url, '^$');
|
275 |
-
$regex_suffix_frag = $self->cachePathRegexSuffixFrag($regex_suffix_frag);
|
276 |
-
$cache_path_regex = ''; // Initialize regex.
|
277 |
-
|
278 |
-
if ($url) { // After `^$` trimming above.
|
279 |
-
$flags = CACHE_PATH_ALLOW_WILDCARDS | CACHE_PATH_NO_SCHEME
|
280 |
-
| CACHE_PATH_NO_PATH_INDEX | CACHE_PATH_NO_QUV | CACHE_PATH_NO_EXT;
|
281 |
-
$cache_path = $self->buildCachePath($url, '', '', $flags); // Without the scheme.
|
282 |
-
$cache_path_regex = isset($cache_path[0]) ? '\/https?\/'.$self->wdRegexToActualRegexFrag($cache_path) : '';
|
283 |
-
}
|
284 |
-
return '/^'.$cache_path_regex.$regex_suffix_frag.'/i';
|
285 |
-
};
|
286 |
-
|
287 |
-
/*
|
288 |
-
* Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
289 |
-
*
|
290 |
-
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
291 |
-
*
|
292 |
-
* @param string $uris A line-delimited list of URIs. These may contain `*^$` also.
|
293 |
-
* However, `^$` are discarded, as they are unnecessary in this context.
|
294 |
-
*
|
295 |
-
* @param string $regex_suffix_frag Regex fragment to come after each relative cache/path.
|
296 |
-
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
297 |
-
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
298 |
-
* See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
299 |
-
*
|
300 |
-
* @return string Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
301 |
-
*/
|
302 |
-
$self->buildHostCachePathRegexFragsFromWcUris = function ($uris, $regex_suffix_frag = CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) use ($self) {
|
303 |
-
$uris = trim((string) $uris);
|
304 |
-
$regex_suffix_frag = $self->cachePathRegexSuffixFrag($regex_suffix_frag);
|
305 |
-
|
306 |
-
$_self = $self; // Reference for the closure below.
|
307 |
-
$flags = CACHE_PATH_ALLOW_WILDCARDS | CACHE_PATH_NO_SCHEME | CACHE_PATH_NO_HOST
|
308 |
-
| CACHE_PATH_NO_PATH_INDEX | CACHE_PATH_NO_QUV | CACHE_PATH_NO_EXT;
|
309 |
-
|
310 |
-
$host = 'doesnt-matter.foo.bar';
|
311 |
-
$host_url = rtrim('http://'.$host, '/');
|
312 |
-
$host_cache_path = $self->buildCachePath($host_url, '', '', $flags);
|
313 |
-
$uri_patterns = array_unique(preg_split('/['."\r\n".']+/', $uris, -1, PREG_SPLIT_NO_EMPTY));
|
314 |
-
|
315 |
-
foreach ($uri_patterns as $_key => &$_uri_pattern) {
|
316 |
-
if (($_uri_pattern = trim($_uri_pattern, '^$'))) {
|
317 |
-
$_cache_path = $_self->buildCachePath($host_url.'/'.trim($_uri_pattern, '/'), '', '', $flags);
|
318 |
-
$_relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $_cache_path);
|
319 |
-
$_uri_pattern = $self->wdRegexToActualRegexFrag($_relative_cache_path);
|
320 |
-
}
|
321 |
-
if (!$_uri_pattern) {
|
322 |
-
unset($uri_patterns[$_key]); // Remove it.
|
323 |
-
}
|
324 |
-
}
|
325 |
-
unset($_key, $_uri_pattern, $_cache_path, $_relative_cache_path); // Housekeeping.
|
326 |
-
|
327 |
-
return $uri_patterns ? '(?:'.implode('|', array_unique($uri_patterns)).')'.$regex_suffix_frag : '';
|
328 |
-
};
|
329 |
-
|
330 |
-
/*
|
331 |
-
* Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
332 |
-
*
|
333 |
-
* @since 151114 Moving this low-level routine into a method of a different name.
|
334 |
-
*
|
335 |
-
* @param string $regex_frag A regex fragment. This CAN be left empty when necessary.
|
336 |
-
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
337 |
-
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
338 |
-
*
|
339 |
-
* @param string $regex_suffix_frag Regex fragment to come after the `$regex_frag`.
|
340 |
-
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
341 |
-
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
342 |
-
* See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
343 |
-
*
|
344 |
-
* @return string Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
345 |
-
*/
|
346 |
-
$self->assembleCachePathRegex = function ($regex_frag, $regex_suffix_frag = CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) use ($self) {
|
347 |
-
$regex_frag = (string) $regex_frag;
|
348 |
-
$regex_suffix_frag = $self->cachePathRegexSuffixFrag($regex_suffix_frag);
|
349 |
-
|
350 |
-
return '/^'.$regex_frag.$regex_suffix_frag.'/i';
|
351 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/ConditionalUtils.php
DELETED
@@ -1,358 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* PHP's language constructs.
|
6 |
-
*
|
7 |
-
* @type array PHP's language constructs.
|
8 |
-
* Keys are currently unimportant. Subject to change.
|
9 |
-
*
|
10 |
-
* @since 160222 First documented version.
|
11 |
-
*/
|
12 |
-
$self->php_constructs = [
|
13 |
-
'die' => 'die',
|
14 |
-
'echo' => 'echo',
|
15 |
-
'empty' => 'empty',
|
16 |
-
'exit' => 'exit',
|
17 |
-
'eval' => 'eval',
|
18 |
-
'include' => 'include',
|
19 |
-
'include_once' => 'include_once',
|
20 |
-
'isset' => 'isset',
|
21 |
-
'list' => 'list',
|
22 |
-
'require' => 'require',
|
23 |
-
'require_once' => 'require_once',
|
24 |
-
'return' => 'return',
|
25 |
-
'print' => 'print',
|
26 |
-
'unset' => 'unset',
|
27 |
-
'__halt_compiler' => '__halt_compiler',
|
28 |
-
];
|
29 |
-
|
30 |
-
/*
|
31 |
-
* Is AdvancedCache class?
|
32 |
-
*
|
33 |
-
* @since 150821 Improving multisite compat.
|
34 |
-
*
|
35 |
-
* @return bool `TRUE` if this is the AdvancedCache class.
|
36 |
-
*/
|
37 |
-
$self->isAdvancedCache = function () use ($self) {
|
38 |
-
return $self instanceof AdvancedCache;
|
39 |
-
};
|
40 |
-
|
41 |
-
/*
|
42 |
-
* Is Plugin class?
|
43 |
-
*
|
44 |
-
* @since 150821 Improving multisite compat.
|
45 |
-
*
|
46 |
-
* @return bool `TRUE` if this is the Plugin class.
|
47 |
-
*/
|
48 |
-
$self->isPlugin = function () use ($self) {
|
49 |
-
return $self instanceof Plugin;
|
50 |
-
};
|
51 |
-
|
52 |
-
/*
|
53 |
-
* Is the current request method `POST`, `PUT` or `DELETE`?
|
54 |
-
*
|
55 |
-
* @since 150422 Rewrite.
|
56 |
-
*
|
57 |
-
* @return boolean `TRUE` if current request method is `POST`, `PUT` or `DELETE`.
|
58 |
-
*
|
59 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
60 |
-
*/
|
61 |
-
$self->isPostPutDeleteRequest = function () use ($self) {
|
62 |
-
if (!is_null($is = &$self->staticKey('isPostPutDeleteRequest'))) {
|
63 |
-
return $is; // Already cached this.
|
64 |
-
}
|
65 |
-
if (!empty($_POST)) {
|
66 |
-
return ($is = true);
|
67 |
-
}
|
68 |
-
if (!empty($_SERVER['REQUEST_METHOD']) && is_string($_SERVER['REQUEST_METHOD'])) {
|
69 |
-
if (in_array(strtoupper($_SERVER['REQUEST_METHOD']), array('POST', 'PUT', 'DELETE'), true)) {
|
70 |
-
return ($is = true);
|
71 |
-
}
|
72 |
-
}
|
73 |
-
return ($is = false);
|
74 |
-
};
|
75 |
-
|
76 |
-
/*
|
77 |
-
* Does the current request include an uncacheable query string?
|
78 |
-
*
|
79 |
-
* @since 151002 Improving Nginx support.
|
80 |
-
*
|
81 |
-
* @return boolean True if request includes an uncacheable query string.
|
82 |
-
*
|
83 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
84 |
-
*/
|
85 |
-
$self->requestContainsUncacheableQueryVars = function () use ($self) {
|
86 |
-
if (!is_null($is = &$self->staticKey('requestContainsUncacheableQueryVars'))) {
|
87 |
-
return $is; // Already cached this.
|
88 |
-
}
|
89 |
-
if (!empty($_GET) || !empty($_SERVER['QUERY_STRING'])) {
|
90 |
-
$_get_count = !empty($_GET) ? count($_GET) : 0;
|
91 |
-
$is_abc_only = $_get_count === 1 && isset($_GET[strtolower(SHORT_NAME).'ABC']);
|
92 |
-
$is_nginx_q_only = $_get_count === 1 && isset($_GET['q']) && $self->isNginx();
|
93 |
-
$is_ac_get_var_true = isset($_GET[strtolower(SHORT_NAME).'AC']) && filter_var($_GET[strtolower(SHORT_NAME).'AC'], FILTER_VALIDATE_BOOLEAN);
|
94 |
-
|
95 |
-
if (!$is_abc_only && !$is_nginx_q_only && !$is_ac_get_var_true) {
|
96 |
-
return ($is = true);
|
97 |
-
}
|
98 |
-
}
|
99 |
-
return ($is = false);
|
100 |
-
};
|
101 |
-
|
102 |
-
/*
|
103 |
-
* Is the current request method is uncacheable?
|
104 |
-
*
|
105 |
-
* @since 150422 Rewrite.
|
106 |
-
*
|
107 |
-
* @return boolean `TRUE` if current request method is uncacheable.
|
108 |
-
*
|
109 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
110 |
-
*/
|
111 |
-
$self->isUncacheableRequestMethod = function () use ($self) {
|
112 |
-
if (!is_null($is = &$self->staticKey('isUncacheableRequestMethod'))) {
|
113 |
-
return $is; // Already cached this.
|
114 |
-
}
|
115 |
-
if (!empty($_POST)) {
|
116 |
-
return ($is = true);
|
117 |
-
}
|
118 |
-
if (!empty($_SERVER['REQUEST_METHOD']) && is_string($_SERVER['REQUEST_METHOD'])) {
|
119 |
-
if (!in_array(strtoupper($_SERVER['REQUEST_METHOD']), array('GET'), true)) {
|
120 |
-
return ($is = true);
|
121 |
-
}
|
122 |
-
}
|
123 |
-
return ($is = false);
|
124 |
-
};
|
125 |
-
|
126 |
-
/*
|
127 |
-
* Should the current user should be considered a logged-in user?
|
128 |
-
*
|
129 |
-
* @since 150422 Rewrite.
|
130 |
-
*
|
131 |
-
* @return boolean `TRUE` if current user should be considered a logged-in user.
|
132 |
-
*
|
133 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
134 |
-
*/
|
135 |
-
$self->isLikeUserLoggedIn = function () use ($self) {
|
136 |
-
if (!is_null($is = &$self->staticKey('isLikeUserLoggedIn'))) {
|
137 |
-
return $is; // Already cached this.
|
138 |
-
}
|
139 |
-
if (defined('SID') && SID) {
|
140 |
-
return ($is = true); // Session ID.
|
141 |
-
}
|
142 |
-
if (empty($_COOKIE)) {
|
143 |
-
return ($is = false); // No cookies.
|
144 |
-
}
|
145 |
-
$regex_logged_in_cookies = '/^'; // Initialize.
|
146 |
-
|
147 |
-
if (defined('LOGGED_IN_COOKIE') && LOGGED_IN_COOKIE) {
|
148 |
-
$regex_logged_in_cookies .= preg_quote(LOGGED_IN_COOKIE, '/');
|
149 |
-
} else { // Use the default hard-coded cookie prefix.
|
150 |
-
$regex_logged_in_cookies .= 'wordpress_logged_in_';
|
151 |
-
}
|
152 |
-
$regex_logged_in_cookies .= '|comment_author_';
|
153 |
-
$regex_logged_in_cookies .= '|wp[_\-]postpass_';
|
154 |
-
|
155 |
-
$regex_logged_in_cookies .= '/'; // Close regex.
|
156 |
-
|
157 |
-
foreach ($_COOKIE as $_key => $_value) {
|
158 |
-
if ($_value && preg_match($regex_logged_in_cookies, $_key)) {
|
159 |
-
return ($is = true); // Like a logged-in user.
|
160 |
-
}
|
161 |
-
} unset($_key, $_value); // Housekeeping.
|
162 |
-
|
163 |
-
return ($is = false);
|
164 |
-
};
|
165 |
-
|
166 |
-
/*
|
167 |
-
* Are we in a LOCALHOST environment?
|
168 |
-
*
|
169 |
-
* @since 150422 Rewrite.
|
170 |
-
*
|
171 |
-
* @return boolean `TRUE` if we are in a LOCALHOST environment.
|
172 |
-
*
|
173 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
174 |
-
*/
|
175 |
-
$self->isLocalhost = function () use ($self) {
|
176 |
-
if (!is_null($is = &$self->staticKey('isLocalhost'))) {
|
177 |
-
return $is; // Already cached this.
|
178 |
-
}
|
179 |
-
if (defined('LOCALHOST')) {
|
180 |
-
return ($is = (boolean) LOCALHOST);
|
181 |
-
}
|
182 |
-
if (preg_match('/\b(?:localhost|127\.0\.0\.1)\b/i', $self->hostToken())) {
|
183 |
-
return ($is = true);
|
184 |
-
}
|
185 |
-
return ($is = false);
|
186 |
-
};
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
/*
|
191 |
-
* Is the current request for a feed?
|
192 |
-
*
|
193 |
-
* @since 150422 Rewrite.
|
194 |
-
*
|
195 |
-
* @return boolean `TRUE` if the current request is for a feed.
|
196 |
-
*
|
197 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
198 |
-
*/
|
199 |
-
$self->isFeed = function () use ($self) {
|
200 |
-
if (!is_null($is = &$self->staticKey('isFeed'))) {
|
201 |
-
return $is; // Already cached this.
|
202 |
-
}
|
203 |
-
if (isset($_REQUEST['feed'])) {
|
204 |
-
return ($is = true);
|
205 |
-
}
|
206 |
-
if (!empty($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])) {
|
207 |
-
if (preg_match('/\/feed(?:[\/?]|$)/', $_SERVER['REQUEST_URI'])) {
|
208 |
-
return ($is = true);
|
209 |
-
}
|
210 |
-
}
|
211 |
-
return ($is = false);
|
212 |
-
};
|
213 |
-
|
214 |
-
/*
|
215 |
-
* Is a document/string an HTML/XML doc; or no?
|
216 |
-
*
|
217 |
-
* @since 150422 Rewrite.
|
218 |
-
*
|
219 |
-
* @param string $doc Input string/document to check.
|
220 |
-
*
|
221 |
-
* @return boolean True if `$doc` is an HTML/XML doc type.
|
222 |
-
*/
|
223 |
-
$self->isHtmlXmlDoc = function ($doc) use ($self) {
|
224 |
-
$doc = trim((string) $doc);
|
225 |
-
$doc_hash = sha1($doc);
|
226 |
-
|
227 |
-
if (!is_null($is = &$self->staticKey('isHtmlXmlDoc', $doc_hash))) {
|
228 |
-
return $is; // Already cached this.
|
229 |
-
}
|
230 |
-
if (stripos($doc, '</html>') !== false) {
|
231 |
-
return ($is = true);
|
232 |
-
}
|
233 |
-
if (stripos($doc, '<?xml') === 0) {
|
234 |
-
return ($is = true);
|
235 |
-
}
|
236 |
-
return ($is = false);
|
237 |
-
};
|
238 |
-
|
239 |
-
/*
|
240 |
-
* Does the current request have a cacheable content type?
|
241 |
-
*
|
242 |
-
* @since 150422 Rewrite.
|
243 |
-
*
|
244 |
-
* @return boolean `TRUE` if the current request has a cacheable content type.
|
245 |
-
*
|
246 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
247 |
-
*
|
248 |
-
* @warning Do NOT call upon this method until the end of a script execution.
|
249 |
-
*/
|
250 |
-
$self->hasACacheableContentType = function () use ($self) {
|
251 |
-
if (!is_null($is = &$self->staticKey('hasACacheableContentType'))) {
|
252 |
-
return $is; // Already cached this.
|
253 |
-
}
|
254 |
-
foreach ($self->headersList() as $_key => $_header) {
|
255 |
-
if (stripos($_header, 'Content-Type:') === 0) {
|
256 |
-
$content_type = $_header; // Last one.
|
257 |
-
}
|
258 |
-
} unset($_key, $_header); // Housekeeping.
|
259 |
-
|
260 |
-
if (isset($content_type[0]) && stripos($content_type, 'html') === false
|
261 |
-
&& stripos($content_type, 'xml') === false && stripos($content_type, GLOBAL_NS) === false) {
|
262 |
-
return ($is = false); // Do NOT cache data sent by scripts serving other MIME types.
|
263 |
-
}
|
264 |
-
return ($is = true);
|
265 |
-
};
|
266 |
-
|
267 |
-
/*
|
268 |
-
* Does the current request have a cacheable HTTP status code?
|
269 |
-
*
|
270 |
-
* @since 150422 Rewrite.
|
271 |
-
*
|
272 |
-
* @return boolean `TRUE` if the current request has a cacheable HTTP status code.
|
273 |
-
*
|
274 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
275 |
-
*
|
276 |
-
* @warning Do NOT call upon this method until the end of a script execution.
|
277 |
-
*/
|
278 |
-
$self->hasACacheableStatus = function () use ($self) {
|
279 |
-
if (!is_null($is = &$self->staticKey('hasACacheableStatus'))) {
|
280 |
-
return $is; // Already cached this.
|
281 |
-
}
|
282 |
-
if (($http_status = (string) $self->httpStatus()) && $http_status[0] !== '2' && $http_status !== '404') {
|
283 |
-
return ($is = false); // A non-2xx & non-404 status code.
|
284 |
-
}
|
285 |
-
foreach ($self->headersList() as $_key => $_header) {
|
286 |
-
if (preg_match('/^(?:Retry\-After\:\s+(?P<retry>.+)|Status\:\s+(?P<status>[0-9]+)|HTTP\/[0-9]+(?:\.[0-9]+)?\s+(?P<http_status>[0-9]+))/i', $_header, $_m)) {
|
287 |
-
if (!empty($_m['retry']) || (!empty($_m['status']) && $_m['status'][0] !== '2' && $_m['status'] !== '404')
|
288 |
-
|| (!empty($_m['http_status']) && $_m['http_status'][0] !== '2' && $_m['http_status'] !== '404')
|
289 |
-
) {
|
290 |
-
return ($is = false); // Not a cacheable status.
|
291 |
-
}
|
292 |
-
}
|
293 |
-
} unset($_key, $_header); // Housekeeping.
|
294 |
-
|
295 |
-
return ($is = true);
|
296 |
-
};
|
297 |
-
|
298 |
-
/*
|
299 |
-
* Checks if a PHP extension is loaded up.
|
300 |
-
*
|
301 |
-
* @since 150422 Rewrite.
|
302 |
-
*
|
303 |
-
* @param string $extension A PHP extension slug (i.e. extension name).
|
304 |
-
*
|
305 |
-
* @return boolean `TRUE` if the extension is loaded.
|
306 |
-
*
|
307 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
308 |
-
*/
|
309 |
-
$self->isExtensionLoaded = function ($extension) use ($self) {
|
310 |
-
$extension = (string) $extension;
|
311 |
-
|
312 |
-
if (!is_null($is = &$self->staticKey('isExtensionLoaded', $extension))) {
|
313 |
-
return $is; // Already cached this.
|
314 |
-
}
|
315 |
-
return ($is = (boolean) extension_loaded($extension));
|
316 |
-
};
|
317 |
-
|
318 |
-
/*
|
319 |
-
* Is a particular function possible in every way?
|
320 |
-
*
|
321 |
-
* @since 150422 Rewrite.
|
322 |
-
*
|
323 |
-
* @param string $function A PHP function (or user function) to check.
|
324 |
-
*
|
325 |
-
* @return string `TRUE` if the function is possible.
|
326 |
-
*
|
327 |
-
* @note This checks (among other things) if the function exists and that it's callable.
|
328 |
-
* It also checks the currently configured `disable_functions` and `suhosin.executor.func.blacklist`.
|
329 |
-
*/
|
330 |
-
$self->functionIsPossible = function ($function) use ($self) {
|
331 |
-
$function = (string) $function;
|
332 |
-
|
333 |
-
if (!is_null($is = &$self->staticKey('functionIsPossible', $function))) {
|
334 |
-
return $is; // Already cached this.
|
335 |
-
}
|
336 |
-
if (is_null($disabled_functions = &$self->staticKey('functionIsPossible_disabled_functions'))) {
|
337 |
-
$disabled_functions = array(); // Initialize disabled/blacklisted functions.
|
338 |
-
|
339 |
-
if (($disable_functions = trim(ini_get('disable_functions')))) {
|
340 |
-
$disabled_functions = array_merge($disabled_functions, preg_split('/[\s;,]+/', strtolower($disable_functions), -1, PREG_SPLIT_NO_EMPTY));
|
341 |
-
}
|
342 |
-
if (($blacklist_functions = trim(ini_get('suhosin.executor.func.blacklist')))) {
|
343 |
-
$disabled_functions = array_merge($disabled_functions, preg_split('/[\s;,]+/', strtolower($blacklist_functions), -1, PREG_SPLIT_NO_EMPTY));
|
344 |
-
}
|
345 |
-
if(filter_var(ini_get('suhosin.executor.disable_eval'), FILTER_VALIDATE_BOOLEAN)) {
|
346 |
-
$disabled_functions = array_merge($disabled_functions, array('eval'));
|
347 |
-
}
|
348 |
-
}
|
349 |
-
if (!function_exists($function) || !is_callable($function)) {
|
350 |
-
if(!in_array($function, $self->php_constructs, true)) { // A language construct
|
351 |
-
return ($is = false); // Not possible.
|
352 |
-
}
|
353 |
-
}
|
354 |
-
if ($disabled_functions && in_array(strtolower($function), $disabled_functions, true)) {
|
355 |
-
return ($is = false); // Not possible.
|
356 |
-
}
|
357 |
-
return ($is = true);
|
358 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/DomainMappingUtils.php
DELETED
@@ -1,264 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Can consider domain mapping?
|
6 |
-
*
|
7 |
-
* @since 150821 Improving multisite compat.
|
8 |
-
*
|
9 |
-
* @return bool `TRUE` if we can consider domain mapping.
|
10 |
-
*
|
11 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
12 |
-
*/
|
13 |
-
$self->canConsiderDomainMapping = function () use ($self) {
|
14 |
-
if (!is_null($can = &$self->staticKey('canConsiderDomainMapping'))) {
|
15 |
-
return $can; // Already cached this.
|
16 |
-
}
|
17 |
-
if (!$self->isAdvancedCache() && is_multisite() && $self->hostBaseToken() === '/'
|
18 |
-
&& defined('SUNRISE_LOADED') && SUNRISE_LOADED && !empty($GLOBALS['dm_domain'])) {
|
19 |
-
return ($can = true); // Can consider.
|
20 |
-
}
|
21 |
-
return ($can = false); // Cannot consider.
|
22 |
-
};
|
23 |
-
|
24 |
-
/*
|
25 |
-
* Domain mapping?
|
26 |
-
*
|
27 |
-
* @since 150821 Improving multisite compat.
|
28 |
-
*
|
29 |
-
* @return integer Domain mapping ID; else `0` (false).
|
30 |
-
*
|
31 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
32 |
-
*/
|
33 |
-
$self->isDomainMapping = function () use ($self) {
|
34 |
-
if (!is_null($is = &$self->staticKey('isDomainMapping'))) {
|
35 |
-
return $is; // Already cached this.
|
36 |
-
}
|
37 |
-
if (!$self->isAdvancedCache() && is_multisite() && $self->canConsiderDomainMapping()
|
38 |
-
&& defined('DOMAIN_MAPPING') && DOMAIN_MAPPING && !empty($GLOBALS['domain_mapping_id'])) {
|
39 |
-
return ($is = (integer) $GLOBALS['domain_mapping_id']); // Blog ID.
|
40 |
-
}
|
41 |
-
return ($is = 0); // Not domain mapping.
|
42 |
-
};
|
43 |
-
|
44 |
-
/*
|
45 |
-
* Filters a URL in order to apply domain mapping.
|
46 |
-
*
|
47 |
-
* @since 150821 Improving multisite compat.
|
48 |
-
*
|
49 |
-
* @param string $url The input URL to filter.
|
50 |
-
*
|
51 |
-
* @return string The filtered URL; else the original URL.
|
52 |
-
*
|
53 |
-
* @note The return value of this function is NOT cached, but inner portions are.
|
54 |
-
*/
|
55 |
-
$self->domainMappingUrlFilter = function ($url) use ($self) {
|
56 |
-
$original_url = (string) $url; // Preserve.
|
57 |
-
$url = trim((string) $url);
|
58 |
-
|
59 |
-
if (!is_multisite() || !$self->canConsiderDomainMapping()) {
|
60 |
-
return $original_url; // Not possible.
|
61 |
-
}
|
62 |
-
if (!$url || !($url_parts = $self->parseUrl($url))) {
|
63 |
-
return $original_url; // Not possible.
|
64 |
-
}
|
65 |
-
if (empty($url_parts['host'])) {
|
66 |
-
return $original_url; // Not possible.
|
67 |
-
}
|
68 |
-
$blog_domain = strtolower($url_parts['host']); // In the unfiltered URL.
|
69 |
-
$blog_path = $self->hostDirToken(false, false, !empty($url_parts['path']) ? $url_parts['path'] : '/');
|
70 |
-
|
71 |
-
if (!($blog_id = (integer) get_blog_id_from_url($blog_domain, $blog_path))) {
|
72 |
-
return $original_url; // Not possible.
|
73 |
-
}
|
74 |
-
if (!($domain = $self->domainMappingBlogDomain($blog_id)) || $domain === $blog_domain) {
|
75 |
-
return $original_url; // Not applicable.
|
76 |
-
}
|
77 |
-
$url_parts['host'] = $domain; // Filter the URL now.
|
78 |
-
if (!empty($url_parts['path']) && $url_parts['path'] !== '/') {
|
79 |
-
if (($host_base_dir_tokens = trim($self->hostBaseDirTokens(false, false, $url_parts['path']), '/'))) {
|
80 |
-
$url_parts['path'] = preg_replace('/^\/'.preg_quote($host_base_dir_tokens, '/').'(\/|$)/i', '${1}', $url_parts['path']);
|
81 |
-
}
|
82 |
-
}
|
83 |
-
return ($url = $self->unParseUrl($url_parts));
|
84 |
-
};
|
85 |
-
|
86 |
-
/*
|
87 |
-
* Filters a URL in order to remove domain mapping.
|
88 |
-
*
|
89 |
-
* @since 150821 Improving multisite compat.
|
90 |
-
*
|
91 |
-
* @param string $url The input URL to filter.
|
92 |
-
*
|
93 |
-
* @return string The filtered URL; else the original URL.
|
94 |
-
*
|
95 |
-
* @note The return value of this function is NOT cached, but inner portions are.
|
96 |
-
*/
|
97 |
-
$self->domainMappingReverseUrlFilter = function ($url) use ($self) {
|
98 |
-
$original_url = (string) $url; // Preserve.
|
99 |
-
$url = trim((string) $url);
|
100 |
-
|
101 |
-
if (!is_multisite() || !$self->canConsiderDomainMapping()) {
|
102 |
-
return $original_url; // Not possible.
|
103 |
-
}
|
104 |
-
if (!$url || !($url_parts = $self->parseUrl($url))) {
|
105 |
-
return $original_url; // Not possible.
|
106 |
-
}
|
107 |
-
if (empty($url_parts['host'])) {
|
108 |
-
return $original_url; // Not possible.
|
109 |
-
}
|
110 |
-
if (!($blog_id = $self->domainMappingBlogId('', $url_parts['host']))) {
|
111 |
-
return $original_url; // No a domain in the map.
|
112 |
-
}
|
113 |
-
if (!($blog_details = $self->blogDetails($blog_id))) {
|
114 |
-
return $original_url; // Not possible.
|
115 |
-
}
|
116 |
-
$url_parts['host'] = $blog_details->domain; // Filter the URL now.
|
117 |
-
if (($host_base_dir_tokens = trim($self->hostBaseDirTokens(false, false, $blog_details->path), '/'))) {
|
118 |
-
$url_parts['path'] = '/'.$host_base_dir_tokens.'/'.ltrim(@$url_parts['path'], '/');
|
119 |
-
}
|
120 |
-
return ($url = $self->unParseUrl($url_parts));
|
121 |
-
};
|
122 |
-
|
123 |
-
/*
|
124 |
-
* Converts a host into a mapped blog ID.
|
125 |
-
*
|
126 |
-
* @since 150821 Improving multisite compat.
|
127 |
-
*
|
128 |
-
* @param string $url URL containing the domain to convert.
|
129 |
-
* @param string $domain The domain to convert. Override URL is provided.
|
130 |
-
*
|
131 |
-
* @return integer The mapped blog ID; else `0` on failure.
|
132 |
-
*
|
133 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
134 |
-
*/
|
135 |
-
$self->domainMappingBlogId = function ($url = '', $domain = '') use ($self) {
|
136 |
-
$domain = (string) $domain;
|
137 |
-
$url = $domain ? '' : (string) $url;
|
138 |
-
|
139 |
-
if (!is_multisite() || !$self->canConsiderDomainMapping()) {
|
140 |
-
return 0; // Not possible/applicable.
|
141 |
-
}
|
142 |
-
if ($url === 'network' || $domain === 'network') {
|
143 |
-
$domain = (string) get_current_site()->domain;
|
144 |
-
}
|
145 |
-
if (!$domain && $url && $url !== 'network') {
|
146 |
-
$domain = $self->parseUrl($url, PHP_URL_HOST);
|
147 |
-
}
|
148 |
-
if (!$url && !$domain && ($blog_details = $self->blogDetails())) {
|
149 |
-
$domain = $blog_details->domain;
|
150 |
-
}
|
151 |
-
$domain = strtolower(preg_replace('/^www\./i', '', $domain));
|
152 |
-
|
153 |
-
if (!$domain || strpos($domain, '.') === false) {
|
154 |
-
return 0; // Not possible.
|
155 |
-
}
|
156 |
-
if (!is_null($blog_id = &$self->staticKey('domainMappingBlogId', $domain))) {
|
157 |
-
return $blog_id; // Already cached this.
|
158 |
-
}
|
159 |
-
$wpdb = $self->wpdb(); // WordPress database class.
|
160 |
-
$suppressing_errors = $wpdb->suppress_errors(); // In case table has not been created yet.
|
161 |
-
$enforcing_primary_domain = !get_site_option('dm_no_primary_domain'); // Enforcing primary domain?
|
162 |
-
|
163 |
-
if (!$enforcing_primary_domain) {
|
164 |
-
$blog_id = (integer) $wpdb->get_var('SELECT `blog_id` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `domain` IN(\''.esc_sql('www.'.$domain).'\', \''.esc_sql($domain).'\') ORDER BY CHAR_LENGTH(`domain`) DESC, `active` DESC LIMIT 1');
|
165 |
-
} else {
|
166 |
-
$blog_id = (integer) $wpdb->get_var('SELECT `blog_id` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `domain` IN(\''.esc_sql('www.'.$domain).'\', \''.esc_sql($domain).'\') AND `active` = \'1\' ORDER BY CHAR_LENGTH(`domain`) DESC LIMIT 1');
|
167 |
-
}
|
168 |
-
$wpdb->suppress_errors($suppressing_errors); // Restore.
|
169 |
-
|
170 |
-
return ($blog_id = (integer) $blog_id);
|
171 |
-
};
|
172 |
-
|
173 |
-
/*
|
174 |
-
* Converts a blog ID into a mapped domain.
|
175 |
-
*
|
176 |
-
* @since 150821 Improving multisite compat.
|
177 |
-
*
|
178 |
-
* @param integer $blog_id The blog ID.
|
179 |
-
*
|
180 |
-
* @param boolean $fallback Fallback on blog's domain?
|
181 |
-
*
|
182 |
-
* @return string The mapped domain, else an empty string.
|
183 |
-
*
|
184 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
185 |
-
*/
|
186 |
-
$self->domainMappingBlogDomain = function ($blog_id = 0, $fallback = false) use ($self) {
|
187 |
-
if (!is_multisite() || !$self->canConsiderDomainMapping()) {
|
188 |
-
return ''; // Not possible/applicable.
|
189 |
-
}
|
190 |
-
if (($blog_id = (integer) $blog_id) < 0) {
|
191 |
-
$blog_id = (integer) get_current_site()->blog_id;
|
192 |
-
}
|
193 |
-
if (!$blog_id) {
|
194 |
-
$blog_id = (integer) get_current_blog_id();
|
195 |
-
}
|
196 |
-
if (!$blog_id || $blog_id < 0) {
|
197 |
-
return ''; // Not possible.
|
198 |
-
}
|
199 |
-
if (!is_null($domain = &$self->staticKey('domainMappingBlogDomain', $blog_id))) {
|
200 |
-
return $domain; // Already cached this.
|
201 |
-
}
|
202 |
-
$wpdb = $self->wpdb(); // WordPress database class.
|
203 |
-
$suppressing_errors = $wpdb->suppress_errors(); // In case table has not been created yet.
|
204 |
-
$enforcing_primary_domain = !get_site_option('dm_no_primary_domain'); // Enforcing primary domain?
|
205 |
-
|
206 |
-
if (!$enforcing_primary_domain) {
|
207 |
-
if ($self->isDomainMapping() === $blog_id) {
|
208 |
-
$domain = $self->hostToken();
|
209 |
-
$domain = preg_replace('/^www\./i', '', $domain);
|
210 |
-
$domain = (string) $wpdb->get_var('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IN(\''.esc_sql('www.'.$domain).'\', \''.esc_sql($domain).'\') ORDER BY CHAR_LENGTH(`domain`) DESC LIMIT 1');
|
211 |
-
} elseif (($domains = $self->domainMappingBlogDomains($blog_id))) {
|
212 |
-
$domain = $domains[0]; // Use the first of all possible domains.
|
213 |
-
}
|
214 |
-
} else { // A single primary domain in this case; i.e., `active` = primary.
|
215 |
-
$domain = (string) $wpdb->get_var('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IS NOT NULL AND `domain` != \'\' AND `active` = \'1\' LIMIT 1');
|
216 |
-
}
|
217 |
-
if (!$domain && $fallback && ($blog_details = $self->blogDetails($blog_id))) {
|
218 |
-
$domain = $blog_details->domain; // Use original domain.
|
219 |
-
}
|
220 |
-
$wpdb->suppress_errors($suppressing_errors); // Restore.
|
221 |
-
|
222 |
-
return ($domain = strtolower((string) $domain));
|
223 |
-
};
|
224 |
-
|
225 |
-
/*
|
226 |
-
* Converts a blog ID into mapped domains (plural).
|
227 |
-
*
|
228 |
-
* @since 150821 Improving multisite compat.
|
229 |
-
*
|
230 |
-
* @param integer $blog_id The blog ID.
|
231 |
-
*
|
232 |
-
* @return array Mapped domains; else an empty array.
|
233 |
-
*
|
234 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
235 |
-
*/
|
236 |
-
$self->domainMappingBlogDomains = function ($blog_id = 0) use ($self) {
|
237 |
-
if (!is_multisite() || !$self->canConsiderDomainMapping()) {
|
238 |
-
return array(); // Not possible/applicable.
|
239 |
-
}
|
240 |
-
if (($blog_id = (integer) $blog_id) < 0) {
|
241 |
-
$blog_id = (integer) get_current_site()->blog_id;
|
242 |
-
}
|
243 |
-
if (!$blog_id) {
|
244 |
-
$blog_id = (integer) get_current_blog_id();
|
245 |
-
}
|
246 |
-
if (!$blog_id || $blog_id < 0) {
|
247 |
-
return array(); // Not possible.
|
248 |
-
}
|
249 |
-
if (!is_null($domains = &$self->staticKey('domainMappingBlogDomains', $blog_id))) {
|
250 |
-
return $domains; // Already cached this.
|
251 |
-
}
|
252 |
-
$wpdb = $self->wpdb(); // WordPress database class.
|
253 |
-
$suppressing_errors = $wpdb->suppress_errors(); // In case table has not been created yet.
|
254 |
-
$enforcing_primary_domain = !get_site_option('dm_no_primary_domain'); // Enforcing primary domain?
|
255 |
-
|
256 |
-
if (!$enforcing_primary_domain) { // Not enforcing a primary domain, so let's pull all of the domains.
|
257 |
-
$domains = $wpdb->get_col('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IS NOT NULL AND `domain` != \'\' ORDER BY `active` DESC');
|
258 |
-
} else { // Primary domains in this case; i.e., `active` = primary.
|
259 |
-
$domains = $wpdb->get_col('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IS NOT NULL AND `domain` != \'\' AND `active` = \'1\'');
|
260 |
-
}
|
261 |
-
$wpdb->suppress_errors($suppressing_errors); // Restore.
|
262 |
-
|
263 |
-
return ($domains = array_unique(array_map('strtolower', (array) $domains)));
|
264 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/EscapeUtils.php
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Escape single quotes.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param string $string Input string to escape.
|
10 |
-
* @param integer $times Optional. Defaults to one escape char; e.g. `\'`.
|
11 |
-
* If you need to escape more than once, set this to something > `1`.
|
12 |
-
*
|
13 |
-
* @return string Escaped string; e.g. `Raam\'s the lead developer`.
|
14 |
-
*/
|
15 |
-
$self->escSq = function ($string, $times = 1) use ($self) {
|
16 |
-
return str_replace("'", str_repeat('\\', abs($times))."'", (string) $string);
|
17 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/FsUtils.php
DELETED
@@ -1,323 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Normalizes directory/file separators.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param string $dir_file Directory/file path.
|
10 |
-
*
|
11 |
-
* @param boolean $allow_trailing_slash Defaults to FALSE.
|
12 |
-
* If TRUE; and `$dir_file` contains a trailing slash; we'll leave it there.
|
13 |
-
*
|
14 |
-
* @return string Normalized directory/file path.
|
15 |
-
*/
|
16 |
-
$self->nDirSeps = function ($dir_file, $allow_trailing_slash = false) use ($self) {
|
17 |
-
$dir_file = (string) $dir_file;
|
18 |
-
|
19 |
-
if (!isset($dir_file[0])) {
|
20 |
-
return ''; // Catch empty string.
|
21 |
-
}
|
22 |
-
if (strpos($dir_file, '://' !== false)) {
|
23 |
-
if (preg_match('/^(?P<stream_wrapper>[a-zA-Z0-9]+)\:\/\//', $dir_file, $stream_wrapper)) {
|
24 |
-
$dir_file = preg_replace('/^(?P<stream_wrapper>[a-zA-Z0-9]+)\:\/\//', '', $dir_file);
|
25 |
-
}
|
26 |
-
}
|
27 |
-
if (strpos($dir_file, ':' !== false)) {
|
28 |
-
if (preg_match('/^(?P<drive_letter>[a-zA-Z])\:[\/\\\\]/', $dir_file)) {
|
29 |
-
$dir_file = preg_replace_callback('/^(?P<drive_letter>[a-zA-Z])\:[\/\\\\]/', create_function('$m', 'return strtoupper($m[0]);'), $dir_file);
|
30 |
-
}
|
31 |
-
}
|
32 |
-
$dir_file = preg_replace('/\/+/', '/', str_replace(array(DIRECTORY_SEPARATOR, '\\', '/'), '/', $dir_file));
|
33 |
-
$dir_file = ($allow_trailing_slash) ? $dir_file : rtrim($dir_file, '/'); // Strip trailing slashes.
|
34 |
-
|
35 |
-
if (!empty($stream_wrapper[0])) {
|
36 |
-
$dir_file = strtolower($stream_wrapper[0]).$dir_file;
|
37 |
-
}
|
38 |
-
return $dir_file; // Normalized now.
|
39 |
-
};
|
40 |
-
|
41 |
-
/*
|
42 |
-
* Acquires system tmp directory path.
|
43 |
-
*
|
44 |
-
* @since 150422 Rewrite.
|
45 |
-
*
|
46 |
-
* @return string System tmp directory path; else an empty string.
|
47 |
-
*/
|
48 |
-
$self->getTmpDir = function () use ($self) {
|
49 |
-
if (!is_null($dir = &$self->staticKey('getTmpDir'))) {
|
50 |
-
return $dir; // Already cached this.
|
51 |
-
}
|
52 |
-
$possible_dirs = array(); // Initialize.
|
53 |
-
|
54 |
-
if (defined('WP_TEMP_DIR')) {
|
55 |
-
$possible_dirs[] = (string) WP_TEMP_DIR;
|
56 |
-
}
|
57 |
-
if ($self->functionIsPossible('sys_get_temp_dir')) {
|
58 |
-
$possible_dirs[] = (string) sys_get_temp_dir();
|
59 |
-
}
|
60 |
-
$possible_dirs[] = (string) ini_get('upload_tmp_dir');
|
61 |
-
|
62 |
-
if (!empty($_SERVER['TEMP'])) {
|
63 |
-
$possible_dirs[] = (string) $_SERVER['TEMP'];
|
64 |
-
}
|
65 |
-
if (!empty($_SERVER['TMPDIR'])) {
|
66 |
-
$possible_dirs[] = (string) $_SERVER['TMPDIR'];
|
67 |
-
}
|
68 |
-
if (!empty($_SERVER['TMP'])) {
|
69 |
-
$possible_dirs[] = (string) $_SERVER['TMP'];
|
70 |
-
}
|
71 |
-
if (stripos(PHP_OS, 'win') === 0) {
|
72 |
-
$possible_dirs[] = 'C:/Temp';
|
73 |
-
}
|
74 |
-
if (stripos(PHP_OS, 'win') !== 0) {
|
75 |
-
$possible_dirs[] = '/tmp';
|
76 |
-
}
|
77 |
-
if (defined('WP_CONTENT_DIR')) {
|
78 |
-
$possible_dirs[] = (string) WP_CONTENT_DIR;
|
79 |
-
}
|
80 |
-
foreach ($possible_dirs as $_key => $_dir) {
|
81 |
-
if (($_dir = trim((string) $_dir)) && @is_dir($_dir) && @is_writable($_dir)) {
|
82 |
-
return ($dir = $self->nDirSeps($_dir));
|
83 |
-
}
|
84 |
-
}
|
85 |
-
unset($_key, $_dir); // Housekeeping.
|
86 |
-
|
87 |
-
return ($dir = '');
|
88 |
-
};
|
89 |
-
|
90 |
-
/*
|
91 |
-
* Finds absolute server path to `/wp-config.php` file.
|
92 |
-
*
|
93 |
-
* @since 150422 Rewrite.
|
94 |
-
*
|
95 |
-
* @return string Absolute server path to `/wp-config.php` file;
|
96 |
-
* else an empty string if unable to locate the file.
|
97 |
-
*/
|
98 |
-
$self->findWpConfigFile = function () use ($self) {
|
99 |
-
if (!is_null($file = &$self->staticKey('findWpConfigFile'))) {
|
100 |
-
return $file; // Already cached this.
|
101 |
-
}
|
102 |
-
$file = ''; // Initialize.
|
103 |
-
|
104 |
-
if (is_file($abspath_wp_config = ABSPATH.'wp-config.php')) {
|
105 |
-
$file = $abspath_wp_config;
|
106 |
-
} elseif (is_file($dirname_abspath_wp_config = dirname(ABSPATH).'/wp-config.php')) {
|
107 |
-
$file = $dirname_abspath_wp_config;
|
108 |
-
}
|
109 |
-
return $file;
|
110 |
-
};
|
111 |
-
|
112 |
-
/*
|
113 |
-
* Adds a tmp name suffix to a directory/file path.
|
114 |
-
*
|
115 |
-
* @since 150422 Rewrite.
|
116 |
-
*
|
117 |
-
* @param string $dir_file An input directory or file path.
|
118 |
-
*
|
119 |
-
* @return string The original `$dir_file` with a tmp name suffix.
|
120 |
-
*/
|
121 |
-
$self->addTmpSuffix = function ($dir_file) use ($self) {
|
122 |
-
$dir_file = (string) $dir_file;
|
123 |
-
$dir_file = rtrim($dir_file, DIRECTORY_SEPARATOR.'\\/');
|
124 |
-
|
125 |
-
return $dir_file.'-'.str_replace('.', '', uniqid('', true)).'-tmp';
|
126 |
-
};
|
127 |
-
|
128 |
-
/*
|
129 |
-
* Recursive directory iterator based on a regex pattern.
|
130 |
-
*
|
131 |
-
* @since 150422 Rewrite.
|
132 |
-
*
|
133 |
-
* @param string $dir An absolute server directory path.
|
134 |
-
* @param string $regex A regex pattern; compares to each full file path.
|
135 |
-
*
|
136 |
-
* @return \RegexIterator Navigable with {@link \foreach()}; where each item
|
137 |
-
* is a {@link \RecursiveDirectoryIterator}.
|
138 |
-
*/
|
139 |
-
$self->dirRegexIteration = function ($dir, $regex = '') use ($self) {
|
140 |
-
$dir = (string) $dir;
|
141 |
-
$regex = (string) $regex;
|
142 |
-
|
143 |
-
$dir_iterator = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_SELF | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS);
|
144 |
-
$iterator_iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::CHILD_FIRST);
|
145 |
-
|
146 |
-
if ($regex && $regex !== '/.*/' && $regex !== '/.+/') { // Apply regex filter?
|
147 |
-
// @TODO Optimize calls to this method in order to avoid the regex iterator when not necessary.
|
148 |
-
return new \RegexIterator($iterator_iterator, $regex, \RegexIterator::MATCH, \RegexIterator::USE_KEY);
|
149 |
-
}
|
150 |
-
return $iterator_iterator; // Iterate everything.
|
151 |
-
};
|
152 |
-
|
153 |
-
/*
|
154 |
-
* Abbreviated byte notation for file sizes.
|
155 |
-
*
|
156 |
-
* @since 151002 Adding a few statistics.
|
157 |
-
*
|
158 |
-
* @param float $bytes File size in bytes. A (float) value.
|
159 |
-
* @param integer $precision Number of decimals to use.
|
160 |
-
*
|
161 |
-
* @return string Byte notation.
|
162 |
-
*/
|
163 |
-
$self->bytesAbbr = function ($bytes, $precision = 2) use ($self) {
|
164 |
-
$bytes = max(0.0, (float) $bytes);
|
165 |
-
$precision = max(0, (integer) $precision);
|
166 |
-
$units = array('bytes', 'kbs', 'MB', 'GB', 'TB');
|
167 |
-
|
168 |
-
$power = floor(($bytes ? log($bytes) : 0) / log(1024));
|
169 |
-
$abbr_bytes = round($bytes / pow(1024, $power), $precision);
|
170 |
-
$abbr = $units[min($power, count($units) - 1)];
|
171 |
-
|
172 |
-
if ($abbr_bytes === (float) 1 && $abbr === 'bytes') {
|
173 |
-
$abbr = 'byte'; // Quick fix.
|
174 |
-
} elseif ($abbr_bytes === (float) 1 && $abbr === 'kbs') {
|
175 |
-
$abbr = 'kb'; // Quick fix.
|
176 |
-
}
|
177 |
-
return $abbr_bytes.' '.$abbr;
|
178 |
-
};
|
179 |
-
|
180 |
-
/*
|
181 |
-
* Converts an abbreviated byte notation into bytes.
|
182 |
-
*
|
183 |
-
* @since 151002 Adding a few statistics.
|
184 |
-
*
|
185 |
-
* @param string $string A string value in byte notation.
|
186 |
-
*
|
187 |
-
* @return float A float indicating the number of bytes.
|
188 |
-
*/
|
189 |
-
$self->abbrBytes = function ($string) use ($self) {
|
190 |
-
$string = (string) $string;
|
191 |
-
$regex = '/^(?P<value>[0-9\.]+)\s*(?P<modifier>bytes|byte|kbs|kb|k|mb|m|gb|g|tb|t)$/i';
|
192 |
-
|
193 |
-
if (!preg_match($regex, $string, $_m)) {
|
194 |
-
return (float) 0;
|
195 |
-
}
|
196 |
-
$value = (float) $_m['value'];
|
197 |
-
$modifier = strtolower($_m['modifier']);
|
198 |
-
unset($_m); // Housekeeping.
|
199 |
-
|
200 |
-
switch ($modifier) {
|
201 |
-
case 't':
|
202 |
-
case 'tb':
|
203 |
-
$value *= 1024;
|
204 |
-
// Fall through.
|
205 |
-
case 'g':
|
206 |
-
case 'gb':
|
207 |
-
$value *= 1024;
|
208 |
-
// Fall through.
|
209 |
-
case 'm':
|
210 |
-
case 'mb':
|
211 |
-
$value *= 1024;
|
212 |
-
// Fall through.
|
213 |
-
case 'k':
|
214 |
-
case 'kb':
|
215 |
-
case 'kbs':
|
216 |
-
$value *= 1024;
|
217 |
-
}
|
218 |
-
return (float) $value;
|
219 |
-
};
|
220 |
-
|
221 |
-
/*
|
222 |
-
* Directory stats.
|
223 |
-
*
|
224 |
-
* @since 151002 Adding a few statistics.
|
225 |
-
*
|
226 |
-
* @param string $dir An absolute server directory path.
|
227 |
-
* @param string $regex A regex pattern; compares to each full file path.
|
228 |
-
* @param boolean $include_paths Include array of all scanned file paths?
|
229 |
-
* @param boolean $check_disk Also check disk statistics?
|
230 |
-
* @param boolean $no_cache Do not read/write cache?
|
231 |
-
*
|
232 |
-
* @return array Directory stats.
|
233 |
-
*/
|
234 |
-
$self->getDirRegexStats = function ($dir, $regex = '', $include_paths = false, $check_disk = true, $no_cache = false) use ($self) {
|
235 |
-
$dir = (string) $dir; // Force string.
|
236 |
-
$cache_keys = array($dir, $regex, $include_paths, $check_disk);
|
237 |
-
if (!$no_cache && !is_null($stats = &$self->staticKey('getDirRegexStats', $cache_keys))) {
|
238 |
-
return $stats; // Already cached this.
|
239 |
-
}
|
240 |
-
$stats = array(
|
241 |
-
'total_size' => 0,
|
242 |
-
'total_resources' => 0,
|
243 |
-
'total_links_files' => 0,
|
244 |
-
|
245 |
-
'total_links' => 0,
|
246 |
-
'link_subpaths' => array(),
|
247 |
-
|
248 |
-
'total_files' => 0,
|
249 |
-
'file_subpaths' => array(),
|
250 |
-
|
251 |
-
'total_dirs' => 0,
|
252 |
-
'dir_subpaths' => array(),
|
253 |
-
|
254 |
-
'disk_total_space' => 0,
|
255 |
-
'disk_free_space' => 0,
|
256 |
-
);
|
257 |
-
if (!$dir || !is_dir($dir)) {
|
258 |
-
return $stats; // Not possible.
|
259 |
-
}
|
260 |
-
$short_name_lc = strtolower(SHORT_NAME); // Once only.
|
261 |
-
|
262 |
-
foreach ($self->dirRegexIteration($dir, $regex) as $_resource) {
|
263 |
-
$_resource_sub_path = $_resource->getSubpathname();
|
264 |
-
$_resource_basename = basename($_resource_sub_path);
|
265 |
-
|
266 |
-
if ($_resource_basename === '.DS_Store') {
|
267 |
-
continue; // Ignore `.htaccess`.
|
268 |
-
}
|
269 |
-
if ($_resource_basename === '.htaccess') {
|
270 |
-
continue; // Ignore `.htaccess`.
|
271 |
-
}
|
272 |
-
if (stripos($_resource_sub_path, $short_name_lc.'-') === 0) {
|
273 |
-
continue; // Ignore [SHORT_NAME] files in base.
|
274 |
-
}
|
275 |
-
switch ($_resource->getType()) { // `link`, `file`, `dir`.
|
276 |
-
case 'link':
|
277 |
-
if ($include_paths) {
|
278 |
-
$stats['link_subpaths'][] = $_sub_path;
|
279 |
-
}
|
280 |
-
++$stats['total_resources'];
|
281 |
-
++$stats['total_links_files'];
|
282 |
-
++$stats['total_links'];
|
283 |
-
|
284 |
-
break; // Break switch.
|
285 |
-
|
286 |
-
case 'file':
|
287 |
-
if ($include_paths) {
|
288 |
-
$stats['file_subpaths'][] = $_sub_path;
|
289 |
-
}
|
290 |
-
$stats['total_size'] += $_resource->getSize();
|
291 |
-
++$stats['total_resources'];
|
292 |
-
++$stats['total_links_files'];
|
293 |
-
++$stats['total_files'];
|
294 |
-
|
295 |
-
break; // Break switch.
|
296 |
-
|
297 |
-
case 'dir':
|
298 |
-
if ($include_paths) {
|
299 |
-
$stats['dir_subpaths'][] = $_sub_path;
|
300 |
-
}
|
301 |
-
++$stats['total_resources'];
|
302 |
-
++$stats['total_dirs'];
|
303 |
-
|
304 |
-
break; // Break switch.
|
305 |
-
}
|
306 |
-
}
|
307 |
-
unset($_resource, $_resource_sub_path, $_resource_basename); // Housekeeping.
|
308 |
-
|
309 |
-
if ($check_disk) { // Check disk also?
|
310 |
-
$stats['disk_total_space'] = disk_total_space($dir);
|
311 |
-
$stats['disk_free_space'] = disk_free_space($dir);
|
312 |
-
}
|
313 |
-
return $stats;
|
314 |
-
};
|
315 |
-
|
316 |
-
/*
|
317 |
-
* Apache `.htaccess` rules that deny public access to the contents of a directory.
|
318 |
-
*
|
319 |
-
* @since 150422 Rewrite.
|
320 |
-
*
|
321 |
-
* @var string `.htaccess` fules.
|
322 |
-
*/
|
323 |
-
$self->htaccess_deny = "<IfModule authz_core_module>\n\tRequire all denied\n</IfModule>\n<IfModule !authz_core_module>\n\tdeny from all\n</IfModule>";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/HookUtils.php
DELETED
@@ -1,249 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Array of hooks.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @type array An array of hooks.
|
10 |
-
*/
|
11 |
-
$self->hooks = array();
|
12 |
-
|
13 |
-
/*
|
14 |
-
* Assigns an ID to each callable attached to a hook/filter.
|
15 |
-
*
|
16 |
-
* @since 150422 Rewrite.
|
17 |
-
*
|
18 |
-
* @param string|callable|mixed $function A string or a callable.
|
19 |
-
*
|
20 |
-
* @return string Hook ID for the given `$function`.
|
21 |
-
*
|
22 |
-
* @throws \Exception If the hook/function is invalid (i.e. it's not possible to generate an ID).
|
23 |
-
*/
|
24 |
-
$self->hookId = function ($function) use ($self) {
|
25 |
-
if (is_string($function)) {
|
26 |
-
return $function;
|
27 |
-
}
|
28 |
-
if (is_object($function)) {
|
29 |
-
$function = array($function, '');
|
30 |
-
} else {
|
31 |
-
$function = (array) $function;
|
32 |
-
}
|
33 |
-
if (isset($function[0], $function[1])) {
|
34 |
-
if (is_object($function[0])) {
|
35 |
-
return spl_object_hash($function[0]).$function[1];
|
36 |
-
} elseif (is_string($function[0])) {
|
37 |
-
return $function[0].'::'.$function[1];
|
38 |
-
}
|
39 |
-
}
|
40 |
-
throw new \Exception(__('Invalid hook.', 'comet-cache'));
|
41 |
-
};
|
42 |
-
|
43 |
-
/*
|
44 |
-
* Adds a new hook (works with both actions & filters).
|
45 |
-
*
|
46 |
-
* @since 150422 Rewrite.
|
47 |
-
*
|
48 |
-
* @param string $hook The name of a hook to attach to.
|
49 |
-
* @param string|callable|mixed $function A string or a callable.
|
50 |
-
* @param integer $priority Hook priority; defaults to `10`.
|
51 |
-
* @param integer $accepted_args Max number of args that should be passed to the `$function`.
|
52 |
-
*
|
53 |
-
* @return boolean This always returns a `TRUE` value.
|
54 |
-
*/
|
55 |
-
$self->addHook = function ($hook, $function, $priority = 10, $accepted_args = 1) use ($self) {
|
56 |
-
$hook = (string) $hook;
|
57 |
-
if (stripos($hook, 'zencache') === 0) {
|
58 |
-
$hook = GLOBAL_NS.substr($hook, strlen('zencache'));
|
59 |
-
}
|
60 |
-
$priority = (integer) $priority;
|
61 |
-
$accepted_args = max(0, (integer) $accepted_args);
|
62 |
-
$hook_id = $self->hookId($function);
|
63 |
-
|
64 |
-
$self->hooks[$hook][$priority][$hook_id] = array(
|
65 |
-
'function' => $function,
|
66 |
-
'accepted_args' => $accepted_args,
|
67 |
-
);
|
68 |
-
return true; // Always returns true.
|
69 |
-
};
|
70 |
-
|
71 |
-
/*
|
72 |
-
* Adds a new action hook.
|
73 |
-
*
|
74 |
-
* @since 150422 Rewrite.
|
75 |
-
*
|
76 |
-
* @return boolean This always returns a `TRUE` value.
|
77 |
-
*/
|
78 |
-
$self->addAction = function () use ($self) {
|
79 |
-
return call_user_func_array(array($self, 'addHook'), func_get_args());
|
80 |
-
};
|
81 |
-
$self->add_action = $self->addAction; // Back compat.
|
82 |
-
|
83 |
-
/*
|
84 |
-
* Adds a new filter.
|
85 |
-
*
|
86 |
-
* @since 150422 Rewrite.
|
87 |
-
*
|
88 |
-
* @return boolean This always returns a `TRUE` value.
|
89 |
-
*/
|
90 |
-
$self->addFilter = function () use ($self) {
|
91 |
-
return call_user_func_array(array($self, 'addHook'), func_get_args());
|
92 |
-
};
|
93 |
-
$self->add_filter = $self->addFilter; // Back compat.
|
94 |
-
|
95 |
-
/*
|
96 |
-
* Removes a hook (works with both actions & filters).
|
97 |
-
*
|
98 |
-
* @since 150422 Rewrite.
|
99 |
-
*
|
100 |
-
* @param string $hook The name of a hook to remove.
|
101 |
-
* @param string|callable|mixed $function A string or a callable.
|
102 |
-
* @param integer $priority Hook priority; defaults to `10`.
|
103 |
-
*
|
104 |
-
* @return boolean `TRUE` if removed; else `FALSE` if not removed for any reason.
|
105 |
-
*/
|
106 |
-
$self->removeHook = function ($hook, $function, $priority = 10) use ($self) {
|
107 |
-
$hook = (string) $hook;
|
108 |
-
if (stripos($hook, 'zencache') === 0) {
|
109 |
-
$hook = GLOBAL_NS.substr($hook, strlen('zencache'));
|
110 |
-
}
|
111 |
-
$priority = (integer) $priority;
|
112 |
-
$hook_id = $self->hookId($function);
|
113 |
-
|
114 |
-
if (!isset($self->hooks[$hook][$priority][$hook_id])) {
|
115 |
-
return false; // Nothing to remove.
|
116 |
-
}
|
117 |
-
unset($self->hooks[$hook][$priority][$hook_id]);
|
118 |
-
|
119 |
-
if (!$self->hooks[$hook][$priority]) {
|
120 |
-
unset($self->hooks[$hook][$priority]);
|
121 |
-
}
|
122 |
-
return true; // Existed before it was removed.
|
123 |
-
};
|
124 |
-
|
125 |
-
/*
|
126 |
-
* Removes an action.
|
127 |
-
*
|
128 |
-
* @since 150422 Rewrite.
|
129 |
-
*
|
130 |
-
* @return boolean `TRUE` if removed; else `FALSE` if not removed for any reason.
|
131 |
-
*/
|
132 |
-
$self->removeAction = function () use ($self) {
|
133 |
-
return call_user_func_array(array($self, 'removeHook'), func_get_args());
|
134 |
-
};
|
135 |
-
|
136 |
-
/*
|
137 |
-
* Removes a filter.
|
138 |
-
*
|
139 |
-
* @since 150422 Rewrite.
|
140 |
-
*
|
141 |
-
* @return boolean `TRUE` if removed; else `FALSE` if not removed for any reason.
|
142 |
-
*/
|
143 |
-
$self->removeFilter = function () use ($self) {
|
144 |
-
return call_user_func_array(array($self, 'removeHook'), func_get_args());
|
145 |
-
};
|
146 |
-
|
147 |
-
/*
|
148 |
-
* Runs any callables attached to an action.
|
149 |
-
*
|
150 |
-
* @since 150422 Rewrite.
|
151 |
-
*
|
152 |
-
* @param string $hook The name of an action hook.
|
153 |
-
*/
|
154 |
-
$self->doAction = function ($hook) use ($self) {
|
155 |
-
$hook = (string) $hook;
|
156 |
-
if (empty($self->hooks[$hook])) {
|
157 |
-
return; // No hooks.
|
158 |
-
}
|
159 |
-
$hook_actions = $self->hooks[$hook];
|
160 |
-
$args = func_get_args();
|
161 |
-
ksort($hook_actions);
|
162 |
-
|
163 |
-
foreach ($hook_actions as $_hook_action) {
|
164 |
-
foreach ($_hook_action as $_action) {
|
165 |
-
if (!isset($_action['function'], $_action['accepted_args'])) {
|
166 |
-
continue; // Not a valid filter in this case.
|
167 |
-
}
|
168 |
-
call_user_func_array($_action['function'], array_slice($args, 1, $_action['accepted_args']));
|
169 |
-
}
|
170 |
-
}
|
171 |
-
unset($_hook_action, $_action); // Housekeeping.
|
172 |
-
};
|
173 |
-
|
174 |
-
/*
|
175 |
-
* Runs any callables attached to a filter.
|
176 |
-
*
|
177 |
-
* @since 150422 Rewrite.
|
178 |
-
*
|
179 |
-
* @param string $hook The name of a filter hook.
|
180 |
-
* @param mixed $value The value to filter.
|
181 |
-
*
|
182 |
-
* @return mixed The filtered `$value`.
|
183 |
-
*/
|
184 |
-
$self->applyFilters = function ($hook, $value) use ($self) {
|
185 |
-
$hook = (string) $hook;
|
186 |
-
if (empty($self->hooks[$hook])) {
|
187 |
-
return $value; // No hooks.
|
188 |
-
}
|
189 |
-
$hook_filters = $self->hooks[$hook];
|
190 |
-
$args = func_get_args();
|
191 |
-
ksort($hook_filters);
|
192 |
-
|
193 |
-
foreach ($hook_filters as $_hook_filter) {
|
194 |
-
foreach ($_hook_filter as $_filter) {
|
195 |
-
if (!isset($_filter['function'], $_filter['accepted_args'])) {
|
196 |
-
continue; // Not a valid filter in this case.
|
197 |
-
}
|
198 |
-
$args[1] = $value; // Continously update the argument `$value`.
|
199 |
-
$value = call_user_func_array($_filter['function'], array_slice($args, 1, $_filter['accepted_args']));
|
200 |
-
}
|
201 |
-
}
|
202 |
-
unset($_hook_filter, $_filter); // Housekeeping.
|
203 |
-
|
204 |
-
return $value; // With applied filters.
|
205 |
-
};
|
206 |
-
|
207 |
-
/*
|
208 |
-
* Does an action w/ back compat. for ZenCache.
|
209 |
-
*
|
210 |
-
* @since 150422 Rewrite.
|
211 |
-
*
|
212 |
-
* @param string $hook The hook to apply.
|
213 |
-
*/
|
214 |
-
$self->doWpAction = function ($hook) use ($self) {
|
215 |
-
$hook = (string) $hook;
|
216 |
-
$args = func_get_args();
|
217 |
-
call_user_func_array('do_action', $args);
|
218 |
-
|
219 |
-
if (stripos($hook, GLOBAL_NS) === 0) {
|
220 |
-
$zencache_filter = 'zencache'.substr($hook, strlen(GLOBAL_NS));
|
221 |
-
$zencache_args = $args; // Use a copy of the args.
|
222 |
-
$zencache_args[0] = $zencache_filter;
|
223 |
-
call_user_func_array('do_action', $zencache_args);
|
224 |
-
}
|
225 |
-
};
|
226 |
-
|
227 |
-
/*
|
228 |
-
* Applies filters w/ back compat. for ZenCache.
|
229 |
-
*
|
230 |
-
* @since 150422 Rewrite.
|
231 |
-
*
|
232 |
-
* @param string $hook The hook to apply.
|
233 |
-
*
|
234 |
-
* @return mixed The filtered value.
|
235 |
-
*/
|
236 |
-
$self->applyWpFilters = function ($hook) use ($self) {
|
237 |
-
$hook = (string) $hook;
|
238 |
-
$args = func_get_args();
|
239 |
-
$value = call_user_func_array('apply_filters', $args);
|
240 |
-
|
241 |
-
if (stripos($hook, GLOBAL_NS) === 0) {
|
242 |
-
$zencache_hook = 'zencache'.substr($hook, strlen(GLOBAL_NS));
|
243 |
-
$zencache_args = $args; // Use a copy of the args.
|
244 |
-
$zencache_args[0] = $zencache_hook;
|
245 |
-
$zencache_args[1] = $value; // Filtered value.
|
246 |
-
$value = call_user_func_array('apply_filters', $zencache_args);
|
247 |
-
}
|
248 |
-
return $value; // Filtered value.
|
249 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/HttpUtils.php
DELETED
@@ -1,166 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Current HTTP protocol.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @return string Current HTTP protocol.
|
10 |
-
*/
|
11 |
-
$self->httpProtocol = function () use ($self) {
|
12 |
-
if (!is_null($protocol = &$self->staticKey('httpProtocol'))) {
|
13 |
-
return $protocol; // Already cached this.
|
14 |
-
}
|
15 |
-
if (!empty($_SERVER['SERVER_PROTOCOL']) && is_string($_SERVER['SERVER_PROTOCOL'])) {
|
16 |
-
$protocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
|
17 |
-
}
|
18 |
-
if (!$protocol || stripos($protocol, 'HTTP/') !== 0) {
|
19 |
-
$protocol = 'HTTP/1.0'; // Default value.
|
20 |
-
}
|
21 |
-
return $protocol;
|
22 |
-
};
|
23 |
-
|
24 |
-
/*
|
25 |
-
* PHP {@link headers_list()} + HTTP status.
|
26 |
-
*
|
27 |
-
* @since 150422 Rewrite.
|
28 |
-
*
|
29 |
-
* @return array PHP {@link headers_list()} + HTTP status.
|
30 |
-
*
|
31 |
-
* @warning Do NOT call until end of script execution.
|
32 |
-
*/
|
33 |
-
$self->headersList = function () use ($self) {
|
34 |
-
if (!is_null($headers = &$self->staticKey('headersList'))) {
|
35 |
-
return $headers; // Already cached this.
|
36 |
-
}
|
37 |
-
$headers = headers_list(); // Lacks status.
|
38 |
-
|
39 |
-
if (($status = (string) $self->httpStatus())) {
|
40 |
-
array_unshift($headers, $self->httpProtocol().' '.$status);
|
41 |
-
}
|
42 |
-
return $headers;
|
43 |
-
};
|
44 |
-
|
45 |
-
/*
|
46 |
-
* PHP {@link headers_list()} + HTTP status.
|
47 |
-
*
|
48 |
-
* @since 150422 Rewrite.
|
49 |
-
*
|
50 |
-
* @return array PHP {@link headers_list()} + HTTP status.
|
51 |
-
*
|
52 |
-
* @warning Do NOT call until end of script execution.
|
53 |
-
*/
|
54 |
-
$self->cacheableHeadersList = function () use ($self) {
|
55 |
-
if (!is_null($headers = &$self->staticKey('cacheableHeadersList'))) {
|
56 |
-
return $headers; // Already cached this.
|
57 |
-
}
|
58 |
-
$headers = headers_list(); // Lacks status.
|
59 |
-
|
60 |
-
$cacheable_headers = array(
|
61 |
-
'Access-Control-Allow-Origin',
|
62 |
-
'Accept-Ranges',
|
63 |
-
'Age',
|
64 |
-
'Allow',
|
65 |
-
'Cache-Control',
|
66 |
-
'Connection',
|
67 |
-
'Content-Encoding',
|
68 |
-
'Content-Language',
|
69 |
-
'Content-Length',
|
70 |
-
'Content-Location',
|
71 |
-
'Content-MD5',
|
72 |
-
'Content-Disposition',
|
73 |
-
'Content-Range',
|
74 |
-
'Content-Type',
|
75 |
-
'Date',
|
76 |
-
'ETag',
|
77 |
-
'Expires',
|
78 |
-
'Last-Modified',
|
79 |
-
'Link',
|
80 |
-
'Location',
|
81 |
-
'P3P',
|
82 |
-
'Pragma',
|
83 |
-
'Proxy-Authenticate',
|
84 |
-
'Refresh',
|
85 |
-
'Retry-After',
|
86 |
-
'Server',
|
87 |
-
'Status',
|
88 |
-
'Strict-Transport-Security',
|
89 |
-
'Trailer',
|
90 |
-
'Transfer-Encoding',
|
91 |
-
'Upgrade',
|
92 |
-
'Vary',
|
93 |
-
'Via',
|
94 |
-
'Warning',
|
95 |
-
'WWW-Authenticate',
|
96 |
-
'X-Frame-Options',
|
97 |
-
'Public-Key-Pins',
|
98 |
-
'X-XSS-Protection',
|
99 |
-
'Content-Security-Policy',
|
100 |
-
'X-Content-Security-Policy',
|
101 |
-
'X-WebKit-CSP',
|
102 |
-
'X-Content-Type-Options',
|
103 |
-
'X-Powered-By',
|
104 |
-
'X-UA-Compatible',
|
105 |
-
);
|
106 |
-
$cacheable_headers = array_map('strtolower', $cacheable_headers);
|
107 |
-
|
108 |
-
foreach ($headers as $_key => $_header) {
|
109 |
-
$_header = strtolower((string) strstr($_header, ':', true));
|
110 |
-
if (!$_header || !in_array($_header, $cacheable_headers, true)) {
|
111 |
-
unset($headers[$_key]);
|
112 |
-
}
|
113 |
-
}
|
114 |
-
unset($_key, $_header); // Housekeeping.
|
115 |
-
|
116 |
-
if (($status = (string) $self->httpStatus())) {
|
117 |
-
array_unshift($headers, $self->httpProtocol().' '.$status);
|
118 |
-
}
|
119 |
-
return $headers;
|
120 |
-
};
|
121 |
-
|
122 |
-
/*
|
123 |
-
* HTTP status code.
|
124 |
-
*
|
125 |
-
* @since 150422 Rewrite.
|
126 |
-
*
|
127 |
-
* @return integer HTTP status code.
|
128 |
-
*
|
129 |
-
* @warning Do NOT call until end of script execution.
|
130 |
-
*
|
131 |
-
* @note Automatically updates HTTP status-related flags.
|
132 |
-
*/
|
133 |
-
$self->httpStatus = function () use ($self) {
|
134 |
-
if (!is_null($status = &$self->staticKey('httpStatus'))) {
|
135 |
-
return $status; // Already cached this.
|
136 |
-
}
|
137 |
-
$status = 0; // Initialize.
|
138 |
-
$has_property_is_404 = property_exists($self, 'is_404');
|
139 |
-
$has_property_http_status = property_exists($self, 'http_status');
|
140 |
-
|
141 |
-
if ($has_property_is_404 && $self->{'is_404'}) {
|
142 |
-
$status = 404; // WordPress said so.
|
143 |
-
} elseif ($self->functionIsPossible('http_response_code') && ($code = (integer) http_response_code())) {
|
144 |
-
$status = (integer) $code; // {@link \http_response_code()} available since PHP v5.4.
|
145 |
-
} elseif ($has_property_http_status && (integer) $self->{'http_status'}) {
|
146 |
-
$status = (integer) $self->{'http_status'}; // {@link \status_header()} filter.
|
147 |
-
}
|
148 |
-
if ($status && $has_property_http_status) {
|
149 |
-
$self->{'http_status'} = $status; // Prefer over {@link status_header()}.
|
150 |
-
}
|
151 |
-
if ($status === 404 && $has_property_is_404) {
|
152 |
-
$self->{'is_404'} = true; // Prefer over {@link is_404()}.
|
153 |
-
}
|
154 |
-
return $status;
|
155 |
-
};
|
156 |
-
/*
|
157 |
-
* Sends no-cache headers.
|
158 |
-
*
|
159 |
-
* @since 151220 Enhancing no-cache headers.
|
160 |
-
*/
|
161 |
-
$self->sendNoCacheHeaders = function() use($self) {
|
162 |
-
header_remove('Last-Modified');
|
163 |
-
header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
|
164 |
-
header('Cache-Control: no-cache, must-revalidate, max-age=0');
|
165 |
-
header('Pragma: no-cache');
|
166 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/I18nUtils.php
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* `X file` or `X files`, translated w/ singlular/plural context.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param integer $counter Total files; i.e. the counter.
|
10 |
-
*
|
11 |
-
* @return string The phrase `X file` or `X files`.
|
12 |
-
*/
|
13 |
-
$self->i18nFiles = function ($counter) use ($self) {
|
14 |
-
$counter = (integer) $counter;
|
15 |
-
return sprintf(_n('%1$s file', '%1$s files', $counter, 'comet-cache'), $counter);
|
16 |
-
};
|
17 |
-
|
18 |
-
/*
|
19 |
-
* `X directory` or `X directories`, translated w/ singlular/plural context.
|
20 |
-
*
|
21 |
-
* @since 150422 Rewrite.
|
22 |
-
*
|
23 |
-
* @param integer $counter Total directories; i.e. the counter.
|
24 |
-
*
|
25 |
-
* @return string The phrase `X directory` or `X directories`.
|
26 |
-
*/
|
27 |
-
$self->i18nDirs = function ($counter) use ($self) {
|
28 |
-
$counter = (integer) $counter;
|
29 |
-
return sprintf(_n('%1$s directory', '%1$s directories', $counter, 'comet-cache'), $counter);
|
30 |
-
};
|
31 |
-
|
32 |
-
/*
|
33 |
-
* `X file/directory` or `X files/directories`, translated w/ singlular/plural context.
|
34 |
-
*
|
35 |
-
* @since 150422 Rewrite.
|
36 |
-
*
|
37 |
-
* @param integer $counter Total files/directories; i.e. the counter.
|
38 |
-
*
|
39 |
-
* @return string The phrase `X file/directory` or `X files/directories`.
|
40 |
-
*/
|
41 |
-
$self->i18nFilesDirs = function ($counter) use ($self) {
|
42 |
-
$counter = (integer) $counter;
|
43 |
-
return sprintf(_n('%1$s file/directory', '%1$s files/directories', $counter, 'comet-cache'), $counter);
|
44 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/IpAddrUtils.php
DELETED
@@ -1,83 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Get the current visitor's real IP address.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @return string Real IP address, else `unknown` on failure.
|
10 |
-
*
|
11 |
-
* @note This supports both IPv4 and IPv6 addresses.
|
12 |
-
* @note See my tests against this here: http://3v4l.org/fVWUp
|
13 |
-
*/
|
14 |
-
$self->currentIp = function () use ($self) {
|
15 |
-
if (!is_null($ip = &$self->staticKey('currentIp'))) {
|
16 |
-
return $ip; // Already cached this.
|
17 |
-
}
|
18 |
-
$sources = array(
|
19 |
-
'HTTP_CF_CONNECTING_IP',
|
20 |
-
'HTTP_CLIENT_IP',
|
21 |
-
'HTTP_X_FORWARDED_FOR',
|
22 |
-
'HTTP_X_FORWARDED',
|
23 |
-
'HTTP_X_CLUSTER_CLIENT_IP',
|
24 |
-
'HTTP_FORWARDED_FOR',
|
25 |
-
'HTTP_FORWARDED',
|
26 |
-
'HTTP_VIA',
|
27 |
-
'REMOTE_ADDR',
|
28 |
-
);
|
29 |
-
$sources = $self->applyFilters(GLOBAL_NS.'\\share::current_ip_sources', $sources);
|
30 |
-
$sources = $self->applyFilters(GLOBAL_NS.'_current_ip_sources', $sources);
|
31 |
-
|
32 |
-
$prioritize_remote_addr = false; // Off by default; can be filtered however.
|
33 |
-
$prioritize_remote_addr = $self->applyFilters(GLOBAL_NS.'\\share::current_ip_prioritize_remote_addr', $prioritize_remote_addr);
|
34 |
-
$prioritize_remote_addr = $self->applyFilters(GLOBAL_NS.'_current_ip_prioritize_remote_addr', $prioritize_remote_addr);
|
35 |
-
|
36 |
-
if (!empty($_SERVER['REMOTE_ADDR']) && $prioritize_remote_addr) {
|
37 |
-
if (($_valid_public_ip = $self->validPublicIp((string) $_SERVER['REMOTE_ADDR']))) {
|
38 |
-
return ($ip = $_valid_public_ip);
|
39 |
-
}
|
40 |
-
unset($_valid_public_ip); // Housekeeping.
|
41 |
-
}
|
42 |
-
foreach ($sources as $_key => $_source) {
|
43 |
-
if (!empty($_SERVER[$_source])) {
|
44 |
-
if (($_valid_public_ip = $self->validPublicIp((string) $_SERVER[$_source]))) {
|
45 |
-
return ($ip = $_valid_public_ip);
|
46 |
-
}
|
47 |
-
}
|
48 |
-
unset($_key, $_source, $_valid_public_ip); // Housekeeping.
|
49 |
-
}
|
50 |
-
if (!empty($_SERVER['REMOTE_ADDR'])) {
|
51 |
-
return ($ip = strtolower((string) $_SERVER['REMOTE_ADDR']));
|
52 |
-
}
|
53 |
-
return ($ip = 'unknown'); // Not possible.
|
54 |
-
};
|
55 |
-
|
56 |
-
/*
|
57 |
-
* Gets a valid/public IP address.
|
58 |
-
*
|
59 |
-
* @since 150422 Rewrite.
|
60 |
-
*
|
61 |
-
* @param string $list_of_possible_ips A single IP, or a comma-delimited list of IPs.
|
62 |
-
*
|
63 |
-
* @return string A valid/public IP address (if one is found), else an empty string.
|
64 |
-
*
|
65 |
-
* @note This supports both IPv4 and IPv6 addresses.
|
66 |
-
* @note See my tests against this here: http://3v4l.org/fVWUp
|
67 |
-
*/
|
68 |
-
$self->validPublicIp = function ($list_of_possible_ips) use ($self) {
|
69 |
-
if (!$list_of_possible_ips || !is_string($list_of_possible_ips)) {
|
70 |
-
return ''; // Empty or invalid data.
|
71 |
-
}
|
72 |
-
if (!($list_of_possible_ips = trim($list_of_possible_ips))) {
|
73 |
-
return ''; // Not possible; i.e., empty string.
|
74 |
-
}
|
75 |
-
foreach (preg_split('/[\s;,]+/', $list_of_possible_ips, -1, PREG_SPLIT_NO_EMPTY) as $_key => $_possible_ip) {
|
76 |
-
if (($_valid_public_ip = filter_var(strtolower($_possible_ip), FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))) {
|
77 |
-
return $_valid_public_ip; // A valid public IPv4 or IPv6 address.
|
78 |
-
}
|
79 |
-
}
|
80 |
-
unset($_key, $_possible_ip, $_valid_public_ip); // Housekeeping.
|
81 |
-
|
82 |
-
return ''; // Default return value.
|
83 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/PatternUtils.php
DELETED
@@ -1,48 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Convert line-delimited patterns to a regex.
|
6 |
-
*
|
7 |
-
* @since 151114 Enhancing exclusion pattern support.
|
8 |
-
*
|
9 |
-
* @param string $patterns Line-delimited list of patterns.
|
10 |
-
*
|
11 |
-
* @return string A `/(?:list|of|regex)/i` patterns.
|
12 |
-
*/
|
13 |
-
$self->lineDelimitedPatternsToRegex = function ($patterns) use ($self) {
|
14 |
-
$regex = ''; // Initialize list of regex patterns.
|
15 |
-
$patterns = (string) $patterns;
|
16 |
-
|
17 |
-
if (($patterns = preg_split('/['."\r\n".']+/', $patterns, -1, PREG_SPLIT_NO_EMPTY))) {
|
18 |
-
$regex = '/(?:'.implode('|', array_map($self->wdRegexToActualRegexFrag, $patterns)).')/i';
|
19 |
-
}
|
20 |
-
return $regex;
|
21 |
-
};
|
22 |
-
|
23 |
-
/*
|
24 |
-
* Convert watered-down regex to actual regex.
|
25 |
-
*
|
26 |
-
* @since 151114 Enhancing exclusion pattern support.
|
27 |
-
*
|
28 |
-
* @param string $string Input watered-down regex to convert.
|
29 |
-
*
|
30 |
-
* @return string Actual regex pattern after conversion.
|
31 |
-
*/
|
32 |
-
$self->wdRegexToActualRegexFrag = function ($string) use ($self) {
|
33 |
-
return preg_replace(
|
34 |
-
array(
|
35 |
-
'/\\\\\^/',
|
36 |
-
'/\\\\\*\\\\\*/',
|
37 |
-
'/\\\\\*/',
|
38 |
-
'/\\\\\$/',
|
39 |
-
),
|
40 |
-
array(
|
41 |
-
'^', // Beginning of line.
|
42 |
-
'.*?', // Zero or more chars.
|
43 |
-
'[^\/]*?', // Zero or more chars != /.
|
44 |
-
'$', // End of line.
|
45 |
-
),
|
46 |
-
preg_quote((string) $string, '/')
|
47 |
-
);
|
48 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/ReplaceUtils.php
DELETED
@@ -1,43 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* String replace ONE time.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param string $needle A string to search/replace.
|
10 |
-
* @param string $replace What to replace `$needle` with.
|
11 |
-
* @param string $haystack The string/haystack to search in.
|
12 |
-
*
|
13 |
-
* @param boolean $caSe_insensitive Defaults to a `FALSE` value.
|
14 |
-
* Pass this as `TRUE` to a caSe-insensitive search/replace.
|
15 |
-
*
|
16 |
-
* @return string The `$haystack`, with `$needle` replaced with `$replace` ONE time only.
|
17 |
-
*/
|
18 |
-
$self->strReplaceOnce = function ($needle, $replace, $haystack, $caSe_insensitive = false) use ($self) {
|
19 |
-
$needle = (string) $needle;
|
20 |
-
$replace = (string) $replace;
|
21 |
-
$haystack = (string) $haystack;
|
22 |
-
$caSe_strpos = $caSe_insensitive ? 'stripos' : 'strpos';
|
23 |
-
|
24 |
-
if (($needle_strpos = $caSe_strpos($haystack, $needle)) === false) {
|
25 |
-
return $haystack; // Nothing to replace.
|
26 |
-
}
|
27 |
-
return (string) substr_replace($haystack, $replace, $needle_strpos, strlen($needle));
|
28 |
-
};
|
29 |
-
|
30 |
-
/*
|
31 |
-
* String replace ONE time (caSe-insensitive).
|
32 |
-
*
|
33 |
-
* @since 150422 Rewrite.
|
34 |
-
*
|
35 |
-
* @param string $needle A string to search/replace.
|
36 |
-
* @param string $replace What to replace `$needle` with.
|
37 |
-
* @param string $haystack The string/haystack to search in.
|
38 |
-
*
|
39 |
-
* @return string The `$haystack`, with `$needle` replaced with `$replace` ONE time only.
|
40 |
-
*/
|
41 |
-
$self->strIreplaceOnce = function ($needle, $replace, $haystack) use ($self) {
|
42 |
-
return $self->strReplaceOnce($needle, $replace, $haystack, true);
|
43 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/ServerUtils.php
DELETED
@@ -1,65 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Is running on Apache?
|
6 |
-
*
|
7 |
-
* @since 151002 This is Apache?
|
8 |
-
*
|
9 |
-
* @return bool True if running Apache.
|
10 |
-
*/
|
11 |
-
$self->isApache = function () use ($self) {
|
12 |
-
if (!is_null($is = &$self->staticKey('isApache'))) {
|
13 |
-
return $is; // Already cached this.
|
14 |
-
}
|
15 |
-
if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
|
16 |
-
if (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false) {
|
17 |
-
return ($is = true);
|
18 |
-
}
|
19 |
-
if (stripos($_SERVER['SERVER_SOFTWARE'], 'litespeed') !== false) {
|
20 |
-
return ($is = true);
|
21 |
-
}
|
22 |
-
}
|
23 |
-
return ($is = false);
|
24 |
-
};
|
25 |
-
|
26 |
-
/*
|
27 |
-
* Is running on Nginx?
|
28 |
-
*
|
29 |
-
* @since 151002 This is Nginx?
|
30 |
-
*
|
31 |
-
* @return bool True if running Nginx.
|
32 |
-
*/
|
33 |
-
$self->isNginx = function () use ($self) {
|
34 |
-
if (!is_null($is = &$self->staticKey('isNginx'))) {
|
35 |
-
return $is; // Already cached this.
|
36 |
-
}
|
37 |
-
if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
|
38 |
-
if (stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false) {
|
39 |
-
return ($is = true);
|
40 |
-
}
|
41 |
-
}
|
42 |
-
return ($is = false);
|
43 |
-
};
|
44 |
-
|
45 |
-
/*
|
46 |
-
* Is running on Windows IIS?
|
47 |
-
*
|
48 |
-
* @since 151002 This is Windows IIS?
|
49 |
-
*
|
50 |
-
* @return bool True if running Windows IIS.
|
51 |
-
*/
|
52 |
-
$self->isIis = function () use ($self) {
|
53 |
-
if (!is_null($is = &$self->staticKey('isIis'))) {
|
54 |
-
return $is; // Already cached this.
|
55 |
-
}
|
56 |
-
if (!empty($_SERVER['SERVER_SOFTWARE']) && is_string($_SERVER['SERVER_SOFTWARE'])) {
|
57 |
-
if (stripos($_SERVER['SERVER_SOFTWARE'], 'microsoft-iis') !== false) {
|
58 |
-
return ($is = true);
|
59 |
-
}
|
60 |
-
if (stripos($_SERVER['SERVER_SOFTWARE'], 'expressiondevserver') !== false) {
|
61 |
-
return ($is = true);
|
62 |
-
}
|
63 |
-
}
|
64 |
-
return ($is = false);
|
65 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/StringUtils.php
DELETED
@@ -1,87 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Clips string(s) to X chars deeply.
|
6 |
-
*
|
7 |
-
* @since 151114 Adding string utils.
|
8 |
-
*
|
9 |
-
* @param mixed $value Any input value.
|
10 |
-
* @param int $max_length Defaults to a value of `80`.
|
11 |
-
* @param bool $force_ellipsis Defaults to a value of `FALSE`.
|
12 |
-
*
|
13 |
-
* @return string|array|object Clipped value.
|
14 |
-
*/
|
15 |
-
$self->clip = function ($value, $max_length = 80, $force_ellipsis = false) use ($self) {
|
16 |
-
if (is_array($value) || is_object($value)) {
|
17 |
-
foreach ($value as $_key => &$_value) {
|
18 |
-
$_value = $self->clip($_value, $max_length, $force_ellipsis);
|
19 |
-
}
|
20 |
-
unset($_key, $_value); // Housekeeping.
|
21 |
-
|
22 |
-
return $value;
|
23 |
-
}
|
24 |
-
if (!($string = (string) $value)) {
|
25 |
-
return $string; // Empty.
|
26 |
-
}
|
27 |
-
$max_length = max(4, $max_length);
|
28 |
-
|
29 |
-
$string = strip_tags($string);
|
30 |
-
$string = preg_replace('/\s+/', ' ', strip_tags($string));
|
31 |
-
$string = trim($string); // Trim it up now.
|
32 |
-
|
33 |
-
if (strlen($string) > $max_length) {
|
34 |
-
$string = (string) substr($string, 0, $max_length - 3).'...';
|
35 |
-
} elseif ($force_ellipsis && strlen($string) + 3 > $max_length) {
|
36 |
-
$string = (string) substr($string, 0, $max_length - 3).'...';
|
37 |
-
} else {
|
38 |
-
$string .= $force_ellipsis ? '...' : '';
|
39 |
-
}
|
40 |
-
return $string;
|
41 |
-
};
|
42 |
-
|
43 |
-
/*
|
44 |
-
* Mid-clips string(s) to X chars deeply.
|
45 |
-
*
|
46 |
-
* @since 151114 Adding string utils.
|
47 |
-
*
|
48 |
-
* @param mixed $value Any input value.
|
49 |
-
* @param int $max_length Defaults to a value of `80`.
|
50 |
-
*
|
51 |
-
* @return string|array|object Mid-clipped value.
|
52 |
-
*/
|
53 |
-
$self->midClip = function ($value, $max_length = 80) use ($self) {
|
54 |
-
if (is_array($value) || is_object($value)) {
|
55 |
-
foreach ($value as $_key => &$_value) {
|
56 |
-
$_value = $self->midClip($_value, $max_length);
|
57 |
-
}
|
58 |
-
unset($_key, $_value); // Housekeeping.
|
59 |
-
|
60 |
-
return $value;
|
61 |
-
}
|
62 |
-
if (!($string = (string) $value)) {
|
63 |
-
return $string; // Empty.
|
64 |
-
}
|
65 |
-
$max_length = max(4, $max_length);
|
66 |
-
|
67 |
-
$string = strip_tags($string);
|
68 |
-
$string = preg_replace('/\s+/', ' ', strip_tags($string));
|
69 |
-
$string = trim($string); // Trim it up now.
|
70 |
-
|
71 |
-
if (strlen($string) <= $max_length) {
|
72 |
-
return $string; // Nothing to do.
|
73 |
-
}
|
74 |
-
$full_string = $string;
|
75 |
-
$half_max_length = floor($max_length / 2);
|
76 |
-
|
77 |
-
$first_clip = $half_max_length - 3;
|
78 |
-
$string = $first_clip >= 1 // Something?
|
79 |
-
? substr($full_string, 0, $first_clip).'...'
|
80 |
-
: '...'; // Ellipsis only.
|
81 |
-
|
82 |
-
$second_clip = strlen($full_string) - ($max_length - strlen($string));
|
83 |
-
$string .= $second_clip >= 0 && $second_clip >= $first_clip
|
84 |
-
? substr($full_string, $second_clip) : '';
|
85 |
-
|
86 |
-
return $string;
|
87 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/SysUtils.php
DELETED
@@ -1,92 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* System load averages.
|
6 |
-
*
|
7 |
-
* @since 151002 Adding cache directory statistics.
|
8 |
-
*
|
9 |
-
* @return array System load averages.
|
10 |
-
*/
|
11 |
-
$self->sysLoadAverages = function () use ($self) {
|
12 |
-
if (!is_null($averages = &$self->cacheKey('sysLoadAverages'))) {
|
13 |
-
return $averages; // Already cached these.
|
14 |
-
}
|
15 |
-
if (!$self->functionIsPossible('sys_getloadavg')) {
|
16 |
-
return ($averages = array());
|
17 |
-
}
|
18 |
-
if (!is_array($averages = sys_getloadavg()) || !$averages) {
|
19 |
-
return ($averages = array());
|
20 |
-
}
|
21 |
-
$averages = array_map('floatval', $averages);
|
22 |
-
$averages = array_slice($averages, 0, 3);
|
23 |
-
// i.e., 1m, 5m, 15m; see: <http://jas.xyz/1gWyJLt>
|
24 |
-
|
25 |
-
return $averages;
|
26 |
-
};
|
27 |
-
|
28 |
-
/*
|
29 |
-
* System memory info.
|
30 |
-
*
|
31 |
-
* @since 151002 Adding cache directory statistics.
|
32 |
-
*
|
33 |
-
* @return \stdClass|boolean System memory info.
|
34 |
-
*/
|
35 |
-
$self->sysMemoryStatus = function () use ($self) {
|
36 |
-
if (!is_null($status = &$self->cacheKey('sysMemoryStatus'))) {
|
37 |
-
return $status; // Already cached this.
|
38 |
-
}
|
39 |
-
if (!$self->functionIsPossible('shell_exec')) {
|
40 |
-
return ($status = false);
|
41 |
-
}
|
42 |
-
if (!($free = trim((string) @shell_exec('free')))) {
|
43 |
-
return ($status = false);
|
44 |
-
}
|
45 |
-
if (!($free_lines = explode("\n", $free))) {
|
46 |
-
return ($status = false);
|
47 |
-
}
|
48 |
-
if (empty($free_lines[1])) {
|
49 |
-
return ($status = false);
|
50 |
-
}
|
51 |
-
if (!($memory = explode(' ', $free_lines[1]))) {
|
52 |
-
return ($status = false);
|
53 |
-
}
|
54 |
-
if (!($memory = array_merge(array_filter($memory)))) {
|
55 |
-
return ($status = false);
|
56 |
-
}
|
57 |
-
if (!isset($memory[1], $memory[2])) {
|
58 |
-
return ($status = false);
|
59 |
-
}
|
60 |
-
if (($total = (integer) $memory[1]) <= 0) {
|
61 |
-
return ($status = false);
|
62 |
-
}
|
63 |
-
$used = (integer) $memory[2];
|
64 |
-
$percent = $used / $total * 100;
|
65 |
-
$percentage = sprintf(__('%s%%', 'comet-cache'), number_format($percent, 2, '.', ''));
|
66 |
-
$status = (object) compact('total', 'used', 'percent', 'percentage');
|
67 |
-
|
68 |
-
return $status;
|
69 |
-
};
|
70 |
-
|
71 |
-
/*
|
72 |
-
* System opcache status/details.
|
73 |
-
*
|
74 |
-
* @since 151002 Adding cache directory statistics.
|
75 |
-
*
|
76 |
-
* @return \stdClass|boolean System opcache status/details.
|
77 |
-
*/
|
78 |
-
$self->sysOpcacheStatus = function () use ($self) {
|
79 |
-
if (!is_null($status = &$self->cacheKey('sysOpcacheStatus'))) {
|
80 |
-
return $status; // Already cached this.
|
81 |
-
}
|
82 |
-
if (!$self->functionIsPossible('opcache_get_status')) {
|
83 |
-
return ($status = false);
|
84 |
-
}
|
85 |
-
if (!is_array($status = opcache_get_status(false)) || !$status) {
|
86 |
-
return ($status = false);
|
87 |
-
}
|
88 |
-
if (empty($status['opcache_enabled'])) {
|
89 |
-
return ($status = false);
|
90 |
-
}
|
91 |
-
return json_decode(json_encode($status));
|
92 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/TokenUtils.php
DELETED
@@ -1,300 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
/*
|
7 |
-
* Current host.
|
8 |
-
*
|
9 |
-
* @since 150422 Rewrite.
|
10 |
-
*
|
11 |
-
* @param boolean $dashify Optional, defaults to a `FALSE` value.
|
12 |
-
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9]`.
|
13 |
-
*
|
14 |
-
* @param boolean $consider_domain_mapping Consider?
|
15 |
-
*
|
16 |
-
* @param string $consider_domain_mapping_domain A specific domain?
|
17 |
-
*
|
18 |
-
* @return string Current host.
|
19 |
-
*
|
20 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
21 |
-
*/
|
22 |
-
$self->hostToken = function ($dashify = false, $consider_domain_mapping = false, $consider_domain_mapping_domain = '') use ($self) {
|
23 |
-
if (!is_null($token = &$self->staticKey('hostToken', array($dashify, $consider_domain_mapping, $consider_domain_mapping_domain)))) {
|
24 |
-
return $token; // Already cached this.
|
25 |
-
}
|
26 |
-
$token = ''; // Initialize token value.
|
27 |
-
|
28 |
-
if (!is_multisite() || $self->isAdvancedCache()) {
|
29 |
-
$token = (string) $_SERVER['HTTP_HOST'];
|
30 |
-
} elseif ($consider_domain_mapping && $self->canConsiderDomainMapping()) {
|
31 |
-
if (($consider_domain_mapping_domain = trim((string) $consider_domain_mapping_domain))) {
|
32 |
-
$token = $consider_domain_mapping_domain;
|
33 |
-
} elseif ($self->isDomainMapping()) {
|
34 |
-
$token = (string) $_SERVER['HTTP_HOST'];
|
35 |
-
} else { // For the current blog ID.
|
36 |
-
$token = $self->domainMappingUrlFilter($self->currentUrl());
|
37 |
-
$token = $self->parseUrl($token, PHP_URL_HOST);
|
38 |
-
}
|
39 |
-
}
|
40 |
-
if (!$token) { // Use default?
|
41 |
-
$token = (string) $_SERVER['HTTP_HOST'];
|
42 |
-
}
|
43 |
-
if ($token) { // Have token?
|
44 |
-
$token = strtolower($token);
|
45 |
-
if ($dashify) { // Dashify it?
|
46 |
-
$token = preg_replace('/[^a-z0-9]/i', '-', $token);
|
47 |
-
$token = trim($token, '-');
|
48 |
-
}
|
49 |
-
}
|
50 |
-
return $token;
|
51 |
-
};
|
52 |
-
|
53 |
-
/*
|
54 |
-
* Host for a specific blog.
|
55 |
-
*
|
56 |
-
* @since 150821 Improving multisite compat.
|
57 |
-
*
|
58 |
-
* @param boolean $dashify Optional, defaults to a `FALSE` value.
|
59 |
-
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9]`.
|
60 |
-
*
|
61 |
-
* @param boolean $consider_domain_mapping Consider?
|
62 |
-
*
|
63 |
-
* @param string $consider_domain_mapping_domain A specific domain?
|
64 |
-
*
|
65 |
-
* @param boolean $fallback Fallback on blog's domain when mapping?
|
66 |
-
*
|
67 |
-
* @param integer $blog_id For which blog ID?
|
68 |
-
*
|
69 |
-
* @return string Host for a specific blog.
|
70 |
-
*
|
71 |
-
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
72 |
-
*/
|
73 |
-
$self->hostTokenForBlog = function ($dashify = false, $consider_domain_mapping = false, $consider_domain_mapping_domain = '', $fallback = false, $blog_id = 0) use ($self) {
|
74 |
-
if (!is_multisite() || $self->isAdvancedCache()) {
|
75 |
-
return $self->hostToken($dashify, $consider_domain_mapping, $consider_domain_mapping_domain);
|
76 |
-
}
|
77 |
-
$token = ''; // Initialize token value.
|
78 |
-
|
79 |
-
if ($consider_domain_mapping && $self->canConsiderDomainMapping()) {
|
80 |
-
if (($consider_domain_mapping_domain = trim((string) $consider_domain_mapping_domain))) {
|
81 |
-
$token = $consider_domain_mapping_domain; // Force this value.
|
82 |
-
} else {
|
83 |
-
$token = $self->domainMappingBlogDomain($blog_id, $fallback);
|
84 |
-
}
|
85 |
-
} elseif (($blog_details = $self->blogDetails($blog_id))) {
|
86 |
-
$token = $blog_details->domain; // Unmapped domain.
|
87 |
-
}
|
88 |
-
if ($token) { // Have token?
|
89 |
-
$token = strtolower($token);
|
90 |
-
if ($dashify) { // Dashify it?
|
91 |
-
$token = preg_replace('/[^a-z0-9]/i', '-', $token);
|
92 |
-
$token = trim($token, '-');
|
93 |
-
}
|
94 |
-
}
|
95 |
-
return $token;
|
96 |
-
};
|
97 |
-
|
98 |
-
/*
|
99 |
-
* Current site's base directory.
|
100 |
-
*
|
101 |
-
* @since 150422 Rewrite.
|
102 |
-
*
|
103 |
-
* @param boolean $dashify Optional, defaults to a `FALSE` value.
|
104 |
-
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9\/]`.
|
105 |
-
*
|
106 |
-
* @param boolean $consider_domain_mapping Consider?
|
107 |
-
*
|
108 |
-
* @return string Current site's base directory.
|
109 |
-
*
|
110 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
111 |
-
*/
|
112 |
-
$self->hostBaseToken = function ($dashify = false, $consider_domain_mapping = false) use ($self) {
|
113 |
-
if (!is_null($token = &$self->staticKey('hostBaseToken', array($dashify, $consider_domain_mapping)))) {
|
114 |
-
return $token; // Already cached this.
|
115 |
-
}
|
116 |
-
$token = '/'; // Assume NOT multisite; or own domain.
|
117 |
-
|
118 |
-
if (!is_multisite()) {
|
119 |
-
return $token; // Not applicable.
|
120 |
-
}
|
121 |
-
if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
|
122 |
-
return $token; // Not applicable.
|
123 |
-
}
|
124 |
-
if ($consider_domain_mapping && $self->canConsiderDomainMapping()) {
|
125 |
-
return $token; // Not applicable.
|
126 |
-
}
|
127 |
-
if (defined('PATH_CURRENT_SITE')) {
|
128 |
-
$token = (string) PATH_CURRENT_SITE;
|
129 |
-
}
|
130 |
-
$token = trim($token, '\\/'." \t\n\r\0\x0B");
|
131 |
-
$token = isset($token[0]) ? '/'.$token.'/' : '/';
|
132 |
-
|
133 |
-
if ($token !== '/' && $dashify) {
|
134 |
-
$token = preg_replace('/[^a-z0-9\/]/i', '-', $token);
|
135 |
-
$token = trim($token, '-');
|
136 |
-
}
|
137 |
-
return $token;
|
138 |
-
};
|
139 |
-
|
140 |
-
/*
|
141 |
-
* Current blog's sub-directory.
|
142 |
-
*
|
143 |
-
* @since 150422 Rewrite.
|
144 |
-
*
|
145 |
-
* @param boolean $dashify Optional, defaults to a `FALSE` value.
|
146 |
-
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9\/]`.
|
147 |
-
*
|
148 |
-
* @param boolean $consider_domain_mapping Consider?
|
149 |
-
*
|
150 |
-
* @param string $path Defaults to the current URI path.
|
151 |
-
*
|
152 |
-
* @return string Current blog's sub-directory.
|
153 |
-
*
|
154 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
155 |
-
*/
|
156 |
-
$self->hostDirToken = function ($dashify = false, $consider_domain_mapping = false, $path = null) use ($self) {
|
157 |
-
if (!isset($path)) { // Use current/default path?
|
158 |
-
$path = (string) $self->parseUrl($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
159 |
-
}
|
160 |
-
$path = '/'.ltrim((string) $path, '/'); // Force leading slash.
|
161 |
-
|
162 |
-
if (!is_null($token = &$self->staticKey('hostDirToken', array($dashify, $consider_domain_mapping, $path)))) {
|
163 |
-
return $token; // Already cached this.
|
164 |
-
}
|
165 |
-
$token = '/'; // Assume NOT multisite; or own domain.
|
166 |
-
|
167 |
-
if (!is_multisite()) {
|
168 |
-
return $token; // Not applicable.
|
169 |
-
}
|
170 |
-
if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
|
171 |
-
return $token; // Not applicable.
|
172 |
-
}
|
173 |
-
if ($consider_domain_mapping && $self->canConsiderDomainMapping()) {
|
174 |
-
return $token; // Not applicable.
|
175 |
-
}
|
176 |
-
if ($path && $path !== '/' && ($host_base_token = trim($self->hostBaseToken(), '/'))) {
|
177 |
-
$path_minus_base = preg_replace('/^\/'.preg_quote($host_base_token, '/').'(\/|$)/i', '${1}', $path);
|
178 |
-
} else {
|
179 |
-
$path_minus_base = $path; // Default value.
|
180 |
-
}
|
181 |
-
list($token) = explode('/', trim($path_minus_base, '/'));
|
182 |
-
$token = trim($token, '\\/'." \t\n\r\0\x0B");
|
183 |
-
$token = isset($token[0]) ? '/'.$token.'/' : '/';
|
184 |
-
|
185 |
-
if ($token !== '/') { // Perhaps NOT the main site?
|
186 |
-
$blog_paths_file = $self->cacheDir().'/'.strtolower(SHORT_NAME).'-blog-paths';
|
187 |
-
if (!is_file($blog_paths_file) || !in_array($token, unserialize(file_get_contents($blog_paths_file)), true)) {
|
188 |
-
$token = '/'; // NOT a real/valid child blog path.
|
189 |
-
}
|
190 |
-
}
|
191 |
-
if ($token !== '/' && $dashify) {
|
192 |
-
$token = preg_replace('/[^a-z0-9\/]/i', '-', $token);
|
193 |
-
$token = trim($token, '-');
|
194 |
-
}
|
195 |
-
return $token;
|
196 |
-
};
|
197 |
-
|
198 |
-
/*
|
199 |
-
* A blog's sub-directory.
|
200 |
-
*
|
201 |
-
* @since 150821 Improving multisite compat.
|
202 |
-
*
|
203 |
-
* @param boolean $dashify Optional, defaults to a `FALSE` value.
|
204 |
-
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9]`.
|
205 |
-
*
|
206 |
-
* @param boolean $consider_domain_mapping Consider?
|
207 |
-
*
|
208 |
-
* @param integer $blog_id For which blog ID?
|
209 |
-
*
|
210 |
-
* @return string A blog's sub-directory.
|
211 |
-
*
|
212 |
-
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
213 |
-
*/
|
214 |
-
$self->hostDirTokenForBlog = function ($dashify = false, $consider_domain_mapping = false, $blog_id = 0) use ($self) {
|
215 |
-
if (!is_multisite() || $self->isAdvancedCache()) {
|
216 |
-
return $self->hostDirToken($dashify, $consider_domain_mapping);
|
217 |
-
}
|
218 |
-
$token = '/'; // Initialize token value.
|
219 |
-
|
220 |
-
if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
|
221 |
-
return $token; // Not applicable.
|
222 |
-
}
|
223 |
-
if ($consider_domain_mapping && $self->canConsiderDomainMapping()) {
|
224 |
-
return $token; // Not applicable.
|
225 |
-
}
|
226 |
-
if (($blog_details = $self->blogDetails($blog_id))) {
|
227 |
-
$path = $blog_details->path; // e.g., `[/base]/path/` (includes base).
|
228 |
-
if ($path && $path !== '/' && ($host_base_token = trim($self->hostBaseToken(), '/'))) {
|
229 |
-
$path_minus_base = preg_replace('/^\/'.preg_quote($host_base_token, '/').'(\/|$)/i', '${1}', $path);
|
230 |
-
} else {
|
231 |
-
$path_minus_base = $path; // Default value.
|
232 |
-
}
|
233 |
-
list($token) = explode('/', trim($path_minus_base, '/'));
|
234 |
-
}
|
235 |
-
$token = trim($token, '\\/'." \t\n\r\0\x0B");
|
236 |
-
$token = isset($token[0]) ? '/'.$token.'/' : '/';
|
237 |
-
|
238 |
-
if ($token !== '/') { // Perhaps NOT the main site?
|
239 |
-
$blog_paths_file = $self->cacheDir().'/'.strtolower(SHORT_NAME).'-blog-paths';
|
240 |
-
if (!is_file($blog_paths_file) || !in_array($token, unserialize(file_get_contents($blog_paths_file)), true)) {
|
241 |
-
$token = '/'; // NOT a real/valid child blog path.
|
242 |
-
}
|
243 |
-
}
|
244 |
-
if ($token !== '/' && $dashify) {
|
245 |
-
$token = preg_replace('/[^a-z0-9\/]/i', '-', $token);
|
246 |
-
$token = trim($token, '-');
|
247 |
-
}
|
248 |
-
return $token;
|
249 |
-
};
|
250 |
-
|
251 |
-
/*
|
252 |
-
* Current site's base directory & current blog's sub-directory.
|
253 |
-
*
|
254 |
-
* @since 150422 Rewrite.
|
255 |
-
*
|
256 |
-
* @param boolean $dashify Optional, defaults to a `FALSE` value.
|
257 |
-
* If `TRUE`, the tokens are returned with dashes in place of `[^a-z0-9\/]`.
|
258 |
-
*
|
259 |
-
* @param boolean $consider_domain_mapping Consider?
|
260 |
-
*
|
261 |
-
* @param string $path Defaults to the current URI path.
|
262 |
-
*
|
263 |
-
* @return string Current site's base directory & current blog's sub-directory.
|
264 |
-
*
|
265 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
266 |
-
*/
|
267 |
-
$self->hostBaseDirTokens = function ($dashify = false, $consider_domain_mapping = false, $path = null) use ($self) {
|
268 |
-
if (!is_null($tokens = &$self->staticKey('hostBaseDirTokens', array($dashify, $consider_domain_mapping, $path)))) {
|
269 |
-
return $tokens; // Already cached this.
|
270 |
-
}
|
271 |
-
$tokens = $self->hostBaseToken($dashify, $consider_domain_mapping);
|
272 |
-
$tokens .= $self->hostDirToken($dashify, $consider_domain_mapping, $path);
|
273 |
-
|
274 |
-
return ($tokens = preg_replace('/\/+/', '/', $tokens));
|
275 |
-
};
|
276 |
-
|
277 |
-
/*
|
278 |
-
* A site's base directory & a blog's sub-directory.
|
279 |
-
*
|
280 |
-
* @since 150821 Improving multisite compat.
|
281 |
-
*
|
282 |
-
* @param boolean $dashify Optional, defaults to a `FALSE` value.
|
283 |
-
* If `TRUE`, the tokens are returned with dashes in place of `[^a-z0-9\/]`.
|
284 |
-
*
|
285 |
-
* @param boolean $consider_domain_mapping Consider?
|
286 |
-
*
|
287 |
-
* @param integer $blog_id For which blog ID?
|
288 |
-
*
|
289 |
-
* @return string A site's base directory & a blog's sub-directory.
|
290 |
-
*
|
291 |
-
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
292 |
-
*/
|
293 |
-
$self->hostBaseDirTokensForBlog = function ($dashify = false, $consider_domain_mapping = false, $blog_id = 0) use ($self) {
|
294 |
-
$tokens = $self->hostBaseToken($dashify, $consider_domain_mapping);
|
295 |
-
$tokens .= $self->hostDirTokenForBlog($dashify, $consider_domain_mapping, $blog_id);
|
296 |
-
|
297 |
-
return ($tokens = preg_replace('/\/+/', '/', $tokens));
|
298 |
-
};
|
299 |
-
|
300 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/TrimUtils.php
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Trims strings deeply.
|
6 |
-
*
|
7 |
-
* @since 150422 Rewrite.
|
8 |
-
*
|
9 |
-
* @param mixed $values Any value can be converted into a trimmed string.
|
10 |
-
* Actually, objects can't, but this recurses into objects.
|
11 |
-
*
|
12 |
-
* @param string $chars Specific chars to trim.
|
13 |
-
* Defaults to PHP's trim: " \r\n\t\0\x0B". Use an empty string to bypass.
|
14 |
-
*
|
15 |
-
* @param string $extra_chars Additional chars to trim.
|
16 |
-
*
|
17 |
-
* @return string|array|object Trimmed string, array, object.
|
18 |
-
*/
|
19 |
-
$self->trimDeep = function ($values, $chars = '', $extra_chars = '') use ($self) {
|
20 |
-
if (is_array($values) || is_object($values)) {
|
21 |
-
foreach ($values as $_key => &$_values) {
|
22 |
-
$_values = $self->trimDeep($_values, $chars, $extra_chars);
|
23 |
-
}
|
24 |
-
unset($_key, $_values); // Housekeeping.
|
25 |
-
|
26 |
-
return $values;
|
27 |
-
}
|
28 |
-
$string = (string) $values;
|
29 |
-
$chars = (string) $chars;
|
30 |
-
$extra_chars = (string) $extra_chars;
|
31 |
-
|
32 |
-
$chars = isset($chars[0]) ? $chars : " \r\n\t\0\x0B";
|
33 |
-
$chars = $chars.$extra_chars; // Concatenate.
|
34 |
-
|
35 |
-
return trim($string, $chars);
|
36 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/closures/Shared/UrlUtils.php
DELETED
@@ -1,131 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebSharks\CometCache;
|
3 |
-
|
4 |
-
/*
|
5 |
-
* Parses a URL.
|
6 |
-
*
|
7 |
-
* @since 150821 Improving multisite compat.
|
8 |
-
*
|
9 |
-
* @param string $url_uri_qsl Input URL, URI, or query string w/ a leading `?`.
|
10 |
-
* @param int $component Optional component to retrieve.
|
11 |
-
*
|
12 |
-
* @return array|string|int|null Array, else `string|int|null` component value.
|
13 |
-
*/
|
14 |
-
$self->parseUrl = function ($url_uri_qsl, $component = -1) use ($self) {
|
15 |
-
$url_uri_qsl = (string) $url_uri_qsl;
|
16 |
-
$component = (integer) $component;
|
17 |
-
${'//'} = strpos($url_uri_qsl, '//') === 0;
|
18 |
-
|
19 |
-
if ($url_uri_qsl && strpos($url_uri_qsl, '&') !== false) {
|
20 |
-
$url_uri_qsl = str_replace('&', '&', $url_uri_qsl);
|
21 |
-
}
|
22 |
-
if ($component > -1) {
|
23 |
-
if (${'//'} && $component === PHP_URL_SCHEME) {
|
24 |
-
return ($part = '//');
|
25 |
-
}
|
26 |
-
return ($part = parse_url($url_uri_qsl, $component));
|
27 |
-
} else {
|
28 |
-
if (!is_array($parts = parse_url($url_uri_qsl))) {
|
29 |
-
return ($parts = array());
|
30 |
-
}
|
31 |
-
if (${'//'}) {
|
32 |
-
$parts['scheme'] = '//';
|
33 |
-
}
|
34 |
-
return $parts;
|
35 |
-
}
|
36 |
-
};
|
37 |
-
|
38 |
-
/*
|
39 |
-
* Unparses a URL.
|
40 |
-
*
|
41 |
-
* @since 150821 Improving multisite compat.
|
42 |
-
*
|
43 |
-
* @param array $parts Input URL parts.
|
44 |
-
*
|
45 |
-
* @return string Unparsed URL in string format.
|
46 |
-
*/
|
47 |
-
$self->unParseUrl = function (array $parts) use ($self) {
|
48 |
-
$scheme = '';
|
49 |
-
$host = '';
|
50 |
-
$port = '';
|
51 |
-
$user = '';
|
52 |
-
$pass = '';
|
53 |
-
$path = '';
|
54 |
-
$query = '';
|
55 |
-
$fragment = '';
|
56 |
-
|
57 |
-
if (!empty($parts['scheme'])) {
|
58 |
-
if ($parts['scheme'] === '//') {
|
59 |
-
$scheme = $parts['scheme'];
|
60 |
-
} else {
|
61 |
-
$scheme = $parts['scheme'].'://';
|
62 |
-
}
|
63 |
-
}
|
64 |
-
if (!empty($parts['host'])) {
|
65 |
-
$host = $parts['host'];
|
66 |
-
}
|
67 |
-
if (!empty($parts['port'])) {
|
68 |
-
$port = ':'.$parts['port'];
|
69 |
-
}
|
70 |
-
if (!empty($parts['user'])) {
|
71 |
-
$user = $parts['user'];
|
72 |
-
}
|
73 |
-
if (!empty($parts['pass'])) {
|
74 |
-
$pass = $parts['pass'];
|
75 |
-
}
|
76 |
-
if ($user || $pass) {
|
77 |
-
$pass .= '@';
|
78 |
-
}
|
79 |
-
if (!empty($parts['path'])) {
|
80 |
-
$path = '/'.ltrim($parts['path'], '/');
|
81 |
-
}
|
82 |
-
if (!empty($parts['query'])) {
|
83 |
-
$query = '?'.$parts['query'];
|
84 |
-
}
|
85 |
-
if (!empty($parts['fragment'])) {
|
86 |
-
$fragment = '#'.$parts['fragment'];
|
87 |
-
}
|
88 |
-
return $scheme.$user.$pass.$host.$port.$path.$query.$fragment;
|
89 |
-
};
|
90 |
-
|
91 |
-
/*
|
92 |
-
* Is the current request over SSL?
|
93 |
-
*
|
94 |
-
* @since 150422 Rewrite.
|
95 |
-
*
|
96 |
-
* @return boolean `TRUE` if the current request is over SSL.
|
97 |
-
*
|
98 |
-
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
99 |
-
*/
|
100 |
-
$self->isSsl = function () use ($self) {
|
101 |
-
if (!is_null($is = &$self->staticKey('isSsl'))) {
|
102 |
-
return $is; // Already cached this.
|
103 |
-
}
|
104 |
-
if (!empty($_SERVER['SERVER_PORT'])) {
|
105 |
-
if ((integer) $_SERVER['SERVER_PORT'] === 443) {
|
106 |
-
return ($is = true);
|
107 |
-
}
|
108 |
-
}
|
109 |
-
if (!empty($_SERVER['HTTPS'])) {
|
110 |
-
if (filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN)) {
|
111 |
-
return ($is = true);
|
112 |
-
}
|
113 |
-
}
|
114 |
-
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
|
115 |
-
if (strcasecmp((string) $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0) {
|
116 |
-
return ($is = true);
|
117 |
-
}
|
118 |
-
}
|
119 |
-
return ($is = false);
|
120 |
-
};
|
121 |
-
|
122 |
-
/*
|
123 |
-
* Current URL.
|
124 |
-
*
|
125 |
-
* @since 150821 Improving multisite compat.
|
126 |
-
*
|
127 |
-
* @return string Current URL.
|
128 |
-
*/
|
129 |
-
$self->currentUrl = function () use ($self) {
|
130 |
-
return ($self->isSsl() ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
131 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/functions/i18n-utils.php
CHANGED
@@ -1,22 +1,37 @@
|
|
1 |
<?php
|
2 |
-
namespace WebSharks\CometCache
|
3 |
|
4 |
-
/**
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
function __($string, $text_domain)
|
15 |
-
{
|
16 |
-
|
17 |
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
}
|
21 |
-
return $string; // Not possible (yet).
|
22 |
}
|
1 |
<?php
|
2 |
+
namespace WebSharks\CometCache {
|
3 |
|
4 |
+
/**
|
5 |
+
* Polyfill for {@link \__()}.
|
6 |
+
*
|
7 |
+
* @since 150422 Rewrite.
|
8 |
+
*
|
9 |
+
* @param string $string String to translate.
|
10 |
+
* @param string $text_domain Plugin text domain.
|
11 |
+
*
|
12 |
+
* @return string Possibly translated string.
|
13 |
+
*/
|
14 |
+
function __($string, $text_domain)
|
15 |
+
{
|
16 |
+
static $exists; // Cache.
|
17 |
|
18 |
+
if ($exists || ($exists = function_exists('__'))) {
|
19 |
+
return \__($string, $text_domain);
|
20 |
+
}
|
21 |
+
return $string; // Not possible (yet).
|
22 |
+
}
|
23 |
+
}
|
24 |
+
namespace WebSharks\CometCache\Traits\Ac {
|
25 |
+
|
26 |
+
function __($string, $text_domain)
|
27 |
+
{
|
28 |
+
return \WebSharks\CometCache\__($string, $text_domain);
|
29 |
+
}
|
30 |
+
}
|
31 |
+
namespace WebSharks\CometCache\Traits\Shared {
|
32 |
+
|
33 |
+
function __($string, $text_domain)
|
34 |
+
{
|
35 |
+
return \WebSharks\CometCache\__($string, $text_domain);
|
36 |
}
|
|
|
37 |
}
|
src/includes/functions/wp-cache-postload.php
CHANGED
@@ -26,7 +26,7 @@ function wp_cache_postload()
|
|
26 |
$advanced_cache->maybeSetDebugInfoPostload();
|
27 |
}
|
28 |
if (!empty($advanced_cache->postload['wp_main_query'])) {
|
29 |
-
add_action('wp',
|
30 |
}
|
31 |
$advanced_cache->doWpAction('after_'.$GLOBAL_NS.'_'.__FUNCTION__, get_defined_vars());
|
32 |
$advanced_cache->doWpAction($GLOBAL_NS.'_'.__FUNCTION__.'_complete', get_defined_vars());
|
26 |
$advanced_cache->maybeSetDebugInfoPostload();
|
27 |
}
|
28 |
if (!empty($advanced_cache->postload['wp_main_query'])) {
|
29 |
+
add_action('wp', [$advanced_cache, 'wpMainQueryPostload'], PHP_INT_MAX);
|
30 |
}
|
31 |
$advanced_cache->doWpAction('after_'.$GLOBAL_NS.'_'.__FUNCTION__, get_defined_vars());
|
32 |
$advanced_cache->doWpAction($GLOBAL_NS.'_'.__FUNCTION__.'_complete', get_defined_vars());
|
src/includes/interfaces/Shared/CachePathConsts.php
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Interfaces\Shared;
|
3 |
+
|
4 |
+
interface CachePathConsts
|
5 |
+
{
|
6 |
+
/**
|
7 |
+
* Default cache path flags.
|
8 |
+
*
|
9 |
+
* @since 150422 Rewrite.
|
10 |
+
*
|
11 |
+
* @type int A bitmask.
|
12 |
+
*/
|
13 |
+
const CACHE_PATH_DEFAULT = 0;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Use a domain-mapped cache path.
|
17 |
+
*
|
18 |
+
* @since 150821 Improving multisite compat.
|
19 |
+
*
|
20 |
+
* @type int Part of a bitmask.
|
21 |
+
*/
|
22 |
+
const CACHE_PATH_CONSIDER_DOMAIN_MAPPING = 1;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Generate an unmapped cache path?
|
26 |
+
*
|
27 |
+
* @since 150821 Improving multisite compat.
|
28 |
+
*
|
29 |
+
* @type int Part of a bitmask.
|
30 |
+
*/
|
31 |
+
const CACHE_PATH_REVERSE_DOMAIN_MAPPING = 2;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Exclude scheme from cache path.
|
35 |
+
*
|
36 |
+
* @since 150422 Rewrite.
|
37 |
+
*
|
38 |
+
* @type int Part of a bitmask.
|
39 |
+
*/
|
40 |
+
const CACHE_PATH_NO_SCHEME = 4;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Exclude host (i.e. domain name) from cache path.
|
44 |
+
*
|
45 |
+
* @since 150422 Rewrite.
|
46 |
+
*
|
47 |
+
* @type int Part of a bitmask.
|
48 |
+
*/
|
49 |
+
const CACHE_PATH_NO_HOST = 8;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Exclude path from cache path.
|
53 |
+
*
|
54 |
+
* @since 150422 Rewrite.
|
55 |
+
*
|
56 |
+
* @type int Part of a bitmask.
|
57 |
+
*/
|
58 |
+
const CACHE_PATH_NO_PATH = 16;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Exclude path index (i.e. no default `index`) from cache path.
|
62 |
+
*
|
63 |
+
* @since 150422 Rewrite.
|
64 |
+
*
|
65 |
+
* @type int Part of a bitmask.
|
66 |
+
*/
|
67 |
+
const CACHE_PATH_NO_PATH_INDEX = 32;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Exclude query, user & version salt from cache path.
|
71 |
+
*
|
72 |
+
* @since 150422 Rewrite.
|
73 |
+
*
|
74 |
+
* @type int Part of a bitmask.
|
75 |
+
*/
|
76 |
+
const CACHE_PATH_NO_QUV = 64;
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Exclude query string from cache path.
|
80 |
+
*
|
81 |
+
* @since 150422 Rewrite.
|
82 |
+
*
|
83 |
+
* @type int Part of a bitmask.
|
84 |
+
*/
|
85 |
+
const CACHE_PATH_NO_QUERY = 128;
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Exclude user token from cache path.
|
89 |
+
*
|
90 |
+
* @since 150422 Rewrite.
|
91 |
+
*
|
92 |
+
* @type int Part of a bitmask.
|
93 |
+
*/
|
94 |
+
const CACHE_PATH_NO_USER = 256;
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Exclude version salt from cache path.
|
98 |
+
*
|
99 |
+
* @since 150422 Rewrite.
|
100 |
+
*
|
101 |
+
* @type int Part of a bitmask.
|
102 |
+
*/
|
103 |
+
const CACHE_PATH_NO_VSALT = 512;
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Exclude extension from cache path.
|
107 |
+
*
|
108 |
+
* @since 150422 Rewrite.
|
109 |
+
*
|
110 |
+
* @type int Part of a bitmask.
|
111 |
+
*/
|
112 |
+
const CACHE_PATH_NO_EXT = 1024;
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Allow wildcards in the cache path.
|
116 |
+
*
|
117 |
+
* @since 150422 Rewrite.
|
118 |
+
*
|
119 |
+
* @type int Part of a bitmask.
|
120 |
+
*/
|
121 |
+
const CACHE_PATH_ALLOW_WILDCARDS = 2048;
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Allow watered-down regex in the cache path.
|
125 |
+
*
|
126 |
+
* @since 151114 Improving regex syntax.
|
127 |
+
*
|
128 |
+
* @type int Part of a bitmask.
|
129 |
+
*/
|
130 |
+
const CACHE_PATH_ALLOW_WD_REGEX = 4096;
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Default cache path regex suffix frag.
|
134 |
+
*
|
135 |
+
* @since 150422 Rewrite.
|
136 |
+
*
|
137 |
+
* @type string Default regex suffix frag used in cache path patterns.
|
138 |
+
*/
|
139 |
+
const CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG = null;
|
140 |
+
}
|
src/includes/interfaces/Shared/NcDebugConsts.php
ADDED
@@ -0,0 +1,293 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Interfaces\Shared;
|
3 |
+
|
4 |
+
interface NcDebugConsts
|
5 |
+
{
|
6 |
+
/**
|
7 |
+
* No-cache because of the current {@link \PHP_SAPI}.
|
8 |
+
*
|
9 |
+
* @since 140422 First documented version.
|
10 |
+
*
|
11 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
12 |
+
*/
|
13 |
+
const NC_DEBUG_PHP_SAPI_CLI = 'nc_debug_php_sapi_cli';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* No-cache because of a missing http host.
|
17 |
+
*
|
18 |
+
* @since 140422 First documented version.
|
19 |
+
*
|
20 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
21 |
+
*/
|
22 |
+
const NC_DEBUG_NO_SERVER_HTTP_HOST = 'nc_debug_no_server_http_host';
|
23 |
+
|
24 |
+
/**
|
25 |
+
* No-cache because of a missing `$_SERVER['REQUEST_URI']`.
|
26 |
+
*
|
27 |
+
* @since 140422 First documented version.
|
28 |
+
*
|
29 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
30 |
+
*/
|
31 |
+
const NC_DEBUG_NO_SERVER_REQUEST_URI = 'nc_debug_no_server_request_uri';
|
32 |
+
|
33 |
+
/**
|
34 |
+
* No-cache because the {@link \COMET_CACHE_ALLOWED} constant says not to.
|
35 |
+
*
|
36 |
+
* @since 140422 First documented version.
|
37 |
+
*
|
38 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
39 |
+
*/
|
40 |
+
const NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT = 'nc_debug_comet_cache_allowed_constant';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* No-cache because the `$_SERVER['COMET_CACHE_ALLOWED']` environment variable says not to.
|
44 |
+
*
|
45 |
+
* @since 140422 First documented version.
|
46 |
+
*
|
47 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
48 |
+
*/
|
49 |
+
const NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR = 'nc_debug_comet_cache_allowed_server_var';
|
50 |
+
|
51 |
+
/**
|
52 |
+
* No-cache because the {@link \DONOTCACHEPAGE} constant says not to.
|
53 |
+
*
|
54 |
+
* @since 140422 First documented version.
|
55 |
+
*
|
56 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
57 |
+
*/
|
58 |
+
const NC_DEBUG_DONOTCACHEPAGE_CONSTANT = 'nc_debug_donotcachepage_constant';
|
59 |
+
|
60 |
+
/**
|
61 |
+
* No-cache because the `$_SERVER['DONOTCACHEPAGE']` environment variable says not to.
|
62 |
+
*
|
63 |
+
* @since 140422 First documented version.
|
64 |
+
*
|
65 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
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 |
+
*
|
72 |
+
* @since 140422 First documented version.
|
73 |
+
*
|
74 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
75 |
+
*/
|
76 |
+
const NC_DEBUG_AC_GET_VAR = 'nc_debug_ac_get_var';
|
77 |
+
|
78 |
+
/**
|
79 |
+
* No-cache because the current request method is `POST|PUT|DELETE`.
|
80 |
+
*
|
81 |
+
* @since 140422 First documented version.
|
82 |
+
*
|
83 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
84 |
+
*/
|
85 |
+
const NC_DEBUG_UNCACHEABLE_REQUEST = 'nc_debug_post_put_del_request';
|
86 |
+
|
87 |
+
/**
|
88 |
+
* No-cache because the current request originated from the server itself.
|
89 |
+
*
|
90 |
+
* @since 140422 First documented version.
|
91 |
+
*
|
92 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
93 |
+
*/
|
94 |
+
const NC_DEBUG_SELF_SERVE_REQUEST = 'nc_debug_self_serve_request';
|
95 |
+
|
96 |
+
/**
|
97 |
+
* No-cache because the current request is for a feed.
|
98 |
+
*
|
99 |
+
* @since 140422 First documented version.
|
100 |
+
*
|
101 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
102 |
+
*/
|
103 |
+
const NC_DEBUG_FEED_REQUEST = 'nc_debug_feed_request';
|
104 |
+
|
105 |
+
/**
|
106 |
+
* No-cache because the current request is systematic.
|
107 |
+
*
|
108 |
+
* @since 140422 First documented version.
|
109 |
+
*
|
110 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
111 |
+
*/
|
112 |
+
const NC_DEBUG_WP_SYSTEMATICS = 'nc_debug_wp_systematics';
|
113 |
+
|
114 |
+
/**
|
115 |
+
* No-cache because the current request is for an administrative area.
|
116 |
+
*
|
117 |
+
* @since 140422 First documented version.
|
118 |
+
*
|
119 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
120 |
+
*/
|
121 |
+
const NC_DEBUG_WP_ADMIN = 'nc_debug_wp_admin';
|
122 |
+
|
123 |
+
/**
|
124 |
+
* No-cache because the current request is multisite `/files/`.
|
125 |
+
*
|
126 |
+
* @since 140422 First documented version.
|
127 |
+
*
|
128 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
129 |
+
*/
|
130 |
+
const NC_DEBUG_MS_FILES = 'nc_debug_ms_files';
|
131 |
+
|
132 |
+
/**
|
133 |
+
* No-cache because the current user is like a logged-in user.
|
134 |
+
*
|
135 |
+
* @since 140422 First documented version.
|
136 |
+
*
|
137 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
138 |
+
*/
|
139 |
+
const NC_DEBUG_IS_LIKE_LOGGED_IN_USER = 'nc_debug_is_like_logged_in_user';
|
140 |
+
|
141 |
+
/**
|
142 |
+
* No-cache because the current user is logged into the site.
|
143 |
+
*
|
144 |
+
* @since 140422 First documented version.
|
145 |
+
*
|
146 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
147 |
+
*/
|
148 |
+
const NC_DEBUG_IS_LOGGED_IN_USER = 'nc_debug_is_logged_in_user';
|
149 |
+
|
150 |
+
/**
|
151 |
+
* No-cache because the current user is logged into the site and the current page contains an `nonce`.
|
152 |
+
*
|
153 |
+
* @since 151220 Enhancing logged-in user caching support.
|
154 |
+
*
|
155 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
156 |
+
*/
|
157 |
+
const NC_DEBUG_IS_LOGGED_IN_USER_NONCE = 'nc_debug_is_logged_in_user_nonce';
|
158 |
+
|
159 |
+
/**
|
160 |
+
* No-cache because the current page contains an `nonce`.
|
161 |
+
*
|
162 |
+
* @since 151220 Enhancing `nonce` detection.
|
163 |
+
*
|
164 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
165 |
+
*/
|
166 |
+
const NC_DEBUG_PAGE_CONTAINS_NONCE = 'nc_debug_page_contains_nonce';
|
167 |
+
|
168 |
+
/**
|
169 |
+
* No-cache because it was not possible to acquire a user token.
|
170 |
+
*
|
171 |
+
* @since 140422 First documented version.
|
172 |
+
*
|
173 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
174 |
+
*/
|
175 |
+
const NC_DEBUG_NO_USER_TOKEN = 'nc_debug_no_user_token';
|
176 |
+
|
177 |
+
/**
|
178 |
+
* No-cache because the current request contains a query string.
|
179 |
+
*
|
180 |
+
* @since 140422 First documented version.
|
181 |
+
*
|
182 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
183 |
+
*/
|
184 |
+
const NC_DEBUG_GET_REQUEST_QUERIES = 'nc_debug_get_request_queries';
|
185 |
+
|
186 |
+
/**
|
187 |
+
* No-cache because it's a preview.
|
188 |
+
*
|
189 |
+
* @since 151114 Adding support for preview detection.
|
190 |
+
*
|
191 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
192 |
+
*/
|
193 |
+
const NC_DEBUG_PREVIEW = 'nc_debug_preview';
|
194 |
+
|
195 |
+
/**
|
196 |
+
* No-cache because the current request excluded by its URI.
|
197 |
+
*
|
198 |
+
* @since 140422 First documented version.
|
199 |
+
*
|
200 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
201 |
+
*/
|
202 |
+
const NC_DEBUG_EXCLUDED_URIS = 'nc_debug_excluded_uris';
|
203 |
+
|
204 |
+
/**
|
205 |
+
* No-cache because the current user-agent is excluded.
|
206 |
+
*
|
207 |
+
* @since 140422 First documented version.
|
208 |
+
*
|
209 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
210 |
+
*/
|
211 |
+
const NC_DEBUG_EXCLUDED_AGENTS = 'nc_debug_excluded_agents';
|
212 |
+
|
213 |
+
/**
|
214 |
+
* No-cache because the current HTTP referrer is excluded.
|
215 |
+
*
|
216 |
+
* @since 140422 First documented version.
|
217 |
+
*
|
218 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
219 |
+
*/
|
220 |
+
const NC_DEBUG_EXCLUDED_REFS = 'nc_debug_excluded_refs';
|
221 |
+
|
222 |
+
/**
|
223 |
+
* No-cache because the current request is a 404 error.
|
224 |
+
*
|
225 |
+
* @since 140422 First documented version.
|
226 |
+
*
|
227 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
228 |
+
*/
|
229 |
+
const NC_DEBUG_404_REQUEST = 'nc_debug_404_request';
|
230 |
+
|
231 |
+
/**
|
232 |
+
* No-cache because the requested page is currently in maintenance mode.
|
233 |
+
*
|
234 |
+
* @since 140422 First documented version.
|
235 |
+
*
|
236 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
237 |
+
*/
|
238 |
+
const NC_DEBUG_MAINTENANCE_PLUGIN = 'nc_debug_maintenance_plugin';
|
239 |
+
|
240 |
+
/**
|
241 |
+
* No-cache because the current request is being compressed by an incompatible ZLIB coding type.
|
242 |
+
*
|
243 |
+
* @since 140422 First documented version.
|
244 |
+
*
|
245 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
246 |
+
*/
|
247 |
+
const NC_DEBUG_OB_ZLIB_CODING_TYPE = 'nc_debug_ob_zlib_coding_type';
|
248 |
+
|
249 |
+
/**
|
250 |
+
* No-cache because the current request resulted in a WP error message.
|
251 |
+
*
|
252 |
+
* @since 140422 First documented version.
|
253 |
+
*
|
254 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
255 |
+
*/
|
256 |
+
const NC_DEBUG_WP_ERROR_PAGE = 'nc_debug_wp_error_page';
|
257 |
+
|
258 |
+
/**
|
259 |
+
* No-cache because the current request is serving an uncacheable content type.
|
260 |
+
*
|
261 |
+
* @since 140422 First documented version.
|
262 |
+
*
|
263 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
264 |
+
*/
|
265 |
+
const NC_DEBUG_UNCACHEABLE_CONTENT_TYPE = 'nc_debug_uncacheable_content_type';
|
266 |
+
|
267 |
+
/**
|
268 |
+
* No-cache because the current request sent a non-2xx & non-404 status code.
|
269 |
+
*
|
270 |
+
* @since 140422 First documented version.
|
271 |
+
*
|
272 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
273 |
+
*/
|
274 |
+
const NC_DEBUG_UNCACHEABLE_STATUS = 'nc_debug_uncacheable_status';
|
275 |
+
|
276 |
+
/**
|
277 |
+
* No-cache because this is a new 404 error that we are symlinking.
|
278 |
+
*
|
279 |
+
* @since 140422 First documented version.
|
280 |
+
*
|
281 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
282 |
+
*/
|
283 |
+
const NC_DEBUG_1ST_TIME_404_SYMLINK = 'nc_debug_1st_time_404_symlink';
|
284 |
+
|
285 |
+
/**
|
286 |
+
* No-cache because we detected an early buffer termination.
|
287 |
+
*
|
288 |
+
* @since 140605 Improving output buffer.
|
289 |
+
*
|
290 |
+
* @type string A unique string identifier in the set of `NC_DEBUG_` constants.
|
291 |
+
*/
|
292 |
+
const NC_DEBUG_EARLY_BUFFER_TERMINATION = 'nc_debug_early_buffer_termination';
|
293 |
+
}
|
src/includes/plugin.php
CHANGED
@@ -6,17 +6,19 @@
|
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
|
|
|
|
9 |
if (!defined('WPINC')) {
|
10 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
11 |
}
|
12 |
-
require_once
|
13 |
|
14 |
-
if (!Conflicts::check()) {
|
15 |
-
$GLOBALS[GLOBAL_NS]
|
16 |
-
$GLOBALS['zencache']
|
17 |
$GLOBALS['quick_cache'] = $GLOBALS[GLOBAL_NS]; // Back compat.
|
18 |
|
19 |
-
add_action('plugins_loaded', function() {
|
20 |
-
require_once
|
21 |
});
|
22 |
}
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
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 |
|
16 |
+
if (!Classes\Conflicts::check()) {
|
17 |
+
$GLOBALS[GLOBAL_NS] = new Classes\Plugin();
|
18 |
+
$GLOBALS['zencache'] = $GLOBALS[GLOBAL_NS]; // Back compat.
|
19 |
$GLOBALS['quick_cache'] = $GLOBALS[GLOBAL_NS]; // Back compat.
|
20 |
|
21 |
+
add_action('plugins_loaded', function () {
|
22 |
+
require_once __DIR__.'/api.php';
|
23 |
});
|
24 |
}
|
src/includes/stub.php
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
* Stub.
|
4 |
*
|
@@ -9,11 +10,11 @@ namespace WebSharks\CometCache;
|
|
9 |
if (!defined('WPINC')) {
|
10 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
11 |
}
|
12 |
-
require_once dirname(
|
13 |
-
require_once
|
14 |
|
15 |
-
${__FILE__}['version'] = '
|
16 |
-
${__FILE__}['plugin'] = dirname(dirname(
|
17 |
${__FILE__}['plugin'] .= '/'.basename(${__FILE__}['plugin']).'.php';
|
18 |
${__FILE__}['ns_path'] = str_replace('\\', '/', __NAMESPACE__); // To dir/path.
|
19 |
${__FILE__}['is_pro'] = strtolower(basename(${__FILE__}['ns_path'])) === 'pro';
|
@@ -27,9 +28,24 @@ define(__NAMESPACE__.'\\VERSION', ${__FILE__}['version']);
|
|
27 |
define(__NAMESPACE__.'\\PLUGIN_FILE', ${__FILE__}['plugin']);
|
28 |
define(__NAMESPACE__.'\\IS_PRO', ${__FILE__}['is_pro']);
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
unset(${__FILE__}); // Housekeeping.
|
31 |
|
32 |
// Fixes PHP Fatal error with upgrades from v160211
|
33 |
-
class_alias(__NAMESPACE__.'\\AdvCacheBackCompat', 'WebSharks\\Comet_Cache\\AdvCacheBackCompat');
|
34 |
-
class_alias(__NAMESPACE__.'\\AdvancedCache', 'WebSharks\\Comet_Cache\\AdvancedCache');
|
|
|
|
|
|
|
|
|
|
|
35 |
|
1 |
<?php
|
2 |
+
// @codingStandardsIgnoreFile
|
3 |
/**
|
4 |
* Stub.
|
5 |
*
|
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'] = '160416'; //version//
|
17 |
+
${__FILE__}['plugin'] = dirname(dirname(__DIR__));
|
18 |
${__FILE__}['plugin'] .= '/'.basename(${__FILE__}['plugin']).'.php';
|
19 |
${__FILE__}['ns_path'] = str_replace('\\', '/', __NAMESPACE__); // To dir/path.
|
20 |
${__FILE__}['is_pro'] = strtolower(basename(${__FILE__}['ns_path'])) === 'pro';
|
28 |
define(__NAMESPACE__.'\\PLUGIN_FILE', ${__FILE__}['plugin']);
|
29 |
define(__NAMESPACE__.'\\IS_PRO', ${__FILE__}['is_pro']);
|
30 |
|
31 |
+
foreach (['Classes', 'Traits\\Shared', 'Traits\\Ac', 'Traits\\Plugin', 'Interfaces\\Shared'] as ${__FILE__}['_sub_namespace']) {
|
32 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\SHORT_NAME', SHORT_NAME);
|
33 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\NAME', NAME);
|
34 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\DOMAIN', DOMAIN);
|
35 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\GLOBAL_NS', GLOBAL_NS);
|
36 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\SLUG_TD', 'comet-cache');
|
37 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\VERSION', VERSION);
|
38 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\PLUGIN_FILE', PLUGIN_FILE);
|
39 |
+
define(__NAMESPACE__.'\\'.${__FILE__}['_sub_namespace'].'\\IS_PRO', IS_PRO);
|
40 |
+
}
|
41 |
unset(${__FILE__}); // Housekeeping.
|
42 |
|
43 |
// Fixes PHP Fatal error with upgrades from v160211
|
44 |
+
class_alias(__NAMESPACE__.'\\Classes\\AdvCacheBackCompat', 'WebSharks\\Comet_Cache\\AdvCacheBackCompat');
|
45 |
+
class_alias(__NAMESPACE__.'\\Classes\\AdvancedCache', 'WebSharks\\Comet_Cache\\AdvancedCache');
|
46 |
+
|
47 |
+
|
48 |
+
// Fixes PHP Fatal error with upgrades from v160227
|
49 |
+
class_alias(__NAMESPACE__.'\\Classes\\AdvCacheBackCompat', 'WebSharks\\CometCache\\AdvCacheBackCompat');
|
50 |
+
class_alias(__NAMESPACE__.'\\Classes\\AdvancedCache', 'WebSharks\\CometCache\\AdvancedCache');
|
51 |
|
src/includes/templates/advanced-cache.txt
CHANGED
@@ -6,6 +6,8 @@
|
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
|
|
|
|
9 |
if (!defined('WPINC')) {
|
10 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
11 |
}
|
@@ -33,8 +35,8 @@ if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
33 |
} elseif ((@include_once(dirname(COMET_CACHE_PLUGIN_FILE).'/src/includes/functions/wp-cache-postload.php')) === false) {
|
34 |
return; // Unable to find postload function(s). Fail softly.
|
35 |
}
|
36 |
-
AdvCacheBackCompat::zenCacheConstants();
|
37 |
-
AdvCacheBackCompat::zcRequestVars();
|
38 |
|
39 |
if (!defined('COMET_CACHE_PRO')) {
|
40 |
/**
|
@@ -218,9 +220,13 @@ if (!defined('COMET_CACHE_404_CACHE_FILENAME')) {
|
|
218 |
|
219 |
|
220 |
|
221 |
-
$GLOBALS[GLOBAL_NS.'_advanced_cache'] = new AdvancedCache();
|
222 |
$GLOBALS[GLOBAL_NS.'__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
223 |
if (!isset($GLOBALS['zencache__advanced_cache'])) {
|
224 |
$GLOBALS['zencache_advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
225 |
$GLOBALS['zencache__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
226 |
}
|
|
|
|
|
|
|
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
9 |
+
use WebSharks\CometCache\Classes;
|
10 |
+
|
11 |
if (!defined('WPINC')) {
|
12 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
13 |
}
|
35 |
} elseif ((@include_once(dirname(COMET_CACHE_PLUGIN_FILE).'/src/includes/functions/wp-cache-postload.php')) === false) {
|
36 |
return; // Unable to find postload function(s). Fail softly.
|
37 |
}
|
38 |
+
Classes\AdvCacheBackCompat::zenCacheConstants();
|
39 |
+
Classes\AdvCacheBackCompat::zcRequestVars();
|
40 |
|
41 |
if (!defined('COMET_CACHE_PRO')) {
|
42 |
/**
|
220 |
|
221 |
|
222 |
|
223 |
+
$GLOBALS[GLOBAL_NS.'_advanced_cache'] = new Classes\AdvancedCache();
|
224 |
$GLOBALS[GLOBAL_NS.'__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
225 |
if (!isset($GLOBALS['zencache__advanced_cache'])) {
|
226 |
$GLOBALS['zencache_advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
227 |
$GLOBALS['zencache__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
228 |
}
|
229 |
+
if (!isset($GLOBALS['quick_cache__advanced_cache'])) {
|
230 |
+
$GLOBALS['quick_cache_advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
231 |
+
$GLOBALS['quick_cache__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
232 |
+
}
|
src/includes/traits/Ac/AbortUtils.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Ac;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait AbortUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Ignores user aborts; when/if the Auto-Cache Engine is running.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*/
|
13 |
+
public function maybeIgnoreUserAbort()
|
14 |
+
{
|
15 |
+
|
16 |
+
}
|
17 |
+
}
|
src/includes/traits/Ac/AcPluginUtils.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Ac;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait AcPluginUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Loads any advanced cache plugin files found inside `/wp-content/ac-plugins`.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*/
|
13 |
+
public function loadAcPlugins()
|
14 |
+
{
|
15 |
+
if (!is_dir(WP_CONTENT_DIR.'/ac-plugins')) {
|
16 |
+
return; // Nothing to do here.
|
17 |
+
}
|
18 |
+
$GLOBALS[GLOBAL_NS.'_advanced_cache'] = $this; // Self reference.
|
19 |
+
$GLOBALS[GLOBAL_NS.'__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
20 |
+
if (!isset($GLOBALS['zencache__advanced_cache'])) {
|
21 |
+
$GLOBALS['zencache_advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
22 |
+
$GLOBALS['zencache__advanced_cache'] = &$GLOBALS[GLOBAL_NS.'_advanced_cache'];
|
23 |
+
}
|
24 |
+
foreach ((array) glob(WP_CONTENT_DIR.'/ac-plugins/*.php') as $_ac_plugin) {
|
25 |
+
if (is_file($_ac_plugin)) {
|
26 |
+
include_once $_ac_plugin;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
unset($_ac_plugin); // Houskeeping.
|
30 |
+
}
|
31 |
+
}
|
src/includes/traits/Ac/BrowserUtils.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Ac;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait BrowserUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Sends no-cache headers (if applicable).
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite. Enhanced/altered 151220.
|
12 |
+
*/
|
13 |
+
public function maybeStopBrowserCaching()
|
14 |
+
{
|
15 |
+
switch ((bool) COMET_CACHE_ALLOW_BROWSER_CACHE) {
|
16 |
+
|
17 |
+
case true: // If global config allows, check exclusions.
|
18 |
+
|
19 |
+
if (isset($_GET[strtolower(SHORT_NAME).'ABC'])) {
|
20 |
+
if (!filter_var($_GET[strtolower(SHORT_NAME).'ABC'], FILTER_VALIDATE_BOOLEAN)) {
|
21 |
+
return $this->sendNoCacheHeaders(); // Disallow.
|
22 |
+
} // Else, allow client-side caching; because `ABC` is a true-ish value.
|
23 |
+
// ↑ Note that exclusion patterns are ignored in this case, in favor of `ABC`.
|
24 |
+
} elseif (COMET_CACHE_EXCLUDE_CLIENT_SIDE_URIS && preg_match(COMET_CACHE_EXCLUDE_CLIENT_SIDE_URIS, $_SERVER['REQUEST_URI'])) {
|
25 |
+
return $this->sendNoCacheHeaders(); // Disallow.
|
26 |
+
}
|
27 |
+
return; // Allow browser caching; default behavior in this mode.
|
28 |
+
|
29 |
+
case false: // Global config disallows; check inclusions.
|
30 |
+
|
31 |
+
if (isset($_GET[strtolower(SHORT_NAME).'ABC'])) {
|
32 |
+
if (filter_var($_GET[strtolower(SHORT_NAME).'ABC'], FILTER_VALIDATE_BOOLEAN)) {
|
33 |
+
return; // Allow, because `ABC` is a false-ish value.
|
34 |
+
} // Else, disallow client-side caching; because `ABC` is a true-ish value.
|
35 |
+
// ↑ Note that inclusion patterns are ignored in this case, in favor of `ABC`.
|
36 |
+
}
|
37 |
+
return $this->sendNoCacheHeaders(); // Disallow; default behavior in this mode.
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
src/includes/traits/Ac/NcDebugUtils.php
ADDED
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Ac;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait NcDebugUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* An array of debug info.
|
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 |
+
|
17 |
+
/**
|
18 |
+
* Used to setup debug info (if enabled).
|
19 |
+
*
|
20 |
+
* @since 150422 Rewrite.
|
21 |
+
*
|
22 |
+
* @param string $reason_code One of the `NC_DEBUG_` constants.
|
23 |
+
* @param string $reason Optionally override the built-in description with a custom message.
|
24 |
+
*/
|
25 |
+
public function maybeSetDebugInfo($reason_code, $reason = '')
|
26 |
+
{
|
27 |
+
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
28 |
+
return; // Nothing to do.
|
29 |
+
}
|
30 |
+
$reason = (string) $reason;
|
31 |
+
if (!($reason_code = (string) $reason_code)) {
|
32 |
+
return; // Not applicable.
|
33 |
+
}
|
34 |
+
$this->debug_info = ['reason_code' => $reason_code, 'reason' => $reason];
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
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 |
+
*/
|
44 |
+
public function maybeEchoNcDebugInfo()
|
45 |
+
{
|
46 |
+
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
47 |
+
return; // Nothing to do.
|
48 |
+
}
|
49 |
+
if (is_admin()) {
|
50 |
+
return; // Not applicable.
|
51 |
+
}
|
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 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
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.
|
67 |
+
*
|
68 |
+
* @return string The debug info; i.e. full description (if applicable).
|
69 |
+
*/
|
70 |
+
public function maybeGetNcDebugInfo($reason_code = '', $reason = '')
|
71 |
+
{
|
72 |
+
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
73 |
+
return ''; // Not applicable.
|
74 |
+
}
|
75 |
+
$reason = (string) $reason;
|
76 |
+
if (!($reason_code = (string) $reason_code)) {
|
77 |
+
return ''; // Not applicable.
|
78 |
+
}
|
79 |
+
if (!$reason) {
|
80 |
+
switch ($reason_code) {
|
81 |
+
case $this::NC_DEBUG_PHP_SAPI_CLI:
|
82 |
+
$reason = __('because `PHP_SAPI` reports that you are currently running from the command line.', 'comet-cache');
|
83 |
+
break; // Break switch handler.
|
84 |
+
|
85 |
+
case $this::NC_DEBUG_NO_SERVER_HTTP_HOST:
|
86 |
+
$reason = __('because `$_SERVER[\'HTTP_HOST\']` is missing from your server configuration.', 'comet-cache');
|
87 |
+
break; // Break switch handler.
|
88 |
+
|
89 |
+
case $this::NC_DEBUG_NO_SERVER_REQUEST_URI:
|
90 |
+
$reason = __('because `$_SERVER[\'REQUEST_URI\']` is missing from your server configuration.', 'comet-cache');
|
91 |
+
break; // Break switch handler.
|
92 |
+
|
93 |
+
case $this::NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT:
|
94 |
+
if ($this->functionIsPossible('did_action') && did_action('ws_plugin__s2member_during_no_cache_constants')) {
|
95 |
+
$reason = __('because the s2Member plugin set the PHP constant `COMET_CACHE_ALLOWED` to a boolean-ish `FALSE` value at runtime. The s2Member plugin is serving content that must remain dynamic on this particular page, and therefore this page was intentionally not cached for a very good reason.', 'comet-cache');
|
96 |
+
} else {
|
97 |
+
$reason = __('because the PHP constant `COMET_CACHE_ALLOWED` has been set to a boolean-ish `FALSE` value 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');
|
98 |
+
}
|
99 |
+
break; // Break switch handler.
|
100 |
+
|
101 |
+
case $this::NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR:
|
102 |
+
$reason = __('because the environment variable `$_SERVER[\'COMET_CACHE_ALLOWED\']` has been set to a boolean-ish `FALSE` value 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');
|
103 |
+
break; // Break switch handler.
|
104 |
+
|
105 |
+
case $this::NC_DEBUG_DONOTCACHEPAGE_CONSTANT:
|
106 |
+
$reason = __('because the PHP constant `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');
|
107 |
+
break; // Break switch handler.
|
108 |
+
|
109 |
+
case $this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR:
|
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'), strtolower(SHORT_NAME));
|
115 |
+
break; // Break switch handler.
|
116 |
+
|
117 |
+
case $this::NC_DEBUG_UNCACHEABLE_REQUEST:
|
118 |
+
$reason = __('because `$_SERVER[\'REQUEST_METHOD\']` is `POST`, `PUT`, `DELETE`, `HEAD`, `OPTIONS`, `TRACE` or `CONNECT`. These request methods should never (ever) be cached in any way.', 'comet-cache');
|
119 |
+
break; // Break switch handler.
|
120 |
+
|
121 |
+
case $this::NC_DEBUG_SELF_SERVE_REQUEST:
|
122 |
+
$reason = __('because `[current IP address]` === `$_SERVER[\'SERVER_ADDR\']`; i.e. a self-serve request. DEVELOPER TIP: if you are testing on a localhost installation, please add `define(\'LOCALHOST\', TRUE);` to your `/wp-config.php` file while you run tests :-) Remove it (or set it to a `FALSE` value) once you go live on the web.', 'comet-cache');
|
123 |
+
break; // Break switch handler.
|
124 |
+
|
125 |
+
case $this::NC_DEBUG_FEED_REQUEST:
|
126 |
+
$reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a `/feed`; and the configuration of this site says not to cache XML-based feeds.', 'comet-cache');
|
127 |
+
break; // Break switch handler.
|
128 |
+
|
129 |
+
case $this::NC_DEBUG_WP_SYSTEMATICS:
|
130 |
+
$reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a `wp-` or `xmlrpc` file; i.e. a WordPress systematic file. WordPress systematics are never (ever) cached in any way.', 'comet-cache');
|
131 |
+
break; // Break switch handler.
|
132 |
+
|
133 |
+
case $this::NC_DEBUG_WP_ADMIN:
|
134 |
+
$reason = __('because `$_SERVER[\'REQUEST_URI\']` or the `is_admin()` function indicates this is an administrative area of the site.', 'comet-cache');
|
135 |
+
break; // Break switch handler.
|
136 |
+
|
137 |
+
case $this::NC_DEBUG_MS_FILES:
|
138 |
+
$reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a Multisite Network; and this was a request for `/files/*`, not a page.', 'comet-cache');
|
139 |
+
break; // Break switch handler.
|
140 |
+
|
141 |
+
case $this::NC_DEBUG_IS_LOGGED_IN_USER:
|
142 |
+
case $this::NC_DEBUG_IS_LIKE_LOGGED_IN_USER:
|
143 |
+
$reason = __('because the current user visiting this page (usually YOU), appears to be logged-in. The current configuration says NOT to cache pages for logged-in visitors. This message may also appear if you have an active PHP session on this site, or if you\'ve left (or replied to) a comment recently. If this message continues, please clear your cookies and try again.', 'comet-cache');
|
144 |
+
break; // Break switch handler.
|
145 |
+
|
146 |
+
case $this::NC_DEBUG_IS_LOGGED_IN_USER_NONCE:
|
147 |
+
$reason = __('because the current page contains `_wpnonce` or `akismet_comment_nonce`. While your current configuration states that pages SHOULD be cache for logged-in visitors, `*nonce*` values in the markup are not cache-compatible. See http://wsharks.com/1O1Kudy for further details.', 'comet-cache');
|
148 |
+
break; // Break switch handler.
|
149 |
+
|
150 |
+
case $this::NC_DEBUG_PAGE_CONTAINS_NONCE:
|
151 |
+
$reason = __('because the current page contains `_wpnonce` or `akismet_comment_nonce`. Note that `*nonce*` values in the markup are not cache-compatible. See http://wsharks.com/1O1Kudy for further details.', 'comet-cache');
|
152 |
+
break; // Break switch handler.
|
153 |
+
|
154 |
+
case $this::NC_DEBUG_NO_USER_TOKEN:
|
155 |
+
$reason = sprintf(__('because the current user appeared to be logged into the site (in one way or another); but %1$s was unable to formulate a User Token for them. Please report this as a possible bug.', 'comet-cache'), NAME);
|
156 |
+
break; // Break switch handler.
|
157 |
+
|
158 |
+
case $this::NC_DEBUG_GET_REQUEST_QUERIES:
|
159 |
+
$reason = __('because `$_GET` contains query string data. The current configuration says NOT to cache GET requests with a query string.', 'comet-cache');
|
160 |
+
break; // Break switch handler.
|
161 |
+
|
162 |
+
case $this::NC_DEBUG_PREVIEW:
|
163 |
+
$reason = __('because `$_REQUEST` indicates this is simply a preview of something to come.', 'comet-cache');
|
164 |
+
break; // Break switch handler.
|
165 |
+
|
166 |
+
case $this::NC_DEBUG_EXCLUDED_URIS:
|
167 |
+
$reason = __('because `$_SERVER[\'REQUEST_URI\']` matches a configured URI Exclusion Pattern on this installation.', 'comet-cache');
|
168 |
+
break; // Break switch handler.
|
169 |
+
|
170 |
+
case $this::NC_DEBUG_EXCLUDED_AGENTS:
|
171 |
+
$reason = __('because `$_SERVER[\'HTTP_USER_AGENT\']` matches a configured User-Agent Exclusion Pattern on this installation.', 'comet-cache');
|
172 |
+
break; // Break switch handler.
|
173 |
+
|
174 |
+
case $this::NC_DEBUG_EXCLUDED_REFS:
|
175 |
+
$reason = __('because `$_SERVER[\'HTTP_REFERER\']` and/or `$_GET[\'_wp_http_referer\']` matches a configured HTTP Referrer Exclusion Pattern on this installation.', 'comet-cache');
|
176 |
+
break; // Break switch handler.
|
177 |
+
|
178 |
+
case $this::NC_DEBUG_404_REQUEST:
|
179 |
+
$reason = __('because the WordPress `is_404()` Conditional Tag says the current page is a 404 error. The current configuration says NOT to cache 404 errors.', 'comet-cache');
|
180 |
+
break; // Break switch handler.
|
181 |
+
|
182 |
+
case $this::NC_DEBUG_MAINTENANCE_PLUGIN:
|
183 |
+
$reason = __('because a plugin running on this installation says this page is in Maintenance Mode; i.e. is not available publicly at this time.', 'comet-cache');
|
184 |
+
break; // Break switch handler.
|
185 |
+
|
186 |
+
case $this::NC_DEBUG_OB_ZLIB_CODING_TYPE:
|
187 |
+
$reason = sprintf(__('because %1$s is unable to cache already-compressed output. Please use `mod_deflate` w/ Apache; or use `zlib.output_compression` in your `php.ini` file. %1$s is NOT compatible with `ob_gzhandler()` and others like this.', 'comet-cache'), NAME);
|
188 |
+
break; // Break switch handler.
|
189 |
+
|
190 |
+
case $this::NC_DEBUG_WP_ERROR_PAGE:
|
191 |
+
$reason = __('because the contents of this document contain `<body id="error-page">`, which indicates this is an auto-generated WordPress error message.', 'comet-cache');
|
192 |
+
break; // Break switch handler.
|
193 |
+
|
194 |
+
case $this::NC_DEBUG_UNCACHEABLE_CONTENT_TYPE:
|
195 |
+
$reason = __('because a `Content-Type:` header was set via PHP at runtime. The header contains a MIME type which is NOT a variation of HTML or XML. This header might have been set by your hosting company, by WordPress itself; or by one of your themes/plugins.', 'comet-cache');
|
196 |
+
break; // Break switch handler.
|
197 |
+
|
198 |
+
case $this::NC_DEBUG_UNCACHEABLE_STATUS:
|
199 |
+
$reason = __('because a `Status:` header (or an `HTTP/` header) was set via PHP at runtime. The header contains a non-`2xx` status code. This indicates the current page was not loaded successfully. This header might have been set by your hosting company, by WordPress itself; or by one of your themes/plugins.', 'comet-cache');
|
200 |
+
break; // Break switch handler.
|
201 |
+
|
202 |
+
case $this::NC_DEBUG_1ST_TIME_404_SYMLINK:
|
203 |
+
$reason = sprintf(__('because the WordPress `is_404()` Conditional Tag says the current page is a 404 error; and this is the first time it\'s happened on this page. Your current configuration says that 404 errors SHOULD be cached, so %1$s built a cached symlink which points future requests for this location to your already-cached 404 error document. If you reload this page (assuming you don\'t clear the cache before you do so); you should get a cached version of your 404 error document. This message occurs ONCE for each new/unique 404 error request.', 'comet-cache'), NAME);
|
204 |
+
break; // Break switch handler.
|
205 |
+
|
206 |
+
case $this::NC_DEBUG_EARLY_BUFFER_TERMINATION:
|
207 |
+
$reason = sprintf(__('because %1$s detected an early output buffer termination. This may happen when a theme/plugin ends, cleans, or flushes all output buffers before reaching the PHP shutdown phase. It\'s not always a bad thing. Sometimes it is necessary for a theme/plugin to do this. However, in this scenario it is NOT possible to cache the output; since %1$s is effectively disabled at runtime when this occurs.', 'comet-cache'), NAME);
|
208 |
+
break; // Break switch handler.
|
209 |
+
|
210 |
+
default: // Default case handler.
|
211 |
+
$reason = __('due to an unexpected behavior in the application. Please report this as a bug!', 'comet-cache');
|
212 |
+
break; // Break switch handler.
|
213 |
+
}
|
214 |
+
}
|
215 |
+
return "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s is NOT caching this page, %2$s', 'comet-cache'), NAME, $reason)).' -->';
|
216 |
+
}
|
217 |
+
}
|
src/includes/traits/Ac/ObUtils.php
ADDED
@@ -0,0 +1,356 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Ac;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait ObUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Calculated protocol; one of `http://` or `https://`.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @type float One of `http://` or `https://`.
|
14 |
+
*/
|
15 |
+
public $protocol = '';
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Host token for this request.
|
19 |
+
*
|
20 |
+
* @since 150821 Improving multisite compat.
|
21 |
+
*
|
22 |
+
* @type string Host token for this request.
|
23 |
+
*/
|
24 |
+
public $host_token = '';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Host base/dir tokens for this request.
|
28 |
+
*
|
29 |
+
* @since 150821 Improving multisite compat.
|
30 |
+
*
|
31 |
+
* @type string Host base/dir tokens for this request.
|
32 |
+
*/
|
33 |
+
public $host_base_dir_tokens = '';
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Calculated version salt; set by site configuration data.
|
37 |
+
*
|
38 |
+
* @since 150422 Rewrite.
|
39 |
+
*
|
40 |
+
* @type string|mixed Any scalar value does fine.
|
41 |
+
*/
|
42 |
+
public $version_salt = '';
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Relative cache path for the current request.
|
46 |
+
*
|
47 |
+
* @since 150422 Rewrite.
|
48 |
+
*
|
49 |
+
* @type string Cache path for the current request.
|
50 |
+
*/
|
51 |
+
public $cache_path = '';
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Absolute cache file path for the current request.
|
55 |
+
*
|
56 |
+
* @since 150422 Rewrite.
|
57 |
+
*
|
58 |
+
* @type string Absolute cache file path for the current request.
|
59 |
+
*/
|
60 |
+
public $cache_file = '';
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Relative 404 cache path for the current request.
|
64 |
+
*
|
65 |
+
* @since 150422 Rewrite.
|
66 |
+
*
|
67 |
+
* @type string 404 cache path for the current request.
|
68 |
+
*/
|
69 |
+
public $cache_path_404 = '';
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Absolute 404 cache file path for the current request.
|
73 |
+
*
|
74 |
+
* @since 150422 Rewrite.
|
75 |
+
*
|
76 |
+
* @type string Absolute 404 cache file path for the current request.
|
77 |
+
*/
|
78 |
+
public $cache_file_404 = '';
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Version salt followed by the current request location.
|
82 |
+
*
|
83 |
+
* @since 150422 Rewrite.
|
84 |
+
*
|
85 |
+
* @type string Version salt followed by the current request location.
|
86 |
+
*/
|
87 |
+
public $salt_location = '';
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Calculated max age; i.e., before expiration.
|
91 |
+
*
|
92 |
+
* @since 151002 Load average checks in pro version.
|
93 |
+
*
|
94 |
+
* @type int Calculated max age; i.e., before expiration.
|
95 |
+
*/
|
96 |
+
public $cache_max_age = 0;
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Start output buffering (if applicable); or serve a cache file (if possible).
|
100 |
+
*
|
101 |
+
* @since 150422 Rewrite.
|
102 |
+
*
|
103 |
+
* @note This is a vital part of Comet Cache. This method serves existing (fresh) cache files.
|
104 |
+
* It is also responsible for beginning the process of collecting the output buffer.
|
105 |
+
*/
|
106 |
+
public function maybeStartOutputBuffering()
|
107 |
+
{
|
108 |
+
if (strcasecmp(PHP_SAPI, 'cli') === 0) {
|
109 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_PHP_SAPI_CLI);
|
110 |
+
}
|
111 |
+
if (empty($_SERVER['HTTP_HOST']) || !$this->hostToken()) {
|
112 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_NO_SERVER_HTTP_HOST);
|
113 |
+
}
|
114 |
+
if (empty($_SERVER['REQUEST_URI'])) {
|
115 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_NO_SERVER_REQUEST_URI);
|
116 |
+
}
|
117 |
+
if (defined('COMET_CACHE_ALLOWED') && !COMET_CACHE_ALLOWED) {
|
118 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT);
|
119 |
+
}
|
120 |
+
if (isset($_SERVER['COMET_CACHE_ALLOWED']) && !$_SERVER['COMET_CACHE_ALLOWED']) {
|
121 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR);
|
122 |
+
}
|
123 |
+
if (defined('DONOTCACHEPAGE')) {
|
124 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_CONSTANT);
|
125 |
+
}
|
126 |
+
if (isset($_SERVER['DONOTCACHEPAGE'])) {
|
127 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
|
128 |
+
}
|
129 |
+
if (isset($_GET[strtolower(SHORT_NAME).'AC']) && !filter_var($_GET[strtolower(SHORT_NAME).'AC'], FILTER_VALIDATE_BOOLEAN)) {
|
130 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_AC_GET_VAR);
|
131 |
+
}
|
132 |
+
if ($this->isUncacheableRequestMethod()) {
|
133 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_UNCACHEABLE_REQUEST);
|
134 |
+
}
|
135 |
+
if (isset($_SERVER['SERVER_ADDR']) && $this->currentIp() === $_SERVER['SERVER_ADDR']) {
|
136 |
+
if ((!IS_PRO || !$this->isAutoCacheEngine()) && !$this->isLocalhost()) {
|
137 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_SELF_SERVE_REQUEST);
|
138 |
+
}
|
139 |
+
}
|
140 |
+
if (!COMET_CACHE_FEEDS_ENABLE && $this->isFeed()) {
|
141 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_FEED_REQUEST);
|
142 |
+
}
|
143 |
+
if (preg_match('/\/(?:wp\-[^\/]+|xmlrpc)\.php(?:[?]|$)/i', $_SERVER['REQUEST_URI'])) {
|
144 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_WP_SYSTEMATICS);
|
145 |
+
}
|
146 |
+
if (is_admin() || preg_match('/\/wp-admin(?:[\/?]|$)/i', $_SERVER['REQUEST_URI'])) {
|
147 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_WP_ADMIN);
|
148 |
+
}
|
149 |
+
if (is_multisite() && preg_match('/\/files(?:[\/?]|$)/i', $_SERVER['REQUEST_URI'])) {
|
150 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_MS_FILES);
|
151 |
+
}
|
152 |
+
if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $this->isLikeUserLoggedIn()) {
|
153 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_IS_LIKE_LOGGED_IN_USER);
|
154 |
+
}
|
155 |
+
if (!COMET_CACHE_GET_REQUESTS && $this->requestContainsUncacheableQueryVars()) {
|
156 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_GET_REQUEST_QUERIES);
|
157 |
+
}
|
158 |
+
if (!empty($_REQUEST['preview'])) {
|
159 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_PREVIEW);
|
160 |
+
}
|
161 |
+
if (COMET_CACHE_EXCLUDE_URIS && preg_match(COMET_CACHE_EXCLUDE_URIS, $_SERVER['REQUEST_URI'])) {
|
162 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_EXCLUDED_URIS);
|
163 |
+
}
|
164 |
+
if (COMET_CACHE_EXCLUDE_AGENTS && !empty($_SERVER['HTTP_USER_AGENT']) && (!IS_PRO || !$this->isAutoCacheEngine())) {
|
165 |
+
if (preg_match(COMET_CACHE_EXCLUDE_AGENTS, $_SERVER['HTTP_USER_AGENT'])) {
|
166 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_EXCLUDED_AGENTS);
|
167 |
+
}
|
168 |
+
}
|
169 |
+
if (COMET_CACHE_EXCLUDE_REFS && !empty($_REQUEST['_wp_http_referer'])) {
|
170 |
+
if (preg_match(COMET_CACHE_EXCLUDE_REFS, stripslashes($_REQUEST['_wp_http_referer']))) {
|
171 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_EXCLUDED_REFS);
|
172 |
+
}
|
173 |
+
}
|
174 |
+
if (COMET_CACHE_EXCLUDE_REFS && !empty($_SERVER['HTTP_REFERER'])) {
|
175 |
+
if (preg_match(COMET_CACHE_EXCLUDE_REFS, $_SERVER['HTTP_REFERER'])) {
|
176 |
+
return $this->maybeSetDebugInfo($this::NC_DEBUG_EXCLUDED_REFS);
|
177 |
+
}
|
178 |
+
}
|
179 |
+
$this->protocol = $this->isSsl() ? 'https://' : 'http://';
|
180 |
+
$this->host_token = $this->hostToken();
|
181 |
+
$this->host_base_dir_tokens = $this->hostBaseDirTokens();
|
182 |
+
|
183 |
+
$this->version_salt = ''; // Initialize the version salt.
|
184 |
+
|
185 |
+
$this->version_salt = $this->applyFilters(get_class($this).'__version_salt', $this->version_salt);
|
186 |
+
$this->version_salt = $this->applyFilters(GLOBAL_NS.'_version_salt', $this->version_salt);
|
187 |
+
|
188 |
+
$this->cache_path = $this->buildCachePath($this->protocol.$this->host_token.$_SERVER['REQUEST_URI'], '', $this->version_salt);
|
189 |
+
$this->cache_file = COMET_CACHE_DIR.'/'.$this->cache_path; // Not considering a user cache. That's done in the postload phase.
|
190 |
+
|
191 |
+
$this->cache_path_404 = $this->buildCachePath($this->protocol.$this->host_token.rtrim($this->host_base_dir_tokens, '/').'/'.COMET_CACHE_404_CACHE_FILENAME);
|
192 |
+
$this->cache_file_404 = COMET_CACHE_DIR.'/'.$this->cache_path_404; // Not considering a user cache at all here--ever.
|
193 |
+
|
194 |
+
$this->salt_location = ltrim($this->version_salt.' '.$this->protocol.$this->host_token.$_SERVER['REQUEST_URI']);
|
195 |
+
|
196 |
+
$this->cache_max_age = strtotime('-'.COMET_CACHE_MAX_AGE);
|
197 |
+
|
198 |
+
if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN === 'postload' && $this->isLikeUserLoggedIn()) {
|
199 |
+
$this->postload['when_logged_in'] = true; // Enable postload check.
|
200 |
+
} elseif (is_file($this->cache_file) && (!$this->cache_max_age || filemtime($this->cache_file) >= $this->cache_max_age)) {
|
201 |
+
list($headers, $cache) = explode('<!--headers-->', file_get_contents($this->cache_file), 2);
|
202 |
+
|
203 |
+
$headers_list = $this->headersList();
|
204 |
+
foreach (unserialize($headers) as $_header) {
|
205 |
+
if (!in_array($_header, $headers_list, true) && stripos($_header, 'Last-Modified:') !== 0) {
|
206 |
+
header($_header); // Only cacheable/safe headers are stored in the cache.
|
207 |
+
}
|
208 |
+
}
|
209 |
+
unset($_header); // Just a little housekeeping.
|
210 |
+
|
211 |
+
if (COMET_CACHE_DEBUGGING_ENABLE && $this->isHtmlXmlDoc($cache)) {
|
212 |
+
$total_time = number_format(microtime(true) - $this->timer, 5, '.', '');
|
213 |
+
$cache .= "\n".'<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->';
|
214 |
+
// translators: This string is actually NOT translatable because the `__()` function is not available at this point in the processing.
|
215 |
+
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s fully functional :-) Cache file served for (%2$s) in %3$s seconds, on: %4$s.', 'comet-cache'), NAME, $this->salt_location, $total_time, date('M jS, Y @ g:i a T'))).' -->';
|
216 |
+
}
|
217 |
+
exit($cache); // Exit with cache contents.
|
218 |
+
} else {
|
219 |
+
ob_start([$this, 'outputBufferCallbackHandler']);
|
220 |
+
}
|
221 |
+
return; // Return value not applicable.
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Output buffer handler; i.e. the cache file generator.
|
226 |
+
*
|
227 |
+
* @note We CANNOT depend on any WP functionality here; it will cause problems.
|
228 |
+
* Anything we need from WP should be saved in the postload phase as a scalar value.
|
229 |
+
*
|
230 |
+
* @since 150422 Rewrite.
|
231 |
+
*
|
232 |
+
* @param string $buffer The buffer from {@link \ob_start()}.
|
233 |
+
* @param int $phase A set of bitmask flags.
|
234 |
+
*
|
235 |
+
* @throws \Exception If unable to handle output buffering for any reason.
|
236 |
+
*
|
237 |
+
* @return string|bool The output buffer, or `FALSE` to indicate no change.
|
238 |
+
*
|
239 |
+
* @attaches-to {@link \ob_start()}
|
240 |
+
*/
|
241 |
+
public function outputBufferCallbackHandler($buffer, $phase)
|
242 |
+
{
|
243 |
+
if (!($phase & PHP_OUTPUT_HANDLER_END)) {
|
244 |
+
throw new \Exception(sprintf(__('Unexpected OB phase: `%1$s`.', 'comet-cache'), $phase));
|
245 |
+
}
|
246 |
+
Classes\AdvCacheBackCompat::zenCacheConstants();
|
247 |
+
|
248 |
+
$cache = trim((string) $buffer);
|
249 |
+
|
250 |
+
if (!isset($cache[0])) {
|
251 |
+
return false; // Don't cache an empty buffer.
|
252 |
+
}
|
253 |
+
if (!isset($GLOBALS[GLOBAL_NS.'_shutdown_flag'])) {
|
254 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_EARLY_BUFFER_TERMINATION);
|
255 |
+
}
|
256 |
+
if (defined('COMET_CACHE_ALLOWED') && !COMET_CACHE_ALLOWED) {
|
257 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_COMET_CACHE_ALLOWED_CONSTANT);
|
258 |
+
}
|
259 |
+
if (isset($_SERVER['COMET_CACHE_ALLOWED']) && !$_SERVER['COMET_CACHE_ALLOWED']) {
|
260 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_COMET_CACHE_ALLOWED_SERVER_VAR);
|
261 |
+
}
|
262 |
+
if (defined('DONOTCACHEPAGE')) {
|
263 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_CONSTANT);
|
264 |
+
}
|
265 |
+
if (isset($_SERVER['DONOTCACHEPAGE'])) {
|
266 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR);
|
267 |
+
}
|
268 |
+
if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $this->is_user_logged_in) {
|
269 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_IS_LOGGED_IN_USER);
|
270 |
+
}
|
271 |
+
if ((!IS_PRO || !COMET_CACHE_WHEN_LOGGED_IN) && $this->isLikeUserLoggedIn()) {
|
272 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_IS_LIKE_LOGGED_IN_USER);
|
273 |
+
}
|
274 |
+
if (!COMET_CACHE_CACHE_NONCE_VALUES && preg_match('/\b(?:_wpnonce|akismet_comment_nonce)\b/', $cache)) {
|
275 |
+
if (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $this->isLikeUserLoggedIn()) {
|
276 |
+
if (!COMET_CACHE_CACHE_NONCE_VALUES_WHEN_LOGGED_IN) {
|
277 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_IS_LOGGED_IN_USER_NONCE);
|
278 |
+
}
|
279 |
+
} else { // Use the default debug notice for nonce conflicts.
|
280 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_PAGE_CONTAINS_NONCE);
|
281 |
+
} // An nonce makes the page dynamic; i.e., NOT cache compatible.
|
282 |
+
}
|
283 |
+
if ($this->is_404 && !COMET_CACHE_CACHE_404_REQUESTS) {
|
284 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_404_REQUEST);
|
285 |
+
}
|
286 |
+
if (stripos($cache, '<body id="error-page">') !== false) {
|
287 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_WP_ERROR_PAGE);
|
288 |
+
}
|
289 |
+
if (!$this->hasACacheableContentType()) {
|
290 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_UNCACHEABLE_CONTENT_TYPE);
|
291 |
+
}
|
292 |
+
if (!$this->hasACacheableStatus()) {
|
293 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_UNCACHEABLE_STATUS);
|
294 |
+
}
|
295 |
+
if ($this->is_maintenance) {
|
296 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_MAINTENANCE_PLUGIN);
|
297 |
+
}
|
298 |
+
if ($this->functionIsPossible('zlib_get_coding_type') && zlib_get_coding_type()
|
299 |
+
&& (!($zlib_oc = ini_get('zlib.output_compression')) || !filter_var($zlib_oc, FILTER_VALIDATE_BOOLEAN))
|
300 |
+
) {
|
301 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_OB_ZLIB_CODING_TYPE);
|
302 |
+
}
|
303 |
+
# Lock the cache directory while writes take place here.
|
304 |
+
|
305 |
+
$cache_lock = $this->cacheLock(); // Lock cache directory.
|
306 |
+
|
307 |
+
# Construct a temp file for atomic cache writes.
|
308 |
+
|
309 |
+
$cache_file_tmp = $this->addTmpSuffix($this->cache_file);
|
310 |
+
|
311 |
+
# Cache directory checks. The cache file directory is created here if necessary.
|
312 |
+
|
313 |
+
if (!is_dir(COMET_CACHE_DIR) && mkdir(COMET_CACHE_DIR, 0775, true) && !is_file(COMET_CACHE_DIR.'/.htaccess')) {
|
314 |
+
file_put_contents(COMET_CACHE_DIR.'/.htaccess', $this->htaccess_deny);
|
315 |
+
}
|
316 |
+
if (!is_dir($cache_file_dir = dirname($this->cache_file))) {
|
317 |
+
$cache_file_dir_writable = mkdir($cache_file_dir, 0775, true);
|
318 |
+
}
|
319 |
+
if (empty($cache_file_dir_writable) && !is_writable($cache_file_dir)) {
|
320 |
+
throw new \Exception(sprintf(__('Cache directory not writable. %1$s needs this directory please: `%2$s`. Set permissions to `755` or higher; `777` might be needed in some cases.', 'comet-cache'), NAME, $cache_file_dir));
|
321 |
+
}
|
322 |
+
# This is where a new 404 request might be detected for the first time.
|
323 |
+
|
324 |
+
if ($this->is_404 && is_file($this->cache_file_404)) {
|
325 |
+
if (!(symlink($this->cache_file_404, $cache_file_tmp) && rename($cache_file_tmp, $this->cache_file))) {
|
326 |
+
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));
|
327 |
+
}
|
328 |
+
$this->cacheUnlock($cache_lock); // Release.
|
329 |
+
return (boolean) $this->maybeSetDebugInfo($this::NC_DEBUG_1ST_TIME_404_SYMLINK);
|
330 |
+
}
|
331 |
+
/* ------- Otherwise, we need to construct & store a new cache file. ----------------------------------------------- */
|
332 |
+
|
333 |
+
|
334 |
+
|
335 |
+
if (COMET_CACHE_DEBUGGING_ENABLE && $this->isHtmlXmlDoc($cache)) {
|
336 |
+
$total_time = number_format(microtime(true) - $this->timer, 5, '.', ''); // Based on the original timer.
|
337 |
+
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s file path: %2$s', 'comet-cache'), NAME, str_replace(WP_CONTENT_DIR, '', $this->is_404 ? $this->cache_file_404 : $this->cache_file))).' -->';
|
338 |
+
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('%1$s file built for (%2$s%3$s) in %4$s seconds, on: %5$s.', 'comet-cache'), NAME, $this->is_404 ? '404 [error document]' : $this->salt_location, (IS_PRO && COMET_CACHE_WHEN_LOGGED_IN && $this->user_token ? '; '.sprintf(__('user token: %1$s', 'comet-cache'), $this->user_token) : ''), $total_time, date('M jS, Y @ g:i a T'))).' -->';
|
339 |
+
$cache .= "\n".'<!-- '.htmlspecialchars(sprintf(__('This %1$s file will auto-expire (and be rebuilt) on: %2$s (based on your configured expiration time).', 'comet-cache'), NAME, date('M jS, Y @ g:i a T', strtotime('+'.COMET_CACHE_MAX_AGE)))).' -->';
|
340 |
+
}
|
341 |
+
if ($this->is_404) {
|
342 |
+
if (file_put_contents($cache_file_tmp, serialize($this->cacheableHeadersList()).'<!--headers-->'.$cache) && rename($cache_file_tmp, $this->cache_file_404)) {
|
343 |
+
if (!(symlink($this->cache_file_404, $cache_file_tmp) && rename($cache_file_tmp, $this->cache_file))) {
|
344 |
+
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));
|
345 |
+
}
|
346 |
+
$this->cacheUnlock($cache_lock); // Release.
|
347 |
+
return $cache; // Return the newly built cache; with possible debug information also.
|
348 |
+
}
|
349 |
+
} elseif (file_put_contents($cache_file_tmp, serialize($this->cacheableHeadersList()).'<!--headers-->'.$cache) && rename($cache_file_tmp, $this->cache_file)) {
|
350 |
+
$this->cacheUnlock($cache_lock); // Release.
|
351 |
+
return $cache; // Return the newly built cache; with possible debug information also.
|
352 |
+
}
|
353 |
+
@unlink($cache_file_tmp); // Clean this up (if it exists); and throw an exception with information for the site owner.
|
354 |
+
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));
|
355 |
+
}
|
356 |
+
}
|
src/includes/traits/Ac/PostloadUtils.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Ac;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait PostloadUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Have we caught the main WP loaded being loaded yet?
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @type bool `TRUE` if main query has been loaded; else `FALSE`.
|
14 |
+
*
|
15 |
+
* @see wpMainQueryPostload()
|
16 |
+
*/
|
17 |
+
public $is_wp_loaded_query = false;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Is the current request a WordPress 404 error?
|
21 |
+
*
|
22 |
+
* @since 150422 Rewrite.
|
23 |
+
*
|
24 |
+
* @type bool `TRUE` if is a 404 error; else `FALSE`.
|
25 |
+
*
|
26 |
+
* @see wpMainQueryPostload()
|
27 |
+
*/
|
28 |
+
public $is_404 = false;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Last HTTP status code passed through {@link \status_header}.
|
32 |
+
*
|
33 |
+
* @since 150422 Rewrite.
|
34 |
+
*
|
35 |
+
* @type int Last HTTP status code (if applicable).
|
36 |
+
*
|
37 |
+
* @see maybeFilterStatusHeaderPostload()
|
38 |
+
*/
|
39 |
+
public $http_status = 0;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Is the current request a WordPress content type?
|
43 |
+
*
|
44 |
+
* @since 150422 Rewrite.
|
45 |
+
*
|
46 |
+
* @type bool `TRUE` if is a WP content type.
|
47 |
+
*
|
48 |
+
* @see wpMainQueryPostload()
|
49 |
+
*/
|
50 |
+
public $is_a_wp_content_type = false;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Current WordPress {@link \content_url()}.
|
54 |
+
*
|
55 |
+
* @since 150422 Rewrite.
|
56 |
+
*
|
57 |
+
* @type string Current WordPress {@link \content_url()}.
|
58 |
+
*
|
59 |
+
* @see wpMainQueryPostload()
|
60 |
+
*/
|
61 |
+
public $content_url = '';
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Flag for {@link \is_user_loged_in()}.
|
65 |
+
*
|
66 |
+
* @since 150422 Rewrite.
|
67 |
+
*
|
68 |
+
* @type bool `TRUE` if {@link \is_user_loged_in()} else `FALSE`.
|
69 |
+
*
|
70 |
+
* @see wpMainQueryPostload()
|
71 |
+
*/
|
72 |
+
public $is_user_logged_in = false;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Flag for {@link \is_maintenance()}.
|
76 |
+
*
|
77 |
+
* @since 150422 Rewrite.
|
78 |
+
*
|
79 |
+
* @type bool `TRUE` if {@link \is_maintenance()} else `FALSE`.
|
80 |
+
*
|
81 |
+
* @see wpMainQueryPostload()
|
82 |
+
*/
|
83 |
+
public $is_maintenance = false;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Array of data targeted at the postload phase.
|
87 |
+
*
|
88 |
+
* @since 150422 Rewrite.
|
89 |
+
*
|
90 |
+
* @type array Data and/or flags that work with various postload handlers.
|
91 |
+
*/
|
92 |
+
public $postload = [
|
93 |
+
|
94 |
+
'filter_status_header' => true,
|
95 |
+
'wp_main_query' => true,
|
96 |
+
'set_debug_info' => COMET_CACHE_DEBUGGING_ENABLE,
|
97 |
+
];
|
98 |
+
|
99 |
+
|
100 |
+
|
101 |
+
|
102 |
+
|
103 |
+
|
104 |
+
|
105 |
+
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Filters WP {@link \status_header()} (if applicable).
|
109 |
+
*
|
110 |
+
* @since 150422 Rewrite.
|
111 |
+
*/
|
112 |
+
public function maybeFilterStatusHeaderPostload()
|
113 |
+
{
|
114 |
+
if (empty($this->postload['filter_status_header'])) {
|
115 |
+
return; // Nothing to do in this case.
|
116 |
+
}
|
117 |
+
|
118 |
+
add_filter(
|
119 |
+
'status_header',
|
120 |
+
function ($status_header, $status_code) {
|
121 |
+
if ($status_code > 0) {
|
122 |
+
$this->http_status = (integer) $status_code;
|
123 |
+
}
|
124 |
+
return $status_header;
|
125 |
+
},
|
126 |
+
PHP_INT_MAX,
|
127 |
+
2
|
128 |
+
);
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Hooks `NC_DEBUG_` info into the WordPress `shutdown` phase (if applicable).
|
133 |
+
*
|
134 |
+
* @since 150422 Rewrite.
|
135 |
+
*/
|
136 |
+
public function maybeSetDebugInfoPostload()
|
137 |
+
{
|
138 |
+
if (!COMET_CACHE_DEBUGGING_ENABLE) {
|
139 |
+
return; // Nothing to do.
|
140 |
+
}
|
141 |
+
if (empty($this->postload['set_debug_info'])) {
|
142 |
+
return; // Nothing to do in this case.
|
143 |
+
}
|
144 |
+
if (is_admin()) {
|
145 |
+
return; // Not applicable.
|
146 |
+
}
|
147 |
+
if (strcasecmp(PHP_SAPI, 'cli') === 0) {
|
148 |
+
return; // Let's not run the risk here.
|
149 |
+
}
|
150 |
+
add_action('shutdown', [$this, 'maybeEchoNcDebugInfo'], PHP_INT_MAX - 10);
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Grab details from WP and the Comet Cache plugin itself,
|
155 |
+
* after the main query is loaded (if at all possible).
|
156 |
+
*
|
157 |
+
* This is where we have a chance to grab any values we need from WordPress; or from the CC plugin.
|
158 |
+
* It is EXTREMEMLY important that we NOT attempt to grab any object references here.
|
159 |
+
* Anything acquired in this phase should be stored as a scalar value.
|
160 |
+
* See {@link outputBufferCallbackHandler()} for further details.
|
161 |
+
*
|
162 |
+
* @since 150422 Rewrite.
|
163 |
+
*
|
164 |
+
* @attaches-to `wp` hook.
|
165 |
+
*/
|
166 |
+
public function wpMainQueryPostload()
|
167 |
+
{
|
168 |
+
if (empty($this->postload['wp_main_query'])) {
|
169 |
+
return; // Nothing to do in this case.
|
170 |
+
}
|
171 |
+
if ($this->is_wp_loaded_query || is_admin()) {
|
172 |
+
return; // Nothing to do.
|
173 |
+
}
|
174 |
+
if (!is_main_query()) {
|
175 |
+
return; // Not main query.
|
176 |
+
}
|
177 |
+
$this->is_wp_loaded_query = true;
|
178 |
+
$this->is_404 = is_404();
|
179 |
+
$this->is_user_logged_in = is_user_logged_in();
|
180 |
+
$this->content_url = rtrim(content_url(), '/');
|
181 |
+
$this->is_maintenance = $this->functionIsPossible('is_maintenance') && is_maintenance();
|
182 |
+
|
183 |
+
add_action(
|
184 |
+
'template_redirect',
|
185 |
+
function () {
|
186 |
+
$this->is_a_wp_content_type = $this->is_404 || $this->is_maintenance
|
187 |
+
|| is_front_page() // See <https://core.trac.wordpress.org/ticket/21602#comment:7>
|
188 |
+
|| is_home() || is_singular() || is_archive() || is_post_type_archive() || is_tax() || is_search() || is_feed();
|
189 |
+
},
|
190 |
+
11
|
191 |
+
);
|
192 |
+
}
|
193 |
+
}
|
src/includes/traits/Ac/ShutdownUtils.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Ac;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait ShutdownUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Registers a shutdown flag.
|
10 |
+
*
|
11 |
+
* @since 140605 Improving output buffer.
|
12 |
+
*
|
13 |
+
* @note In `/wp-settings.php`, Comet Cache is loaded before WP registers its own shutdown function.
|
14 |
+
* Therefore, this flag is set before {@link shutdown_action_hook()} fires, and thus before {@link wp_ob_end_flush_all()}.
|
15 |
+
*
|
16 |
+
* @see http://www.php.net/manual/en/function.register-shutdown-function.php
|
17 |
+
*/
|
18 |
+
public function registerShutdownFlag()
|
19 |
+
{
|
20 |
+
register_shutdown_function(
|
21 |
+
function () {
|
22 |
+
$GLOBALS[GLOBAL_NS.'_shutdown_flag'] = -1;
|
23 |
+
}
|
24 |
+
);
|
25 |
+
}
|
26 |
+
}
|
src/includes/traits/Plugin/ActionUtils.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait ActionUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Plugin action handler.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @attaches-to `wp_loaded` hook.
|
14 |
+
*/
|
15 |
+
public function actions()
|
16 |
+
{
|
17 |
+
if (!empty($_REQUEST[GLOBAL_NS])) {
|
18 |
+
new Classes\Actions();
|
19 |
+
}
|
20 |
+
|
21 |
+
}
|
22 |
+
}
|
src/includes/traits/Plugin/BbPressUtils.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait BbPressUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Is bbPress active?
|
10 |
+
*
|
11 |
+
* @since 150821 Improving bbPress support.
|
12 |
+
*
|
13 |
+
* @return bool `TRUE` if bbPress is active.
|
14 |
+
*/
|
15 |
+
public function isBbPressActive()
|
16 |
+
{
|
17 |
+
return class_exists('bbPress');
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* bbPress post types.
|
22 |
+
*
|
23 |
+
* @since 150821 Improving bbPress support.
|
24 |
+
*
|
25 |
+
* @return array All bbPress post types.
|
26 |
+
*/
|
27 |
+
public function bbPressPostTypes()
|
28 |
+
{
|
29 |
+
if (!$this->isBbPressActive()) {
|
30 |
+
return [];
|
31 |
+
}
|
32 |
+
if (!is_null($types = &$this->cacheKey('bbPressPostTypes'))) {
|
33 |
+
return $types; // Already did this.
|
34 |
+
}
|
35 |
+
$types = []; // Initialize.
|
36 |
+
$types[] = bbp_get_forum_post_type();
|
37 |
+
$types[] = bbp_get_topic_post_type();
|
38 |
+
$types[] = bbp_get_reply_post_type();
|
39 |
+
|
40 |
+
return $types;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* bbPress post statuses.
|
45 |
+
*
|
46 |
+
* @since 150821 Improving bbPress support.
|
47 |
+
*
|
48 |
+
* @return array All bbPress post statuses.
|
49 |
+
*/
|
50 |
+
public function bbPressStatuses()
|
51 |
+
{
|
52 |
+
if (!$this->isBbPressActive()) {
|
53 |
+
return [];
|
54 |
+
}
|
55 |
+
if (!is_null($statuses = &$this->cacheKey('bbPressStatuses'))) {
|
56 |
+
return $statuses; // Already did this.
|
57 |
+
}
|
58 |
+
$statuses = []; // Initialize.
|
59 |
+
|
60 |
+
foreach (get_post_stati([], 'objects') as $_key => $_status) {
|
61 |
+
if (isset($_status->label_count['domain']) && $_status->label_count['domain'] === 'bbpress') {
|
62 |
+
$statuses[] = $_status->name;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
unset($_key, $_status); // Housekeeping.
|
66 |
+
|
67 |
+
return $statuses;
|
68 |
+
}
|
69 |
+
}
|
src/includes/traits/Plugin/CleanupUtils.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait CleanupUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Runs cleanup routine via CRON job.
|
10 |
+
*
|
11 |
+
* @since 151002 While working on directory stats.
|
12 |
+
*
|
13 |
+
* @attaches-to `'_cron_'.__GLOBAL_NS__.'_cleanup'`
|
14 |
+
*/
|
15 |
+
public function cleanupCache()
|
16 |
+
{
|
17 |
+
if (!$this->options['enable']) {
|
18 |
+
return; // Nothing to do.
|
19 |
+
}
|
20 |
+
|
21 |
+
|
22 |
+
|
23 |
+
$this->wurgeCache(); // Purge now.
|
24 |
+
}
|
25 |
+
}
|
src/includes/traits/Plugin/CondUtils.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait CondUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Is pro preview?
|
10 |
+
*
|
11 |
+
* @since 150511 Rewrite.
|
12 |
+
*
|
13 |
+
* @return bool `TRUE` if it's a pro preview.
|
14 |
+
*/
|
15 |
+
public function isProPreview()
|
16 |
+
{
|
17 |
+
return !empty($_REQUEST[GLOBAL_NS.'_pro_preview']);
|
18 |
+
}
|
19 |
+
}
|
src/includes/traits/Plugin/CronUtils.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait CronUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Extends WP-Cron schedules.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @attaches-to `cron_schedules` filter.
|
14 |
+
*
|
15 |
+
* @param array $schedules An array of the current schedules.
|
16 |
+
*
|
17 |
+
* @return array Revised array of WP-Cron schedules.
|
18 |
+
*/
|
19 |
+
public function extendCronSchedules($schedules)
|
20 |
+
{
|
21 |
+
$schedules['every15m'] = [
|
22 |
+
'interval' => 900,
|
23 |
+
'display' => __('Every 15 Minutes', 'comet-cache'),
|
24 |
+
];
|
25 |
+
return $schedules;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Checks Cron setup, validates schedules, and reschedules events if necessary.
|
30 |
+
*
|
31 |
+
* @attaches-to `init` hook.
|
32 |
+
*
|
33 |
+
* @since 151220 Improving WP Cron setup and validation of schedules
|
34 |
+
*/
|
35 |
+
public function checkCronSetup()
|
36 |
+
{
|
37 |
+
if ($this->options['crons_setup'] < 1439005906
|
38 |
+
|| $this->options['crons_setup_on_namespace'] !== __NAMESPACE__
|
39 |
+
|| $this->options['crons_setup_with_cache_cleanup_schedule'] !== $this->options['cache_cleanup_schedule']
|
40 |
+
|| $this->options['crons_setup_on_wp_with_schedules'] !== sha1(serialize(wp_get_schedules()))
|
41 |
+
|| !wp_next_scheduled('_cron_'.GLOBAL_NS.'_cleanup')
|
42 |
+
|
43 |
+
) {
|
44 |
+
wp_clear_scheduled_hook('_cron_'.GLOBAL_NS.'_cleanup');
|
45 |
+
wp_schedule_event(time() + 60, $this->options['cache_cleanup_schedule'], '_cron_'.GLOBAL_NS.'_cleanup');
|
46 |
+
|
47 |
+
|
48 |
+
|
49 |
+
$this->updateOptions(
|
50 |
+
[
|
51 |
+
'crons_setup' => time(),
|
52 |
+
'crons_setup_on_namespace' => __NAMESPACE__,
|
53 |
+
'crons_setup_with_cache_cleanup_schedule' => $this->options['cache_cleanup_schedule'],
|
54 |
+
'crons_setup_on_wp_with_schedules' => sha1(serialize(wp_get_schedules())),
|
55 |
+
]
|
56 |
+
);
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Resets `crons_setup` and clears WP-Cron schedules.
|
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 |
+
{
|
69 |
+
if (is_multisite()) { // Main site CRON jobs.
|
70 |
+
switch_to_blog(get_current_site()->blog_id);
|
71 |
+
|
72 |
+
wp_clear_scheduled_hook('_cron_'.GLOBAL_NS.'_cleanup');
|
73 |
+
restore_current_blog(); // Restore current blog.
|
74 |
+
} else { // Standard WP installation.
|
75 |
+
|
76 |
+
wp_clear_scheduled_hook('_cron_'.GLOBAL_NS.'_cleanup');
|
77 |
+
}
|
78 |
+
$this->updateOptions(
|
79 |
+
[ // Reset so that crons are rescheduled upon next activation
|
80 |
+
'crons_setup' => $this->default_options['crons_setup'],
|
81 |
+
'crons_setup_on_namespace' => $this->default_options['crons_setup_on_namespace'],
|
82 |
+
'crons_setup_with_cache_cleanup_schedule' => $this->default_options['crons_setup_with_cache_cleanup_schedule'],
|
83 |
+
'crons_setup_on_wp_with_schedules' => $this->default_options['crons_setup_on_wp_with_schedules'],
|
84 |
+
]
|
85 |
+
);
|
86 |
+
}
|
87 |
+
}
|
src/includes/traits/Plugin/DbUtils.php
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait DbUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* WordPress database instance.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @return \wpdb Reference for IDEs.
|
14 |
+
*/
|
15 |
+
public function wpdb()
|
16 |
+
{
|
17 |
+
return $GLOBALS['wpdb'];
|
18 |
+
}
|
19 |
+
}
|
src/includes/traits/Plugin/DirUtils.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait DirUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* This constructs an absolute server directory path (no trailing slashes);
|
10 |
+
* which is always nested into {@link \WP_CONTENT_DIR} and the configured `base_dir` option value.
|
11 |
+
*
|
12 |
+
* @since 150422 Rewrite.
|
13 |
+
*
|
14 |
+
* @param string $rel_dir_file A sub-directory or file; relative location please.
|
15 |
+
*
|
16 |
+
* @throws \Exception If `base_dir` is empty when this method is called upon;
|
17 |
+
* i.e. if you attempt to call upon this method before {@link setup()} runs.
|
18 |
+
*
|
19 |
+
* @return string The full absolute server path to `$rel_dir_file`.
|
20 |
+
*/
|
21 |
+
public function wpContentBaseDirTo($rel_dir_file)
|
22 |
+
{
|
23 |
+
$rel_dir_file = trim((string) $rel_dir_file, '\\/'." \t\n\r\0\x0B");
|
24 |
+
|
25 |
+
if (empty($this->options['base_dir'])) {
|
26 |
+
throw new \Exception(__('Missing `base_dir` option value.', 'comet-cache'));
|
27 |
+
}
|
28 |
+
$wp_content_base_dir_to = WP_CONTENT_DIR.'/'.$this->options['base_dir'];
|
29 |
+
|
30 |
+
if (isset($rel_dir_file[0])) {
|
31 |
+
$wp_content_base_dir_to .= '/'.$rel_dir_file;
|
32 |
+
}
|
33 |
+
return $wp_content_base_dir_to;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* This constructs a relative/base directory path (no leading/trailing slashes).
|
38 |
+
* Always relative to {@link \WP_CONTENT_DIR}. Depends on the configured `base_dir` option value.
|
39 |
+
*
|
40 |
+
* @since 150422 Rewrite.
|
41 |
+
*
|
42 |
+
* @param string $rel_dir_file A sub-directory or file; relative location please.
|
43 |
+
*
|
44 |
+
* @throws \Exception If `base_dir` is empty when this method is called upon;
|
45 |
+
* i.e. if you attempt to call upon this method before {@link setup()} runs.
|
46 |
+
*
|
47 |
+
* @return string The relative/base directory path to `$rel_dir_file`.
|
48 |
+
*/
|
49 |
+
public function basePathTo($rel_dir_file)
|
50 |
+
{
|
51 |
+
$rel_dir_file = trim((string) $rel_dir_file, '\\/'." \t\n\r\0\x0B");
|
52 |
+
|
53 |
+
if (empty($this->options['base_dir'])) {
|
54 |
+
throw new \Exception(__('Missing `base_dir` option value.', 'comet-cache'));
|
55 |
+
}
|
56 |
+
$base_path_to = $this->options['base_dir'];
|
57 |
+
|
58 |
+
if (isset($rel_dir_file[0])) {
|
59 |
+
$base_path_to .= '/'.$rel_dir_file;
|
60 |
+
}
|
61 |
+
return $base_path_to;
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Get the absolute filesystem path to the root of the WordPress installation.
|
66 |
+
*
|
67 |
+
* Copied verbatim from get_home_path() in wp-admin/includes/file.php
|
68 |
+
*
|
69 |
+
* @since 151114 Adding `.htaccess` tweaks.
|
70 |
+
*
|
71 |
+
* @return string Full filesystem path to the root of the WordPress installation
|
72 |
+
*/
|
73 |
+
public function wpHomePath()
|
74 |
+
{
|
75 |
+
$home = set_url_scheme(get_option('home'), 'http');
|
76 |
+
$siteurl = set_url_scheme(get_option('siteurl'), 'http');
|
77 |
+
if (!empty($home) && 0 !== strcasecmp($home, $siteurl)) {
|
78 |
+
$wp_path_rel_to_home = str_ireplace($home, '', $siteurl); /* $siteurl - $home */
|
79 |
+
$pos = strripos(str_replace('\\', '/', $_SERVER['SCRIPT_FILENAME']), trailingslashit($wp_path_rel_to_home));
|
80 |
+
$home_path = substr($_SERVER['SCRIPT_FILENAME'], 0, $pos);
|
81 |
+
$home_path = trailingslashit($home_path);
|
82 |
+
} else {
|
83 |
+
$home_path = ABSPATH;
|
84 |
+
}
|
85 |
+
return str_replace('\\', '/', $home_path);
|
86 |
+
}
|
87 |
+
}
|
src/includes/traits/Plugin/HtaccessUtils.php
ADDED
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait HtaccessUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Unique comment marker.
|
10 |
+
*
|
11 |
+
* @since 151220 Enhancing `.htaccess` tweaks.
|
12 |
+
*
|
13 |
+
* @return string Used in `.htaccess` parsing.
|
14 |
+
*/
|
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'];
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Add template blocks to `/.htaccess` file.
|
30 |
+
*
|
31 |
+
* @since 151114 Adding `.htaccess` tweaks.
|
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;
|
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.
|
46 |
+
}
|
47 |
+
if (!$this->needHtaccessRules()) {
|
48 |
+
if ($this->findHtaccessMarker()) { // Do we need to clean up previously added rules?
|
49 |
+
$this->removeWpHtaccess(); // Fail silently since we don't need rules in place.
|
50 |
+
}
|
51 |
+
return true; // Nothing to do; no options enabled that require htaccess rules.
|
52 |
+
}
|
53 |
+
if (!$this->removeWpHtaccess()) {
|
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 |
+
if (is_dir($templates_dir = dirname(dirname(__DIR__)).'/templates/htaccess')) {
|
62 |
+
foreach (scandir($templates_dir) as $_template_file) {
|
63 |
+
switch ($_template_file) {
|
64 |
+
|
65 |
+
}
|
66 |
+
}
|
67 |
+
unset($_template_file); // Housekeeping.
|
68 |
+
}
|
69 |
+
|
70 |
+
if (empty($template_blocks)) { // Do we need to add anything to htaccess?
|
71 |
+
$this->closeHtaccessFile($htaccess); // No need to write to htaccess file in this case.
|
72 |
+
return true; // Nothing to do, but no failures either.
|
73 |
+
}
|
74 |
+
|
75 |
+
$template_header = '# BEGIN '.NAME.' '.$this->htaccess_marker.' (the '.$this->htaccess_marker.' marker is required for '.NAME.'; do not remove)'."\n";
|
76 |
+
$template_footer = '# END '.NAME.' '.$this->htaccess_marker;
|
77 |
+
$htaccess['file_contents'] = $template_header.trim($template_blocks)."\n".$template_footer."\n\n".$htaccess['file_contents'];
|
78 |
+
|
79 |
+
if (!$this->writeHtaccessFile($htaccess, true)) {
|
80 |
+
return false; // Failure; could not write changes.
|
81 |
+
}
|
82 |
+
|
83 |
+
return true; // Added successfully.
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Remove template blocks from `/.htaccess` file.
|
88 |
+
*
|
89 |
+
* @since 151114 Adding `.htaccess` tweaks.
|
90 |
+
*
|
91 |
+
* @return bool True if removed successfully.
|
92 |
+
*
|
93 |
+
* @TODO Improve error reporting detail to better catch unexpected failures; see http://git.io/vEFLT
|
94 |
+
*/
|
95 |
+
public function removeWpHtaccess()
|
96 |
+
{
|
97 |
+
global $is_apache;
|
98 |
+
|
99 |
+
if (!$is_apache) {
|
100 |
+
return false; // Not running the Apache web server.
|
101 |
+
}
|
102 |
+
if (!($htaccess_file = $this->findHtaccessFile())) {
|
103 |
+
return true; // File does not exist.
|
104 |
+
}
|
105 |
+
if (!$this->findHtaccessMarker()) {
|
106 |
+
return true; // Template blocks are already gone.
|
107 |
+
}
|
108 |
+
if (!($htaccess = $this->readHtaccessFile())) {
|
109 |
+
return false; // Failure; could not read file, create file, or invalid UTF8 encountered, file may be corrupt.
|
110 |
+
}
|
111 |
+
|
112 |
+
$regex = '/#\s*BEGIN\s+'.preg_quote(NAME, '/').'\s+'.$this->htaccess_marker.'.*?#\s*END\s+'.preg_quote(NAME, '/').'\s+'.$this->htaccess_marker.'\s*/is';
|
113 |
+
$htaccess['file_contents'] = preg_replace($regex, '', $htaccess['file_contents']);
|
114 |
+
|
115 |
+
if (!$this->writeHtaccessFile($htaccess, false)) {
|
116 |
+
return false; // Failure; could not write changes.
|
117 |
+
}
|
118 |
+
|
119 |
+
return true; // Removed successfully.
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Finds absolute server path to `/.htaccess` file.
|
124 |
+
*
|
125 |
+
* @since 151114 Adding `.htaccess` tweaks.
|
126 |
+
*
|
127 |
+
* @return string Absolute server path to `/.htaccess` file;
|
128 |
+
* else an empty string if unable to locate the file.
|
129 |
+
*/
|
130 |
+
public function findHtaccessFile()
|
131 |
+
{
|
132 |
+
$file = ''; // Initialize.
|
133 |
+
$home_path = $this->wpHomePath();
|
134 |
+
|
135 |
+
if (is_file($htaccess_file = $home_path.'.htaccess')) {
|
136 |
+
$file = $htaccess_file;
|
137 |
+
}
|
138 |
+
return $file;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Determines if there are any plugin options enabled that require htaccess rules to be added.
|
143 |
+
*
|
144 |
+
* @since 160103 Improving `.htaccess` tweaks.
|
145 |
+
*
|
146 |
+
* @return bool True when an option is enabled that requires htaccess rules, false otherwise.
|
147 |
+
*/
|
148 |
+
public function needHtaccessRules()
|
149 |
+
{
|
150 |
+
if (!is_array($this->options_with_htaccess_rules)) {
|
151 |
+
return false; // Nothing to do.
|
152 |
+
}
|
153 |
+
foreach ($this->options_with_htaccess_rules as $option) {
|
154 |
+
if ($this->options[$option]) {
|
155 |
+
return true; // Yes, there are options enabled that require htaccess rules.
|
156 |
+
}
|
157 |
+
}
|
158 |
+
return false; // No, there are no options enabled that require htaccess rules.
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Utility method used to check if htaccess file contains $htaccess_marker.
|
163 |
+
*
|
164 |
+
* @since 151114 Adding `.htaccess` tweaks.
|
165 |
+
*
|
166 |
+
* @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
|
167 |
+
*
|
168 |
+
* @return bool False on failure or when marker does not exist in htaccess, true otherwise.
|
169 |
+
*/
|
170 |
+
public function findHtaccessMarker($htaccess_marker = '')
|
171 |
+
{
|
172 |
+
if (!($htaccess_file = $this->findHtaccessFile())) {
|
173 |
+
return false; // File does not exist.
|
174 |
+
}
|
175 |
+
if (!is_readable($htaccess_file)) {
|
176 |
+
return false; // Not possible.
|
177 |
+
}
|
178 |
+
if (($htaccess_file_contents = file_get_contents($htaccess_file)) === false) {
|
179 |
+
return false; // Failure; could not read file.
|
180 |
+
}
|
181 |
+
if (empty($htaccess_marker)) {
|
182 |
+
$htaccess_marker = $this->htaccess_marker;
|
183 |
+
}
|
184 |
+
if (stripos($htaccess_file_contents, $htaccess_marker) === false) {
|
185 |
+
return false; // Htaccess marker is missing
|
186 |
+
}
|
187 |
+
|
188 |
+
return true; // Htaccess has the marker
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Gets contents of `/.htaccess` file with exclusive lock to read+write. If file doesn't exist, we attempt to create it.
|
193 |
+
*
|
194 |
+
* @since 151220 Improving `.htaccess` utils.
|
195 |
+
*
|
196 |
+
* @param string $htaccess_file Absolute path to the htaccess file. Optional.
|
197 |
+
* If not provided, we attempt to find it or create it if it doesn't exist.
|
198 |
+
*
|
199 |
+
* @return array|bool Returns an array with data necessary to call $this->writeHtaccessFile():
|
200 |
+
* `fp` a file pointer resource, `file_contents` a string. Returns `false` on failure.
|
201 |
+
*
|
202 |
+
* @note If a call to this method is not followed by a call to $this->writeHtaccessFile(),
|
203 |
+
* you must make sure that you unlock and close the `fp` resource yourself.
|
204 |
+
*/
|
205 |
+
public function readHtaccessFile($htaccess_file = '')
|
206 |
+
{
|
207 |
+
if (empty($htaccess_file) && !($htaccess_file = $this->findHtaccessFile())) {
|
208 |
+
if (!is_writable($this->wpHomePath()) || file_put_contents($htaccess_file = $this->wpHomePath().'.htaccess', '') === false) {
|
209 |
+
return false; // Unable to find and/or create `.htaccess`.
|
210 |
+
} // If it doesn't exist, we create the `.htaccess` file here.
|
211 |
+
}
|
212 |
+
if (!is_readable($htaccess_file) || !is_writable($htaccess_file) || (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS)) {
|
213 |
+
return false; // Not possible.
|
214 |
+
}
|
215 |
+
if (!($fp = fopen($htaccess_file, 'rb+')) || !flock($fp, LOCK_EX)) {
|
216 |
+
fclose($fp); // Just in case we opened it before failing to obtain a lock.
|
217 |
+
return false; // Failure; could not open file and obtain an exclusive lock.
|
218 |
+
}
|
219 |
+
if (($file_contents = fread($fp, filesize($htaccess_file))) && ($file_contents === wp_check_invalid_utf8($file_contents))) {
|
220 |
+
rewind($fp); // Rewind pointer to beginning of file.
|
221 |
+
return compact('fp', 'file_contents');
|
222 |
+
} else { // Failure; could not read file or invalid UTF8 encountered, file may be corrupt.
|
223 |
+
flock($fp, LOCK_UN);
|
224 |
+
fclose($fp);
|
225 |
+
return false;
|
226 |
+
}
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Writes to `/.htaccess` file using provided file pointer.
|
231 |
+
*
|
232 |
+
* @since 151220 Improving `.htaccess` utils.
|
233 |
+
*
|
234 |
+
* @param array $htaccess Array containing `fp` file resource pointing to htaccess file and `file_contents` to write to file.
|
235 |
+
* @param bool $require_marker Whether or not to require the marker be present in contents before writing.
|
236 |
+
* @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
|
237 |
+
*
|
238 |
+
* @return bool True on success, false on failure.
|
239 |
+
*/
|
240 |
+
public function writeHtaccessFile(array $htaccess, $require_marker = true, $htaccess_marker = '')
|
241 |
+
{
|
242 |
+
if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
|
243 |
+
return false; // Not possible.
|
244 |
+
}
|
245 |
+
if (!is_resource($htaccess['fp'])) {
|
246 |
+
return false;
|
247 |
+
}
|
248 |
+
$htaccess_marker = $htaccess_marker ?: $this->htaccess_marker;
|
249 |
+
|
250 |
+
$_have_marker = stripos($htaccess['file_contents'], $htaccess_marker);
|
251 |
+
|
252 |
+
// Note: rewind() necessary here because we fread() above.
|
253 |
+
if (($require_marker && $_have_marker === false) || !rewind($htaccess['fp']) || !ftruncate($htaccess['fp'], 0) || !fwrite($htaccess['fp'], $htaccess['file_contents'])) {
|
254 |
+
flock($htaccess['fp'], LOCK_UN);
|
255 |
+
fclose($htaccess['fp']);
|
256 |
+
return false; // Failure; could not write changes.
|
257 |
+
}
|
258 |
+
fflush($htaccess['fp']);
|
259 |
+
flock($htaccess['fp'], LOCK_UN);
|
260 |
+
fclose($htaccess['fp']);
|
261 |
+
|
262 |
+
return true;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Utility method used to unlock and close htaccess file resource.
|
267 |
+
*
|
268 |
+
* @since 151114 Adding `.htaccess` tweaks.
|
269 |
+
*
|
270 |
+
* @param array $htaccess Array containing at least an `fp` file resource pointing to htaccess file.
|
271 |
+
*
|
272 |
+
* @return bool False on failure, true otherwise.
|
273 |
+
*/
|
274 |
+
public function closeHtaccessFile(array $htaccess)
|
275 |
+
{
|
276 |
+
if (!is_resource($htaccess['fp'])) {
|
277 |
+
return false; // Failure; requires a valid file resource.
|
278 |
+
}
|
279 |
+
flock($htaccess['fp'], LOCK_UN);
|
280 |
+
fclose($htaccess['fp']);
|
281 |
+
|
282 |
+
return true;
|
283 |
+
}
|
284 |
+
}
|
src/includes/traits/Plugin/InstallUtils.php
ADDED
@@ -0,0 +1,553 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait InstallUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Plugin activation hook.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @attaches-to {@link \register_activation_hook()}
|
14 |
+
*/
|
15 |
+
public function activate()
|
16 |
+
{
|
17 |
+
$this->setup(); // Ensure setup is complete.
|
18 |
+
|
19 |
+
if (defined('WP_CLI') && WP_CLI) {
|
20 |
+
$this->updateOptions(['enable' => '1']);
|
21 |
+
}
|
22 |
+
if (!$this->options['welcomed'] && !$this->options['enable']) {
|
23 |
+
$settings_url = add_query_arg(urlencode_deep(['page' => GLOBAL_NS]), network_admin_url('/admin.php'));
|
24 |
+
$this->enqueueMainNotice(sprintf(__('<strong>%1$s</strong> successfully installed! :-) <strong>Please <a href="%2$s">enable caching and review options</a>.</strong>', 'comet-cache'), esc_html(NAME), esc_attr($settings_url)), ['push_to_top' => true]);
|
25 |
+
$this->updateOptions(['welcomed' => '1']);
|
26 |
+
}
|
27 |
+
if (!$this->options['enable']) {
|
28 |
+
return; // Nothing to do.
|
29 |
+
}
|
30 |
+
$this->addWpCacheToWpConfig();
|
31 |
+
$this->addWpHtaccess();
|
32 |
+
$this->addAdvancedCache();
|
33 |
+
$this->updateBlogPaths();
|
34 |
+
$this->autoClearCache();
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Check current plugin version that is installed in WP.
|
39 |
+
*
|
40 |
+
* @since 150422 Rewrite.
|
41 |
+
*
|
42 |
+
* @attaches-to `admin_init` hook.
|
43 |
+
*/
|
44 |
+
public function checkVersion()
|
45 |
+
{
|
46 |
+
$prev_version = $this->options['version'];
|
47 |
+
if (version_compare($prev_version, VERSION, '>=')) {
|
48 |
+
return; // Nothing to do; up-to-date.
|
49 |
+
}
|
50 |
+
$this->updateOptions(['version' => VERSION]);
|
51 |
+
|
52 |
+
new Classes\VsUpgrades($prev_version);
|
53 |
+
|
54 |
+
if ($this->options['enable']) {
|
55 |
+
$this->addWpCacheToWpConfig();
|
56 |
+
$this->addWpHtaccess();
|
57 |
+
$this->addAdvancedCache();
|
58 |
+
$this->updateBlogPaths();
|
59 |
+
}
|
60 |
+
$this->wipeCache(); // Fresh start now.
|
61 |
+
|
62 |
+
$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]);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Plugin deactivation hook.
|
67 |
+
*
|
68 |
+
* @since 150422 Rewrite.
|
69 |
+
*
|
70 |
+
* @attaches-to {@link \register_deactivation_hook()}
|
71 |
+
*/
|
72 |
+
public function deactivate()
|
73 |
+
{
|
74 |
+
$this->setup(); // Ensure setup is complete.
|
75 |
+
|
76 |
+
$this->removeWpCacheFromWpConfig();
|
77 |
+
$this->removeWpHtaccess();
|
78 |
+
$this->removeAdvancedCache();
|
79 |
+
$this->clearCache();
|
80 |
+
$this->resetCronSetup();
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Plugin uninstall hook.
|
85 |
+
*
|
86 |
+
* @since 150422 Rewrite.
|
87 |
+
*/
|
88 |
+
public function uninstall()
|
89 |
+
{
|
90 |
+
$this->setup(); // Ensure setup is complete.
|
91 |
+
|
92 |
+
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
93 |
+
return; // Disallow.
|
94 |
+
}
|
95 |
+
if (empty($GLOBALS[GLOBAL_NS.'_uninstalling'])) {
|
96 |
+
return; // Not uninstalling.
|
97 |
+
}
|
98 |
+
if (!current_user_can($this->uninstall_cap)) {
|
99 |
+
return; // Extra layer of security.
|
100 |
+
}
|
101 |
+
$this->removeWpCacheFromWpConfig();
|
102 |
+
$this->removeWpHtaccess();
|
103 |
+
$this->removeAdvancedCache();
|
104 |
+
$this->wipeCache();
|
105 |
+
$this->resetCronSetup();
|
106 |
+
|
107 |
+
if (!$this->options['uninstall_on_deletion']) {
|
108 |
+
return; // Nothing to do here.
|
109 |
+
}
|
110 |
+
$this->deleteAdvancedCache();
|
111 |
+
$this->deleteBaseDir();
|
112 |
+
|
113 |
+
$wpdb = $this->wpdb(); // WordPress DB.
|
114 |
+
$like = '%'.$wpdb->esc_like(GLOBAL_NS).'%';
|
115 |
+
|
116 |
+
if (is_multisite()) { // Site options for a network installation.
|
117 |
+
$wpdb->query('DELETE FROM `'.esc_sql($wpdb->sitemeta).'` WHERE `meta_key` LIKE \''.esc_sql($like).'\'');
|
118 |
+
|
119 |
+
switch_to_blog(get_current_site()->blog_id); // In case it started as a standard WP installation.
|
120 |
+
$wpdb->query('DELETE FROM `'.esc_sql($wpdb->options).'` WHERE `option_name` LIKE \''.esc_sql($like).'\'');
|
121 |
+
restore_current_blog(); // Restore current blog.
|
122 |
+
//
|
123 |
+
} else { // Standard WP installation.
|
124 |
+
$wpdb->query('DELETE FROM `'.esc_sql($wpdb->options).'` WHERE `option_name` LIKE \''.esc_sql($like).'\'');
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Adds `define('WP_CACHE', TRUE);` to the `/wp-config.php` file.
|
130 |
+
*
|
131 |
+
* @since 150422 Rewrite.
|
132 |
+
*
|
133 |
+
* @return string The new contents of the updated `/wp-config.php` file;
|
134 |
+
* else an empty string if unable to add the `WP_CACHE` constant.
|
135 |
+
*/
|
136 |
+
public function addWpCacheToWpConfig()
|
137 |
+
{
|
138 |
+
if (!$this->options['enable']) {
|
139 |
+
return ''; // Nothing to do.
|
140 |
+
}
|
141 |
+
if (!($wp_config_file = $this->findWpConfigFile())) {
|
142 |
+
return ''; // Unable to find `/wp-config.php`.
|
143 |
+
}
|
144 |
+
if (!is_readable($wp_config_file)) {
|
145 |
+
return ''; // Not possible.
|
146 |
+
}
|
147 |
+
if (!($wp_config_file_contents = file_get_contents($wp_config_file))) {
|
148 |
+
return ''; // Failure; could not read file.
|
149 |
+
}
|
150 |
+
if (!($wp_config_file_contents_no_whitespace = php_strip_whitespace($wp_config_file))) {
|
151 |
+
return ''; // Failure; file empty
|
152 |
+
}
|
153 |
+
if (preg_match('/\bdefine\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:\-?[1-9][0-9\.]*|TRUE|([\'"])(?:[^0\'"]|[^\'"]{2,})\\2)\s*\)\s*;/i', $wp_config_file_contents_no_whitespace)) {
|
154 |
+
return $wp_config_file_contents; // It's already in there; no need to modify this file.
|
155 |
+
}
|
156 |
+
if (!($wp_config_file_contents = $this->removeWpCacheFromWpConfig())) {
|
157 |
+
return ''; // Unable to remove previous value.
|
158 |
+
}
|
159 |
+
if (!($wp_config_file_contents = preg_replace('/^\s*(\<\?php|\<\?)\s+/i', '${1}'."\n"."define('WP_CACHE', TRUE);"."\n", $wp_config_file_contents, 1))) {
|
160 |
+
return ''; // Failure; something went terribly wrong here.
|
161 |
+
}
|
162 |
+
if (strpos($wp_config_file_contents, "define('WP_CACHE', TRUE);") === false) {
|
163 |
+
return ''; // Failure; unable to add; unexpected PHP code.
|
164 |
+
}
|
165 |
+
if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
|
166 |
+
return ''; // We may NOT edit any files.
|
167 |
+
}
|
168 |
+
if (!is_writable($wp_config_file)) {
|
169 |
+
return ''; // Not possible.
|
170 |
+
}
|
171 |
+
if (!file_put_contents($wp_config_file, $wp_config_file_contents)) {
|
172 |
+
return ''; // Failure; could not write changes.
|
173 |
+
}
|
174 |
+
return $wp_config_file_contents;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Removes `define('WP_CACHE', TRUE);` from the `/wp-config.php` file.
|
179 |
+
*
|
180 |
+
* @since 150422 Rewrite.
|
181 |
+
*
|
182 |
+
* @return string The new contents of the updated `/wp-config.php` file;
|
183 |
+
* else an empty string if unable to remove the `WP_CACHE` constant.
|
184 |
+
*/
|
185 |
+
public function removeWpCacheFromWpConfig()
|
186 |
+
{
|
187 |
+
if (!($wp_config_file = $this->findWpConfigFile())) {
|
188 |
+
return ''; // Unable to find `/wp-config.php`.
|
189 |
+
}
|
190 |
+
if (!is_readable($wp_config_file)) {
|
191 |
+
return ''; // Not possible.
|
192 |
+
}
|
193 |
+
if (!($wp_config_file_contents = file_get_contents($wp_config_file))) {
|
194 |
+
return ''; // Failure; could not read file.
|
195 |
+
}
|
196 |
+
if (!($wp_config_file_contents_no_whitespace = php_strip_whitespace($wp_config_file))) {
|
197 |
+
return ''; // Failure; file empty
|
198 |
+
}
|
199 |
+
if (!preg_match('/([\'"])WP_CACHE\\1/i', $wp_config_file_contents_no_whitespace)) {
|
200 |
+
return $wp_config_file_contents; // Already gone.
|
201 |
+
}
|
202 |
+
if (preg_match('/\bdefine\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:0|FALSE|NULL|([\'"])0?\\2)\s*\)\s*;/i', $wp_config_file_contents_no_whitespace) && !is_writable($wp_config_file)) {
|
203 |
+
return $wp_config_file_contents; // It's already disabled, and since we can't write to this file let's let this slide.
|
204 |
+
}
|
205 |
+
if (!($wp_config_file_contents = preg_replace('/\bdefine\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:\-?[0-9\.]+|TRUE|FALSE|NULL|([\'"])[^\'"]*\\2)\s*\)\s*;/i', '', $wp_config_file_contents))) {
|
206 |
+
return ''; // Failure; something went terribly wrong here.
|
207 |
+
}
|
208 |
+
if (preg_match('/([\'"])WP_CACHE\\1/i', $wp_config_file_contents)) {
|
209 |
+
return ''; // Failure; perhaps the `/wp-config.php` file contains syntax we cannot remove safely.
|
210 |
+
}
|
211 |
+
if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
|
212 |
+
return ''; // We may NOT edit any files.
|
213 |
+
}
|
214 |
+
if (!is_writable($wp_config_file)) {
|
215 |
+
return ''; // Not possible.
|
216 |
+
}
|
217 |
+
if (!file_put_contents($wp_config_file, $wp_config_file_contents)) {
|
218 |
+
return ''; // Failure; could not write changes.
|
219 |
+
}
|
220 |
+
return $wp_config_file_contents;
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Checks to make sure the `advanced-cache.php` file still exists;
|
225 |
+
* and if it doesn't, the `advanced-cache.php` is regenerated automatically.
|
226 |
+
*
|
227 |
+
* @since 150422 Rewrite.
|
228 |
+
*
|
229 |
+
* @attaches-to `init` hook.
|
230 |
+
*
|
231 |
+
* @note This runs so that remote deployments which completely wipe out an
|
232 |
+
* existing set of website files (like the AWS Elastic Beanstalk does) will NOT cause Comet Cache
|
233 |
+
* to stop functioning due to the lack of an `advanced-cache.php` file, which is generated by Comet Cache.
|
234 |
+
*
|
235 |
+
* For instance, if you have a Git repo with all of your site files; when you push those files
|
236 |
+
* to your website to deploy them, you most likely do NOT have the `advanced-cache.php` file.
|
237 |
+
* Comet Cache creates this file on its own. Thus, if it's missing (and CC is active)
|
238 |
+
* we simply regenerate the file automatically to keep Comet Cache running.
|
239 |
+
*/
|
240 |
+
public function checkAdvancedCache()
|
241 |
+
{
|
242 |
+
if (!$this->options['enable']) {
|
243 |
+
return; // Nothing to do.
|
244 |
+
}
|
245 |
+
if (!empty($_REQUEST[GLOBAL_NS])) {
|
246 |
+
return; // Skip on plugin actions.
|
247 |
+
}
|
248 |
+
$cache_dir = $this->cacheDir();
|
249 |
+
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
250 |
+
$advanced_cache_check_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-advanced-cache';
|
251 |
+
|
252 |
+
// Fixes zero-byte advanced-cache.php bug related to migrating from ZenCache
|
253 |
+
// See: <https://github.com/websharks/zencache/issues/432>
|
254 |
+
|
255 |
+
// Also fixes a missing `define('WP_CACHE', TRUE)` bug related to migrating from ZenCache
|
256 |
+
// See <https://github.com/websharks/zencache/issues/450>
|
257 |
+
|
258 |
+
if (!is_file($advanced_cache_check_file) || !is_file($advanced_cache_file) || filesize($advanced_cache_file) === 0) {
|
259 |
+
$this->addAdvancedCache();
|
260 |
+
$this->addWpCacheToWpConfig();
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Creates and adds the `advanced-cache.php` file.
|
266 |
+
*
|
267 |
+
* @since 150422 Rewrite.
|
268 |
+
*
|
269 |
+
* @return bool|null `TRUE` on success. `FALSE` or `NULL` on failure.
|
270 |
+
* A special `NULL` return value indicates success with a single failure
|
271 |
+
* that is specifically related to the `[SHORT_NAME]-advanced-cache` file.
|
272 |
+
*/
|
273 |
+
public function addAdvancedCache()
|
274 |
+
{
|
275 |
+
if (!$this->removeAdvancedCache()) {
|
276 |
+
return false; // Still exists.
|
277 |
+
}
|
278 |
+
$cache_dir = $this->cacheDir();
|
279 |
+
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
280 |
+
$advanced_cache_check_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-advanced-cache';
|
281 |
+
$advanced_cache_template = dirname(dirname(__DIR__)).'/templates/advanced-cache.txt';
|
282 |
+
|
283 |
+
if (is_file($advanced_cache_file) && !is_writable($advanced_cache_file)) {
|
284 |
+
return false; // Not possible to create.
|
285 |
+
}
|
286 |
+
if (!is_file($advanced_cache_file) && !is_writable(dirname($advanced_cache_file))) {
|
287 |
+
return false; // Not possible to create.
|
288 |
+
}
|
289 |
+
if (!is_file($advanced_cache_template) || !is_readable($advanced_cache_template)) {
|
290 |
+
return false; // Template file is missing; or not readable.
|
291 |
+
}
|
292 |
+
if (!($advanced_cache_contents = file_get_contents($advanced_cache_template))) {
|
293 |
+
return false; // Template file is missing; or is not readable.
|
294 |
+
}
|
295 |
+
$possible_advanced_cache_constant_key_values = array_merge(
|
296 |
+
$this->options, // The following additional keys are dynamic.
|
297 |
+
[
|
298 |
+
'cache_dir' => $this->basePathTo($this->cache_sub_dir),
|
299 |
+
|
300 |
+
]
|
301 |
+
);
|
302 |
+
if ($this->applyWpFilters(GLOBAL_NS.'_exclude_uris_client_side_too', true)) {
|
303 |
+
$possible_advanced_cache_constant_key_values['exclude_client_side_uris'] .= "\n".$this->options['exclude_uris'];
|
304 |
+
}
|
305 |
+
foreach ($possible_advanced_cache_constant_key_values as $_option => $_value) {
|
306 |
+
$_value = (string) $_value; // Force string.
|
307 |
+
|
308 |
+
switch ($_option) {
|
309 |
+
case 'exclude_uris': // Converts to regex (caSe insensitive).
|
310 |
+
case 'exclude_client_side_uris': // Converts to regex (caSe insensitive).
|
311 |
+
case 'exclude_refs': // Converts to regex (caSe insensitive).
|
312 |
+
case 'exclude_agents': // Converts to regex (caSe insensitive).
|
313 |
+
|
314 |
+
|
315 |
+
|
316 |
+
$_value = "'".$this->escSq($this->lineDelimitedPatternsToRegex($_value))."'";
|
317 |
+
|
318 |
+
break; // Break switch handler.
|
319 |
+
|
320 |
+
|
321 |
+
|
322 |
+
default: // Default case handler.
|
323 |
+
$_value = "'".$this->escSq($_value)."'";
|
324 |
+
break; // Break switch handler.
|
325 |
+
}
|
326 |
+
$advanced_cache_contents = // Fill replacement codes.
|
327 |
+
str_ireplace(
|
328 |
+
[
|
329 |
+
"'%%".GLOBAL_NS.'_'.$_option."%%'",
|
330 |
+
"'%%".GLOBAL_NS.'_'.preg_replace('/^cache_/i', '', $_option)."%%'",
|
331 |
+
],
|
332 |
+
$_value,
|
333 |
+
$advanced_cache_contents
|
334 |
+
);
|
335 |
+
}
|
336 |
+
unset($_option, $_value, $_values, $_response); // Housekeeping.
|
337 |
+
|
338 |
+
if (strpos(PLUGIN_FILE, WP_CONTENT_DIR) === 0) {
|
339 |
+
$plugin_file = "WP_CONTENT_DIR.'".$this->escSq(str_replace(WP_CONTENT_DIR, '', PLUGIN_FILE))."'";
|
340 |
+
} else {
|
341 |
+
$plugin_file = "'".$this->escSq(PLUGIN_FILE)."'"; // Full absolute path.
|
342 |
+
}
|
343 |
+
// Make it possible for the `advanced-cache.php` handler to find the plugin directory reliably.
|
344 |
+
$advanced_cache_contents = str_ireplace("'%%".GLOBAL_NS."_PLUGIN_FILE%%'", $plugin_file, $advanced_cache_contents);
|
345 |
+
|
346 |
+
// Ignore; this is created by Comet Cache; and we don't need to obey in this case.
|
347 |
+
#if(defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS)
|
348 |
+
# return FALSE; // We may NOT edit any files.
|
349 |
+
|
350 |
+
if (!file_put_contents($advanced_cache_file, $advanced_cache_contents)) {
|
351 |
+
return false; // Failure; could not write file.
|
352 |
+
}
|
353 |
+
$cache_lock = $this->cacheLock(); // Lock cache.
|
354 |
+
|
355 |
+
if (!is_dir($cache_dir)) {
|
356 |
+
mkdir($cache_dir, 0775, true);
|
357 |
+
}
|
358 |
+
if (is_writable($cache_dir) && !is_file($cache_dir.'/.htaccess')) {
|
359 |
+
file_put_contents($cache_dir.'/.htaccess', $this->htaccess_deny);
|
360 |
+
}
|
361 |
+
if (!is_dir($cache_dir) || !is_writable($cache_dir) || !is_file($cache_dir.'/.htaccess') || !file_put_contents($advanced_cache_check_file, time())) {
|
362 |
+
$this->cacheUnlock($cache_lock); // Release.
|
363 |
+
return; // Special return value (NULL).
|
364 |
+
}
|
365 |
+
$this->cacheUnlock($cache_lock); // Release.
|
366 |
+
|
367 |
+
$this->clearAcDropinFromOpcacheByForce();
|
368 |
+
|
369 |
+
return true;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Removes the `advanced-cache.php` file.
|
374 |
+
*
|
375 |
+
* @since 150422 Rewrite.
|
376 |
+
*
|
377 |
+
* @return bool `TRUE` on success. `FALSE` on failure.
|
378 |
+
*
|
379 |
+
* @note The `advanced-cache.php` file is NOT actually deleted by this routine.
|
380 |
+
* Instead of deleting the file, we simply empty it out so that it's `0` bytes in size.
|
381 |
+
*
|
382 |
+
* The reason for this is to preserve any file permissions set by the site owner.
|
383 |
+
* If the site owner previously allowed this specific file to become writable, we don't want to
|
384 |
+
* lose that permission by deleting the file; forcing the site owner to do it all over again later.
|
385 |
+
*
|
386 |
+
* An example of where this is useful is when a site owner deactivates the CC plugin,
|
387 |
+
* but later they decide that CC really is the most awesome plugin in the world and they turn it back on.
|
388 |
+
*/
|
389 |
+
public function removeAdvancedCache()
|
390 |
+
{
|
391 |
+
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
392 |
+
|
393 |
+
if (!is_file($advanced_cache_file)) {
|
394 |
+
return true; // Already gone.
|
395 |
+
}
|
396 |
+
if (is_readable($advanced_cache_file) && filesize($advanced_cache_file) === 0) {
|
397 |
+
return true; // Already gone; i.e. it's empty already.
|
398 |
+
}
|
399 |
+
if (!is_writable($advanced_cache_file)) {
|
400 |
+
return false; // Not possible.
|
401 |
+
}
|
402 |
+
/* Empty the file only. This way permissions are NOT lost in cases where
|
403 |
+
a site owner makes this specific file writable for Comet Cache. */
|
404 |
+
if (file_put_contents($advanced_cache_file, '') !== 0) {
|
405 |
+
return false; // Failure.
|
406 |
+
}
|
407 |
+
$this->clearAcDropinFromOpcacheByForce();
|
408 |
+
|
409 |
+
return true;
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* Deletes the `advanced-cache.php` file.
|
414 |
+
*
|
415 |
+
* @since 150422 Rewrite.
|
416 |
+
*
|
417 |
+
* @return bool `TRUE` on success. `FALSE` on failure.
|
418 |
+
*
|
419 |
+
* @note The `advanced-cache.php` file is deleted by this routine.
|
420 |
+
*/
|
421 |
+
public function deleteAdvancedCache()
|
422 |
+
{
|
423 |
+
$cache_dir = $this->cacheDir();
|
424 |
+
$advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php';
|
425 |
+
$advanced_cache_check_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-advanced-cache';
|
426 |
+
|
427 |
+
if (is_file($advanced_cache_file)) {
|
428 |
+
if (!is_writable($advanced_cache_file) || !unlink($advanced_cache_file)) {
|
429 |
+
return false; // Not possible; or outright failure.
|
430 |
+
}
|
431 |
+
}
|
432 |
+
if (is_file($advanced_cache_check_file)) {
|
433 |
+
if (!is_writable($advanced_cache_check_file) || !unlink($advanced_cache_check_file)) {
|
434 |
+
return false; // Not possible; or outright failure.
|
435 |
+
}
|
436 |
+
}
|
437 |
+
$this->clearAcDropinFromOpcacheByForce();
|
438 |
+
|
439 |
+
return true; // Deletion success.
|
440 |
+
}
|
441 |
+
|
442 |
+
/**
|
443 |
+
* Checks to make sure the `[SHORT_NAME]-blog-paths` file still exists;
|
444 |
+
* and if it doesn't, the `[SHORT_NAME]-blog-paths` file is regenerated automatically.
|
445 |
+
*
|
446 |
+
* @since 150422 Rewrite.
|
447 |
+
*
|
448 |
+
* @attaches-to `init` hook.
|
449 |
+
*
|
450 |
+
* @note This runs so that remote deployments which completely wipe out an
|
451 |
+
* existing set of website files (like the AWS Elastic Beanstalk does) will NOT cause Comet Cache
|
452 |
+
* to stop functioning due to the lack of a `[SHORT_NAME]-blog-paths` file, which is generated by Comet Cache.
|
453 |
+
*
|
454 |
+
* For instance, if you have a Git repo with all of your site files; when you push those files
|
455 |
+
* to your website to deploy them, you most likely do NOT have the `[SHORT_NAME]-blog-paths` file.
|
456 |
+
* Comet Cache creates this file on its own. Thus, if it's missing (and CC is active)
|
457 |
+
* we simply regenerate the file automatically to keep Comet Cache running.
|
458 |
+
*/
|
459 |
+
public function checkBlogPaths()
|
460 |
+
{
|
461 |
+
if (!$this->options['enable']) {
|
462 |
+
return; // Nothing to do.
|
463 |
+
}
|
464 |
+
if (!is_multisite()) {
|
465 |
+
return; // N/A.
|
466 |
+
}
|
467 |
+
if (!empty($_REQUEST[GLOBAL_NS])) {
|
468 |
+
return; // Skip on plugin actions.
|
469 |
+
}
|
470 |
+
$cache_dir = $this->cacheDir();
|
471 |
+
$blog_paths_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-blog-paths';
|
472 |
+
|
473 |
+
if (!is_file($blog_paths_file)) {
|
474 |
+
$this->updateBlogPaths();
|
475 |
+
}
|
476 |
+
}
|
477 |
+
|
478 |
+
/**
|
479 |
+
* Creates and/or updates the `[SHORT_NAME]-blog-paths` file.
|
480 |
+
*
|
481 |
+
* @since 150422 Rewrite.
|
482 |
+
*
|
483 |
+
* @attaches-to `enable_live_network_counts` filter.
|
484 |
+
*
|
485 |
+
* @param mixed $enable_live_network_counts Optional, defaults to a `NULL` value.
|
486 |
+
*
|
487 |
+
* @return mixed The value of `$enable_live_network_counts` (passes through).
|
488 |
+
*
|
489 |
+
* @note While this routine is attached to a WP filter, we also call upon it directly at times.
|
490 |
+
*/
|
491 |
+
public function updateBlogPaths($enable_live_network_counts = null)
|
492 |
+
{
|
493 |
+
$value = $enable_live_network_counts; // This hook actually rides on a filter.
|
494 |
+
|
495 |
+
if (!$this->options['enable']) {
|
496 |
+
return $value; // Nothing to do.
|
497 |
+
}
|
498 |
+
if (!is_multisite()) {
|
499 |
+
return $value; // N/A.
|
500 |
+
}
|
501 |
+
$cache_dir = $this->cacheDir();
|
502 |
+
$blog_paths_file = $cache_dir.'/'.strtolower(SHORT_NAME).'-blog-paths';
|
503 |
+
|
504 |
+
$cache_lock = $this->cacheLock();
|
505 |
+
|
506 |
+
if (!is_dir($cache_dir)) {
|
507 |
+
mkdir($cache_dir, 0775, true);
|
508 |
+
}
|
509 |
+
if (is_writable($cache_dir) && !is_file($cache_dir.'/.htaccess')) {
|
510 |
+
file_put_contents($cache_dir.'/.htaccess', $this->htaccess_deny);
|
511 |
+
}
|
512 |
+
if (is_dir($cache_dir) && is_writable($cache_dir)) {
|
513 |
+
$paths = // Collect child `[/base]/path/`s from the WordPress database.
|
514 |
+
$this->wpdb()->get_col('SELECT `path` FROM `'.esc_sql($this->wpdb()->blogs)."` WHERE `deleted` <= '0'");
|
515 |
+
|
516 |
+
$host_base_token = $this->hostBaseToken(); // Pull this once only.
|
517 |
+
|
518 |
+
foreach ($paths as $_key => &$_path) {
|
519 |
+
if ($_path && $_path !== '/' && $host_base_token && $host_base_token !== '/') {
|
520 |
+
// Note that each `path` in the DB looks like: `[/base]/path/` (i.e., it includes base).
|
521 |
+
$_path = '/'.ltrim(preg_replace('/^'.preg_quote($host_base_token, '/').'/', '', $_path), '/');
|
522 |
+
}
|
523 |
+
if (!$_path || $_path === '/') {
|
524 |
+
unset($paths[$_key]); // Exclude main site.
|
525 |
+
}
|
526 |
+
}
|
527 |
+
unset($_key, $_path); // Housekeeping.
|
528 |
+
|
529 |
+
file_put_contents($blog_paths_file, serialize($paths));
|
530 |
+
}
|
531 |
+
$this->cacheUnlock($cache_lock); // Release.
|
532 |
+
|
533 |
+
return $value; // Pass through untouched (always).
|
534 |
+
}
|
535 |
+
|
536 |
+
/**
|
537 |
+
* Deletes base directory.
|
538 |
+
*
|
539 |
+
* @since 151002 Improving multisite compat.
|
540 |
+
*
|
541 |
+
* @return int Total files removed by this routine (if any).
|
542 |
+
*/
|
543 |
+
public function deleteBaseDir()
|
544 |
+
{
|
545 |
+
$counter = 0; // Initialize.
|
546 |
+
|
547 |
+
@set_time_limit(1800); // @TODO Display a warning.
|
548 |
+
|
549 |
+
$counter += $this->deleteAllFilesDirsIn($this->wpContentBaseDirTo(''), true);
|
550 |
+
|
551 |
+
return $counter;
|
552 |
+
}
|
553 |
+
}
|
src/includes/traits/Plugin/MenuPageUtils.php
ADDED
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait MenuPageUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Adds CSS for administrative menu pages.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @attaches-to `admin_enqueue_scripts` hook.
|
14 |
+
*/
|
15 |
+
public function enqueueAdminStyles()
|
16 |
+
{
|
17 |
+
if (empty($_GET['page']) || strpos($_GET['page'], GLOBAL_NS) !== 0) {
|
18 |
+
return; // NOT a plugin page in the administrative area.
|
19 |
+
}
|
20 |
+
$deps = []; // Plugin dependencies.
|
21 |
+
|
22 |
+
wp_enqueue_style(GLOBAL_NS, $this->url('/src/client-s/css/menu-pages.min.css'), $deps, VERSION, 'all');
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Adds JS for administrative menu pages.
|
27 |
+
*
|
28 |
+
* @since 150422 Rewrite.
|
29 |
+
*
|
30 |
+
* @attaches-to `admin_enqueue_scripts` hook.
|
31 |
+
*/
|
32 |
+
public function enqueueAdminScripts()
|
33 |
+
{
|
34 |
+
if (empty($_GET['page']) || strpos($_GET['page'], GLOBAL_NS) !== 0) {
|
35 |
+
return; // NOT a plugin page in the administrative area.
|
36 |
+
}
|
37 |
+
$deps = ['jquery', 'chartjs']; // Plugin dependencies.
|
38 |
+
|
39 |
+
wp_enqueue_script('chartjs', set_url_scheme('//cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js'), [], null, true);
|
40 |
+
wp_enqueue_script(GLOBAL_NS, $this->url('/src/client-s/js/menu-pages.min.js'), $deps, VERSION, true);
|
41 |
+
wp_localize_script(
|
42 |
+
GLOBAL_NS,
|
43 |
+
GLOBAL_NS.'_menu_page_vars',
|
44 |
+
[
|
45 |
+
'_wpnonce' => wp_create_nonce(),
|
46 |
+
'isMultisite' => is_multisite(), // Network?
|
47 |
+
'currentUserHasCap' => current_user_can($this->cap),
|
48 |
+
'currentUserHasNetworkCap' => current_user_can($this->network_cap),
|
49 |
+
'htmlCompressorEnabled' => (boolean) $this->options['htmlc_enable'],
|
50 |
+
'ajaxURL' => site_url('/wp-load.php', is_ssl() ? 'https' : 'http'),
|
51 |
+
'emptyStatsCountsImageUrl' => $this->url('/src/client-s/images/stats-fc-empty.png'),
|
52 |
+
'emptyStatsFilesImageUrl' => $this->url('/src/client-s/images/stats-fs-empty.png'),
|
53 |
+
'i18n' => [
|
54 |
+
'name' => NAME,
|
55 |
+
'perSymbol' => __('%', 'comet-cache'),
|
56 |
+
'file' => __('file', 'comet-cache'),
|
57 |
+
'files' => __('files', 'comet-cache'),
|
58 |
+
'pageCache' => __('Page Cache', 'comet-cache'),
|
59 |
+
'htmlCompressor' => __('HTML Compressor', 'comet-cache'),
|
60 |
+
'currentTotal' => __('Current Total', 'comet-cache'),
|
61 |
+
'currentSite' => __('Current Site', 'comet-cache'),
|
62 |
+
'xDayHigh' => __('%s Day High', 'comet-cache'),
|
63 |
+
],
|
64 |
+
]
|
65 |
+
);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Creates network admin menu pages.
|
70 |
+
*
|
71 |
+
* @since 150422 Rewrite.
|
72 |
+
*
|
73 |
+
* @attaches-to `network_admin_menu` hook.
|
74 |
+
*/
|
75 |
+
public function addNetworkMenuPages()
|
76 |
+
{
|
77 |
+
if (!is_multisite()) {
|
78 |
+
return; // Not applicable.
|
79 |
+
}
|
80 |
+
$icon = file_get_contents(dirname(dirname(dirname(__DIR__))).'/client-s/images/inline-icon.svg');
|
81 |
+
$icon = 'data:image/svg+xml;base64,'.base64_encode($this->colorSvgMenuIcon($icon));
|
82 |
+
|
83 |
+
add_menu_page(NAME.(IS_PRO ? ' Pro' : ''), NAME.(IS_PRO ? ' Pro' : ''), $this->network_cap, GLOBAL_NS, [$this, 'menuPageOptions'], $icon);
|
84 |
+
add_submenu_page(GLOBAL_NS, __('Plugin Options', 'comet-cache'), __('Plugin Options', 'comet-cache'), $this->network_cap, GLOBAL_NS, [$this, 'menuPageOptions']);
|
85 |
+
|
86 |
+
|
87 |
+
|
88 |
+
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Creates admin menu pages.
|
93 |
+
*
|
94 |
+
* @since 150422 Rewrite.
|
95 |
+
*
|
96 |
+
* @attaches-to `admin_menu` hook.
|
97 |
+
*/
|
98 |
+
public function addMenuPages()
|
99 |
+
{
|
100 |
+
if (is_multisite()) {
|
101 |
+
return; // Multisite networks MUST use network admin area.
|
102 |
+
}
|
103 |
+
$icon = file_get_contents(dirname(dirname(dirname(__DIR__))).'/client-s/images/inline-icon.svg');
|
104 |
+
$icon = 'data:image/svg+xml;base64,'.base64_encode($this->colorSvgMenuIcon($icon));
|
105 |
+
|
106 |
+
add_menu_page(NAME.(IS_PRO ? ' Pro' : ''), NAME.(IS_PRO ? ' Pro' : ''), $this->cap, GLOBAL_NS, [$this, 'menuPageOptions'], $icon);
|
107 |
+
add_submenu_page(GLOBAL_NS, __('Plugin Options', 'comet-cache'), __('Plugin Options', 'comet-cache'), $this->cap, GLOBAL_NS, [$this, 'menuPageOptions']);
|
108 |
+
|
109 |
+
|
110 |
+
|
111 |
+
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Adds link(s) to Comet Cache row on the WP plugins page.
|
116 |
+
*
|
117 |
+
* @since 150422 Rewrite.
|
118 |
+
*
|
119 |
+
* @attaches-to `plugin_action_links_'.plugin_basename(PLUGIN_FILE)` filter.
|
120 |
+
*
|
121 |
+
* @param array $links An array of the existing links provided by WordPress.
|
122 |
+
*
|
123 |
+
* @return array Revised array of links.
|
124 |
+
*/
|
125 |
+
public function addSettingsLink($links)
|
126 |
+
{
|
127 |
+
if (is_multisite() && !is_network_admin()) {
|
128 |
+
return $links;
|
129 |
+
}
|
130 |
+
|
131 |
+
$links[] = '<a href="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS]), self_admin_url('/admin.php'))).'">'.__('Settings', 'comet-cache').'</a>';
|
132 |
+
if (!IS_PRO) {
|
133 |
+
$links[] = '<br/><a href="'.esc_attr(add_query_arg(urlencode_deep(['page' => GLOBAL_NS, GLOBAL_NS.'_pro_preview' => '1']), self_admin_url('/admin.php'))).'">'.__('Preview Pro Features', 'comet-cache').'</a>';
|
134 |
+
$links[] = '<a href="'.esc_attr('http://cometcache.com/prices/').'" target="_blank">'.__('Upgrade', 'comet-cache').'</a>';
|
135 |
+
}
|
136 |
+
return $links;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Fills menu page inline SVG icon color.
|
141 |
+
*
|
142 |
+
* @since 150422 Rewrite.
|
143 |
+
*
|
144 |
+
* @param string $svg Inline SVG icon markup.
|
145 |
+
*
|
146 |
+
* @return string Inline SVG icon markup.
|
147 |
+
*/
|
148 |
+
public function colorSvgMenuIcon($svg)
|
149 |
+
{
|
150 |
+
if (!($color = get_user_option('admin_color'))) {
|
151 |
+
$color = 'fresh'; // Default color scheme.
|
152 |
+
}
|
153 |
+
if (empty($this->wp_admin_icon_colors[$color])) {
|
154 |
+
return $svg; // Not possible.
|
155 |
+
}
|
156 |
+
$icon_colors = $this->wp_admin_icon_colors[$color];
|
157 |
+
$use_icon_fill_color = $icon_colors['base']; // Default base.
|
158 |
+
|
159 |
+
$current_pagenow = !empty($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : '';
|
160 |
+
$current_page = !empty($_REQUEST['page']) ? $_REQUEST['page'] : '';
|
161 |
+
|
162 |
+
if (strpos($current_pagenow, GLOBAL_NS) === 0 || strpos($current_page, GLOBAL_NS) === 0) {
|
163 |
+
$use_icon_fill_color = $icon_colors['current'];
|
164 |
+
}
|
165 |
+
return str_replace(' fill="currentColor"', ' fill="'.esc_attr($use_icon_fill_color).'"', $svg);
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Loads the admin menu page options.
|
170 |
+
*
|
171 |
+
* @since 150422 Rewrite.
|
172 |
+
*/
|
173 |
+
public function menuPageOptions()
|
174 |
+
{
|
175 |
+
new Classes\MenuPage('options');
|
176 |
+
}
|
177 |
+
|
178 |
+
|
179 |
+
|
180 |
+
|
181 |
+
|
182 |
+
/**
|
183 |
+
* WordPress admin icon color schemes.
|
184 |
+
*
|
185 |
+
* @since 150422 Rewrite.
|
186 |
+
*
|
187 |
+
* @type array WP admin icon colors.
|
188 |
+
*
|
189 |
+
* @note These must be hard-coded, because they don't become available
|
190 |
+
* in core until `admin_init`; i.e., too late for `admin_menu`.
|
191 |
+
*/
|
192 |
+
public $wp_admin_icon_colors = [
|
193 |
+
'fresh' => ['base' => '#999999', 'focus' => '#2EA2CC', 'current' => '#FFFFFF'],
|
194 |
+
'light' => ['base' => '#999999', 'focus' => '#CCCCCC', 'current' => '#CCCCCC'],
|
195 |
+
'blue' => ['base' => '#E5F8FF', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'],
|
196 |
+
'midnight' => ['base' => '#F1F2F3', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'],
|
197 |
+
'sunrise' => ['base' => '#F3F1F1', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'],
|
198 |
+
'ectoplasm' => ['base' => '#ECE6F6', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'],
|
199 |
+
'ocean' => ['base' => '#F2FCFF', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'],
|
200 |
+
'coffee' => ['base' => '#F3F2F1', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'],
|
201 |
+
];
|
202 |
+
|
203 |
+
/**
|
204 |
+
* On a specific menu page?
|
205 |
+
*
|
206 |
+
* @since 151002 Improving multisite compat.
|
207 |
+
*
|
208 |
+
* @param string $which Which page to check; may contain wildcards.
|
209 |
+
*
|
210 |
+
* @return bool True if is the menu page.
|
211 |
+
*/
|
212 |
+
public function isMenuPage($which)
|
213 |
+
{
|
214 |
+
if (!($which = trim((string) $which))) {
|
215 |
+
return false; // Empty.
|
216 |
+
}
|
217 |
+
if (!is_admin()) {
|
218 |
+
return false;
|
219 |
+
}
|
220 |
+
$page = $pagenow = ''; // Initialize.
|
221 |
+
|
222 |
+
if (!empty($_REQUEST['page'])) {
|
223 |
+
$page = (string) $_REQUEST['page'];
|
224 |
+
}
|
225 |
+
if (!empty($GLOBALS['pagenow'])) {
|
226 |
+
$pagenow = (string) $GLOBALS['pagenow'];
|
227 |
+
}
|
228 |
+
if ($page && fnmatch($which, $page, FNM_CASEFOLD)) {
|
229 |
+
return true; // Wildcard match.
|
230 |
+
}
|
231 |
+
if ($pagenow && fnmatch($which, $pagenow, FNM_CASEFOLD)) {
|
232 |
+
return true; // Wildcard match.
|
233 |
+
}
|
234 |
+
return false; // Nope.
|
235 |
+
}
|
236 |
+
}
|
src/includes/traits/Plugin/NoticeUtils.php
ADDED
@@ -0,0 +1,337 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait NoticeUtils
|
7 |
+
{
|
8 |
+
/*
|
9 |
+
* Notice queue handlers.
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Enqueue an administrative notice.
|
14 |
+
*
|
15 |
+
* @since 150422 Rewrite. Improved 151002.
|
16 |
+
*
|
17 |
+
* @param string $notice HTML markup containing the notice itself.
|
18 |
+
* @param array $args Any additional arguments supported by the notice API in this plugin.
|
19 |
+
* @param int $blog_id Optional. Defaults to the current blog ID. Use any value `< 0` to indicate the main site.
|
20 |
+
*
|
21 |
+
* @return string A unique key generated for this notice.
|
22 |
+
*/
|
23 |
+
public function enqueueNotice($notice, array $args = [], $blog_id = 0)
|
24 |
+
{
|
25 |
+
$notice = trim((string) $notice);
|
26 |
+
$blog_id = (integer) $blog_id;
|
27 |
+
|
28 |
+
if (!$notice) {
|
29 |
+
return; // Nothing to do.
|
30 |
+
}
|
31 |
+
$notice = ['notice' => $notice];
|
32 |
+
$notice = $this->normalizeNotice($notice, $args);
|
33 |
+
$key = sha1(serialize($notice)); // Prevent dupes.
|
34 |
+
|
35 |
+
$notices = $this->getNotices($blog_id);
|
36 |
+
|
37 |
+
if ($notice['push_to_top']) {
|
38 |
+
$notices = [$key => $notice] + $notices;
|
39 |
+
} else {
|
40 |
+
$notices[$key] = $notice; // Default behavior.
|
41 |
+
}
|
42 |
+
$this->updateNotices($notices, $blog_id);
|
43 |
+
|
44 |
+
return $key; // For dismissals.
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Dismiss an administrative notice.
|
49 |
+
*
|
50 |
+
* @since 151002 Improving multisite compat.
|
51 |
+
*
|
52 |
+
* @param string $key_to_dismiss A unique key which identifies a particular notice.
|
53 |
+
* Or, a persistent key which identifies one or more persistent notices.
|
54 |
+
* @param int $blog_id The blog ID from which to dismiss the notice.
|
55 |
+
*
|
56 |
+
* @return array All remaining notices.
|
57 |
+
*/
|
58 |
+
public function dismissNotice($key_to_dismiss, $blog_id = 0)
|
59 |
+
{
|
60 |
+
$key_to_dismiss = trim((string) $key_to_dismiss);
|
61 |
+
$blog_id = (integer) $blog_id; // For multisite compat.
|
62 |
+
$notices = $enqueued_notices = $this->getNotices($blog_id);
|
63 |
+
|
64 |
+
if (!$key_to_dismiss) {
|
65 |
+
return $notices; // Nothing to do.
|
66 |
+
}
|
67 |
+
foreach ($notices as $_key => $_notice) {
|
68 |
+
if ($_key === $key_to_dismiss) {
|
69 |
+
unset($notices[$_key]); // A specific key.
|
70 |
+
} elseif ($_notice['persistent_key'] === $key_to_dismiss) {
|
71 |
+
unset($notices[$_key]); // All matching keys.
|
72 |
+
}
|
73 |
+
} // ↑ Dismisses all matching keys.
|
74 |
+
unset($_key, $_notice); // Housekeeping.
|
75 |
+
|
76 |
+
if ($notices !== $enqueued_notices) { // Something changed?
|
77 |
+
$this->updateNotices($notices, $blog_id); // Update.
|
78 |
+
}
|
79 |
+
return $notices; // All remaining notices.
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Enqueue an administrative error notice.
|
84 |
+
*
|
85 |
+
* @since 150422 Rewrite. Improved 151002.
|
86 |
+
*/
|
87 |
+
public function enqueueError($notice, array $args = [], $blog_id = 0)
|
88 |
+
{
|
89 |
+
return $this->enqueueNotice($notice, array_merge($args, ['class' => 'error']), $blog_id);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Enqueue an administrative notice (main site).
|
94 |
+
*
|
95 |
+
* @since 151002. Improving multisite compat.
|
96 |
+
*/
|
97 |
+
public function enqueueMainNotice($notice, array $args = [])
|
98 |
+
{
|
99 |
+
return $this->enqueueNotice($notice, $args, -1);
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Enqueue an administrative error notice (main site).
|
104 |
+
*
|
105 |
+
* @since 151002. Improving multisite compat.
|
106 |
+
*/
|
107 |
+
public function enqueueMainError($notice, array $args = [])
|
108 |
+
{
|
109 |
+
return $this->enqueueNotice($notice, array_merge($args, ['class' => 'error']), -1);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Dismiss an administrative notice (main site).
|
114 |
+
*
|
115 |
+
* @since 151002 Improving multisite compat.
|
116 |
+
*/
|
117 |
+
public function dismissMainNotice($key_to_dismiss)
|
118 |
+
{
|
119 |
+
return $this->dismissNotice($key_to_dismiss, -1);
|
120 |
+
}
|
121 |
+
|
122 |
+
/*
|
123 |
+
* Notice display handler.
|
124 |
+
*/
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Render admin notices.
|
128 |
+
*
|
129 |
+
* @since 150422 Rewrite. Improved 151002.
|
130 |
+
*
|
131 |
+
* @attaches-to `all_admin_notices` hook.
|
132 |
+
*/
|
133 |
+
public function allAdminNotices()
|
134 |
+
{
|
135 |
+
$notices = $enqueued_notices = $this->getNotices();
|
136 |
+
$combined_notices = []; // Initialize
|
137 |
+
|
138 |
+
foreach ($notices as $_key => $_notice) {
|
139 |
+
# Always dismiss all non-persistent transients.
|
140 |
+
|
141 |
+
if ($_notice['is_transient'] && !$_notice['persistent_key']) {
|
142 |
+
unset($notices[$_key]); // Dismiss.
|
143 |
+
}
|
144 |
+
# Current user can see this notice?
|
145 |
+
|
146 |
+
if (!current_user_can($this->cap)) {
|
147 |
+
continue; // Current user unable to see.
|
148 |
+
}
|
149 |
+
if ($_notice['cap_required'] && !current_user_can($_notice['cap_required'])) {
|
150 |
+
continue; // Current user unable to see this notice.
|
151 |
+
}
|
152 |
+
# Current URI matches a limited scope/context for this notice?
|
153 |
+
|
154 |
+
if ($_notice['only_on_uris'] && !@preg_match($_notice['only_on_uris'], $_SERVER['REQUEST_URI'])) {
|
155 |
+
continue; // Not in the right context at the moment; i.e., does not regex.
|
156 |
+
}
|
157 |
+
# If persistent, allow a site owner to dismiss.
|
158 |
+
|
159 |
+
$_dismiss = ''; // Initialize
|
160 |
+
if ($_notice['persistent_key'] && $_notice['dismissable']) { // See above. The `dismissNotice()` action requires `$this->cap` always.
|
161 |
+
$_dismiss = add_query_arg(urlencode_deep([GLOBAL_NS => ['dismissNotice' => ['key' => $_key]], '_wpnonce' => wp_create_nonce()]));
|
162 |
+
$_dismiss = '<a href="'.esc_attr($_dismiss).'"><button type="button" class="notice-dismiss"><span class="screen-reader-text">'.__('Dismiss this notice.', 'comet-cache').'</span></button></a>';
|
163 |
+
}
|
164 |
+
# Display this notice, or save for displaying compacted later. If not persistent, we can dismiss it too.
|
165 |
+
|
166 |
+
if ($_notice['combinable'] && !$_notice['persistent_key']) {
|
167 |
+
$combined_notices[] = $_notice['notice']; // Save this for displaying as part of a single, combined notice.
|
168 |
+
} else {
|
169 |
+
echo '<div class="'.esc_attr($_notice['class']).'" style="clear:both; padding-right:38px; position: relative;"><p>'.$_notice['notice'].'</p>'.$_dismiss.'</div>';
|
170 |
+
}
|
171 |
+
|
172 |
+
if (!$_notice['persistent_key']) { // If not persistent, dismiss.
|
173 |
+
unset($notices[$_key]); // Dismiss; this notice has been displayed now.
|
174 |
+
}
|
175 |
+
}
|
176 |
+
unset($_key, $_notice, $_dismiss); // Housekeeping.
|
177 |
+
|
178 |
+
if (!empty($combined_notices)) { // Display a single notice with details hidden by default.
|
179 |
+
$_line_items = ''; // Initialize
|
180 |
+
foreach ($combined_notices as $_item) {
|
181 |
+
$_line_items .= '<p><span class="dashicons dashicons-yes"></span> '.$_item.'</p>'."\n";
|
182 |
+
}
|
183 |
+
|
184 |
+
$_show_details = __('Show details.', 'comet-cache');
|
185 |
+
$_hide_details = __('Hide details.', 'comet-cache');
|
186 |
+
|
187 |
+
$_combined = '<div class="updated notice is-dismissible" style="clear:both; padding-right:38px; position: relative;">';
|
188 |
+
$_combined .= '<p><img src="'.esc_attr($this->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />';
|
189 |
+
$_combined .= sprintf(__('<strong>%1$s</strong> detected changes and intelligently cleared the cache to keep your site up-to-date. <a href="#" id="'.SLUG_TD.'-toggle-notices" onclick="jQuery(\'#'.SLUG_TD.'-combined-notices\').toggle();if (jQuery(\'#comet-cache-combined-notices\').is(\':visible\')) { jQuery(this).text(\''.$_hide_details.'\'); } else { jQuery(this).text(\''.$_show_details.'\'); }">'.$_show_details.'</a>', 'comet-cache'), esc_html(NAME)).'</p>';
|
190 |
+
$_combined .= '<div id="'.SLUG_TD.'-combined-notices" style="display: none;">'.$_line_items.'</div>';
|
191 |
+
$_combined .= '<button type="button" class="notice-dismiss"><span class="screen-reader-text">'.__('Dismiss this notice.', 'comet-cache').'</span></button>';
|
192 |
+
$_combined .= '</div>';
|
193 |
+
|
194 |
+
echo $_combined;
|
195 |
+
|
196 |
+
unset($_item, $_line_item, $_combined); // Housekeeping.
|
197 |
+
}
|
198 |
+
|
199 |
+
# Update notices if something changed above.
|
200 |
+
|
201 |
+
if ($notices !== $enqueued_notices) { // Something changed?
|
202 |
+
$this->updateNotices($notices); // Update.
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
/*
|
207 |
+
* Notice getter/setter.
|
208 |
+
*/
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Get admin notices.
|
212 |
+
*
|
213 |
+
* @since 151002 Improving multisite compat.
|
214 |
+
*
|
215 |
+
* @param int $blog_id Optional. Defaults to the current blog ID.
|
216 |
+
* Use any value `< 0` to indicate the main site.
|
217 |
+
*
|
218 |
+
* @return array All notices.
|
219 |
+
*/
|
220 |
+
public function getNotices($blog_id = 0)
|
221 |
+
{
|
222 |
+
if (is_multisite()) {
|
223 |
+
if (!($blog_id = (integer) $blog_id)) {
|
224 |
+
$blog_id = (integer) get_current_blog_id();
|
225 |
+
}
|
226 |
+
if ($blog_id < 0) { // Blog for main site.
|
227 |
+
$blog_id = (integer) get_current_site()->blog_id;
|
228 |
+
}
|
229 |
+
$blog_suffix = '_'.$blog_id; // Site option suffix.
|
230 |
+
$notices = get_site_option(GLOBAL_NS.$blog_suffix.'_notices');
|
231 |
+
} else {
|
232 |
+
$notices = get_site_option(GLOBAL_NS.'_notices');
|
233 |
+
}
|
234 |
+
if (!is_array($notices)) {
|
235 |
+
$notices = []; // Force array.
|
236 |
+
// Prevent multiple DB queries by adding this key.
|
237 |
+
$this->updateNotices($notices, $blog_id);
|
238 |
+
}
|
239 |
+
foreach ($notices as $_key => &$_notice) {
|
240 |
+
if (!is_string($_key) || !is_array($_notice) || empty($_notice['notice'])) {
|
241 |
+
unset($notices[$_key]); // Old notice.
|
242 |
+
continue; // Bypass; i.e., do not normalize.
|
243 |
+
}
|
244 |
+
$_notice = $this->normalizeNotice($_notice);
|
245 |
+
} // ↑ Typecast/normalized each of the array elements.
|
246 |
+
unset($_key, $_notice); // Housekeeping.
|
247 |
+
|
248 |
+
return $notices;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Update admin notices.
|
253 |
+
*
|
254 |
+
* @since 151002 Improving multisite compat.
|
255 |
+
*
|
256 |
+
* @param array $notices New array of notices.
|
257 |
+
* @param int $blog_id Optional. Defaults to the current blog ID.
|
258 |
+
* Use any value `< 0` to indicate the main site.
|
259 |
+
*
|
260 |
+
* @return array All notices.
|
261 |
+
*/
|
262 |
+
public function updateNotices(array $notices, $blog_id = 0)
|
263 |
+
{
|
264 |
+
if (is_multisite()) {
|
265 |
+
if (!($blog_id = (integer) $blog_id)) {
|
266 |
+
$blog_id = (integer) get_current_blog_id();
|
267 |
+
}
|
268 |
+
if ($blog_id < 0) { // Blog for main site.
|
269 |
+
$blog_id = (integer) get_current_site()->blog_id;
|
270 |
+
}
|
271 |
+
$blog_suffix = '_'.$blog_id; // Site option suffix.
|
272 |
+
update_site_option(GLOBAL_NS.$blog_suffix.'_notices', $notices);
|
273 |
+
} else {
|
274 |
+
update_site_option(GLOBAL_NS.'_notices', $notices);
|
275 |
+
}
|
276 |
+
return $notices;
|
277 |
+
}
|
278 |
+
|
279 |
+
/*
|
280 |
+
* Notice property utilities.
|
281 |
+
*/
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Normalize notice elements.
|
285 |
+
*
|
286 |
+
* @since 151002 Improving multisite compat.
|
287 |
+
*
|
288 |
+
* @param array $notice Notice array elements.
|
289 |
+
* @param array $args Any additional array elements.
|
290 |
+
*
|
291 |
+
* @return array Normalized notice array elements.
|
292 |
+
*/
|
293 |
+
public function normalizeNotice(array $notice, array $args = [])
|
294 |
+
{
|
295 |
+
$notice_defaults = [
|
296 |
+
'notice' => '',
|
297 |
+
'only_on_uris' => '',
|
298 |
+
'persistent_key' => '',
|
299 |
+
'combinable' => false,
|
300 |
+
'dismissable' => true,
|
301 |
+
'is_transient' => true,
|
302 |
+
'push_to_top' => false,
|
303 |
+
'class' => 'updated',
|
304 |
+
'cap_required' => '', // `$this->cap` always.
|
305 |
+
// i.e., this cap is in addition to `$this->cap`.
|
306 |
+
];
|
307 |
+
$notice = array_merge($notice_defaults, $notice, $args);
|
308 |
+
$notice = array_intersect_key($notice, $notice_defaults);
|
309 |
+
|
310 |
+
foreach ($notice as $_key => &$_value) {
|
311 |
+
switch ($_key) {
|
312 |
+
case 'notice':
|
313 |
+
case 'only_on_uris':
|
314 |
+
case 'persistent_key':
|
315 |
+
$_value = trim((string) $_value);
|
316 |
+
break; // Stop here.
|
317 |
+
|
318 |
+
case 'is_transient':
|
319 |
+
case 'push_to_top':
|
320 |
+
case 'combinable':
|
321 |
+
case 'dismissable':
|
322 |
+
$_value = (boolean) $_value;
|
323 |
+
break; // Stop here.
|
324 |
+
|
325 |
+
case 'class':
|
326 |
+
case 'cap_required':
|
327 |
+
$_value = trim((string) $_value);
|
328 |
+
break; // Stop here.
|
329 |
+
}
|
330 |
+
} // ↑ Typecast each of the array elements.
|
331 |
+
unset($_key, $_value); // A little housekeeping.
|
332 |
+
|
333 |
+
ksort($notice); // For more accurate comparison in other routines.
|
334 |
+
|
335 |
+
return $notice; // Normalized.
|
336 |
+
}
|
337 |
+
}
|
src/includes/traits/Plugin/OptionUtils.php
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait OptionUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Get plugin options.
|
10 |
+
*
|
11 |
+
* @since 151002 Improving multisite compat.
|
12 |
+
*
|
13 |
+
* @return array Plugin options.
|
14 |
+
*/
|
15 |
+
public function getOptions()
|
16 |
+
{
|
17 |
+
if (!($options = $this->options)) { // Not defined yet?
|
18 |
+
if (!is_array($options = get_site_option(GLOBAL_NS.'_options'))) {
|
19 |
+
$options = []; // Force array.
|
20 |
+
}
|
21 |
+
if (!$options && is_array($zencache_options = get_site_option('zencache_options'))) {
|
22 |
+
$options = $zencache_options; // Old ZenCache options.
|
23 |
+
$options['crons_setup'] = $this->default_options['crons_setup'];
|
24 |
+
$options['latest_lite_version'] = $this->default_options['latest_lite_version'];
|
25 |
+
$options['latest_pro_version'] = $this->default_options['latest_pro_version'];
|
26 |
+
}
|
27 |
+
}
|
28 |
+
$this->options = array_merge($this->default_options, $options);
|
29 |
+
$this->options = $this->applyWpFilters(GLOBAL_NS.'_options', $this->options);
|
30 |
+
$this->options = array_intersect_key($this->options, $this->default_options);
|
31 |
+
|
32 |
+
foreach ($this->options as $_key => &$_value) {
|
33 |
+
$_value = trim((string) $_value); // Force strings.
|
34 |
+
}
|
35 |
+
unset($_key, $_value); // Housekeeping.
|
36 |
+
|
37 |
+
$this->options['base_dir'] = trim($this->options['base_dir'], '\\/'." \t\n\r\0\x0B");
|
38 |
+
if (!$this->options['base_dir'] || strpos(basename($this->options['base_dir']), 'wp-') === 0) {
|
39 |
+
$this->options['base_dir'] = $this->default_options['base_dir'];
|
40 |
+
}
|
41 |
+
return $this->options; // Plugin options.
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Update plugin options.
|
46 |
+
*
|
47 |
+
* @since 151002 Improving multisite compat.
|
48 |
+
*
|
49 |
+
* @param array $options One or more new options.
|
50 |
+
*
|
51 |
+
* @return array Plugin options after update.
|
52 |
+
*/
|
53 |
+
public function updateOptions(array $options)
|
54 |
+
{
|
55 |
+
if (!IS_PRO) { // Do not save Pro option keys.
|
56 |
+
$options = array_diff_key($options, $this->pro_only_option_keys);
|
57 |
+
}
|
58 |
+
if (!empty($options['base_dir']) && $options['base_dir'] !== $this->options['base_dir']) {
|
59 |
+
$this->tryErasingAllFilesDirsIn($this->wpContentBaseDirTo(''));
|
60 |
+
}
|
61 |
+
$this->options = array_merge($this->default_options, $this->options, $options);
|
62 |
+
$this->options = array_intersect_key($this->options, $this->default_options);
|
63 |
+
update_site_option(GLOBAL_NS.'_options', $this->options);
|
64 |
+
|
65 |
+
return $this->getOptions();
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Restore default plugin options.
|
70 |
+
*
|
71 |
+
* @since 151002 Improving multisite compat.
|
72 |
+
*
|
73 |
+
* @return array Plugin options after update.
|
74 |
+
*/
|
75 |
+
public function restoreDefaultOptions()
|
76 |
+
{
|
77 |
+
delete_site_option(GLOBAL_NS.'_options'); // Force restore.
|
78 |
+
$this->options = $this->default_options; // In real-time.
|
79 |
+
return $this->getOptions();
|
80 |
+
}
|
81 |
+
}
|
src/includes/traits/Plugin/PostUtils.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait PostUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* All post statuses.
|
10 |
+
*
|
11 |
+
* @since 150821 Improving bbPress support.
|
12 |
+
*
|
13 |
+
* @return array All post statuses.
|
14 |
+
*/
|
15 |
+
public function postStatuses()
|
16 |
+
{
|
17 |
+
if (!is_null($statuses = &$this->cacheKey('postStatuses'))) {
|
18 |
+
return $statuses; // Already did this.
|
19 |
+
}
|
20 |
+
$statuses = get_post_stati();
|
21 |
+
$statuses = array_keys($statuses);
|
22 |
+
|
23 |
+
return $statuses;
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* All built-in post statuses.
|
28 |
+
*
|
29 |
+
* @since 150821 Improving bbPress support.
|
30 |
+
*
|
31 |
+
* @return array All built-in post statuses.
|
32 |
+
*/
|
33 |
+
public function builtInPostStatuses()
|
34 |
+
{
|
35 |
+
if (!is_null($statuses = &$this->cacheKey('builtInPostStatuses'))) {
|
36 |
+
return $statuses; // Already did this.
|
37 |
+
}
|
38 |
+
$statuses = []; // Initialize.
|
39 |
+
|
40 |
+
foreach (get_post_stati([], 'objects') as $_key => $_status) {
|
41 |
+
if (!empty($_status->_builtin)) {
|
42 |
+
$statuses[] = $_status->name;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
unset($_key, $_status); // Housekeeping.
|
46 |
+
|
47 |
+
return $statuses;
|
48 |
+
}
|
49 |
+
}
|
src/includes/traits/Plugin/UpdateUtils.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
*
|
13 |
+
* @attaches-to `admin_init` hook.
|
14 |
+
*/
|
15 |
+
public function maybeCheckLatestLiteVersion()
|
16 |
+
{
|
17 |
+
if (IS_PRO) {
|
18 |
+
return; // Not applicable.
|
19 |
+
}
|
20 |
+
if (!$this->options['lite_update_check']) {
|
21 |
+
return; // Nothing to do.
|
22 |
+
}
|
23 |
+
if (!current_user_can($this->update_cap)) {
|
24 |
+
return; // Nothing to do.
|
25 |
+
}
|
26 |
+
if (is_multisite() && !current_user_can($this->network_cap)) {
|
27 |
+
return; // Nothing to do.
|
28 |
+
}
|
29 |
+
if ($this->options['last_lite_update_check'] >= strtotime('-1 hour')) {
|
30 |
+
return; // No reason to keep checking on this.
|
31 |
+
}
|
32 |
+
$this->updateOptions(['last_lite_update_check' => time()]);
|
33 |
+
|
34 |
+
$product_api_url = 'https://'.urlencode(DOMAIN).'/';
|
35 |
+
$product_api_input_vars = ['product_api' => ['action' => 'latest_lite_version']];
|
36 |
+
|
37 |
+
$product_api_response = wp_remote_post($product_api_url, ['body' => $product_api_input_vars]);
|
38 |
+
$product_api_response = json_decode(wp_remote_retrieve_body($product_api_response));
|
39 |
+
|
40 |
+
if (is_object($product_api_response) && !empty($product_api_response->lite_version)) {
|
41 |
+
$this->updateOptions(['latest_lite_version' => $product_api_response->lite_version]);
|
42 |
+
}
|
43 |
+
// Disabling the notice for now. We only run this check to collect the latest version number.
|
44 |
+
#if ($this->options['latest_lite_version'] && version_compare(VERSION, $this->options['latest_lite_version'], '<')) {
|
45 |
+
# $this->dismissMainNotice('new-lite-version-available'); // Dismiss any existing notices like this.
|
46 |
+
# $lite_updater_page = network_admin_url('/plugins.php'); // In a network this points to the master plugins list.
|
47 |
+
# $this->enqueueMainNotice(sprintf(__('<strong>%1$s:</strong> a new version is now available. Please <a href="%2$s">upgrade to v%3$s</a>.', 'comet-cache'), esc_html(NAME), esc_attr($lite_updater_page), esc_html($this->options['latest_lite_version'])), array('persistent_key' => 'new-lite-version-available'));
|
48 |
+
#}
|
49 |
+
}
|
50 |
+
|
51 |
+
|
52 |
+
}
|
src/includes/traits/Plugin/UrlUtils.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait UrlUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* URL to a Comet Cache plugin file.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param string $file Optional file path; relative to plugin directory.
|
14 |
+
* @param string $scheme Optional URL scheme; defaults to the current scheme.
|
15 |
+
*
|
16 |
+
* @return string URL to plugin directory; or to the specified `$file` if applicable.
|
17 |
+
*/
|
18 |
+
public function url($file = '', $scheme = '')
|
19 |
+
{
|
20 |
+
$url = rtrim(plugin_dir_url(PLUGIN_FILE), '/');
|
21 |
+
$url .= (string) $file;
|
22 |
+
|
23 |
+
if ($scheme) {
|
24 |
+
$url = set_url_scheme($url, (string) $scheme);
|
25 |
+
}
|
26 |
+
return $url;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Retrieves the home URL for a given site preserving the home URL scheme.
|
31 |
+
*
|
32 |
+
* @since 160416 Improving Auto-Cache Engine Sitemap routines.
|
33 |
+
*
|
34 |
+
* @param int $blog_id (Optional) Blog ID. Default null (current blog).
|
35 |
+
*
|
36 |
+
* @return string $url Home URL link with Home URL scheme preserved.
|
37 |
+
*/
|
38 |
+
public function getHomeUrlWithHomeScheme($blog_id = null)
|
39 |
+
{
|
40 |
+
if (empty($blog_id) || !is_multisite()) {
|
41 |
+
$url = get_option('home');
|
42 |
+
} else {
|
43 |
+
switch_to_blog($blog_id);
|
44 |
+
$url = get_option('home');
|
45 |
+
restore_current_blog();
|
46 |
+
}
|
47 |
+
|
48 |
+
$url = set_url_scheme($url, parse_url($url, PHP_URL_SCHEME));
|
49 |
+
|
50 |
+
return $url;
|
51 |
+
}
|
52 |
+
}
|
src/includes/traits/Plugin/UserUtils.php
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait UserUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Current user can clear the cache?
|
10 |
+
*
|
11 |
+
* @since 151002 Enhancing user permissions.
|
12 |
+
*
|
13 |
+
* @return bool Current user can clear the cache?
|
14 |
+
*/
|
15 |
+
public function currentUserCanClearCache()
|
16 |
+
{
|
17 |
+
if (!is_null($can = &$this->cacheKey('currentUserCanClearCache'))) {
|
18 |
+
return $can; // Already cached this.
|
19 |
+
}
|
20 |
+
$is_multisite = is_multisite();
|
21 |
+
|
22 |
+
if (!$is_multisite && current_user_can($this->cap)) {
|
23 |
+
return $can = true; // Plugin admin.
|
24 |
+
}
|
25 |
+
if ($is_multisite && current_user_can($this->network_cap)) {
|
26 |
+
return $can = true; // Plugin admin.
|
27 |
+
}
|
28 |
+
|
29 |
+
return $can = false;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Alias for currentUserCanClearCache().
|
34 |
+
*
|
35 |
+
* @since 151002 Enhancing user permissions.
|
36 |
+
*
|
37 |
+
* @return bool Current user can clear the cache?
|
38 |
+
*/
|
39 |
+
public function currentUserCanWipeCache()
|
40 |
+
{
|
41 |
+
return call_user_func_array([$this, 'currentUserCanClearCache'], func_get_args());
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Current user can clear the opcache?
|
46 |
+
*
|
47 |
+
* @since 151114 Enhancing user permissions.
|
48 |
+
*
|
49 |
+
* @return bool Current user can clear the opcache?
|
50 |
+
*/
|
51 |
+
public function currentUserCanClearOpCache()
|
52 |
+
{
|
53 |
+
if (!is_null($can = &$this->cacheKey('currentUserCanClearOpCache'))) {
|
54 |
+
return $can; // Already cached this.
|
55 |
+
}
|
56 |
+
$is_multisite = is_multisite();
|
57 |
+
|
58 |
+
if (!$is_multisite && current_user_can($this->cap)) {
|
59 |
+
return $can = true; // Plugin admin.
|
60 |
+
}
|
61 |
+
if ($is_multisite && current_user_can($this->network_cap)) {
|
62 |
+
return $can = true; // Plugin admin.
|
63 |
+
}
|
64 |
+
return $can = false;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Alias for currentUserCanClearOpCache().
|
69 |
+
*
|
70 |
+
* @since 151114 Enhancing user permissions.
|
71 |
+
*
|
72 |
+
* @return bool Current user can clear the opcache?
|
73 |
+
*/
|
74 |
+
public function currentUserCanWipeOpCache()
|
75 |
+
{
|
76 |
+
return call_user_func_array([$this, 'currentUserCanClearOpCache'], func_get_args());
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Current user can clear the CDN cache?
|
81 |
+
*
|
82 |
+
* @since 151114 Enhancing user permissions.
|
83 |
+
*
|
84 |
+
* @return bool Current user can clear the CDN cache?
|
85 |
+
*/
|
86 |
+
public function currentUserCanClearCdnCache()
|
87 |
+
{
|
88 |
+
if (!is_null($can = &$this->cacheKey('currentUserCanClearCdnCache'))) {
|
89 |
+
return $can; // Already cached this.
|
90 |
+
}
|
91 |
+
$is_multisite = is_multisite();
|
92 |
+
|
93 |
+
if (!$is_multisite && current_user_can($this->cap)) {
|
94 |
+
return $can = true; // Plugin admin.
|
95 |
+
}
|
96 |
+
if ($is_multisite && current_user_can($this->network_cap)) {
|
97 |
+
return $can = true; // Plugin admin.
|
98 |
+
}
|
99 |
+
return $can = false;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Alias for currentUserCanClearCdnCache().
|
104 |
+
*
|
105 |
+
* @since 151114 Enhancing user permissions.
|
106 |
+
*
|
107 |
+
* @return bool Current user can clear the CDN cache?
|
108 |
+
*/
|
109 |
+
public function currentUserCanWipeCdnCache()
|
110 |
+
{
|
111 |
+
return call_user_func_array([$this, 'currentUserCanClearCdnCache'], func_get_args());
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Current user can clear expired transients?
|
116 |
+
*
|
117 |
+
* @since 151220 Enhancing user permissions.
|
118 |
+
*
|
119 |
+
* @return bool Current user can clear expired transients?
|
120 |
+
*/
|
121 |
+
public function currentUserCanClearExpiredTransients()
|
122 |
+
{
|
123 |
+
if (!is_null($can = &$this->cacheKey('currentUserCanClearExpiredTransients'))) {
|
124 |
+
return $can; // Already cached this.
|
125 |
+
}
|
126 |
+
$is_multisite = is_multisite();
|
127 |
+
|
128 |
+
if (!$is_multisite && current_user_can($this->cap)) {
|
129 |
+
return $can = true; // Plugin admin.
|
130 |
+
}
|
131 |
+
if ($is_multisite && current_user_can($this->network_cap)) {
|
132 |
+
return $can = true; // Plugin admin.
|
133 |
+
}
|
134 |
+
return $can = false;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Alias for currentUserCanClearExpiredTransients().
|
139 |
+
*
|
140 |
+
* @since 151220 Enhancing user permissions.
|
141 |
+
*
|
142 |
+
* @return bool Current user can clear expired transients?
|
143 |
+
*/
|
144 |
+
public function currentUserCanWipeExpiredTransients()
|
145 |
+
{
|
146 |
+
return call_user_func_array([$this, 'currentUserCanClearExpiredTransients'], func_get_args());
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Current user can see stats?
|
151 |
+
*
|
152 |
+
* @since 151002 Enhancing user permissions.
|
153 |
+
*
|
154 |
+
* @return bool Current user can see stats?
|
155 |
+
*/
|
156 |
+
public function currentUserCanSeeStats()
|
157 |
+
{
|
158 |
+
if (!is_null($can = &$this->cacheKey('currentUserCanSeeStats'))) {
|
159 |
+
return $can; // Already cached this.
|
160 |
+
}
|
161 |
+
$is_multisite = is_multisite();
|
162 |
+
|
163 |
+
if (!$is_multisite && current_user_can($this->cap)) {
|
164 |
+
return $can = true; // Plugin admin.
|
165 |
+
}
|
166 |
+
if ($is_multisite && current_user_can($this->network_cap)) {
|
167 |
+
return $can = true; // Plugin admin.
|
168 |
+
}
|
169 |
+
|
170 |
+
return $can = false;
|
171 |
+
}
|
172 |
+
}
|
src/includes/traits/Plugin/WcpAuthorUtils.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpAuthorUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files for the author page(s).
|
10 |
+
*
|
11 |
+
* @attaches-to `post_updated` hook.
|
12 |
+
*
|
13 |
+
* @since 150422 Rewrite.
|
14 |
+
*
|
15 |
+
* @param int $post_id A WordPress post ID.
|
16 |
+
* @param \WP_Post $post_after WP_Post object following the update.
|
17 |
+
* @param \WP_Post $post_before WP_Post object before the update.
|
18 |
+
*
|
19 |
+
* @throws \Exception If a clear failure occurs.
|
20 |
+
*
|
21 |
+
* @return int Total files cleared by this routine (if any).
|
22 |
+
*
|
23 |
+
* @note If the author for the post is being changed, both the previous author
|
24 |
+
* and current author pages are cleared, if the post status is applicable.
|
25 |
+
*/
|
26 |
+
public function autoClearAuthorPageCache($post_id, \WP_Post $post_after, \WP_Post $post_before)
|
27 |
+
{
|
28 |
+
$counter = 0; // Initialize.
|
29 |
+
$enqueued_notices = 0; // Initialize.
|
30 |
+
$authors = []; // Initialize.
|
31 |
+
$authors_to_clear = []; // Initialize.
|
32 |
+
|
33 |
+
if (!($post_id = (integer) $post_id)) {
|
34 |
+
return $counter; // Nothing to do.
|
35 |
+
}
|
36 |
+
if (!is_null($done = &$this->cacheKey('autoClearAuthorPageCache', [$post_id, $post_after->ID, $post_before->ID]))) {
|
37 |
+
return $counter; // Already did this.
|
38 |
+
}
|
39 |
+
$done = true; // Flag as having been done.
|
40 |
+
|
41 |
+
if (!$this->options['enable']) {
|
42 |
+
return $counter; // Nothing to do.
|
43 |
+
}
|
44 |
+
if (!$this->options['cache_clear_author_page_enable']) {
|
45 |
+
return $counter; // Nothing to do.
|
46 |
+
}
|
47 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
48 |
+
return $counter; // Nothing to do.
|
49 |
+
}
|
50 |
+
/*
|
51 |
+
* If we're changing the post author AND
|
52 |
+
* the previous post status was either 'published' or 'private'
|
53 |
+
* then clear the author page for both authors.
|
54 |
+
*
|
55 |
+
* Else if the old post status was 'published' or 'private' OR
|
56 |
+
* the new post status is 'published' or 'private'
|
57 |
+
* then clear the author page for the current author.
|
58 |
+
*
|
59 |
+
* Else return the counter; post status does not warrant clearing author page cache.
|
60 |
+
*/
|
61 |
+
if ($post_after->post_author !== $post_before->post_author &&
|
62 |
+
($post_before->post_status === 'publish' || $post_before->post_status === 'private')
|
63 |
+
) {
|
64 |
+
$authors[] = (integer) $post_before->post_author;
|
65 |
+
$authors[] = (integer) $post_after->post_author;
|
66 |
+
} elseif (($post_before->post_status === 'publish' || $post_before->post_status === 'private') ||
|
67 |
+
($post_after->post_status === 'publish' || $post_after->post_status === 'private')
|
68 |
+
) {
|
69 |
+
$authors[] = (integer) $post_after->post_author;
|
70 |
+
}
|
71 |
+
if (!$authors) {
|
72 |
+
return $counter; // Nothing to do.
|
73 |
+
}
|
74 |
+
foreach ($authors as $_author_id) {
|
75 |
+
$authors_to_clear[$_author_id]['posts_url'] = get_author_posts_url($_author_id);
|
76 |
+
$authors_to_clear[$_author_id]['display_name'] = get_the_author_meta('display_name', $_author_id);
|
77 |
+
}
|
78 |
+
unset($_author_id); // Housekeeping.
|
79 |
+
|
80 |
+
foreach ($authors_to_clear as $_author) {
|
81 |
+
$_author_regex = $this->buildHostCachePathRegex($_author['posts_url']);
|
82 |
+
$_author_counter = $this->clearFilesFromHostCacheDir($_author_regex);
|
83 |
+
$counter += $_author_counter; // Add to overall counter.
|
84 |
+
|
85 |
+
if ($_author_counter && $enqueued_notices < 100 && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
86 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache for Author Page: <code>%2$s</code>; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($_author_counter)), esc_html($_author['display_name'])), ['combinable' => true]);
|
87 |
+
++$enqueued_notices; // Increment enqueued notices counter.
|
88 |
+
}
|
89 |
+
}
|
90 |
+
unset($_author, $_author_regex, $_author_counter); // Housekeeping.
|
91 |
+
|
92 |
+
$counter += $this->autoClearXmlFeedsCache('blog');
|
93 |
+
$counter += $this->autoClearXmlFeedsCache('post-authors', $post_id);
|
94 |
+
|
95 |
+
return $counter;
|
96 |
+
}
|
97 |
+
}
|
src/includes/traits/Plugin/WcpCommentUtils.php
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpCommentUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files for a post associated with a particular comment.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @attaches-to `trackback_post` hook.
|
14 |
+
* @attaches-to `pingback_post` hook.
|
15 |
+
* @attaches-to `comment_post` hook.
|
16 |
+
*
|
17 |
+
* @param int $comment_id A WordPress comment ID.
|
18 |
+
*
|
19 |
+
* @return int Total files cleared by this routine (if any).
|
20 |
+
*/
|
21 |
+
public function autoClearCommentPostCache($comment_id)
|
22 |
+
{
|
23 |
+
$counter = 0; // Initialize.
|
24 |
+
|
25 |
+
if (!($comment_id = (integer) $comment_id)) {
|
26 |
+
return $counter; // Nothing to do.
|
27 |
+
}
|
28 |
+
if (!is_null($done = &$this->cacheKey('autoClearCommentPostCache', $comment_id))) {
|
29 |
+
return $counter; // Already did this.
|
30 |
+
}
|
31 |
+
$done = true; // Flag as having been done.
|
32 |
+
|
33 |
+
if (!$this->options['enable']) {
|
34 |
+
return $counter; // Nothing to do.
|
35 |
+
}
|
36 |
+
if (!is_object($comment = get_comment($comment_id))) {
|
37 |
+
return $counter; // Nothing we can do.
|
38 |
+
}
|
39 |
+
if (empty($comment->comment_post_ID)) {
|
40 |
+
return $counter; // Nothing we can do.
|
41 |
+
}
|
42 |
+
if ($comment->comment_approved === 'spam' || $comment->comment_approved === '0') {
|
43 |
+
// Don't allow next `autoClearPostCache()` call to clear post cache.
|
44 |
+
$allow = &$this->cacheKey('autoClearPostCache_allow');
|
45 |
+
$allow = false; // Flag as false; i.e., disallow.
|
46 |
+
return $counter;
|
47 |
+
}
|
48 |
+
$counter += $this->autoClearXmlFeedsCache('blog-comments');
|
49 |
+
$counter += $this->autoClearXmlFeedsCache('post-comments', $comment->comment_post_ID);
|
50 |
+
$counter += $this->autoClearPostCache($comment->comment_post_ID);
|
51 |
+
|
52 |
+
return $counter;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Automatically clears cache files for a post associated with a particular comment.
|
57 |
+
*
|
58 |
+
* @since 150422 Rewrite.
|
59 |
+
*
|
60 |
+
* @attaches-to `transition_comment_status` hook.
|
61 |
+
*
|
62 |
+
* @param string $new_status New comment status.
|
63 |
+
* @param string $old_status Old comment status.
|
64 |
+
* @param \stdClass $comment Comment object.
|
65 |
+
*
|
66 |
+
* @throws \Exception If a clear failure occurs.
|
67 |
+
*
|
68 |
+
* @return int Total files cleared by this routine (if any).
|
69 |
+
*
|
70 |
+
* @note This is also called upon by other routines which listen for
|
71 |
+
* events that are indirectly associated with a comment ID.
|
72 |
+
*/
|
73 |
+
public function autoClearCommentPostCacheTransition($new_status, $old_status, $comment)
|
74 |
+
{
|
75 |
+
$counter = 0; // Initialize.
|
76 |
+
|
77 |
+
if (!is_object($comment)) {
|
78 |
+
return $counter; // Nothing we can do.
|
79 |
+
}
|
80 |
+
if (empty($comment->comment_post_ID)) {
|
81 |
+
return $counter; // Nothing we can do.
|
82 |
+
}
|
83 |
+
if (!is_null($done = &$this->cacheKey('autoClearCommentPostCacheTransition', [$new_status, $old_status, $comment->comment_post_ID]))) {
|
84 |
+
return $counter; // Already did this.
|
85 |
+
}
|
86 |
+
$done = true; // Flag as having been done.
|
87 |
+
|
88 |
+
if (!$this->options['enable']) {
|
89 |
+
return $counter; // Nothing to do.
|
90 |
+
}
|
91 |
+
if (!($old_status === 'approved' || ($old_status === 'unapproved' && $new_status === 'approved'))) {
|
92 |
+
// If excluded here, don't allow next `autoClearPostCache()` call to clear post cache.
|
93 |
+
$allow = &$this->cacheKey('autoClearPostCache_allow');
|
94 |
+
$allow = false; // Flag as false; i.e., disallow.
|
95 |
+
return $counter;
|
96 |
+
}
|
97 |
+
$counter += $this->autoClearXmlFeedsCache('blog-comments');
|
98 |
+
$counter += $this->autoClearXmlFeedsCache('post-comments', $comment->comment_post_ID);
|
99 |
+
$counter += $this->autoClearPostCache($comment->comment_post_ID);
|
100 |
+
|
101 |
+
return $counter;
|
102 |
+
}
|
103 |
+
}
|
src/includes/traits/Plugin/WcpFeedUtils.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpFeedUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files related to XML feeds.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param string $type Type of feed(s) to auto-clear.
|
14 |
+
* @param int $post_id A Post ID (when applicable).
|
15 |
+
*
|
16 |
+
* @throws \Exception If a clear failure occurs.
|
17 |
+
*
|
18 |
+
* @return int Total files cleared by this routine (if any).
|
19 |
+
*
|
20 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
21 |
+
* attached to any hooks. However, it is called upon by other routines attached to hooks.
|
22 |
+
*/
|
23 |
+
public function autoClearXmlFeedsCache($type, $post_id = 0)
|
24 |
+
{
|
25 |
+
$counter = 0; // Initialize.
|
26 |
+
|
27 |
+
if (!($type = (string) $type)) {
|
28 |
+
return $counter; // Nothing we can do.
|
29 |
+
}
|
30 |
+
$post_id = (integer) $post_id; // Force integer.
|
31 |
+
|
32 |
+
if (!is_null($done = &$this->cacheKey('autoClearXmlFeedsCache', [$type, $post_id]))) {
|
33 |
+
return $counter; // Already did this.
|
34 |
+
}
|
35 |
+
$done = true; // Flag as having been done.
|
36 |
+
|
37 |
+
if (!$this->options['enable']) {
|
38 |
+
return $counter; // Nothing to do.
|
39 |
+
}
|
40 |
+
if (!$this->options['feeds_enable']) {
|
41 |
+
return $counter; // Nothing to do.
|
42 |
+
}
|
43 |
+
if (!$this->options['cache_clear_xml_feeds_enable']) {
|
44 |
+
return $counter; // Nothing to do.
|
45 |
+
}
|
46 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
47 |
+
return $counter; // Nothing to do.
|
48 |
+
}
|
49 |
+
$utils = new Classes\FeedUtils(); // Feed utilities.
|
50 |
+
$variations = $variation_regex_frags = []; // Initialize.
|
51 |
+
|
52 |
+
switch ($type) { // Handle clearing based on the `$type`.
|
53 |
+
|
54 |
+
case 'blog': // The blog feed; i.e. `/feed/` on most WP installs.
|
55 |
+
$variations = array_merge($variations, $utils->feedLinkVariations());
|
56 |
+
break; // Break switch handler.
|
57 |
+
|
58 |
+
case 'blog-comments': // The blog comments feed; i.e. `/comments/feed/` on most WP installs.
|
59 |
+
$variations = array_merge($variations, $utils->feedLinkVariations('comments_'));
|
60 |
+
break; // Break switch handler.
|
61 |
+
|
62 |
+
case 'post-comments': // Feeds related to comments that a post has.
|
63 |
+
if (!$post_id) {
|
64 |
+
break; // Break switch handler.
|
65 |
+
}
|
66 |
+
if (!($post = get_post($post_id))) {
|
67 |
+
break; // Break switch handler.
|
68 |
+
}
|
69 |
+
$variations = array_merge($variations, $utils->postCommentsFeedLinkVariations($post));
|
70 |
+
break; // Break switch handler.
|
71 |
+
|
72 |
+
case 'post-authors': // Feeds related to authors that a post has.
|
73 |
+
if (!$post_id) {
|
74 |
+
break; // Break switch handler.
|
75 |
+
}
|
76 |
+
if (!($post = get_post($post_id))) {
|
77 |
+
break; // Break switch handler.
|
78 |
+
}
|
79 |
+
$variations = array_merge($variations, $utils->postAuthorFeedLinkVariations($post));
|
80 |
+
break; // Break switch handler.
|
81 |
+
|
82 |
+
case 'post-terms': // Feeds related to terms that a post has.
|
83 |
+
if (!$post_id) {
|
84 |
+
break; // Break switch handler.
|
85 |
+
}
|
86 |
+
if (!($post = get_post($post_id))) {
|
87 |
+
break; // Break switch handler.
|
88 |
+
}
|
89 |
+
$variations = array_merge($variations, $utils->postTermFeedLinkVariations($post, true));
|
90 |
+
break; // Break switch handler.
|
91 |
+
|
92 |
+
case 'custom-post-type': // Feeds related to a custom post type archive view.
|
93 |
+
if (!$post_id) {
|
94 |
+
break; // Break switch handler.
|
95 |
+
}
|
96 |
+
if (!($post = get_post($post_id))) {
|
97 |
+
break; // Break switch handler.
|
98 |
+
}
|
99 |
+
$variations = array_merge($variations, $utils->postTypeArchiveFeedLinkVariations($post));
|
100 |
+
break; // Break switch handler.
|
101 |
+
|
102 |
+
// @TODO Possibly consider search-related feeds in the future.
|
103 |
+
// See: <http://codex.wordpress.org/WordPress_Feeds#Categories_and_Tags>
|
104 |
+
}
|
105 |
+
if (!($variation_regex_frags = $utils->convertVariationsToHostCachePathRegexFrags($variations))) {
|
106 |
+
return $counter; // Nothing to do here.
|
107 |
+
}
|
108 |
+
$in_sets_of = $this->applyWpFilters(GLOBAL_NS.'_autoClearXmlFeedsCache_in_sets_of', 10, get_defined_vars());
|
109 |
+
for ($_i = 0; $_i < count($variation_regex_frags); $_i = $_i + $in_sets_of) {
|
110 |
+
$_variation_regex_frags = array_slice($variation_regex_frags, $_i, $in_sets_of);
|
111 |
+
$_regex = '/^\/(?:'.implode('|', $_variation_regex_frags).')\./i';
|
112 |
+
$counter += $this->clearFilesFromHostCacheDir($_regex);
|
113 |
+
}
|
114 |
+
unset($_i, $_variation_regex_frags, $_regex); // Housekeeping.
|
115 |
+
|
116 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
117 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache, for XML feeds of type: <code>%2$s</code>; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($counter)), esc_html($type)), ['combinable' => true]);
|
118 |
+
}
|
119 |
+
return $counter;
|
120 |
+
}
|
121 |
+
}
|
src/includes/traits/Plugin/WcpHomeBlogUtils.php
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpHomeBlogUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files for the home page.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @throws \Exception If a clear failure occurs.
|
14 |
+
*
|
15 |
+
* @return int Total files cleared by this routine (if any).
|
16 |
+
*
|
17 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
18 |
+
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
19 |
+
*/
|
20 |
+
public function autoClearHomePageCache()
|
21 |
+
{
|
22 |
+
$counter = 0; // Initialize.
|
23 |
+
|
24 |
+
if (!is_null($done = &$this->cacheKey('autoClearHomePageCache'))) {
|
25 |
+
return $counter; // Already did this.
|
26 |
+
}
|
27 |
+
$done = true; // Flag as having been done.
|
28 |
+
|
29 |
+
if (!$this->options['enable']) {
|
30 |
+
return $counter; // Nothing to do.
|
31 |
+
}
|
32 |
+
if (!$this->options['cache_clear_home_page_enable']) {
|
33 |
+
return $counter; // Nothing to do.
|
34 |
+
}
|
35 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
36 |
+
return $counter; // Nothing to do.
|
37 |
+
}
|
38 |
+
$regex = $this->buildHostCachePathRegex(home_url('/'));
|
39 |
+
$counter += $this->clearFilesFromHostCacheDir($regex);
|
40 |
+
|
41 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
42 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache for the designated "Home Page"; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($counter))), ['combinable' => true]);
|
43 |
+
}
|
44 |
+
$counter += $this->autoClearXmlFeedsCache('blog');
|
45 |
+
|
46 |
+
return $counter;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Automatically clears cache files for the posts page.
|
51 |
+
*
|
52 |
+
* @since 150422 Rewrite.
|
53 |
+
*
|
54 |
+
* @throws \Exception If a clear failure occurs.
|
55 |
+
*
|
56 |
+
* @return int Total files cleared by this routine (if any).
|
57 |
+
*
|
58 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
59 |
+
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
60 |
+
*/
|
61 |
+
public function autoClearPostsPageCache()
|
62 |
+
{
|
63 |
+
$counter = 0; // Initialize.
|
64 |
+
|
65 |
+
if (!is_null($done = &$this->cacheKey('autoClearPostsPageCache'))) {
|
66 |
+
return $counter; // Already did this.
|
67 |
+
}
|
68 |
+
$done = true; // Flag as having been done.
|
69 |
+
|
70 |
+
if (!$this->options['enable']) {
|
71 |
+
return $counter; // Nothing to do.
|
72 |
+
}
|
73 |
+
if (!$this->options['cache_clear_posts_page_enable']) {
|
74 |
+
return $counter; // Nothing to do.
|
75 |
+
}
|
76 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
77 |
+
return $counter; // Nothing to do.
|
78 |
+
}
|
79 |
+
$show_on_front = get_option('show_on_front');
|
80 |
+
$page_for_posts = get_option('page_for_posts');
|
81 |
+
|
82 |
+
if (!in_array($show_on_front, ['posts', 'page'], true)) {
|
83 |
+
return $counter; // Nothing we can do in this case.
|
84 |
+
}
|
85 |
+
if ($show_on_front === 'page' && !$page_for_posts) {
|
86 |
+
return $counter; // Nothing we can do.
|
87 |
+
}
|
88 |
+
if ($show_on_front === 'posts') {
|
89 |
+
$posts_page = home_url('/');
|
90 |
+
} elseif ($show_on_front === 'page') {
|
91 |
+
$posts_page = get_permalink($page_for_posts);
|
92 |
+
}
|
93 |
+
if (empty($posts_page)) {
|
94 |
+
return $counter; // Nothing we can do.
|
95 |
+
}
|
96 |
+
$regex = $this->buildHostCachePathRegex($posts_page);
|
97 |
+
$counter += $this->clearFilesFromHostCacheDir($regex);
|
98 |
+
|
99 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
100 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache for the designated "Posts Page"; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($counter))), ['combinable' => true]);
|
101 |
+
}
|
102 |
+
$counter += $this->autoClearXmlFeedsCache('blog');
|
103 |
+
|
104 |
+
return $counter;
|
105 |
+
}
|
106 |
+
}
|
src/includes/traits/Plugin/WcpJetpackUtils.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpJetpackUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears all cache files for current blog when JetPack Custom CSS is saved.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @attaches-to `safecss_save_pre` hook.
|
14 |
+
*
|
15 |
+
* @param array $args Args passed in by hook.
|
16 |
+
*/
|
17 |
+
public function autoClearCacheOnJetpackCustomCss($args)
|
18 |
+
{
|
19 |
+
$counter = 0; // Initialize.
|
20 |
+
|
21 |
+
if (!is_null($done = &$this->cacheKey('autoClearCacheOnJetpackCustomCss', $args))) {
|
22 |
+
return $counter; // Already did this.
|
23 |
+
}
|
24 |
+
$done = true; // Flag as having been done.
|
25 |
+
|
26 |
+
if (empty($args['is_preview']) && class_exists('\\Jetpack')) {
|
27 |
+
$counter += $this->autoClearCache();
|
28 |
+
}
|
29 |
+
}
|
30 |
+
}
|
src/includes/traits/Plugin/WcpOpcacheUtils.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpOpcacheUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Wipe (i.e., reset) OPCache.
|
10 |
+
*
|
11 |
+
* @since 151002 Adding OPCache support.
|
12 |
+
*
|
13 |
+
* @param bool $manually True if wiping is done manually.
|
14 |
+
* @param bool $maybe Defaults to a true value.
|
15 |
+
* @param array $files Optional; wipe only specific files?
|
16 |
+
*
|
17 |
+
* @return int Total keys wiped.
|
18 |
+
*/
|
19 |
+
public function wipeOpcache($manually = false, $maybe = true, $files = [])
|
20 |
+
{
|
21 |
+
$counter = 0; // Initialize counter.
|
22 |
+
|
23 |
+
if ($maybe && !$this->options['cache_clear_opcache_enable']) {
|
24 |
+
return $counter; // Not enabled at this time.
|
25 |
+
}
|
26 |
+
if (!$this->functionIsPossible('opcache_reset')) {
|
27 |
+
return $counter; // Not possible.
|
28 |
+
}
|
29 |
+
if (!($status = $this->sysOpcacheStatus())) {
|
30 |
+
return $counter; // Not possible.
|
31 |
+
}
|
32 |
+
if (empty($status->opcache_enabled)) {
|
33 |
+
return $counter; // Not necessary.
|
34 |
+
}
|
35 |
+
if (empty($status->opcache_statistics->num_cached_keys)) {
|
36 |
+
return $counter; // Not possible.
|
37 |
+
}
|
38 |
+
if ($files) { // Specific files?
|
39 |
+
foreach ($files as $_file) {
|
40 |
+
$counter += (int) opcache_invalidate($_file, true);
|
41 |
+
} // unset($_file); // Housekeeping.
|
42 |
+
} elseif (opcache_reset()) { // True if a reset occurs.
|
43 |
+
$counter += $status->opcache_statistics->num_cached_keys;
|
44 |
+
}
|
45 |
+
return $counter;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Clear (i.e., reset) OPCache.
|
50 |
+
*
|
51 |
+
* @since 151002 Adding OPCache support.
|
52 |
+
*
|
53 |
+
* @param bool $manually True if clearing is done manually.
|
54 |
+
* @param bool $maybe Defaults to a true value.
|
55 |
+
*
|
56 |
+
* @return int Total keys cleared.
|
57 |
+
*/
|
58 |
+
public function clearOpcache($manually = false, $maybe = true)
|
59 |
+
{
|
60 |
+
if (!is_multisite() || is_main_site() || current_user_can($this->network_cap)) {
|
61 |
+
return $this->wipeOpcache($manually, $maybe);
|
62 |
+
}
|
63 |
+
return 0; // Not applicable.
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Clear AC class file from Opcache (by force).
|
68 |
+
*
|
69 |
+
* @since 151215 Adding OPCache support.
|
70 |
+
*
|
71 |
+
* @return int Total keys cleared.
|
72 |
+
*/
|
73 |
+
public function clearAcDropinFromOpcacheByForce()
|
74 |
+
{
|
75 |
+
return $this->wipeOpcache(false, false, [WP_CONTENT_DIR.'/advanced-cache.php']);
|
76 |
+
}
|
77 |
+
}
|
src/includes/traits/Plugin/WcpPluginUtils.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpPluginUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically wipes/clears on plugin activation/deactivation.
|
10 |
+
*
|
11 |
+
* @since 151220 Adding auto-wipe|clear on plugin activations/deactivations.
|
12 |
+
*
|
13 |
+
* @attaches-to `activated_plugin` hook.
|
14 |
+
* @attaches-to `deactivated_plugin` hook.
|
15 |
+
*
|
16 |
+
* @param string $plugin Plugin basename.
|
17 |
+
* @param bool True if activating|deactivating network-wide. Defaults to boolean `FALSE` in case parameter is not passed to hook.
|
18 |
+
*
|
19 |
+
* @return int Total files wiped|cleared by this routine (if any).
|
20 |
+
*/
|
21 |
+
public function autoClearOnPluginActivationDeactivation($plugin, $network_wide = false)
|
22 |
+
{
|
23 |
+
if (!$this->applyWpFilters(GLOBAL_NS.'_auto_clear_on_plugin_activation_deactivation', true)) {
|
24 |
+
return 0; // Nothing to do here.
|
25 |
+
}
|
26 |
+
return $this->{($network_wide ? 'autoWipeCache' : 'autoClearCache')}();
|
27 |
+
}
|
28 |
+
}
|
src/includes/traits/Plugin/WcpPostTypeUtils.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpPostTypeUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files for a custom post type archive view.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param int $post_id A WordPress post ID.
|
14 |
+
*
|
15 |
+
* @throws \Exception If a clear failure occurs.
|
16 |
+
*
|
17 |
+
* @return int Total files cleared by this routine (if any).
|
18 |
+
*
|
19 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
20 |
+
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
21 |
+
*/
|
22 |
+
public function autoClearCustomPostTypeArchiveCache($post_id)
|
23 |
+
{
|
24 |
+
$counter = 0; // Initialize.
|
25 |
+
|
26 |
+
if (!($post_id = (integer) $post_id)) {
|
27 |
+
return $counter; // Nothing to do.
|
28 |
+
}
|
29 |
+
if (!is_null($done = &$this->cacheKey('autoClearCustomPostTypeArchiveCache', $post_id))) {
|
30 |
+
return $counter; // Already did this.
|
31 |
+
}
|
32 |
+
$done = true; // Flag as having been done.
|
33 |
+
|
34 |
+
if (!$this->options['enable']) {
|
35 |
+
return $counter; // Nothing to do.
|
36 |
+
}
|
37 |
+
if (!$this->options['cache_clear_custom_post_type_enable']) {
|
38 |
+
return $counter; // Nothing to do.
|
39 |
+
}
|
40 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
41 |
+
return $counter; // Nothing to do.
|
42 |
+
}
|
43 |
+
if (!($post_type = get_post_type($post_id))) {
|
44 |
+
return $counter; // Nothing to do.
|
45 |
+
}
|
46 |
+
if (!($all_custom_post_types = get_post_types(['_builtin' => false]))) {
|
47 |
+
return $counter; // No custom post types.
|
48 |
+
}
|
49 |
+
if (!in_array($post_type, array_keys($all_custom_post_types), true)) {
|
50 |
+
return $counter; // This is NOT a custom post type.
|
51 |
+
}
|
52 |
+
if (!($custom_post_type = get_post_type_object($post_type))) {
|
53 |
+
return $counter; // Unable to retrieve post type.
|
54 |
+
}
|
55 |
+
if (empty($custom_post_type->labels->name) || !($custom_post_type_name = $custom_post_type->labels->name)) {
|
56 |
+
$custom_post_type_name = __('Untitled', 'comet-cache');
|
57 |
+
}
|
58 |
+
if (!($custom_post_type_archive_link = get_post_type_archive_link($post_type))) {
|
59 |
+
return $counter; // Nothing to do; no link to work from in this case.
|
60 |
+
}
|
61 |
+
$regex = $this->buildHostCachePathRegex($custom_post_type_archive_link);
|
62 |
+
$counter += $this->clearFilesFromHostCacheDir($regex);
|
63 |
+
|
64 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
65 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache for Custom Post Type: <code>%2$s</code>; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($counter)), esc_html($custom_post_type_name)), ['combinable' => true]);
|
66 |
+
}
|
67 |
+
$counter += $this->autoClearXmlFeedsCache('custom-post-type', $post_id);
|
68 |
+
|
69 |
+
return $counter;
|
70 |
+
}
|
71 |
+
}
|
src/includes/traits/Plugin/WcpPostUtils.php
ADDED
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpPostUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files for a particular post.
|
10 |
+
*
|
11 |
+
* @attaches-to `save_post` hook.
|
12 |
+
* @attaches-to `delete_post` hook.
|
13 |
+
* @attaches-to `clean_post_cache` hook.
|
14 |
+
*
|
15 |
+
* @since 150422 Rewrite.
|
16 |
+
*
|
17 |
+
* @param int $post_id A WordPress post ID.
|
18 |
+
* @param bool $force Defaults to a `FALSE` value.
|
19 |
+
* Pass as TRUE if clearing should be done for `draft`, `pending`,
|
20 |
+
* `future`, or `trash` post statuses.
|
21 |
+
*
|
22 |
+
* @throws \Exception If a clear failure occurs.
|
23 |
+
*
|
24 |
+
* @return int Total files cleared by this routine (if any).
|
25 |
+
*
|
26 |
+
* @note This is also called upon by other routines which listen for
|
27 |
+
* events that are indirectly associated with a post ID.
|
28 |
+
*/
|
29 |
+
public function autoClearPostCache($post_id, $force = false)
|
30 |
+
{
|
31 |
+
$counter = 0; // Initialize.
|
32 |
+
|
33 |
+
if (!is_null($allow = &$this->cacheKey('autoClearPostCache_allow'))) {
|
34 |
+
if ($allow === false) { // Disallow?
|
35 |
+
$allow = true; // Reset flag.
|
36 |
+
return $counter;
|
37 |
+
}
|
38 |
+
}
|
39 |
+
if (!($post_id = (integer) $post_id)) {
|
40 |
+
return $counter; // Nothing to do.
|
41 |
+
}
|
42 |
+
if (!is_null($done = &$this->cacheKey('autoClearPostCache', [$post_id, $force]))) {
|
43 |
+
return $counter; // Already did this.
|
44 |
+
}
|
45 |
+
$done = true; // Flag as having been done.
|
46 |
+
|
47 |
+
if (!$this->options['enable']) {
|
48 |
+
return $counter; // Nothing to do.
|
49 |
+
}
|
50 |
+
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
51 |
+
return $counter; // Nothing to do.
|
52 |
+
}
|
53 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
54 |
+
return $counter; // Nothing to do.
|
55 |
+
}
|
56 |
+
if (!($post_type = get_post_type($post_id))) {
|
57 |
+
return $counter; // Nothing to do.
|
58 |
+
}
|
59 |
+
$post_statuses = $this->postStatuses();
|
60 |
+
$unpublished_post_statuses = array_diff($post_statuses, ['publish']);
|
61 |
+
$is_bbpress_post_type = in_array($post_type, $this->bbPressPostTypes(), true);
|
62 |
+
|
63 |
+
if (!empty($this->pre_post_update_post_permalink[$post_id])) {
|
64 |
+
$permalink = $this->pre_post_update_post_permalink[$post_id];
|
65 |
+
$this->pre_post_update_post_permalink[$post_id] = ''; // Reset; only used for post status transitions.
|
66 |
+
} elseif (!($permalink = get_permalink($post_id))) {
|
67 |
+
return $counter; // Nothing we can do.
|
68 |
+
}
|
69 |
+
if (!($post_status = get_post_status($post_id))) {
|
70 |
+
return $counter; // Nothing to do.
|
71 |
+
}
|
72 |
+
if ($post_status === 'draft' && isset($GLOBALS['pagenow'], $_POST['publish'])
|
73 |
+
&& is_admin() && $GLOBALS['pagenow'] === 'post.php' && current_user_can('publish_posts')
|
74 |
+
&& strpos(wp_get_referer(), '/post-new.php') !== false
|
75 |
+
) {
|
76 |
+
$post_status = 'publish'; // A new post being published now.
|
77 |
+
}
|
78 |
+
if (in_array($post_status, ['inherit', 'auto-draft'], true)) {
|
79 |
+
return $counter; // Nothing to do. Note: `inherit` = revision.
|
80 |
+
}
|
81 |
+
if (in_array($post_status, ['draft', 'pending', 'future', 'trash'], true) && !$force) {
|
82 |
+
return $counter; // Nothing to do; i.e., NOT forcing in this case.
|
83 |
+
}
|
84 |
+
if (($post_type_obj = get_post_type_object($post_type)) && !empty($post_type_obj->labels->singular_name)) {
|
85 |
+
$post_type_singular_name = $post_type_obj->labels->singular_name; // Singular name for the post type.
|
86 |
+
} else {
|
87 |
+
$post_type_singular_name = __('Post', 'comet-cache'); // Default value.
|
88 |
+
}
|
89 |
+
$regex = $this->buildHostCachePathRegex($permalink);
|
90 |
+
$counter += $this->clearFilesFromHostCacheDir($regex);
|
91 |
+
|
92 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
93 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache for %2$s ID: <code>%3$s</code>; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($counter)), esc_html($post_type_singular_name), esc_html($post_id)), ['combinable' => true]);
|
94 |
+
}
|
95 |
+
$counter += $this->autoClearXmlFeedsCache('blog');
|
96 |
+
$counter += $this->autoClearXmlFeedsCache('post-terms', $post_id);
|
97 |
+
$counter += $this->autoClearXmlFeedsCache('post-authors', $post_id);
|
98 |
+
|
99 |
+
$counter += $this->autoClearXmlSitemapsCache();
|
100 |
+
$counter += $this->autoClearHomePageCache();
|
101 |
+
$counter += $this->autoClearPostsPageCache();
|
102 |
+
$counter += $this->autoClearPostTermsCache($post_id, $force);
|
103 |
+
$counter += $this->autoClearCustomPostTypeArchiveCache($post_id);
|
104 |
+
|
105 |
+
|
106 |
+
if ($post_type !== 'page' && ($parent_post_id = wp_get_post_parent_id($post_id))) {
|
107 |
+
// Recursion: i.e., nested post types like bbPress forums/topic/replies.
|
108 |
+
$counter += $this->autoClearPostCache($parent_post_id, $force);
|
109 |
+
}
|
110 |
+
return $counter;
|
111 |
+
}
|
112 |
+
|
113 |
+
// @codingStandardsIgnoreStart
|
114 |
+
/*
|
115 |
+
* Back compat. alias for autoClearPostCache()
|
116 |
+
*/
|
117 |
+
public function auto_clear_post_cache()
|
118 |
+
{ // @codingStandardsIgnoreEnd
|
119 |
+
return call_user_func_array([$this, 'autoClearPostCache'], func_get_args());
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Handles post status transitioning.
|
124 |
+
*
|
125 |
+
* @attaches-to `pre_post_update` hook.
|
126 |
+
*
|
127 |
+
* @since 150422 Rewrite.
|
128 |
+
*
|
129 |
+
* @param int $post_id Post ID.
|
130 |
+
* @param array $data Array of unslashed post data.
|
131 |
+
*
|
132 |
+
* @throws \Exception If a clear failure occurs.
|
133 |
+
*
|
134 |
+
* @return int Total files cleared by this routine (if any).
|
135 |
+
*
|
136 |
+
* @note This is also called upon by other routines which listen for
|
137 |
+
* events that are indirectly associated with a post ID.
|
138 |
+
*/
|
139 |
+
public function autoClearPostCacheTransition($post_id, $data)
|
140 |
+
{
|
141 |
+
$counter = 0; // Initialize.
|
142 |
+
|
143 |
+
$old_status = (string) get_post_status($post_id);
|
144 |
+
$new_status = (string) $data['post_status'];
|
145 |
+
/*
|
146 |
+
* When a post has a status of `pending` or `draft`, the `get_permalink()` function
|
147 |
+
* does not return a friendly permalink and therefore `autoClearPostCache()` will
|
148 |
+
* have no way of building a path to the cache file that should be cleared as part of
|
149 |
+
* this post status transition. To get around this, we temporarily store the permalink
|
150 |
+
* in $this->pre_post_update_post_permalink for `autoClearPostCache()` to use.
|
151 |
+
*
|
152 |
+
* See also: <https://github.com/websharks/zencache/issues/441>
|
153 |
+
*/
|
154 |
+
if (in_array($new_status, ['pending', 'draft'], true)) {
|
155 |
+
$this->pre_post_update_post_permalink[$post_id] = get_permalink($post_id);
|
156 |
+
}
|
157 |
+
// Begin post status transition sub-routine now.
|
158 |
+
|
159 |
+
if (!is_null($done = &$this->cacheKey('autoClearPostCacheTransition', [$old_status, $new_status, $post_id]))) {
|
160 |
+
return $counter; // Already did this.
|
161 |
+
}
|
162 |
+
$done = true; // Flag as having been done.
|
163 |
+
|
164 |
+
if (!$this->options['enable']) {
|
165 |
+
return $counter; // Nothing to do.
|
166 |
+
}
|
167 |
+
if ($new_status === $old_status) {
|
168 |
+
return $counter; // Nothing to do.
|
169 |
+
}
|
170 |
+
if (!($post_type = get_post_type($post_id))) {
|
171 |
+
return $counter; // Nothing to do.
|
172 |
+
}
|
173 |
+
$post_statuses = $this->postStatuses();
|
174 |
+
$unpublished_post_statuses = array_diff($post_statuses, ['publish']);
|
175 |
+
$is_bbpress_post_type = in_array($post_type, $this->bbPressPostTypes(), true);
|
176 |
+
|
177 |
+
if ($is_bbpress_post_type) {
|
178 |
+
if (in_array($old_status, ['publish', 'private', 'closed', 'spam', 'hidden'], true)) {
|
179 |
+
if (in_array($new_status, $unpublished_post_statuses, true)) {
|
180 |
+
$counter += $this->autoClearPostCache($post_id, true);
|
181 |
+
}
|
182 |
+
}
|
183 |
+
} elseif (in_array($old_status, ['publish', 'private'], true)) {
|
184 |
+
if (in_array($new_status, $unpublished_post_statuses, true)) {
|
185 |
+
$counter += $this->autoClearPostCache($post_id, true);
|
186 |
+
}
|
187 |
+
}
|
188 |
+
return $counter;
|
189 |
+
}
|
190 |
+
}
|
src/includes/traits/Plugin/WcpSettingUtils.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpSettingUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears all cache files for current blog under various conditions;
|
10 |
+
* used to check for conditions that don't have a hook that we can attach to.
|
11 |
+
*
|
12 |
+
* @since 150422 Rewrite.
|
13 |
+
*
|
14 |
+
* @attaches-to `admin_init` hook.
|
15 |
+
*/
|
16 |
+
public function autoClearCacheOnSettingChanges()
|
17 |
+
{
|
18 |
+
$counter = 0; // Initialize.
|
19 |
+
$pagenow = !empty($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : '';
|
20 |
+
$settings_updated = !empty($_REQUEST['settings-updated']);
|
21 |
+
|
22 |
+
if (!is_null($done = &$this->cacheKey('autoClearCacheOnSettingChanges', [$pagenow, $settings_updated]))) {
|
23 |
+
return $counter; // Already did this.
|
24 |
+
}
|
25 |
+
$done = true; // Flag as having been done.
|
26 |
+
|
27 |
+
if ($pagenow === 'options-general.php' && $settings_updated) {
|
28 |
+
$counter += $this->autoClearCache();
|
29 |
+
} elseif ($pagenow === 'options-reading.php' && $settings_updated) {
|
30 |
+
$counter += $this->autoClearCache();
|
31 |
+
} elseif ($pagenow === 'options-discussion.php' && $settings_updated) {
|
32 |
+
$counter += $this->autoClearCache();
|
33 |
+
} elseif ($pagenow === 'options-permalink.php' && $settings_updated) {
|
34 |
+
$counter += $this->autoClearCache();
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
src/includes/traits/Plugin/WcpSitemapUtils.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpSitemapUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files related to XML sitemaps.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @throws \Exception If a clear failure occurs.
|
14 |
+
*
|
15 |
+
* @return int Total files cleared by this routine (if any).
|
16 |
+
*
|
17 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently
|
18 |
+
* attached to any hooks. However, it is called upon by {@link autoClearPostCache()}.
|
19 |
+
*/
|
20 |
+
public function autoClearXmlSitemapsCache()
|
21 |
+
{
|
22 |
+
$counter = 0; // Initialize.
|
23 |
+
|
24 |
+
if (!is_null($done = &$this->cacheKey('autoClearXmlSitemapsCache'))) {
|
25 |
+
return $counter; // Already did this.
|
26 |
+
}
|
27 |
+
$done = true; // Flag as having been done.
|
28 |
+
|
29 |
+
if (!$this->options['enable']) {
|
30 |
+
return $counter; // Nothing to do.
|
31 |
+
}
|
32 |
+
if (!$this->options['cache_clear_xml_sitemaps_enable']) {
|
33 |
+
return $counter; // Nothing to do.
|
34 |
+
}
|
35 |
+
if (!$this->options['cache_clear_xml_sitemap_patterns']) {
|
36 |
+
return $counter; // Nothing to do.
|
37 |
+
}
|
38 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
39 |
+
return $counter; // Nothing to do.
|
40 |
+
}
|
41 |
+
if (!($regex_frags = $this->buildHostCachePathRegexFragsFromWcUris($this->options['cache_clear_xml_sitemap_patterns'], ''))) {
|
42 |
+
return $counter; // There are no patterns to look for.
|
43 |
+
}
|
44 |
+
$regex = $this->buildHostCachePathRegex('', '\/'.$regex_frags.'\.');
|
45 |
+
$counter += $this->clearFilesFromHostCacheDir($regex);
|
46 |
+
|
47 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
48 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache for XML sitemaps; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($counter))), ['combinable' => true]);
|
49 |
+
}
|
50 |
+
return $counter;
|
51 |
+
}
|
52 |
+
}
|
src/includes/traits/Plugin/WcpTermUtils.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpTermUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache files for terms associated with a post.
|
10 |
+
*
|
11 |
+
* @attaches-to `added_term_relationship` hook.
|
12 |
+
* @attaches-to `delete_term_relationships` hook.
|
13 |
+
*
|
14 |
+
* @since 150422 Rewrite.
|
15 |
+
*
|
16 |
+
* @param int $post_id A WordPress post ID.
|
17 |
+
* @param bool $force Defaults to a `FALSE` value.
|
18 |
+
* Pass as TRUE if clearing should be done for `draft`, `pending`,
|
19 |
+
* or `future` post statuses.
|
20 |
+
*
|
21 |
+
* @throws \Exception If a clear failure occurs.
|
22 |
+
*
|
23 |
+
* @return int Total files cleared by this routine (if any).
|
24 |
+
*
|
25 |
+
* @note In addition to the hooks this is attached to, it is also
|
26 |
+
* called upon by {@link autoClearPostCache()}.
|
27 |
+
*/
|
28 |
+
public function autoClearPostTermsCache($post_id, $force = false)
|
29 |
+
{
|
30 |
+
$counter = 0; // Initialize.
|
31 |
+
$enqueued_notices = 0; // Initialize.
|
32 |
+
|
33 |
+
if (!($post_id = (integer) $post_id)) {
|
34 |
+
return $counter; // Nothing to do.
|
35 |
+
}
|
36 |
+
if (!is_null($done = &$this->cacheKey('autoClearPostTermsCache', [$post_id, $force]))) {
|
37 |
+
return $counter; // Already did this.
|
38 |
+
}
|
39 |
+
$done = true; // Flag as having been done.
|
40 |
+
|
41 |
+
if (!$this->options['enable']) {
|
42 |
+
return $counter; // Nothing to do.
|
43 |
+
}
|
44 |
+
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
45 |
+
return $counter; // Nothing to do.
|
46 |
+
}
|
47 |
+
if (!$this->options['cache_clear_term_category_enable'] && !$this->options['cache_clear_term_post_tag_enable'] && !$this->options['cache_clear_term_other_enable']) {
|
48 |
+
return $counter; // Nothing to do.
|
49 |
+
}
|
50 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
51 |
+
return $counter; // Nothing to do.
|
52 |
+
}
|
53 |
+
$post_status = get_post_status($post_id); // Cache this.
|
54 |
+
|
55 |
+
if ($post_status === 'draft' && isset($GLOBALS['pagenow'], $_POST['publish'])
|
56 |
+
&& is_admin() && $GLOBALS['pagenow'] === 'post.php' && current_user_can('publish_posts')
|
57 |
+
&& strpos(wp_get_referer(), '/post-new.php') !== false
|
58 |
+
) {
|
59 |
+
$post_status = 'publish'; // A new post being published now.
|
60 |
+
}
|
61 |
+
if (in_array($post_status, ['inherit', 'auto-draft'], true)) {
|
62 |
+
return $counter; // Nothing to do. Note: `inherit` = revision.
|
63 |
+
}
|
64 |
+
if (in_array($post_status, ['draft', 'pending', 'future'], true) && !$force) {
|
65 |
+
return $counter; // Nothing to do; i.e., NOT forcing in this case.
|
66 |
+
}
|
67 |
+
/*
|
68 |
+
* Build an array of available taxonomies for this post (as taxonomy objects).
|
69 |
+
*/
|
70 |
+
$taxonomies = get_object_taxonomies(get_post($post_id), 'objects');
|
71 |
+
|
72 |
+
if (!is_array($taxonomies)) {
|
73 |
+
return $counter; // Nothing to do.
|
74 |
+
}
|
75 |
+
/*
|
76 |
+
* Build an array of terms associated with this post for each taxonomy.
|
77 |
+
* Also save taxonomy label information for Dashboard messaging later.
|
78 |
+
*/
|
79 |
+
$terms = [];
|
80 |
+
$taxonomy_labels = [];
|
81 |
+
|
82 |
+
foreach ($taxonomies as $_taxonomy) {
|
83 |
+
if (// Check if this is a taxonomy/term that we should clear.
|
84 |
+
($_taxonomy->name === 'category' && !$this->options['cache_clear_term_category_enable'])
|
85 |
+
|| ($_taxonomy->name === 'post_tag' && !$this->options['cache_clear_term_post_tag_enable'])
|
86 |
+
|| ($_taxonomy->name !== 'category' && $_taxonomy->name !== 'post_tag' && !$this->options['cache_clear_term_other_enable'])
|
87 |
+
) {
|
88 |
+
continue; // Continue; nothing to do for this taxonomy.
|
89 |
+
}
|
90 |
+
if (is_array($_terms = wp_get_post_terms($post_id, $_taxonomy->name))) {
|
91 |
+
$terms = array_merge($terms, $_terms);
|
92 |
+
if (empty($_taxonomy->labels->singular_name) || $_taxonomy->labels->singular_name === '') {
|
93 |
+
$taxonomy_labels[$_taxonomy->name] = $_taxonomy->name;
|
94 |
+
} else {
|
95 |
+
$taxonomy_labels[$_taxonomy->name] = $_taxonomy->labels->singular_name;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
unset($_taxonomy, $_terms);
|
100 |
+
|
101 |
+
if (empty($terms)) {
|
102 |
+
return $counter; // Nothing to do.
|
103 |
+
}
|
104 |
+
/*
|
105 |
+
* Build an array of terms with term names,
|
106 |
+
* permalinks, and associated taxonomy labels.
|
107 |
+
*/
|
108 |
+
$terms_to_clear = [];
|
109 |
+
$_i = 0;
|
110 |
+
|
111 |
+
foreach ($terms as $_term) {
|
112 |
+
if (($_link = get_term_link($_term))) {
|
113 |
+
$terms_to_clear[$_i]['permalink'] = $_link;
|
114 |
+
$terms_to_clear[$_i]['term_name'] = $_term->name;
|
115 |
+
if (!empty($taxonomy_labels[$_term->taxonomy])) {
|
116 |
+
$terms_to_clear[$_i]['taxonomy_label'] = $taxonomy_labels[$_term->taxonomy];
|
117 |
+
} else {
|
118 |
+
$terms_to_clear[$_i]['taxonomy_label'] = $_term->taxonomy;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
++$_i; // Array index counter.
|
122 |
+
}
|
123 |
+
unset($_term, $_link, $_i);
|
124 |
+
|
125 |
+
if (empty($terms_to_clear)) {
|
126 |
+
return $counter; // Nothing to do.
|
127 |
+
}
|
128 |
+
foreach ($terms_to_clear as $_term) {
|
129 |
+
$_term_regex = $this->buildHostCachePathRegex($_term['permalink']);
|
130 |
+
$_term_counter = $this->clearFilesFromHostCacheDir($_term_regex);
|
131 |
+
$counter += $_term_counter; // Add to overall counter.
|
132 |
+
|
133 |
+
if ($_term_counter && $enqueued_notices < 100 && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
134 |
+
$this->enqueueNotice(sprintf(__('Found %1$s in the cache for %2$s: <code>%3$s</code>; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($_term_counter)), esc_html($_term['taxonomy_label']), esc_html($_term['term_name'])), ['combinable' => true]);
|
135 |
+
++$enqueued_notices; // Increment enqueued notices counter.
|
136 |
+
}
|
137 |
+
}
|
138 |
+
unset($_term, $_term_regex, $_term_counter); // Housekeeping.
|
139 |
+
|
140 |
+
$counter += $this->autoClearXmlFeedsCache('post-terms', $post_id);
|
141 |
+
|
142 |
+
return $counter;
|
143 |
+
}
|
144 |
+
}
|
src/includes/traits/Plugin/WcpUpdaterUtils.php
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpUpdaterUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears all cache files for current blog when WordPress core, or an active component, is upgraded.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @attaches-to `upgrader_process_complete` hook.
|
14 |
+
*
|
15 |
+
* @param \WP_Upgrader $upgrader_instance An instance of \WP_Upgrader.
|
16 |
+
* Or, any class that extends \WP_Upgrader.
|
17 |
+
* @param array $data Array of bulk item update data.
|
18 |
+
*
|
19 |
+
* This array may include one or more of the following keys:
|
20 |
+
*
|
21 |
+
* - `string` `$action` Type of action. Default 'update'.
|
22 |
+
* - `string` `$type` Type of update process; e.g. 'plugin', 'theme', 'core'.
|
23 |
+
* - `boolean` `$bulk` Whether the update process is a bulk update. Default true.
|
24 |
+
* - `array` `$packages` Array of plugin, theme, or core packages to update.
|
25 |
+
*/
|
26 |
+
public function autoClearOnUpgraderProcessComplete(\WP_Upgrader $upgrader_instance, array $data)
|
27 |
+
{
|
28 |
+
$counter = 0; // Initialize.
|
29 |
+
|
30 |
+
switch (!empty($data['type']) ? $data['type'] : '') {
|
31 |
+
case 'plugin': // Plugin upgrade.
|
32 |
+
|
33 |
+
$multi_plugin_update = $single_plugin_update = false;
|
34 |
+
$upgrading_active_plugin = false; // Initialize.
|
35 |
+
|
36 |
+
if (!empty($data['bulk']) && !empty($data['plugins']) && is_array($data['plugins'])) {
|
37 |
+
$multi_plugin_update = true;
|
38 |
+
} elseif (!empty($data['plugin']) && is_string($data['plugin'])) {
|
39 |
+
$single_plugin_update = true;
|
40 |
+
}
|
41 |
+
if ($multi_plugin_update) {
|
42 |
+
foreach ($data['plugins'] as $_plugin) {
|
43 |
+
if ($_plugin && is_string($_plugin) && is_plugin_active($_plugin)) {
|
44 |
+
$upgrading_active_plugin = true;
|
45 |
+
break; // Got what we need here.
|
46 |
+
}
|
47 |
+
}
|
48 |
+
unset($_plugin); // Housekeeping.
|
49 |
+
} elseif ($single_plugin_update && is_plugin_active($data['plugin'])) {
|
50 |
+
$upgrading_active_plugin = true;
|
51 |
+
}
|
52 |
+
if ($upgrading_active_plugin) {
|
53 |
+
$counter += $this->autoClearCache();
|
54 |
+
}
|
55 |
+
break; // Break switch.
|
56 |
+
|
57 |
+
case 'theme': // Theme upgrade.
|
58 |
+
|
59 |
+
$current_active_theme = wp_get_theme();
|
60 |
+
$current_active_theme_parent = $current_active_theme->parent();
|
61 |
+
$multi_theme_update = $single_theme_update = false;
|
62 |
+
$upgrading_active_parent_theme = $upgrading_active_theme = false;
|
63 |
+
|
64 |
+
if (!empty($data['bulk']) && !empty($data['themes']) && is_array($data['themes'])) {
|
65 |
+
$multi_theme_update = true;
|
66 |
+
} elseif (!empty($data['theme']) && is_string($data['theme'])) {
|
67 |
+
$single_theme_update = true;
|
68 |
+
}
|
69 |
+
if ($multi_theme_update) {
|
70 |
+
foreach ($data['themes'] as $_theme) {
|
71 |
+
if (!$_theme || !is_string($_theme) || !($_theme_obj = wp_get_theme($_theme))) {
|
72 |
+
continue; // Unable to acquire theme object instance.
|
73 |
+
}
|
74 |
+
if ($current_active_theme_parent && $current_active_theme_parent->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
75 |
+
$upgrading_active_parent_theme = true;
|
76 |
+
break; // Got what we needed here.
|
77 |
+
} elseif ($current_active_theme->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
78 |
+
$upgrading_active_theme = true;
|
79 |
+
break; // Got what we needed here.
|
80 |
+
}
|
81 |
+
}
|
82 |
+
unset($_theme, $_theme_obj); // Housekeeping.
|
83 |
+
} elseif ($single_theme_update && ($_theme_obj = wp_get_theme($data['theme']))) {
|
84 |
+
if ($current_active_theme_parent && $current_active_theme_parent->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
85 |
+
$upgrading_active_parent_theme = true;
|
86 |
+
} elseif ($current_active_theme->get_stylesheet() === $_theme_obj->get_stylesheet()) {
|
87 |
+
$upgrading_active_theme = true;
|
88 |
+
}
|
89 |
+
}
|
90 |
+
unset($_theme_obj); // Housekeeping.
|
91 |
+
|
92 |
+
if ($upgrading_active_theme || $upgrading_active_parent_theme) {
|
93 |
+
$counter += $this->autoClearCache();
|
94 |
+
}
|
95 |
+
break; // Break switch.
|
96 |
+
|
97 |
+
case 'core': // Core upgrade.
|
98 |
+
default: // Or any other sort of upgrade.
|
99 |
+
$counter += $this->autoClearCache();
|
100 |
+
break; // Break switch.
|
101 |
+
}
|
102 |
+
}
|
103 |
+
}
|
src/includes/traits/Plugin/WcpUtils.php
ADDED
@@ -0,0 +1,383 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Used for temporarily storing the permalink for posts transitioning from
|
10 |
+
* `publish` or `private` post status to `pending` or `draft` post status.
|
11 |
+
*
|
12 |
+
* @since 150422 Rewrite.
|
13 |
+
*
|
14 |
+
* @type array An associative array with the Post ID as the named key containing
|
15 |
+
* the post permalink before the post has been transitioned.
|
16 |
+
*/
|
17 |
+
public $pre_post_update_post_permalink = [];
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Wipes out all cache files.
|
21 |
+
*
|
22 |
+
* @since 150422 Rewrite.
|
23 |
+
*
|
24 |
+
* @param bool $manually TRUE if wiping is done manually.
|
25 |
+
*
|
26 |
+
* @throws \Exception If a wipe failure occurs.
|
27 |
+
*
|
28 |
+
* @return int Total files wiped by this routine.
|
29 |
+
*/
|
30 |
+
public function wipeCache($manually = false)
|
31 |
+
{
|
32 |
+
$counter = 0; // Initialize.
|
33 |
+
|
34 |
+
if (!$manually && $this->disableAutoWipeCacheRoutines()) {
|
35 |
+
return $counter; // Nothing to do.
|
36 |
+
}
|
37 |
+
@set_time_limit(1800); // @TODO Display a warning.
|
38 |
+
|
39 |
+
if (is_dir($cache_dir = $this->cacheDir())) {
|
40 |
+
$regex = $this->assembleCachePathRegex('', '.+');
|
41 |
+
$counter += $this->wipeFilesFromCacheDir($regex);
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
|
48 |
+
return $counter;
|
49 |
+
}
|
50 |
+
|
51 |
+
// @codingStandardsIgnoreStart
|
52 |
+
/*
|
53 |
+
* Back compat. alias for autoClearUserCache()
|
54 |
+
*/
|
55 |
+
public function wipe_cache()
|
56 |
+
{ // @codingStandardsIgnoreEnd
|
57 |
+
return call_user_func_array([$this, 'wipeCache'], func_get_args());
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Clears cache files (current blog).
|
62 |
+
*
|
63 |
+
* @since 150422 Rewrite.
|
64 |
+
*
|
65 |
+
* @param bool $manually TRUE if clearing is done manually.
|
66 |
+
*
|
67 |
+
* @throws \Exception If a clearing failure occurs.
|
68 |
+
*
|
69 |
+
* @return int Total files cleared by this routine.
|
70 |
+
*/
|
71 |
+
public function clearCache($manually = false)
|
72 |
+
{
|
73 |
+
$counter = 0; // Initialize.
|
74 |
+
|
75 |
+
if (!$manually && $this->disableAutoClearCacheRoutines()) {
|
76 |
+
return $counter; // Nothing to do.
|
77 |
+
}
|
78 |
+
@set_time_limit(1800); // @TODO Display a warning.
|
79 |
+
|
80 |
+
if (is_dir($cache_dir = $this->cacheDir())) {
|
81 |
+
$regex = $this->buildHostCachePathRegex('', '.+');
|
82 |
+
$counter += $this->clearFilesFromHostCacheDir($regex);
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
|
87 |
+
|
88 |
+
|
89 |
+
return $counter;
|
90 |
+
}
|
91 |
+
|
92 |
+
// @codingStandardsIgnoreStart
|
93 |
+
/*
|
94 |
+
* Back compat. alias for clearCache()
|
95 |
+
*/
|
96 |
+
public function clear_cache()
|
97 |
+
{ // @codingStandardsIgnoreEnd
|
98 |
+
return call_user_func_array([$this, 'clearCache'], func_get_args());
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Purges expired cache files (current blog).
|
103 |
+
*
|
104 |
+
* @since 150422 Rewrite.
|
105 |
+
*
|
106 |
+
* @param bool $manually TRUE if purging is done manually.
|
107 |
+
*
|
108 |
+
* @throws \Exception If a purge failure occurs.
|
109 |
+
*
|
110 |
+
* @return int Total files purged by this routine.
|
111 |
+
*/
|
112 |
+
public function purgeCache($manually = false)
|
113 |
+
{
|
114 |
+
$counter = 0; // Initialize.
|
115 |
+
|
116 |
+
if (!$manually && $this->disableAutoPurgeCacheRoutines()) {
|
117 |
+
return $counter; // Nothing to do.
|
118 |
+
}
|
119 |
+
@set_time_limit(1800); // @TODO Display a warning.
|
120 |
+
|
121 |
+
if (is_dir($cache_dir = $this->cacheDir())) {
|
122 |
+
$regex = $this->buildHostCachePathRegex('', '.+');
|
123 |
+
$counter += $this->purgeFilesFromHostCacheDir($regex);
|
124 |
+
}
|
125 |
+
|
126 |
+
return $counter;
|
127 |
+
}
|
128 |
+
|
129 |
+
// @codingStandardsIgnoreStart
|
130 |
+
/*
|
131 |
+
* Back compat. alias for purgeCache()
|
132 |
+
*/
|
133 |
+
public function purge_cache()
|
134 |
+
{ // @codingStandardsIgnoreEnd
|
135 |
+
return call_user_func_array([$this, 'purgeCache'], func_get_args());
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Wurges (purges) all expired cache files; like wipe, but expired files only.
|
140 |
+
*
|
141 |
+
* @since 151002 Look at entire cache directory.
|
142 |
+
*
|
143 |
+
* @param bool $manually TRUE if wurging is done manually.
|
144 |
+
*
|
145 |
+
* @throws \Exception If a wurge failure occurs.
|
146 |
+
*
|
147 |
+
* @return int Total files wurged by this routine.
|
148 |
+
*/
|
149 |
+
public function wurgeCache($manually = false)
|
150 |
+
{
|
151 |
+
$counter = 0; // Initialize.
|
152 |
+
|
153 |
+
if (!$manually && $this->disableAutoPurgeCacheRoutines()) {
|
154 |
+
return $counter; // Nothing to do.
|
155 |
+
}
|
156 |
+
@set_time_limit(1800); // @TODO Display a warning.
|
157 |
+
|
158 |
+
if (is_dir($cache_dir = $this->cacheDir())) {
|
159 |
+
$regex = $this->assembleCachePathRegex('', '.+');
|
160 |
+
$counter += $this->wurgeFilesFromCacheDir($regex);
|
161 |
+
}
|
162 |
+
|
163 |
+
return $counter;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Automatically wipes out all cache files.
|
168 |
+
*
|
169 |
+
* @attaches-to Nothing at this time.
|
170 |
+
*
|
171 |
+
* @since 150422 Rewrite.
|
172 |
+
*
|
173 |
+
* @return int Total files wiped by this routine (if any).
|
174 |
+
*
|
175 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently attached to any hooks.
|
176 |
+
* This is called upon whenever options are saved and/or restored though.
|
177 |
+
*/
|
178 |
+
public function autoWipeCache()
|
179 |
+
{
|
180 |
+
$counter = 0; // Initialize.
|
181 |
+
|
182 |
+
if (!is_null($done = &$this->cacheKey('autoWipeCache'))) {
|
183 |
+
return $counter; // Already did this.
|
184 |
+
}
|
185 |
+
$done = true; // Flag as having been done.
|
186 |
+
|
187 |
+
if (!$this->options['enable']) {
|
188 |
+
return $counter; // Nothing to do.
|
189 |
+
}
|
190 |
+
if ($this->disableAutoWipeCacheRoutines()) {
|
191 |
+
return $counter; // Nothing to do.
|
192 |
+
}
|
193 |
+
$counter += $this->wipeCache();
|
194 |
+
|
195 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
196 |
+
$this->enqueueNotice(sprintf(__('Detected significant changes that require a full wipe of the cache. Found %1$s in the cache; auto-wiping.', 'comet-cache'), esc_html($this->i18nFiles($counter))), ['combinable' => true]);
|
197 |
+
}
|
198 |
+
return $counter;
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Automatically clears all cache files (current host).
|
203 |
+
*
|
204 |
+
* @attaches-to `switch_theme` hook.
|
205 |
+
*
|
206 |
+
* @attaches-to `wp_create_nav_menu` hook.
|
207 |
+
* @attaches-to `wp_update_nav_menu` hook.
|
208 |
+
* @attaches-to `wp_delete_nav_menu` hook.
|
209 |
+
*
|
210 |
+
* @attaches-to `create_term` hook.
|
211 |
+
* @attaches-to `edit_terms` hook.
|
212 |
+
* @attaches-to `delete_term` hook.
|
213 |
+
*
|
214 |
+
* @attaches-to `add_link` hook.
|
215 |
+
* @attaches-to `edit_link` hook.
|
216 |
+
* @attaches-to `delete_link` hook.
|
217 |
+
*
|
218 |
+
* @since 150422 Rewrite.
|
219 |
+
*
|
220 |
+
* @return int Total files cleared by this routine (if any).
|
221 |
+
*
|
222 |
+
* @note This is also called upon during plugin activation.
|
223 |
+
*/
|
224 |
+
public function autoClearCache()
|
225 |
+
{
|
226 |
+
$counter = 0; // Initialize.
|
227 |
+
|
228 |
+
if (!is_null($done = &$this->cacheKey('autoClearCache'))) {
|
229 |
+
return $counter; // Already did this.
|
230 |
+
}
|
231 |
+
$done = true; // Flag as having been done.
|
232 |
+
|
233 |
+
if (!$this->options['enable']) {
|
234 |
+
return $counter; // Nothing to do.
|
235 |
+
}
|
236 |
+
if ($this->disableAutoClearCacheRoutines()) {
|
237 |
+
return $counter; // Nothing to do.
|
238 |
+
}
|
239 |
+
$counter += $this->clearCache();
|
240 |
+
|
241 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
242 |
+
$this->enqueueNotice(sprintf(__('Detected important site changes that affect the entire cache. Found %1$s in the cache for this site; auto-clearing.', 'comet-cache'), esc_html($this->i18nFiles($counter))), ['combinable' => true]);
|
243 |
+
}
|
244 |
+
return $counter;
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* Automatically purges all cache files (current host).
|
249 |
+
*
|
250 |
+
* @attaches-to Nothing at this time.
|
251 |
+
*
|
252 |
+
* @since 151002 While working on directory stats.
|
253 |
+
*
|
254 |
+
* @return int Total files purged by this routine.
|
255 |
+
*
|
256 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently attached to any hooks.
|
257 |
+
*/
|
258 |
+
public function autoPurgeCache()
|
259 |
+
{
|
260 |
+
$counter = 0; // Initialize.
|
261 |
+
|
262 |
+
if (!is_null($done = &$this->cacheKey('autoPurgeCache'))) {
|
263 |
+
return $counter; // Already did this.
|
264 |
+
}
|
265 |
+
$done = true; // Flag as having been done.
|
266 |
+
|
267 |
+
if (!$this->options['enable']) {
|
268 |
+
return $counter; // Nothing to do.
|
269 |
+
}
|
270 |
+
if ($this->disableAutoPurgeCacheRoutines()) {
|
271 |
+
return $counter; // Nothing to do.
|
272 |
+
}
|
273 |
+
$counter += $this->purgeCache();
|
274 |
+
|
275 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
276 |
+
$this->enqueueNotice(sprintf(__('Detected important site changes. Found %1$s in the cache for this site that were expired; auto-purging.', 'comet-cache'), esc_html($this->i18nFiles($counter))), ['combinable' => true]);
|
277 |
+
}
|
278 |
+
return $counter;
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Automatically wurges all cache files.
|
283 |
+
*
|
284 |
+
* @attaches-to Nothing at this time.
|
285 |
+
*
|
286 |
+
* @since 151002 While working on directory stats.
|
287 |
+
*
|
288 |
+
* @return int Total files wurged by this routine.
|
289 |
+
*
|
290 |
+
* @note Unlike many of the other `auto_` methods, this one is NOT currently attached to any hooks.
|
291 |
+
*/
|
292 |
+
public function autoWurgeCache()
|
293 |
+
{
|
294 |
+
$counter = 0; // Initialize.
|
295 |
+
|
296 |
+
if (!is_null($done = &$this->cacheKey('autoWurgeCache'))) {
|
297 |
+
return $counter; // Already did this.
|
298 |
+
}
|
299 |
+
$done = true; // Flag as having been done.
|
300 |
+
|
301 |
+
if (!$this->options['enable']) {
|
302 |
+
return $counter; // Nothing to do.
|
303 |
+
}
|
304 |
+
if ($this->disableAutoPurgeCacheRoutines()) {
|
305 |
+
return $counter; // Nothing to do.
|
306 |
+
}
|
307 |
+
$counter += $this->wurgeCache();
|
308 |
+
|
309 |
+
if ($counter && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
310 |
+
$this->enqueueNotice(sprintf(__('Detected important site changes. Found %1$s in the cache that were expired; auto-purging.', 'comet-cache'), esc_html($this->i18nFiles($counter))), ['combinable' => true]);
|
311 |
+
}
|
312 |
+
return $counter;
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Allows a site owner to disable the automatic cache wiping routines.
|
317 |
+
*
|
318 |
+
* This is done by filtering `'.__GLOBAL_NS__.'_disable_auto_wipe_cache_routines` to return TRUE,
|
319 |
+
* in which case this method returns TRUE, otherwise it returns FALSE.
|
320 |
+
*
|
321 |
+
* @since 150422 Rewrite.
|
322 |
+
*
|
323 |
+
* @return bool `TRUE` if disabled; and this also creates a dashboard notice in some cases.
|
324 |
+
*/
|
325 |
+
public function disableAutoWipeCacheRoutines()
|
326 |
+
{
|
327 |
+
$is_disabled = (boolean) $this->applyWpFilters(GLOBAL_NS.'_disable_auto_wipe_cache_routines', false);
|
328 |
+
|
329 |
+
if ($is_disabled && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
330 |
+
$this->enqueueMainNotice(
|
331 |
+
'<img src="'.esc_attr($this->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
332 |
+
sprintf(__('<strong>%1$s:</strong> detected significant changes that would normally trigger cache wiping routines. However, cache wiping routines have been disabled by a site administrator. [<a href="http://cometcache.com/r/kb-clear-and-wipe-cache-routines/" target="_blank">?</a>]', 'comet-cache'), esc_html(NAME))
|
333 |
+
);
|
334 |
+
}
|
335 |
+
return $is_disabled;
|
336 |
+
}
|
337 |
+
|
338 |
+
/**
|
339 |
+
* Allows a site owner to disable the automatic cache clearing routines.
|
340 |
+
*
|
341 |
+
* This is done by filtering `'.__GLOBAL_NS__.'_disable_auto_clear_cache_routines` to return TRUE,
|
342 |
+
* in which case this method returns TRUE, otherwise it returns FALSE.
|
343 |
+
*
|
344 |
+
* @since 150422 Rewrite.
|
345 |
+
*
|
346 |
+
* @return bool `TRUE` if disabled; and this also creates a dashboard notice in some cases.
|
347 |
+
*/
|
348 |
+
public function disableAutoClearCacheRoutines()
|
349 |
+
{
|
350 |
+
$is_disabled = (boolean) $this->applyWpFilters(GLOBAL_NS.'_disable_auto_clear_cache_routines', false);
|
351 |
+
|
352 |
+
if ($is_disabled && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
353 |
+
$this->enqueueMainNotice(
|
354 |
+
'<img src="'.esc_attr($this->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
355 |
+
sprintf(__('<strong>%1$s:</strong> detected important site changes that would normally trigger cache clearing routines. However, cache clearing routines have been disabled by a site administrator. [<a href="http://cometcache.com/r/kb-clear-and-wipe-cache-routines/" target="_blank">?</a>]', 'comet-cache'), esc_html(NAME))
|
356 |
+
);
|
357 |
+
}
|
358 |
+
return $is_disabled;
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* Allows a site owner to disable the automatic cache purging routines.
|
363 |
+
*
|
364 |
+
* This is done by filtering `'.__GLOBAL_NS__.'_disable_auto_purge_cache_routines` to return TRUE,
|
365 |
+
* in which case this method returns TRUE, otherwise it returns FALSE.
|
366 |
+
*
|
367 |
+
* @since 151002 While working on directory stats.
|
368 |
+
*
|
369 |
+
* @return bool `TRUE` if disabled; and this also creates a dashboard notice in some cases.
|
370 |
+
*/
|
371 |
+
public function disableAutoPurgeCacheRoutines()
|
372 |
+
{
|
373 |
+
$is_disabled = (boolean) $this->applyWpFilters(GLOBAL_NS.'_disable_auto_purge_cache_routines', false);
|
374 |
+
|
375 |
+
if ($is_disabled && is_admin() && (!IS_PRO || $this->options['change_notifications_enable'])) {
|
376 |
+
$this->enqueueMainNotice(
|
377 |
+
'<img src="'.esc_attr($this->url('/src/client-s/images/clear.png')).'" style="float:left; margin:0 10px 0 0; border:0;" />'.
|
378 |
+
sprintf(__('<strong>%1$s:</strong> detected important site changes that would normally trigger cache purging routines. However, cache purging routines have been disabled by a site administrator. [<a href="http://cometcache.com/r/kb-clear-and-wipe-cache-routines/" target="_blank">?</a>]', 'comet-cache'), esc_html(NAME))
|
379 |
+
);
|
380 |
+
}
|
381 |
+
return $is_disabled;
|
382 |
+
}
|
383 |
+
}
|
src/includes/traits/Plugin/WcpWooCommerceUtils.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Plugin;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait WcpWooCommerceUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Automatically clears cache file for a WooCommerce Product when its stock is changed.
|
10 |
+
*
|
11 |
+
* @since 151220 Improving WooCommerce Compatibility.
|
12 |
+
*
|
13 |
+
* @attaches-to `woocommerce_product_set_stock` hook.
|
14 |
+
*
|
15 |
+
* @param \WC_Product $product A WooCommerce WC_Product object
|
16 |
+
*/
|
17 |
+
public function autoClearPostCacheOnWooCommerceSetStock($product)
|
18 |
+
{
|
19 |
+
$counter = 0; // Initialize.
|
20 |
+
|
21 |
+
if (!is_null($done = &$this->cacheKey('autoClearPostCacheOnWooCommerceSetStock'))) {
|
22 |
+
return $counter; // Already did this.
|
23 |
+
}
|
24 |
+
$done = true; // Flag as having been done.
|
25 |
+
|
26 |
+
if (class_exists('\\WooCommerce')) {
|
27 |
+
$counter += $this->autoClearPostCache($product->id);
|
28 |
+
}
|
29 |
+
}
|
30 |
+
}
|
src/includes/traits/Shared/BlogUtils.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait BlogUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Get blog details.
|
10 |
+
*
|
11 |
+
* @since 150821 Improving multisite compat.
|
12 |
+
*
|
13 |
+
* @param int $blog_id For which blog ID?
|
14 |
+
*
|
15 |
+
* @return \stdClass|null Blog details if possible.
|
16 |
+
*
|
17 |
+
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
18 |
+
*/
|
19 |
+
public function blogDetails($blog_id = 0)
|
20 |
+
{
|
21 |
+
if (!is_multisite() || $this->isAdvancedCache()) {
|
22 |
+
return null; // Not possible.
|
23 |
+
}
|
24 |
+
if (($blog_id = (integer) $blog_id) < 0) {
|
25 |
+
$blog_id = (integer) get_current_site()->blog_id;
|
26 |
+
}
|
27 |
+
if (!$blog_id) {
|
28 |
+
$blog_id = (integer) get_current_blog_id();
|
29 |
+
}
|
30 |
+
if (!$blog_id || $blog_id < 0) {
|
31 |
+
return null; // Not possible.
|
32 |
+
}
|
33 |
+
$details = get_blog_details($blog_id);
|
34 |
+
|
35 |
+
return is_object($details) ? $details : null;
|
36 |
+
}
|
37 |
+
}
|
src/includes/traits/Shared/CacheDirUtils.php
ADDED
@@ -0,0 +1,651 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait CacheDirUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Cache directory path.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param string $rel_path Relative path inside cache directory.
|
14 |
+
*
|
15 |
+
* @throws \Exception If unable to get cache directory.
|
16 |
+
*
|
17 |
+
* @return string Absolute path to cache directory.
|
18 |
+
*/
|
19 |
+
public function cacheDir($rel_path = '')
|
20 |
+
{
|
21 |
+
$rel_path = (string) $rel_path;
|
22 |
+
|
23 |
+
if ($this->isAdvancedCache()) {
|
24 |
+
$cache_dir = defined('COMET_CACHE_DIR') ? COMET_CACHE_DIR : '';
|
25 |
+
} elseif (!empty($this->cache_sub_dir)) {
|
26 |
+
$cache_dir = $this->wpContentBaseDirTo($this->cache_sub_dir);
|
27 |
+
}
|
28 |
+
if (empty($cache_dir)) {
|
29 |
+
throw new \Exception(__('Unable to determine cache directory location.', 'comet-cache'));
|
30 |
+
}
|
31 |
+
return rtrim($cache_dir, '/').($rel_path ? '/'.ltrim($rel_path) : '');
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Wipe files from the cache directory (for all hosts/blogs);
|
36 |
+
* i.e., those that match a specific regex pattern.
|
37 |
+
*
|
38 |
+
* @since 151002 While working on directory stats.
|
39 |
+
*
|
40 |
+
* @param string $regex A regex pattern; see {@link deleteFilesFromCacheDir()}.
|
41 |
+
*
|
42 |
+
* @return int Total files wiped by this routine.
|
43 |
+
*/
|
44 |
+
public function wipeFilesFromCacheDir($regex)
|
45 |
+
{
|
46 |
+
return $this->deleteFilesFromCacheDir($regex);
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Clear files from the cache directory (for the current host);
|
51 |
+
* i.e., those that match a specific regex pattern.
|
52 |
+
*
|
53 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
54 |
+
*
|
55 |
+
* @param string $regex A regex pattern; see {@link deleteFilesFromHostCacheDir()}.
|
56 |
+
*
|
57 |
+
* @return int Total files cleared by this routine (if any).
|
58 |
+
*/
|
59 |
+
public function clearFilesFromHostCacheDir($regex)
|
60 |
+
{
|
61 |
+
return $this->deleteFilesFromHostCacheDir($regex);
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Wurge (purge) files from the cache directory (for all hosts/blogs);
|
66 |
+
* i.e., those that match a specific regex pattern.
|
67 |
+
*
|
68 |
+
* @since 151002 While working on directory stats.
|
69 |
+
*
|
70 |
+
* @param string $regex A regex pattern; see {@link deleteFilesFromCacheDir()}.
|
71 |
+
*
|
72 |
+
* @return int Total files wurged by this routine.
|
73 |
+
*/
|
74 |
+
public function wurgeFilesFromCacheDir($regex)
|
75 |
+
{
|
76 |
+
return $this->deleteFilesFromCacheDir($regex, true);
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Purge files from the cache directory (for the current host);
|
81 |
+
* i.e., those that match a specific regex pattern.
|
82 |
+
*
|
83 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
84 |
+
*
|
85 |
+
* @param string $regex A regex pattern; see {@link deleteFilesFromHostCacheDir()}.
|
86 |
+
*
|
87 |
+
* @return int Total files purged by this routine (if any).
|
88 |
+
*/
|
89 |
+
public function purgeFilesFromHostCacheDir($regex)
|
90 |
+
{
|
91 |
+
return $this->deleteFilesFromHostCacheDir($regex, true);
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Delete files from the cache directory (for all hosts/blogs);
|
96 |
+
* i.e., those that match a specific regex pattern.
|
97 |
+
*
|
98 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
99 |
+
*
|
100 |
+
* @param string $regex A `/[regex pattern]/`; relative to the cache directory.
|
101 |
+
* e.g. `/^http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
102 |
+
*
|
103 |
+
* Or, this can also be a full/absolute regex pattern against an absolute path;
|
104 |
+
* provided that it always starts with `/^`; including the full absolute cache/host directory path.
|
105 |
+
* e.g. `/^\/cache\/dir\/http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
106 |
+
* @param bool $check_max_age Check max age? i.e., use purge behavior?
|
107 |
+
*
|
108 |
+
* @throws \Exception If unable to delete a file for any reason.
|
109 |
+
* @return int Total files deleted by this routine (if any).
|
110 |
+
*
|
111 |
+
*
|
112 |
+
* @TODO Optimize this for multisite networks w/ a LOT of child blogs.
|
113 |
+
* @TODO Optimize this for extremely large sites. A LOT of files here could slow things down.
|
114 |
+
* This class member is currently used in wiping and purging for a network. So there is the potential for a LOT of files in a single scan.
|
115 |
+
* See also: <https://codex.wordpress.org/Function_Reference/wp_is_large_network>
|
116 |
+
*/
|
117 |
+
public function deleteFilesFromCacheDir($regex, $check_max_age = false)
|
118 |
+
{
|
119 |
+
$counter = 0; // Initialize.
|
120 |
+
|
121 |
+
if (!($regex = (string) $regex)) {
|
122 |
+
return $counter; // Nothing to do.
|
123 |
+
}
|
124 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
125 |
+
return $counter; // Nothing to do.
|
126 |
+
}
|
127 |
+
$cache_dir = $this->nDirSeps($cache_dir);
|
128 |
+
|
129 |
+
if ($check_max_age && $this->isAdvancedCache()) {
|
130 |
+
throw new \Exception(__('Invalid argument; isAdvancedCache!', 'comet-cache'));
|
131 |
+
}
|
132 |
+
if ($check_max_age && !($max_age = strtotime('-'.$this->options['cache_max_age']))) {
|
133 |
+
return $counter; // Invalid cache expiration time.
|
134 |
+
}
|
135 |
+
/* ------- Begin lock state... ----------- */
|
136 |
+
|
137 |
+
$cache_lock = $this->cacheLock(); // Lock cache writes.
|
138 |
+
|
139 |
+
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
140 |
+
|
141 |
+
$cache_dir_tmp = $this->addTmpSuffix($cache_dir); // Temporary directory.
|
142 |
+
|
143 |
+
$cache_dir_tmp_regex = $regex; // Initialize host-specific regex pattern for the tmp directory.
|
144 |
+
$cache_dir_tmp_regex = '\\/'.ltrim($cache_dir_tmp_regex, '^\\/'); // Make sure it begins with an escaped `/`.
|
145 |
+
$cache_dir_tmp_regex = $this->strIreplaceOnce(preg_quote($cache_dir.'/', '/'), '', $cache_dir_tmp_regex);
|
146 |
+
|
147 |
+
$cache_dir_tmp_regex = ltrim($cache_dir_tmp_regex, '^\\/');
|
148 |
+
if (strpos($cache_dir_tmp_regex, '(?:\/') === 0 || strpos($cache_dir_tmp_regex, '(\/') === 0) {
|
149 |
+
$cache_dir_tmp_regex = '/^'.preg_quote($cache_dir_tmp, '/').$cache_dir_tmp_regex;
|
150 |
+
} else {
|
151 |
+
$cache_dir_tmp_regex = '/^'.preg_quote($cache_dir_tmp.'/', '/').$cache_dir_tmp_regex;
|
152 |
+
}
|
153 |
+
# if(WP_DEBUG) file_put_contents(WP_CONTENT_DIR.'/'.strtolower(SHORT_NAME).'-debug.log', print_r($regex, TRUE)."\n".print_r($cache_dir_tmp_regex, TRUE)."\n\n", FILE_APPEND);
|
154 |
+
// Uncomment the above line to debug regex pattern matching used by this routine; and others that call upon it.
|
155 |
+
|
156 |
+
if (!rename($cache_dir, $cache_dir_tmp)) {
|
157 |
+
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on directory: `%1$s`.', 'comet-cache'), $cache_dir));
|
158 |
+
}
|
159 |
+
foreach (($_dir_regex_iteration = $this->dirRegexIteration($cache_dir_tmp, $cache_dir_tmp_regex)) as $_resource) {
|
160 |
+
$_resource_type = $_resource->getType();
|
161 |
+
$_sub_path_name = $_resource->getSubpathname();
|
162 |
+
$_path_name = $_resource->getPathname();
|
163 |
+
|
164 |
+
if ($_resource_type !== 'dir' && strpos($_sub_path_name, '/') === false) {
|
165 |
+
continue; // Don't delete links/files in the immediate directory; e.g. `[SHORT_NAME]-advanced-cache` or `.htaccess`, etc.
|
166 |
+
// Actual `http|https/...` cache links/files are nested. Links/files in the immediate directory are for other purposes.
|
167 |
+
}
|
168 |
+
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
169 |
+
|
170 |
+
case 'link': // Symbolic links; i.e., 404 errors.
|
171 |
+
|
172 |
+
if ($check_max_age && !empty($max_age) && is_file($_resource->getLinkTarget())) {
|
173 |
+
if (($_lstat = lstat($_path_name)) && !empty($_lstat['mtime'])) {
|
174 |
+
if ($_lstat['mtime'] >= $max_age) {
|
175 |
+
break; // Break switch.
|
176 |
+
}
|
177 |
+
}
|
178 |
+
}
|
179 |
+
if (!unlink($_path_name)) {
|
180 |
+
$this->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
181 |
+
throw new \Exception(sprintf(__('Unable to delete symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
182 |
+
}
|
183 |
+
++$counter; // Increment counter for each link we delete.
|
184 |
+
|
185 |
+
break; // Break switch handler.
|
186 |
+
|
187 |
+
case 'file': // Regular files; i.e., not symlinks.
|
188 |
+
|
189 |
+
if ($check_max_age && !empty($max_age)) {
|
190 |
+
if ($_resource->getMTime() >= $max_age) {
|
191 |
+
break; // Break switch.
|
192 |
+
}
|
193 |
+
}
|
194 |
+
if (!unlink($_path_name)) {
|
195 |
+
$this->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
196 |
+
throw new \Exception(sprintf(__('Unable to delete file: `%1$s`.', 'comet-cache'), $_path_name));
|
197 |
+
}
|
198 |
+
++$counter; // Increment counter for each file we delete.
|
199 |
+
|
200 |
+
break; // Break switch handler.
|
201 |
+
|
202 |
+
case 'dir': // A regular directory; i.e., not a symlink.
|
203 |
+
|
204 |
+
if ($regex !== '/^.+/i') {
|
205 |
+
break; // Not deleting everything.
|
206 |
+
}
|
207 |
+
if ($check_max_age && !empty($max_age)) {
|
208 |
+
break; // Not deleting everything.
|
209 |
+
}
|
210 |
+
if (!rmdir($_path_name)) {
|
211 |
+
$this->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
212 |
+
throw new \Exception(sprintf(__('Unable to delete dir: `%1$s`.', 'comet-cache'), $_path_name));
|
213 |
+
}
|
214 |
+
# $counter++; // Increment counter for each directory we delete. ~ NO don't do that here.
|
215 |
+
|
216 |
+
break; // Break switch handler.
|
217 |
+
|
218 |
+
default: // Something else that is totally unexpected here.
|
219 |
+
$this->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
220 |
+
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
221 |
+
}
|
222 |
+
}
|
223 |
+
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name, $_lstat); // Housekeeping.
|
224 |
+
|
225 |
+
if (!rename($cache_dir_tmp, $cache_dir)) {
|
226 |
+
$this->tryErasingAllFilesDirsIn($cache_dir_tmp, true); // Cleanup if possible.
|
227 |
+
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $cache_dir_tmp));
|
228 |
+
}
|
229 |
+
/* ------- End lock state... ------------- */
|
230 |
+
|
231 |
+
$this->cacheUnlock($cache_lock); // Release.
|
232 |
+
|
233 |
+
return $counter;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Delete files from the cache directory (for the current host);
|
238 |
+
* i.e., those that match a specific regex pattern.
|
239 |
+
*
|
240 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
241 |
+
*
|
242 |
+
* @param string $regex A `/[regex pattern]/`; relative to the host cache directory.
|
243 |
+
* e.g. `/^my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
244 |
+
*
|
245 |
+
* Or, this can also be a full/absolute regex pattern against an absolute path;
|
246 |
+
* provided that it always starts with `/^`; including the full absolute cache/host directory path.
|
247 |
+
* e.g. `/^\/cache\/dir\/http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/`
|
248 |
+
* @param bool $check_max_age Check max age? i.e., use purge behavior?
|
249 |
+
* @param bool $___considering_domain_mapping For internal use only.
|
250 |
+
* @param bool $___consider_domain_mapping_host_token For internal use only.
|
251 |
+
* @param bool $___consider_domain_mapping_host_base_dir_tokens For internal use only.
|
252 |
+
*
|
253 |
+
* @throws \Exception If unable to delete a file for any reason.
|
254 |
+
* @return int Total files deleted by this routine (if any).
|
255 |
+
*
|
256 |
+
*/
|
257 |
+
public function deleteFilesFromHostCacheDir(
|
258 |
+
$regex,
|
259 |
+
$check_max_age = false,
|
260 |
+
$___considering_domain_mapping = false,
|
261 |
+
$___consider_domain_mapping_host_token = null,
|
262 |
+
$___consider_domain_mapping_host_base_dir_tokens = null
|
263 |
+
) {
|
264 |
+
$counter = 0; // Initialize.
|
265 |
+
|
266 |
+
if (!($regex = (string) $regex)) {
|
267 |
+
return $counter; // Nothing to do.
|
268 |
+
}
|
269 |
+
if (!is_dir($cache_dir = $this->cacheDir())) {
|
270 |
+
return $counter; // Nothing to do.
|
271 |
+
}
|
272 |
+
$cache_dir = $this->nDirSeps($cache_dir); // Normalize.
|
273 |
+
$host_token = $current_host_token = $this->hostToken();
|
274 |
+
$host_base_dir_tokens = $current_host_base_dir_tokens = $this->hostBaseDirTokens();
|
275 |
+
|
276 |
+
if ($___considering_domain_mapping && isset($___consider_domain_mapping_host_token, $___consider_domain_mapping_host_base_dir_tokens)) {
|
277 |
+
$host_token = (string) $___consider_domain_mapping_host_token;
|
278 |
+
$host_base_dir_tokens = (string) $___consider_domain_mapping_host_base_dir_tokens;
|
279 |
+
}
|
280 |
+
if (!$host_token) { // Must have a host in the sub-routine below.
|
281 |
+
throw new \Exception(__('Invalid argument; host token empty!', 'comet-cache'));
|
282 |
+
}
|
283 |
+
if ($check_max_age && $this->isAdvancedCache()) {
|
284 |
+
throw new \Exception(__('Invalid argument; isAdvancedCache!', 'comet-cache'));
|
285 |
+
}
|
286 |
+
if ($check_max_age && !($max_age = strtotime('-'.$this->options['cache_max_age']))) {
|
287 |
+
return $counter; // Invalid cache expiration time.
|
288 |
+
}
|
289 |
+
/* ------- Begin lock state... ----------- */
|
290 |
+
|
291 |
+
$cache_lock = $this->cacheLock(); // Lock cache writes.
|
292 |
+
|
293 |
+
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
294 |
+
|
295 |
+
foreach (['http', 'https'] as $_host_scheme) {
|
296 |
+
$_host_url = $_host_scheme.'://'.$host_token.$host_base_dir_tokens;
|
297 |
+
$_host_cache_path_flags = $this::CACHE_PATH_NO_PATH_INDEX | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT;
|
298 |
+
$_host_cache_path = $this->buildCachePath($_host_url, '', '', $_host_cache_path_flags);
|
299 |
+
$_host_cache_dir = $this->nDirSeps($cache_dir.'/'.$_host_cache_path); // Normalize.
|
300 |
+
|
301 |
+
if (!$_host_cache_dir || !is_dir($_host_cache_dir)) {
|
302 |
+
// On a multisite install this may have a cache sub-directory.
|
303 |
+
// e.g., `http/example-com[[-base]-child1][[/base]/child1]` instead of `http/example-com`.
|
304 |
+
continue; // Nothing to do.
|
305 |
+
}
|
306 |
+
$_host_cache_dir_tmp = $this->addTmpSuffix($_host_cache_dir); // Temporary directory.
|
307 |
+
|
308 |
+
$_host_cache_dir_tmp_regex = $regex; // Initialize host-specific regex pattern for the tmp directory.
|
309 |
+
$_host_cache_dir_tmp_regex = '\\/'.ltrim($_host_cache_dir_tmp_regex, '^\\/'); // Make sure it begins with an escaped `/`.
|
310 |
+
$_host_cache_dir_tmp_regex = $this->strIreplaceOnce(preg_quote($_host_cache_path.'/', '/'), '', $_host_cache_dir_tmp_regex);
|
311 |
+
$_host_cache_dir_tmp_regex = $this->strIreplaceOnce(preg_quote($_host_cache_dir.'/', '/'), '', $_host_cache_dir_tmp_regex);
|
312 |
+
|
313 |
+
$_host_cache_dir_tmp_regex = ltrim($_host_cache_dir_tmp_regex, '^\\/');
|
314 |
+
if (strpos($_host_cache_dir_tmp_regex, '(?:\/') === 0 || strpos($_host_cache_dir_tmp_regex, '(\/') === 0) {
|
315 |
+
$_host_cache_dir_tmp_regex = '/^'.preg_quote($_host_cache_dir_tmp, '/').$_host_cache_dir_tmp_regex;
|
316 |
+
} else {
|
317 |
+
$_host_cache_dir_tmp_regex = '/^'.preg_quote($_host_cache_dir_tmp.'/', '/').$_host_cache_dir_tmp_regex;
|
318 |
+
}
|
319 |
+
#if(WP_DEBUG) file_put_contents(WP_CONTENT_DIR.'/'.strtolower(SHORT_NAME).'-debug.log', print_r($regex, TRUE)."\n".print_r($_host_cache_dir_tmp_regex, TRUE)."\n\n", FILE_APPEND);
|
320 |
+
// Uncomment the above line to debug regex pattern matching used by this routine; and others that call upon it.
|
321 |
+
|
322 |
+
if (!rename($_host_cache_dir, $_host_cache_dir_tmp)) {
|
323 |
+
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $_host_cache_dir));
|
324 |
+
}
|
325 |
+
foreach (($_dir_regex_iteration = $this->dirRegexIteration($_host_cache_dir_tmp, $_host_cache_dir_tmp_regex)) as $_resource) {
|
326 |
+
$_resource_type = $_resource->getType();
|
327 |
+
$_sub_path_name = $_resource->getSubpathname();
|
328 |
+
$_path_name = $_resource->getPathname();
|
329 |
+
|
330 |
+
if ($_host_cache_dir === $cache_dir && $_resource_type !== 'dir' && strpos($_sub_path_name, '/') === false) {
|
331 |
+
continue; // Don't delete links/files in the immediate directory; e.g. `[SHORT_NAME]-advanced-cache` or `.htaccess`, etc.
|
332 |
+
// Actual `http|https/...` cache links/files are nested. Links/files in the immediate directory are for other purposes.
|
333 |
+
}
|
334 |
+
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
335 |
+
|
336 |
+
case 'link': // Symbolic links; i.e., 404 errors.
|
337 |
+
|
338 |
+
if ($check_max_age && !empty($max_age) && is_file($_resource->getLinkTarget())) {
|
339 |
+
if (($_lstat = lstat($_path_name)) && !empty($_lstat['mtime'])) {
|
340 |
+
if ($_lstat['mtime'] >= $max_age) {
|
341 |
+
break; // Break switch.
|
342 |
+
}
|
343 |
+
}
|
344 |
+
}
|
345 |
+
if (!unlink($_path_name)) {
|
346 |
+
$this->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
347 |
+
throw new \Exception(sprintf(__('Unable to delete symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
348 |
+
}
|
349 |
+
++$counter; // Increment counter for each link we delete.
|
350 |
+
|
351 |
+
break; // Break switch handler.
|
352 |
+
|
353 |
+
case 'file': // Regular files; i.e., not symlinks.
|
354 |
+
|
355 |
+
if ($check_max_age && !empty($max_age)) {
|
356 |
+
if ($_resource->getMTime() >= $max_age) {
|
357 |
+
break; // Break switch handler.
|
358 |
+
}
|
359 |
+
}
|
360 |
+
if (!unlink($_path_name)) {
|
361 |
+
$this->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
362 |
+
throw new \Exception(sprintf(__('Unable to delete file: `%1$s`.', 'comet-cache'), $_path_name));
|
363 |
+
}
|
364 |
+
++$counter; // Increment counter for each file we delete.
|
365 |
+
|
366 |
+
break; // Break switch handler.
|
367 |
+
|
368 |
+
case 'dir': // A regular directory; i.e., not a symlink.
|
369 |
+
|
370 |
+
if ($regex !== '/^.+/i') {
|
371 |
+
break; // Not deleting everything.
|
372 |
+
}
|
373 |
+
if ($check_max_age && !empty($max_age)) {
|
374 |
+
break; // Not deleting everything.
|
375 |
+
}
|
376 |
+
if (!rmdir($_path_name)) {
|
377 |
+
$this->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
378 |
+
throw new \Exception(sprintf(__('Unable to delete dir: `%1$s`.', 'comet-cache'), $_path_name));
|
379 |
+
}
|
380 |
+
# $counter++; // Increment counter for each directory we delete. ~ NO don't do that here.
|
381 |
+
|
382 |
+
break; // Break switch handler.
|
383 |
+
|
384 |
+
default: // Something else that is totally unexpected here.
|
385 |
+
$this->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
386 |
+
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
387 |
+
}
|
388 |
+
}
|
389 |
+
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name, $_lstat); // Housekeeping.
|
390 |
+
|
391 |
+
if (!rename($_host_cache_dir_tmp, $_host_cache_dir)) {
|
392 |
+
$this->tryErasingAllFilesDirsIn($_host_cache_dir_tmp, true); // Cleanup if possible.
|
393 |
+
throw new \Exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $_host_cache_dir_tmp));
|
394 |
+
}
|
395 |
+
}
|
396 |
+
unset($_host_scheme, $_host_url, $_host_cache_path_flags, $_host_cache_path, $_host_cache_dir, $_host_cache_dir_tmp, $_host_cache_dir_tmp_regex);
|
397 |
+
|
398 |
+
/* ------- End lock state... ------------- */
|
399 |
+
|
400 |
+
$this->cacheUnlock($cache_lock); // Release.
|
401 |
+
|
402 |
+
/* ------- Include domain mapping variations also. ------- */
|
403 |
+
|
404 |
+
if (!$___considering_domain_mapping && is_multisite() && $this->canConsiderDomainMapping()) {
|
405 |
+
$domain_mapping_variations = []; // Initialize array of domain variations.
|
406 |
+
|
407 |
+
if (($_host_token_for_blog = $this->hostTokenForBlog())) {
|
408 |
+
$_host_base_dir_tokens_for_blog = $this->hostBaseDirTokensForBlog();
|
409 |
+
$domain_mapping_variations[] = ['host_token' => $_host_token_for_blog, 'host_base_dir_tokens' => $_host_base_dir_tokens_for_blog];
|
410 |
+
} // The original blog host; i.e., without domain mapping.
|
411 |
+
unset($_host_token_for_blog, $_host_base_dir_tokens_for_blog); // Housekeeping.
|
412 |
+
|
413 |
+
foreach ($this->domainMappingBlogDomains() as $_domain_mapping_blog_domain) {
|
414 |
+
if (($_domain_host_token_for_blog = $this->hostTokenForBlog(false, true, $_domain_mapping_blog_domain))) {
|
415 |
+
$_domain_host_base_dir_tokens_for_blog = $this->hostBaseDirTokensForBlog(false, true); // This is only a formality.
|
416 |
+
$domain_mapping_variations[] = ['host_token' => $_domain_host_token_for_blog, 'host_base_dir_tokens' => $_domain_host_base_dir_tokens_for_blog];
|
417 |
+
}
|
418 |
+
} // This includes all of the domain mappings configured for the current blog ID.
|
419 |
+
unset($_domain_mapping_blog_domain, $_domain_host_token_for_blog, $_domain_host_base_dir_tokens_for_blog); // Housekeeping.
|
420 |
+
|
421 |
+
foreach ($domain_mapping_variations as $_domain_mapping_variation) {
|
422 |
+
if ($_domain_mapping_variation['host_token'] === $current_host_token && $_domain_mapping_variation['host_base_dir_tokens'] === $current_host_base_dir_tokens) {
|
423 |
+
continue; // Exclude current tokens. They were already iterated above.
|
424 |
+
}
|
425 |
+
$counter += $this->deleteFilesFromHostCacheDir($regex, $check_max_age, true, $_domain_mapping_variation['host_token'], $_domain_mapping_variation['host_base_dir_tokens']);
|
426 |
+
}
|
427 |
+
unset($_domain_mapping_variation); // Housekeeping.
|
428 |
+
}
|
429 |
+
return $counter;
|
430 |
+
}
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Delete all files/dirs from a directory (for all schemes/hosts);
|
434 |
+
* including `[SHORT_NAME]-` prefixed files; or anything else for that matter.
|
435 |
+
*
|
436 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
437 |
+
*
|
438 |
+
* @param string $dir The directory from which to delete files/dirs.
|
439 |
+
*
|
440 |
+
* SECURITY: This directory MUST be located inside the `/wp-content/` directory.
|
441 |
+
* Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself.
|
442 |
+
* Also, it cannot be: `mu-plugins`, `themes`, or `plugins`.
|
443 |
+
* @param bool $delete_dir_too Delete parent? i.e., delete the `$dir` itself also?
|
444 |
+
*
|
445 |
+
* @throws \Exception If unable to delete a file/directory for any reason.
|
446 |
+
* @return int Total files/directories deleted by this routine (if any).
|
447 |
+
*
|
448 |
+
*/
|
449 |
+
public function deleteAllFilesDirsIn($dir, $delete_dir_too = false)
|
450 |
+
{
|
451 |
+
$counter = 0; // Initialize.
|
452 |
+
|
453 |
+
if (!($dir = trim((string) $dir)) || !is_dir($dir)) {
|
454 |
+
return $counter; // Nothing to do.
|
455 |
+
}
|
456 |
+
$dir = $this->nDirSeps($dir);
|
457 |
+
$dir_temp = $this->addTmpSuffix($dir);
|
458 |
+
$wp_content_dir = $this->nDirSeps(WP_CONTENT_DIR);
|
459 |
+
$wp_content_dir_regex = preg_quote($wp_content_dir, '/');
|
460 |
+
|
461 |
+
if (!preg_match('/^'.$wp_content_dir_regex.'\/[^\/]+/i', $dir)) {
|
462 |
+
return $counter; // Security flag; do nothing in this case.
|
463 |
+
}
|
464 |
+
if (preg_match('/^'.$wp_content_dir_regex.'\/(?:mu\-plugins|themes|plugins)(?:\/|$)/i', $dir)) {
|
465 |
+
return $counter; // Security flag; do nothing in this case.
|
466 |
+
}
|
467 |
+
/* ------- Begin lock state... ----------- */
|
468 |
+
|
469 |
+
$cache_lock = $this->cacheLock(); // Lock cache writes.
|
470 |
+
|
471 |
+
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
472 |
+
|
473 |
+
if (!rename($dir, $dir_temp)) {
|
474 |
+
throw new \Exception(sprintf(__('Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $dir));
|
475 |
+
}
|
476 |
+
foreach (($_dir_regex_iteration = $this->dirRegexIteration($dir_temp, '/.+/')) as $_resource) {
|
477 |
+
$_resource_type = $_resource->getType();
|
478 |
+
$_sub_path_name = $_resource->getSubpathname();
|
479 |
+
$_path_name = $_resource->getPathname();
|
480 |
+
|
481 |
+
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
482 |
+
|
483 |
+
case 'link': // Symbolic links; i.e., 404 errors.
|
484 |
+
|
485 |
+
if (!unlink($_path_name)) {
|
486 |
+
$this->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
487 |
+
throw new \Exception(sprintf(__('Unable to delete symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
488 |
+
}
|
489 |
+
++$counter; // Increment counter for each link we delete.
|
490 |
+
|
491 |
+
break; // Break switch handler.
|
492 |
+
|
493 |
+
case 'file': // Regular files; i.e., not symlinks.
|
494 |
+
|
495 |
+
if (!unlink($_path_name)) {
|
496 |
+
$this->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
497 |
+
throw new \Exception(sprintf(__('Unable to delete file: `%1$s`.', 'comet-cache'), $_path_name));
|
498 |
+
}
|
499 |
+
++$counter; // Increment counter for each file we delete.
|
500 |
+
|
501 |
+
break; // Break switch handler.
|
502 |
+
|
503 |
+
case 'dir': // A regular directory; i.e., not a symlink.
|
504 |
+
|
505 |
+
if (!rmdir($_path_name)) {
|
506 |
+
$this->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
507 |
+
throw new \Exception(sprintf(__('Unable to delete dir: `%1$s`.', 'comet-cache'), $_path_name));
|
508 |
+
}
|
509 |
+
# ++$counter; // Increment counter for each directory we delete. ~ NO don't do that here.
|
510 |
+
|
511 |
+
break; // Break switch handler.
|
512 |
+
|
513 |
+
default: // Something else that is totally unexpected here.
|
514 |
+
$this->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
515 |
+
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
516 |
+
}
|
517 |
+
}
|
518 |
+
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name); // Housekeeping.
|
519 |
+
|
520 |
+
if (!rename($dir_temp, $dir)) {
|
521 |
+
$this->tryErasingAllFilesDirsIn($dir_temp, true); // Cleanup if possible.
|
522 |
+
throw new \Exception(sprintf(__('Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`.', 'comet-cache'), $dir_temp));
|
523 |
+
}
|
524 |
+
if ($delete_dir_too) {
|
525 |
+
if (!rmdir($dir)) {
|
526 |
+
throw new \Exception(sprintf(__('Unable to delete directory: `%1$s`.', 'comet-cache'), $dir));
|
527 |
+
}
|
528 |
+
++$counter; // Increment counter for each directory we delete.
|
529 |
+
}
|
530 |
+
/* ------- End lock state... ------------- */
|
531 |
+
|
532 |
+
$this->cacheUnlock($cache_lock); // Release.
|
533 |
+
|
534 |
+
return $counter;
|
535 |
+
}
|
536 |
+
|
537 |
+
/**
|
538 |
+
* Erase all files/dirs from a directory (for all schemes/hosts);
|
539 |
+
* including `[SHORT_NAME]-` prefixed files; or anything else for that matter.
|
540 |
+
*
|
541 |
+
* WARNING: This does NO LOCKING and NO ATOMIC deletions.
|
542 |
+
*
|
543 |
+
* @since 150821 Improving recovery under stress.
|
544 |
+
*
|
545 |
+
* @param string $dir The directory from which to erase files/dirs.
|
546 |
+
*
|
547 |
+
* SECURITY: This directory MUST be located inside the `/wp-content/` directory.
|
548 |
+
* Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself.
|
549 |
+
* Also, it cannot be: `mu-plugins`, `themes`, or `plugins`.
|
550 |
+
* @param bool $erase_dir_too Erase parent? i.e., erase the `$dir` itself also?
|
551 |
+
*
|
552 |
+
* @throws \Exception If unable to erase a file/directory for any reason.
|
553 |
+
* @return int Total files/directories erased by this routine (if any).
|
554 |
+
*
|
555 |
+
*/
|
556 |
+
public function eraseAllFilesDirsIn($dir, $erase_dir_too = false)
|
557 |
+
{
|
558 |
+
$counter = 0; // Initialize.
|
559 |
+
|
560 |
+
if (!($dir = trim((string) $dir)) || !is_dir($dir)) {
|
561 |
+
return $counter; // Nothing to do.
|
562 |
+
}
|
563 |
+
$dir = $this->nDirSeps($dir);
|
564 |
+
$wp_content_dir = $this->nDirSeps(WP_CONTENT_DIR);
|
565 |
+
$wp_content_dir_regex = preg_quote($wp_content_dir, '/');
|
566 |
+
|
567 |
+
if (!preg_match('/^'.$wp_content_dir_regex.'\/[^\/]+/i', $dir)) {
|
568 |
+
return $counter; // Security flag; do nothing in this case.
|
569 |
+
}
|
570 |
+
if (preg_match('/^'.$wp_content_dir_regex.'\/(?:mu\-plugins|themes|plugins)(?:\/|$)/i', $dir)) {
|
571 |
+
return $counter; // Security flag; do nothing in this case.
|
572 |
+
}
|
573 |
+
clearstatcache(); // Clear stat cache to be sure we have a fresh start below.
|
574 |
+
|
575 |
+
foreach (($_dir_regex_iteration = $this->dirRegexIteration($dir, '/.+/')) as $_resource) {
|
576 |
+
$_resource_type = $_resource->getType();
|
577 |
+
$_sub_path_name = $_resource->getSubpathname();
|
578 |
+
$_path_name = $_resource->getPathname();
|
579 |
+
|
580 |
+
switch ($_resource_type) {// Based on type; i.e., `link`, `file`, `dir`.
|
581 |
+
|
582 |
+
case 'link': // Symbolic links; i.e., 404 errors.
|
583 |
+
|
584 |
+
if (!unlink($_path_name)) {
|
585 |
+
throw new \Exception(sprintf(__('Unable to erase symlink: `%1$s`.', 'comet-cache'), $_path_name));
|
586 |
+
}
|
587 |
+
++$counter; // Increment counter for each link we erase.
|
588 |
+
|
589 |
+
break; // Break switch handler.
|
590 |
+
|
591 |
+
case 'file': // Regular files; i.e., not symlinks.
|
592 |
+
|
593 |
+
if (!unlink($_path_name)) {
|
594 |
+
throw new \Exception(sprintf(__('Unable to erase file: `%1$s`.', 'comet-cache'), $_path_name));
|
595 |
+
}
|
596 |
+
++$counter; // Increment counter for each file we erase.
|
597 |
+
|
598 |
+
break; // Break switch handler.
|
599 |
+
|
600 |
+
case 'dir': // A regular directory; i.e., not a symlink.
|
601 |
+
|
602 |
+
if (!rmdir($_path_name)) {
|
603 |
+
throw new \Exception(sprintf(__('Unable to erase dir: `%1$s`.', 'comet-cache'), $_path_name));
|
604 |
+
}
|
605 |
+
# ++$counter; // Increment counter for each directory we erase. ~ NO don't do that here.
|
606 |
+
|
607 |
+
break; // Break switch handler.
|
608 |
+
|
609 |
+
default: // Something else that is totally unexpected here.
|
610 |
+
throw new \Exception(sprintf(__('Unexpected resource type: `%1$s`.', 'comet-cache'), $_resource_type));
|
611 |
+
}
|
612 |
+
}
|
613 |
+
unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name); // Housekeeping.
|
614 |
+
|
615 |
+
if ($erase_dir_too) {
|
616 |
+
if (!rmdir($dir)) {
|
617 |
+
throw new \Exception(sprintf(__('Unable to erase directory: `%1$s`.', 'comet-cache'), $dir));
|
618 |
+
}
|
619 |
+
++$counter; // Increment counter for each directory we erase.
|
620 |
+
}
|
621 |
+
return $counter;
|
622 |
+
}
|
623 |
+
|
624 |
+
/**
|
625 |
+
* Try to erase all files/dirs from a directory (for all schemes/hosts);
|
626 |
+
* including `[SHORT_NAME]-` prefixed files; or anything else for that matter.
|
627 |
+
*
|
628 |
+
* WARNING: This does NO LOCKING and NO ATOMIC deletions.
|
629 |
+
*
|
630 |
+
* @since 150821 Improving recovery under stress.
|
631 |
+
*
|
632 |
+
* @param string $dir The directory from which to erase files/dirs.
|
633 |
+
*
|
634 |
+
* SECURITY: This directory MUST be located inside the `/wp-content/` directory.
|
635 |
+
* Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself.
|
636 |
+
* Also, it cannot be: `mu-plugins`, `themes`, or `plugins`.
|
637 |
+
* @param bool $erase_dir_too Erase parent? i.e., erase the `$dir` itself also?
|
638 |
+
*
|
639 |
+
* @return int Total files/directories erased by this routine (if any).
|
640 |
+
*/
|
641 |
+
public function tryErasingAllFilesDirsIn($dir, $erase_dir_too = false)
|
642 |
+
{
|
643 |
+
$counter = 0; // Initialize counter.
|
644 |
+
try {
|
645 |
+
$counter += $this->eraseAllFilesDirsIn($dir, $erase_dir_too);
|
646 |
+
} catch (\Exception $exception) {
|
647 |
+
// Fail softly.
|
648 |
+
}
|
649 |
+
return $counter;
|
650 |
+
}
|
651 |
+
}
|
src/includes/traits/Shared/CacheLockUtils.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait CacheLockUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Get an exclusive lock on the cache directory.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @throws \Exception If {@link \sem_get()} not available and there's
|
14 |
+
* no writable tmp directory for {@link \flock()} either.
|
15 |
+
* @throws \Exception If unable to obtain an exclusive lock by any available means.
|
16 |
+
* @return array Lock type & resource handle needed to unlock later or FALSE if disabled by filter.
|
17 |
+
*
|
18 |
+
*
|
19 |
+
* @note This call is blocking; i.e. it will not return a lock until a lock becomes possible.
|
20 |
+
* In short, this will block the caller until such time as write access becomes possible.
|
21 |
+
*/
|
22 |
+
public function cacheLock()
|
23 |
+
{
|
24 |
+
if ($this->applyWpFilters(GLOBAL_NS.'\\share::disable_cache_locking', false)
|
25 |
+
|| $this->applyWpFilters(GLOBAL_NS.'_disable_cache_locking', false)
|
26 |
+
) {
|
27 |
+
return false; // Disabled cache locking.
|
28 |
+
}
|
29 |
+
if (!($wp_config_file = $this->findWpConfigFile())) {
|
30 |
+
throw new \Exception(__('Unable to find the wp-config.php file.', 'comet-cache'));
|
31 |
+
}
|
32 |
+
$lock_type = 'flock'; // Default lock type.
|
33 |
+
$lock_type = $this->applyWpFilters(GLOBAL_NS.'\\share::cache_lock_lock_type', $lock_type);
|
34 |
+
$lock_type = $this->applyWpFilters(GLOBAL_NS.'_cache_lock_type', $lock_type);
|
35 |
+
|
36 |
+
if (!in_array($lock_type, ['flock', 'sem'], true)) {
|
37 |
+
$lock_type = 'flock'; // Default lock type.
|
38 |
+
}
|
39 |
+
if ($lock_type === 'sem' && $this->functionIsPossible('sem_get')) {
|
40 |
+
if (($ipc_key = ftok($wp_config_file, 'w'))) {
|
41 |
+
if (($resource = sem_get($ipc_key, 1)) && sem_acquire($resource)) {
|
42 |
+
return ['type' => 'sem', 'resource' => $resource];
|
43 |
+
}
|
44 |
+
}
|
45 |
+
}
|
46 |
+
if (!($tmp_dir = $this->getTmpDir())) {
|
47 |
+
throw new \Exception(__('No writable tmp directory.', 'comet-cache'));
|
48 |
+
}
|
49 |
+
$inode_key = fileinode($wp_config_file);
|
50 |
+
$mutex = $tmp_dir.'/'.SLUG_TD.'-'.$inode_key.'.lock';
|
51 |
+
|
52 |
+
if (!($resource = fopen($mutex, 'wb')) || !flock($resource, LOCK_EX)) {
|
53 |
+
throw new \Exception(__('Unable to obtain an exclusive lock.', 'comet-cache'));
|
54 |
+
}
|
55 |
+
|
56 |
+
@chmod($mutex, 0666); // See https://git.io/v2WAt
|
57 |
+
|
58 |
+
return ['type' => 'flock', 'resource' => $resource];
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Release an exclusive lock on the cache directory.
|
63 |
+
*
|
64 |
+
* @since 150422 Rewrite. Updated 151002 to remove the `array` typecast.
|
65 |
+
*
|
66 |
+
* @param array|mixed $lock Type & resource.
|
67 |
+
*/
|
68 |
+
public function cacheUnlock($lock)
|
69 |
+
{
|
70 |
+
if (!is_array($lock)) {
|
71 |
+
return; // Not possible.
|
72 |
+
// Or, they disabled cache locking.
|
73 |
+
}
|
74 |
+
if (empty($lock['type']) || empty($lock['resource'])) {
|
75 |
+
return; // Not possible.
|
76 |
+
}
|
77 |
+
if (!is_resource($lock['resource'])) {
|
78 |
+
return; // Not possible.
|
79 |
+
}
|
80 |
+
if ($lock['type'] === 'sem') {
|
81 |
+
sem_release($lock['resource']);
|
82 |
+
} elseif ($lock['type'] === 'flock') {
|
83 |
+
flock($lock['resource'], LOCK_UN);
|
84 |
+
fclose($lock['resource']);
|
85 |
+
}
|
86 |
+
}
|
87 |
+
}
|
src/includes/traits/Shared/CachePathUtils.php
ADDED
@@ -0,0 +1,358 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait CachePathUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Cache-path suffix frag (regex).
|
10 |
+
*
|
11 |
+
* @since 151220 Enhancing translation support.
|
12 |
+
*
|
13 |
+
* @param string $regex_suffix_frag Existing regex suffix frag?
|
14 |
+
*
|
15 |
+
* @return string Cache-path suffix frag (regex).
|
16 |
+
*/
|
17 |
+
public function cachePathRegexSuffixFrag($regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG)
|
18 |
+
{
|
19 |
+
if ($regex_suffix_frag === $this::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) {
|
20 |
+
return $this->cachePathRegexDefaultSuffixFrag();
|
21 |
+
}
|
22 |
+
return (string) $regex_suffix_frag;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Default cache-path suffix frag (regex).
|
27 |
+
*
|
28 |
+
* @since 151220 Enhancing translation support.
|
29 |
+
*
|
30 |
+
* @return string Default cache-path suffix frag (regex).
|
31 |
+
*
|
32 |
+
* @TODO Use conditional to detect the AMP plugin (e.g., `isAmpInstalled()`) to avoid edge cases with the `|\/amp` regex here
|
33 |
+
*/
|
34 |
+
public function cachePathRegexDefaultSuffixFrag()
|
35 |
+
{
|
36 |
+
if ($this->isPlugin() && !empty($GLOBALS['wp_rewrite'])) {
|
37 |
+
$pagination_base = $GLOBALS['wp_rewrite']->pagination_base;
|
38 |
+
$comments_pagination_base = $GLOBALS['wp_rewrite']->comments_pagination_base;
|
39 |
+
return '(?:\/index|\/amp)?(?:\.|\/(?:'.preg_quote($pagination_base, '/').'\/[0-9]+|'.preg_quote($comments_pagination_base, '/').'\-[0-9]+)[.\/])';
|
40 |
+
} else {
|
41 |
+
return '(?:\/index|\/amp)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])';
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Converts a URL into a `cache/path` based on input `$flags`.
|
47 |
+
*
|
48 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
49 |
+
*
|
50 |
+
* @param string $url The input URL to convert.
|
51 |
+
* @param string $with_user_token Optional user token (if applicable).
|
52 |
+
* @param string $with_version_salt Optional version salt (if applicable).
|
53 |
+
* @param int $flags Optional flags. A bitmask via `$this::CACHE_PATH_*` constants.
|
54 |
+
*
|
55 |
+
* @return string The resulting `cache/path` based on the input `$url` & `$flags`.
|
56 |
+
*/
|
57 |
+
public function buildCachePath($url, $with_user_token = '', $with_version_salt = '', $flags = self::CACHE_PATH_DEFAULT)
|
58 |
+
{
|
59 |
+
# Force parameter types.
|
60 |
+
|
61 |
+
$url = trim((string) $url);
|
62 |
+
$with_user_token = trim((string) $with_user_token);
|
63 |
+
$with_version_salt = trim((string) $with_version_salt);
|
64 |
+
|
65 |
+
# Initialize variables.
|
66 |
+
|
67 |
+
$is_multisite = is_multisite();
|
68 |
+
$can_consider_domain_mapping = $is_multisite && $this->canConsiderDomainMapping();
|
69 |
+
$cache_path = ''; // Initialize cache path being built here.
|
70 |
+
|
71 |
+
# Deal w/ domain mapping considerations.
|
72 |
+
|
73 |
+
if ($flags & $this::CACHE_PATH_CONSIDER_DOMAIN_MAPPING && $is_multisite && $can_consider_domain_mapping) {
|
74 |
+
if ($flags & $this::CACHE_PATH_REVERSE_DOMAIN_MAPPING) {
|
75 |
+
$url = $this->domainMappingReverseUrlFilter($url);
|
76 |
+
} else {
|
77 |
+
$url = $this->domainMappingUrlFilter($url);
|
78 |
+
}
|
79 |
+
}
|
80 |
+
# Validate the URL we have now.
|
81 |
+
|
82 |
+
if (!$url || !($url_parts = $this->parseUrl($url))) {
|
83 |
+
return $cache_path = ''; // Not possible.
|
84 |
+
}
|
85 |
+
if (empty($url_parts['scheme']) || $url_parts['scheme'] === '//') {
|
86 |
+
return $cache_path = ''; // Not possible.
|
87 |
+
}
|
88 |
+
if (empty($url_parts['host'])) {
|
89 |
+
return $cache_path = ''; // Not possible.
|
90 |
+
}
|
91 |
+
# Initialize additional variables; based on the parsed URL.
|
92 |
+
|
93 |
+
$is_url_domain_mapped = $is_multisite && $can_consider_domain_mapping && $this->domainMappingBlogId($url);
|
94 |
+
$host_base_dir_tokens = $this->hostBaseDirTokens(false, $is_url_domain_mapped, !empty($url_parts['path']) ? $url_parts['path'] : '/');
|
95 |
+
|
96 |
+
$is_a_multisite_base_dir = $is_multisite && $host_base_dir_tokens && $host_base_dir_tokens !== '/' // Check?
|
97 |
+
&& stripos(!empty($url_parts['path']) ? rtrim($url_parts['path'], '/').'/' : '/', $host_base_dir_tokens) === 0;
|
98 |
+
|
99 |
+
$is_a_multisite_base_dir_root = $is_multisite && $is_a_multisite_base_dir // Save time by using the previous check here.
|
100 |
+
&& strcasecmp(trim($host_base_dir_tokens, '/'), trim(!empty($url_parts['path']) ? $url_parts['path'] : '/', '/')) === 0;
|
101 |
+
|
102 |
+
# Build and return the cache path.
|
103 |
+
|
104 |
+
if (!($flags & $this::CACHE_PATH_NO_SCHEME)) {
|
105 |
+
$cache_path .= $url_parts['scheme'].'/';
|
106 |
+
}
|
107 |
+
if (!($flags & $this::CACHE_PATH_NO_HOST)) {
|
108 |
+
$cache_path .= $url_parts['host'].'/';
|
109 |
+
|
110 |
+
// Put multisite sub-roots into a host directory of their own.
|
111 |
+
// e.g., `example-com[[-base]-child1]` instead of `example-com`.
|
112 |
+
if ($is_a_multisite_base_dir && $host_base_dir_tokens && $host_base_dir_tokens !== '/') {
|
113 |
+
$host_base_dir_suffix = preg_replace('/[^a-z0-9.]/i', '-', rtrim($host_base_dir_tokens, '/'));
|
114 |
+
$cache_path = rtrim($cache_path, '/').$host_base_dir_suffix.'/';
|
115 |
+
}
|
116 |
+
}
|
117 |
+
if (!($flags & $this::CACHE_PATH_NO_PATH)) {
|
118 |
+
if (isset($url_parts['path'][201])) {
|
119 |
+
$_path_tmp = '/'; // Initialize tmp path.
|
120 |
+
foreach (explode('/', $url_parts['path']) as $_path_component) {
|
121 |
+
if (!isset($_path_component[0])) {
|
122 |
+
continue; // Empty.
|
123 |
+
}
|
124 |
+
if (isset($_path_component[201])) {
|
125 |
+
$_path_component = 'lpc-'.sha1($_path_component);
|
126 |
+
}
|
127 |
+
$_path_tmp .= $_path_component.'/';
|
128 |
+
}
|
129 |
+
$url_parts['path'] = $_path_tmp; // Shorter components.
|
130 |
+
unset($_path_component, $_path_tmp); // Housekeeping.
|
131 |
+
|
132 |
+
if (isset($url_parts['path'][2001])) {
|
133 |
+
$url_parts['path'] = '/lp-'.sha1($url_parts['path']).'/';
|
134 |
+
}
|
135 |
+
} // Now add the path and check for a possible root `index/` suffix.
|
136 |
+
if (!empty($url_parts['path']) && strlen($url_parts['path'] = trim($url_parts['path'], '\\/'." \t\n\r\0\x0B"))) {
|
137 |
+
$cache_path .= $url_parts['path'].'/'; // Add the path as it exists.
|
138 |
+
|
139 |
+
if (!($flags & $this::CACHE_PATH_NO_PATH_INDEX) && $is_multisite && $is_a_multisite_base_dir_root) {
|
140 |
+
// We should build an `index/` when this ends with a multisite [[/base]/child1] root.
|
141 |
+
// e.g., `http/example-com[[-base]-child1][[/base]/child1]` is a root directory.
|
142 |
+
$cache_path .= 'index/'; // Use an index suffix.
|
143 |
+
}
|
144 |
+
} elseif (!($flags & $this::CACHE_PATH_NO_PATH_INDEX)) {
|
145 |
+
$cache_path .= 'index/';
|
146 |
+
}
|
147 |
+
}
|
148 |
+
if ($this->isExtensionLoaded('mbstring') && mb_check_encoding($cache_path, 'UTF-8')) {
|
149 |
+
$cache_path = mb_strtolower($cache_path, 'UTF-8');
|
150 |
+
}
|
151 |
+
$cache_path = str_replace('.', '-', strtolower($cache_path));
|
152 |
+
|
153 |
+
if (!($flags & $this::CACHE_PATH_NO_QUV)) {
|
154 |
+
if (!($flags & $this::CACHE_PATH_NO_QUERY)) {
|
155 |
+
if (isset($url_parts['query']) && $url_parts['query'] !== '') {
|
156 |
+
$cache_path = rtrim($cache_path, '/').'.q/'.md5($url_parts['query']).'/';
|
157 |
+
}
|
158 |
+
}
|
159 |
+
if (!($flags & $this::CACHE_PATH_NO_USER)) {
|
160 |
+
if ($with_user_token !== '') {
|
161 |
+
$cache_path = rtrim($cache_path, '/').'.u/'.str_replace(['/', '\\'], '-', $with_user_token).'/';
|
162 |
+
}
|
163 |
+
}
|
164 |
+
if (!($flags & $this::CACHE_PATH_NO_VSALT)) {
|
165 |
+
if ($with_version_salt !== '') {
|
166 |
+
$cache_path = rtrim($cache_path, '/').'.v/'.str_replace(['/', '\\'], '-', $with_version_salt).'/';
|
167 |
+
}
|
168 |
+
}
|
169 |
+
}
|
170 |
+
$cache_path = trim(preg_replace(['/\/+/', '/\.+/'], ['/', '.'], $cache_path), '/');
|
171 |
+
|
172 |
+
if ($flags & $this::CACHE_PATH_ALLOW_WD_REGEX) {
|
173 |
+
$cache_path = preg_replace('/[^a-z0-9\/.*\^$]/i', '-', $cache_path);
|
174 |
+
} elseif ($flags & $this::CACHE_PATH_ALLOW_WILDCARDS) {
|
175 |
+
$cache_path = preg_replace('/[^a-z0-9\/.*]/i', '-', $cache_path);
|
176 |
+
} else {
|
177 |
+
$cache_path = preg_replace('/[^a-z0-9\/.]/i', '-', $cache_path);
|
178 |
+
}
|
179 |
+
if (!($flags & $this::CACHE_PATH_NO_EXT)) {
|
180 |
+
$cache_path .= '.html';
|
181 |
+
}
|
182 |
+
return $cache_path;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
187 |
+
*
|
188 |
+
* @since 151114 Updated to support an arbitrary URL instead of a regex frag.
|
189 |
+
*
|
190 |
+
* @param string $url The input URL to convert. This CAN be left empty when necessary.
|
191 |
+
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
192 |
+
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
193 |
+
* @param string $regex_suffix_frag Regex fragment to come after the `$regex_frag`.
|
194 |
+
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
195 |
+
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
196 |
+
* See also: {@link $this::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
197 |
+
*
|
198 |
+
* @return string Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
199 |
+
*/
|
200 |
+
public function buildCachePathRegex($url, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG)
|
201 |
+
{
|
202 |
+
$url = trim((string) $url);
|
203 |
+
$regex_suffix_frag = $this->cachePathRegexSuffixFrag($regex_suffix_frag);
|
204 |
+
$cache_path_regex = ''; // Initialize regex.
|
205 |
+
|
206 |
+
if ($url) {
|
207 |
+
$flags = $this::CACHE_PATH_NO_SCHEME // Scheme added below.
|
208 |
+
| $this::CACHE_PATH_NO_PATH_INDEX | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT;
|
209 |
+
$cache_path = $this->buildCachePath($url, '', '', $flags); // Without the scheme.
|
210 |
+
$cache_path_regex = isset($cache_path[0]) ? '\/https?\/'.preg_quote($cache_path, '/') : '';
|
211 |
+
}
|
212 |
+
return '/^'.$cache_path_regex.$regex_suffix_frag.'/i';
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
217 |
+
*
|
218 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
219 |
+
*
|
220 |
+
* @param string $url The input URL to convert. This CAN be left empty when necessary.
|
221 |
+
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
222 |
+
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
223 |
+
* @param string $regex_suffix_frag Regex fragment to come after the relative cache/path regex frag.
|
224 |
+
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
225 |
+
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
226 |
+
* See also: {@link $this::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
227 |
+
*
|
228 |
+
* @return string Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
229 |
+
*/
|
230 |
+
public function buildHostCachePathRegex($url, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG)
|
231 |
+
{
|
232 |
+
$url = trim((string) $url);
|
233 |
+
$regex_suffix_frag = $this->cachePathRegexSuffixFrag($regex_suffix_frag);
|
234 |
+
$abs_relative_cache_path_regex = ''; // Initialize regex.
|
235 |
+
$is_url_domain_mapped = false; // Initialize.
|
236 |
+
|
237 |
+
if ($url) {
|
238 |
+
if (is_multisite() && $this->canConsiderDomainMapping()) {
|
239 |
+
// Shortest possible URI; i.e., consider domain mapping.
|
240 |
+
$url = $this->domainMappingUrlFilter($url);
|
241 |
+
$is_url_domain_mapped = $url && $this->domainMappingBlogId($url);
|
242 |
+
}
|
243 |
+
if ($url && ($url_parts = $this->parseUrl($url)) && !empty($url_parts['host'])) {
|
244 |
+
$flags = $this::CACHE_PATH_NO_SCHEME | $this::CACHE_PATH_NO_HOST
|
245 |
+
| $this::CACHE_PATH_NO_PATH_INDEX | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT;
|
246 |
+
|
247 |
+
$host_base_dir_tokens = $this->hostBaseDirTokens(false, $is_url_domain_mapped, !empty($url_parts['path']) ? $url_parts['path'] : '/');
|
248 |
+
$host_url = rtrim('http://'.$url_parts['host'].$host_base_dir_tokens, '/');
|
249 |
+
$host_cache_path = $this->buildCachePath($host_url, '', '', $flags);
|
250 |
+
|
251 |
+
$cache_path = $this->buildCachePath($url, '', '', $flags);
|
252 |
+
$relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $cache_path);
|
253 |
+
|
254 |
+
$abs_relative_cache_path = isset($relative_cache_path[0]) ? '/'.$relative_cache_path : '';
|
255 |
+
$abs_relative_cache_path_regex = isset($abs_relative_cache_path[0]) ? preg_quote($abs_relative_cache_path, '/') : '';
|
256 |
+
}
|
257 |
+
}
|
258 |
+
return '/^'.$abs_relative_cache_path_regex.$regex_suffix_frag.'/i';
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
263 |
+
*
|
264 |
+
* @since 151114 Improving watered-down regex syntax.
|
265 |
+
*
|
266 |
+
* @param string $url The input URL to convert. This CAN be left empty when necessary.
|
267 |
+
* This may also contain watered-down regex; i.e., `*^$` characters are OK here.
|
268 |
+
* However, `^$` are discarded, as they are unnecessary in this context.
|
269 |
+
*
|
270 |
+
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
271 |
+
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
272 |
+
* @param string $regex_suffix_frag Regex fragment to come after the `$regex_frag`.
|
273 |
+
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
274 |
+
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
275 |
+
* See also: {@link $this::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
276 |
+
*
|
277 |
+
* @return string Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
278 |
+
*/
|
279 |
+
public function buildCachePathRegexFromWcUrl($url, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG)
|
280 |
+
{
|
281 |
+
$url = trim((string) $url, '^$');
|
282 |
+
$regex_suffix_frag = $this->cachePathRegexSuffixFrag($regex_suffix_frag);
|
283 |
+
$cache_path_regex = ''; // Initialize regex.
|
284 |
+
|
285 |
+
if ($url) { // After `^$` trimming above.
|
286 |
+
$flags = $this::CACHE_PATH_ALLOW_WILDCARDS | $this::CACHE_PATH_NO_SCHEME
|
287 |
+
| $this::CACHE_PATH_NO_PATH_INDEX | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT;
|
288 |
+
$cache_path = $this->buildCachePath($url, '', '', $flags); // Without the scheme.
|
289 |
+
$cache_path_regex = isset($cache_path[0]) ? '\/https?\/'.$this->wdRegexToActualRegexFrag($cache_path) : '';
|
290 |
+
}
|
291 |
+
return '/^'.$cache_path_regex.$regex_suffix_frag.'/i';
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
296 |
+
*
|
297 |
+
* @since 150422 Rewrite. Updated 151002 w/ multisite compat. improvements.
|
298 |
+
*
|
299 |
+
* @param string $uris A line-delimited list of URIs. These may contain `*^$` also.
|
300 |
+
* However, `^$` are discarded, as they are unnecessary in this context.
|
301 |
+
* @param string $regex_suffix_frag Regex fragment to come after each relative cache/path.
|
302 |
+
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
303 |
+
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
304 |
+
* See also: {@link $this::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
305 |
+
*
|
306 |
+
* @return string Regex pattern for a call to `deleteFilesFromHostCacheDir()`.
|
307 |
+
*/
|
308 |
+
public function buildHostCachePathRegexFragsFromWcUris($uris, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG)
|
309 |
+
{
|
310 |
+
$uris = trim((string) $uris);
|
311 |
+
$regex_suffix_frag = $this->cachePathRegexSuffixFrag($regex_suffix_frag);
|
312 |
+
|
313 |
+
$flags = $this::CACHE_PATH_ALLOW_WILDCARDS | $this::CACHE_PATH_NO_SCHEME | $this::CACHE_PATH_NO_HOST
|
314 |
+
| $this::CACHE_PATH_NO_PATH_INDEX | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT;
|
315 |
+
|
316 |
+
$host = 'doesnt-matter.foo.bar';
|
317 |
+
$host_url = rtrim('http://'.$host, '/');
|
318 |
+
$host_cache_path = $this->buildCachePath($host_url, '', '', $flags);
|
319 |
+
$uri_patterns = array_unique(preg_split('/['."\r\n".']+/', $uris, -1, PREG_SPLIT_NO_EMPTY));
|
320 |
+
|
321 |
+
foreach ($uri_patterns as $_key => &$_uri_pattern) {
|
322 |
+
if (($_uri_pattern = trim($_uri_pattern, '^$'))) {
|
323 |
+
$_cache_path = $this->buildCachePath($host_url.'/'.trim($_uri_pattern, '/'), '', '', $flags);
|
324 |
+
$_relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $_cache_path);
|
325 |
+
$_uri_pattern = $this->wdRegexToActualRegexFrag($_relative_cache_path);
|
326 |
+
}
|
327 |
+
if (!$_uri_pattern) {
|
328 |
+
unset($uri_patterns[$_key]); // Remove it.
|
329 |
+
}
|
330 |
+
}
|
331 |
+
unset($_key, $_uri_pattern, $_cache_path, $_relative_cache_path); // Housekeeping.
|
332 |
+
|
333 |
+
return $uri_patterns ? '(?:'.implode('|', array_unique($uri_patterns)).')'.$regex_suffix_frag : '';
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
338 |
+
*
|
339 |
+
* @since 151114 Moving this low-level routine into a method of a different name.
|
340 |
+
*
|
341 |
+
* @param string $regex_frag A regex fragment. This CAN be left empty when necessary.
|
342 |
+
* If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`.
|
343 |
+
* If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`.
|
344 |
+
* @param string $regex_suffix_frag Regex fragment to come after the `$regex_frag`.
|
345 |
+
* Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`.
|
346 |
+
* Note: this should NOT have delimiters; i.e. do NOT start or end with `/`.
|
347 |
+
* See also: {@link $this::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}.
|
348 |
+
*
|
349 |
+
* @return string Regex pattern for a call to `deleteFilesFromCacheDir()`.
|
350 |
+
*/
|
351 |
+
public function assembleCachePathRegex($regex_frag, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG)
|
352 |
+
{
|
353 |
+
$regex_frag = (string) $regex_frag;
|
354 |
+
$regex_suffix_frag = $this->cachePathRegexSuffixFrag($regex_suffix_frag);
|
355 |
+
|
356 |
+
return '/^'.$regex_frag.$regex_suffix_frag.'/i';
|
357 |
+
}
|
358 |
+
}
|
src/includes/traits/Shared/ConditionalUtils.php
ADDED
@@ -0,0 +1,380 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait ConditionalUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* PHP's language constructs.
|
10 |
+
*
|
11 |
+
* @type array PHP's language constructs.
|
12 |
+
* Keys are currently unimportant. Subject to change.
|
13 |
+
*
|
14 |
+
* @since 160222 First documented version.
|
15 |
+
*/
|
16 |
+
public $php_constructs = [
|
17 |
+
'die' => 'die',
|
18 |
+
'echo' => 'echo',
|
19 |
+
'empty' => 'empty',
|
20 |
+
'exit' => 'exit',
|
21 |
+
'eval' => 'eval',
|
22 |
+
'include' => 'include',
|
23 |
+
'include_once' => 'include_once',
|
24 |
+
'isset' => 'isset',
|
25 |
+
'list' => 'list',
|
26 |
+
'require' => 'require',
|
27 |
+
'require_once' => 'require_once',
|
28 |
+
'return' => 'return',
|
29 |
+
'print' => 'print',
|
30 |
+
'unset' => 'unset',
|
31 |
+
'__halt_compiler' => '__halt_compiler',
|
32 |
+
];
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Is AdvancedCache class?
|
36 |
+
*
|
37 |
+
* @since 150821 Improving multisite compat.
|
38 |
+
*
|
39 |
+
* @return bool `TRUE` if this is the AdvancedCache class.
|
40 |
+
*/
|
41 |
+
public function isAdvancedCache()
|
42 |
+
{
|
43 |
+
return $this instanceof Classes\AdvancedCache;
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Is Plugin class?
|
48 |
+
*
|
49 |
+
* @since 150821 Improving multisite compat.
|
50 |
+
*
|
51 |
+
* @return bool `TRUE` if this is the Plugin class.
|
52 |
+
*/
|
53 |
+
public function isPlugin()
|
54 |
+
{
|
55 |
+
return $this instanceof Classes\Plugin;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Is the current request method `POST`, `PUT` or `DELETE`?
|
60 |
+
*
|
61 |
+
* @since 150422 Rewrite.
|
62 |
+
*
|
63 |
+
* @return bool `TRUE` if current request method is `POST`, `PUT` or `DELETE`.
|
64 |
+
*
|
65 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
66 |
+
*/
|
67 |
+
public function isPostPutDeleteRequest()
|
68 |
+
{
|
69 |
+
if (!is_null($is = &$this->staticKey('isPostPutDeleteRequest'))) {
|
70 |
+
return $is; // Already cached this.
|
71 |
+
}
|
72 |
+
if (!empty($_POST)) {
|
73 |
+
return $is = true;
|
74 |
+
}
|
75 |
+
if (!empty($_SERVER['REQUEST_METHOD']) && is_string($_SERVER['REQUEST_METHOD'])) {
|
76 |
+
if (in_array(strtoupper($_SERVER['REQUEST_METHOD']), ['POST', 'PUT', 'DELETE'], true)) {
|
77 |
+
return $is = true;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
return $is = false;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Does the current request include an uncacheable query string?
|
85 |
+
*
|
86 |
+
* @since 151002 Improving Nginx support.
|
87 |
+
*
|
88 |
+
* @return bool True if request includes an uncacheable query string.
|
89 |
+
*
|
90 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
91 |
+
*/
|
92 |
+
public function requestContainsUncacheableQueryVars()
|
93 |
+
{
|
94 |
+
if (!is_null($is = &$this->staticKey('requestContainsUncacheableQueryVars'))) {
|
95 |
+
return $is; // Already cached this.
|
96 |
+
}
|
97 |
+
if (!empty($_GET) || !empty($_SERVER['QUERY_STRING'])) {
|
98 |
+
$_get_count = !empty($_GET) ? count($_GET) : 0;
|
99 |
+
$is_abc_only = $_get_count === 1 && isset($_GET[strtolower(SHORT_NAME).'ABC']);
|
100 |
+
$is_nginx_q_only = $_get_count === 1 && isset($_GET['q']) && $this->isNginx();
|
101 |
+
$is_ac_get_var_true = isset($_GET[strtolower(SHORT_NAME).'AC']) && filter_var($_GET[strtolower(SHORT_NAME).'AC'], FILTER_VALIDATE_BOOLEAN);
|
102 |
+
|
103 |
+
if (!$is_abc_only && !$is_nginx_q_only && !$is_ac_get_var_true) {
|
104 |
+
return $is = true;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
return $is = false;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Is the current request method is uncacheable?
|
112 |
+
*
|
113 |
+
* @since 150422 Rewrite.
|
114 |
+
*
|
115 |
+
* @return bool `TRUE` if current request method is uncacheable.
|
116 |
+
*
|
117 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
118 |
+
*/
|
119 |
+
public function isUncacheableRequestMethod()
|
120 |
+
{
|
121 |
+
if (!is_null($is = &$this->staticKey('isUncacheableRequestMethod'))) {
|
122 |
+
return $is; // Already cached this.
|
123 |
+
}
|
124 |
+
if (!empty($_POST)) {
|
125 |
+
return $is = true;
|
126 |
+
}
|
127 |
+
if (!empty($_SERVER['REQUEST_METHOD']) && is_string($_SERVER['REQUEST_METHOD'])) {
|
128 |
+
if (!in_array(strtoupper($_SERVER['REQUEST_METHOD']), ['GET'], true)) {
|
129 |
+
return $is = true;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
return $is = false;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Should the current user should be considered a logged-in user?
|
137 |
+
*
|
138 |
+
* @since 150422 Rewrite.
|
139 |
+
*
|
140 |
+
* @return bool `TRUE` if current user should be considered a logged-in user.
|
141 |
+
*
|
142 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
143 |
+
*/
|
144 |
+
public function isLikeUserLoggedIn()
|
145 |
+
{
|
146 |
+
if (!is_null($is = &$this->staticKey('isLikeUserLoggedIn'))) {
|
147 |
+
return $is; // Already cached this.
|
148 |
+
}
|
149 |
+
if (defined('SID') && SID) {
|
150 |
+
return $is = true; // Session ID.
|
151 |
+
}
|
152 |
+
if (empty($_COOKIE)) {
|
153 |
+
return $is = false; // No cookies.
|
154 |
+
}
|
155 |
+
$regex_logged_in_cookies = '/^'; // Initialize.
|
156 |
+
|
157 |
+
if (defined('LOGGED_IN_COOKIE') && LOGGED_IN_COOKIE) {
|
158 |
+
$regex_logged_in_cookies .= preg_quote(LOGGED_IN_COOKIE, '/');
|
159 |
+
} else { // Use the default hard-coded cookie prefix.
|
160 |
+
$regex_logged_in_cookies .= 'wordpress_logged_in_';
|
161 |
+
}
|
162 |
+
$regex_logged_in_cookies .= '|comment_author_';
|
163 |
+
$regex_logged_in_cookies .= '|wp[_\-]postpass_';
|
164 |
+
|
165 |
+
$regex_logged_in_cookies .= '/'; // Close regex.
|
166 |
+
|
167 |
+
foreach ($_COOKIE as $_key => $_value) {
|
168 |
+
if ($_value && preg_match($regex_logged_in_cookies, $_key)) {
|
169 |
+
return $is = true; // Like a logged-in user.
|
170 |
+
}
|
171 |
+
}
|
172 |
+
unset($_key, $_value); // Housekeeping.
|
173 |
+
|
174 |
+
return $is = false;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Are we in a LOCALHOST environment?
|
179 |
+
*
|
180 |
+
* @since 150422 Rewrite.
|
181 |
+
*
|
182 |
+
* @return bool `TRUE` if we are in a LOCALHOST environment.
|
183 |
+
*
|
184 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
185 |
+
*/
|
186 |
+
public function isLocalhost()
|
187 |
+
{
|
188 |
+
if (!is_null($is = &$this->staticKey('isLocalhost'))) {
|
189 |
+
return $is; // Already cached this.
|
190 |
+
}
|
191 |
+
if (defined('LOCALHOST')) {
|
192 |
+
return $is = (boolean) LOCALHOST;
|
193 |
+
}
|
194 |
+
if (preg_match('/\b(?:localhost|127\.0\.0\.1)\b/i', $this->hostToken())) {
|
195 |
+
return $is = true;
|
196 |
+
}
|
197 |
+
return $is = false;
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Is the current request for a feed?
|
204 |
+
*
|
205 |
+
* @since 150422 Rewrite.
|
206 |
+
*
|
207 |
+
* @return bool `TRUE` if the current request is for a feed.
|
208 |
+
*
|
209 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
210 |
+
*/
|
211 |
+
public function isFeed()
|
212 |
+
{
|
213 |
+
if (!is_null($is = &$this->staticKey('isFeed'))) {
|
214 |
+
return $is; // Already cached this.
|
215 |
+
}
|
216 |
+
if (isset($_REQUEST['feed'])) {
|
217 |
+
return $is = true;
|
218 |
+
}
|
219 |
+
if (!empty($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])) {
|
220 |
+
if (preg_match('/\/feed(?:[\/?]|$)/', $_SERVER['REQUEST_URI'])) {
|
221 |
+
return $is = true;
|
222 |
+
}
|
223 |
+
}
|
224 |
+
return $is = false;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Is a document/string an HTML/XML doc; or no?
|
229 |
+
*
|
230 |
+
* @since 150422 Rewrite.
|
231 |
+
*
|
232 |
+
* @param string $doc Input string/document to check.
|
233 |
+
*
|
234 |
+
* @return bool True if `$doc` is an HTML/XML doc type.
|
235 |
+
*/
|
236 |
+
public function isHtmlXmlDoc($doc)
|
237 |
+
{
|
238 |
+
$doc = trim((string) $doc);
|
239 |
+
$doc_hash = sha1($doc);
|
240 |
+
|
241 |
+
if (!is_null($is = &$this->staticKey('isHtmlXmlDoc', $doc_hash))) {
|
242 |
+
return $is; // Already cached this.
|
243 |
+
}
|
244 |
+
if (stripos($doc, '</html>') !== false) {
|
245 |
+
return $is = true;
|
246 |
+
}
|
247 |
+
if (stripos($doc, '<?xml') === 0) {
|
248 |
+
return $is = true;
|
249 |
+
}
|
250 |
+
return $is = false;
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Does the current request have a cacheable content type?
|
255 |
+
*
|
256 |
+
* @since 150422 Rewrite.
|
257 |
+
*
|
258 |
+
* @return bool `TRUE` if the current request has a cacheable content type.
|
259 |
+
*
|
260 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
261 |
+
*
|
262 |
+
* @warning Do NOT call upon this method until the end of a script execution.
|
263 |
+
*/
|
264 |
+
public function hasACacheableContentType()
|
265 |
+
{
|
266 |
+
if (!is_null($is = &$this->staticKey('hasACacheableContentType'))) {
|
267 |
+
return $is; // Already cached this.
|
268 |
+
}
|
269 |
+
foreach ($this->headersList() as $_key => $_header) {
|
270 |
+
if (stripos($_header, 'Content-Type:') === 0) {
|
271 |
+
$content_type = $_header; // Last one.
|
272 |
+
}
|
273 |
+
}
|
274 |
+
unset($_key, $_header); // Housekeeping.
|
275 |
+
|
276 |
+
if (isset($content_type[0]) && stripos($content_type, 'html') === false
|
277 |
+
&& stripos($content_type, 'xml') === false && stripos($content_type, GLOBAL_NS) === false
|
278 |
+
) {
|
279 |
+
return $is = false; // Do NOT cache data sent by scripts serving other MIME types.
|
280 |
+
}
|
281 |
+
return $is = true;
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Does the current request have a cacheable HTTP status code?
|
286 |
+
*
|
287 |
+
* @since 150422 Rewrite.
|
288 |
+
*
|
289 |
+
* @return bool `TRUE` if the current request has a cacheable HTTP status code.
|
290 |
+
*
|
291 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
292 |
+
*
|
293 |
+
* @warning Do NOT call upon this method until the end of a script execution.
|
294 |
+
*/
|
295 |
+
public function hasACacheableStatus()
|
296 |
+
{
|
297 |
+
if (!is_null($is = &$this->staticKey('hasACacheableStatus'))) {
|
298 |
+
return $is; // Already cached this.
|
299 |
+
}
|
300 |
+
if (($http_status = (string) $this->httpStatus()) && $http_status[0] !== '2' && $http_status !== '404') {
|
301 |
+
return $is = false; // A non-2xx & non-404 status code.
|
302 |
+
}
|
303 |
+
foreach ($this->headersList() as $_key => $_header) {
|
304 |
+
if (preg_match('/^(?:Retry\-After\:\s+(?P<retry>.+)|Status\:\s+(?P<status>[0-9]+)|HTTP\/[0-9]+(?:\.[0-9]+)?\s+(?P<http_status>[0-9]+))/i', $_header, $_m)) {
|
305 |
+
if (!empty($_m['retry']) || (!empty($_m['status']) && $_m['status'][0] !== '2' && $_m['status'] !== '404')
|
306 |
+
|| (!empty($_m['http_status']) && $_m['http_status'][0] !== '2' && $_m['http_status'] !== '404')
|
307 |
+
) {
|
308 |
+
return $is = false; // Not a cacheable status.
|
309 |
+
}
|
310 |
+
}
|
311 |
+
}
|
312 |
+
unset($_key, $_header); // Housekeeping.
|
313 |
+
|
314 |
+
return $is = true;
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Checks if a PHP extension is loaded up.
|
319 |
+
*
|
320 |
+
* @since 150422 Rewrite.
|
321 |
+
*
|
322 |
+
* @param string $extension A PHP extension slug (i.e. extension name).
|
323 |
+
*
|
324 |
+
* @return bool `TRUE` if the extension is loaded.
|
325 |
+
*
|
326 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
327 |
+
*/
|
328 |
+
public function isExtensionLoaded($extension)
|
329 |
+
{
|
330 |
+
$extension = (string) $extension;
|
331 |
+
|
332 |
+
if (!is_null($is = &$this->staticKey('isExtensionLoaded', $extension))) {
|
333 |
+
return $is; // Already cached this.
|
334 |
+
}
|
335 |
+
return $is = (boolean) extension_loaded($extension);
|
336 |
+
}
|
337 |
+
|
338 |
+
/**
|
339 |
+
* Is a particular function possible in every way?
|
340 |
+
*
|
341 |
+
* @since 150422 Rewrite.
|
342 |
+
*
|
343 |
+
* @param string $function A PHP function (or user function) to check.
|
344 |
+
*
|
345 |
+
* @return string `TRUE` if the function is possible.
|
346 |
+
*
|
347 |
+
* @note This checks (among other things) if the function exists and that it's callable.
|
348 |
+
* It also checks the currently configured `disable_functions` and `suhosin.executor.func.blacklist`.
|
349 |
+
*/
|
350 |
+
public function functionIsPossible($function)
|
351 |
+
{
|
352 |
+
$function = (string) $function;
|
353 |
+
|
354 |
+
if (!is_null($is = &$this->staticKey('functionIsPossible', $function))) {
|
355 |
+
return $is; // Already cached this.
|
356 |
+
}
|
357 |
+
if (is_null($disabled_functions = &$this->staticKey('functionIsPossible_disabled_functions'))) {
|
358 |
+
$disabled_functions = []; // Initialize disabled/blacklisted functions.
|
359 |
+
|
360 |
+
if (($disable_functions = trim(ini_get('disable_functions')))) {
|
361 |
+
$disabled_functions = array_merge($disabled_functions, preg_split('/[\s;,]+/', strtolower($disable_functions), -1, PREG_SPLIT_NO_EMPTY));
|
362 |
+
}
|
363 |
+
if (($blacklist_functions = trim(ini_get('suhosin.executor.func.blacklist')))) {
|
364 |
+
$disabled_functions = array_merge($disabled_functions, preg_split('/[\s;,]+/', strtolower($blacklist_functions), -1, PREG_SPLIT_NO_EMPTY));
|
365 |
+
}
|
366 |
+
if (filter_var(ini_get('suhosin.executor.disable_eval'), FILTER_VALIDATE_BOOLEAN)) {
|
367 |
+
$disabled_functions = array_merge($disabled_functions, ['eval']);
|
368 |
+
}
|
369 |
+
}
|
370 |
+
if (!function_exists($function) || !is_callable($function)) {
|
371 |
+
if (!in_array($function, $this->php_constructs, true)) { // A language construct
|
372 |
+
return $is = false; // Not possible.
|
373 |
+
}
|
374 |
+
}
|
375 |
+
if ($disabled_functions && in_array(strtolower($function), $disabled_functions, true)) {
|
376 |
+
return $is = false; // Not possible.
|
377 |
+
}
|
378 |
+
return $is = true;
|
379 |
+
}
|
380 |
+
}
|
src/includes/traits/Shared/DomainMappingUtils.php
ADDED
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait DomainMappingUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Can consider domain mapping?
|
10 |
+
*
|
11 |
+
* @since 150821 Improving multisite compat.
|
12 |
+
*
|
13 |
+
* @return bool `TRUE` if we can consider domain mapping.
|
14 |
+
*
|
15 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
16 |
+
*/
|
17 |
+
public function canConsiderDomainMapping()
|
18 |
+
{
|
19 |
+
if (!is_null($can = &$this->staticKey('canConsiderDomainMapping'))) {
|
20 |
+
return $can; // Already cached this.
|
21 |
+
}
|
22 |
+
if (!$this->isAdvancedCache() && is_multisite() && $this->hostBaseToken() === '/'
|
23 |
+
&& defined('SUNRISE_LOADED') && SUNRISE_LOADED && !empty($GLOBALS['dm_domain'])
|
24 |
+
) {
|
25 |
+
return $can = true; // Can consider.
|
26 |
+
}
|
27 |
+
return $can = false; // Cannot consider.
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Domain mapping?
|
32 |
+
*
|
33 |
+
* @since 150821 Improving multisite compat.
|
34 |
+
*
|
35 |
+
* @return int Domain mapping ID; else `0` (false).
|
36 |
+
*
|
37 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
38 |
+
*/
|
39 |
+
public function isDomainMapping()
|
40 |
+
{
|
41 |
+
if (!is_null($is = &$this->staticKey('isDomainMapping'))) {
|
42 |
+
return $is; // Already cached this.
|
43 |
+
}
|
44 |
+
if (!$this->isAdvancedCache() && is_multisite() && $this->canConsiderDomainMapping()
|
45 |
+
&& defined('DOMAIN_MAPPING') && DOMAIN_MAPPING && !empty($GLOBALS['domain_mapping_id'])
|
46 |
+
) {
|
47 |
+
return $is = (integer) $GLOBALS['domain_mapping_id']; // Blog ID.
|
48 |
+
}
|
49 |
+
return $is = 0; // Not domain mapping.
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Filters a URL in order to apply domain mapping.
|
54 |
+
*
|
55 |
+
* @since 150821 Improving multisite compat.
|
56 |
+
*
|
57 |
+
* @param string $url The input URL to filter.
|
58 |
+
*
|
59 |
+
* @return string The filtered URL; else the original URL.
|
60 |
+
*
|
61 |
+
* @note The return value of this function is NOT cached, but inner portions are.
|
62 |
+
*/
|
63 |
+
public function domainMappingUrlFilter($url)
|
64 |
+
{
|
65 |
+
$original_url = (string) $url; // Preserve.
|
66 |
+
$url = trim((string) $url);
|
67 |
+
|
68 |
+
if (!is_multisite() || !$this->canConsiderDomainMapping()) {
|
69 |
+
return $original_url; // Not possible.
|
70 |
+
}
|
71 |
+
if (!$url || !($url_parts = $this->parseUrl($url))) {
|
72 |
+
return $original_url; // Not possible.
|
73 |
+
}
|
74 |
+
if (empty($url_parts['host'])) {
|
75 |
+
return $original_url; // Not possible.
|
76 |
+
}
|
77 |
+
$blog_domain = strtolower($url_parts['host']); // In the unfiltered URL.
|
78 |
+
$blog_path = $this->hostDirToken(false, false, !empty($url_parts['path']) ? $url_parts['path'] : '/');
|
79 |
+
|
80 |
+
if (!($blog_id = (integer) get_blog_id_from_url($blog_domain, $blog_path))) {
|
81 |
+
return $original_url; // Not possible.
|
82 |
+
}
|
83 |
+
if (!($domain = $this->domainMappingBlogDomain($blog_id)) || $domain === $blog_domain) {
|
84 |
+
return $original_url; // Not applicable.
|
85 |
+
}
|
86 |
+
$url_parts['host'] = $domain; // Filter the URL now.
|
87 |
+
if (!empty($url_parts['path']) && $url_parts['path'] !== '/') {
|
88 |
+
if (($host_base_dir_tokens = trim($this->hostBaseDirTokens(false, false, $url_parts['path']), '/'))) {
|
89 |
+
$url_parts['path'] = preg_replace('/^\/'.preg_quote($host_base_dir_tokens, '/').'(\/|$)/i', '${1}', $url_parts['path']);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
return $url = $this->unParseUrl($url_parts);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Filters a URL in order to remove domain mapping.
|
97 |
+
*
|
98 |
+
* @since 150821 Improving multisite compat.
|
99 |
+
*
|
100 |
+
* @param string $url The input URL to filter.
|
101 |
+
*
|
102 |
+
* @return string The filtered URL; else the original URL.
|
103 |
+
*
|
104 |
+
* @note The return value of this function is NOT cached, but inner portions are.
|
105 |
+
*/
|
106 |
+
public function domainMappingReverseUrlFilter($url)
|
107 |
+
{
|
108 |
+
$original_url = (string) $url; // Preserve.
|
109 |
+
$url = trim((string) $url);
|
110 |
+
|
111 |
+
if (!is_multisite() || !$this->canConsiderDomainMapping()) {
|
112 |
+
return $original_url; // Not possible.
|
113 |
+
}
|
114 |
+
if (!$url || !($url_parts = $this->parseUrl($url))) {
|
115 |
+
return $original_url; // Not possible.
|
116 |
+
}
|
117 |
+
if (empty($url_parts['host'])) {
|
118 |
+
return $original_url; // Not possible.
|
119 |
+
}
|
120 |
+
if (!($blog_id = $this->domainMappingBlogId('', $url_parts['host']))) {
|
121 |
+
return $original_url; // No a domain in the map.
|
122 |
+
}
|
123 |
+
if (!($blog_details = $this->blogDetails($blog_id))) {
|
124 |
+
return $original_url; // Not possible.
|
125 |
+
}
|
126 |
+
$url_parts['host'] = $blog_details->domain; // Filter the URL now.
|
127 |
+
if (($host_base_dir_tokens = trim($this->hostBaseDirTokens(false, false, $blog_details->path), '/'))) {
|
128 |
+
$url_parts['path'] = '/'.$host_base_dir_tokens.'/'.ltrim(@$url_parts['path'], '/');
|
129 |
+
}
|
130 |
+
return $url = $this->unParseUrl($url_parts);
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Converts a host into a mapped blog ID.
|
135 |
+
*
|
136 |
+
* @since 150821 Improving multisite compat.
|
137 |
+
*
|
138 |
+
* @param string $url URL containing the domain to convert.
|
139 |
+
* @param string $domain The domain to convert. Override URL is provided.
|
140 |
+
*
|
141 |
+
* @return int The mapped blog ID; else `0` on failure.
|
142 |
+
*
|
143 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
144 |
+
*/
|
145 |
+
public function domainMappingBlogId($url = '', $domain = '')
|
146 |
+
{
|
147 |
+
$domain = (string) $domain;
|
148 |
+
$url = $domain ? '' : (string) $url;
|
149 |
+
|
150 |
+
if (!is_multisite() || !$this->canConsiderDomainMapping()) {
|
151 |
+
return 0; // Not possible/applicable.
|
152 |
+
}
|
153 |
+
if ($url === 'network' || $domain === 'network') {
|
154 |
+
$domain = (string) get_current_site()->domain;
|
155 |
+
}
|
156 |
+
if (!$domain && $url && $url !== 'network') {
|
157 |
+
$domain = $this->parseUrl($url, PHP_URL_HOST);
|
158 |
+
}
|
159 |
+
if (!$url && !$domain && ($blog_details = $this->blogDetails())) {
|
160 |
+
$domain = $blog_details->domain;
|
161 |
+
}
|
162 |
+
$domain = strtolower(preg_replace('/^www\./i', '', $domain));
|
163 |
+
|
164 |
+
if (!$domain || strpos($domain, '.') === false) {
|
165 |
+
return 0; // Not possible.
|
166 |
+
}
|
167 |
+
if (!is_null($blog_id = &$this->staticKey('domainMappingBlogId', $domain))) {
|
168 |
+
return $blog_id; // Already cached this.
|
169 |
+
}
|
170 |
+
$wpdb = $this->wpdb(); // WordPress database class.
|
171 |
+
$suppressing_errors = $wpdb->suppress_errors(); // In case table has not been created yet.
|
172 |
+
$enforcing_primary_domain = !get_site_option('dm_no_primary_domain'); // Enforcing primary domain?
|
173 |
+
|
174 |
+
if (!$enforcing_primary_domain) {
|
175 |
+
$blog_id = (integer) $wpdb->get_var('SELECT `blog_id` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `domain` IN(\''.esc_sql('www.'.$domain).'\', \''.esc_sql($domain).'\') ORDER BY CHAR_LENGTH(`domain`) DESC, `active` DESC LIMIT 1');
|
176 |
+
} else {
|
177 |
+
$blog_id = (integer) $wpdb->get_var('SELECT `blog_id` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `domain` IN(\''.esc_sql('www.'.$domain).'\', \''.esc_sql($domain).'\') AND `active` = \'1\' ORDER BY CHAR_LENGTH(`domain`) DESC LIMIT 1');
|
178 |
+
}
|
179 |
+
$wpdb->suppress_errors($suppressing_errors); // Restore.
|
180 |
+
|
181 |
+
return $blog_id = (integer) $blog_id;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Converts a blog ID into a mapped domain.
|
186 |
+
*
|
187 |
+
* @since 150821 Improving multisite compat.
|
188 |
+
*
|
189 |
+
* @param int $blog_id The blog ID.
|
190 |
+
* @param bool $fallback Fallback on blog's domain?
|
191 |
+
*
|
192 |
+
* @return string The mapped domain, else an empty string.
|
193 |
+
*
|
194 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
195 |
+
*/
|
196 |
+
public function domainMappingBlogDomain($blog_id = 0, $fallback = false)
|
197 |
+
{
|
198 |
+
if (!is_multisite() || !$this->canConsiderDomainMapping()) {
|
199 |
+
return ''; // Not possible/applicable.
|
200 |
+
}
|
201 |
+
if (($blog_id = (integer) $blog_id) < 0) {
|
202 |
+
$blog_id = (integer) get_current_site()->blog_id;
|
203 |
+
}
|
204 |
+
if (!$blog_id) {
|
205 |
+
$blog_id = (integer) get_current_blog_id();
|
206 |
+
}
|
207 |
+
if (!$blog_id || $blog_id < 0) {
|
208 |
+
return ''; // Not possible.
|
209 |
+
}
|
210 |
+
if (!is_null($domain = &$this->staticKey('domainMappingBlogDomain', $blog_id))) {
|
211 |
+
return $domain; // Already cached this.
|
212 |
+
}
|
213 |
+
$wpdb = $this->wpdb(); // WordPress database class.
|
214 |
+
$suppressing_errors = $wpdb->suppress_errors(); // In case table has not been created yet.
|
215 |
+
$enforcing_primary_domain = !get_site_option('dm_no_primary_domain'); // Enforcing primary domain?
|
216 |
+
|
217 |
+
if (!$enforcing_primary_domain) {
|
218 |
+
if ($this->isDomainMapping() === $blog_id) {
|
219 |
+
$domain = $this->hostToken();
|
220 |
+
$domain = preg_replace('/^www\./i', '', $domain);
|
221 |
+
$domain = (string) $wpdb->get_var('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IN(\''.esc_sql('www.'.$domain).'\', \''.esc_sql($domain).'\') ORDER BY CHAR_LENGTH(`domain`) DESC LIMIT 1');
|
222 |
+
} elseif (($domains = $this->domainMappingBlogDomains($blog_id))) {
|
223 |
+
$domain = $domains[0]; // Use the first of all possible domains.
|
224 |
+
}
|
225 |
+
} else { // A single primary domain in this case; i.e., `active` = primary.
|
226 |
+
$domain = (string) $wpdb->get_var('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IS NOT NULL AND `domain` != \'\' AND `active` = \'1\' LIMIT 1');
|
227 |
+
}
|
228 |
+
if (!$domain && $fallback && ($blog_details = $this->blogDetails($blog_id))) {
|
229 |
+
$domain = $blog_details->domain; // Use original domain.
|
230 |
+
}
|
231 |
+
$wpdb->suppress_errors($suppressing_errors); // Restore.
|
232 |
+
|
233 |
+
return $domain = strtolower((string) $domain);
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Converts a blog ID into mapped domains (plural).
|
238 |
+
*
|
239 |
+
* @since 150821 Improving multisite compat.
|
240 |
+
*
|
241 |
+
* @param int $blog_id The blog ID.
|
242 |
+
*
|
243 |
+
* @return array Mapped domains; else an empty array.
|
244 |
+
*
|
245 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
246 |
+
*/
|
247 |
+
public function domainMappingBlogDomains($blog_id = 0)
|
248 |
+
{
|
249 |
+
if (!is_multisite() || !$this->canConsiderDomainMapping()) {
|
250 |
+
return []; // Not possible/applicable.
|
251 |
+
}
|
252 |
+
if (($blog_id = (integer) $blog_id) < 0) {
|
253 |
+
$blog_id = (integer) get_current_site()->blog_id;
|
254 |
+
}
|
255 |
+
if (!$blog_id) {
|
256 |
+
$blog_id = (integer) get_current_blog_id();
|
257 |
+
}
|
258 |
+
if (!$blog_id || $blog_id < 0) {
|
259 |
+
return []; // Not possible.
|
260 |
+
}
|
261 |
+
if (!is_null($domains = &$this->staticKey('domainMappingBlogDomains', $blog_id))) {
|
262 |
+
return $domains; // Already cached this.
|
263 |
+
}
|
264 |
+
$wpdb = $this->wpdb(); // WordPress database class.
|
265 |
+
$suppressing_errors = $wpdb->suppress_errors(); // In case table has not been created yet.
|
266 |
+
$enforcing_primary_domain = !get_site_option('dm_no_primary_domain'); // Enforcing primary domain?
|
267 |
+
|
268 |
+
if (!$enforcing_primary_domain) { // Not enforcing a primary domain, so let's pull all of the domains.
|
269 |
+
$domains = $wpdb->get_col('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IS NOT NULL AND `domain` != \'\' ORDER BY `active` DESC');
|
270 |
+
} else { // Primary domains in this case; i.e., `active` = primary.
|
271 |
+
$domains = $wpdb->get_col('SELECT `domain` FROM `'.esc_sql($wpdb->base_prefix.'domain_mapping').'` WHERE `blog_id` = \''.esc_sql($blog_id).'\' AND `domain` IS NOT NULL AND `domain` != \'\' AND `active` = \'1\'');
|
272 |
+
}
|
273 |
+
$wpdb->suppress_errors($suppressing_errors); // Restore.
|
274 |
+
|
275 |
+
return $domains = array_unique(array_map('strtolower', (array) $domains));
|
276 |
+
}
|
277 |
+
}
|
src/includes/traits/Shared/EscapeUtils.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait EscapeUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Escape single quotes.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param string $string Input string to escape.
|
14 |
+
* @param int $times Optional. Defaults to one escape char; e.g. `\'`.
|
15 |
+
* If you need to escape more than once, set this to something > `1`.
|
16 |
+
*
|
17 |
+
* @return string Escaped string; e.g. `Raam\'s the lead developer`.
|
18 |
+
*/
|
19 |
+
public function escSq($string, $times = 1)
|
20 |
+
{
|
21 |
+
return str_replace("'", str_repeat('\\', abs($times))."'", (string) $string);
|
22 |
+
}
|
23 |
+
}
|
src/includes/traits/Shared/FsUtils.php
ADDED
@@ -0,0 +1,335 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait FsUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Normalizes directory/file separators.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param string $dir_file Directory/file path.
|
14 |
+
* @param bool $allow_trailing_slash Defaults to FALSE.
|
15 |
+
* If TRUE; and `$dir_file` contains a trailing slash; we'll leave it there.
|
16 |
+
*
|
17 |
+
* @return string Normalized directory/file path.
|
18 |
+
*/
|
19 |
+
public function nDirSeps($dir_file, $allow_trailing_slash = false)
|
20 |
+
{
|
21 |
+
$dir_file = (string) $dir_file;
|
22 |
+
|
23 |
+
if (!isset($dir_file[0])) {
|
24 |
+
return ''; // Catch empty string.
|
25 |
+
}
|
26 |
+
if (strpos($dir_file, '://' !== false)) {
|
27 |
+
if (preg_match('/^(?P<stream_wrapper>[a-zA-Z0-9]+)\:\/\//', $dir_file, $stream_wrapper)) {
|
28 |
+
$dir_file = preg_replace('/^(?P<stream_wrapper>[a-zA-Z0-9]+)\:\/\//', '', $dir_file);
|
29 |
+
}
|
30 |
+
}
|
31 |
+
if (strpos($dir_file, ':' !== false)) {
|
32 |
+
if (preg_match('/^(?P<drive_letter>[a-zA-Z])\:[\/\\\\]/', $dir_file)) {
|
33 |
+
$dir_file = preg_replace_callback('/^(?P<drive_letter>[a-zA-Z])\:[\/\\\\]/', create_function('$m', 'return strtoupper($m[0]);'), $dir_file);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
$dir_file = preg_replace('/\/+/', '/', str_replace([DIRECTORY_SEPARATOR, '\\', '/'], '/', $dir_file));
|
37 |
+
$dir_file = ($allow_trailing_slash) ? $dir_file : rtrim($dir_file, '/'); // Strip trailing slashes.
|
38 |
+
|
39 |
+
if (!empty($stream_wrapper[0])) {
|
40 |
+
$dir_file = strtolower($stream_wrapper[0]).$dir_file;
|
41 |
+
}
|
42 |
+
return $dir_file; // Normalized now.
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Acquires system tmp directory path.
|
47 |
+
*
|
48 |
+
* @since 150422 Rewrite.
|
49 |
+
*
|
50 |
+
* @return string System tmp directory path; else an empty string.
|
51 |
+
*/
|
52 |
+
public function getTmpDir()
|
53 |
+
{
|
54 |
+
if (!is_null($dir = &$this->staticKey('getTmpDir'))) {
|
55 |
+
return $dir; // Already cached this.
|
56 |
+
}
|
57 |
+
$possible_dirs = []; // Initialize.
|
58 |
+
|
59 |
+
if (defined('WP_TEMP_DIR')) {
|
60 |
+
$possible_dirs[] = (string) WP_TEMP_DIR;
|
61 |
+
}
|
62 |
+
if ($this->functionIsPossible('sys_get_temp_dir')) {
|
63 |
+
$possible_dirs[] = (string) sys_get_temp_dir();
|
64 |
+
}
|
65 |
+
$possible_dirs[] = (string) ini_get('upload_tmp_dir');
|
66 |
+
|
67 |
+
if (!empty($_SERVER['TEMP'])) {
|
68 |
+
$possible_dirs[] = (string) $_SERVER['TEMP'];
|
69 |
+
}
|
70 |
+
if (!empty($_SERVER['TMPDIR'])) {
|
71 |
+
$possible_dirs[] = (string) $_SERVER['TMPDIR'];
|
72 |
+
}
|
73 |
+
if (!empty($_SERVER['TMP'])) {
|
74 |
+
$possible_dirs[] = (string) $_SERVER['TMP'];
|
75 |
+
}
|
76 |
+
if (stripos(PHP_OS, 'win') === 0) {
|
77 |
+
$possible_dirs[] = 'C:/Temp';
|
78 |
+
}
|
79 |
+
if (stripos(PHP_OS, 'win') !== 0) {
|
80 |
+
$possible_dirs[] = '/tmp';
|
81 |
+
}
|
82 |
+
if (defined('WP_CONTENT_DIR')) {
|
83 |
+
$possible_dirs[] = (string) WP_CONTENT_DIR;
|
84 |
+
}
|
85 |
+
foreach ($possible_dirs as $_key => $_dir) {
|
86 |
+
if (($_dir = trim((string) $_dir)) && @is_dir($_dir) && @is_writable($_dir)) {
|
87 |
+
return $dir = $this->nDirSeps($_dir);
|
88 |
+
}
|
89 |
+
}
|
90 |
+
unset($_key, $_dir); // Housekeeping.
|
91 |
+
|
92 |
+
return $dir = '';
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Finds absolute server path to `/wp-config.php` file.
|
97 |
+
*
|
98 |
+
* @since 150422 Rewrite.
|
99 |
+
*
|
100 |
+
* @return string Absolute server path to `/wp-config.php` file;
|
101 |
+
* else an empty string if unable to locate the file.
|
102 |
+
*/
|
103 |
+
public function findWpConfigFile()
|
104 |
+
{
|
105 |
+
if (!is_null($file = &$this->staticKey('findWpConfigFile'))) {
|
106 |
+
return $file; // Already cached this.
|
107 |
+
}
|
108 |
+
$file = ''; // Initialize.
|
109 |
+
|
110 |
+
if (is_file($abspath_wp_config = ABSPATH.'wp-config.php')) {
|
111 |
+
$file = $abspath_wp_config;
|
112 |
+
} elseif (is_file($dirname_abspath_wp_config = dirname(ABSPATH).'/wp-config.php')) {
|
113 |
+
$file = $dirname_abspath_wp_config;
|
114 |
+
}
|
115 |
+
return $file;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Adds a tmp name suffix to a directory/file path.
|
120 |
+
*
|
121 |
+
* @since 150422 Rewrite.
|
122 |
+
*
|
123 |
+
* @param string $dir_file An input directory or file path.
|
124 |
+
*
|
125 |
+
* @return string The original `$dir_file` with a tmp name suffix.
|
126 |
+
*/
|
127 |
+
public function addTmpSuffix($dir_file)
|
128 |
+
{
|
129 |
+
$dir_file = (string) $dir_file;
|
130 |
+
$dir_file = rtrim($dir_file, DIRECTORY_SEPARATOR.'\\/');
|
131 |
+
|
132 |
+
return $dir_file.'-'.str_replace('.', '', uniqid('', true)).'-tmp';
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Recursive directory iterator based on a regex pattern.
|
137 |
+
*
|
138 |
+
* @since 150422 Rewrite.
|
139 |
+
*
|
140 |
+
* @param string $dir An absolute server directory path.
|
141 |
+
* @param string $regex A regex pattern; compares to each full file path.
|
142 |
+
*
|
143 |
+
* @return \RegexIterator Navigable with {@link \foreach()} where each item
|
144 |
+
* is a {@link \RecursiveDirectoryIterator}.
|
145 |
+
*/
|
146 |
+
public function dirRegexIteration($dir, $regex = '')
|
147 |
+
{
|
148 |
+
$dir = (string) $dir;
|
149 |
+
$regex = (string) $regex;
|
150 |
+
|
151 |
+
$dir_iterator = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_SELF | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS);
|
152 |
+
$iterator_iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::CHILD_FIRST);
|
153 |
+
|
154 |
+
if ($regex && $regex !== '/.*/' && $regex !== '/.+/') { // Apply regex filter?
|
155 |
+
// @TODO Optimize calls to this method in order to avoid the regex iterator when not necessary.
|
156 |
+
return new \RegexIterator($iterator_iterator, $regex, \RegexIterator::MATCH, \RegexIterator::USE_KEY);
|
157 |
+
}
|
158 |
+
return $iterator_iterator; // Iterate everything.
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Abbreviated byte notation for file sizes.
|
163 |
+
*
|
164 |
+
* @since 151002 Adding a few statistics.
|
165 |
+
*
|
166 |
+
* @param float $bytes File size in bytes. A (float) value.
|
167 |
+
* @param int $precision Number of decimals to use.
|
168 |
+
*
|
169 |
+
* @return string Byte notation.
|
170 |
+
*/
|
171 |
+
public function bytesAbbr($bytes, $precision = 2)
|
172 |
+
{
|
173 |
+
$bytes = max(0.0, (float) $bytes);
|
174 |
+
$precision = max(0, (integer) $precision);
|
175 |
+
$units = ['bytes', 'kbs', 'MB', 'GB', 'TB'];
|
176 |
+
|
177 |
+
$power = floor(($bytes ? log($bytes) : 0) / log(1024));
|
178 |
+
$abbr_bytes = round($bytes / pow(1024, $power), $precision);
|
179 |
+
$abbr = $units[min($power, count($units) - 1)];
|
180 |
+
|
181 |
+
if ($abbr_bytes === (float) 1 && $abbr === 'bytes') {
|
182 |
+
$abbr = 'byte'; // Quick fix.
|
183 |
+
} elseif ($abbr_bytes === (float) 1 && $abbr === 'kbs') {
|
184 |
+
$abbr = 'kb'; // Quick fix.
|
185 |
+
}
|
186 |
+
return $abbr_bytes.' '.$abbr;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Converts an abbreviated byte notation into bytes.
|
191 |
+
*
|
192 |
+
* @since 151002 Adding a few statistics.
|
193 |
+
*
|
194 |
+
* @param string $string A string value in byte notation.
|
195 |
+
*
|
196 |
+
* @return float A float indicating the number of bytes.
|
197 |
+
*/
|
198 |
+
public function abbrBytes($string)
|
199 |
+
{
|
200 |
+
$string = (string) $string;
|
201 |
+
$regex = '/^(?P<value>[0-9\.]+)\s*(?P<modifier>bytes|byte|kbs|kb|k|mb|m|gb|g|tb|t)$/i';
|
202 |
+
|
203 |
+
if (!preg_match($regex, $string, $_m)) {
|
204 |
+
return (float) 0;
|
205 |
+
}
|
206 |
+
$value = (float) $_m['value'];
|
207 |
+
$modifier = strtolower($_m['modifier']);
|
208 |
+
unset($_m); // Housekeeping.
|
209 |
+
|
210 |
+
switch ($modifier) {
|
211 |
+
case 't':
|
212 |
+
case 'tb':
|
213 |
+
$value *= 1024;
|
214 |
+
// Fall through.
|
215 |
+
case 'g':
|
216 |
+
case 'gb':
|
217 |
+
$value *= 1024;
|
218 |
+
// Fall through.
|
219 |
+
case 'm':
|
220 |
+
case 'mb':
|
221 |
+
$value *= 1024;
|
222 |
+
// Fall through.
|
223 |
+
case 'k':
|
224 |
+
case 'kb':
|
225 |
+
case 'kbs':
|
226 |
+
$value *= 1024;
|
227 |
+
}
|
228 |
+
return (float) $value;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Directory stats.
|
233 |
+
*
|
234 |
+
* @since 151002 Adding a few statistics.
|
235 |
+
*
|
236 |
+
* @param string $dir An absolute server directory path.
|
237 |
+
* @param string $regex A regex pattern; compares to each full file path.
|
238 |
+
* @param bool $include_paths Include array of all scanned file paths?
|
239 |
+
* @param bool $check_disk Also check disk statistics?
|
240 |
+
* @param bool $no_cache Do not read/write cache?
|
241 |
+
*
|
242 |
+
* @return array Directory stats.
|
243 |
+
*/
|
244 |
+
public function getDirRegexStats($dir, $regex = '', $include_paths = false, $check_disk = true, $no_cache = false)
|
245 |
+
{
|
246 |
+
$dir = (string) $dir; // Force string.
|
247 |
+
$cache_keys = [$dir, $regex, $include_paths, $check_disk];
|
248 |
+
if (!$no_cache && !is_null($stats = &$this->staticKey('getDirRegexStats', $cache_keys))) {
|
249 |
+
return $stats; // Already cached this.
|
250 |
+
}
|
251 |
+
$stats = [
|
252 |
+
'total_size' => 0,
|
253 |
+
'total_resources' => 0,
|
254 |
+
'total_links_files' => 0,
|
255 |
+
|
256 |
+
'total_links' => 0,
|
257 |
+
'link_subpaths' => [],
|
258 |
+
|
259 |
+
'total_files' => 0,
|
260 |
+
'file_subpaths' => [],
|
261 |
+
|
262 |
+
'total_dirs' => 0,
|
263 |
+
'dir_subpaths' => [],
|
264 |
+
|
265 |
+
'disk_total_space' => 0,
|
266 |
+
'disk_free_space' => 0,
|
267 |
+
];
|
268 |
+
if (!$dir || !is_dir($dir)) {
|
269 |
+
return $stats; // Not possible.
|
270 |
+
}
|
271 |
+
$short_name_lc = strtolower(SHORT_NAME); // Once only.
|
272 |
+
|
273 |
+
foreach ($this->dirRegexIteration($dir, $regex) as $_resource) {
|
274 |
+
$_resource_sub_path = $_resource->getSubpathname();
|
275 |
+
$_resource_basename = basename($_resource_sub_path);
|
276 |
+
|
277 |
+
if ($_resource_basename === '.DS_Store') {
|
278 |
+
continue; // Ignore `.htaccess`.
|
279 |
+
}
|
280 |
+
if ($_resource_basename === '.htaccess') {
|
281 |
+
continue; // Ignore `.htaccess`.
|
282 |
+
}
|
283 |
+
if (stripos($_resource_sub_path, $short_name_lc.'-') === 0) {
|
284 |
+
continue; // Ignore [SHORT_NAME] files in base.
|
285 |
+
}
|
286 |
+
switch ($_resource->getType()) { // `link`, `file`, `dir`.
|
287 |
+
case 'link':
|
288 |
+
if ($include_paths) {
|
289 |
+
$stats['link_subpaths'][] = $_resource_sub_path;
|
290 |
+
}
|
291 |
+
++$stats['total_resources'];
|
292 |
+
++$stats['total_links_files'];
|
293 |
+
++$stats['total_links'];
|
294 |
+
|
295 |
+
break; // Break switch.
|
296 |
+
|
297 |
+
case 'file':
|
298 |
+
if ($include_paths) {
|
299 |
+
$stats['file_subpaths'][] = $_resource_sub_path;
|
300 |
+
}
|
301 |
+
$stats['total_size'] += $_resource->getSize();
|
302 |
+
++$stats['total_resources'];
|
303 |
+
++$stats['total_links_files'];
|
304 |
+
++$stats['total_files'];
|
305 |
+
|
306 |
+
break; // Break switch.
|
307 |
+
|
308 |
+
case 'dir':
|
309 |
+
if ($include_paths) {
|
310 |
+
$stats['dir_subpaths'][] = $_resource_sub_path;
|
311 |
+
}
|
312 |
+
++$stats['total_resources'];
|
313 |
+
++$stats['total_dirs'];
|
314 |
+
|
315 |
+
break; // Break switch.
|
316 |
+
}
|
317 |
+
}
|
318 |
+
unset($_resource, $_resource_sub_path, $_resource_basename); // Housekeeping.
|
319 |
+
|
320 |
+
if ($check_disk) { // Check disk also?
|
321 |
+
$stats['disk_total_space'] = disk_total_space($dir);
|
322 |
+
$stats['disk_free_space'] = disk_free_space($dir);
|
323 |
+
}
|
324 |
+
return $stats;
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Apache `.htaccess` rules that deny public access to the contents of a directory.
|
329 |
+
*
|
330 |
+
* @since 150422 Rewrite.
|
331 |
+
*
|
332 |
+
* @type string `.htaccess` fules.
|
333 |
+
*/
|
334 |
+
public $htaccess_deny = "<IfModule authz_core_module>\n\tRequire all denied\n</IfModule>\n<IfModule !authz_core_module>\n\tdeny from all\n</IfModule>";
|
335 |
+
}
|
src/includes/traits/Shared/HookUtils.php
ADDED
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait HookUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Array of hooks.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @type array An array of hooks.
|
14 |
+
*/
|
15 |
+
public $hooks = [];
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Assigns an ID to each callable attached to a hook/filter.
|
19 |
+
*
|
20 |
+
* @since 150422 Rewrite.
|
21 |
+
*
|
22 |
+
* @param string|callable|mixed $function A string or a callable.
|
23 |
+
*
|
24 |
+
* @throws \Exception If the hook/function is invalid (i.e. it's not possible to generate an ID).
|
25 |
+
*
|
26 |
+
* @return string Hook ID for the given `$function`.
|
27 |
+
*/
|
28 |
+
public function hookId($function)
|
29 |
+
{
|
30 |
+
if (is_string($function)) {
|
31 |
+
return $function;
|
32 |
+
}
|
33 |
+
if (is_object($function)) {
|
34 |
+
$function = [$function, ''];
|
35 |
+
} else {
|
36 |
+
$function = (array) $function;
|
37 |
+
}
|
38 |
+
if (isset($function[0], $function[1])) {
|
39 |
+
if (is_object($function[0])) {
|
40 |
+
return spl_object_hash($function[0]).$function[1];
|
41 |
+
} elseif (is_string($function[0])) {
|
42 |
+
return $function[0].'::'.$function[1];
|
43 |
+
}
|
44 |
+
}
|
45 |
+
throw new \Exception(__('Invalid hook.', 'comet-cache'));
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Adds a new hook (works with both actions & filters).
|
50 |
+
*
|
51 |
+
* @since 150422 Rewrite.
|
52 |
+
*
|
53 |
+
* @param string $hook The name of a hook to attach to.
|
54 |
+
* @param string|callable|mixed $function A string or a callable.
|
55 |
+
* @param int $priority Hook priority; defaults to `10`.
|
56 |
+
* @param int $accepted_args Max number of args that should be passed to the `$function`.
|
57 |
+
*
|
58 |
+
* @return bool This always returns a `TRUE` value.
|
59 |
+
*/
|
60 |
+
public function addHook($hook, $function, $priority = 10, $accepted_args = 1)
|
61 |
+
{
|
62 |
+
$hook = (string) $hook;
|
63 |
+
if (stripos($hook, 'zencache') === 0) {
|
64 |
+
$hook = GLOBAL_NS.substr($hook, strlen('zencache'));
|
65 |
+
}
|
66 |
+
$priority = (integer) $priority;
|
67 |
+
$accepted_args = max(0, (integer) $accepted_args);
|
68 |
+
$hook_id = $this->hookId($function);
|
69 |
+
|
70 |
+
$this->hooks[$hook][$priority][$hook_id] = [
|
71 |
+
'function' => $function,
|
72 |
+
'accepted_args' => $accepted_args,
|
73 |
+
];
|
74 |
+
return true; // Always returns true.
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Adds a new action hook.
|
79 |
+
*
|
80 |
+
* @since 150422 Rewrite.
|
81 |
+
*
|
82 |
+
* @return bool This always returns a `TRUE` value.
|
83 |
+
*/
|
84 |
+
public function addAction()
|
85 |
+
{
|
86 |
+
return call_user_func_array([$this, 'addHook'], func_get_args());
|
87 |
+
}
|
88 |
+
|
89 |
+
// @codingStandardsIgnoreStart
|
90 |
+
/*
|
91 |
+
* Back compat. alias for addAction()
|
92 |
+
*/
|
93 |
+
public function add_action()
|
94 |
+
{ // @codingStandardsIgnoreEnd
|
95 |
+
return call_user_func_array([$this, 'addAction'], func_get_args());
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Adds a new filter.
|
100 |
+
*
|
101 |
+
* @since 150422 Rewrite.
|
102 |
+
*
|
103 |
+
* @return bool This always returns a `TRUE` value.
|
104 |
+
*/
|
105 |
+
public function addFilter()
|
106 |
+
{
|
107 |
+
return call_user_func_array([$this, 'addHook'], func_get_args());
|
108 |
+
}
|
109 |
+
|
110 |
+
// @codingStandardsIgnoreStart
|
111 |
+
/*
|
112 |
+
* Back compat. alias for addFilter()
|
113 |
+
*/
|
114 |
+
public function add_filter()
|
115 |
+
{ // @codingStandardsIgnoreEnd
|
116 |
+
return call_user_func_array([$this, 'addFilter'], func_get_args());
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Removes a hook (works with both actions & filters).
|
121 |
+
*
|
122 |
+
* @since 150422 Rewrite.
|
123 |
+
*
|
124 |
+
* @param string $hook The name of a hook to remove.
|
125 |
+
* @param string|callable|mixed $function A string or a callable.
|
126 |
+
* @param int $priority Hook priority; defaults to `10`.
|
127 |
+
*
|
128 |
+
* @return bool `TRUE` if removed; else `FALSE` if not removed for any reason.
|
129 |
+
*/
|
130 |
+
public function removeHook($hook, $function, $priority = 10)
|
131 |
+
{
|
132 |
+
$hook = (string) $hook;
|
133 |
+
if (stripos($hook, 'zencache') === 0) {
|
134 |
+
$hook = GLOBAL_NS.substr($hook, strlen('zencache'));
|
135 |
+
}
|
136 |
+
$priority = (integer) $priority;
|
137 |
+
$hook_id = $this->hookId($function);
|
138 |
+
|
139 |
+
if (!isset($this->hooks[$hook][$priority][$hook_id])) {
|
140 |
+
return false; // Nothing to remove.
|
141 |
+
}
|
142 |
+
unset($this->hooks[$hook][$priority][$hook_id]);
|
143 |
+
|
144 |
+
if (!$this->hooks[$hook][$priority]) {
|
145 |
+
unset($this->hooks[$hook][$priority]);
|
146 |
+
}
|
147 |
+
return true; // Existed before it was removed.
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Removes an action.
|
152 |
+
*
|
153 |
+
* @since 150422 Rewrite.
|
154 |
+
*
|
155 |
+
* @return bool `TRUE` if removed; else `FALSE` if not removed for any reason.
|
156 |
+
*/
|
157 |
+
public function removeAction()
|
158 |
+
{
|
159 |
+
return call_user_func_array([$this, 'removeHook'], func_get_args());
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Removes a filter.
|
164 |
+
*
|
165 |
+
* @since 150422 Rewrite.
|
166 |
+
*
|
167 |
+
* @return bool `TRUE` if removed; else `FALSE` if not removed for any reason.
|
168 |
+
*/
|
169 |
+
public function removeFilter()
|
170 |
+
{
|
171 |
+
return call_user_func_array([$this, 'removeHook'], func_get_args());
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Runs any callables attached to an action.
|
176 |
+
*
|
177 |
+
* @since 150422 Rewrite.
|
178 |
+
*
|
179 |
+
* @param string $hook The name of an action hook.
|
180 |
+
*/
|
181 |
+
public function doAction($hook)
|
182 |
+
{
|
183 |
+
$hook = (string) $hook;
|
184 |
+
if (empty($this->hooks[$hook])) {
|
185 |
+
return; // No hooks.
|
186 |
+
}
|
187 |
+
$hook_actions = $this->hooks[$hook];
|
188 |
+
$args = func_get_args();
|
189 |
+
ksort($hook_actions);
|
190 |
+
|
191 |
+
foreach ($hook_actions as $_hook_action) {
|
192 |
+
foreach ($_hook_action as $_action) {
|
193 |
+
if (!isset($_action['function'], $_action['accepted_args'])) {
|
194 |
+
continue; // Not a valid filter in this case.
|
195 |
+
}
|
196 |
+
call_user_func_array($_action['function'], array_slice($args, 1, $_action['accepted_args']));
|
197 |
+
}
|
198 |
+
}
|
199 |
+
unset($_hook_action, $_action); // Housekeeping.
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Runs any callables attached to a filter.
|
204 |
+
*
|
205 |
+
* @since 150422 Rewrite.
|
206 |
+
*
|
207 |
+
* @param string $hook The name of a filter hook.
|
208 |
+
* @param mixed $value The value to filter.
|
209 |
+
*
|
210 |
+
* @return mixed The filtered `$value`.
|
211 |
+
*/
|
212 |
+
public function applyFilters($hook, $value)
|
213 |
+
{
|
214 |
+
$hook = (string) $hook;
|
215 |
+
if (empty($this->hooks[$hook])) {
|
216 |
+
return $value; // No hooks.
|
217 |
+
}
|
218 |
+
$hook_filters = $this->hooks[$hook];
|
219 |
+
$args = func_get_args();
|
220 |
+
ksort($hook_filters);
|
221 |
+
|
222 |
+
foreach ($hook_filters as $_hook_filter) {
|
223 |
+
foreach ($_hook_filter as $_filter) {
|
224 |
+
if (!isset($_filter['function'], $_filter['accepted_args'])) {
|
225 |
+
continue; // Not a valid filter in this case.
|
226 |
+
}
|
227 |
+
$args[1] = $value; // Continously update the argument `$value`.
|
228 |
+
$value = call_user_func_array($_filter['function'], array_slice($args, 1, $_filter['accepted_args']));
|
229 |
+
}
|
230 |
+
}
|
231 |
+
unset($_hook_filter, $_filter); // Housekeeping.
|
232 |
+
|
233 |
+
return $value; // With applied filters.
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Does an action w/ back compat. for ZenCache.
|
238 |
+
*
|
239 |
+
* @since 150422 Rewrite.
|
240 |
+
*
|
241 |
+
* @param string $hook The hook to apply.
|
242 |
+
*/
|
243 |
+
public function doWpAction($hook)
|
244 |
+
{
|
245 |
+
$hook = (string) $hook;
|
246 |
+
$args = func_get_args();
|
247 |
+
call_user_func_array('do_action', $args);
|
248 |
+
|
249 |
+
if (stripos($hook, GLOBAL_NS) === 0) {
|
250 |
+
$zencache_filter = 'zencache'.substr($hook, strlen(GLOBAL_NS));
|
251 |
+
$zencache_args = $args; // Use a copy of the args.
|
252 |
+
$zencache_args[0] = $zencache_filter;
|
253 |
+
call_user_func_array('do_action', $zencache_args);
|
254 |
+
}
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Applies filters w/ back compat. for ZenCache.
|
259 |
+
*
|
260 |
+
* @since 150422 Rewrite.
|
261 |
+
*
|
262 |
+
* @param string $hook The hook to apply.
|
263 |
+
*
|
264 |
+
* @return mixed The filtered value.
|
265 |
+
*/
|
266 |
+
public function applyWpFilters($hook)
|
267 |
+
{
|
268 |
+
$hook = (string) $hook;
|
269 |
+
$args = func_get_args();
|
270 |
+
$value = call_user_func_array('apply_filters', $args);
|
271 |
+
|
272 |
+
if (stripos($hook, GLOBAL_NS) === 0) {
|
273 |
+
$zencache_hook = 'zencache'.substr($hook, strlen(GLOBAL_NS));
|
274 |
+
$zencache_args = $args; // Use a copy of the args.
|
275 |
+
$zencache_args[0] = $zencache_hook;
|
276 |
+
$zencache_args[1] = $value; // Filtered value.
|
277 |
+
$value = call_user_func_array('apply_filters', $zencache_args);
|
278 |
+
}
|
279 |
+
return $value; // Filtered value.
|
280 |
+
}
|
281 |
+
}
|
src/includes/traits/Shared/HttpUtils.php
ADDED
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait HttpUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Current HTTP protocol.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @return string Current HTTP protocol.
|
14 |
+
*/
|
15 |
+
public function httpProtocol()
|
16 |
+
{
|
17 |
+
if (!is_null($protocol = &$this->staticKey('httpProtocol'))) {
|
18 |
+
return $protocol; // Already cached this.
|
19 |
+
}
|
20 |
+
if (!empty($_SERVER['SERVER_PROTOCOL']) && is_string($_SERVER['SERVER_PROTOCOL'])) {
|
21 |
+
$protocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
|
22 |
+
}
|
23 |
+
if (!$protocol || stripos($protocol, 'HTTP/') !== 0) {
|
24 |
+
$protocol = 'HTTP/1.0'; // Default value.
|
25 |
+
}
|
26 |
+
return $protocol;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* PHP {@link headers_list()} + HTTP status.
|
31 |
+
*
|
32 |
+
* @since 150422 Rewrite.
|
33 |
+
*
|
34 |
+
* @return array PHP {@link headers_list()} + HTTP status.
|
35 |
+
*
|
36 |
+
* @warning Do NOT call until end of script execution.
|
37 |
+
*/
|
38 |
+
public function headersList()
|
39 |
+
{
|
40 |
+
if (!is_null($headers = &$this->staticKey('headersList'))) {
|
41 |
+
return $headers; // Already cached this.
|
42 |
+
}
|
43 |
+
$headers = headers_list(); // Lacks status.
|
44 |
+
|
45 |
+
if (($status = (string) $this->httpStatus())) {
|
46 |
+
array_unshift($headers, $this->httpProtocol().' '.$status);
|
47 |
+
}
|
48 |
+
return $headers;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* PHP {@link headers_list()} + HTTP status.
|
53 |
+
*
|
54 |
+
* @since 150422 Rewrite.
|
55 |
+
*
|
56 |
+
* @return array PHP {@link headers_list()} + HTTP status.
|
57 |
+
*
|
58 |
+
* @warning Do NOT call until end of script execution.
|
59 |
+
*/
|
60 |
+
public function cacheableHeadersList()
|
61 |
+
{
|
62 |
+
if (!is_null($headers = &$this->staticKey('cacheableHeadersList'))) {
|
63 |
+
return $headers; // Already cached this.
|
64 |
+
}
|
65 |
+
$headers = headers_list(); // Lacks status.
|
66 |
+
|
67 |
+
$cacheable_headers = [
|
68 |
+
'Access-Control-Allow-Origin',
|
69 |
+
'Accept-Ranges',
|
70 |
+
'Age',
|
71 |
+
'Allow',
|
72 |
+
'Cache-Control',
|
73 |
+
'Connection',
|
74 |
+
'Content-Encoding',
|
75 |
+
'Content-Language',
|
76 |
+
'Content-Length',
|
77 |
+
'Content-Location',
|
78 |
+
'Content-MD5',
|
79 |
+
'Content-Disposition',
|
80 |
+
'Content-Range',
|
81 |
+
'Content-Type',
|
82 |
+
'Date',
|
83 |
+
'ETag',
|
84 |
+
'Expires',
|
85 |
+
'Last-Modified',
|
86 |
+
'Link',
|
87 |
+
'Location',
|
88 |
+
'P3P',
|
89 |
+
'Pragma',
|
90 |
+
'Proxy-Authenticate',
|
91 |
+
'Refresh',
|
92 |
+
'Retry-After',
|
93 |
+
'Server',
|
94 |
+
'Status',
|
95 |
+
'Strict-Transport-Security',
|
96 |
+
'Trailer',
|
97 |
+
'Transfer-Encoding',
|
98 |
+
'Upgrade',
|
99 |
+
'Vary',
|
100 |
+
'Via',
|
101 |
+
'Warning',
|
102 |
+
'WWW-Authenticate',
|
103 |
+
'X-Frame-Options',
|
104 |
+
'Public-Key-Pins',
|
105 |
+
'X-XSS-Protection',
|
106 |
+
'Content-Security-Policy',
|
107 |
+
'X-Content-Security-Policy',
|
108 |
+
'X-WebKit-CSP',
|
109 |
+
'X-Content-Type-Options',
|
110 |
+
'X-Powered-By',
|
111 |
+
'X-UA-Compatible',
|
112 |
+
];
|
113 |
+
$cacheable_headers = array_map('strtolower', $cacheable_headers);
|
114 |
+
|
115 |
+
foreach ($headers as $_key => $_header) {
|
116 |
+
$_header = strtolower((string) strstr($_header, ':', true));
|
117 |
+
if (!$_header || !in_array($_header, $cacheable_headers, true)) {
|
118 |
+
unset($headers[$_key]);
|
119 |
+
}
|
120 |
+
}
|
121 |
+
unset($_key, $_header); // Housekeeping.
|
122 |
+
|
123 |
+
if (($status = (string) $this->httpStatus())) {
|
124 |
+
array_unshift($headers, $this->httpProtocol().' '.$status);
|
125 |
+
}
|
126 |
+
return $headers;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* HTTP status code.
|
131 |
+
*
|
132 |
+
* @since 150422 Rewrite.
|
133 |
+
*
|
134 |
+
* @return int HTTP status code.
|
135 |
+
*
|
136 |
+
* @warning Do NOT call until end of script execution.
|
137 |
+
*
|
138 |
+
* @note Automatically updates HTTP status-related flags.
|
139 |
+
*/
|
140 |
+
public function httpStatus()
|
141 |
+
{
|
142 |
+
if (!is_null($status = &$this->staticKey('httpStatus'))) {
|
143 |
+
return $status; // Already cached this.
|
144 |
+
}
|
145 |
+
$status = 0; // Initialize.
|
146 |
+
$has_property_is_404 = property_exists($this, 'is_404');
|
147 |
+
$has_property_http_status = property_exists($this, 'http_status');
|
148 |
+
|
149 |
+
if ($has_property_is_404 && $this->is_404) {
|
150 |
+
$status = 404; // WordPress said so.
|
151 |
+
} elseif (($code = (integer) http_response_code())) {
|
152 |
+
$status = (integer) $code; // {@link \http_response_code()} available since PHP v5.4.
|
153 |
+
} elseif ($has_property_http_status && (integer) $this->http_status) {
|
154 |
+
$status = (integer) $this->http_status; // {@link \status_header()} filter.
|
155 |
+
}
|
156 |
+
if ($status && $has_property_http_status) {
|
157 |
+
$this->http_status = $status; // Prefer over {@link status_header()}.
|
158 |
+
}
|
159 |
+
if ($status === 404 && $has_property_is_404) {
|
160 |
+
$this->is_404 = true; // Prefer over {@link is_404()}.
|
161 |
+
}
|
162 |
+
return $status;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Sends no-cache headers.
|
167 |
+
*
|
168 |
+
* @since 151220 Enhancing no-cache headers.
|
169 |
+
*/
|
170 |
+
public function sendNoCacheHeaders()
|
171 |
+
{
|
172 |
+
header_remove('Last-Modified');
|
173 |
+
header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
|
174 |
+
header('Cache-Control: no-cache, must-revalidate, max-age=0');
|
175 |
+
header('Pragma: no-cache');
|
176 |
+
}
|
177 |
+
}
|
src/includes/traits/Shared/I18nUtils.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait I18nUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* `X file` or `X files`, translated w/ singlular/plural context.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param int $counter Total files; i.e. the counter.
|
14 |
+
*
|
15 |
+
* @return string The phrase `X file` or `X files`.
|
16 |
+
*/
|
17 |
+
public function i18nFiles($counter)
|
18 |
+
{
|
19 |
+
$counter = (integer) $counter;
|
20 |
+
return sprintf(_n('%1$s file', '%1$s files', $counter, 'comet-cache'), $counter);
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* `X directory` or `X directories`, translated w/ singlular/plural context.
|
25 |
+
*
|
26 |
+
* @since 150422 Rewrite.
|
27 |
+
*
|
28 |
+
* @param int $counter Total directories; i.e. the counter.
|
29 |
+
*
|
30 |
+
* @return string The phrase `X directory` or `X directories`.
|
31 |
+
*/
|
32 |
+
public function i18nDirs($counter)
|
33 |
+
{
|
34 |
+
$counter = (integer) $counter;
|
35 |
+
return sprintf(_n('%1$s directory', '%1$s directories', $counter, 'comet-cache'), $counter);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* `X file/directory` or `X files/directories`, translated w/ singlular/plural context.
|
40 |
+
*
|
41 |
+
* @since 150422 Rewrite.
|
42 |
+
*
|
43 |
+
* @param int $counter Total files/directories; i.e. the counter.
|
44 |
+
*
|
45 |
+
* @return string The phrase `X file/directory` or `X files/directories`.
|
46 |
+
*/
|
47 |
+
public function i18nFilesDirs($counter)
|
48 |
+
{
|
49 |
+
$counter = (integer) $counter;
|
50 |
+
return sprintf(_n('%1$s file/directory', '%1$s files/directories', $counter, 'comet-cache'), $counter);
|
51 |
+
}
|
52 |
+
}
|
src/includes/traits/Shared/IpAddrUtils.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait IpAddrUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Get the current visitor's real IP address.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @return string Real IP address, else `unknown` on failure.
|
14 |
+
*
|
15 |
+
* @note This supports both IPv4 and IPv6 addresses.
|
16 |
+
* @note See my tests against this here: http://3v4l.org/fVWUp
|
17 |
+
*/
|
18 |
+
public function currentIp()
|
19 |
+
{
|
20 |
+
if (!is_null($ip = &$this->staticKey('currentIp'))) {
|
21 |
+
return $ip; // Already cached this.
|
22 |
+
}
|
23 |
+
$sources = [
|
24 |
+
'HTTP_CF_CONNECTING_IP',
|
25 |
+
'HTTP_CLIENT_IP',
|
26 |
+
'HTTP_X_FORWARDED_FOR',
|
27 |
+
'HTTP_X_FORWARDED',
|
28 |
+
'HTTP_X_CLUSTER_CLIENT_IP',
|
29 |
+
'HTTP_FORWARDED_FOR',
|
30 |
+
'HTTP_FORWARDED',
|
31 |
+
'HTTP_VIA',
|
32 |
+
'REMOTE_ADDR',
|
33 |
+
];
|
34 |
+
$sources = $this->applyFilters(GLOBAL_NS.'\\share::current_ip_sources', $sources);
|
35 |
+
$sources = $this->applyFilters(GLOBAL_NS.'_current_ip_sources', $sources);
|
36 |
+
|
37 |
+
$prioritize_remote_addr = false; // Off by default; can be filtered however.
|
38 |
+
$prioritize_remote_addr = $this->applyFilters(GLOBAL_NS.'\\share::current_ip_prioritize_remote_addr', $prioritize_remote_addr);
|
39 |
+
$prioritize_remote_addr = $this->applyFilters(GLOBAL_NS.'_current_ip_prioritize_remote_addr', $prioritize_remote_addr);
|
40 |
+
|
41 |
+
if (!empty($_SERVER['REMOTE_ADDR']) && $prioritize_remote_addr) {
|
42 |
+
if (($_valid_public_ip = $this->validPublicIp((string) $_SERVER['REMOTE_ADDR']))) {
|
43 |
+
return $ip = $_valid_public_ip;
|
44 |
+
}
|
45 |
+
unset($_valid_public_ip); // Housekeeping.
|
46 |
+
}
|
47 |
+
foreach ($sources as $_key => $_source) {
|
48 |
+
if (!empty($_SERVER[$_source])) {
|
49 |
+
if (($_valid_public_ip = $this->validPublicIp((string) $_SERVER[$_source]))) {
|
50 |
+
return $ip = $_valid_public_ip;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
unset($_key, $_source, $_valid_public_ip); // Housekeeping.
|
54 |
+
}
|
55 |
+
if (!empty($_SERVER['REMOTE_ADDR'])) {
|
56 |
+
return $ip = strtolower((string) $_SERVER['REMOTE_ADDR']);
|
57 |
+
}
|
58 |
+
return $ip = 'unknown'; // Not possible.
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Gets a valid/public IP address.
|
63 |
+
*
|
64 |
+
* @since 150422 Rewrite.
|
65 |
+
*
|
66 |
+
* @param string $list_of_possible_ips A single IP, or a comma-delimited list of IPs.
|
67 |
+
*
|
68 |
+
* @return string A valid/public IP address (if one is found), else an empty string.
|
69 |
+
*
|
70 |
+
* @note This supports both IPv4 and IPv6 addresses.
|
71 |
+
* @note See my tests against this here: http://3v4l.org/fVWUp
|
72 |
+
*/
|
73 |
+
public function validPublicIp($list_of_possible_ips)
|
74 |
+
{
|
75 |
+
if (!$list_of_possible_ips || !is_string($list_of_possible_ips)) {
|
76 |
+
return ''; // Empty or invalid data.
|
77 |
+
}
|
78 |
+
if (!($list_of_possible_ips = trim($list_of_possible_ips))) {
|
79 |
+
return ''; // Not possible; i.e., empty string.
|
80 |
+
}
|
81 |
+
foreach (preg_split('/[\s;,]+/', $list_of_possible_ips, -1, PREG_SPLIT_NO_EMPTY) as $_key => $_possible_ip) {
|
82 |
+
if (($_valid_public_ip = filter_var(strtolower($_possible_ip), FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))) {
|
83 |
+
return $_valid_public_ip; // A valid public IPv4 or IPv6 address.
|
84 |
+
}
|
85 |
+
}
|
86 |
+
unset($_key, $_possible_ip, $_valid_public_ip); // Housekeeping.
|
87 |
+
|
88 |
+
return ''; // Default return value.
|
89 |
+
}
|
90 |
+
}
|
src/includes/traits/Shared/PatternUtils.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait PatternUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Convert line-delimited patterns to a regex.
|
10 |
+
*
|
11 |
+
* @since 151114 Enhancing exclusion pattern support.
|
12 |
+
*
|
13 |
+
* @param string $patterns Line-delimited list of patterns.
|
14 |
+
*
|
15 |
+
* @return string A `/(?:list|of|regex)/i` patterns.
|
16 |
+
*/
|
17 |
+
public function lineDelimitedPatternsToRegex($patterns)
|
18 |
+
{
|
19 |
+
$regex = ''; // Initialize list of regex patterns.
|
20 |
+
$patterns = (string) $patterns;
|
21 |
+
|
22 |
+
if (($patterns = preg_split('/['."\r\n".']+/', $patterns, -1, PREG_SPLIT_NO_EMPTY))) {
|
23 |
+
$regex = '/(?:'.implode('|', array_map([$this, 'wdRegexToActualRegexFrag'], $patterns)).')/i';
|
24 |
+
}
|
25 |
+
return $regex;
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Convert watered-down regex to actual regex.
|
30 |
+
*
|
31 |
+
* @since 151114 Enhancing exclusion pattern support.
|
32 |
+
*
|
33 |
+
* @param string $string Input watered-down regex to convert.
|
34 |
+
*
|
35 |
+
* @return string Actual regex pattern after conversion.
|
36 |
+
*/
|
37 |
+
public function wdRegexToActualRegexFrag($string)
|
38 |
+
{
|
39 |
+
return preg_replace(
|
40 |
+
[
|
41 |
+
'/\\\\\^/',
|
42 |
+
'/\\\\\*\\\\\*/',
|
43 |
+
'/\\\\\*/',
|
44 |
+
'/\\\\\$/',
|
45 |
+
],
|
46 |
+
[
|
47 |
+
'^', // Beginning of line.
|
48 |
+
'.*?', // Zero or more chars.
|
49 |
+
'[^\/]*?', // Zero or more chars != /.
|
50 |
+
'$', // End of line.
|
51 |
+
],
|
52 |
+
preg_quote((string) $string, '/')
|
53 |
+
);
|
54 |
+
}
|
55 |
+
}
|
src/includes/traits/Shared/ReplaceUtils.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait ReplaceUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* String replace ONE time.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param string $needle A string to search/replace.
|
14 |
+
* @param string $replace What to replace `$needle` with.
|
15 |
+
* @param string $haystack The string/haystack to search in.
|
16 |
+
* @param bool $caSe_insensitive Defaults to a `FALSE` value.
|
17 |
+
* Pass this as `TRUE` to a caSe-insensitive search/replace.
|
18 |
+
*
|
19 |
+
* @return string The `$haystack`, with `$needle` replaced with `$replace` ONE time only.
|
20 |
+
*/
|
21 |
+
public function strReplaceOnce($needle, $replace, $haystack, $caSe_insensitive = false)
|
22 |
+
{
|
23 |
+
$needle = (string) $needle;
|
24 |
+
$replace = (string) $replace;
|
25 |
+
$haystack = (string) $haystack;
|
26 |
+
$caSe_strpos = $caSe_insensitive ? 'stripos' : 'strpos';
|
27 |
+
|
28 |
+
if (($needle_strpos = $caSe_strpos($haystack, $needle)) === false) {
|
29 |
+
return $haystack; // Nothing to replace.
|
30 |
+
}
|
31 |
+
return (string) substr_replace($haystack, $replace, $needle_strpos, strlen($needle));
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* String replace ONE time (caSe-insensitive).
|
36 |
+
*
|
37 |
+
* @since 150422 Rewrite.
|
38 |
+
*
|
39 |
+
* @param string $needle A string to search/replace.
|
40 |
+
* @param string $replace What to replace `$needle` with.
|
41 |
+
* @param string $haystack The string/haystack to search in.
|
42 |
+
*
|
43 |
+
* @return string The `$haystack`, with `$needle` replaced with `$replace` ONE time only.
|
44 |
+
*/
|
45 |
+
public function strIreplaceOnce($needle, $replace, $haystack)
|
46 |
+
{
|
47 |
+
return $this->strReplaceOnce($needle, $replace, $haystack, true);
|
48 |
+
}
|
49 |
+
}
|
src/includes/traits/Shared/ServerUtils.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait ServerUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Is running on Apache?
|
10 |
+
*
|
11 |
+
* @since 151002 This is Apache?
|
12 |
+
*
|
13 |
+
* @return bool True if running Apache.
|
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 (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== false) {
|
22 |
+
return $is = true;
|
23 |
+
}
|
24 |
+
if (stripos($_SERVER['SERVER_SOFTWARE'], 'litespeed') !== false) {
|
25 |
+
return $is = true;
|
26 |
+
}
|
27 |
+
}
|
28 |
+
return $is = false;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Is running on Nginx?
|
33 |
+
*
|
34 |
+
* @since 151002 This is Nginx?
|
35 |
+
*
|
36 |
+
* @return bool True if running Nginx.
|
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 (stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false) {
|
45 |
+
return $is = true;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
return $is = false;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Is running on Windows IIS?
|
53 |
+
*
|
54 |
+
* @since 151002 This is Windows IIS?
|
55 |
+
*
|
56 |
+
* @return bool True if running Windows IIS.
|
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 (stripos($_SERVER['SERVER_SOFTWARE'], 'microsoft-iis') !== false) {
|
65 |
+
return $is = true;
|
66 |
+
}
|
67 |
+
if (stripos($_SERVER['SERVER_SOFTWARE'], 'expressiondevserver') !== false) {
|
68 |
+
return $is = true;
|
69 |
+
}
|
70 |
+
}
|
71 |
+
return $is = false;
|
72 |
+
}
|
73 |
+
}
|
src/includes/traits/Shared/StringUtils.php
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait StringUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Clips string(s) to X chars deeply.
|
10 |
+
*
|
11 |
+
* @since 151114 Adding string utils.
|
12 |
+
*
|
13 |
+
* @param mixed $value Any input value.
|
14 |
+
* @param int $max_length Defaults to a value of `80`.
|
15 |
+
* @param bool $force_ellipsis Defaults to a value of `FALSE`.
|
16 |
+
*
|
17 |
+
* @return string|array|object Clipped value.
|
18 |
+
*/
|
19 |
+
public function clip($value, $max_length = 80, $force_ellipsis = false)
|
20 |
+
{
|
21 |
+
if (is_array($value) || is_object($value)) {
|
22 |
+
foreach ($value as $_key => &$_value) {
|
23 |
+
$_value = $this->clip($_value, $max_length, $force_ellipsis);
|
24 |
+
}
|
25 |
+
unset($_key, $_value); // Housekeeping.
|
26 |
+
|
27 |
+
return $value;
|
28 |
+
}
|
29 |
+
if (!($string = (string) $value)) {
|
30 |
+
return $string; // Empty.
|
31 |
+
}
|
32 |
+
$max_length = max(4, $max_length);
|
33 |
+
|
34 |
+
$string = strip_tags($string);
|
35 |
+
$string = preg_replace('/\s+/', ' ', strip_tags($string));
|
36 |
+
$string = trim($string); // Trim it up now.
|
37 |
+
|
38 |
+
if (strlen($string) > $max_length) {
|
39 |
+
$string = (string) substr($string, 0, $max_length - 3).'...';
|
40 |
+
} elseif ($force_ellipsis && strlen($string) + 3 > $max_length) {
|
41 |
+
$string = (string) substr($string, 0, $max_length - 3).'...';
|
42 |
+
} else {
|
43 |
+
$string .= $force_ellipsis ? '...' : '';
|
44 |
+
}
|
45 |
+
return $string;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Mid-clips string(s) to X chars deeply.
|
50 |
+
*
|
51 |
+
* @since 151114 Adding string utils.
|
52 |
+
*
|
53 |
+
* @param mixed $value Any input value.
|
54 |
+
* @param int $max_length Defaults to a value of `80`.
|
55 |
+
*
|
56 |
+
* @return string|array|object Mid-clipped value.
|
57 |
+
*/
|
58 |
+
public function midClip($value, $max_length = 80)
|
59 |
+
{
|
60 |
+
if (is_array($value) || is_object($value)) {
|
61 |
+
foreach ($value as $_key => &$_value) {
|
62 |
+
$_value = $this->midClip($_value, $max_length);
|
63 |
+
}
|
64 |
+
unset($_key, $_value); // Housekeeping.
|
65 |
+
|
66 |
+
return $value;
|
67 |
+
}
|
68 |
+
if (!($string = (string) $value)) {
|
69 |
+
return $string; // Empty.
|
70 |
+
}
|
71 |
+
$max_length = max(4, $max_length);
|
72 |
+
|
73 |
+
$string = strip_tags($string);
|
74 |
+
$string = preg_replace('/\s+/', ' ', strip_tags($string));
|
75 |
+
$string = trim($string); // Trim it up now.
|
76 |
+
|
77 |
+
if (strlen($string) <= $max_length) {
|
78 |
+
return $string; // Nothing to do.
|
79 |
+
}
|
80 |
+
$full_string = $string;
|
81 |
+
$half_max_length = floor($max_length / 2);
|
82 |
+
|
83 |
+
$first_clip = $half_max_length - 3;
|
84 |
+
$string = $first_clip >= 1 // Something?
|
85 |
+
? substr($full_string, 0, $first_clip).'...'
|
86 |
+
: '...'; // Ellipsis only.
|
87 |
+
|
88 |
+
$second_clip = strlen($full_string) - ($max_length - strlen($string));
|
89 |
+
$string .= $second_clip >= 0 && $second_clip >= $first_clip
|
90 |
+
? substr($full_string, $second_clip) : '';
|
91 |
+
|
92 |
+
return $string;
|
93 |
+
}
|
94 |
+
}
|
src/includes/traits/Shared/SysUtils.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait SysUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* System load averages.
|
10 |
+
*
|
11 |
+
* @since 151002 Adding cache directory statistics.
|
12 |
+
*
|
13 |
+
* @return array System load averages.
|
14 |
+
*/
|
15 |
+
public function sysLoadAverages()
|
16 |
+
{
|
17 |
+
if (!is_null($averages = &$this->cacheKey('sysLoadAverages'))) {
|
18 |
+
return $averages; // Already cached these.
|
19 |
+
}
|
20 |
+
if (!$this->functionIsPossible('sys_getloadavg')) {
|
21 |
+
return $averages = [];
|
22 |
+
}
|
23 |
+
if (!is_array($averages = sys_getloadavg()) || !$averages) {
|
24 |
+
return $averages = [];
|
25 |
+
}
|
26 |
+
$averages = array_map('floatval', $averages);
|
27 |
+
$averages = array_slice($averages, 0, 3);
|
28 |
+
// i.e., 1m, 5m, 15m; see: <http://jas.xyz/1gWyJLt>
|
29 |
+
|
30 |
+
return $averages;
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* System memory info.
|
35 |
+
*
|
36 |
+
* @since 151002 Adding cache directory statistics.
|
37 |
+
*
|
38 |
+
* @return \stdClass|bool System memory info.
|
39 |
+
*/
|
40 |
+
public function sysMemoryStatus()
|
41 |
+
{
|
42 |
+
if (!is_null($status = &$this->cacheKey('sysMemoryStatus'))) {
|
43 |
+
return $status; // Already cached this.
|
44 |
+
}
|
45 |
+
if (!$this->functionIsPossible('shell_exec')) {
|
46 |
+
return $status = false;
|
47 |
+
}
|
48 |
+
if (!($free = trim((string) @shell_exec('free')))) {
|
49 |
+
return $status = false;
|
50 |
+
}
|
51 |
+
if (!($free_lines = explode("\n", $free))) {
|
52 |
+
return $status = false;
|
53 |
+
}
|
54 |
+
if (empty($free_lines[1])) {
|
55 |
+
return $status = false;
|
56 |
+
}
|
57 |
+
if (!($memory = explode(' ', $free_lines[1]))) {
|
58 |
+
return $status = false;
|
59 |
+
}
|
60 |
+
if (!($memory = array_merge(array_filter($memory)))) {
|
61 |
+
return $status = false;
|
62 |
+
}
|
63 |
+
if (!isset($memory[1], $memory[2])) {
|
64 |
+
return $status = false;
|
65 |
+
}
|
66 |
+
if (($total = (integer) $memory[1]) <= 0) {
|
67 |
+
return $status = false;
|
68 |
+
}
|
69 |
+
$used = (integer) $memory[2];
|
70 |
+
$percent = $used / $total * 100;
|
71 |
+
$percentage = sprintf(__('%s%%', 'comet-cache'), number_format($percent, 2, '.', ''));
|
72 |
+
$status = (object) compact('total', 'used', 'percent', 'percentage');
|
73 |
+
|
74 |
+
return $status;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* System opcache status/details.
|
79 |
+
*
|
80 |
+
* @since 151002 Adding cache directory statistics.
|
81 |
+
*
|
82 |
+
* @return \stdClass|bool System opcache status/details.
|
83 |
+
*/
|
84 |
+
public function sysOpcacheStatus()
|
85 |
+
{
|
86 |
+
if (!is_null($status = &$this->cacheKey('sysOpcacheStatus'))) {
|
87 |
+
return $status; // Already cached this.
|
88 |
+
}
|
89 |
+
if (!$this->functionIsPossible('opcache_get_status')) {
|
90 |
+
return $status = false;
|
91 |
+
}
|
92 |
+
if (!is_array($status = opcache_get_status(false)) || !$status) {
|
93 |
+
return $status = false;
|
94 |
+
}
|
95 |
+
if (empty($status['opcache_enabled'])) {
|
96 |
+
return $status = false;
|
97 |
+
}
|
98 |
+
return json_decode(json_encode($status));
|
99 |
+
}
|
100 |
+
}
|
src/includes/traits/Shared/TokenUtils.php
ADDED
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait TokenUtils
|
7 |
+
{
|
8 |
+
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Current host.
|
12 |
+
*
|
13 |
+
* @since 150422 Rewrite.
|
14 |
+
*
|
15 |
+
* @param bool $dashify Optional, defaults to a `FALSE` value.
|
16 |
+
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9]`.
|
17 |
+
* @param bool $consider_domain_mapping Consider?
|
18 |
+
* @param string $consider_domain_mapping_domain A specific domain?
|
19 |
+
*
|
20 |
+
* @return string Current host.
|
21 |
+
*
|
22 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
23 |
+
*/
|
24 |
+
public function hostToken($dashify = false, $consider_domain_mapping = false, $consider_domain_mapping_domain = '')
|
25 |
+
{
|
26 |
+
if (!is_null($token = &$this->staticKey('hostToken', [$dashify, $consider_domain_mapping, $consider_domain_mapping_domain]))) {
|
27 |
+
return $token; // Already cached this.
|
28 |
+
}
|
29 |
+
$token = ''; // Initialize token value.
|
30 |
+
|
31 |
+
if (!is_multisite() || $this->isAdvancedCache()) {
|
32 |
+
$token = (string) $_SERVER['HTTP_HOST'];
|
33 |
+
} elseif ($consider_domain_mapping && $this->canConsiderDomainMapping()) {
|
34 |
+
if (($consider_domain_mapping_domain = trim((string) $consider_domain_mapping_domain))) {
|
35 |
+
$token = $consider_domain_mapping_domain;
|
36 |
+
} elseif ($this->isDomainMapping()) {
|
37 |
+
$token = (string) $_SERVER['HTTP_HOST'];
|
38 |
+
} else { // For the current blog ID.
|
39 |
+
$token = $this->domainMappingUrlFilter($this->currentUrl());
|
40 |
+
$token = $this->parseUrl($token, PHP_URL_HOST);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
if (!$token) { // Use default?
|
44 |
+
$token = (string) $_SERVER['HTTP_HOST'];
|
45 |
+
}
|
46 |
+
if ($token) { // Have token?
|
47 |
+
$token = strtolower($token);
|
48 |
+
if ($dashify) { // Dashify it?
|
49 |
+
$token = preg_replace('/[^a-z0-9]/i', '-', $token);
|
50 |
+
$token = trim($token, '-');
|
51 |
+
}
|
52 |
+
}
|
53 |
+
return $token;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Host for a specific blog.
|
58 |
+
*
|
59 |
+
* @since 150821 Improving multisite compat.
|
60 |
+
*
|
61 |
+
* @param bool $dashify Optional, defaults to a `FALSE` value.
|
62 |
+
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9]`.
|
63 |
+
* @param bool $consider_domain_mapping Consider?
|
64 |
+
* @param string $consider_domain_mapping_domain A specific domain?
|
65 |
+
* @param bool $fallback Fallback on blog's domain when mapping?
|
66 |
+
* @param int $blog_id For which blog ID?
|
67 |
+
*
|
68 |
+
* @return string Host for a specific blog.
|
69 |
+
*
|
70 |
+
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
71 |
+
*/
|
72 |
+
public function hostTokenForBlog($dashify = false, $consider_domain_mapping = false, $consider_domain_mapping_domain = '', $fallback = false, $blog_id = 0)
|
73 |
+
{
|
74 |
+
if (!is_multisite() || $this->isAdvancedCache()) {
|
75 |
+
return $this->hostToken($dashify, $consider_domain_mapping, $consider_domain_mapping_domain);
|
76 |
+
}
|
77 |
+
$token = ''; // Initialize token value.
|
78 |
+
|
79 |
+
if ($consider_domain_mapping && $this->canConsiderDomainMapping()) {
|
80 |
+
if (($consider_domain_mapping_domain = trim((string) $consider_domain_mapping_domain))) {
|
81 |
+
$token = $consider_domain_mapping_domain; // Force this value.
|
82 |
+
} else {
|
83 |
+
$token = $this->domainMappingBlogDomain($blog_id, $fallback);
|
84 |
+
}
|
85 |
+
} elseif (($blog_details = $this->blogDetails($blog_id))) {
|
86 |
+
$token = $blog_details->domain; // Unmapped domain.
|
87 |
+
}
|
88 |
+
if ($token) { // Have token?
|
89 |
+
$token = strtolower($token);
|
90 |
+
if ($dashify) { // Dashify it?
|
91 |
+
$token = preg_replace('/[^a-z0-9]/i', '-', $token);
|
92 |
+
$token = trim($token, '-');
|
93 |
+
}
|
94 |
+
}
|
95 |
+
return $token;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Current site's base directory.
|
100 |
+
*
|
101 |
+
* @since 150422 Rewrite.
|
102 |
+
*
|
103 |
+
* @param bool $dashify Optional, defaults to a `FALSE` value.
|
104 |
+
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9\/]`.
|
105 |
+
* @param bool $consider_domain_mapping Consider?
|
106 |
+
*
|
107 |
+
* @return string Current site's base directory.
|
108 |
+
*
|
109 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
110 |
+
*/
|
111 |
+
public function hostBaseToken($dashify = false, $consider_domain_mapping = false)
|
112 |
+
{
|
113 |
+
if (!is_null($token = &$this->staticKey('hostBaseToken', [$dashify, $consider_domain_mapping]))) {
|
114 |
+
return $token; // Already cached this.
|
115 |
+
}
|
116 |
+
$token = '/'; // Assume NOT multisite; or own domain.
|
117 |
+
|
118 |
+
if (!is_multisite()) {
|
119 |
+
return $token; // Not applicable.
|
120 |
+
}
|
121 |
+
if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
|
122 |
+
return $token; // Not applicable.
|
123 |
+
}
|
124 |
+
if ($consider_domain_mapping && $this->canConsiderDomainMapping()) {
|
125 |
+
return $token; // Not applicable.
|
126 |
+
}
|
127 |
+
if (defined('PATH_CURRENT_SITE')) {
|
128 |
+
$token = (string) PATH_CURRENT_SITE;
|
129 |
+
}
|
130 |
+
$token = trim($token, '\\/'." \t\n\r\0\x0B");
|
131 |
+
$token = isset($token[0]) ? '/'.$token.'/' : '/';
|
132 |
+
|
133 |
+
if ($token !== '/' && $dashify) {
|
134 |
+
$token = preg_replace('/[^a-z0-9\/]/i', '-', $token);
|
135 |
+
$token = trim($token, '-');
|
136 |
+
}
|
137 |
+
return $token;
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Current blog's sub-directory.
|
142 |
+
*
|
143 |
+
* @since 150422 Rewrite.
|
144 |
+
*
|
145 |
+
* @param bool $dashify Optional, defaults to a `FALSE` value.
|
146 |
+
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9\/]`.
|
147 |
+
* @param bool $consider_domain_mapping Consider?
|
148 |
+
* @param string $path Defaults to the current URI path.
|
149 |
+
*
|
150 |
+
* @return string Current blog's sub-directory.
|
151 |
+
*
|
152 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
153 |
+
*/
|
154 |
+
public function hostDirToken($dashify = false, $consider_domain_mapping = false, $path = null)
|
155 |
+
{
|
156 |
+
if (!isset($path)) { // Use current/default path?
|
157 |
+
$path = (string) $this->parseUrl($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
158 |
+
}
|
159 |
+
$path = '/'.ltrim((string) $path, '/'); // Force leading slash.
|
160 |
+
|
161 |
+
if (!is_null($token = &$this->staticKey('hostDirToken', [$dashify, $consider_domain_mapping, $path]))) {
|
162 |
+
return $token; // Already cached this.
|
163 |
+
}
|
164 |
+
$token = '/'; // Assume NOT multisite; or own domain.
|
165 |
+
|
166 |
+
if (!is_multisite()) {
|
167 |
+
return $token; // Not applicable.
|
168 |
+
}
|
169 |
+
if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
|
170 |
+
return $token; // Not applicable.
|
171 |
+
}
|
172 |
+
if ($consider_domain_mapping && $this->canConsiderDomainMapping()) {
|
173 |
+
return $token; // Not applicable.
|
174 |
+
}
|
175 |
+
if ($path && $path !== '/' && ($host_base_token = trim($this->hostBaseToken(), '/'))) {
|
176 |
+
$path_minus_base = preg_replace('/^\/'.preg_quote($host_base_token, '/').'(\/|$)/i', '${1}', $path);
|
177 |
+
} else {
|
178 |
+
$path_minus_base = $path; // Default value.
|
179 |
+
}
|
180 |
+
list($token) = explode('/', trim($path_minus_base, '/'));
|
181 |
+
$token = trim($token, '\\/'." \t\n\r\0\x0B");
|
182 |
+
$token = isset($token[0]) ? '/'.$token.'/' : '/';
|
183 |
+
|
184 |
+
if ($token !== '/') { // Perhaps NOT the main site?
|
185 |
+
$blog_paths_file = $this->cacheDir().'/'.strtolower(SHORT_NAME).'-blog-paths';
|
186 |
+
if (!is_file($blog_paths_file) || !in_array($token, unserialize(file_get_contents($blog_paths_file)), true)) {
|
187 |
+
$token = '/'; // NOT a real/valid child blog path.
|
188 |
+
}
|
189 |
+
}
|
190 |
+
if ($token !== '/' && $dashify) {
|
191 |
+
$token = preg_replace('/[^a-z0-9\/]/i', '-', $token);
|
192 |
+
$token = trim($token, '-');
|
193 |
+
}
|
194 |
+
return $token;
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* A blog's sub-directory.
|
199 |
+
*
|
200 |
+
* @since 150821 Improving multisite compat.
|
201 |
+
*
|
202 |
+
* @param bool $dashify Optional, defaults to a `FALSE` value.
|
203 |
+
* If `TRUE`, the token is returned with dashes in place of `[^a-z0-9]`.
|
204 |
+
* @param bool $consider_domain_mapping Consider?
|
205 |
+
* @param int $blog_id For which blog ID?
|
206 |
+
*
|
207 |
+
* @return string A blog's sub-directory.
|
208 |
+
*
|
209 |
+
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
210 |
+
*/
|
211 |
+
public function hostDirTokenForBlog($dashify = false, $consider_domain_mapping = false, $blog_id = 0)
|
212 |
+
{
|
213 |
+
if (!is_multisite() || $this->isAdvancedCache()) {
|
214 |
+
return $this->hostDirToken($dashify, $consider_domain_mapping);
|
215 |
+
}
|
216 |
+
$token = '/'; // Initialize token value.
|
217 |
+
|
218 |
+
if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
|
219 |
+
return $token; // Not applicable.
|
220 |
+
}
|
221 |
+
if ($consider_domain_mapping && $this->canConsiderDomainMapping()) {
|
222 |
+
return $token; // Not applicable.
|
223 |
+
}
|
224 |
+
if (($blog_details = $this->blogDetails($blog_id))) {
|
225 |
+
$path = $blog_details->path; // e.g., `[/base]/path/` (includes base).
|
226 |
+
if ($path && $path !== '/' && ($host_base_token = trim($this->hostBaseToken(), '/'))) {
|
227 |
+
$path_minus_base = preg_replace('/^\/'.preg_quote($host_base_token, '/').'(\/|$)/i', '${1}', $path);
|
228 |
+
} else {
|
229 |
+
$path_minus_base = $path; // Default value.
|
230 |
+
}
|
231 |
+
list($token) = explode('/', trim($path_minus_base, '/'));
|
232 |
+
}
|
233 |
+
$token = trim($token, '\\/'." \t\n\r\0\x0B");
|
234 |
+
$token = isset($token[0]) ? '/'.$token.'/' : '/';
|
235 |
+
|
236 |
+
if ($token !== '/') { // Perhaps NOT the main site?
|
237 |
+
$blog_paths_file = $this->cacheDir().'/'.strtolower(SHORT_NAME).'-blog-paths';
|
238 |
+
if (!is_file($blog_paths_file) || !in_array($token, unserialize(file_get_contents($blog_paths_file)), true)) {
|
239 |
+
$token = '/'; // NOT a real/valid child blog path.
|
240 |
+
}
|
241 |
+
}
|
242 |
+
if ($token !== '/' && $dashify) {
|
243 |
+
$token = preg_replace('/[^a-z0-9\/]/i', '-', $token);
|
244 |
+
$token = trim($token, '-');
|
245 |
+
}
|
246 |
+
return $token;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Current site's base directory & current blog's sub-directory.
|
251 |
+
*
|
252 |
+
* @since 150422 Rewrite.
|
253 |
+
*
|
254 |
+
* @param bool $dashify Optional, defaults to a `FALSE` value.
|
255 |
+
* If `TRUE`, the tokens are returned with dashes in place of `[^a-z0-9\/]`.
|
256 |
+
* @param bool $consider_domain_mapping Consider?
|
257 |
+
* @param string $path Defaults to the current URI path.
|
258 |
+
*
|
259 |
+
* @return string Current site's base directory & current blog's sub-directory.
|
260 |
+
*
|
261 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
262 |
+
*/
|
263 |
+
public function hostBaseDirTokens($dashify = false, $consider_domain_mapping = false, $path = null)
|
264 |
+
{
|
265 |
+
if (!is_null($tokens = &$this->staticKey('hostBaseDirTokens', [$dashify, $consider_domain_mapping, $path]))) {
|
266 |
+
return $tokens; // Already cached this.
|
267 |
+
}
|
268 |
+
$tokens = $this->hostBaseToken($dashify, $consider_domain_mapping);
|
269 |
+
$tokens .= $this->hostDirToken($dashify, $consider_domain_mapping, $path);
|
270 |
+
|
271 |
+
return $tokens = preg_replace('/\/+/', '/', $tokens);
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* A site's base directory & a blog's sub-directory.
|
276 |
+
*
|
277 |
+
* @since 150821 Improving multisite compat.
|
278 |
+
*
|
279 |
+
* @param bool $dashify Optional, defaults to a `FALSE` value.
|
280 |
+
* If `TRUE`, the tokens are returned with dashes in place of `[^a-z0-9\/]`.
|
281 |
+
* @param bool $consider_domain_mapping Consider?
|
282 |
+
* @param int $blog_id For which blog ID?
|
283 |
+
*
|
284 |
+
* @return string A site's base directory & a blog's sub-directory.
|
285 |
+
*
|
286 |
+
* @note The return value of this function is NOT cached in support of `switch_to_blog()`.
|
287 |
+
*/
|
288 |
+
public function hostBaseDirTokensForBlog($dashify = false, $consider_domain_mapping = false, $blog_id = 0)
|
289 |
+
{
|
290 |
+
$tokens = $this->hostBaseToken($dashify, $consider_domain_mapping);
|
291 |
+
$tokens .= $this->hostDirTokenForBlog($dashify, $consider_domain_mapping, $blog_id);
|
292 |
+
|
293 |
+
return $tokens = preg_replace('/\/+/', '/', $tokens);
|
294 |
+
}
|
295 |
+
|
296 |
+
|
297 |
+
}
|
src/includes/traits/Shared/TrimUtils.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait TrimUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Trims strings deeply.
|
10 |
+
*
|
11 |
+
* @since 150422 Rewrite.
|
12 |
+
*
|
13 |
+
* @param mixed $values Any value can be converted into a trimmed string.
|
14 |
+
* Actually, objects can't, but this recurses into objects.
|
15 |
+
* @param string $chars Specific chars to trim.
|
16 |
+
* Defaults to PHP's trim: " \r\n\t\0\x0B". Use an empty string to bypass.
|
17 |
+
* @param string $extra_chars Additional chars to trim.
|
18 |
+
*
|
19 |
+
* @return string|array|object Trimmed string, array, object.
|
20 |
+
*/
|
21 |
+
public function trimDeep($values, $chars = '', $extra_chars = '')
|
22 |
+
{
|
23 |
+
if (is_array($values) || is_object($values)) {
|
24 |
+
foreach ($values as $_key => &$_values) {
|
25 |
+
$_values = $this->trimDeep($_values, $chars, $extra_chars);
|
26 |
+
}
|
27 |
+
unset($_key, $_values); // Housekeeping.
|
28 |
+
|
29 |
+
return $values;
|
30 |
+
}
|
31 |
+
$string = (string) $values;
|
32 |
+
$chars = (string) $chars;
|
33 |
+
$extra_chars = (string) $extra_chars;
|
34 |
+
|
35 |
+
$chars = isset($chars[0]) ? $chars : " \r\n\t\0\x0B";
|
36 |
+
$chars = $chars.$extra_chars; // Concatenate.
|
37 |
+
|
38 |
+
return trim($string, $chars);
|
39 |
+
}
|
40 |
+
}
|
src/includes/traits/Shared/UrlUtils.php
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WebSharks\CometCache\Traits\Shared;
|
3 |
+
|
4 |
+
use WebSharks\CometCache\Classes;
|
5 |
+
|
6 |
+
trait UrlUtils
|
7 |
+
{
|
8 |
+
/**
|
9 |
+
* Parses a URL.
|
10 |
+
*
|
11 |
+
* @since 150821 Improving multisite compat.
|
12 |
+
*
|
13 |
+
* @param string $url_uri_qsl Input URL, URI, or query string w/ a leading `?`.
|
14 |
+
* @param int $component Optional component to retrieve.
|
15 |
+
*
|
16 |
+
* @return array|string|int|null Array, else `string|int|null` component value.
|
17 |
+
*/
|
18 |
+
public function parseUrl($url_uri_qsl, $component = -1)
|
19 |
+
{
|
20 |
+
$url_uri_qsl = (string) $url_uri_qsl;
|
21 |
+
$component = (integer) $component;
|
22 |
+
${'//'} = strpos($url_uri_qsl, '//') === 0;
|
23 |
+
|
24 |
+
if ($url_uri_qsl && strpos($url_uri_qsl, '&') !== false) {
|
25 |
+
$url_uri_qsl = str_replace('&', '&', $url_uri_qsl);
|
26 |
+
}
|
27 |
+
if ($component > -1) {
|
28 |
+
if (${'//'} && $component === PHP_URL_SCHEME) {
|
29 |
+
return $part = '//';
|
30 |
+
}
|
31 |
+
return $part = parse_url($url_uri_qsl, $component);
|
32 |
+
} else {
|
33 |
+
if (!is_array($parts = parse_url($url_uri_qsl))) {
|
34 |
+
return $parts = [];
|
35 |
+
}
|
36 |
+
if (${'//'}) {
|
37 |
+
$parts['scheme'] = '//';
|
38 |
+
}
|
39 |
+
return $parts;
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Unparses a URL.
|
45 |
+
*
|
46 |
+
* @since 150821 Improving multisite compat.
|
47 |
+
*
|
48 |
+
* @param array $parts Input URL parts.
|
49 |
+
*
|
50 |
+
* @return string Unparsed URL in string format.
|
51 |
+
*/
|
52 |
+
public function unParseUrl(array $parts)
|
53 |
+
{
|
54 |
+
$scheme = '';
|
55 |
+
$host = '';
|
56 |
+
$port = '';
|
57 |
+
$user = '';
|
58 |
+
$pass = '';
|
59 |
+
$path = '';
|
60 |
+
$query = '';
|
61 |
+
$fragment = '';
|
62 |
+
|
63 |
+
if (!empty($parts['scheme'])) {
|
64 |
+
if ($parts['scheme'] === '//') {
|
65 |
+
$scheme = $parts['scheme'];
|
66 |
+
} else {
|
67 |
+
$scheme = $parts['scheme'].'://';
|
68 |
+
}
|
69 |
+
}
|
70 |
+
if (!empty($parts['host'])) {
|
71 |
+
$host = $parts['host'];
|
72 |
+
}
|
73 |
+
if (!empty($parts['port'])) {
|
74 |
+
$port = ':'.$parts['port'];
|
75 |
+
}
|
76 |
+
if (!empty($parts['user'])) {
|
77 |
+
$user = $parts['user'];
|
78 |
+
}
|
79 |
+
if (!empty($parts['pass'])) {
|
80 |
+
$pass = $parts['pass'];
|
81 |
+
}
|
82 |
+
if ($user || $pass) {
|
83 |
+
$pass .= '@';
|
84 |
+
}
|
85 |
+
if (!empty($parts['path'])) {
|
86 |
+
$path = '/'.ltrim($parts['path'], '/');
|
87 |
+
}
|
88 |
+
if (!empty($parts['query'])) {
|
89 |
+
$query = '?'.$parts['query'];
|
90 |
+
}
|
91 |
+
if (!empty($parts['fragment'])) {
|
92 |
+
$fragment = '#'.$parts['fragment'];
|
93 |
+
}
|
94 |
+
return $scheme.$user.$pass.$host.$port.$path.$query.$fragment;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Is the current request over SSL?
|
99 |
+
*
|
100 |
+
* @since 150422 Rewrite.
|
101 |
+
*
|
102 |
+
* @return bool `TRUE` if the current request is over SSL.
|
103 |
+
*
|
104 |
+
* @note The return value of this function is cached to reduce overhead on repeat calls.
|
105 |
+
*/
|
106 |
+
public function isSsl()
|
107 |
+
{
|
108 |
+
if (!is_null($is = &$this->staticKey('isSsl'))) {
|
109 |
+
return $is; // Already cached this.
|
110 |
+
}
|
111 |
+
if (!empty($_SERVER['SERVER_PORT'])) {
|
112 |
+
if ((integer) $_SERVER['SERVER_PORT'] === 443) {
|
113 |
+
return $is = true;
|
114 |
+
}
|
115 |
+
}
|
116 |
+
if (!empty($_SERVER['HTTPS'])) {
|
117 |
+
if (filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN)) {
|
118 |
+
return $is = true;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
|
122 |
+
if (strcasecmp((string) $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0) {
|
123 |
+
return $is = true;
|
124 |
+
}
|
125 |
+
}
|
126 |
+
return $is = false;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Current URL.
|
131 |
+
*
|
132 |
+
* @since 150821 Improving multisite compat.
|
133 |
+
*
|
134 |
+
* @return string Current URL.
|
135 |
+
*/
|
136 |
+
public function currentUrl()
|
137 |
+
{
|
138 |
+
return ($this->isSsl() ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
139 |
+
}
|
140 |
+
}
|
src/includes/translations/comet-cache.pot
DELETED
@@ -1,1927 +0,0 @@
|
|
1 |
-
# Copyright (C) 2016 Comet Cache
|
2 |
-
# This file is distributed under the same license as the Comet Cache package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"Project-Id-Version: Comet Cache 160227\n"
|
6 |
-
"Report-Msgid-Bugs-To: http://wordpress.org/tag/comet-cache\n"
|
7 |
-
"POT-Creation-Date: 2016-02-27 20:13:18+00:00\n"
|
8 |
-
"MIME-Version: 1.0\n"
|
9 |
-
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
-
"Content-Transfer-Encoding: 8bit\n"
|
11 |
-
"PO-Revision-Date: 2016-MO-DA HO:MI+ZONE\n"
|
12 |
-
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
-
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
-
|
15 |
-
#: plugin.php:17
|
16 |
-
msgid "<strong>NOTICE: Comet Cache Minimum PHP Version</strong></h3>"
|
17 |
-
msgstr ""
|
18 |
-
|
19 |
-
#: plugin.php:18
|
20 |
-
msgid "<strong>As of December 1st, 2015 Comet Cache requires PHP 5.4 or higher.</strong> Your server is currently running PHP v%1$s. You will need to upgrade to PHP 5.4 or higher to run this version of Comet Cache."
|
21 |
-
msgstr ""
|
22 |
-
|
23 |
-
#: plugin.php:19
|
24 |
-
msgid "Learn more about this change here: <a href=\"http://cometcache.com/r/new-minimum-php-version-php-5-4/\" target=\"_blank\">New Minimum PHP Version: PHP 5.4</a>"
|
25 |
-
msgstr ""
|
26 |
-
|
27 |
-
#: plugin.php:21
|
28 |
-
msgid "Your server is also running the <strong>outdated PHP APC extension</strong>. Please see: <a href=\"http://cometcache.com/r/php-apc-extension-no-longer-supported/\" target=\"_blank\">PHP APC Extension No Longer Supported</a>"
|
29 |
-
msgstr ""
|
30 |
-
|
31 |
-
#: plugin.php:39
|
32 |
-
msgid "<strong>NOTICE: Comet Cache + PHP APC Extension</strong></h3>"
|
33 |
-
msgstr ""
|
34 |
-
|
35 |
-
#: plugin.php:40
|
36 |
-
msgid "<strong>As of December 1st, 2015 Comet Cache no longer runs with the outdated PHP APC extension.</strong> It appears that you're currently running PHP v%1$s with APC enabled. You will need to follow one of the actions below to run this version of Comet Cache."
|
37 |
-
msgstr ""
|
38 |
-
|
39 |
-
#: plugin.php:41
|
40 |
-
msgid "<h4 style=\"margin:0 0 .5em 0; font-size:1.25em;\"><span class=\"dashicons dashicons-lightbulb\"></span> Options Available (Action Required):</h4>"
|
41 |
-
msgstr ""
|
42 |
-
|
43 |
-
#: plugin.php:43
|
44 |
-
msgid "Please add <code>ini_set('apc.cache_by_default', false);</code> to the top of your <code>/wp-config.php</code> file. That will get rid of this message and allow Comet Cache to run without issue."
|
45 |
-
msgstr ""
|
46 |
-
|
47 |
-
#: plugin.php:44
|
48 |
-
msgid "Or, contact your web hosting provider and ask about upgrading to PHP v5.5+; which includes the new <a href=\"http://cometcache.com/r/php-opcache-extension/\" target=\"_blank\">OPcache extension for PHP</a>. The new OPcache extension replaces APC in modern versions of PHP."
|
49 |
-
msgstr ""
|
50 |
-
|
51 |
-
#: plugin.php:46
|
52 |
-
msgid "To learn more about this change, please see the announcement: <a href=\"http://cometcache.com/r/php-apc-extension-no-longer-supported/\" target=\"_blank\">PHP APC Extension No Longer Supported</a>"
|
53 |
-
msgstr ""
|
54 |
-
|
55 |
-
#: plugin.php:66
|
56 |
-
msgid "<strong>NOTICE: Comet Cache Will Require the PHP <code>mbstring</code> Extension</strong></h3>"
|
57 |
-
msgstr ""
|
58 |
-
|
59 |
-
#: plugin.php:67
|
60 |
-
msgid "<strong>After March 1st, 2016 Comet Cache will require PHP Multibyte String support.</strong> It appears that your site is currently running PHP v%1$s <strong>without</strong> the <code>mbstring</code> extension enabled. You will need to contact your web hosting company and have them enable the PHP <code>mbstring</code> extension if you want to run the next version of Comet Cache."
|
61 |
-
msgstr ""
|
62 |
-
|
63 |
-
#: plugin.php:68
|
64 |
-
msgid "The <code>mbstring</code> extension provides Multibyte String support to PHP and is required to properly handle UTF-8 characters, which many sites now use. Without Multibyte String support, Comet Cache will be unstable. For that reason we are requiring the <code>mbstring</code> extension to improve reliablity when caching and to prevent your site from experiencing unforeseen issues in the future."
|
65 |
-
msgstr ""
|
66 |
-
|
67 |
-
#: src/includes/classes/AbsBase.php:116
|
68 |
-
msgid "Undefined overload property: `%1$s`."
|
69 |
-
msgstr ""
|
70 |
-
|
71 |
-
#: src/includes/classes/AbsBase.php:134
|
72 |
-
msgid "Refused to set overload property: `%1$s`."
|
73 |
-
msgstr ""
|
74 |
-
|
75 |
-
#: src/includes/classes/AbsBase.php:151
|
76 |
-
msgid "Refused to unset overload property: `%1$s`."
|
77 |
-
msgstr ""
|
78 |
-
|
79 |
-
#: src/includes/classes/AbsBaseAp.php:57
|
80 |
-
msgid "Undefined method/closure: `%1$s`."
|
81 |
-
msgstr ""
|
82 |
-
|
83 |
-
#: src/includes/classes/Conflicts.php:89
|
84 |
-
msgid "Pro"
|
85 |
-
msgstr ""
|
86 |
-
|
87 |
-
#: src/includes/classes/Conflicts.php:90
|
88 |
-
msgid "Lite"
|
89 |
-
msgstr ""
|
90 |
-
|
91 |
-
#: src/includes/classes/Conflicts.php:95
|
92 |
-
msgid "<strong>%1$s</strong> is NOT running. A conflicting plugin, <strong>%2$s</strong>, is currently active. Please deactivate the %2$s plugin to clear this message."
|
93 |
-
msgstr ""
|
94 |
-
|
95 |
-
#: src/includes/classes/MenuPageOptions.php:30
|
96 |
-
msgid "Wipe Cache (Start Fresh); clears the cache for all sites in this network at once!"
|
97 |
-
msgstr ""
|
98 |
-
|
99 |
-
#: src/includes/classes/MenuPageOptions.php:32
|
100 |
-
msgid "Wipe"
|
101 |
-
msgstr ""
|
102 |
-
|
103 |
-
#: src/includes/classes/MenuPageOptions.php:34
|
104 |
-
msgid "Clear Cache (Start Fresh)"
|
105 |
-
msgstr ""
|
106 |
-
|
107 |
-
#: src/includes/classes/MenuPageOptions.php:34
|
108 |
-
msgid "; affects the current site only."
|
109 |
-
msgstr ""
|
110 |
-
|
111 |
-
#: src/includes/classes/MenuPageOptions.php:36
|
112 |
-
msgid "Clear"
|
113 |
-
msgstr ""
|
114 |
-
|
115 |
-
#: src/includes/classes/MenuPageOptions.php:39
|
116 |
-
msgid "Restore default plugin options? You will lose all of your current settings! Are you absolutely sure about this?"
|
117 |
-
msgstr ""
|
118 |
-
|
119 |
-
#: src/includes/classes/MenuPageOptions.php:41
|
120 |
-
msgid "Restore"
|
121 |
-
msgstr ""
|
122 |
-
|
123 |
-
#: src/includes/classes/MenuPageOptions.php:43
|
124 |
-
msgid "All Panels"
|
125 |
-
msgstr ""
|
126 |
-
|
127 |
-
#: src/includes/classes/MenuPageOptions.php:50
|
128 |
-
msgid "Pro Updater"
|
129 |
-
msgstr ""
|
130 |
-
|
131 |
-
#: src/includes/classes/MenuPageOptions.php:51
|
132 |
-
#: src/includes/classes/MenuPageOptions.php:73
|
133 |
-
msgid "Newsletter"
|
134 |
-
msgstr ""
|
135 |
-
|
136 |
-
#: src/includes/classes/MenuPageOptions.php:52
|
137 |
-
#: src/includes/classes/MenuPageOptions.php:74
|
138 |
-
msgid "Beta Testers"
|
139 |
-
msgstr ""
|
140 |
-
|
141 |
-
#: src/includes/classes/MenuPageOptions.php:55
|
142 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:120
|
143 |
-
msgid "Preview Pro Features"
|
144 |
-
msgstr ""
|
145 |
-
|
146 |
-
#: src/includes/classes/MenuPageOptions.php:56
|
147 |
-
msgid "Pro Upgrade"
|
148 |
-
msgstr ""
|
149 |
-
|
150 |
-
#: src/includes/classes/MenuPageOptions.php:62
|
151 |
-
msgid "Support"
|
152 |
-
msgstr ""
|
153 |
-
|
154 |
-
#: src/includes/classes/MenuPageOptions.php:65
|
155 |
-
msgid "Community Forum"
|
156 |
-
msgstr ""
|
157 |
-
|
158 |
-
#: src/includes/classes/MenuPageOptions.php:67
|
159 |
-
msgid "Knowledge Base"
|
160 |
-
msgstr ""
|
161 |
-
|
162 |
-
#: src/includes/classes/MenuPageOptions.php:68
|
163 |
-
msgid "Blog"
|
164 |
-
msgstr ""
|
165 |
-
|
166 |
-
#: src/includes/classes/MenuPageOptions.php:80
|
167 |
-
msgid "%1$s™ Pro v%2$s"
|
168 |
-
msgstr ""
|
169 |
-
|
170 |
-
#: src/includes/classes/MenuPageOptions.php:83
|
171 |
-
#: src/includes/classes/MenuPageOptions.php:93
|
172 |
-
msgid "update available"
|
173 |
-
msgstr ""
|
174 |
-
|
175 |
-
#: src/includes/classes/MenuPageOptions.php:85
|
176 |
-
#: src/includes/classes/MenuPageOptions.php:95
|
177 |
-
msgid "changelog"
|
178 |
-
msgstr ""
|
179 |
-
|
180 |
-
#: src/includes/classes/MenuPageOptions.php:90
|
181 |
-
msgid "%1$s™ v%2$s"
|
182 |
-
msgstr ""
|
183 |
-
|
184 |
-
#: src/includes/classes/MenuPageOptions.php:99
|
185 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:73
|
186 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:95
|
187 |
-
msgid "Plugin Options"
|
188 |
-
msgstr ""
|
189 |
-
|
190 |
-
#: src/includes/classes/MenuPageOptions.php:113
|
191 |
-
msgid "Options updated successfully."
|
192 |
-
msgstr ""
|
193 |
-
|
194 |
-
#: src/includes/classes/MenuPageOptions.php:118
|
195 |
-
msgid "Default options successfully restored."
|
196 |
-
msgstr ""
|
197 |
-
|
198 |
-
#: src/includes/classes/MenuPageOptions.php:123
|
199 |
-
msgid "Cache wiped across all sites; recreation will occur automatically over time."
|
200 |
-
msgstr ""
|
201 |
-
|
202 |
-
#: src/includes/classes/MenuPageOptions.php:129
|
203 |
-
msgid "Cache cleared for main site; recreation will occur automatically over time."
|
204 |
-
msgstr ""
|
205 |
-
|
206 |
-
#: src/includes/classes/MenuPageOptions.php:131
|
207 |
-
msgid "Cache cleared for this site; recreation will occur automatically over time."
|
208 |
-
msgstr ""
|
209 |
-
|
210 |
-
#: src/includes/classes/MenuPageOptions.php:137
|
211 |
-
#: src/includes/classes/MenuPageOptions.php:142
|
212 |
-
msgid "Failed to update your <code>/.htaccess</code> file automatically. Most likely a permissions error. Please make sure it has permissions <code>644</code> or higher (perhaps <code>666</code>). Once you've done this, please try saving the %1$s options again."
|
213 |
-
msgstr ""
|
214 |
-
|
215 |
-
#: src/includes/classes/MenuPageOptions.php:147
|
216 |
-
msgid "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>. 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>."
|
217 |
-
msgstr ""
|
218 |
-
|
219 |
-
#: src/includes/classes/MenuPageOptions.php:152
|
220 |
-
msgid "Failed to update your <code>/wp-config.php</code> file automatically. Please add the following line to your <code>/wp-config.php</code> file (right after the opening <code><?php</code> tag; on it's own line). <pre class=\"code\"><code><?php<br />define('WP_CACHE', TRUE);</code></pre>"
|
221 |
-
msgstr ""
|
222 |
-
|
223 |
-
#: src/includes/classes/MenuPageOptions.php:157
|
224 |
-
msgid "Failed to update your <code>/wp-config.php</code> file automatically. Please remove the following line from your <code>/wp-config.php</code> file, or set <code>WP_CACHE</code> to a <code>FALSE</code> value. <pre class=\"code\"><code>define('WP_CACHE', TRUE);</code></pre>"
|
225 |
-
msgstr ""
|
226 |
-
|
227 |
-
#: src/includes/classes/MenuPageOptions.php:163
|
228 |
-
msgid "Failed to update your <code>/wp-content/advanced-cache.php</code> file. Cannot write stat file: <code>%1$s/%2$s-advanced-cache</code>. Please be sure this directory exists (and that it's writable): <code>%1$s</code>. Please use directory permissions <code>755</code> or higher (perhaps <code>777</code>). Once you've done this, please try again."
|
229 |
-
msgstr ""
|
230 |
-
|
231 |
-
#: src/includes/classes/MenuPageOptions.php:165
|
232 |
-
msgid "Failed to update your <code>/wp-content/advanced-cache.php</code> file. Most likely a permissions error. Please create an empty file here: <code>/wp-content/advanced-cache.php</code> (just an empty PHP file, with nothing in it); give it permissions <code>644</code> or higher (perhaps <code>666</code>). Once you've done this, please try again."
|
233 |
-
msgstr ""
|
234 |
-
|
235 |
-
#: src/includes/classes/MenuPageOptions.php:171
|
236 |
-
msgid "Failed to remove your <code>/wp-content/advanced-cache.php</code> file. Most likely a permissions error. Please delete (or empty the contents of) this file: <code>/wp-content/advanced-cache.php</code>."
|
237 |
-
msgstr ""
|
238 |
-
|
239 |
-
#: src/includes/classes/MenuPageOptions.php:176
|
240 |
-
msgid "close"
|
241 |
-
msgstr ""
|
242 |
-
|
243 |
-
#: src/includes/classes/MenuPageOptions.php:177
|
244 |
-
msgid "<strong>Pro Features (Preview)</strong> ~ New option panels below. Please explore before <a href=\"http://cometcache.com/prices/\" target=\"_blank\">upgrading <i class=\"si si-heart-o\"></i></a>.<br /><small>NOTE: the free version of %1$s (this lite version) is more-than-adequate for most sites. Please upgrade only if you desire advanced features or would like to support the developer.</small>"
|
245 |
-
msgstr ""
|
246 |
-
|
247 |
-
#: src/includes/classes/MenuPageOptions.php:182
|
248 |
-
msgid "%1$s is currently disabled; please review options below."
|
249 |
-
msgstr ""
|
250 |
-
|
251 |
-
#: src/includes/classes/MenuPageOptions.php:192
|
252 |
-
msgid "Basic Configuration (Required)"
|
253 |
-
msgstr ""
|
254 |
-
|
255 |
-
#: src/includes/classes/MenuPageOptions.php:193
|
256 |
-
msgid "Review these basic options and %1$s™ will be ready-to-go!"
|
257 |
-
msgstr ""
|
258 |
-
|
259 |
-
#: src/includes/classes/MenuPageOptions.php:201
|
260 |
-
msgid "Enable/Disable"
|
261 |
-
msgstr ""
|
262 |
-
|
263 |
-
#: src/includes/classes/MenuPageOptions.php:206
|
264 |
-
msgid "%1$s™ = SPEED<em>!!</em>"
|
265 |
-
msgstr ""
|
266 |
-
|
267 |
-
#: src/includes/classes/MenuPageOptions.php:207
|
268 |
-
msgid "Yes, enable %1$s™"
|
269 |
-
msgstr ""
|
270 |
-
|
271 |
-
#: src/includes/classes/MenuPageOptions.php:207
|
272 |
-
msgid "No, disable."
|
273 |
-
msgstr ""
|
274 |
-
|
275 |
-
#: src/includes/classes/MenuPageOptions.php:208
|
276 |
-
msgid "<strong>HUGE Time-Saver:</strong> Approx. 95%% of all WordPress sites running %1$s, simply enable it here; and that's it :-) <strong>No further configuration is necessary (really).</strong> All of the other options (down below) are already tuned for the BEST performance on a typical WordPress installation. Simply enable %1$s here and click \"Save All Changes\". If you get any warnings please follow the instructions given. Otherwise, you're good <i class=\"si si-smile-o\"></i>. This plugin is designed to run just fine like it is. Take it for a spin right away; you can always fine-tune things later if you deem necessary."
|
277 |
-
msgstr ""
|
278 |
-
|
279 |
-
#: src/includes/classes/MenuPageOptions.php:211
|
280 |
-
msgid "How Can I Tell %1$s is Working?"
|
281 |
-
msgstr ""
|
282 |
-
|
283 |
-
#: src/includes/classes/MenuPageOptions.php:212
|
284 |
-
msgid "First of all, please make sure that you've enabled %1$s here; then scroll down to the bottom of this page and click \"Save All Changes\". All of the other options (below) are already pre-configured for typical usage. Feel free to skip them all for now. You can go back through all of these later and fine-tune things the way you like them."
|
285 |
-
msgstr ""
|
286 |
-
|
287 |
-
#: src/includes/classes/MenuPageOptions.php:213
|
288 |
-
msgid "Once %1$s has been enabled, <strong>you'll need to log out (and/or clear browser cookies)</strong>. By default, cache files are NOT served to visitors who are logged-in, and that includes you too ;-) Cache files are NOT served to recent comment authors either. If you've commented (or replied to a comment lately); please clear your browser cookies before testing."
|
289 |
-
msgstr ""
|
290 |
-
|
291 |
-
#: src/includes/classes/MenuPageOptions.php:214
|
292 |
-
msgid "<strong>To verify that %1$s is working</strong>, navigate your site like a normal visitor would. Right-click on any page (choose View Source), then scroll to the very bottom of the document. At the bottom, you'll find comments that show %1$s stats and information. You should also notice that page-to-page navigation is <i class=\"si si-flash\"></i> <strong>lightning fast</strong> now that %1$s is running; and it gets faster over time!"
|
293 |
-
msgstr ""
|
294 |
-
|
295 |
-
#: src/includes/classes/MenuPageOptions.php:216
|
296 |
-
msgid "Yes, enable notes in the source code so I can see it's working (recommended)."
|
297 |
-
msgstr ""
|
298 |
-
|
299 |
-
#: src/includes/classes/MenuPageOptions.php:217
|
300 |
-
msgid "Yes, enable notes in the source code AND show debugging details (not recommended for production)."
|
301 |
-
msgstr ""
|
302 |
-
|
303 |
-
#: src/includes/classes/MenuPageOptions.php:218
|
304 |
-
msgid "No, I don't want my source code to contain any of these notes."
|
305 |
-
msgstr ""
|
306 |
-
|
307 |
-
#: src/includes/classes/MenuPageOptions.php:229
|
308 |
-
msgid "Plugin Deletion Safeguards"
|
309 |
-
msgstr ""
|
310 |
-
|
311 |
-
#: src/includes/classes/MenuPageOptions.php:234
|
312 |
-
msgid "Uninstall on Plugin Deletion; or Safeguard Options?"
|
313 |
-
msgstr ""
|
314 |
-
|
315 |
-
#: src/includes/classes/MenuPageOptions.php:235
|
316 |
-
msgid "<strong>Tip:</strong> By default, if you delete %1$s using the plugins menu in WordPress, nothing is lost. However, if you want to completely uninstall %1$s you should set this to <code>Yes</code> and <strong>THEN</strong> deactivate & delete %1$s from the plugins menu in WordPress. This way %1$s will erase your options for the plugin, erase directories/files created by the plugin, remove the <code>advanced-cache.php</code> file, terminate CRON jobs, etc. It erases itself from existence completely."
|
317 |
-
msgstr ""
|
318 |
-
|
319 |
-
#: src/includes/classes/MenuPageOptions.php:237
|
320 |
-
msgid "Safeguard my options and the cache (recommended)."
|
321 |
-
msgstr ""
|
322 |
-
|
323 |
-
#: src/includes/classes/MenuPageOptions.php:238
|
324 |
-
msgid "Yes, uninstall (completely erase) %1$s on plugin deletion."
|
325 |
-
msgstr ""
|
326 |
-
|
327 |
-
#: src/includes/classes/MenuPageOptions.php:247
|
328 |
-
msgid "Advanced Configuration (All Optional)"
|
329 |
-
msgstr ""
|
330 |
-
|
331 |
-
#: src/includes/classes/MenuPageOptions.php:248
|
332 |
-
msgid "Recommended for advanced site owners only; already pre-configured for most WP installs."
|
333 |
-
msgstr ""
|
334 |
-
|
335 |
-
#: src/includes/classes/MenuPageOptions.php:257
|
336 |
-
msgid "Manual Cache Clearing"
|
337 |
-
msgstr ""
|
338 |
-
|
339 |
-
#: src/includes/classes/MenuPageOptions.php:261
|
340 |
-
msgid "Clearing the Cache Manually"
|
341 |
-
msgstr ""
|
342 |
-
|
343 |
-
#: src/includes/classes/MenuPageOptions.php:263
|
344 |
-
msgid "Once %1$s is enabled, you will find this new option in your WordPress Admin Bar (screenshot on right). Clicking this button will clear the cache and you can start fresh at anytime (e.g., you can do this manually; and as often as you wish)."
|
345 |
-
msgstr ""
|
346 |
-
|
347 |
-
#: src/includes/classes/MenuPageOptions.php:264
|
348 |
-
msgid "Depending on the structure of your site, there could be many reasons to clear the cache. However, the most common reasons are related to Post/Page edits or deletions, Category/Tag edits or deletions, and Theme changes. %1$s handles most scenarios all by itself. However, many site owners like to clear the cache manually; for a variety of reasons (just to force a refresh)."
|
349 |
-
msgstr ""
|
350 |
-
|
351 |
-
#: src/includes/classes/MenuPageOptions.php:266
|
352 |
-
msgid "Yes, enable "Clear Cache" button in admin bar"
|
353 |
-
msgstr ""
|
354 |
-
|
355 |
-
#: src/includes/classes/MenuPageOptions.php:267
|
356 |
-
msgid "No, I don't intend to clear the cache manually."
|
357 |
-
msgstr ""
|
358 |
-
|
359 |
-
#: src/includes/classes/MenuPageOptions.php:270
|
360 |
-
msgid "w/ dropdown options."
|
361 |
-
msgstr ""
|
362 |
-
|
363 |
-
#: src/includes/classes/MenuPageOptions.php:271
|
364 |
-
msgid "w/ dropdown options in split menu."
|
365 |
-
msgstr ""
|
366 |
-
|
367 |
-
#: src/includes/classes/MenuPageOptions.php:272
|
368 |
-
msgid "w/o dropdown options."
|
369 |
-
msgstr ""
|
370 |
-
|
371 |
-
#: src/includes/classes/MenuPageOptions.php:277
|
372 |
-
msgid "Also allow Child Sites in a Network to clear the cache from their Admin Bar?"
|
373 |
-
msgstr ""
|
374 |
-
|
375 |
-
#: src/includes/classes/MenuPageOptions.php:278
|
376 |
-
msgid "In a Multisite Network, each child site can clear its own cache. If you want child sites to see the \"Clear Cache\" button in their WordPress Admin Bar, you can specify a comma-delimited list of <a href=\"http://cometcache.com/r/wp-roles-caps/\" target=\"_blank\">Roles and/or Capabilities</a> that are allowed. For example, if I want Administrators to be capable of clearing the cache from their Admin Bar, I could enter <code>administrator</code> here. If I also want to allow Editors, I can use a comma-delimited list: <code>administrator,editor</code>. Or, I could use a single Capability of: <code>edit_others_posts</code>; which covers both Administrators & Editors at the same time."
|
377 |
-
msgstr ""
|
378 |
-
|
379 |
-
#: src/includes/classes/MenuPageOptions.php:280
|
380 |
-
#: src/includes/classes/MenuPageOptions.php:471
|
381 |
-
msgid "<strong>Note:</strong> As a security measure, in addition to the Role(s) and/or Capabilities that you list here, each child site owner must also have the ability to <code>%1$s</code>."
|
382 |
-
msgstr ""
|
383 |
-
|
384 |
-
#: src/includes/classes/MenuPageOptions.php:285
|
385 |
-
msgid "Also allow others to clear the cache from their Admin Bar?"
|
386 |
-
msgstr ""
|
387 |
-
|
388 |
-
#: src/includes/classes/MenuPageOptions.php:286
|
389 |
-
msgid "If you want others to see the \"Clear Cache\" button in their WordPress Admin Bar, you can specify a comma-delimited list of <a href=\"http://cometcache.com/r/wp-roles-caps/\" target=\"_blank\">Roles and/or Capabilities</a> that are allowed. For example, if I want Editors to be capable of clearing the cache from their Admin Bar, I could enter <code>editor</code> here. If I also want to allow Authors, I can use a comma-delimited list: <code>editor,author</code>. Or, I could use a single Capability of: <code>publish_posts</code>; which covers both Editors & Authors at the same time."
|
390 |
-
msgstr ""
|
391 |
-
|
392 |
-
#: src/includes/classes/MenuPageOptions.php:288
|
393 |
-
#: src/includes/classes/MenuPageOptions.php:479
|
394 |
-
msgid "<strong>Note:</strong> As a security measure, in addition to the Role(s) and/or Capabilities that you list here, each user must also have the ability to <code>%1$s</code>."
|
395 |
-
msgstr ""
|
396 |
-
|
397 |
-
#: src/includes/classes/MenuPageOptions.php:294
|
398 |
-
msgid "Clear the <a href=\"http://cometcache.com/r/php-opcache/\" target=\"_blank\">PHP OPcache</a> Too?"
|
399 |
-
msgstr ""
|
400 |
-
|
401 |
-
#: src/includes/classes/MenuPageOptions.php:295
|
402 |
-
msgid "If you clear the cache manually, do you want %1$s to clear the PHP OPcache too? This is not necessary, but if you want a truly clean start, this will clear all PHP files in the server's opcode cache also. Note: If you don't already know what the PHP OPcache is, it is suggested that you leave this disabled. It really is not necessary. This is just an added feature for advanced users."
|
403 |
-
msgstr ""
|
404 |
-
|
405 |
-
#: src/includes/classes/MenuPageOptions.php:297
|
406 |
-
msgid "No, I don't use the PHP OPcache extension; or, I don't want the opcode cache cleared."
|
407 |
-
msgstr ""
|
408 |
-
|
409 |
-
#: src/includes/classes/MenuPageOptions.php:298
|
410 |
-
msgid "Yes, if the PHP OPcache extension is enabled, also clear the entire PHP opcode cache."
|
411 |
-
msgstr ""
|
412 |
-
|
413 |
-
#: src/includes/classes/MenuPageOptions.php:303
|
414 |
-
msgid "Clear the <a href=\"http://websharks-inc.com/product/s2clean/\" target=\"_blank\">s2Clean</a> Cache Too?"
|
415 |
-
msgstr ""
|
416 |
-
|
417 |
-
#: src/includes/classes/MenuPageOptions.php:304
|
418 |
-
msgid "If the s2Clean theme is installed, and you clear the cache manually, %1$s can clear the s2Clean Markdown cache too (if you've enabled Markdown processing with s2Clean)."
|
419 |
-
msgstr ""
|
420 |
-
|
421 |
-
#: src/includes/classes/MenuPageOptions.php:306
|
422 |
-
msgid "Yes, if the s2Clean theme is installed, also clear s2Clean-related caches."
|
423 |
-
msgstr ""
|
424 |
-
|
425 |
-
#: src/includes/classes/MenuPageOptions.php:307
|
426 |
-
msgid "No, I don't use s2Clean; or, I don't want s2Clean-related caches cleared."
|
427 |
-
msgstr ""
|
428 |
-
|
429 |
-
#: src/includes/classes/MenuPageOptions.php:311
|
430 |
-
msgid "Evaluate Custom PHP Code when Clearing the Cache?"
|
431 |
-
msgstr ""
|
432 |
-
|
433 |
-
#: src/includes/classes/MenuPageOptions.php:312
|
434 |
-
msgid "If you have any custom routines you'd like to process when the cache is cleared manually, please enter PHP code here. If your PHP code outputs a message, it will be displayed along with any other notes from %1$s itself. This feature is intended for developers, and it may come in handy if you need to clear any system caches not already covered by %1$s configuration options."
|
435 |
-
msgstr ""
|
436 |
-
|
437 |
-
#: src/includes/classes/MenuPageOptions.php:314
|
438 |
-
msgid "<strong>Example:</strong> <code><?php apc_clear_cache(); echo '<p>Also cleared APC cache.</p>'; ?></code>"
|
439 |
-
msgstr ""
|
440 |
-
|
441 |
-
#: src/includes/classes/MenuPageOptions.php:317
|
442 |
-
msgid "Clear the CDN Cache Too?"
|
443 |
-
msgstr ""
|
444 |
-
|
445 |
-
#: src/includes/classes/MenuPageOptions.php:318
|
446 |
-
msgid "If you clear the cache manually, do you want %1$s to automatically bump the CDN invalidation counter too? i.e., automatically increment the <code>?%2$s=[counter]</code> in all static CDN URLs?"
|
447 |
-
msgstr ""
|
448 |
-
|
449 |
-
#: src/includes/classes/MenuPageOptions.php:320
|
450 |
-
msgid "No, I don't use Static CDN Filters; or, I don't want the CDN cache cleared."
|
451 |
-
msgstr ""
|
452 |
-
|
453 |
-
#: src/includes/classes/MenuPageOptions.php:321
|
454 |
-
msgid "Yes, if Static CDN Filters are enabled, also clear the CDN cache."
|
455 |
-
msgstr ""
|
456 |
-
|
457 |
-
#: src/includes/classes/MenuPageOptions.php:332
|
458 |
-
msgid "Automatic Cache Clearing"
|
459 |
-
msgstr ""
|
460 |
-
|
461 |
-
#: src/includes/classes/MenuPageOptions.php:337
|
462 |
-
msgid "Clearing the Cache Automatically"
|
463 |
-
msgstr ""
|
464 |
-
|
465 |
-
#: src/includes/classes/MenuPageOptions.php:339
|
466 |
-
msgid "This is built into the %1$s plugin; i.e., this functionality is \"always on\". If you edit a Post/Page (or delete one), %1$s will automatically clear the cache file(s) associated with that content. This way a new updated version of the cache will be created automatically the next time this content is accessed. Simple updates like this occur each time you make changes in the Dashboard, and %1$s will notify you of these as they occur. %1$s monitors changes to Posts (of any kind, including Pages), Categories, Tags, Links, Themes (even Users), and more."
|
467 |
-
msgstr ""
|
468 |
-
|
469 |
-
#: src/includes/classes/MenuPageOptions.php:343
|
470 |
-
msgid "Yes, enable %1$s notifications in the Dashboard when changes are detected & one or more cache files are cleared automatically."
|
471 |
-
msgstr ""
|
472 |
-
|
473 |
-
#: src/includes/classes/MenuPageOptions.php:344
|
474 |
-
msgid "No, I don't want to know (don't really care) what %1$s is doing behind-the-scene."
|
475 |
-
msgstr ""
|
476 |
-
|
477 |
-
#: src/includes/classes/MenuPageOptions.php:349
|
478 |
-
msgid "Primary Page Options"
|
479 |
-
msgstr ""
|
480 |
-
|
481 |
-
#: src/includes/classes/MenuPageOptions.php:351
|
482 |
-
msgid "Auto-Clear Designated \"Home Page\" Too?"
|
483 |
-
msgstr ""
|
484 |
-
|
485 |
-
#: src/includes/classes/MenuPageOptions.php:352
|
486 |
-
msgid "On many sites, the Home Page (aka: the Front Page) offers an archive view of all Posts (or even Pages). 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 \"Home Page\"?"
|
487 |
-
msgstr ""
|
488 |
-
|
489 |
-
#: src/includes/classes/MenuPageOptions.php:354
|
490 |
-
msgid "Yes, if any single Post/Page is cleared/reset; also clear the \"Home Page\"."
|
491 |
-
msgstr ""
|
492 |
-
|
493 |
-
#: src/includes/classes/MenuPageOptions.php:355
|
494 |
-
msgid "No, my Home Page does not provide a list of Posts/Pages; e.g., this is not necessary."
|
495 |
-
msgstr ""
|
496 |
-
|
497 |
-
#: src/includes/classes/MenuPageOptions.php:357
|
498 |
-
msgid "Auto-Clear Designated \"Posts Page\" Too?"
|
499 |
-
msgstr ""
|
500 |
-
|
501 |
-
#: src/includes/classes/MenuPageOptions.php:358
|
502 |
-
msgid "On many sites, the Posts Page (aka: the Blog Page) offers an archive view of all Posts (or even Pages). 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 \"Posts Page\"?"
|
503 |
-
msgstr ""
|
504 |
-
|
505 |
-
#: src/includes/classes/MenuPageOptions.php:360
|
506 |
-
msgid "Yes, if any single Post/Page is cleared/reset; also clear the \"Posts Page\"."
|
507 |
-
msgstr ""
|
508 |
-
|
509 |
-
#: src/includes/classes/MenuPageOptions.php:361
|
510 |
-
msgid "No, I don't use a separate Posts Page; e.g., my Home Page IS my Posts Page."
|
511 |
-
msgstr ""
|
512 |
-
|
513 |
-
#: src/includes/classes/MenuPageOptions.php:365
|
514 |
-
msgid "Author, Archive, and Tag/Term Options"
|
515 |
-
msgstr ""
|
516 |
-
|
517 |
-
#: src/includes/classes/MenuPageOptions.php:367
|
518 |
-
msgid "Auto-Clear \"Author Page\" Too?"
|
519 |
-
msgstr ""
|
520 |
-
|
521 |
-
#: src/includes/classes/MenuPageOptions.php:368
|
522 |
-
msgid "On many sites, each author has a related \"Author Page\" that offers an archive view of all posts associated with that author. 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 related \"Author Page\"?"
|
523 |
-
msgstr ""
|
524 |
-
|
525 |
-
#: src/includes/classes/MenuPageOptions.php:370
|
526 |
-
msgid "Yes, if any single Post/Page is cleared/reset; also clear the \"Author Page\"."
|
527 |
-
msgstr ""
|
528 |
-
|
529 |
-
#: src/includes/classes/MenuPageOptions.php:371
|
530 |
-
msgid "No, my site doesn't use multiple authors and/or I don't have any \"Author Page\" archive views."
|
531 |
-
msgstr ""
|
532 |
-
|
533 |
-
#: src/includes/classes/MenuPageOptions.php:374
|
534 |
-
msgid "Auto-Clear \"Category Archives\" Too?"
|
535 |
-
msgstr ""
|
536 |
-
|
537 |
-
#: src/includes/classes/MenuPageOptions.php:375
|
538 |
-
msgid "On many sites, each post is associated with at least one Category. Each category then has an archive view that contains all the posts within that category. 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 Category archive views?"
|
539 |
-
msgstr ""
|
540 |
-
|
541 |
-
#: src/includes/classes/MenuPageOptions.php:377
|
542 |
-
msgid "Yes, if any single Post/Page is cleared/reset; also clear the associated Category archive views."
|
543 |
-
msgstr ""
|
544 |
-
|
545 |
-
#: src/includes/classes/MenuPageOptions.php:378
|
546 |
-
msgid "No, my site doesn't use Categories and/or I don't have any Category archive views."
|
547 |
-
msgstr ""
|
548 |
-
|
549 |
-
#: src/includes/classes/MenuPageOptions.php:381
|
550 |
-
msgid "Auto-Clear \"Tag Archives\" Too?"
|
551 |
-
msgstr ""
|
552 |
-
|
553 |
-
#: src/includes/classes/MenuPageOptions.php:382
|
554 |
-
msgid "On many sites, each post may be associated with at least one Tag. Each tag then has an archive view that contains all the posts assigned that tag. 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?"
|
555 |
-
msgstr ""
|
556 |
-
|
557 |
-
#: src/includes/classes/MenuPageOptions.php:384
|
558 |
-
msgid "Yes, if any single Post/Page is cleared/reset; also clear the associated Tag archive views."
|
559 |
-
msgstr ""
|
560 |
-
|
561 |
-
#: src/includes/classes/MenuPageOptions.php:385
|
562 |
-
msgid "No, my site doesn't use Tags and/or I don't have any Tag archive views."
|
563 |
-
msgstr ""
|
564 |
-
|
565 |
-
#: src/includes/classes/MenuPageOptions.php:388
|
566 |
-
msgid "Auto-Clear \"Custom Term Archives\" Too?"
|
567 |
-
msgstr ""
|
568 |
-
|
569 |
-
#: src/includes/classes/MenuPageOptions.php:389
|
570 |
-
msgid "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?"
|
571 |
-
msgstr ""
|
572 |
-
|
573 |
-
#: src/includes/classes/MenuPageOptions.php:391
|
574 |
-
msgid "Yes, if any single Post/Page is cleared/reset; also clear any associated custom Term archive views."
|
575 |
-
msgstr ""
|
576 |
-
|
577 |
-
#: src/includes/classes/MenuPageOptions.php:392
|
578 |
-
msgid "No, my site doesn't use any custom Terms and/or I don't have any custom Term archive views."
|
579 |
-
msgstr ""
|
580 |
-
|
581 |
-
#: src/includes/classes/MenuPageOptions.php:395
|
582 |
-
msgid "Auto-Clear \"Custom Post Type Archives\" Too?"
|
583 |
-
msgstr ""
|
584 |
-
|
585 |
-
#: src/includes/classes/MenuPageOptions.php:396
|
586 |
-
msgid "Most sites do not use any Custom Post Types so it should be safe to disable this option. However, if your site uses Custom Post Types and they have their own Custom Post Type archive views, you may want to clear those when any associated post is cleared. Therefore, if a single Post with a Custom Post 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 the associated Custom Post Type archive views?"
|
587 |
-
msgstr ""
|
588 |
-
|
589 |
-
#: src/includes/classes/MenuPageOptions.php:398
|
590 |
-
msgid "Yes, if any single Post with a Custom Post Type is cleared/reset; also clear any associated Custom Post Type archive views."
|
591 |
-
msgstr ""
|
592 |
-
|
593 |
-
#: src/includes/classes/MenuPageOptions.php:399
|
594 |
-
msgid "No, my site doesn't use any Custom Post Types and/or I don't have any Custom Post Type archive views."
|
595 |
-
msgstr ""
|
596 |
-
|
597 |
-
#: src/includes/classes/MenuPageOptions.php:403
|
598 |
-
msgid "Feed-Related Options"
|
599 |
-
msgstr ""
|
600 |
-
|
601 |
-
#: src/includes/classes/MenuPageOptions.php:405
|
602 |
-
msgid "Auto-Clear \"RSS/RDF/ATOM Feeds\" Too?"
|
603 |
-
msgstr ""
|
604 |
-
|
605 |
-
#: src/includes/classes/MenuPageOptions.php:406
|
606 |
-
msgid "If you enable Feed Caching (below), this can be quite handy. If enabled, when you update a Post/Page, approve a Comment, or make other changes where %1$s can detect that certain types of Feeds should be cleared to keep your site up-to-date, then %1$s will do this for you automatically. For instance, the blog's master feed, the blog's master comments feed, feeds associated with comments on a Post/Page, term-related feeds (including mixed term-related feeds), author-related feeds, etc. Under various circumstances (i.e., as you work in the Dashboard) these can be cleared automatically to keep your site up-to-date."
|
607 |
-
msgstr ""
|
608 |
-
|
609 |
-
#: src/includes/classes/MenuPageOptions.php:408
|
610 |
-
msgid "Yes, automatically clear RSS/RDF/ATOM Feeds from the cache when certain changes occur."
|
611 |
-
msgstr ""
|
612 |
-
|
613 |
-
#: src/includes/classes/MenuPageOptions.php:409
|
614 |
-
msgid "No, I don't have Feed Caching enabled, or I prefer not to automatically clear Feeds."
|
615 |
-
msgstr ""
|
616 |
-
|
617 |
-
#: src/includes/classes/MenuPageOptions.php:413
|
618 |
-
msgid "Sitemap-Related Options"
|
619 |
-
msgstr ""
|
620 |
-
|
621 |
-
#: src/includes/classes/MenuPageOptions.php:415
|
622 |
-
msgid "Auto-Clear \"XML Sitemaps\" Too?"
|
623 |
-
msgstr ""
|
624 |
-
|
625 |
-
#: src/includes/classes/MenuPageOptions.php:416
|
626 |
-
msgid "If you're generating XML Sitemaps with a plugin like <a href=\"http://wordpress.org/plugins/google-sitemap-generator/\" target=\"_blank\">Google XML Sitemaps</a>, you can tell %1$s to automatically clear the cache of any XML Sitemaps whenever it clears a Post/Page. Note: This does NOT clear the XML Sitemap itself of course, only the cache. The point being, to clear the cache and allow changes to a Post/Page to be reflected by a fresh copy of your XML Sitemap; sooner rather than later."
|
627 |
-
msgstr ""
|
628 |
-
|
629 |
-
#: src/includes/classes/MenuPageOptions.php:418
|
630 |
-
msgid "Yes, if any single Post/Page is cleared/reset; also clear the cache for any XML Sitemaps."
|
631 |
-
msgstr ""
|
632 |
-
|
633 |
-
#: src/includes/classes/MenuPageOptions.php:419
|
634 |
-
msgid "No, my site doesn't use any XML Sitemaps and/or I prefer NOT to clear the cache for XML Sitemaps."
|
635 |
-
msgstr ""
|
636 |
-
|
637 |
-
#: src/includes/classes/MenuPageOptions.php:422
|
638 |
-
msgid "<strong style=\"font-size:110%;\">XML Sitemap Patterns...</strong> A default value of <code>/sitemap**.xml</code> covers all XML Sitemaps for most installations. However, you may customize this further if you deem necessary. <strong>Please list one pattern per line.</strong> These XML Sitemap Pattern searches are performed against the <a href=\"https://gist.github.com/jaswsinc/338b6eb03a36c048c26f\" target=\"_blank\">REQUEST_URI</a>. A wildcard <code>**</code> character can also be used when necessary; e.g., <code>/sitemap**.xml</code> (where <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes). Other special characters include: <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href=\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
639 |
-
msgstr ""
|
640 |
-
|
641 |
-
#: src/includes/classes/MenuPageOptions.php:425
|
642 |
-
msgid "In a Multisite Network, each child blog (whether it be a sub-domain, a sub-directory, or a mapped domain); will automatically change the leading <code>http://[sub.]domain/[sub-directory]</code> used in pattern matching. In short, there is no need to add sub-domains or sub-directories for each child blog in these patterns. Please include only the <a href=\"https://gist.github.com/jaswsinc/338b6eb03a36c048c26f\" target=\"_blank\">REQUEST_URI</a> (i.e., the path) which leads to the XML Sitemap on all child blogs in the network."
|
643 |
-
msgstr ""
|
644 |
-
|
645 |
-
#: src/includes/classes/MenuPageOptions.php:431
|
646 |
-
msgid "Misc. Auto-Clear Options"
|
647 |
-
msgstr ""
|
648 |
-
|
649 |
-
#: src/includes/classes/MenuPageOptions.php:432
|
650 |
-
msgid "Auto-Clear a List of Custom URLs Too?"
|
651 |
-
msgstr ""
|
652 |
-
|
653 |
-
#: src/includes/classes/MenuPageOptions.php:433
|
654 |
-
msgid "When you update a Post/Page, approve a Comment, or make other changes where %1$s can detect that a Post/Page cache should be cleared to keep your site up-to-date; then %1$s will also clear a list of custom URLs that you list here. <strong>Please list one URL per line.</strong> A wildcard <code>*</code> character can also be used when necessary; e.g., <code>/category/abc-followed-by-*</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
655 |
-
msgstr ""
|
656 |
-
|
657 |
-
#: src/includes/classes/MenuPageOptions.php:446
|
658 |
-
msgid "Cache-Related Statistics"
|
659 |
-
msgstr ""
|
660 |
-
|
661 |
-
#: src/includes/classes/MenuPageOptions.php:451
|
662 |
-
msgid "Enable Cache-Related Stats & Charts?"
|
663 |
-
msgstr ""
|
664 |
-
|
665 |
-
#: src/includes/classes/MenuPageOptions.php:452
|
666 |
-
msgid "%1$s can collect and display cache-related statistics (including charts). Stats are displayed in the WordPress Admin Bar, and also in your Dashboard under: <strong>%1$s → Stats/Charts</strong>. Cache-related stats provide you with a quick look at what's happening behind-the-scenes. Your site grows faster and faster as the cache grows larger in size."
|
667 |
-
msgstr ""
|
668 |
-
|
669 |
-
#: src/includes/classes/MenuPageOptions.php:454
|
670 |
-
msgid "Yes, enable stats collection & the menu page in WordPress for viewing stats."
|
671 |
-
msgstr ""
|
672 |
-
|
673 |
-
#: src/includes/classes/MenuPageOptions.php:455
|
674 |
-
msgid "No, I have a VERY large site and I want to avoid any unnecessary directory scans."
|
675 |
-
msgstr ""
|
676 |
-
|
677 |
-
#: src/includes/classes/MenuPageOptions.php:457
|
678 |
-
msgid "<strong>Note:</strong> %1$s does a great job of collecting stats, in ways that don't cause a performance issue. In addition, as your cache grows larger than several hundred files in total size, statistics are collected less often and at longer intervals. All of that being said, if you run a VERY large site (e.g., more than 20K posts), you might want to disable stats collection in favor of blazing fast speeds not impeded by any directory scans needed to collect stats."
|
679 |
-
msgstr ""
|
680 |
-
|
681 |
-
#: src/includes/classes/MenuPageOptions.php:461
|
682 |
-
msgid "Show Stats in the WordPress Admin Bar?"
|
683 |
-
msgstr ""
|
684 |
-
|
685 |
-
#: src/includes/classes/MenuPageOptions.php:463
|
686 |
-
msgid "Yes, enable stats in the WordPress admin bar."
|
687 |
-
msgstr ""
|
688 |
-
|
689 |
-
#: src/includes/classes/MenuPageOptions.php:464
|
690 |
-
msgid "No, I'll review stats from the menu page in WordPress if I need to."
|
691 |
-
msgstr ""
|
692 |
-
|
693 |
-
#: src/includes/classes/MenuPageOptions.php:468
|
694 |
-
msgid "Allow Child Sites in a Network to See Stats in Admin Bar?"
|
695 |
-
msgstr ""
|
696 |
-
|
697 |
-
#: src/includes/classes/MenuPageOptions.php:469
|
698 |
-
msgid "In a Multisite Network, each child site has stats of its own. If you want child sites to see cache-related stats in their WordPress Admin Bar, you can specify a comma-delimited list of <a href=\"http://cometcache.com/r/wp-roles-caps/\" target=\"_blank\">Roles and/or Capabilities</a> that are allowed to see stats. For example, if I want the Administrator to see stats in their Admin Bar, I could enter <code>administrator</code> here. If I also want to show stats to Editors, I can use a comma-delimited list: <code>administrator,editor</code>. Or, I could use a single Capability of: <code>edit_others_posts</code>; which covers both Administrators & Editors at the same time."
|
699 |
-
msgstr ""
|
700 |
-
|
701 |
-
#: src/includes/classes/MenuPageOptions.php:476
|
702 |
-
msgid "Allow Others to See Stats in Admin Bar?"
|
703 |
-
msgstr ""
|
704 |
-
|
705 |
-
#: src/includes/classes/MenuPageOptions.php:477
|
706 |
-
msgid "If you want others to see cache-related stats in their WordPress Admin Bar, you can specify a comma-delimited list of <a href=\"http://cometcache.com/r/wp-roles-caps/\" target=\"_blank\">Roles and/or Capabilities</a> that are allowed to see stats. For example, if I want Editors to see stats in their Admin Bar, I could enter <code>editor</code> here. If I also want to show stats to Authors, I can use a comma-delimited list: <code>editor,author</code>. Or, I could use a single Capability of: <code>publish_posts</code>; which covers both Editors & Authors at the same time."
|
707 |
-
msgstr ""
|
708 |
-
|
709 |
-
#: src/includes/classes/MenuPageOptions.php:493
|
710 |
-
msgid "Cache Directory"
|
711 |
-
msgstr ""
|
712 |
-
|
713 |
-
#: src/includes/classes/MenuPageOptions.php:497
|
714 |
-
msgid "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)"
|
715 |
-
msgstr ""
|
716 |
-
|
717 |
-
#: src/includes/classes/MenuPageOptions.php:498
|
718 |
-
msgid "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."
|
719 |
-
msgstr ""
|
720 |
-
|
721 |
-
#: src/includes/classes/MenuPageOptions.php:509
|
722 |
-
msgid "Cache Expiration Time"
|
723 |
-
msgstr ""
|
724 |
-
|
725 |
-
#: src/includes/classes/MenuPageOptions.php:514
|
726 |
-
msgid "Automatic Expiration Time (Max Age)"
|
727 |
-
msgstr ""
|
728 |
-
|
729 |
-
#: src/includes/classes/MenuPageOptions.php:515
|
730 |
-
msgid "If you don't update your site much, you could set this to <code>6 months</code> and optimize everything even further. The longer the Cache Expiration Time is, the greater your performance gain. Alternatively, the shorter the Expiration Time, the fresher everything will remain on your site. A default value of <code>7 days</code> (recommended); is a good conservative middle-ground."
|
731 |
-
msgstr ""
|
732 |
-
|
733 |
-
#: src/includes/classes/MenuPageOptions.php:516
|
734 |
-
msgid "Keep in mind that your Expiration Time is only one part of the big picture. %1$s will also clear the cache automatically as changes are made to the site (i.e., you edit a post, someone comments on a post, you change your theme, you add a new navigation menu item, etc., etc.). Thus, your Expiration Time is really just a fallback; e.g., the maximum amount of time that a cache file could ever possibly live."
|
735 |
-
msgstr ""
|
736 |
-
|
737 |
-
#: src/includes/classes/MenuPageOptions.php:517
|
738 |
-
msgid "All of that being said, you could set this to just <code>60 seconds</code> and you would still see huge differences in speed and performance. If you're just starting out with %1$s (perhaps a bit nervous about old cache files being served to your visitors); you could set this to something like <code>30 minutes</code> and experiment with it while you build confidence in %1$s. It's not necessary to do so, but many site owners have reported this makes them feel like they're more-in-control when the cache has a short expiration time. All-in-all, it's a matter of preference <i class=\"si si-smile-o\"></i>."
|
739 |
-
msgstr ""
|
740 |
-
|
741 |
-
#: src/includes/classes/MenuPageOptions.php:519
|
742 |
-
msgid "<strong>Tip:</strong> the value that you specify here MUST be compatible with PHP's <a href=\"http://php.net/manual/en/function.strtotime.php\" target=\"_blank\" style=\"text-decoration:none;\"><code>strtotime()</code></a> function. Examples: <code>30 seconds</code>, <code>2 hours</code>, <code>7 days</code>, <code>6 months</code>, <code>1 year</code>."
|
743 |
-
msgstr ""
|
744 |
-
|
745 |
-
#: src/includes/classes/MenuPageOptions.php:520
|
746 |
-
msgid "<strong>Note:</strong> %1$s will never serve a cache file that is older than what you specify here (even if one exists in your cache directory; stale cache files are never used). In addition, a WP Cron job will automatically cleanup your cache directory (once per hour); purging expired cache files periodically. This prevents a HUGE cache from building up over time, creating a potential storage issue."
|
747 |
-
msgstr ""
|
748 |
-
|
749 |
-
#: src/includes/classes/MenuPageOptions.php:524
|
750 |
-
msgid "Cache Cleanup Schedule"
|
751 |
-
msgstr ""
|
752 |
-
|
753 |
-
#: src/includes/classes/MenuPageOptions.php:525
|
754 |
-
msgid "If you have an extremely large site and you lower the default Cache Expiration Time of <code>7 days</code>, expired cache files can build up more quickly. By default, %1$s cleans up expired cache files via <a href=\"http://cometcache.com/r/wp_cron-functions/\" target=\"_blank\">WP Cron</a> at an <code>hourly</code> interval, but you can tell %1$s to use a custom Cache Cleanup Schedule below to run the cleanup process more or less frequently, depending on your specific needs."
|
755 |
-
msgstr ""
|
756 |
-
|
757 |
-
#: src/includes/classes/MenuPageOptions.php:537
|
758 |
-
msgid "Disable Cache Expiration If Server Load Average is High?"
|
759 |
-
msgstr ""
|
760 |
-
|
761 |
-
#: src/includes/classes/MenuPageOptions.php:538
|
762 |
-
msgid "If you have high traffic at certain times of the day, %1$s can be told to check the current load average via <a href=\"http://cometcache.com/r/system-load-average-via-php/\" target=\"_blank\"><code>sys_getloadavg()</code></a>. If your server's load average has been high in the last 15 minutes or so, cache expiration is disabled automatically to help reduce stress on the server; i.e., to avoid generating a new version of the cache while the server is very busy."
|
763 |
-
msgstr ""
|
764 |
-
|
765 |
-
#: src/includes/classes/MenuPageOptions.php:539
|
766 |
-
msgid "To enable this functionality you should first determine what a high load average is for your server. If you log into your machine via SSH you can run the <code>top</code> command to get a feel for what a high load average looks like. Once you know the number, you can enter it in the field below; e.g., <code>1.05</code> might be a high load average for a server with one CPU. See also: <a href=\"http://cometcache.com/r/understanding-load-average/\" target=\"_blank\">Understanding Load Average</a>"
|
767 |
-
msgstr ""
|
768 |
-
|
769 |
-
#: src/includes/classes/MenuPageOptions.php:542
|
770 |
-
msgid "<strong>Note:</strong> It appears that your server is running Windows. The <code>sys_getloadavg()</code> function has not been implemented in PHP for Windows servers yet."
|
771 |
-
msgstr ""
|
772 |
-
|
773 |
-
#: src/includes/classes/MenuPageOptions.php:544
|
774 |
-
msgid "<strong>Note:</strong> <code>sys_getloadavg()</code> has been disabled by your web hosting company or is not available on your server."
|
775 |
-
msgstr ""
|
776 |
-
|
777 |
-
#: src/includes/classes/MenuPageOptions.php:557
|
778 |
-
msgid "Client-Side Cache"
|
779 |
-
msgstr ""
|
780 |
-
|
781 |
-
#: src/includes/classes/MenuPageOptions.php:562
|
782 |
-
msgid "Allow Double-Caching In The Client-Side Browser?"
|
783 |
-
msgstr ""
|
784 |
-
|
785 |
-
#: src/includes/classes/MenuPageOptions.php:563
|
786 |
-
msgid "Recommended setting: <code>No</code> (for membership sites, very important). Otherwise, <code>Yes</code> would be better (if users do NOT log in/out of your site)."
|
787 |
-
msgstr ""
|
788 |
-
|
789 |
-
#: src/includes/classes/MenuPageOptions.php:564
|
790 |
-
msgid "%1$s handles content delivery through its ability to communicate with a browser using PHP. If you allow a browser to (cache) the caching system itself, you are momentarily losing some control; and this can have a negative impact on users that see more than one version of your site; e.g., one version while logged-in, and another while NOT logged-in. For instance, a user may log out of your site, but upon logging out they report seeing pages on the site which indicate they are STILL logged in (even though they're not — that's bad). This can happen if you allow a client-side cache, because their browser may cache web pages they visited while logged into your site which persist even after logging out. Sending no-cache headers will work to prevent this issue."
|
791 |
-
msgstr ""
|
792 |
-
|
793 |
-
#: src/includes/classes/MenuPageOptions.php:565
|
794 |
-
msgid "All of that being said, if all you care about is blazing fast speed and users don't log in/out of your site (only you do); you can safely set this to <code>Yes</code> (recommended in this case). Allowing a client-side browser cache will improve speed and reduce outgoing bandwidth when this option is feasible."
|
795 |
-
msgstr ""
|
796 |
-
|
797 |
-
#: src/includes/classes/MenuPageOptions.php:567
|
798 |
-
msgid "No, prevent a client-side browser cache (safest option)."
|
799 |
-
msgstr ""
|
800 |
-
|
801 |
-
#: src/includes/classes/MenuPageOptions.php:568
|
802 |
-
msgid "Yes, I will allow a client-side browser cache of pages on the site."
|
803 |
-
msgstr ""
|
804 |
-
|
805 |
-
#: src/includes/classes/MenuPageOptions.php:570
|
806 |
-
msgid "<strong>Tip:</strong> Setting this to <code>No</code> is highly recommended when running a membership plugin like <a href=\"http://wordpress.org/plugins/s2member/\" target=\"_blank\">s2Member</a> (as one example). In fact, many plugins like s2Member will send <a href=\"http://codex.wordpress.org/Function_Reference/nocache_headers\" target=\"_blank\">nocache_headers()</a> on their own, so your configuration here will likely be overwritten when you run such plugins (which is better anyway). In short, if you run a membership plugin, you should NOT allow a client-side browser cache."
|
807 |
-
msgstr ""
|
808 |
-
|
809 |
-
#: src/includes/classes/MenuPageOptions.php:571
|
810 |
-
msgid "<strong>Tip:</strong> Setting this to <code>No</code> will NOT impact static content; e.g., CSS, JS, images, or other media. This setting pertains only to dynamic PHP scripts which produce content generated by WordPress."
|
811 |
-
msgstr ""
|
812 |
-
|
813 |
-
#: src/includes/classes/MenuPageOptions.php:572
|
814 |
-
msgid "<strong>Advanced Tip:</strong> if you have this set to <code>No</code>, but you DO want to allow a few special URLs to be cached by the browser; you can add this parameter to your URL <code>?%2$sABC=1</code>. This tells %1$s that it's OK for the browser to cache that particular URL. In other words, the <code>%2$sABC=1</code> parameter tells %1$s NOT to send no-cache headers to the browser."
|
815 |
-
msgstr ""
|
816 |
-
|
817 |
-
#: src/includes/classes/MenuPageOptions.php:573
|
818 |
-
msgid "Exclusion Patterns for Client-Side Caching"
|
819 |
-
msgstr ""
|
820 |
-
|
821 |
-
#: src/includes/classes/MenuPageOptions.php:574
|
822 |
-
msgid "When you enable Client-Side Caching above, you may want to prevent certain pages on your site from being cached by a client-side browser. This is where you will enter those if you need to (one per line). Searches are performed against the <a href=\"https://gist.github.com/jaswsinc/338b6eb03a36c048c26f\" target=\"_blank\" style=\"text-decoration:none;\"><code>REQUEST_URI</code></a>; i.e., <code>/path/?query</code> (caSe insensitive). So, don't put in full URLs here, just word fragments found in the file path (or query string) is all you need, excluding the http:// and domain name. A wildcard <code>*</code> character can also be used when necessary; e.g., <code>/category/abc-followed-by-*</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
823 |
-
msgstr ""
|
824 |
-
|
825 |
-
#: src/includes/classes/MenuPageOptions.php:576
|
826 |
-
#: src/includes/classes/MenuPageOptions.php:700
|
827 |
-
#: src/includes/classes/MenuPageOptions.php:861
|
828 |
-
msgid "<strong>Tip:</strong> let's use this example URL: <code>http://www.example.com/post/example-post-123</code>. To exclude this URL, you would put this line into the field above: <code>/post/example-post-123</code>. Or, you could also just put in a small fragment, like: <code>example</code> or <code>example-*-123</code> and that would exclude any URI containing that word fragment."
|
829 |
-
msgstr ""
|
830 |
-
|
831 |
-
#: src/includes/classes/MenuPageOptions.php:577
|
832 |
-
#: src/includes/classes/MenuPageOptions.php:701
|
833 |
-
#: src/includes/classes/MenuPageOptions.php:719
|
834 |
-
#: src/includes/classes/MenuPageOptions.php:737
|
835 |
-
#: src/includes/classes/MenuPageOptions.php:853
|
836 |
-
#: src/includes/classes/MenuPageOptions.php:857
|
837 |
-
#: src/includes/classes/MenuPageOptions.php:862
|
838 |
-
#: src/includes/classes/MenuPageOptions.php:986
|
839 |
-
msgid "<strong>Note:</strong> please remember that your entries here should be formatted as a line-delimited list; e.g., one exclusion pattern per line."
|
840 |
-
msgstr ""
|
841 |
-
|
842 |
-
#: src/includes/classes/MenuPageOptions.php:588
|
843 |
-
msgid "Logged-In Users"
|
844 |
-
msgstr ""
|
845 |
-
|
846 |
-
#: src/includes/classes/MenuPageOptions.php:593
|
847 |
-
msgid "Caching Enabled for Logged-In Users & Comment Authors?"
|
848 |
-
msgstr ""
|
849 |
-
|
850 |
-
#: src/includes/classes/MenuPageOptions.php:594
|
851 |
-
msgid "This should almost ALWAYS be set to <code>No</code>. Most sites will NOT want to cache content generated while a user is logged-in. Doing so could result in a cache of dynamic content generated specifically for a particular user, where the content being cached may contain details that pertain only to the user that was logged-in when the cache was generated. Imagine visiting a website that says you're logged-in as Billy Bob (but you're not Billy Bob; NOT good). In short, do NOT turn this on unless you know what you're doing."
|
852 |
-
msgstr ""
|
853 |
-
|
854 |
-
#: src/includes/classes/MenuPageOptions.php:596
|
855 |
-
msgid "<strong>Exception (Membership Sites):</strong> If you run a site with many users and the majority of your traffic comes from users who ARE logged-in, please choose: <code>Yes (maintain separate cache)</code>. %1$s will operate normally; but when a user is logged-in, the cache is user-specific. %1$s will intelligently refresh the cache when/if a user submits a form on your site with the GET or POST method. Or, if you make changes to their account (or another plugin makes changes to their account); including user <a href=\"http://codex.wordpress.org/Function_Reference/update_user_option\" target=\"_blank\">option</a>|<a href=\"http://codex.wordpress.org/Function_Reference/update_user_meta\" target=\"_blank\">meta</a> additions, updates & deletions too. However, please note that enabling this feature (e.g., user-specific cache entries); will eat up MUCH more disk space. That being said, the benefits of this feature for most sites will outweigh the disk overhead (e.g., it's NOT an issue in most cases). Unless you are short on disk space (or you have MANY thousands of users), the disk overhead is neglible."
|
856 |
-
msgstr ""
|
857 |
-
|
858 |
-
#: src/includes/classes/MenuPageOptions.php:598
|
859 |
-
msgid "No, do NOT cache; or serve a cache file when a user is logged-in (safest option)."
|
860 |
-
msgstr ""
|
861 |
-
|
862 |
-
#: src/includes/classes/MenuPageOptions.php:599
|
863 |
-
msgid "Yes, and maintain a separate cache for each user (recommended for membership sites)."
|
864 |
-
msgstr ""
|
865 |
-
|
866 |
-
#: src/includes/classes/MenuPageOptions.php:602
|
867 |
-
msgid "Yes, but DON'T maintain a separate cache for each user (I know what I'm doing)."
|
868 |
-
msgstr ""
|
869 |
-
|
870 |
-
#: src/includes/classes/MenuPageOptions.php:606
|
871 |
-
msgid "<strong>Warning:</strong> Whenever you enable caching for logged-in users (without a separate cache for each user), the WordPress Admin Bar <em>must</em> be disabled to prevent one user from seeing another user's details in the Admin Bar. <strong>Given your current configuration, %1$s will automatically hide the WordPress Admin Bar on the front-end of your site.</strong>"
|
872 |
-
msgstr ""
|
873 |
-
|
874 |
-
#: src/includes/classes/MenuPageOptions.php:608
|
875 |
-
msgid "<strong>Note:</strong> For most sites, the majority of their traffic (if not all of their traffic) comes from visitors who are not logged in, so disabling the cache for logged-in users is NOT ordinarily a performance issue. When a user IS logged-in, disabling the cache is considered ideal, because a logged-in user has a session open with your site; and the content they view should remain very dynamic in this scenario."
|
876 |
-
msgstr ""
|
877 |
-
|
878 |
-
#: src/includes/classes/MenuPageOptions.php:609
|
879 |
-
msgid "<strong>Note:</strong> This setting includes some users who AREN'T actually logged into the system, but who HAVE authored comments recently. %1$s includes comment authors as part of it's logged-in user check. This way comment authors will be able to see updates to the comment thread immediately; and, so that any dynamically-generated messages displayed by your theme will work as intended. In short, %1$s thinks of a comment author as a logged-in user, even though technically they are not. ~ Users who gain access to password-protected Posts/Pages are also included."
|
880 |
-
msgstr ""
|
881 |
-
|
882 |
-
#: src/includes/classes/MenuPageOptions.php:611
|
883 |
-
msgid "Static CDN Filters Enabled for Logged-In Users & Comment Authors?"
|
884 |
-
msgstr ""
|
885 |
-
|
886 |
-
#: src/includes/classes/MenuPageOptions.php:612
|
887 |
-
msgid "While this defaults to a value of <code>No</code>, it should almost always be set to <code>Yes</code>. This value defaults to <code>No</code> only because Logged-In User caching (see above) defaults to <code>No</code> and setting this value to <code>Yes</code> by default can cause confusion for some users. Once you understand that Static CDN Filters can be applied safely for all visitors (logged-in or not logged-in), please choose <code>Yes</code> in the dropdown below. If you are not using Static CDN Filters, the value below is ignored."
|
888 |
-
msgstr ""
|
889 |
-
|
890 |
-
#: src/includes/classes/MenuPageOptions.php:614
|
891 |
-
msgid "No, disable Static CDN Filters when a user is logged-in."
|
892 |
-
msgstr ""
|
893 |
-
|
894 |
-
#: src/includes/classes/MenuPageOptions.php:615
|
895 |
-
msgid "Yes, enable Static CDN Filters for logged-in users (recommended) ."
|
896 |
-
msgstr ""
|
897 |
-
|
898 |
-
#: src/includes/classes/MenuPageOptions.php:617
|
899 |
-
msgid "<strong>Note:</strong> Static CDN Filters serve <em>static</em> resources. Static resources, are, simply put, static. Thus, it is not a problem to cache these resources for any visitor (logged-in or not logged-in). To avoid confusion, this defaults to a value of <code>No</code>, and we ask that you set it to <code>Yes</code> on your own so that you'll know to expect this behavior; i.e., that static resources will always be served from the CDN (logged-in or not logged-in) even though Logged-In User caching may be disabled above."
|
900 |
-
msgstr ""
|
901 |
-
|
902 |
-
#: src/includes/classes/MenuPageOptions.php:627
|
903 |
-
msgid "GET Requests"
|
904 |
-
msgstr ""
|
905 |
-
|
906 |
-
#: src/includes/classes/MenuPageOptions.php:632
|
907 |
-
msgid "Caching Enabled for GET (Query String) Requests?"
|
908 |
-
msgstr ""
|
909 |
-
|
910 |
-
#: src/includes/classes/MenuPageOptions.php:633
|
911 |
-
msgid "This should almost ALWAYS be set to <code>No</code>. UNLESS, you're using unfriendly Permalinks. In other words, if all of your URLs contain a query string (e.g., <code>/?key=value</code>); you're using unfriendly Permalinks. Ideally, you would refrain from doing this; and instead, update your Permalink options immediately; which also optimizes your site for search engines. That being said, if you really want to use unfriendly Permalinks, and ONLY if you're using unfriendly Permalinks, you should set this to <code>Yes</code>; and don't worry too much, the sky won't fall on your head :-)"
|
912 |
-
msgstr ""
|
913 |
-
|
914 |
-
#: src/includes/classes/MenuPageOptions.php:635
|
915 |
-
msgid "No, do NOT cache (or serve a cache file) when a query string is present."
|
916 |
-
msgstr ""
|
917 |
-
|
918 |
-
#: src/includes/classes/MenuPageOptions.php:636
|
919 |
-
msgid "Yes, I would like to cache URLs that contain a query string."
|
920 |
-
msgstr ""
|
921 |
-
|
922 |
-
#: src/includes/classes/MenuPageOptions.php:638
|
923 |
-
msgid "<strong>Note:</strong> POST requests (i.e., forms with <code>method="post"</code>) are always excluded from the cache, which is the way it should be. Any <a href=\"http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html\" target=\"_blank\">POST/PUT/DELETE</a> request should NEVER (ever) be cached. CLI (and self-serve) requests are also excluded from the cache (always). A CLI request is one that comes from the command line; commonly used by CRON jobs and other automated routines. A self-serve request is an HTTP connection established from your site -› to your site. For instance, a WP Cron job, or any other HTTP request that is spawned not by a user, but by the server itself."
|
924 |
-
msgstr ""
|
925 |
-
|
926 |
-
#: src/includes/classes/MenuPageOptions.php:639
|
927 |
-
msgid "<strong>Advanced Tip:</strong> If you are NOT caching GET requests (recommended), but you DO want to allow some special URLs that include query string parameters to be cached; you can add this special parameter to any URL <code>?%2$sAC=1</code>. This tells %1$s that it's OK to cache that particular URL, even though it contains query string arguments. If you ARE caching GET requests and you want to force %1$s to NOT cache a specific request, you can add this special parameter to any URL <code>?%2$sAC=0</code>."
|
928 |
-
msgstr ""
|
929 |
-
|
930 |
-
#: src/includes/classes/MenuPageOptions.php:649
|
931 |
-
msgid "404 Requests"
|
932 |
-
msgstr ""
|
933 |
-
|
934 |
-
#: src/includes/classes/MenuPageOptions.php:654
|
935 |
-
msgid "Caching Enabled for 404 Requests?"
|
936 |
-
msgstr ""
|
937 |
-
|
938 |
-
#: src/includes/classes/MenuPageOptions.php:655
|
939 |
-
msgid "When this is set to <code>No</code>, %1$s will ignore all 404 requests and no cache file will be served. While this is fine for most site owners, caching the 404 page on a high-traffic site may further reduce server load. When this is set to <code>Yes</code>, %1$s will cache the 404 page (see <a href=\"https://codex.wordpress.org/Creating_an_Error_404_Page\" target=\"_blank\">Creating an Error 404 Page</a>) and then serve that single cache file to all future 404 requests."
|
940 |
-
msgstr ""
|
941 |
-
|
942 |
-
#: src/includes/classes/MenuPageOptions.php:657
|
943 |
-
msgid "No, do NOT cache (or serve a cache file) for 404 requests."
|
944 |
-
msgstr ""
|
945 |
-
|
946 |
-
#: src/includes/classes/MenuPageOptions.php:658
|
947 |
-
msgid "Yes, I would like to cache the 404 page and serve the cached file for 404 requests."
|
948 |
-
msgstr ""
|
949 |
-
|
950 |
-
#: src/includes/classes/MenuPageOptions.php:660
|
951 |
-
msgid "<strong>How does %1$s cache 404 requests?</strong> %1$s will create a special cache file (<code>----404----.html</code>, see Advanced Tip below) for the first 404 request and then <a href=\"http://www.php.net/manual/en/function.symlink.php\" target=\"_blank\">symlink</a> future 404 requests to this special cache file. That way you don't end up with lots of 404 cache files that all contain the same thing (the contents of the 404 page). Instead, you'll have one 404 cache file and then several symlinks (i.e., references) to that 404 cache file."
|
952 |
-
msgstr ""
|
953 |
-
|
954 |
-
#: src/includes/classes/MenuPageOptions.php:661
|
955 |
-
msgid "<strong>Advanced Tip:</strong> The default 404 cache filename (<code>----404----.html</code>) is designed to minimize the chance of a collision with a cache file for a real page with the same name. However, if you want to override this default and define your own 404 cache filename, you can do so by adding <code>define('COMET_CACHE_404_CACHE_FILENAME', 'your-404-cache-filename');</code> to your <code>wp-config.php</code> file (note that the <code>.html</code> extension should be excluded when defining a new filename)."
|
956 |
-
msgstr ""
|
957 |
-
|
958 |
-
#: src/includes/classes/MenuPageOptions.php:671
|
959 |
-
msgid "RSS, RDF, and Atom Feeds"
|
960 |
-
msgstr ""
|
961 |
-
|
962 |
-
#: src/includes/classes/MenuPageOptions.php:676
|
963 |
-
msgid "Caching Enabled for RSS, RDF, Atom Feeds?"
|
964 |
-
msgstr ""
|
965 |
-
|
966 |
-
#: src/includes/classes/MenuPageOptions.php:677
|
967 |
-
msgid "This should almost ALWAYS be set to <code>No</code>. UNLESS, you're sure that you want to cache your feeds. If you use a web feed management provider like Google® Feedburner and you set this option to <code>Yes</code>, you may experience delays in the detection of new posts. <strong>NOTE:</strong> If you do enable this, it is highly recommended that you also enable automatic Feed Clearing too. Please see the section above: \"Automatic Cache Clearing\". Find the sub-section titled: \"Auto-Clear RSS/RDF/ATOM Feeds\"."
|
968 |
-
msgstr ""
|
969 |
-
|
970 |
-
#: src/includes/classes/MenuPageOptions.php:679
|
971 |
-
msgid "No, do NOT cache (or serve a cache file) when displaying a feed."
|
972 |
-
msgstr ""
|
973 |
-
|
974 |
-
#: src/includes/classes/MenuPageOptions.php:680
|
975 |
-
msgid "Yes, I would like to cache feed URLs."
|
976 |
-
msgstr ""
|
977 |
-
|
978 |
-
#: src/includes/classes/MenuPageOptions.php:682
|
979 |
-
msgid "<strong>Note:</strong> This option affects all feeds served by WordPress, including the site feed, the site comment feed, post-specific comment feeds, author feeds, search feeds, and category and tag feeds. See also: <a href=\"http://codex.wordpress.org/WordPress_Feeds\" target=\"_blank\">WordPress Feeds</a>."
|
980 |
-
msgstr ""
|
981 |
-
|
982 |
-
#: src/includes/classes/MenuPageOptions.php:692
|
983 |
-
msgid "URI Exclusion Patterns"
|
984 |
-
msgstr ""
|
985 |
-
|
986 |
-
#: src/includes/classes/MenuPageOptions.php:696
|
987 |
-
msgid "Don't Cache These Special URI Exclusion Patterns?"
|
988 |
-
msgstr ""
|
989 |
-
|
990 |
-
#: src/includes/classes/MenuPageOptions.php:697
|
991 |
-
msgid "Sometimes there are certain cases where a particular file, or a particular group of files, should never be cached. This is where you will enter those if you need to (one per line). Searches are performed against the <a href=\"https://gist.github.com/jaswsinc/338b6eb03a36c048c26f\" target=\"_blank\" style=\"text-decoration:none;\"><code>REQUEST_URI</code></a>; i.e., <code>/path/?query</code> (caSe insensitive). So, don't put in full URLs here, just word fragments found in the file path (or query string) is all you need, excluding the http:// and domain name. A wildcard <code>*</code> character can also be used when necessary; e.g., <code>/category/abc-followed-by-*</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
992 |
-
msgstr ""
|
993 |
-
|
994 |
-
#: src/includes/classes/MenuPageOptions.php:711
|
995 |
-
msgid "HTTP Referrer Exclusion Patterns"
|
996 |
-
msgstr ""
|
997 |
-
|
998 |
-
#: src/includes/classes/MenuPageOptions.php:715
|
999 |
-
msgid "Don't Cache These Special HTTP Referrer Exclusion Patterns?"
|
1000 |
-
msgstr ""
|
1001 |
-
|
1002 |
-
#: src/includes/classes/MenuPageOptions.php:716
|
1003 |
-
msgid "Sometimes there are special cases where a particular referring URL (or referring domain) that sends you traffic; or even a particular group of referring URLs or domains that send you traffic; should result in a page being loaded on your site that is NOT from the cache (and that resulting page should never be cached). This is where you will enter those if you need to (one per line). Searches are performed against the <a href=\"http://www.php.net//manual/en/reserved.variables.server.php\" target=\"_blank\" style=\"text-decoration:none;\"><code>HTTP_REFERER</code></a> (caSe insensitive). A wildcard <code>*</code> character can also be used when necessary; e.g., <code>*.domain.com</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
1004 |
-
msgstr ""
|
1005 |
-
|
1006 |
-
#: src/includes/classes/MenuPageOptions.php:718
|
1007 |
-
msgid "<strong>Tip:</strong> let's use this example URL: <code>http://www.referring-domain.com/search/?q=search+terms</code>. To exclude this referring URL, you could put this line into the field above: <code>www.referring-domain.com</code>. Or, you could also just put in a small fragment, like: <code>/search/</code> or <code>q=*</code>; and that would exclude any referrer containing that word fragment."
|
1008 |
-
msgstr ""
|
1009 |
-
|
1010 |
-
#: src/includes/classes/MenuPageOptions.php:729
|
1011 |
-
msgid "User-Agent Exclusion Patterns"
|
1012 |
-
msgstr ""
|
1013 |
-
|
1014 |
-
#: src/includes/classes/MenuPageOptions.php:733
|
1015 |
-
msgid "Don't Cache These Special User-Agent Exclusion Patterns?"
|
1016 |
-
msgstr ""
|
1017 |
-
|
1018 |
-
#: src/includes/classes/MenuPageOptions.php:734
|
1019 |
-
msgid "Sometimes there are special cases when a particular user-agent (e.g., a specific browser or a specific type of device); should be shown a page on your site that is NOT from the cache (and that resulting page should never be cached). This is where you will enter those if you need to (one per line). Searches are performed against the <a href=\"http://www.php.net//manual/en/reserved.variables.server.php\" target=\"_blank\" style=\"text-decoration:none;\"><code>HTTP_USER_AGENT</code></a> (caSe insensitive). A wildcard <code>*</code> character can also be used when necessary; e.g., <code>Android *; Chrome/* Mobile</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
1020 |
-
msgstr ""
|
1021 |
-
|
1022 |
-
#: src/includes/classes/MenuPageOptions.php:736
|
1023 |
-
msgid "<strong>Tip:</strong> if you wanted to exclude iPhones put this line into the field above: <code>iPhone;*AppleWebKit</code>. Or, you could also just put in a small fragment, like: <code>iphone</code>; and that would exclude any user-agent containing that word fragment. Note, this is just an example. With a default installation of %1$s, there is no compelling reason to exclude iOS devices (or any mobile device for that matter)."
|
1024 |
-
msgstr ""
|
1025 |
-
|
1026 |
-
#: src/includes/classes/MenuPageOptions.php:748
|
1027 |
-
msgid "Auto-Cache Engine"
|
1028 |
-
msgstr ""
|
1029 |
-
|
1030 |
-
#: src/includes/classes/MenuPageOptions.php:753
|
1031 |
-
msgid "Enable the Auto-Cache Engine?"
|
1032 |
-
msgstr ""
|
1033 |
-
|
1034 |
-
#: src/includes/classes/MenuPageOptions.php:754
|
1035 |
-
msgid "After using %1$s for awhile (or any other page caching plugin, for that matter); it becomes obvious that at some point (based on your configured Expiration Time) %1$s has to refresh itself. It does this by ditching its cached version of a page, reloading the database-driven content, and then recreating the cache with the latest data. This is a never ending regeneration cycle that is based entirely on your configured Expiration Time."
|
1036 |
-
msgstr ""
|
1037 |
-
|
1038 |
-
#: src/includes/classes/MenuPageOptions.php:755
|
1039 |
-
msgid "Understanding this, you can see that 99% of your visitors are going to receive a lightning fast response from your server. However, there will always be around 1% of your visitors that land on a page for the very first time (before it's been cached), or land on a page that needs to have its cache regenerated, because the existing cache has become outdated. We refer to this as a <em>First-Come Slow-Load Issue</em>. Not a huge problem, but if you're optimizing your site for every ounce of speed possible, the Auto-Cache Engine can help with this. The Auto-Cache Engine has been designed to combat this issue by taking on the responsibility of being that first visitor to a page that has not yet been cached, or has an expired cache. The Auto-Cache Engine is powered, in part, by <a href=\"http://codex.wordpress.org/Category:WP-Cron_Functions\" target=\"_blank\">WP-Cron</a> (already built into WordPress). The Auto-Cache Engine runs at 15-minute intervals via WP-Cron. It also uses the <a href=\"http://core.trac.wordpress.org/browser/trunk/wp-includes/http.php\" target=\"_blank\">WP_Http</a> class, which is also built into WordPress already."
|
1040 |
-
msgstr ""
|
1041 |
-
|
1042 |
-
#: src/includes/classes/MenuPageOptions.php:756
|
1043 |
-
msgid "The Auto-Cache Engine obtains its list of URLs to auto-cache, from two different sources. It can read an <a href=\"http://wordpress.org/extend/plugins/google-sitemap-generator/\" target=\"_blank\">XML Sitemap</a> and/or a list of specific URLs that you supply. If you supply both sources, it will use both sources collectively. The Auto-Cache Engine takes ALL of your other configuration options into consideration too, including your Expiration Time, as well as any cache exclusion rules."
|
1044 |
-
msgstr ""
|
1045 |
-
|
1046 |
-
#: src/includes/classes/MenuPageOptions.php:758
|
1047 |
-
msgid "No, leave the Auto-Cache Engine disabled please."
|
1048 |
-
msgstr ""
|
1049 |
-
|
1050 |
-
#: src/includes/classes/MenuPageOptions.php:759
|
1051 |
-
msgid "Yes, I want the Auto-Cache Engine to keep pages cached automatically."
|
1052 |
-
msgstr ""
|
1053 |
-
|
1054 |
-
#: src/includes/classes/MenuPageOptions.php:765
|
1055 |
-
msgid "XML Sitemap URL (or an XML Sitemap Index)"
|
1056 |
-
msgstr ""
|
1057 |
-
|
1058 |
-
#: src/includes/classes/MenuPageOptions.php:769
|
1059 |
-
msgid "All URLs in this network are in the sitemap for the main site."
|
1060 |
-
msgstr ""
|
1061 |
-
|
1062 |
-
#: src/includes/classes/MenuPageOptions.php:770
|
1063 |
-
msgid "Using the path I've given, look for blog-specific sitemaps in each child blog also."
|
1064 |
-
msgstr ""
|
1065 |
-
|
1066 |
-
#: src/includes/classes/MenuPageOptions.php:772
|
1067 |
-
msgid "<strong>↑</strong> If enabled here, each child blog can be auto-cached too. %1$s will dynamically change the leading <code>%2$s</code> as necessary; for each child blog in the network. %1$s supports both sub-directory & sub-domain networks, including domain mapping plugins. For more information about how the Auto-Cache Engine caches child blogs, see <a href=\"http://cometcache.com/r/kb-article-how-does-the-auto-cache-engine-cache-child-blogs-in-a-multisite-network/\" target=\"_blank\">this article</a>."
|
1068 |
-
msgstr ""
|
1069 |
-
|
1070 |
-
#: src/includes/classes/MenuPageOptions.php:776
|
1071 |
-
msgid "And/Or; a List of URLs to Auto-Cache (One Per Line)"
|
1072 |
-
msgstr ""
|
1073 |
-
|
1074 |
-
#: src/includes/classes/MenuPageOptions.php:778
|
1075 |
-
msgid "<strong>Note:</strong> Wildcards are NOT supported here. If you are going to supply a list of URLs above, each line must contain one full URL for the Auto-Cache Engine to auto-cache. If you have many URLs, we recommend using an <a href=\"https://en.wikipedia.org/wiki/Sitemaps\" target=\"_blank\">XML Sitemap</a>."
|
1076 |
-
msgstr ""
|
1077 |
-
|
1078 |
-
#: src/includes/classes/MenuPageOptions.php:782
|
1079 |
-
msgid "Auto-Cache Delay Timer (in Milliseconds)"
|
1080 |
-
msgstr ""
|
1081 |
-
|
1082 |
-
#: src/includes/classes/MenuPageOptions.php:783
|
1083 |
-
msgid "As the Auto-Cache Engine runs through each URL, you can tell it to wait X number of milliseconds between each connection that it makes. It is strongly suggested that you DO have some small delay here. Otherwise, you run the risk of hammering your own web server with multiple repeated connections whenever the Auto-Cache Engine is running. This is especially true on very large sites; where there is the potential for hundreds of repeated connections as the Auto-Cache Engine goes through a long list of URLs. Adding a delay between each connection will prevent the Auto-Cache Engine from placing a heavy load on the processor that powers your web server. A value of <code>500</code> milliseconds is suggested here (half a second). If you experience problems, you can bump this up a little at a time, in increments of <code>500</code> milliseconds; until you find a happy place for your server. <em>Please note that <code>1000</code> milliseconds = <code>1</code> full second.</em>"
|
1084 |
-
msgstr ""
|
1085 |
-
|
1086 |
-
#: src/includes/classes/MenuPageOptions.php:788
|
1087 |
-
msgid "Auto-Cache User-Agent String"
|
1088 |
-
msgstr ""
|
1089 |
-
|
1090 |
-
#: src/includes/classes/MenuPageOptions.php:790
|
1091 |
-
msgid "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."
|
1092 |
-
msgstr ""
|
1093 |
-
|
1094 |
-
#: src/includes/classes/MenuPageOptions.php:802
|
1095 |
-
msgid "HTML Compression"
|
1096 |
-
msgstr ""
|
1097 |
-
|
1098 |
-
#: src/includes/classes/MenuPageOptions.php:807
|
1099 |
-
msgid "Enable WebSharks™ HTML Compression?"
|
1100 |
-
msgstr ""
|
1101 |
-
|
1102 |
-
#: src/includes/classes/MenuPageOptions.php:809
|
1103 |
-
msgid "No, do NOT compress HTML/CSS/JS code at runtime."
|
1104 |
-
msgstr ""
|
1105 |
-
|
1106 |
-
#: src/includes/classes/MenuPageOptions.php:810
|
1107 |
-
msgid "Yes, I want to compress HTML/CSS/JS for blazing fast speeds."
|
1108 |
-
msgstr ""
|
1109 |
-
|
1110 |
-
#: src/includes/classes/MenuPageOptions.php:812
|
1111 |
-
msgid "<strong>Note:</strong> This is experimental. Please <a href=\"https://github.com/websharks/comet-cache/issues\" target=\"_blank\">report issues here</a>."
|
1112 |
-
msgstr ""
|
1113 |
-
|
1114 |
-
#: src/includes/classes/MenuPageOptions.php:815
|
1115 |
-
msgid "HTML Compression Options"
|
1116 |
-
msgstr ""
|
1117 |
-
|
1118 |
-
#: src/includes/classes/MenuPageOptions.php:816
|
1119 |
-
msgid "You can <a href=\"https://github.com/websharks/html-compressor\" target=\"_blank\">learn more about all of these options here</a>."
|
1120 |
-
msgstr ""
|
1121 |
-
|
1122 |
-
#: src/includes/classes/MenuPageOptions.php:818
|
1123 |
-
msgid "Yes, combine CSS from <head> and <body> into fewer files."
|
1124 |
-
msgstr ""
|
1125 |
-
|
1126 |
-
#: src/includes/classes/MenuPageOptions.php:819
|
1127 |
-
msgid "No, do not combine CSS from <head> and <body> into fewer files."
|
1128 |
-
msgstr ""
|
1129 |
-
|
1130 |
-
#: src/includes/classes/MenuPageOptions.php:822
|
1131 |
-
msgid "Yes, compress the code in any unified CSS files."
|
1132 |
-
msgstr ""
|
1133 |
-
|
1134 |
-
#: src/includes/classes/MenuPageOptions.php:823
|
1135 |
-
msgid "No, do not compress the code in any unified CSS files."
|
1136 |
-
msgstr ""
|
1137 |
-
|
1138 |
-
#: src/includes/classes/MenuPageOptions.php:826
|
1139 |
-
msgid "Yes, combine JS from <head> into fewer files."
|
1140 |
-
msgstr ""
|
1141 |
-
|
1142 |
-
#: src/includes/classes/MenuPageOptions.php:827
|
1143 |
-
msgid "No, do not combine JS from <head> into fewer files."
|
1144 |
-
msgstr ""
|
1145 |
-
|
1146 |
-
#: src/includes/classes/MenuPageOptions.php:830
|
1147 |
-
msgid "Yes, combine JS footer scripts into fewer files."
|
1148 |
-
msgstr ""
|
1149 |
-
|
1150 |
-
#: src/includes/classes/MenuPageOptions.php:831
|
1151 |
-
msgid "No, do not combine JS footer scripts into fewer files."
|
1152 |
-
msgstr ""
|
1153 |
-
|
1154 |
-
#: src/includes/classes/MenuPageOptions.php:834
|
1155 |
-
msgid "Yes, combine CSS/JS from remote resources too."
|
1156 |
-
msgstr ""
|
1157 |
-
|
1158 |
-
#: src/includes/classes/MenuPageOptions.php:835
|
1159 |
-
msgid "No, do not combine CSS/JS from remote resources."
|
1160 |
-
msgstr ""
|
1161 |
-
|
1162 |
-
#: src/includes/classes/MenuPageOptions.php:838
|
1163 |
-
msgid "Yes, compress the code in any unified JS files."
|
1164 |
-
msgstr ""
|
1165 |
-
|
1166 |
-
#: src/includes/classes/MenuPageOptions.php:839
|
1167 |
-
msgid "No, do not compress the code in any unified JS files."
|
1168 |
-
msgstr ""
|
1169 |
-
|
1170 |
-
#: src/includes/classes/MenuPageOptions.php:842
|
1171 |
-
msgid "Yes, compress inline JavaScript snippets."
|
1172 |
-
msgstr ""
|
1173 |
-
|
1174 |
-
#: src/includes/classes/MenuPageOptions.php:843
|
1175 |
-
msgid "No, do not compress inline JavaScript snippets."
|
1176 |
-
msgstr ""
|
1177 |
-
|
1178 |
-
#: src/includes/classes/MenuPageOptions.php:846
|
1179 |
-
msgid "Yes, compress (remove extra whitespace) in the final HTML code too."
|
1180 |
-
msgstr ""
|
1181 |
-
|
1182 |
-
#: src/includes/classes/MenuPageOptions.php:847
|
1183 |
-
msgid "No, do not compress the final HTML code."
|
1184 |
-
msgstr ""
|
1185 |
-
|
1186 |
-
#: src/includes/classes/MenuPageOptions.php:850
|
1187 |
-
msgid "CSS Exclusion Patterns?"
|
1188 |
-
msgstr ""
|
1189 |
-
|
1190 |
-
#: src/includes/classes/MenuPageOptions.php:851
|
1191 |
-
msgid "Sometimes there are special cases when a particular CSS file should NOT be consolidated or compressed in any way. This is where you will enter those if you need to (one per line). Searches are performed against the <code><link href=""></code> value, and also against the contents of any inline <code><style></code> tags (caSe insensitive). A wildcard <code>*</code> character can also be used when necessary; e.g., <code>xy*-framework</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
1192 |
-
msgstr ""
|
1193 |
-
|
1194 |
-
#: src/includes/classes/MenuPageOptions.php:854
|
1195 |
-
msgid "JavaScript Exclusion Patterns?"
|
1196 |
-
msgstr ""
|
1197 |
-
|
1198 |
-
#: src/includes/classes/MenuPageOptions.php:855
|
1199 |
-
msgid "Sometimes there are special cases when a particular JS file should NOT be consolidated or compressed in any way. This is where you will enter those if you need to (one per line). Searches are performed against the <code><script src=""></code> value, and also against the contents of any inline <code><script></code> tags (caSe insensitive). A wildcard <code>*</code> character can also be used when necessary; e.g., <code>xy*-framework</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
1200 |
-
msgstr ""
|
1201 |
-
|
1202 |
-
#: src/includes/classes/MenuPageOptions.php:858
|
1203 |
-
msgid "URI Exclusions for HTML Compressor?"
|
1204 |
-
msgstr ""
|
1205 |
-
|
1206 |
-
#: src/includes/classes/MenuPageOptions.php:859
|
1207 |
-
msgid "When you enable HTML Compression above, you may want to prevent certain pages on your site from being cached by the HTML Compressor. This is where you will enter those if you need to (one per line). Searches are performed against the <a href=\"https://gist.github.com/jaswsinc/338b6eb03a36c048c26f\" target=\"_blank\" style=\"text-decoration:none;\"><code>REQUEST_URI</code></a>; i.e., <code>/path/?query</code> (caSe insensitive). So, don't put in full URLs here, just word fragments found in the file path (or query string) is all you need, excluding the http:// and domain name. A wildcard <code>*</code> character can also be used when necessary; e.g., <code>/category/abc-followed-by-*</code> (where <code>*</code> = 0 or more characters that are NOT a slash <code>/</code>). Other special characters include: <code>**</code> = 0 or more characters of any kind, including <code>/</code> slashes; <code>^</code> = beginning of the string; <code>$</code> = end of the string. To learn more about this syntax, please see <a href =\"http://cometcache.com/r/watered-down-regex-syntax/\" target=\"_blank\">this KB article</a>."
|
1208 |
-
msgstr ""
|
1209 |
-
|
1210 |
-
#: src/includes/classes/MenuPageOptions.php:864
|
1211 |
-
msgid "HTML Compression Cache Expiration"
|
1212 |
-
msgstr ""
|
1213 |
-
|
1214 |
-
#: src/includes/classes/MenuPageOptions.php:866
|
1215 |
-
msgid "<strong>Tip:</strong> the value that you specify here MUST be compatible with PHP's <a href=\"http://php.net/manual/en/function.strtotime.php\" target=\"_blank\" style=\"text-decoration:none;\"><code>strtotime()</code></a> function. Examples: <code>2 hours</code>, <code>7 days</code>, <code>6 months</code>, <code>1 year</code>."
|
1216 |
-
msgstr ""
|
1217 |
-
|
1218 |
-
#: src/includes/classes/MenuPageOptions.php:867
|
1219 |
-
msgid "<strong>Note:</strong> This does NOT impact the overall cache expiration time that you configure with %1$s. It only impacts the sub-routines provided by the HTML Compressor. In fact, this expiration time is mostly irrelevant. The HTML Compressor uses an internal checksum, and it also checks <code>filemtime()</code> before using an existing cache file. The HTML Compressor class also handles the automatic cleanup of your cache directories to keep it from growing too large over time. Therefore, unless you have VERY little disk space there is no reason to set this to a lower value (even if your site changes dynamically quite often). If anything, you might like to increase this value which could help to further reduce server load. You can <a href=\"https://github.com/websharks/HTML-Compressor\" target=\"_blank\">learn more here</a>. We recommend setting this value to at least double that of your overall %1$s expiration time."
|
1220 |
-
msgstr ""
|
1221 |
-
|
1222 |
-
#: src/includes/classes/MenuPageOptions.php:869
|
1223 |
-
msgid "Enable HTML Compression for Logged-In Users?"
|
1224 |
-
msgstr ""
|
1225 |
-
|
1226 |
-
#: src/includes/classes/MenuPageOptions.php:870
|
1227 |
-
msgid "Disabled by default. This setting is only applicable when caching for Logged-In Users is enabled. This should remain disabled for logged-in users because the user-specific cache has a much shorter Time To Live (TTL) which means their cache is likely to expire more quickly than a normal visitor. Rebuilding the HTML Compressor cache is time-consuming and doing it too frequently will actually slow things down for them. For example, if you're logged into the site as a user and you submit a form, that triggers a clearing of the cache for that user, including the HTML Compressor cache (when Logged-In User caching is enabled). Lots of little actions you take can result in a clearing of the cache. This shorter TTL is not ideal when running the HTML Compressor because it does a deep analysis of the page content and the associated resources in order to intelligently compress things. For logged-in users, it is better to skip that extra work and just cache the HTML source as-is, avoiding that extra overhead. In short, do NOT turn this on unless you know what you're doing."
|
1228 |
-
msgstr ""
|
1229 |
-
|
1230 |
-
#: src/includes/classes/MenuPageOptions.php:872
|
1231 |
-
msgid "No, disable HTML Compression for logged-in users (recommended)."
|
1232 |
-
msgstr ""
|
1233 |
-
|
1234 |
-
#: src/includes/classes/MenuPageOptions.php:873
|
1235 |
-
msgid "Yes, enable HTML Compression for logged-in users."
|
1236 |
-
msgstr ""
|
1237 |
-
|
1238 |
-
#: src/includes/classes/MenuPageOptions.php:885
|
1239 |
-
msgid "GZIP Compression"
|
1240 |
-
msgstr ""
|
1241 |
-
|
1242 |
-
#: src/includes/classes/MenuPageOptions.php:890
|
1243 |
-
msgid "<a href=\"https://developers.google.com/speed/articles/gzip\" target=\"_blank\">GZIP Compression</a> (Optional; Highly Recommended)"
|
1244 |
-
msgstr ""
|
1245 |
-
|
1246 |
-
#: src/includes/classes/MenuPageOptions.php:891
|
1247 |
-
msgid "You don't have to use an <code>.htaccess</code> file to enjoy the performance enhancements provided by this plugin; caching is handled automatically by WordPress/PHP alone. That being said, if you want to take advantage of the additional speed enhancements associated w/ GZIP compression (and we do recommend this), then you WILL need an <code>.htaccess</code> file to accomplish that part."
|
1248 |
-
msgstr ""
|
1249 |
-
|
1250 |
-
#: src/includes/classes/MenuPageOptions.php:892
|
1251 |
-
msgid "%1$s fully supports GZIP compression on its output. However, it does not handle GZIP compression directly. We purposely left GZIP compression out of this plugin, because GZIP compression is something that should really be enabled at the Apache level or inside your <code>php.ini</code> file. GZIP compression can be used for things like JavaScript and CSS files as well, so why bother turning it on for only WordPress-generated pages when you can enable GZIP at the server level and cover all the bases!"
|
1252 |
-
msgstr ""
|
1253 |
-
|
1254 |
-
#: src/includes/classes/MenuPageOptions.php:893
|
1255 |
-
msgid "If you want to enable GZIP, create an <code>.htaccess</code> file in your WordPress® installation directory, and put the following few lines in it. Alternatively, if you already have an <code>.htaccess</code> file, just add these lines to it, and that is all there is to it. GZIP is now enabled in the recommended way! See also: <a href=\"https://developers.google.com/speed/articles/gzip\" target=\"_blank\"><i class=\"si si-youtube-play\"></i> video about GZIP Compression</a>."
|
1256 |
-
msgstr ""
|
1257 |
-
|
1258 |
-
#: src/includes/classes/MenuPageOptions.php:907
|
1259 |
-
msgid "Static CDN Filters"
|
1260 |
-
msgstr ""
|
1261 |
-
|
1262 |
-
#: src/includes/classes/MenuPageOptions.php:911
|
1263 |
-
msgid "Clear CDN Cache (Bump CDN Invalidation Counter)"
|
1264 |
-
msgstr ""
|
1265 |
-
|
1266 |
-
#: src/includes/classes/MenuPageOptions.php:911
|
1267 |
-
msgid "Clear CDN Cache"
|
1268 |
-
msgstr ""
|
1269 |
-
|
1270 |
-
#: src/includes/classes/MenuPageOptions.php:912
|
1271 |
-
msgid "Enable Static CDN Filters (e.g., MaxCDN/CloudFront)?"
|
1272 |
-
msgstr ""
|
1273 |
-
|
1274 |
-
#: src/includes/classes/MenuPageOptions.php:913
|
1275 |
-
msgid "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."
|
1276 |
-
msgstr ""
|
1277 |
-
|
1278 |
-
#: src/includes/classes/MenuPageOptions.php:914
|
1279 |
-
msgid "<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."
|
1280 |
-
msgstr ""
|
1281 |
-
|
1282 |
-
#: src/includes/classes/MenuPageOptions.php:917
|
1283 |
-
msgid "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>."
|
1284 |
-
msgstr ""
|
1285 |
-
|
1286 |
-
#: src/includes/classes/MenuPageOptions.php:921
|
1287 |
-
msgid "No, I do NOT want CDN filters applied at runtime."
|
1288 |
-
msgstr ""
|
1289 |
-
|
1290 |
-
#: src/includes/classes/MenuPageOptions.php:922
|
1291 |
-
msgid "Yes, I want CDN filters applied w/ my configuration below."
|
1292 |
-
msgstr ""
|
1293 |
-
|
1294 |
-
#: src/includes/classes/MenuPageOptions.php:929
|
1295 |
-
msgid "CDN Host Name (Required)"
|
1296 |
-
msgstr ""
|
1297 |
-
|
1298 |
-
#: src/includes/classes/MenuPageOptions.php:935
|
1299 |
-
msgid "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."
|
1300 |
-
msgstr ""
|
1301 |
-
|
1302 |
-
#: src/includes/classes/MenuPageOptions.php:940
|
1303 |
-
msgid "Multiple CDN Host Names for Domain Sharding and Multisite Networks (Optional)"
|
1304 |
-
msgstr ""
|
1305 |
-
|
1306 |
-
#: src/includes/classes/MenuPageOptions.php:941
|
1307 |
-
msgid "%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><head></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."
|
1308 |
-
msgstr ""
|
1309 |
-
|
1310 |
-
#: src/includes/classes/MenuPageOptions.php:942
|
1311 |
-
msgid "<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>."
|
1312 |
-
msgstr ""
|
1313 |
-
|
1314 |
-
#: src/includes/classes/MenuPageOptions.php:944
|
1315 |
-
msgid "<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."
|
1316 |
-
msgstr ""
|
1317 |
-
|
1318 |
-
#: src/includes/classes/MenuPageOptions.php:948
|
1319 |
-
msgid "CDN Supports HTTPS Connections?"
|
1320 |
-
msgstr ""
|
1321 |
-
|
1322 |
-
#: src/includes/classes/MenuPageOptions.php:950
|
1323 |
-
msgid "No, I don't serve content over https://; or I haven't configured my CDN w/ an SSL certificate."
|
1324 |
-
msgstr ""
|
1325 |
-
|
1326 |
-
#: src/includes/classes/MenuPageOptions.php:951
|
1327 |
-
msgid "Yes, I've configured my CDN w/ an SSL certificate; I need https:// enabled."
|
1328 |
-
msgstr ""
|
1329 |
-
|
1330 |
-
#: src/includes/classes/MenuPageOptions.php:958
|
1331 |
-
msgid "Additional Options (For Advanced Users)"
|
1332 |
-
msgstr ""
|
1333 |
-
|
1334 |
-
#: src/includes/classes/MenuPageOptions.php:963
|
1335 |
-
msgid "Everything else below is 100% completely optional; i.e., not required to enjoy the benefits of Static CDN Filters."
|
1336 |
-
msgstr ""
|
1337 |
-
|
1338 |
-
#: src/includes/classes/MenuPageOptions.php:967
|
1339 |
-
msgid "Whitelisted File Extensions (Optional; Comma-Delimited)"
|
1340 |
-
msgstr ""
|
1341 |
-
|
1342 |
-
#: src/includes/classes/MenuPageOptions.php:969
|
1343 |
-
msgid "If you leave this empty a default set of extensions are taken from WordPress itself. The default set of whitelisted file extensions includes everything supported by the WordPress media library."
|
1344 |
-
msgstr ""
|
1345 |
-
|
1346 |
-
#: src/includes/classes/MenuPageOptions.php:971
|
1347 |
-
msgid "Blacklisted File Extensions (Optional; Comma-Delimited)"
|
1348 |
-
msgstr ""
|
1349 |
-
|
1350 |
-
#: src/includes/classes/MenuPageOptions.php:973
|
1351 |
-
msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain file extensions of your choosing. Please note, the <code>php</code> extension will never be considered a static resource; i.e., it is automatically blacklisted at all times."
|
1352 |
-
msgstr ""
|
1353 |
-
|
1354 |
-
#: src/includes/classes/MenuPageOptions.php:977
|
1355 |
-
msgid "Whitelisted URI Inclusion Patterns (Optional; One Per Line)"
|
1356 |
-
msgstr ""
|
1357 |
-
|
1358 |
-
#: src/includes/classes/MenuPageOptions.php:979
|
1359 |
-
msgid "<strong>Note:</strong> please remember that your entries here should be formatted as a line-delimited list; e.g., one inclusion pattern per line."
|
1360 |
-
msgstr ""
|
1361 |
-
|
1362 |
-
#: src/includes/classes/MenuPageOptions.php:980
|
1363 |
-
msgid "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."
|
1364 |
-
msgstr ""
|
1365 |
-
|
1366 |
-
#: src/includes/classes/MenuPageOptions.php:981
|
1367 |
-
msgid "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>"
|
1368 |
-
msgstr ""
|
1369 |
-
|
1370 |
-
#: src/includes/classes/MenuPageOptions.php:983
|
1371 |
-
msgid "Blacklisted URI Exclusion Patterns (Optional; One Per Line)"
|
1372 |
-
msgstr ""
|
1373 |
-
|
1374 |
-
#: src/includes/classes/MenuPageOptions.php:985
|
1375 |
-
msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain URI patterns. 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/*/dynamic.pdf*</code> would exclude a file with the name <code>dynamic.pdf</code> located anywhere inside a sub-directory of <code>wp-content</code>."
|
1376 |
-
msgstr ""
|
1377 |
-
|
1378 |
-
#: src/includes/classes/MenuPageOptions.php:990
|
1379 |
-
msgid "Query String Invalidation Variable Name"
|
1380 |
-
msgstr ""
|
1381 |
-
|
1382 |
-
#: src/includes/classes/MenuPageOptions.php:992
|
1383 |
-
msgid "Each filtered URL (which then leads to your CDN) will include this query string variable as an easy way to invalidate the CDN cache at any time. Invalidating the CDN cache is simply a matter of changing the global invalidation counter (i.e., the value assigned to this query string variable). %1$s manages invalidations automatically; i.e., %1$s will automatically bump an internal counter each time you upgrade a WordPress component (e.g., a plugin, theme, or WP itself). Or, if you ask %1$s to invalidate the CDN cache (e.g., a manual clearing of the CDN cache); the internal counter is bumped then too. In short, %1$s handles cache invalidations for you reliably. This option simply allows you to customize the query string variable name which makes cache invalidations possible. <strong>Please note, the default value is adequate for most sites. You can change this if you like, but it's not necessary.</strong>"
|
1384 |
-
msgstr ""
|
1385 |
-
|
1386 |
-
#: src/includes/classes/MenuPageOptions.php:993
|
1387 |
-
msgid "<strong>Tip:</strong> You can also tell %1$s to automatically bump the CDN Invalidation Counter whenever you clear the cache manually. See: <strong>%1$s → Manual Cache Clearing → Clear the CDN Cache Too?</strong>"
|
1388 |
-
msgstr ""
|
1389 |
-
|
1390 |
-
#: src/includes/classes/MenuPageOptions.php:994
|
1391 |
-
msgid "<strong>Note:</strong> If you empty this field, it will effectively disable the %1$s invalidation system for Static CDN Filters; i.e., the query string variable will NOT be included if you do not supply a variable name."
|
1392 |
-
msgstr ""
|
1393 |
-
|
1394 |
-
#: src/includes/classes/MenuPageOptions.php:1007
|
1395 |
-
msgid "Dynamic Version Salt"
|
1396 |
-
msgstr ""
|
1397 |
-
|
1398 |
-
#: src/includes/classes/MenuPageOptions.php:1012
|
1399 |
-
msgid "<i class=\"si si-flask\"></i> <span style=\"display:inline-block; padding:5px; border-radius:3px; background:#FFFFFF; color:#354913;\"><span style=\"font-weight:bold; font-size:80%;\">GEEK ALERT</span></span> This is for VERY advanced users only..."
|
1400 |
-
msgstr ""
|
1401 |
-
|
1402 |
-
#: src/includes/classes/MenuPageOptions.php:1013
|
1403 |
-
msgid "<em>Note: Understanding the %1$s <a href=\"http://cometcache.com/r/kb-branched-cache-structure/\" target=\"_blank\">Branched Cache Structure</a> is a prerequisite to understanding how Dynamic Version Salts are added to the mix.</em>"
|
1404 |
-
msgstr ""
|
1405 |
-
|
1406 |
-
#: src/includes/classes/MenuPageOptions.php:1014
|
1407 |
-
msgid "A Version Salt gives you the ability to dynamically create multiple variations of the cache, and those dynamic variations will be served on subsequent visits; e.g., if a visitor has a specific cookie (of a certain value) they will see pages which were cached with that version (i.e., w/ that Version Salt: the value of the cookie). A Version Salt can really be anything."
|
1408 |
-
msgstr ""
|
1409 |
-
|
1410 |
-
#: src/includes/classes/MenuPageOptions.php:1015
|
1411 |
-
msgid "A Version Salt can be a single variable like <code>$_COOKIE['my_cookie']</code>, or it can be a combination of multiple variables, like <code>$_COOKIE['my_cookie'].$_COOKIE['my_other_cookie']</code>. (When using multiple variables, please separate them with a dot, as shown in the example.)"
|
1412 |
-
msgstr ""
|
1413 |
-
|
1414 |
-
#: src/includes/classes/MenuPageOptions.php:1016
|
1415 |
-
msgid "Experts could even use PHP ternary expressions that evaluate into something. For example: <code>((preg_match('/iPhone/i', $_SERVER['HTTP_USER_AGENT'])) ? 'iPhones' : '')</code>. This would force a separate version of the cache to be created for iPhones (e.g., <code>/cache/PROTOCOL/HOST/REQUEST-URI.v/iPhones.html</code>)."
|
1416 |
-
msgstr ""
|
1417 |
-
|
1418 |
-
#: src/includes/classes/MenuPageOptions.php:1017
|
1419 |
-
msgid "For more documentation, please see <a href=\"http://cometcache.com/r/kb-dynamic-version-salts/\" target=\"_blank\">Dynamic Version Salts</a>."
|
1420 |
-
msgstr ""
|
1421 |
-
|
1422 |
-
#: src/includes/classes/MenuPageOptions.php:1019
|
1423 |
-
msgid "Create a Dynamic Version Salt For %1$s? <span style=\"font-size:90%%; opacity:0.5;\">150%% OPTIONAL</span>"
|
1424 |
-
msgstr ""
|
1425 |
-
|
1426 |
-
#: src/includes/classes/MenuPageOptions.php:1021
|
1427 |
-
msgid "<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>."
|
1428 |
-
msgstr ""
|
1429 |
-
|
1430 |
-
#: src/includes/classes/MenuPageOptions.php:1022
|
1431 |
-
msgid "<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."
|
1432 |
-
msgstr ""
|
1433 |
-
|
1434 |
-
#: src/includes/classes/MenuPageOptions.php:1023
|
1435 |
-
msgid "If you've enabled a separate cache for each user (optional) that's perfectly OK. A Version Salt works with user caching too."
|
1436 |
-
msgstr ""
|
1437 |
-
|
1438 |
-
#: src/includes/classes/MenuPageOptions.php:1033
|
1439 |
-
msgid "Theme/Plugin Developers"
|
1440 |
-
msgstr ""
|
1441 |
-
|
1442 |
-
#: src/includes/classes/MenuPageOptions.php:1038
|
1443 |
-
msgid "Developing a Theme or Plugin for WordPress?"
|
1444 |
-
msgstr ""
|
1445 |
-
|
1446 |
-
#: src/includes/classes/MenuPageOptions.php:1039
|
1447 |
-
msgid "<strong>Tip:</strong> %1$s can be disabled temporarily. If you're a theme/plugin developer, you can set a flag within your PHP code to disable the cache engine at runtime. Perhaps on a specific page, or in a specific scenario. In your PHP script, set: <code>$_SERVER['COMET_CACHE_ALLOWED'] = FALSE;</code> or <code>define('COMET_CACHE_ALLOWED', FALSE)</code>. %1$s is also compatible with: <code>define('DONOTCACHEPAGE', TRUE)</code>. It does't matter where or when you define one of these, because %1$s is the last thing to run before script execution ends."
|
1448 |
-
msgstr ""
|
1449 |
-
|
1450 |
-
#: src/includes/classes/MenuPageOptions.php:1041
|
1451 |
-
msgid "Writing \"Advanced Cache\" Plugins Specifically for %1$s"
|
1452 |
-
msgstr ""
|
1453 |
-
|
1454 |
-
#: src/includes/classes/MenuPageOptions.php:1042
|
1455 |
-
msgid "Theme/plugin developers can take advantage of the %1$s plugin architecture by creating PHP files inside this special directory: <code>/wp-content/ac-plugins/</code>. There is an <a href=\"http://cometcache.com/r/ac-plugin-example/\" target=\"_blank\">example plugin file @ GitHub</a> (please review it carefully and ask questions). If you develop a plugin for %1$s, please share it with the community by publishing it in the plugins respository at WordPress.org."
|
1456 |
-
msgstr ""
|
1457 |
-
|
1458 |
-
#: src/includes/classes/MenuPageOptions.php:1043
|
1459 |
-
msgid "<strong>Why does %1$s have it's own plugin architecture?</strong> WordPress loads the <code>advanced-cache.php</code> drop-in file (for caching purposes) very early-on; before any other plugins or a theme. For this reason, %1$s implements it's own watered-down version of functions like <code>add_action()</code>, <code>do_action()</code>, <code>add_filter()</code>, <code>apply_filters()</code>."
|
1460 |
-
msgstr ""
|
1461 |
-
|
1462 |
-
#: src/includes/classes/MenuPageOptions.php:1054
|
1463 |
-
msgid "Import/Export Options"
|
1464 |
-
msgstr ""
|
1465 |
-
|
1466 |
-
#: src/includes/classes/MenuPageOptions.php:1059
|
1467 |
-
msgid "Import Options from Another %1$s Installation?"
|
1468 |
-
msgstr ""
|
1469 |
-
|
1470 |
-
#: src/includes/classes/MenuPageOptions.php:1060
|
1471 |
-
msgid "Upload your <code>%1$s-options.json</code> file and click \"Save All Changes\" below. The options provided by your import file will override any that exist currently."
|
1472 |
-
msgstr ""
|
1473 |
-
|
1474 |
-
#: src/includes/classes/MenuPageOptions.php:1063
|
1475 |
-
msgid "Export Existing Options from this %1$s Installation?"
|
1476 |
-
msgstr ""
|
1477 |
-
|
1478 |
-
#: src/includes/classes/MenuPageOptions.php:1066
|
1479 |
-
msgid "%1$s-options.json"
|
1480 |
-
msgstr ""
|
1481 |
-
|
1482 |
-
#: src/includes/classes/MenuPageOptions.php:1067
|
1483 |
-
msgid "Download your existing options and import them all into another %1$s installation; saves time on future installs."
|
1484 |
-
msgstr ""
|
1485 |
-
|
1486 |
-
#: src/includes/classes/MenuPageOptions.php:1075
|
1487 |
-
msgid "Save All Changes"
|
1488 |
-
msgstr ""
|
1489 |
-
|
1490 |
-
#: src/includes/classes/VsUpgrades.php:201
|
1491 |
-
msgid "<strong>Woohoo! %1$s activated.</strong> :-)"
|
1492 |
-
msgstr ""
|
1493 |
-
|
1494 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:75
|
1495 |
-
msgid "because `PHP_SAPI` reports that you are currently running from the command line."
|
1496 |
-
msgstr ""
|
1497 |
-
|
1498 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:79
|
1499 |
-
msgid "because `$_SERVER['HTTP_HOST']` is missing from your server configuration."
|
1500 |
-
msgstr ""
|
1501 |
-
|
1502 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:83
|
1503 |
-
msgid "because `$_SERVER['REQUEST_URI']` is missing from your server configuration."
|
1504 |
-
msgstr ""
|
1505 |
-
|
1506 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:88
|
1507 |
-
msgid "because the s2Member plugin set the PHP constant `COMET_CACHE_ALLOWED` to a boolean-ish `FALSE` value at runtime. The s2Member plugin is serving content that must remain dynamic on this particular page, and therefore this page was intentionally not cached for a very good reason."
|
1508 |
-
msgstr ""
|
1509 |
-
|
1510 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:90
|
1511 |
-
msgid "because the PHP constant `COMET_CACHE_ALLOWED` has been set to a boolean-ish `FALSE` value 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."
|
1512 |
-
msgstr ""
|
1513 |
-
|
1514 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:95
|
1515 |
-
msgid "because the environment variable `$_SERVER['COMET_CACHE_ALLOWED']` has been set to a boolean-ish `FALSE` value 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."
|
1516 |
-
msgstr ""
|
1517 |
-
|
1518 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:99
|
1519 |
-
msgid "because the PHP constant `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."
|
1520 |
-
msgstr ""
|
1521 |
-
|
1522 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:103
|
1523 |
-
msgid "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."
|
1524 |
-
msgstr ""
|
1525 |
-
|
1526 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:107
|
1527 |
-
msgid "because `$_GET['%1$sAC']` is set to a boolean-ish FALSE value."
|
1528 |
-
msgstr ""
|
1529 |
-
|
1530 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:111
|
1531 |
-
msgid "because `$_SERVER['REQUEST_METHOD']` is `POST`, `PUT`, `DELETE`, `HEAD`, `OPTIONS`, `TRACE` or `CONNECT`. These request methods should never (ever) be cached in any way."
|
1532 |
-
msgstr ""
|
1533 |
-
|
1534 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:115
|
1535 |
-
msgid "because `[current IP address]` === `$_SERVER['SERVER_ADDR']`; i.e. a self-serve request. DEVELOPER TIP: if you are testing on a localhost installation, please add `define('LOCALHOST', TRUE);` to your `/wp-config.php` file while you run tests :-) Remove it (or set it to a `FALSE` value) once you go live on the web."
|
1536 |
-
msgstr ""
|
1537 |
-
|
1538 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:119
|
1539 |
-
msgid "because `$_SERVER['REQUEST_URI']` indicates this is a `/feed`; and the configuration of this site says not to cache XML-based feeds."
|
1540 |
-
msgstr ""
|
1541 |
-
|
1542 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:123
|
1543 |
-
msgid "because `$_SERVER['REQUEST_URI']` indicates this is a `wp-` or `xmlrpc` file; i.e. a WordPress systematic file. WordPress systematics are never (ever) cached in any way."
|
1544 |
-
msgstr ""
|
1545 |
-
|
1546 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:127
|
1547 |
-
msgid "because `$_SERVER['REQUEST_URI']` or the `is_admin()` function indicates this is an administrative area of the site."
|
1548 |
-
msgstr ""
|
1549 |
-
|
1550 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:131
|
1551 |
-
msgid "because `$_SERVER['REQUEST_URI']` indicates this is a Multisite Network; and this was a request for `/files/*`, not a page."
|
1552 |
-
msgstr ""
|
1553 |
-
|
1554 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:136
|
1555 |
-
msgid "because the current user visiting this page (usually YOU), appears to be logged-in. The current configuration says NOT to cache pages for logged-in visitors. This message may also appear if you have an active PHP session on this site, or if you've left (or replied to) a comment recently. If this message continues, please clear your cookies and try again."
|
1556 |
-
msgstr ""
|
1557 |
-
|
1558 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:140
|
1559 |
-
msgid "because the current page contains `_wpnonce` or `akismet_comment_nonce`. While your current configuration states that pages SHOULD be cache for logged-in visitors, `*nonce*` values in the markup are not cache-compatible. See http://wsharks.com/1O1Kudy for further details."
|
1560 |
-
msgstr ""
|
1561 |
-
|
1562 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:144
|
1563 |
-
msgid "because the current page contains `_wpnonce` or `akismet_comment_nonce`. Note that `*nonce*` values in the markup are not cache-compatible. See http://wsharks.com/1O1Kudy for further details."
|
1564 |
-
msgstr ""
|
1565 |
-
|
1566 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:148
|
1567 |
-
msgid "because the current user appeared to be logged into the site (in one way or another); but %1$s was unable to formulate a User Token for them. Please report this as a possible bug."
|
1568 |
-
msgstr ""
|
1569 |
-
|
1570 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:152
|
1571 |
-
msgid "because `$_GET` contains query string data. The current configuration says NOT to cache GET requests with a query string."
|
1572 |
-
msgstr ""
|
1573 |
-
|
1574 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:156
|
1575 |
-
msgid "because `$_REQUEST` indicates this is simply a preview of something to come."
|
1576 |
-
msgstr ""
|
1577 |
-
|
1578 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:160
|
1579 |
-
msgid "because `$_SERVER['REQUEST_URI']` matches a configured URI Exclusion Pattern on this installation."
|
1580 |
-
msgstr ""
|
1581 |
-
|
1582 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:164
|
1583 |
-
msgid "because `$_SERVER['HTTP_USER_AGENT']` matches a configured User-Agent Exclusion Pattern on this installation."
|
1584 |
-
msgstr ""
|
1585 |
-
|
1586 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:168
|
1587 |
-
msgid "because `$_SERVER['HTTP_REFERER']` and/or `$_GET['_wp_http_referer']` matches a configured HTTP Referrer Exclusion Pattern on this installation."
|
1588 |
-
msgstr ""
|
1589 |
-
|
1590 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:172
|
1591 |
-
msgid "because the WordPress `is_404()` Conditional Tag says the current page is a 404 error. The current configuration says NOT to cache 404 errors."
|
1592 |
-
msgstr ""
|
1593 |
-
|
1594 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:176
|
1595 |
-
msgid "because a plugin running on this installation says this page is in Maintenance Mode; i.e. is not available publicly at this time."
|
1596 |
-
msgstr ""
|
1597 |
-
|
1598 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:180
|
1599 |
-
msgid "because %1$s is unable to cache already-compressed output. Please use `mod_deflate` w/ Apache; or use `zlib.output_compression` in your `php.ini` file. %1$s is NOT compatible with `ob_gzhandler()` and others like this."
|
1600 |
-
msgstr ""
|
1601 |
-
|
1602 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:184
|
1603 |
-
msgid "because the contents of this document contain `<body id=\"error-page\">`, which indicates this is an auto-generated WordPress error message."
|
1604 |
-
msgstr ""
|
1605 |
-
|
1606 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:188
|
1607 |
-
msgid "because a `Content-Type:` header was set via PHP at runtime. The header contains a MIME type which is NOT a variation of HTML or XML. This header might have been set by your hosting company, by WordPress itself; or by one of your themes/plugins."
|
1608 |
-
msgstr ""
|
1609 |
-
|
1610 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:192
|
1611 |
-
msgid "because a `Status:` header (or an `HTTP/` header) was set via PHP at runtime. The header contains a non-`2xx` status code. This indicates the current page was not loaded successfully. This header might have been set by your hosting company, by WordPress itself; or by one of your themes/plugins."
|
1612 |
-
msgstr ""
|
1613 |
-
|
1614 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:196
|
1615 |
-
msgid "because the WordPress `is_404()` Conditional Tag says the current page is a 404 error; and this is the first time it's happened on this page. Your current configuration says that 404 errors SHOULD be cached, so %1$s built a cached symlink which points future requests for this location to your already-cached 404 error document. If you reload this page (assuming you don't clear the cache before you do so); you should get a cached version of your 404 error document. This message occurs ONCE for each new/unique 404 error request."
|
1616 |
-
msgstr ""
|
1617 |
-
|
1618 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:200
|
1619 |
-
msgid "because %1$s detected an early output buffer termination. This may happen when a theme/plugin ends, cleans, or flushes all output buffers before reaching the PHP shutdown phase. It's not always a bad thing. Sometimes it is necessary for a theme/plugin to do this. However, in this scenario it is NOT possible to cache the output; since %1$s is effectively disabled at runtime when this occurs."
|
1620 |
-
msgstr ""
|
1621 |
-
|
1622 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:204
|
1623 |
-
msgid "due to an unexpected behavior in the application. Please report this as a bug!"
|
1624 |
-
msgstr ""
|
1625 |
-
|
1626 |
-
#: src/includes/closures/Ac/NcDebugUtils.php:208
|
1627 |
-
msgid "%1$s is NOT caching this page, %2$s"
|
1628 |
-
msgstr ""
|
1629 |
-
|
1630 |
-
#. translators: This string is actually NOT translatable because the `__()`
|
1631 |
-
#. function is not available at this point in the processing.
|
1632 |
-
#: src/includes/closures/Ac/ObUtils.php:210
|
1633 |
-
msgid "%1$s fully functional :-) Cache file served for (%2$s) in %3$s seconds, on: %4$s."
|
1634 |
-
msgstr ""
|
1635 |
-
|
1636 |
-
#: src/includes/closures/Ac/ObUtils.php:238
|
1637 |
-
msgid "Unexpected OB phase: `%1$s`."
|
1638 |
-
msgstr ""
|
1639 |
-
|
1640 |
-
#: src/includes/closures/Ac/ObUtils.php:318
|
1641 |
-
msgid "Cache directory not writable. %1$s needs this directory please: `%2$s`. Set permissions to `755` or higher; `777` might be needed in some cases."
|
1642 |
-
msgstr ""
|
1643 |
-
|
1644 |
-
#: src/includes/closures/Ac/ObUtils.php:324
|
1645 |
-
#: src/includes/closures/Ac/ObUtils.php:342
|
1646 |
-
msgid "Unable to create symlink: `%1$s` » `%2$s`. Possible permissions issue (or race condition), please check your cache directory: `%3$s`."
|
1647 |
-
msgstr ""
|
1648 |
-
|
1649 |
-
#: src/includes/closures/Ac/ObUtils.php:335
|
1650 |
-
msgid "%1$s file path: %2$s"
|
1651 |
-
msgstr ""
|
1652 |
-
|
1653 |
-
#: src/includes/closures/Ac/ObUtils.php:336
|
1654 |
-
msgid "%1$s file built for (%2$s%3$s) in %4$s seconds, on: %5$s."
|
1655 |
-
msgstr ""
|
1656 |
-
|
1657 |
-
#: src/includes/closures/Ac/ObUtils.php:336
|
1658 |
-
msgid "user token: %1$s"
|
1659 |
-
msgstr ""
|
1660 |
-
|
1661 |
-
#: src/includes/closures/Ac/ObUtils.php:337
|
1662 |
-
msgid "This %1$s file will auto-expire (and be rebuilt) on: %2$s (based on your configured expiration time)."
|
1663 |
-
msgstr ""
|
1664 |
-
|
1665 |
-
#: src/includes/closures/Ac/ObUtils.php:352
|
1666 |
-
msgid "%1$s: failed to write cache file for: `%2$s`; possible permissions issue (or race condition), please check your cache directory: `%3$s`."
|
1667 |
-
msgstr ""
|
1668 |
-
|
1669 |
-
#: src/includes/closures/Plugin/CronUtils.php:18
|
1670 |
-
msgid "Every 15 Minutes"
|
1671 |
-
msgstr ""
|
1672 |
-
|
1673 |
-
#: src/includes/closures/Plugin/DirUtils.php:21
|
1674 |
-
#: src/includes/closures/Plugin/DirUtils.php:48
|
1675 |
-
msgid "Missing `base_dir` option value."
|
1676 |
-
msgstr ""
|
1677 |
-
|
1678 |
-
#: src/includes/closures/Plugin/InstallUtils.php:16
|
1679 |
-
msgid "<strong>%1$s</strong> successfully installed! :-) <strong>Please <a href=\"%2$s\">enable caching and review options</a>.</strong>"
|
1680 |
-
msgstr ""
|
1681 |
-
|
1682 |
-
#: src/includes/closures/Plugin/InstallUtils.php:55
|
1683 |
-
msgid "<strong>%1$s:</strong> detected a new version of itself. Recompiling w/ latest version... wiping the cache... all done :-)"
|
1684 |
-
msgstr ""
|
1685 |
-
|
1686 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:46
|
1687 |
-
msgid "%"
|
1688 |
-
msgstr ""
|
1689 |
-
|
1690 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:47
|
1691 |
-
msgid "file"
|
1692 |
-
msgstr ""
|
1693 |
-
|
1694 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:48
|
1695 |
-
msgid "files"
|
1696 |
-
msgstr ""
|
1697 |
-
|
1698 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:49
|
1699 |
-
msgid "Page Cache"
|
1700 |
-
msgstr ""
|
1701 |
-
|
1702 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:50
|
1703 |
-
msgid "HTML Compressor"
|
1704 |
-
msgstr ""
|
1705 |
-
|
1706 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:51
|
1707 |
-
msgid "Current Total"
|
1708 |
-
msgstr ""
|
1709 |
-
|
1710 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:52
|
1711 |
-
msgid "Current Site"
|
1712 |
-
msgstr ""
|
1713 |
-
|
1714 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:53
|
1715 |
-
msgid "%s Day High"
|
1716 |
-
msgstr ""
|
1717 |
-
|
1718 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:118
|
1719 |
-
msgid "Settings"
|
1720 |
-
msgstr ""
|
1721 |
-
|
1722 |
-
#: src/includes/closures/Plugin/MenuPageUtils.php:121
|
1723 |
-
msgid "Upgrade"
|
1724 |
-
msgstr ""
|
1725 |
-
|
1726 |
-
#: src/includes/closures/Plugin/NoticeUtils.php:151
|
1727 |
-
msgid "dismiss ×"
|
1728 |
-
msgstr ""
|
1729 |
-
|
1730 |
-
#: src/includes/closures/Plugin/WcpAuthorUtils.php:82
|
1731 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache for Author Page: <code>%3$s</code>; auto-clearing."
|
1732 |
-
msgstr ""
|
1733 |
-
|
1734 |
-
#: src/includes/closures/Plugin/WcpFeedUtils.php:113
|
1735 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache, for XML feeds of type: <code>%3$s</code>; auto-clearing."
|
1736 |
-
msgstr ""
|
1737 |
-
|
1738 |
-
#: src/includes/closures/Plugin/WcpHomeBlogUtils.php:38
|
1739 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache for the designated \"Home Page\"; auto-clearing."
|
1740 |
-
msgstr ""
|
1741 |
-
|
1742 |
-
#: src/includes/closures/Plugin/WcpHomeBlogUtils.php:96
|
1743 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache for the designated \"Posts Page\"; auto-clearing."
|
1744 |
-
msgstr ""
|
1745 |
-
|
1746 |
-
#: src/includes/closures/Plugin/WcpPostTypeUtils.php:51
|
1747 |
-
msgid "Untitled"
|
1748 |
-
msgstr ""
|
1749 |
-
|
1750 |
-
#: src/includes/closures/Plugin/WcpPostTypeUtils.php:61
|
1751 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache for Custom Post Type: <code>%3$s</code>; auto-clearing."
|
1752 |
-
msgstr ""
|
1753 |
-
|
1754 |
-
#: src/includes/closures/Plugin/WcpPostUtils.php:82
|
1755 |
-
msgid "Post"
|
1756 |
-
msgstr ""
|
1757 |
-
|
1758 |
-
#: src/includes/closures/Plugin/WcpPostUtils.php:89
|
1759 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache for %3$s ID: <code>%4$s</code>; auto-clearing."
|
1760 |
-
msgstr ""
|
1761 |
-
|
1762 |
-
#: src/includes/closures/Plugin/WcpSitemapUtils.php:44
|
1763 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache for XML sitemaps; auto-clearing."
|
1764 |
-
msgstr ""
|
1765 |
-
|
1766 |
-
#: src/includes/closures/Plugin/WcpTermUtils.php:130
|
1767 |
-
msgid "<strong>%1$s:</strong> detected changes. Found %2$s in the cache for %3$s: <code>%4$s</code>; auto-clearing."
|
1768 |
-
msgstr ""
|
1769 |
-
|
1770 |
-
#: src/includes/closures/Plugin/WcpUtils.php:164
|
1771 |
-
msgid "<strong>%1$s:</strong> detected significant changes. Found %2$s in the cache; auto-wiping."
|
1772 |
-
msgstr ""
|
1773 |
-
|
1774 |
-
#: src/includes/closures/Plugin/WcpUtils.php:210
|
1775 |
-
msgid "<strong>%1$s:</strong> detected important site changes. Found %2$s in the cache for this site; auto-clearing."
|
1776 |
-
msgstr ""
|
1777 |
-
|
1778 |
-
#: src/includes/closures/Plugin/WcpUtils.php:244
|
1779 |
-
msgid "<strong>%1$s:</strong> detected important site changes. Found %2$s in the cache for this site that were expired; auto-purging."
|
1780 |
-
msgstr ""
|
1781 |
-
|
1782 |
-
#: src/includes/closures/Plugin/WcpUtils.php:278
|
1783 |
-
msgid "<strong>%1$s:</strong> detected important site changes. Found %2$s in the cache that were expired; auto-purging."
|
1784 |
-
msgstr ""
|
1785 |
-
|
1786 |
-
#: src/includes/closures/Plugin/WcpUtils.php:298
|
1787 |
-
msgid "<strong>%1$s:</strong> detected significant changes that would normally trigger cache wiping routines. However, cache wiping routines have been disabled by a site administrator. [<a href=\"http://cometcache.com/r/kb-clear-and-wipe-cache-routines/\" target=\"_blank\">?</a>]"
|
1788 |
-
msgstr ""
|
1789 |
-
|
1790 |
-
#: src/includes/closures/Plugin/WcpUtils.php:318
|
1791 |
-
msgid "<strong>%1$s:</strong> detected important site changes that would normally trigger cache clearing routines. However, cache clearing routines have been disabled by a site administrator. [<a href=\"http://cometcache.com/r/kb-clear-and-wipe-cache-routines/\" target=\"_blank\">?</a>]"
|
1792 |
-
msgstr ""
|
1793 |
-
|
1794 |
-
#: src/includes/closures/Plugin/WcpUtils.php:338
|
1795 |
-
msgid "<strong>%1$s:</strong> detected important site changes that would normally trigger cache purging routines. However, cache purging routines have been disabled by a site administrator. [<a href=\"http://cometcache.com/r/kb-clear-and-wipe-cache-routines/\" target=\"_blank\">?</a>]"
|
1796 |
-
msgstr ""
|
1797 |
-
|
1798 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:24
|
1799 |
-
msgid "Unable to determine cache directory location."
|
1800 |
-
msgstr ""
|
1801 |
-
|
1802 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:121
|
1803 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:277
|
1804 |
-
msgid "Invalid argument; isAdvancedCache!"
|
1805 |
-
msgstr ""
|
1806 |
-
|
1807 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:148
|
1808 |
-
msgid "Unable to delete files. Rename failure on directory: `%1$s`."
|
1809 |
-
msgstr ""
|
1810 |
-
|
1811 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:172
|
1812 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:340
|
1813 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:480
|
1814 |
-
msgid "Unable to delete symlink: `%1$s`."
|
1815 |
-
msgstr ""
|
1816 |
-
|
1817 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:187
|
1818 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:355
|
1819 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:490
|
1820 |
-
msgid "Unable to delete file: `%1$s`."
|
1821 |
-
msgstr ""
|
1822 |
-
|
1823 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:203
|
1824 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:371
|
1825 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:500
|
1826 |
-
msgid "Unable to delete dir: `%1$s`."
|
1827 |
-
msgstr ""
|
1828 |
-
|
1829 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:211
|
1830 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:379
|
1831 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:508
|
1832 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:603
|
1833 |
-
msgid "Unexpected resource type: `%1$s`."
|
1834 |
-
msgstr ""
|
1835 |
-
|
1836 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:218
|
1837 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:316
|
1838 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:386
|
1839 |
-
msgid "Unable to delete files. Rename failure on tmp directory: `%1$s`."
|
1840 |
-
msgstr ""
|
1841 |
-
|
1842 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:274
|
1843 |
-
msgid "Invalid argument; host token empty!"
|
1844 |
-
msgstr ""
|
1845 |
-
|
1846 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:467
|
1847 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:515
|
1848 |
-
msgid "Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`."
|
1849 |
-
msgstr ""
|
1850 |
-
|
1851 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:519
|
1852 |
-
msgid "Unable to delete directory: `%1$s`."
|
1853 |
-
msgstr ""
|
1854 |
-
|
1855 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:578
|
1856 |
-
msgid "Unable to erase symlink: `%1$s`."
|
1857 |
-
msgstr ""
|
1858 |
-
|
1859 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:587
|
1860 |
-
msgid "Unable to erase file: `%1$s`."
|
1861 |
-
msgstr ""
|
1862 |
-
|
1863 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:596
|
1864 |
-
msgid "Unable to erase dir: `%1$s`."
|
1865 |
-
msgstr ""
|
1866 |
-
|
1867 |
-
#: src/includes/closures/Shared/CacheDirUtils.php:610
|
1868 |
-
msgid "Unable to erase directory: `%1$s`."
|
1869 |
-
msgstr ""
|
1870 |
-
|
1871 |
-
#: src/includes/closures/Shared/CacheLockUtils.php:25
|
1872 |
-
msgid "Unable to find the wp-config.php file."
|
1873 |
-
msgstr ""
|
1874 |
-
|
1875 |
-
#: src/includes/closures/Shared/CacheLockUtils.php:42
|
1876 |
-
msgid "No writable tmp directory."
|
1877 |
-
msgstr ""
|
1878 |
-
|
1879 |
-
#: src/includes/closures/Shared/CacheLockUtils.php:48
|
1880 |
-
msgid "Unable to obtain an exclusive lock."
|
1881 |
-
msgstr ""
|
1882 |
-
|
1883 |
-
#: src/includes/closures/Shared/HookUtils.php:40
|
1884 |
-
msgid "Invalid hook."
|
1885 |
-
msgstr ""
|
1886 |
-
|
1887 |
-
#: src/includes/closures/Shared/I18nUtils.php:15
|
1888 |
-
msgid "%1$s file"
|
1889 |
-
msgid_plural "%1$s files"
|
1890 |
-
msgstr[0] ""
|
1891 |
-
msgstr[1] ""
|
1892 |
-
|
1893 |
-
#: src/includes/closures/Shared/I18nUtils.php:29
|
1894 |
-
msgid "%1$s directory"
|
1895 |
-
msgid_plural "%1$s directories"
|
1896 |
-
msgstr[0] ""
|
1897 |
-
msgstr[1] ""
|
1898 |
-
|
1899 |
-
#: src/includes/closures/Shared/I18nUtils.php:43
|
1900 |
-
msgid "%1$s file/directory"
|
1901 |
-
msgid_plural "%1$s files/directories"
|
1902 |
-
msgstr[0] ""
|
1903 |
-
msgstr[1] ""
|
1904 |
-
|
1905 |
-
#: src/includes/closures/Shared/SysUtils.php:65
|
1906 |
-
msgid "%s%%"
|
1907 |
-
msgstr ""
|
1908 |
-
|
1909 |
-
#. Plugin Name of the plugin/theme
|
1910 |
-
msgid "Comet Cache"
|
1911 |
-
msgstr ""
|
1912 |
-
|
1913 |
-
#. Plugin URI of the plugin/theme
|
1914 |
-
msgid "http://cometcache.com/"
|
1915 |
-
msgstr ""
|
1916 |
-
|
1917 |
-
#. Description of the plugin/theme
|
1918 |
-
msgid "Comet Cache is an advanced WordPress caching plugin inspired by simplicity."
|
1919 |
-
msgstr ""
|
1920 |
-
|
1921 |
-
#. Author of the plugin/theme
|
1922 |
-
msgid "WebSharks, Inc."
|
1923 |
-
msgstr ""
|
1924 |
-
|
1925 |
-
#. Author URI of the plugin/theme
|
1926 |
-
msgid "http://websharks-inc.com/"
|
1927 |
-
msgstr ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/includes/uninstall.php
CHANGED
@@ -6,14 +6,16 @@
|
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
|
|
|
|
9 |
if (!defined('WPINC')) {
|
10 |
exit('Do NOT access this file directly: '.basename(__FILE__));
|
11 |
}
|
12 |
-
require_once
|
13 |
|
14 |
$GLOBALS[GLOBAL_NS.'_uninstalling'] = true; // Needs to be set before calling Conflicts class
|
15 |
|
16 |
-
if (!Conflicts::check()) {
|
17 |
-
$GLOBALS[GLOBAL_NS] = new Plugin(false);
|
18 |
$GLOBALS[GLOBAL_NS]->uninstall();
|
19 |
}
|
6 |
*/
|
7 |
namespace WebSharks\CometCache;
|
8 |
|
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 |
|
16 |
$GLOBALS[GLOBAL_NS.'_uninstalling'] = true; // Needs to be set before calling Conflicts class
|
17 |
|
18 |
+
if (!Classes\Conflicts::check()) {
|
19 |
+
$GLOBALS[GLOBAL_NS] = new Classes\Plugin(false);
|
20 |
$GLOBALS[GLOBAL_NS]->uninstall();
|
21 |
}
|
src/vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInitc1a53f596a710aab47629b58885a6ec2::getLoader();
|
src/vendor/composer/ClassLoader.php
CHANGED
@@ -13,9 +13,7 @@
|
|
13 |
namespace Composer\Autoload;
|
14 |
|
15 |
/**
|
16 |
-
* ClassLoader implements a PSR-0 class loader
|
17 |
-
*
|
18 |
-
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
|
19 |
*
|
20 |
* $loader = new \Composer\Autoload\ClassLoader();
|
21 |
*
|
@@ -39,6 +37,8 @@ namespace Composer\Autoload;
|
|
39 |
*
|
40 |
* @author Fabien Potencier <fabien@symfony.com>
|
41 |
* @author Jordi Boggiano <j.boggiano@seld.be>
|
|
|
|
|
42 |
*/
|
43 |
class ClassLoader
|
44 |
{
|
@@ -147,7 +147,7 @@ class ClassLoader
|
|
147 |
* appending or prepending to the ones previously set for this namespace.
|
148 |
*
|
149 |
* @param string $prefix The prefix/namespace, with trailing '\\'
|
150 |
-
* @param array|string $paths The PSR-
|
151 |
* @param bool $prepend Whether to prepend the directories
|
152 |
*
|
153 |
* @throws \InvalidArgumentException
|
13 |
namespace Composer\Autoload;
|
14 |
|
15 |
/**
|
16 |
+
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
|
|
|
|
17 |
*
|
18 |
* $loader = new \Composer\Autoload\ClassLoader();
|
19 |
*
|
37 |
*
|
38 |
* @author Fabien Potencier <fabien@symfony.com>
|
39 |
* @author Jordi Boggiano <j.boggiano@seld.be>
|
40 |
+
* @see http://www.php-fig.org/psr/psr-0/
|
41 |
+
* @see http://www.php-fig.org/psr/psr-4/
|
42 |
*/
|
43 |
class ClassLoader
|
44 |
{
|
147 |
* appending or prepending to the ones previously set for this namespace.
|
148 |
*
|
149 |
* @param string $prefix The prefix/namespace, with trailing '\\'
|
150 |
+
* @param array|string $paths The PSR-4 base directories
|
151 |
* @param bool $prepend Whether to prepend the directories
|
152 |
*
|
153 |
* @throws \InvalidArgumentException
|
src/vendor/composer/LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
|
2 |
-
Copyright (c)
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
1 |
|
2 |
+
Copyright (c) 2016 Nils Adermann, Jordi Boggiano
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
src/vendor/composer/autoload_psr4.php
CHANGED
@@ -9,5 +9,7 @@ return array(
|
|
9 |
'WebSharks\\JsMinifier\\' => array($vendorDir . '/websharks/js-minifier/src/includes/classes'),
|
10 |
'WebSharks\\HtmlCompressor\\' => array($vendorDir . '/websharks/html-compressor/src/includes/classes'),
|
11 |
'WebSharks\\CssMinifier\\' => array($vendorDir . '/websharks/css-minifier/src/includes/classes'),
|
12 |
-
'WebSharks\\CometCache\\' => array($baseDir . '/src/includes/
|
|
|
|
|
13 |
);
|
9 |
'WebSharks\\JsMinifier\\' => array($vendorDir . '/websharks/js-minifier/src/includes/classes'),
|
10 |
'WebSharks\\HtmlCompressor\\' => array($vendorDir . '/websharks/html-compressor/src/includes/classes'),
|
11 |
'WebSharks\\CssMinifier\\' => array($vendorDir . '/websharks/css-minifier/src/includes/classes'),
|
12 |
+
'WebSharks\\CometCache\\Traits\\' => array($baseDir . '/src/includes/traits'),
|
13 |
+
'WebSharks\\CometCache\\Interfaces\\' => array($baseDir . '/src/includes/interfaces'),
|
14 |
+
'WebSharks\\CometCache\\Classes\\' => array($baseDir . '/src/includes/classes'),
|
15 |
);
|
src/vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit33853609dfb2ae52d36861a4ab25a03b
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
@@ -43,8 +43,3 @@ class ComposerAutoloaderInit33853609dfb2ae52d36861a4ab25a03b
|
|
43 |
return $loader;
|
44 |
}
|
45 |
}
|
46 |
-
|
47 |
-
function composerRequire33853609dfb2ae52d36861a4ab25a03b($file)
|
48 |
-
{
|
49 |
-
require $file;
|
50 |
-
}
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInitc1a53f596a710aab47629b58885a6ec2
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInitc1a53f596a710aab47629b58885a6ec2', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInitc1a53f596a710aab47629b58885a6ec2', 'loadClassLoader'));
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
43 |
return $loader;
|
44 |
}
|
45 |
}
|
|
|
|
|
|
|
|
|
|
src/vendor/composer/installed.json
CHANGED
@@ -1,25 +1,31 @@
|
|
1 |
[
|
2 |
{
|
3 |
-
"name": "websharks/
|
4 |
-
"version": "
|
5 |
-
"version_normalized": "
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
-
"url": "https://github.com/websharks/
|
9 |
-
"reference": "
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
-
"url": "https://api.github.com/repos/websharks/
|
14 |
-
"reference": "
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
18 |
-
"
|
|
|
19 |
},
|
20 |
-
"time": "2015-05-
|
21 |
"type": "library",
|
22 |
"installation-source": "dist",
|
|
|
|
|
|
|
|
|
|
|
23 |
"notification-url": "https://packagist.org/downloads/",
|
24 |
"license": [
|
25 |
"GPL-3.0+"
|
@@ -41,12 +47,13 @@
|
|
41 |
"role": "developer"
|
42 |
}
|
43 |
],
|
44 |
-
"description": "
|
45 |
-
"homepage": "https://github.com/websharks/
|
46 |
"keywords": [
|
47 |
-
"
|
48 |
-
"
|
49 |
-
"
|
|
|
50 |
]
|
51 |
},
|
52 |
{
|
@@ -106,30 +113,34 @@
|
|
106 |
]
|
107 |
},
|
108 |
{
|
109 |
-
"name": "websharks/
|
110 |
-
"version": "
|
111 |
-
"version_normalized": "
|
112 |
"source": {
|
113 |
"type": "git",
|
114 |
-
"url": "https://github.com/websharks/
|
115 |
-
"reference": "
|
116 |
},
|
117 |
"dist": {
|
118 |
"type": "zip",
|
119 |
-
"url": "https://api.github.com/repos/websharks/
|
120 |
-
"reference": "
|
121 |
"shasum": ""
|
122 |
},
|
123 |
"require": {
|
|
|
124 |
"ext-mbstring": "*",
|
125 |
-
"
|
|
|
|
|
|
|
126 |
},
|
127 |
-
"time": "
|
128 |
"type": "library",
|
129 |
"installation-source": "dist",
|
130 |
"autoload": {
|
131 |
"psr-4": {
|
132 |
-
"WebSharks\\
|
133 |
}
|
134 |
},
|
135 |
"notification-url": "https://packagist.org/downloads/",
|
@@ -153,45 +164,37 @@
|
|
153 |
"role": "developer"
|
154 |
}
|
155 |
],
|
156 |
-
"description": "
|
157 |
-
"homepage": "https://github.com/websharks/
|
158 |
"keywords": [
|
159 |
-
"JS",
|
160 |
"compressor",
|
161 |
-
"
|
162 |
"websharks"
|
163 |
]
|
164 |
},
|
165 |
{
|
166 |
-
"name": "websharks/
|
167 |
-
"version": "
|
168 |
-
"version_normalized": "
|
169 |
"source": {
|
170 |
"type": "git",
|
171 |
-
"url": "https://github.com/websharks/
|
172 |
-
"reference": "
|
173 |
},
|
174 |
"dist": {
|
175 |
"type": "zip",
|
176 |
-
"url": "https://api.github.com/repos/websharks/
|
177 |
-
"reference": "
|
178 |
"shasum": ""
|
179 |
},
|
180 |
-
"require": {
|
181 |
-
"
|
182 |
-
"ext-mbstring": "*",
|
183 |
-
"ext-openssl": "*",
|
184 |
-
"php": ">=5.3",
|
185 |
-
"websharks/css-minifier": "dev-master",
|
186 |
-
"websharks/js-minifier": "dev-master"
|
187 |
},
|
188 |
-
"time": "2016-
|
189 |
"type": "library",
|
190 |
"installation-source": "dist",
|
191 |
"autoload": {
|
192 |
-
"psr-4":
|
193 |
-
"WebSharks\\HtmlCompressor\\": "src/includes/classes"
|
194 |
-
}
|
195 |
},
|
196 |
"notification-url": "https://packagist.org/downloads/",
|
197 |
"license": [
|
@@ -214,38 +217,35 @@
|
|
214 |
"role": "developer"
|
215 |
}
|
216 |
],
|
217 |
-
"description": "
|
218 |
-
"homepage": "https://github.com/websharks/
|
219 |
"keywords": [
|
220 |
-
"
|
221 |
-
"
|
222 |
-
"
|
223 |
]
|
224 |
},
|
225 |
{
|
226 |
-
"name": "websharks/
|
227 |
-
"version": "
|
228 |
-
"version_normalized": "
|
229 |
"source": {
|
230 |
"type": "git",
|
231 |
-
"url": "https://github.com/websharks/
|
232 |
-
"reference": "
|
233 |
},
|
234 |
"dist": {
|
235 |
"type": "zip",
|
236 |
-
"url": "https://api.github.com/repos/websharks/
|
237 |
-
"reference": "
|
238 |
"shasum": ""
|
239 |
},
|
240 |
-
"require
|
241 |
-
"
|
242 |
},
|
243 |
-
"time": "
|
244 |
"type": "library",
|
245 |
"installation-source": "dist",
|
246 |
-
"autoload": {
|
247 |
-
"psr-4": []
|
248 |
-
},
|
249 |
"notification-url": "https://packagist.org/downloads/",
|
250 |
"license": [
|
251 |
"GPL-3.0+"
|
@@ -267,8 +267,8 @@
|
|
267 |
"role": "developer"
|
268 |
}
|
269 |
],
|
270 |
-
"description": "
|
271 |
-
"homepage": "https://github.com/websharks/
|
272 |
"keywords": [
|
273 |
"php",
|
274 |
"websharks",
|
@@ -295,15 +295,15 @@
|
|
295 |
"source": {
|
296 |
"type": "git",
|
297 |
"url": "https://github.com/websharks/wp-i18n-tools.git",
|
298 |
-
"reference": "
|
299 |
},
|
300 |
"dist": {
|
301 |
"type": "zip",
|
302 |
-
"url": "https://api.github.com/repos/websharks/wp-i18n-tools/zipball/
|
303 |
-
"reference": "
|
304 |
"shasum": ""
|
305 |
},
|
306 |
-
"time": "
|
307 |
"type": "library",
|
308 |
"installation-source": "dist",
|
309 |
"notification-url": "https://packagist.org/downloads/",
|
1 |
[
|
2 |
{
|
3 |
+
"name": "websharks/js-minifier",
|
4 |
+
"version": "dev-master",
|
5 |
+
"version_normalized": "9999999-dev",
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
+
"url": "https://github.com/websharks/js-minifier.git",
|
9 |
+
"reference": "3c1e99af6df9df8f691642fbb769a10e49bfba23"
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/websharks/js-minifier/zipball/3c1e99af6df9df8f691642fbb769a10e49bfba23",
|
14 |
+
"reference": "3c1e99af6df9df8f691642fbb769a10e49bfba23",
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
18 |
+
"ext-mbstring": "*",
|
19 |
+
"php": ">=5.3"
|
20 |
},
|
21 |
+
"time": "2015-05-11 20:53:04",
|
22 |
"type": "library",
|
23 |
"installation-source": "dist",
|
24 |
+
"autoload": {
|
25 |
+
"psr-4": {
|
26 |
+
"WebSharks\\JsMinifier\\": "src/includes/classes"
|
27 |
+
}
|
28 |
+
},
|
29 |
"notification-url": "https://packagist.org/downloads/",
|
30 |
"license": [
|
31 |
"GPL-3.0+"
|
47 |
"role": "developer"
|
48 |
}
|
49 |
],
|
50 |
+
"description": "Compresses JavaScript code.",
|
51 |
+
"homepage": "https://github.com/websharks/js-minifier",
|
52 |
"keywords": [
|
53 |
+
"JS",
|
54 |
+
"compressor",
|
55 |
+
"javascript",
|
56 |
+
"websharks"
|
57 |
]
|
58 |
},
|
59 |
{
|
113 |
]
|
114 |
},
|
115 |
{
|
116 |
+
"name": "websharks/html-compressor",
|
117 |
+
"version": "160118",
|
118 |
+
"version_normalized": "160118",
|
119 |
"source": {
|
120 |
"type": "git",
|
121 |
+
"url": "https://github.com/websharks/html-compressor.git",
|
122 |
+
"reference": "bd1ba2407b9c2c067549600a6ef1faa726c3c2d2"
|
123 |
},
|
124 |
"dist": {
|
125 |
"type": "zip",
|
126 |
+
"url": "https://api.github.com/repos/websharks/html-compressor/zipball/bd1ba2407b9c2c067549600a6ef1faa726c3c2d2",
|
127 |
+
"reference": "bd1ba2407b9c2c067549600a6ef1faa726c3c2d2",
|
128 |
"shasum": ""
|
129 |
},
|
130 |
"require": {
|
131 |
+
"ext-curl": "*",
|
132 |
"ext-mbstring": "*",
|
133 |
+
"ext-openssl": "*",
|
134 |
+
"php": ">=5.3",
|
135 |
+
"websharks/css-minifier": "dev-master",
|
136 |
+
"websharks/js-minifier": "dev-master"
|
137 |
},
|
138 |
+
"time": "2016-01-18 03:17:20",
|
139 |
"type": "library",
|
140 |
"installation-source": "dist",
|
141 |
"autoload": {
|
142 |
"psr-4": {
|
143 |
+
"WebSharks\\HtmlCompressor\\": "src/includes/classes"
|
144 |
}
|
145 |
},
|
146 |
"notification-url": "https://packagist.org/downloads/",
|
164 |
"role": "developer"
|
165 |
}
|
166 |
],
|
167 |
+
"description": "Combines & compresses CSS/JS/HTML code.",
|
168 |
+
"homepage": "https://github.com/websharks/html-compressor",
|
169 |
"keywords": [
|
|
|
170 |
"compressor",
|
171 |
+
"html",
|
172 |
"websharks"
|
173 |
]
|
174 |
},
|
175 |
{
|
176 |
+
"name": "websharks/sharkicons",
|
177 |
+
"version": "160221",
|
178 |
+
"version_normalized": "160221",
|
179 |
"source": {
|
180 |
"type": "git",
|
181 |
+
"url": "https://github.com/websharks/sharkicons.git",
|
182 |
+
"reference": "2e6d6663c050f343fe944b424dea1759aa67cd05"
|
183 |
},
|
184 |
"dist": {
|
185 |
"type": "zip",
|
186 |
+
"url": "https://api.github.com/repos/websharks/sharkicons/zipball/2e6d6663c050f343fe944b424dea1759aa67cd05",
|
187 |
+
"reference": "2e6d6663c050f343fe944b424dea1759aa67cd05",
|
188 |
"shasum": ""
|
189 |
},
|
190 |
+
"require-dev": {
|
191 |
+
"package/bourbon": "4.2.3"
|
|
|
|
|
|
|
|
|
|
|
192 |
},
|
193 |
+
"time": "2016-02-21 15:16:12",
|
194 |
"type": "library",
|
195 |
"installation-source": "dist",
|
196 |
"autoload": {
|
197 |
+
"psr-4": []
|
|
|
|
|
198 |
},
|
199 |
"notification-url": "https://packagist.org/downloads/",
|
200 |
"license": [
|
217 |
"role": "developer"
|
218 |
}
|
219 |
],
|
220 |
+
"description": "Font containing WebSharks logos/icons.",
|
221 |
+
"homepage": "https://github.com/websharks/sharkicons",
|
222 |
"keywords": [
|
223 |
+
"php",
|
224 |
+
"websharks",
|
225 |
+
"wordpress"
|
226 |
]
|
227 |
},
|
228 |
{
|
229 |
+
"name": "websharks/wp-php-rv",
|
230 |
+
"version": "150511",
|
231 |
+
"version_normalized": "150511",
|
232 |
"source": {
|
233 |
"type": "git",
|
234 |
+
"url": "https://github.com/websharks/wp-php-rv.git",
|
235 |
+
"reference": "ed0a58f3647e59c740560235da1e61904dca8d84"
|
236 |
},
|
237 |
"dist": {
|
238 |
"type": "zip",
|
239 |
+
"url": "https://api.github.com/repos/websharks/wp-php-rv/zipball/ed0a58f3647e59c740560235da1e61904dca8d84",
|
240 |
+
"reference": "ed0a58f3647e59c740560235da1e61904dca8d84",
|
241 |
"shasum": ""
|
242 |
},
|
243 |
+
"require": {
|
244 |
+
"php": ">=5.2"
|
245 |
},
|
246 |
+
"time": "2015-05-10 10:30:04",
|
247 |
"type": "library",
|
248 |
"installation-source": "dist",
|
|
|
|
|
|
|
249 |
"notification-url": "https://packagist.org/downloads/",
|
250 |
"license": [
|
251 |
"GPL-3.0+"
|
267 |
"role": "developer"
|
268 |
}
|
269 |
],
|
270 |
+
"description": "Stub for WordPress themes/plugins that require PHP vX.x+.",
|
271 |
+
"homepage": "https://github.com/websharks/wp-php-rv",
|
272 |
"keywords": [
|
273 |
"php",
|
274 |
"websharks",
|
295 |
"source": {
|
296 |
"type": "git",
|
297 |
"url": "https://github.com/websharks/wp-i18n-tools.git",
|
298 |
+
"reference": "0275dc189293aee71e80a8bde43c4087f81ce9bb"
|
299 |
},
|
300 |
"dist": {
|
301 |
"type": "zip",
|
302 |
+
"url": "https://api.github.com/repos/websharks/wp-i18n-tools/zipball/0275dc189293aee71e80a8bde43c4087f81ce9bb",
|
303 |
+
"reference": "0275dc189293aee71e80a8bde43c4087f81ce9bb",
|
304 |
"shasum": ""
|
305 |
},
|
306 |
+
"time": "2016-04-16 08:29:33",
|
307 |
"type": "library",
|
308 |
"installation-source": "dist",
|
309 |
"notification-url": "https://packagist.org/downloads/",
|
src/vendor/websharks/sharkicons/src/long-classes.min.css
CHANGED
@@ -1,3 +1,2 @@
|
|
1 |
@font-face{font-family:sharkicons;src:url("fonts/sharkicons.eot?v160221");src:url("fonts/sharkicons.eot?#iefix&v160221") format("embedded-opentype"),url("fonts/sharkicons.ttf?v160221") format("truetype"),url("fonts/sharkicons.woff?v160221") format("woff"),url("fonts/sharkicons.svg?v160221#sharkicons") format("svg");font-weight:normal;font-style:normal}.sharkicon::before{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none}.sharkicon-broom::before{content:""}.sharkicon-comment-mail-one::before{content:""}.sharkicon-comment-mail::before{content:""}.sharkicon-s2member::before{content:""}.sharkicon-websharks::before{content:""}.sharkicon-wp-kb-articles::before{content:""}.sharkicon-zencache-logo::before{content:""}.sharkicon-zencache::before{content:""}.sharkicon-wp-sharks::before{content:""}.sharkicon-wp-sharks-fin::before{content:""}.sharkicon-comet-cache::before{content:""}.sharkicon-comet-cache-logo::before{content:""}.sharkicon-comet-cache-comet::before{content:""}.sharkicon-feat-watch::before{content:""}.sharkicon-feat-server::before{content:""}.sharkicon-feat-layers::before{content:""}.sharkicon-feat-box::before{content:""}.sharkicon-feat-ellipsis::before{content:""}.sharkicon-typi-group::before{content:""}.sharkicon-enty-bookmark::before{content:""}.sharkicon-enty-bookmarks::before{content:""}.sharkicon-enty-open-book::before{content:""}.sharkicon-enty-archive::before{content:""}.sharkicon-enty-area-graph::before{content:""}.sharkicon-enty-bucket::before{content:""}.sharkicon-enty-colors::before{content:""}.sharkicon-enty-copy::before{content:""}.sharkicon-enty-drive::before{content:""}.sharkicon-enty-feather::before{content:""}.sharkicon-enty-gauge::before{content:""}.sharkicon-enty-hand::before{content:""}.sharkicon-enty-lab-flask::before{content:""}.sharkicon-enty-mask::before{content:""}.sharkicon-enty-medal::before{content:""}.sharkicon-enty-exclamation::before{content:""}.sharkicon-enty-palette::before{content:""}.sharkicon-enty-ruler::before{content:""}.sharkicon-enty-shop::before{content:""}.sharkicon-enty-basket::before{content:""}.sharkicon-enty-cart::before{content:""}.sharkicon-enty-traffic-cone::before{content:""}.sharkicon-enty-tree::before{content:""}.sharkicon-enty-trophy::before{content:""}.sharkicon-enty-v-card::before{content:""}.sharkicon-enty-google-hangouts::before{content:""}.sharkicon-eleg-line-graph::before{content:""}.sharkicon-eleg-male::before{content:""}.sharkicon-eleg-female::before{content:""}.sharkicon-eleg-atom::before{content:""}.sharkicon-broc-cart::before{content:""}.sharkicon-broc-crap::before{content:""}.sharkicon-broc-atom::before{content:""}.sharkicon-icom-headphones::before{content:""}.sharkicon-icom-barcode::before{content:""}.sharkicon-icom-user::before{content:""}.sharkicon-icom-users::before{content:""}.sharkicon-icom-user-plus::before{content:""}.sharkicon-icom-user-minus::before{content:""}.sharkicon-icom-user-check::before{content:""}.sharkicon-icom-user-tie::before{content:""}.sharkicon-icom-key::before{content:""}.sharkicon-icom-key2::before{content:""}.sharkicon-icom-happy::before{content:""}.sharkicon-icom-happy2::before{content:""}.sharkicon-icom-smile::before{content:""}.sharkicon-icom-smile2::before{content:""}.sharkicon-icom-tongue::before{content:""}.sharkicon-icom-tongue2::before{content:""}.sharkicon-icom-sad::before{content:""}.sharkicon-icom-sad2::before{content:""}.sharkicon-icom-wink::before{content:""}.sharkicon-icom-wink2::before{content:""}.sharkicon-icom-grin::before{content:""}.sharkicon-icom-grin2::before{content:""}.sharkicon-icom-cool::before{content:""}.sharkicon-icom-cool2::before{content:""}.sharkicon-icom-angry::before{content:""}.sharkicon-icom-angry2::before{content:""}.sharkicon-icom-evil::before{content:""}.sharkicon-icom-evil2::before{content:""}.sharkicon-icom-shocked::before{content:""}.sharkicon-icom-shocked2::before{content:""}.sharkicon-icom-baffled::before{content:""}.sharkicon-icom-baffled2::before{content:""}.sharkicon-icom-confused::before{content:""}.sharkicon-icom-confused2::before{content:""}.sharkicon-icom-neutral::before{content:""}.sharkicon-icom-neutral2::before{content:""}.sharkicon-icom-hipster::before{content:""}.sharkicon-icom-hipster2::before{content:""}.sharkicon-icom-wondering::before{content:""}.sharkicon-icom-wondering2::before{content:""}.sharkicon-icom-sleepy::before{content:""}.sharkicon-icom-sleepy2::before{content:""}.sharkicon-icom-frustrated::before{content:""}.sharkicon-icom-frustrated2::before{content:""}.sharkicon-icom-crying::before{content:""}.sharkicon-icom-crying2::before{content:""}.sharkicon-icom-spell-check::before{content:""}.sharkicon-icom-command-key::before{content:""}.sharkicon-icom-shift-key::before{content:""}.sharkicon-icom-control-key::before{content:""}.sharkicon-icom-option-key::before{content:""}.sharkicon-icom-wordpress::before{content:""}.sharkicon-icom-wordpress-square::before{content:""}.sharkicon-icom-yahoo::before{content:""}.sharkicon-icom-linux::before{content:""}.sharkicon-icom-finder::before{content:""}.sharkicon-icom-android::before{content:""}.sharkicon-icom-reddit::before{content:""}.sharkicon-icom-paypal::before{content:""}.sharkicon-icom-git::before{content:""}.sharkicon-octi-alignment-align::before{content:""}.sharkicon-octi-alignment-aligned-to::before{content:""}.sharkicon-octi-alignment-unalign::before{content:""}.sharkicon-octi-bookmark::before{content:""}.sharkicon-octi-broadcast::before{content:""}.sharkicon-octi-browser::before{content:""}.sharkicon-octi-checklist::before{content:""}.sharkicon-octi-circuit-board::before{content:""}.sharkicon-octi-clippy::before{content:""}.sharkicon-octi-cloud-download::before{content:""}.sharkicon-octi-cloud-upload::before{content:""}.sharkicon-octi-comment::before{content:""}.sharkicon-octi-comments::before{content:""}.sharkicon-octi-tach::before{content:""}.sharkicon-octi-device-camera::before{content:""}.sharkicon-octi-device-camera-video::before{content:""}.sharkicon-octi-device-desktop::before{content:""}.sharkicon-octi-diff::before{content:""}.sharkicon-octi-file-binary::before{content:""}.sharkicon-octi-file-media::before{content:""}.sharkicon-octi-file-submodule::before{content:""}.sharkicon-octi-file-symlink-directory::before{content:""}.sharkicon-octi-file-symlink-file::before{content:""}.sharkicon-octi-fold::before{content:""}.sharkicon-octi-git-branch::before{content:""}.sharkicon-octi-git-commit::before{content:""}.sharkicon-octi-git-compare::before{content:""}.sharkicon-octi-git-merge::before{content:""}.sharkicon-octi-git-pull-request::before{content:""}.sharkicon-octi-graph::before{content:""}.sharkicon-octi-home::before{content:""}.sharkicon-octi-horizontal-rule::before{content:""}.sharkicon-octi-key::before{content:""}.sharkicon-octi-light-bulb::before{content:""}.sharkicon-octi-link-external::before{content:""}.sharkicon-octi-lock::before{content:""}.sharkicon-octi-markdown::before{content:""}.sharkicon-octi-microscope::before{content:""}.sharkicon-octi-mirror::before{content:""}.sharkicon-octi-move-down::before{content:""}.sharkicon-octi-move-left::before{content:""}.sharkicon-octi-move-right::before{content:""}.sharkicon-octi-move-up::before{content:""}.sharkicon-octi-mute::before{content:""}.sharkicon-octi-organization::before{content:""}.sharkicon-octi-package::before{content:""}.sharkicon-octi-paintcan::before{content:""}.sharkicon-octi-person::before{content:""}.sharkicon-octi-plug::before{content:""}.sharkicon-octi-podium::before{content:""}.sharkicon-octi-pulse::before{content:""}.sharkicon-octi-puzzle::before{content:""}.sharkicon-octi-repo::before{content:""}.sharkicon-octi-repo-clone::before{content:""}.sharkicon-octi-repo-force-push::before{content:""}.sharkicon-octi-repo-forked::before{content:""}.sharkicon-octi-repo-pull::before{content:""}.sharkicon-octi-repo-push::before{content:""}.sharkicon-octi-rocket::before{content:""}.sharkicon-octi-ruby::before{content:""}.sharkicon-octi-screen-full::before{content:""}.sharkicon-octi-screen-normal::before{content:""}.sharkicon-octi-sign-in::before{content:""}.sharkicon-octi-sign-out::before{content:""}.sharkicon-octi-split::before{content:""}.sharkicon-octi-squirrel::before{content:""}.sharkicon-octi-steps::before{content:""}.sharkicon-octi-tag::before{content:""}.sharkicon-octi-telescope::before{content:""}.sharkicon-octi-terminal::before{content:""}.sharkicon-octi-unfold::before{content:""}.sharkicon-octi-versions::before{content:""}.sharkicon-glass::before{content:""}.sharkicon-music::before{content:""}.sharkicon-search::before{content:""}.sharkicon-envelope-o::before{content:""}.sharkicon-heart::before{content:""}.sharkicon-star::before{content:""}.sharkicon-star-o::before{content:""}.sharkicon-user::before{content:""}.sharkicon-film::before{content:""}.sharkicon-th-large::before{content:""}.sharkicon-th::before{content:""}.sharkicon-th-list::before{content:""}.sharkicon-check::before{content:""}.sharkicon-close::before{content:""}.sharkicon-search-plus::before{content:""}.sharkicon-search-minus::before{content:""}.sharkicon-power-off::before{content:""}.sharkicon-signal::before{content:""}.sharkicon-cog::before{content:""}.sharkicon-trash-o::before{content:""}.sharkicon-home::before{content:""}.sharkicon-file-o::before{content:""}.sharkicon-clock-o::before{content:""}.sharkicon-road::before{content:""}.sharkicon-download::before{content:""}.sharkicon-arrow-circle-o-down::before{content:""}.sharkicon-arrow-circle-o-up::before{content:""}.sharkicon-inbox::before{content:""}.sharkicon-play-circle-o::before{content:""}.sharkicon-repeat::before{content:""}.sharkicon-refresh::before{content:""}.sharkicon-list-alt::before{content:""}.sharkicon-lock::before{content:""}.sharkicon-flag::before{content:""}.sharkicon-headphones::before{content:""}.sharkicon-volume-off::before{content:""}.sharkicon-volume-down::before{content:""}.sharkicon-volume-up::before{content:""}.sharkicon-qrcode::before{content:""}.sharkicon-barcode::before{content:""}.sharkicon-tag::before{content:""}.sharkicon-tags::before{content:""}.sharkicon-book::before{content:""}.sharkicon-bookmark::before{content:""}.sharkicon-print::before{content:""}.sharkicon-camera::before{content:""}.sharkicon-font::before{content:""}.sharkicon-bold::before{content:""}.sharkicon-italic::before{content:""}.sharkicon-text-height::before{content:""}.sharkicon-text-width::before{content:""}.sharkicon-align-left::before{content:""}.sharkicon-align-center::before{content:""}.sharkicon-align-right::before{content:""}.sharkicon-align-justify::before{content:""}.sharkicon-list::before{content:""}.sharkicon-dedent::before{content:""}.sharkicon-indent::before{content:""}.sharkicon-video-camera::before{content:""}.sharkicon-image::before{content:""}.sharkicon-pencil::before{content:""}.sharkicon-map-marker::before{content:""}.sharkicon-adjust::before{content:""}.sharkicon-tint::before{content:""}.sharkicon-edit::before{content:""}.sharkicon-share-square-o::before{content:""}.sharkicon-check-square-o::before{content:""}.sharkicon-arrows::before{content:""}.sharkicon-step-backward::before{content:""}.sharkicon-fast-backward::before{content:""}.sharkicon-backward::before{content:""}.sharkicon-play::before{content:""}.sharkicon-pause::before{content:""}.sharkicon-stop::before{content:""}.sharkicon-forward::before{content:""}.sharkicon-fast-forward::before{content:""}.sharkicon-step-forward::before{content:""}.sharkicon-eject::before{content:""}.sharkicon-chevron-left::before{content:""}.sharkicon-chevron-right::before{content:""}.sharkicon-plus-circle::before{content:""}.sharkicon-minus-circle::before{content:""}.sharkicon-times-circle::before{content:""}.sharkicon-check-circle::before{content:""}.sharkicon-question-circle::before{content:""}.sharkicon-info-circle::before{content:""}.sharkicon-crosshairs::before{content:""}.sharkicon-times-circle-o::before{content:""}.sharkicon-check-circle-o::before{content:""}.sharkicon-ban::before{content:""}.sharkicon-arrow-left::before{content:""}.sharkicon-arrow-right::before{content:""}.sharkicon-arrow-up::before{content:""}.sharkicon-arrow-down::before{content:""}.sharkicon-mail-forward::before{content:""}.sharkicon-expand::before{content:""}.sharkicon-compress::before{content:""}.sharkicon-plus::before{content:""}.sharkicon-minus::before{content:""}.sharkicon-asterisk::before{content:""}.sharkicon-exclamation-circle::before{content:""}.sharkicon-gift::before{content:""}.sharkicon-leaf::before{content:""}.sharkicon-fire::before{content:""}.sharkicon-eye::before{content:""}.sharkicon-eye-slash::before{content:""}.sharkicon-exclamation-triangle::before{content:""}.sharkicon-plane::before{content:""}.sharkicon-calendar::before{content:""}.sharkicon-random::before{content:""}.sharkicon-comment::before{content:""}.sharkicon-magnet::before{content:""}.sharkicon-chevron-up::before{content:""}.sharkicon-chevron-down::before{content:""}.sharkicon-retweet::before{content:""}.sharkicon-shopping-cart::before{content:""}.sharkicon-folder::before{content:""}.sharkicon-folder-open::before{content:""}.sharkicon-arrows-v::before{content:""}.sharkicon-arrows-h::before{content:""}.sharkicon-bar-chart::before{content:""}.sharkicon-twitter-square::before{content:""}.sharkicon-facebook-square::before{content:""}.sharkicon-camera-retro::before{content:""}.sharkicon-key::before{content:""}.sharkicon-cogs::before{content:""}.sharkicon-comments::before{content:""}.sharkicon-thumbs-o-up::before{content:""}.sharkicon-thumbs-o-down::before{content:""}.sharkicon-star-half::before{content:""}.sharkicon-heart-o::before{content:""}.sharkicon-sign-out::before{content:""}.sharkicon-linkedin-square::before{content:""}.sharkicon-thumb-tack::before{content:""}.sharkicon-external-link::before{content:""}.sharkicon-sign-in::before{content:""}.sharkicon-trophy::before{content:""}.sharkicon-github-square::before{content:""}.sharkicon-upload::before{content:""}.sharkicon-lemon-o::before{content:""}.sharkicon-phone::before{content:""}.sharkicon-square-o::before{content:""}.sharkicon-bookmark-o::before{content:""}.sharkicon-phone-square::before{content:""}.sharkicon-twitter::before{content:""}.sharkicon-facebook::before{content:""}.sharkicon-github::before{content:""}.sharkicon-unlock::before{content:""}.sharkicon-credit-card::before{content:""}.sharkicon-feed::before{content:""}.sharkicon-hdd-o::before{content:""}.sharkicon-bullhorn::before{content:""}.sharkicon-bell-o::before{content:""}.sharkicon-certificate::before{content:""}.sharkicon-hand-o-right::before{content:""}.sharkicon-hand-o-left::before{content:""}.sharkicon-hand-o-up::before{content:""}.sharkicon-hand-o-down::before{content:""}.sharkicon-arrow-circle-left::before{content:""}.sharkicon-arrow-circle-right::before{content:""}.sharkicon-arrow-circle-up::before{content:""}.sharkicon-arrow-circle-down::before{content:""}.sharkicon-globe::before{content:""}.sharkicon-wrench::before{content:""}.sharkicon-tasks::before{content:""}.sharkicon-filter::before{content:""}.sharkicon-briefcase::before{content:""}.sharkicon-arrows-alt::before{content:""}.sharkicon-group::before{content:""}.sharkicon-chain::before{content:""}.sharkicon-cloud::before{content:""}.sharkicon-flask::before{content:""}.sharkicon-cut::before{content:""}.sharkicon-copy::before{content:""}.sharkicon-paperclip::before{content:""}.sharkicon-floppy-o::before{content:""}.sharkicon-square::before{content:""}.sharkicon-bars::before{content:""}.sharkicon-list-ul::before{content:""}.sharkicon-list-ol::before{content:""}.sharkicon-strikethrough::before{content:""}.sharkicon-underline::before{content:""}.sharkicon-table::before{content:""}.sharkicon-magic::before{content:""}.sharkicon-truck::before{content:""}.sharkicon-pinterest::before{content:""}.sharkicon-pinterest-square::before{content:""}.sharkicon-google-plus-square::before{content:""}.sharkicon-google-plus::before{content:""}.sharkicon-money::before{content:""}.sharkicon-caret-down::before{content:""}.sharkicon-caret-up::before{content:""}.sharkicon-caret-left::before{content:""}.sharkicon-caret-right::before{content:""}.sharkicon-columns::before{content:""}.sharkicon-sort::before{content:""}.sharkicon-sort-desc::before{content:""}.sharkicon-sort-asc::before{content:""}.sharkicon-envelope::before{content:""}.sharkicon-linkedin::before{content:""}.sharkicon-rotate-left::before{content:""}.sharkicon-gavel::before{content:""}.sharkicon-dashboard::before{content:""}.sharkicon-comment-o::before{content:""}.sharkicon-comments-o::before{content:""}.sharkicon-bolt::before{content:""}.sharkicon-sitemap::before{content:""}.sharkicon-umbrella::before{content:""}.sharkicon-clipboard::before{content:""}.sharkicon-lightbulb-o::before{content:""}.sharkicon-exchange::before{content:""}.sharkicon-cloud-download::before{content:""}.sharkicon-cloud-upload::before{content:""}.sharkicon-user-md::before{content:""}.sharkicon-stethoscope::before{content:""}.sharkicon-suitcase::before{content:""}.sharkicon-bell::before{content:""}.sharkicon-coffee::before{content:""}.sharkicon-cutlery::before{content:""}.sharkicon-file-text-o::before{content:""}.sharkicon-building-o::before{content:""}.sharkicon-hospital-o::before{content:""}.sharkicon-ambulance::before{content:""}.sharkicon-medkit::before{content:""}.sharkicon-fighter-jet::before{content:""}.sharkicon-beer::before{content:""}.sharkicon-h-square::before{content:""}.sharkicon-plus-square::before{content:""}.sharkicon-angle-double-left::before{content:""}.sharkicon-angle-double-right::before{content:""}.sharkicon-angle-double-up::before{content:""}.sharkicon-angle-double-down::before{content:""}.sharkicon-angle-left::before{content:""}.sharkicon-angle-right::before{content:""}.sharkicon-angle-up::before{content:""}.sharkicon-angle-down::before{content:""}.sharkicon-desktop::before{content:""}.sharkicon-laptop::before{content:""}.sharkicon-tablet::before{content:""}.sharkicon-mobile::before{content:""}.sharkicon-circle-o::before{content:""}.sharkicon-quote-left::before{content:""}.sharkicon-quote-right::before{content:""}.sharkicon-spinner::before{content:""}.sharkicon-circle::before{content:""}.sharkicon-mail-reply::before{content:""}.sharkicon-github-alt::before{content:""}.sharkicon-folder-o::before{content:""}.sharkicon-folder-open-o::before{content:""}.sharkicon-smile-o::before{content:""}.sharkicon-frown-o::before{content:""}.sharkicon-meh-o::before{content:""}.sharkicon-gamepad::before{content:""}.sharkicon-keyboard-o::before{content:""}.sharkicon-flag-o::before{content:""}.sharkicon-flag-checkered::before{content:""}.sharkicon-terminal::before{content:""}.sharkicon-code::before{content:""}.sharkicon-mail-reply-all::before{content:""}.sharkicon-star-half-empty::before{content:""}.sharkicon-location-arrow::before{content:""}.sharkicon-crop::before{content:""}.sharkicon-code-fork::before{content:""}.sharkicon-chain-broken::before{content:""}.sharkicon-question::before{content:""}.sharkicon-info::before{content:""}.sharkicon-exclamation::before{content:""}.sharkicon-superscript::before{content:""}.sharkicon-subscript::before{content:""}.sharkicon-eraser::before{content:""}.sharkicon-puzzle-piece::before{content:""}.sharkicon-microphone::before{content:""}.sharkicon-microphone-slash::before{content:""}.sharkicon-shield::before{content:""}.sharkicon-calendar-o::before{content:""}.sharkicon-fire-extinguisher::before{content:""}.sharkicon-rocket::before{content:""}.sharkicon-maxcdn::before{content:""}.sharkicon-chevron-circle-left::before{content:""}.sharkicon-chevron-circle-right::before{content:""}.sharkicon-chevron-circle-up::before{content:""}.sharkicon-chevron-circle-down::before{content:""}.sharkicon-html5::before{content:""}.sharkicon-css3::before{content:""}.sharkicon-anchor::before{content:""}.sharkicon-unlock-alt::before{content:""}.sharkicon-bullseye::before{content:""}.sharkicon-ellipsis-h::before{content:""}.sharkicon-ellipsis-v::before{content:""}.sharkicon-rss-square::before{content:""}.sharkicon-play-circle::before{content:""}.sharkicon-ticket::before{content:""}.sharkicon-minus-square::before{content:""}.sharkicon-minus-square-o::before{content:""}.sharkicon-level-up::before{content:""}.sharkicon-level-down::before{content:""}.sharkicon-check-square::before{content:""}.sharkicon-pencil-square::before{content:""}.sharkicon-external-link-square::before{content:""}.sharkicon-share-square::before{content:""}.sharkicon-compass::before{content:""}.sharkicon-caret-square-o-down::before{content:""}.sharkicon-caret-square-o-up::before{content:""}.sharkicon-caret-square-o-right::before{content:""}.sharkicon-eur::before{content:""}.sharkicon-gbp::before{content:""}.sharkicon-dollar::before{content:""}.sharkicon-inr::before{content:""}.sharkicon-cny::before{content:""}.sharkicon-rouble::before{content:""}.sharkicon-krw::before{content:""}.sharkicon-bitcoin::before{content:""}.sharkicon-file::before{content:""}.sharkicon-file-text::before{content:""}.sharkicon-sort-alpha-asc::before{content:""}.sharkicon-sort-alpha-desc::before{content:""}.sharkicon-sort-amount-asc::before{content:""}.sharkicon-sort-amount-desc::before{content:""}.sharkicon-sort-numeric-asc::before{content:""}.sharkicon-sort-numeric-desc::before{content:""}.sharkicon-thumbs-up::before{content:""}.sharkicon-thumbs-down::before{content:""}.sharkicon-youtube-square::before{content:""}.sharkicon-youtube::before{content:""}.sharkicon-xing::before{content:""}.sharkicon-xing-square::before{content:""}.sharkicon-youtube-play::before{content:""}.sharkicon-dropbox::before{content:""}.sharkicon-stack-overflow::before{content:""}.sharkicon-instagram::before{content:""}.sharkicon-flickr::before{content:""}.sharkicon-adn::before{content:""}.sharkicon-bitbucket::before{content:""}.sharkicon-bitbucket-square::before{content:""}.sharkicon-tumblr::before{content:""}.sharkicon-tumblr-square::before{content:""}.sharkicon-long-arrow-down::before{content:""}.sharkicon-long-arrow-up::before{content:""}.sharkicon-long-arrow-left::before{content:""}.sharkicon-long-arrow-right::before{content:""}.sharkicon-apple::before{content:""}.sharkicon-windows::before{content:""}.sharkicon-android::before{content:""}.sharkicon-linux::before{content:""}.sharkicon-dribbble::before{content:""}.sharkicon-skype::before{content:""}.sharkicon-foursquare::before{content:""}.sharkicon-trello::before{content:""}.sharkicon-female::before{content:""}.sharkicon-male::before{content:""}.sharkicon-gittip::before{content:""}.sharkicon-sun-o::before{content:""}.sharkicon-moon-o::before{content:""}.sharkicon-archive::before{content:""}.sharkicon-bug::before{content:""}.sharkicon-vk::before{content:""}.sharkicon-weibo::before{content:""}.sharkicon-renren::before{content:""}.sharkicon-pagelines::before{content:""}.sharkicon-stack-exchange::before{content:""}.sharkicon-arrow-circle-o-right::before{content:""}.sharkicon-arrow-circle-o-left::before{content:""}.sharkicon-caret-square-o-left::before{content:""}.sharkicon-dot-circle-o::before{content:""}.sharkicon-wheelchair::before{content:""}.sharkicon-vimeo-square::before{content:""}.sharkicon-try::before{content:""}.sharkicon-plus-square-o::before{content:""}.sharkicon-space-shuttle::before{content:""}.sharkicon-slack::before{content:""}.sharkicon-envelope-square::before{content:""}.sharkicon-wordpress::before{content:""}.sharkicon-openid::before{content:""}.sharkicon-bank::before{content:""}.sharkicon-graduation-cap::before{content:""}.sharkicon-yahoo::before{content:""}.sharkicon-google::before{content:""}.sharkicon-reddit::before{content:""}.sharkicon-reddit-square::before{content:""}.sharkicon-stumbleupon-circle::before{content:""}.sharkicon-stumbleupon::before{content:""}.sharkicon-delicious::before{content:""}.sharkicon-digg::before{content:""}.sharkicon-pied-piper::before{content:""}.sharkicon-pied-piper-alt::before{content:""}.sharkicon-drupal::before{content:""}.sharkicon-joomla::before{content:""}.sharkicon-language::before{content:""}.sharkicon-fax::before{content:""}.sharkicon-building::before{content:""}.sharkicon-child::before{content:""}.sharkicon-paw::before{content:""}.sharkicon-spoon::before{content:""}.sharkicon-cube::before{content:""}.sharkicon-cubes::before{content:""}.sharkicon-behance::before{content:""}.sharkicon-behance-square::before{content:""}.sharkicon-steam::before{content:""}.sharkicon-steam-square::before{content:""}.sharkicon-recycle::before{content:""}.sharkicon-automobile::before{content:""}.sharkicon-cab::before{content:""}.sharkicon-tree::before{content:""}.sharkicon-spotify::before{content:""}.sharkicon-deviantart::before{content:""}.sharkicon-soundcloud::before{content:""}.sharkicon-database::before{content:""}.sharkicon-file-pdf-o::before{content:""}.sharkicon-file-word-o::before{content:""}.sharkicon-file-excel-o::before{content:""}.sharkicon-file-powerpoint-o::before{content:""}.sharkicon-file-image-o::before{content:""}.sharkicon-file-archive-o::before{content:""}.sharkicon-file-audio-o::before{content:""}.sharkicon-file-movie-o::before{content:""}.sharkicon-file-code-o::before{content:""}.sharkicon-vine::before{content:""}.sharkicon-codepen::before{content:""}.sharkicon-jsfiddle::before{content:""}.sharkicon-life-bouy::before{content:""}.sharkicon-circle-o-notch::before{content:""}.sharkicon-ra::before{content:""}.sharkicon-empire::before{content:""}.sharkicon-git-square::before{content:""}.sharkicon-git::before{content:""}.sharkicon-hacker-news::before{content:""}.sharkicon-tencent-weibo::before{content:""}.sharkicon-qq::before{content:""}.sharkicon-wechat::before{content:""}.sharkicon-paper-plane::before{content:""}.sharkicon-paper-plane-o::before{content:""}.sharkicon-history::before{content:""}.sharkicon-circle-thin::before{content:""}.sharkicon-header::before{content:""}.sharkicon-paragraph::before{content:""}.sharkicon-sliders::before{content:""}.sharkicon-share-alt::before{content:""}.sharkicon-share-alt-square::before{content:""}.sharkicon-bomb::before{content:""}.sharkicon-futbol-o::before{content:""}.sharkicon-tty::before{content:""}.sharkicon-binoculars::before{content:""}.sharkicon-plug::before{content:""}.sharkicon-slideshare::before{content:""}.sharkicon-twitch::before{content:""}.sharkicon-yelp::before{content:""}.sharkicon-newspaper-o::before{content:""}.sharkicon-wifi::before{content:""}.sharkicon-calculator::before{content:""}.sharkicon-paypal::before{content:""}.sharkicon-google-wallet::before{content:""}.sharkicon-cc-visa::before{content:""}.sharkicon-cc-mastercard::before{content:""}.sharkicon-cc-discover::before{content:""}.sharkicon-cc-amex::before{content:""}.sharkicon-cc-paypal::before{content:""}.sharkicon-cc-stripe::before{content:""}.sharkicon-bell-slash::before{content:""}.sharkicon-bell-slash-o::before{content:""}.sharkicon-trash::before{content:""}.sharkicon-copyright::before{content:""}.sharkicon-at::before{content:""}.sharkicon-eyedropper::before{content:""}.sharkicon-paint-brush::before{content:""}.sharkicon-birthday-cake::before{content:""}.sharkicon-area-chart::before{content:""}.sharkicon-pie-chart::before{content:""}.sharkicon-line-chart::before{content:""}.sharkicon-lastfm::before{content:""}.sharkicon-lastfm-square::before{content:""}.sharkicon-toggle-off::before{content:""}.sharkicon-toggle-on::before{content:""}.sharkicon-bicycle::before{content:""}.sharkicon-bus::before{content:""}.sharkicon-ioxhost::before{content:""}.sharkicon-angellist::before{content:""}.sharkicon-cc::before{content:""}.sharkicon-ils::before{content:""}.sharkicon-meanpath::before{content:""}.sharkicon-buysellads::before{content:""}.sharkicon-connectdevelop::before{content:""}.sharkicon-dashcube::before{content:""}.sharkicon-forumbee::before{content:""}.sharkicon-leanpub::before{content:""}.sharkicon-sellsy::before{content:""}.sharkicon-shirtsinbulk::before{content:""}.sharkicon-simplybuilt::before{content:""}.sharkicon-skyatlas::before{content:""}.sharkicon-cart-plus::before{content:""}.sharkicon-cart-arrow-down::before{content:""}.sharkicon-diamond::before{content:""}.sharkicon-ship::before{content:""}.sharkicon-user-secret::before{content:""}.sharkicon-motorcycle::before{content:""}.sharkicon-street-view::before{content:""}.sharkicon-heartbeat::before{content:""}.sharkicon-venus::before{content:""}.sharkicon-mars::before{content:""}.sharkicon-mercury::before{content:""}.sharkicon-intersex::before{content:""}.sharkicon-transgender-alt::before{content:""}.sharkicon-venus-double::before{content:""}.sharkicon-mars-double::before{content:""}.sharkicon-venus-mars::before{content:""}.sharkicon-mars-stroke::before{content:""}.sharkicon-mars-stroke-v::before{content:""}.sharkicon-mars-stroke-h::before{content:""}.sharkicon-neuter::before{content:""}.sharkicon-genderless::before{content:""}.sharkicon-facebook-official::before{content:""}.sharkicon-pinterest-p::before{content:""}.sharkicon-whatsapp::before{content:""}.sharkicon-server::before{content:""}.sharkicon-user-plus::before{content:""}.sharkicon-user-times::before{content:""}.sharkicon-bed::before{content:""}.sharkicon-viacoin::before{content:""}.sharkicon-train::before{content:""}.sharkicon-subway::before{content:""}.sharkicon-medium::before{content:""}.sharkicon-y-combinator::before{content:""}.sharkicon-optin-monster::before{content:""}.sharkicon-opencart::before{content:""}.sharkicon-expeditedssl::before{content:""}.sharkicon-battery-4::before{content:""}.sharkicon-battery-3::before{content:""}.sharkicon-battery-2::before{content:""}.sharkicon-battery-1::before{content:""}.sharkicon-battery-0::before{content:""}.sharkicon-mouse-pointer::before{content:""}.sharkicon-i-cursor::before{content:""}.sharkicon-object-group::before{content:""}.sharkicon-object-ungroup::before{content:""}.sharkicon-sticky-note::before{content:""}.sharkicon-sticky-note-o::before{content:""}.sharkicon-cc-jcb::before{content:""}.sharkicon-cc-diners-club::before{content:""}.sharkicon-clone::before{content:""}.sharkicon-balance-scale::before{content:""}.sharkicon-hourglass-o::before{content:""}.sharkicon-hourglass-1::before{content:""}.sharkicon-hourglass-2::before{content:""}.sharkicon-hourglass-3::before{content:""}.sharkicon-hourglass::before{content:""}.sharkicon-hand-grab-o::before{content:""}.sharkicon-hand-paper-o::before{content:""}.sharkicon-hand-scissors-o::before{content:""}.sharkicon-hand-lizard-o::before{content:""}.sharkicon-hand-spock-o::before{content:""}.sharkicon-hand-pointer-o::before{content:""}.sharkicon-hand-peace-o::before{content:""}.sharkicon-trademark::before{content:""}.sharkicon-registered::before{content:""}.sharkicon-creative-commons::before{content:""}.sharkicon-gg::before{content:""}.sharkicon-gg-circle::before{content:""}.sharkicon-tripadvisor::before{content:""}.sharkicon-odnoklassniki::before{content:""}.sharkicon-odnoklassniki-square::before{content:""}.sharkicon-get-pocket::before{content:""}.sharkicon-wikipedia-w::before{content:""}.sharkicon-safari::before{content:""}.sharkicon-chrome::before{content:""}.sharkicon-firefox::before{content:""}.sharkicon-opera::before{content:""}.sharkicon-internet-explorer::before{content:""}.sharkicon-television::before{content:""}.sharkicon-contao::before{content:""}.sharkicon-500px::before{content:""}.sharkicon-amazon::before{content:""}.sharkicon-calendar-plus-o::before{content:""}.sharkicon-calendar-minus-o::before{content:""}.sharkicon-calendar-times-o::before{content:""}.sharkicon-calendar-check-o::before{content:""}.sharkicon-industry::before{content:""}.sharkicon-map-pin::before{content:""}.sharkicon-map-signs::before{content:""}.sharkicon-map-o::before{content:""}.sharkicon-map::before{content:""}.sharkicon-commenting::before{content:""}.sharkicon-commenting-o::before{content:""}.sharkicon-houzz::before{content:""}.sharkicon-vimeo::before{content:""}.sharkicon-black-tie::before{content:""}.sharkicon-fonticons::before{content:""}.sharkicon-lg{font-size:1.33333333em;line-height:0.75em;vertical-align:-15%}.sharkicon-2x{font-size:2em}.sharkicon-3x{font-size:3em}.sharkicon-4x{font-size:4em}.sharkicon-5x{font-size:5em}.sharkicon-fw{text-align:center;width:1.28571429em}.sharkicon-border{border-radius:.1em;padding:.2em .25em .15em;border:solid 0.08em}.sharkicon-pull-left{float:left;margin-right:.3em}.sharkicon-pull-right{float:right;margin-left:.3em}.sharkicon-rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.sharkicon-rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.sharkicon-rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.sharkicon-flip-horizontal{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.sharkicon-flip-vertical{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.sharkicon-inverse{-webkit-filter:invert(100%);filter:invert(100%)}.sharkicon-spin{-webkit-animation:sharkicon-animation-spin 2s infinite linear;-moz-animation:sharkicon-animation-spin 2s infinite linear;animation:sharkicon-animation-spin 2s infinite linear}.sharkicon-pulse{-webkit-animation:sharkicon-animation-spin 1s infinite steps(8);-moz-animation:sharkicon-animation-spin 1s infinite steps(8);animation:sharkicon-animation-spin 1s infinite steps(8)}.sharkicon-ul{padding-left:0;list-style-type:none;margin-left:2.14285714em}.sharkicon-ul>li{position:relative}.sharkicon-ul>li .sharkicon-li{text-align:center;position:absolute;left:-2.14285714em;width:2.14285714em;top:0.14285714em}.sharkicon-ul>li .sharkicon-li .sharkicon-lg{left:-1.85714286em}.sharkicon-stack{width:2em;height:2em;line-height:2em;vertical-align:middle;position:relative;display:inline-block}.sharkicon-stack .sharkicon-stack-1x,.sharkicon-stack .sharkicon-stack-2x{left:0;width:100%;text-align:center;position:absolute}.sharkicon-stack .sharkicon-stack-1x{line-height:inherit}.sharkicon-stack .sharkicon-stack-2x{font-size:2em}@-webkit-keyframes sharkicon-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-moz-keyframes sharkicon-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@keyframes sharkicon-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}
|
2 |
|
3 |
-
/*# sourceMappingURL=long-classes.min.css.map */
|
1 |
@font-face{font-family:sharkicons;src:url("fonts/sharkicons.eot?v160221");src:url("fonts/sharkicons.eot?#iefix&v160221") format("embedded-opentype"),url("fonts/sharkicons.ttf?v160221") format("truetype"),url("fonts/sharkicons.woff?v160221") format("woff"),url("fonts/sharkicons.svg?v160221#sharkicons") format("svg");font-weight:normal;font-style:normal}.sharkicon::before{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none}.sharkicon-broom::before{content:""}.sharkicon-comment-mail-one::before{content:""}.sharkicon-comment-mail::before{content:""}.sharkicon-s2member::before{content:""}.sharkicon-websharks::before{content:""}.sharkicon-wp-kb-articles::before{content:""}.sharkicon-zencache-logo::before{content:""}.sharkicon-zencache::before{content:""}.sharkicon-wp-sharks::before{content:""}.sharkicon-wp-sharks-fin::before{content:""}.sharkicon-comet-cache::before{content:""}.sharkicon-comet-cache-logo::before{content:""}.sharkicon-comet-cache-comet::before{content:""}.sharkicon-feat-watch::before{content:""}.sharkicon-feat-server::before{content:""}.sharkicon-feat-layers::before{content:""}.sharkicon-feat-box::before{content:""}.sharkicon-feat-ellipsis::before{content:""}.sharkicon-typi-group::before{content:""}.sharkicon-enty-bookmark::before{content:""}.sharkicon-enty-bookmarks::before{content:""}.sharkicon-enty-open-book::before{content:""}.sharkicon-enty-archive::before{content:""}.sharkicon-enty-area-graph::before{content:""}.sharkicon-enty-bucket::before{content:""}.sharkicon-enty-colors::before{content:""}.sharkicon-enty-copy::before{content:""}.sharkicon-enty-drive::before{content:""}.sharkicon-enty-feather::before{content:""}.sharkicon-enty-gauge::before{content:""}.sharkicon-enty-hand::before{content:""}.sharkicon-enty-lab-flask::before{content:""}.sharkicon-enty-mask::before{content:""}.sharkicon-enty-medal::before{content:""}.sharkicon-enty-exclamation::before{content:""}.sharkicon-enty-palette::before{content:""}.sharkicon-enty-ruler::before{content:""}.sharkicon-enty-shop::before{content:""}.sharkicon-enty-basket::before{content:""}.sharkicon-enty-cart::before{content:""}.sharkicon-enty-traffic-cone::before{content:""}.sharkicon-enty-tree::before{content:""}.sharkicon-enty-trophy::before{content:""}.sharkicon-enty-v-card::before{content:""}.sharkicon-enty-google-hangouts::before{content:""}.sharkicon-eleg-line-graph::before{content:""}.sharkicon-eleg-male::before{content:""}.sharkicon-eleg-female::before{content:""}.sharkicon-eleg-atom::before{content:""}.sharkicon-broc-cart::before{content:""}.sharkicon-broc-crap::before{content:""}.sharkicon-broc-atom::before{content:""}.sharkicon-icom-headphones::before{content:""}.sharkicon-icom-barcode::before{content:""}.sharkicon-icom-user::before{content:""}.sharkicon-icom-users::before{content:""}.sharkicon-icom-user-plus::before{content:""}.sharkicon-icom-user-minus::before{content:""}.sharkicon-icom-user-check::before{content:""}.sharkicon-icom-user-tie::before{content:""}.sharkicon-icom-key::before{content:""}.sharkicon-icom-key2::before{content:""}.sharkicon-icom-happy::before{content:""}.sharkicon-icom-happy2::before{content:""}.sharkicon-icom-smile::before{content:""}.sharkicon-icom-smile2::before{content:""}.sharkicon-icom-tongue::before{content:""}.sharkicon-icom-tongue2::before{content:""}.sharkicon-icom-sad::before{content:""}.sharkicon-icom-sad2::before{content:""}.sharkicon-icom-wink::before{content:""}.sharkicon-icom-wink2::before{content:""}.sharkicon-icom-grin::before{content:""}.sharkicon-icom-grin2::before{content:""}.sharkicon-icom-cool::before{content:""}.sharkicon-icom-cool2::before{content:""}.sharkicon-icom-angry::before{content:""}.sharkicon-icom-angry2::before{content:""}.sharkicon-icom-evil::before{content:""}.sharkicon-icom-evil2::before{content:""}.sharkicon-icom-shocked::before{content:""}.sharkicon-icom-shocked2::before{content:""}.sharkicon-icom-baffled::before{content:""}.sharkicon-icom-baffled2::before{content:""}.sharkicon-icom-confused::before{content:""}.sharkicon-icom-confused2::before{content:""}.sharkicon-icom-neutral::before{content:""}.sharkicon-icom-neutral2::before{content:""}.sharkicon-icom-hipster::before{content:""}.sharkicon-icom-hipster2::before{content:""}.sharkicon-icom-wondering::before{content:""}.sharkicon-icom-wondering2::before{content:""}.sharkicon-icom-sleepy::before{content:""}.sharkicon-icom-sleepy2::before{content:""}.sharkicon-icom-frustrated::before{content:""}.sharkicon-icom-frustrated2::before{content:""}.sharkicon-icom-crying::before{content:""}.sharkicon-icom-crying2::before{content:""}.sharkicon-icom-spell-check::before{content:""}.sharkicon-icom-command-key::before{content:""}.sharkicon-icom-shift-key::before{content:""}.sharkicon-icom-control-key::before{content:""}.sharkicon-icom-option-key::before{content:""}.sharkicon-icom-wordpress::before{content:""}.sharkicon-icom-wordpress-square::before{content:""}.sharkicon-icom-yahoo::before{content:""}.sharkicon-icom-linux::before{content:""}.sharkicon-icom-finder::before{content:""}.sharkicon-icom-android::before{content:""}.sharkicon-icom-reddit::before{content:""}.sharkicon-icom-paypal::before{content:""}.sharkicon-icom-git::before{content:""}.sharkicon-octi-alignment-align::before{content:""}.sharkicon-octi-alignment-aligned-to::before{content:""}.sharkicon-octi-alignment-unalign::before{content:""}.sharkicon-octi-bookmark::before{content:""}.sharkicon-octi-broadcast::before{content:""}.sharkicon-octi-browser::before{content:""}.sharkicon-octi-checklist::before{content:""}.sharkicon-octi-circuit-board::before{content:""}.sharkicon-octi-clippy::before{content:""}.sharkicon-octi-cloud-download::before{content:""}.sharkicon-octi-cloud-upload::before{content:""}.sharkicon-octi-comment::before{content:""}.sharkicon-octi-comments::before{content:""}.sharkicon-octi-tach::before{content:""}.sharkicon-octi-device-camera::before{content:""}.sharkicon-octi-device-camera-video::before{content:""}.sharkicon-octi-device-desktop::before{content:""}.sharkicon-octi-diff::before{content:""}.sharkicon-octi-file-binary::before{content:""}.sharkicon-octi-file-media::before{content:""}.sharkicon-octi-file-submodule::before{content:""}.sharkicon-octi-file-symlink-directory::before{content:""}.sharkicon-octi-file-symlink-file::before{content:""}.sharkicon-octi-fold::before{content:""}.sharkicon-octi-git-branch::before{content:""}.sharkicon-octi-git-commit::before{content:""}.sharkicon-octi-git-compare::before{content:""}.sharkicon-octi-git-merge::before{content:""}.sharkicon-octi-git-pull-request::before{content:""}.sharkicon-octi-graph::before{content:""}.sharkicon-octi-home::before{content:""}.sharkicon-octi-horizontal-rule::before{content:""}.sharkicon-octi-key::before{content:""}.sharkicon-octi-light-bulb::before{content:""}.sharkicon-octi-link-external::before{content:""}.sharkicon-octi-lock::before{content:""}.sharkicon-octi-markdown::before{content:""}.sharkicon-octi-microscope::before{content:""}.sharkicon-octi-mirror::before{content:""}.sharkicon-octi-move-down::before{content:""}.sharkicon-octi-move-left::before{content:""}.sharkicon-octi-move-right::before{content:""}.sharkicon-octi-move-up::before{content:""}.sharkicon-octi-mute::before{content:""}.sharkicon-octi-organization::before{content:""}.sharkicon-octi-package::before{content:""}.sharkicon-octi-paintcan::before{content:""}.sharkicon-octi-person::before{content:""}.sharkicon-octi-plug::before{content:""}.sharkicon-octi-podium::before{content:""}.sharkicon-octi-pulse::before{content:""}.sharkicon-octi-puzzle::before{content:""}.sharkicon-octi-repo::before{content:""}.sharkicon-octi-repo-clone::before{content:""}.sharkicon-octi-repo-force-push::before{content:""}.sharkicon-octi-repo-forked::before{content:""}.sharkicon-octi-repo-pull::before{content:""}.sharkicon-octi-repo-push::before{content:""}.sharkicon-octi-rocket::before{content:""}.sharkicon-octi-ruby::before{content:""}.sharkicon-octi-screen-full::before{content:""}.sharkicon-octi-screen-normal::before{content:""}.sharkicon-octi-sign-in::before{content:""}.sharkicon-octi-sign-out::before{content:""}.sharkicon-octi-split::before{content:""}.sharkicon-octi-squirrel::before{content:""}.sharkicon-octi-steps::before{content:""}.sharkicon-octi-tag::before{content:""}.sharkicon-octi-telescope::before{content:""}.sharkicon-octi-terminal::before{content:""}.sharkicon-octi-unfold::before{content:""}.sharkicon-octi-versions::before{content:""}.sharkicon-glass::before{content:""}.sharkicon-music::before{content:""}.sharkicon-search::before{content:""}.sharkicon-envelope-o::before{content:""}.sharkicon-heart::before{content:""}.sharkicon-star::before{content:""}.sharkicon-star-o::before{content:""}.sharkicon-user::before{content:""}.sharkicon-film::before{content:""}.sharkicon-th-large::before{content:""}.sharkicon-th::before{content:""}.sharkicon-th-list::before{content:""}.sharkicon-check::before{content:""}.sharkicon-close::before{content:""}.sharkicon-search-plus::before{content:""}.sharkicon-search-minus::before{content:""}.sharkicon-power-off::before{content:""}.sharkicon-signal::before{content:""}.sharkicon-cog::before{content:""}.sharkicon-trash-o::before{content:""}.sharkicon-home::before{content:""}.sharkicon-file-o::before{content:""}.sharkicon-clock-o::before{content:""}.sharkicon-road::before{content:""}.sharkicon-download::before{content:""}.sharkicon-arrow-circle-o-down::before{content:""}.sharkicon-arrow-circle-o-up::before{content:""}.sharkicon-inbox::before{content:""}.sharkicon-play-circle-o::before{content:""}.sharkicon-repeat::before{content:""}.sharkicon-refresh::before{content:""}.sharkicon-list-alt::before{content:""}.sharkicon-lock::before{content:""}.sharkicon-flag::before{content:""}.sharkicon-headphones::before{content:""}.sharkicon-volume-off::before{content:""}.sharkicon-volume-down::before{content:""}.sharkicon-volume-up::before{content:""}.sharkicon-qrcode::before{content:""}.sharkicon-barcode::before{content:""}.sharkicon-tag::before{content:""}.sharkicon-tags::before{content:""}.sharkicon-book::before{content:""}.sharkicon-bookmark::before{content:""}.sharkicon-print::before{content:""}.sharkicon-camera::before{content:""}.sharkicon-font::before{content:""}.sharkicon-bold::before{content:""}.sharkicon-italic::before{content:""}.sharkicon-text-height::before{content:""}.sharkicon-text-width::before{content:""}.sharkicon-align-left::before{content:""}.sharkicon-align-center::before{content:""}.sharkicon-align-right::before{content:""}.sharkicon-align-justify::before{content:""}.sharkicon-list::before{content:""}.sharkicon-dedent::before{content:""}.sharkicon-indent::before{content:""}.sharkicon-video-camera::before{content:""}.sharkicon-image::before{content:""}.sharkicon-pencil::before{content:""}.sharkicon-map-marker::before{content:""}.sharkicon-adjust::before{content:""}.sharkicon-tint::before{content:""}.sharkicon-edit::before{content:""}.sharkicon-share-square-o::before{content:""}.sharkicon-check-square-o::before{content:""}.sharkicon-arrows::before{content:""}.sharkicon-step-backward::before{content:""}.sharkicon-fast-backward::before{content:""}.sharkicon-backward::before{content:""}.sharkicon-play::before{content:""}.sharkicon-pause::before{content:""}.sharkicon-stop::before{content:""}.sharkicon-forward::before{content:""}.sharkicon-fast-forward::before{content:""}.sharkicon-step-forward::before{content:""}.sharkicon-eject::before{content:""}.sharkicon-chevron-left::before{content:""}.sharkicon-chevron-right::before{content:""}.sharkicon-plus-circle::before{content:""}.sharkicon-minus-circle::before{content:""}.sharkicon-times-circle::before{content:""}.sharkicon-check-circle::before{content:""}.sharkicon-question-circle::before{content:""}.sharkicon-info-circle::before{content:""}.sharkicon-crosshairs::before{content:""}.sharkicon-times-circle-o::before{content:""}.sharkicon-check-circle-o::before{content:""}.sharkicon-ban::before{content:""}.sharkicon-arrow-left::before{content:""}.sharkicon-arrow-right::before{content:""}.sharkicon-arrow-up::before{content:""}.sharkicon-arrow-down::before{content:""}.sharkicon-mail-forward::before{content:""}.sharkicon-expand::before{content:""}.sharkicon-compress::before{content:""}.sharkicon-plus::before{content:""}.sharkicon-minus::before{content:""}.sharkicon-asterisk::before{content:""}.sharkicon-exclamation-circle::before{content:""}.sharkicon-gift::before{content:""}.sharkicon-leaf::before{content:""}.sharkicon-fire::before{content:""}.sharkicon-eye::before{content:""}.sharkicon-eye-slash::before{content:""}.sharkicon-exclamation-triangle::before{content:""}.sharkicon-plane::before{content:""}.sharkicon-calendar::before{content:""}.sharkicon-random::before{content:""}.sharkicon-comment::before{content:""}.sharkicon-magnet::before{content:""}.sharkicon-chevron-up::before{content:""}.sharkicon-chevron-down::before{content:""}.sharkicon-retweet::before{content:""}.sharkicon-shopping-cart::before{content:""}.sharkicon-folder::before{content:""}.sharkicon-folder-open::before{content:""}.sharkicon-arrows-v::before{content:""}.sharkicon-arrows-h::before{content:""}.sharkicon-bar-chart::before{content:""}.sharkicon-twitter-square::before{content:""}.sharkicon-facebook-square::before{content:""}.sharkicon-camera-retro::before{content:""}.sharkicon-key::before{content:""}.sharkicon-cogs::before{content:""}.sharkicon-comments::before{content:""}.sharkicon-thumbs-o-up::before{content:""}.sharkicon-thumbs-o-down::before{content:""}.sharkicon-star-half::before{content:""}.sharkicon-heart-o::before{content:""}.sharkicon-sign-out::before{content:""}.sharkicon-linkedin-square::before{content:""}.sharkicon-thumb-tack::before{content:""}.sharkicon-external-link::before{content:""}.sharkicon-sign-in::before{content:""}.sharkicon-trophy::before{content:""}.sharkicon-github-square::before{content:""}.sharkicon-upload::before{content:""}.sharkicon-lemon-o::before{content:""}.sharkicon-phone::before{content:""}.sharkicon-square-o::before{content:""}.sharkicon-bookmark-o::before{content:""}.sharkicon-phone-square::before{content:""}.sharkicon-twitter::before{content:""}.sharkicon-facebook::before{content:""}.sharkicon-github::before{content:""}.sharkicon-unlock::before{content:""}.sharkicon-credit-card::before{content:""}.sharkicon-feed::before{content:""}.sharkicon-hdd-o::before{content:""}.sharkicon-bullhorn::before{content:""}.sharkicon-bell-o::before{content:""}.sharkicon-certificate::before{content:""}.sharkicon-hand-o-right::before{content:""}.sharkicon-hand-o-left::before{content:""}.sharkicon-hand-o-up::before{content:""}.sharkicon-hand-o-down::before{content:""}.sharkicon-arrow-circle-left::before{content:""}.sharkicon-arrow-circle-right::before{content:""}.sharkicon-arrow-circle-up::before{content:""}.sharkicon-arrow-circle-down::before{content:""}.sharkicon-globe::before{content:""}.sharkicon-wrench::before{content:""}.sharkicon-tasks::before{content:""}.sharkicon-filter::before{content:""}.sharkicon-briefcase::before{content:""}.sharkicon-arrows-alt::before{content:""}.sharkicon-group::before{content:""}.sharkicon-chain::before{content:""}.sharkicon-cloud::before{content:""}.sharkicon-flask::before{content:""}.sharkicon-cut::before{content:""}.sharkicon-copy::before{content:""}.sharkicon-paperclip::before{content:""}.sharkicon-floppy-o::before{content:""}.sharkicon-square::before{content:""}.sharkicon-bars::before{content:""}.sharkicon-list-ul::before{content:""}.sharkicon-list-ol::before{content:""}.sharkicon-strikethrough::before{content:""}.sharkicon-underline::before{content:""}.sharkicon-table::before{content:""}.sharkicon-magic::before{content:""}.sharkicon-truck::before{content:""}.sharkicon-pinterest::before{content:""}.sharkicon-pinterest-square::before{content:""}.sharkicon-google-plus-square::before{content:""}.sharkicon-google-plus::before{content:""}.sharkicon-money::before{content:""}.sharkicon-caret-down::before{content:""}.sharkicon-caret-up::before{content:""}.sharkicon-caret-left::before{content:""}.sharkicon-caret-right::before{content:""}.sharkicon-columns::before{content:""}.sharkicon-sort::before{content:""}.sharkicon-sort-desc::before{content:""}.sharkicon-sort-asc::before{content:""}.sharkicon-envelope::before{content:""}.sharkicon-linkedin::before{content:""}.sharkicon-rotate-left::before{content:""}.sharkicon-gavel::before{content:""}.sharkicon-dashboard::before{content:""}.sharkicon-comment-o::before{content:""}.sharkicon-comments-o::before{content:""}.sharkicon-bolt::before{content:""}.sharkicon-sitemap::before{content:""}.sharkicon-umbrella::before{content:""}.sharkicon-clipboard::before{content:""}.sharkicon-lightbulb-o::before{content:""}.sharkicon-exchange::before{content:""}.sharkicon-cloud-download::before{content:""}.sharkicon-cloud-upload::before{content:""}.sharkicon-user-md::before{content:""}.sharkicon-stethoscope::before{content:""}.sharkicon-suitcase::before{content:""}.sharkicon-bell::before{content:""}.sharkicon-coffee::before{content:""}.sharkicon-cutlery::before{content:""}.sharkicon-file-text-o::before{content:""}.sharkicon-building-o::before{content:""}.sharkicon-hospital-o::before{content:""}.sharkicon-ambulance::before{content:""}.sharkicon-medkit::before{content:""}.sharkicon-fighter-jet::before{content:""}.sharkicon-beer::before{content:""}.sharkicon-h-square::before{content:""}.sharkicon-plus-square::before{content:""}.sharkicon-angle-double-left::before{content:""}.sharkicon-angle-double-right::before{content:""}.sharkicon-angle-double-up::before{content:""}.sharkicon-angle-double-down::before{content:""}.sharkicon-angle-left::before{content:""}.sharkicon-angle-right::before{content:""}.sharkicon-angle-up::before{content:""}.sharkicon-angle-down::before{content:""}.sharkicon-desktop::before{content:""}.sharkicon-laptop::before{content:""}.sharkicon-tablet::before{content:""}.sharkicon-mobile::before{content:""}.sharkicon-circle-o::before{content:""}.sharkicon-quote-left::before{content:""}.sharkicon-quote-right::before{content:""}.sharkicon-spinner::before{content:""}.sharkicon-circle::before{content:""}.sharkicon-mail-reply::before{content:""}.sharkicon-github-alt::before{content:""}.sharkicon-folder-o::before{content:""}.sharkicon-folder-open-o::before{content:""}.sharkicon-smile-o::before{content:""}.sharkicon-frown-o::before{content:""}.sharkicon-meh-o::before{content:""}.sharkicon-gamepad::before{content:""}.sharkicon-keyboard-o::before{content:""}.sharkicon-flag-o::before{content:""}.sharkicon-flag-checkered::before{content:""}.sharkicon-terminal::before{content:""}.sharkicon-code::before{content:""}.sharkicon-mail-reply-all::before{content:""}.sharkicon-star-half-empty::before{content:""}.sharkicon-location-arrow::before{content:""}.sharkicon-crop::before{content:""}.sharkicon-code-fork::before{content:""}.sharkicon-chain-broken::before{content:""}.sharkicon-question::before{content:""}.sharkicon-info::before{content:""}.sharkicon-exclamation::before{content:""}.sharkicon-superscript::before{content:""}.sharkicon-subscript::before{content:""}.sharkicon-eraser::before{content:""}.sharkicon-puzzle-piece::before{content:""}.sharkicon-microphone::before{content:""}.sharkicon-microphone-slash::before{content:""}.sharkicon-shield::before{content:""}.sharkicon-calendar-o::before{content:""}.sharkicon-fire-extinguisher::before{content:""}.sharkicon-rocket::before{content:""}.sharkicon-maxcdn::before{content:""}.sharkicon-chevron-circle-left::before{content:""}.sharkicon-chevron-circle-right::before{content:""}.sharkicon-chevron-circle-up::before{content:""}.sharkicon-chevron-circle-down::before{content:""}.sharkicon-html5::before{content:""}.sharkicon-css3::before{content:""}.sharkicon-anchor::before{content:""}.sharkicon-unlock-alt::before{content:""}.sharkicon-bullseye::before{content:""}.sharkicon-ellipsis-h::before{content:""}.sharkicon-ellipsis-v::before{content:""}.sharkicon-rss-square::before{content:""}.sharkicon-play-circle::before{content:""}.sharkicon-ticket::before{content:""}.sharkicon-minus-square::before{content:""}.sharkicon-minus-square-o::before{content:""}.sharkicon-level-up::before{content:""}.sharkicon-level-down::before{content:""}.sharkicon-check-square::before{content:""}.sharkicon-pencil-square::before{content:""}.sharkicon-external-link-square::before{content:""}.sharkicon-share-square::before{content:""}.sharkicon-compass::before{content:""}.sharkicon-caret-square-o-down::before{content:""}.sharkicon-caret-square-o-up::before{content:""}.sharkicon-caret-square-o-right::before{content:""}.sharkicon-eur::before{content:""}.sharkicon-gbp::before{content:""}.sharkicon-dollar::before{content:""}.sharkicon-inr::before{content:""}.sharkicon-cny::before{content:""}.sharkicon-rouble::before{content:""}.sharkicon-krw::before{content:""}.sharkicon-bitcoin::before{content:""}.sharkicon-file::before{content:""}.sharkicon-file-text::before{content:""}.sharkicon-sort-alpha-asc::before{content:""}.sharkicon-sort-alpha-desc::before{content:""}.sharkicon-sort-amount-asc::before{content:""}.sharkicon-sort-amount-desc::before{content:""}.sharkicon-sort-numeric-asc::before{content:""}.sharkicon-sort-numeric-desc::before{content:""}.sharkicon-thumbs-up::before{content:""}.sharkicon-thumbs-down::before{content:""}.sharkicon-youtube-square::before{content:""}.sharkicon-youtube::before{content:""}.sharkicon-xing::before{content:""}.sharkicon-xing-square::before{content:""}.sharkicon-youtube-play::before{content:""}.sharkicon-dropbox::before{content:""}.sharkicon-stack-overflow::before{content:""}.sharkicon-instagram::before{content:""}.sharkicon-flickr::before{content:""}.sharkicon-adn::before{content:""}.sharkicon-bitbucket::before{content:""}.sharkicon-bitbucket-square::before{content:""}.sharkicon-tumblr::before{content:""}.sharkicon-tumblr-square::before{content:""}.sharkicon-long-arrow-down::before{content:""}.sharkicon-long-arrow-up::before{content:""}.sharkicon-long-arrow-left::before{content:""}.sharkicon-long-arrow-right::before{content:""}.sharkicon-apple::before{content:""}.sharkicon-windows::before{content:""}.sharkicon-android::before{content:""}.sharkicon-linux::before{content:""}.sharkicon-dribbble::before{content:""}.sharkicon-skype::before{content:""}.sharkicon-foursquare::before{content:""}.sharkicon-trello::before{content:""}.sharkicon-female::before{content:""}.sharkicon-male::before{content:""}.sharkicon-gittip::before{content:""}.sharkicon-sun-o::before{content:""}.sharkicon-moon-o::before{content:""}.sharkicon-archive::before{content:""}.sharkicon-bug::before{content:""}.sharkicon-vk::before{content:""}.sharkicon-weibo::before{content:""}.sharkicon-renren::before{content:""}.sharkicon-pagelines::before{content:""}.sharkicon-stack-exchange::before{content:""}.sharkicon-arrow-circle-o-right::before{content:""}.sharkicon-arrow-circle-o-left::before{content:""}.sharkicon-caret-square-o-left::before{content:""}.sharkicon-dot-circle-o::before{content:""}.sharkicon-wheelchair::before{content:""}.sharkicon-vimeo-square::before{content:""}.sharkicon-try::before{content:""}.sharkicon-plus-square-o::before{content:""}.sharkicon-space-shuttle::before{content:""}.sharkicon-slack::before{content:""}.sharkicon-envelope-square::before{content:""}.sharkicon-wordpress::before{content:""}.sharkicon-openid::before{content:""}.sharkicon-bank::before{content:""}.sharkicon-graduation-cap::before{content:""}.sharkicon-yahoo::before{content:""}.sharkicon-google::before{content:""}.sharkicon-reddit::before{content:""}.sharkicon-reddit-square::before{content:""}.sharkicon-stumbleupon-circle::before{content:""}.sharkicon-stumbleupon::before{content:""}.sharkicon-delicious::before{content:""}.sharkicon-digg::before{content:""}.sharkicon-pied-piper::before{content:""}.sharkicon-pied-piper-alt::before{content:""}.sharkicon-drupal::before{content:""}.sharkicon-joomla::before{content:""}.sharkicon-language::before{content:""}.sharkicon-fax::before{content:""}.sharkicon-building::before{content:""}.sharkicon-child::before{content:""}.sharkicon-paw::before{content:""}.sharkicon-spoon::before{content:""}.sharkicon-cube::before{content:""}.sharkicon-cubes::before{content:""}.sharkicon-behance::before{content:""}.sharkicon-behance-square::before{content:""}.sharkicon-steam::before{content:""}.sharkicon-steam-square::before{content:""}.sharkicon-recycle::before{content:""}.sharkicon-automobile::before{content:""}.sharkicon-cab::before{content:""}.sharkicon-tree::before{content:""}.sharkicon-spotify::before{content:""}.sharkicon-deviantart::before{content:""}.sharkicon-soundcloud::before{content:""}.sharkicon-database::before{content:""}.sharkicon-file-pdf-o::before{content:""}.sharkicon-file-word-o::before{content:""}.sharkicon-file-excel-o::before{content:""}.sharkicon-file-powerpoint-o::before{content:""}.sharkicon-file-image-o::before{content:""}.sharkicon-file-archive-o::before{content:""}.sharkicon-file-audio-o::before{content:""}.sharkicon-file-movie-o::before{content:""}.sharkicon-file-code-o::before{content:""}.sharkicon-vine::before{content:""}.sharkicon-codepen::before{content:""}.sharkicon-jsfiddle::before{content:""}.sharkicon-life-bouy::before{content:""}.sharkicon-circle-o-notch::before{content:""}.sharkicon-ra::before{content:""}.sharkicon-empire::before{content:""}.sharkicon-git-square::before{content:""}.sharkicon-git::before{content:""}.sharkicon-hacker-news::before{content:""}.sharkicon-tencent-weibo::before{content:""}.sharkicon-qq::before{content:""}.sharkicon-wechat::before{content:""}.sharkicon-paper-plane::before{content:""}.sharkicon-paper-plane-o::before{content:""}.sharkicon-history::before{content:""}.sharkicon-circle-thin::before{content:""}.sharkicon-header::before{content:""}.sharkicon-paragraph::before{content:""}.sharkicon-sliders::before{content:""}.sharkicon-share-alt::before{content:""}.sharkicon-share-alt-square::before{content:""}.sharkicon-bomb::before{content:""}.sharkicon-futbol-o::before{content:""}.sharkicon-tty::before{content:""}.sharkicon-binoculars::before{content:""}.sharkicon-plug::before{content:""}.sharkicon-slideshare::before{content:""}.sharkicon-twitch::before{content:""}.sharkicon-yelp::before{content:""}.sharkicon-newspaper-o::before{content:""}.sharkicon-wifi::before{content:""}.sharkicon-calculator::before{content:""}.sharkicon-paypal::before{content:""}.sharkicon-google-wallet::before{content:""}.sharkicon-cc-visa::before{content:""}.sharkicon-cc-mastercard::before{content:""}.sharkicon-cc-discover::before{content:""}.sharkicon-cc-amex::before{content:""}.sharkicon-cc-paypal::before{content:""}.sharkicon-cc-stripe::before{content:""}.sharkicon-bell-slash::before{content:""}.sharkicon-bell-slash-o::before{content:""}.sharkicon-trash::before{content:""}.sharkicon-copyright::before{content:""}.sharkicon-at::before{content:""}.sharkicon-eyedropper::before{content:""}.sharkicon-paint-brush::before{content:""}.sharkicon-birthday-cake::before{content:""}.sharkicon-area-chart::before{content:""}.sharkicon-pie-chart::before{content:""}.sharkicon-line-chart::before{content:""}.sharkicon-lastfm::before{content:""}.sharkicon-lastfm-square::before{content:""}.sharkicon-toggle-off::before{content:""}.sharkicon-toggle-on::before{content:""}.sharkicon-bicycle::before{content:""}.sharkicon-bus::before{content:""}.sharkicon-ioxhost::before{content:""}.sharkicon-angellist::before{content:""}.sharkicon-cc::before{content:""}.sharkicon-ils::before{content:""}.sharkicon-meanpath::before{content:""}.sharkicon-buysellads::before{content:""}.sharkicon-connectdevelop::before{content:""}.sharkicon-dashcube::before{content:""}.sharkicon-forumbee::before{content:""}.sharkicon-leanpub::before{content:""}.sharkicon-sellsy::before{content:""}.sharkicon-shirtsinbulk::before{content:""}.sharkicon-simplybuilt::before{content:""}.sharkicon-skyatlas::before{content:""}.sharkicon-cart-plus::before{content:""}.sharkicon-cart-arrow-down::before{content:""}.sharkicon-diamond::before{content:""}.sharkicon-ship::before{content:""}.sharkicon-user-secret::before{content:""}.sharkicon-motorcycle::before{content:""}.sharkicon-street-view::before{content:""}.sharkicon-heartbeat::before{content:""}.sharkicon-venus::before{content:""}.sharkicon-mars::before{content:""}.sharkicon-mercury::before{content:""}.sharkicon-intersex::before{content:""}.sharkicon-transgender-alt::before{content:""}.sharkicon-venus-double::before{content:""}.sharkicon-mars-double::before{content:""}.sharkicon-venus-mars::before{content:""}.sharkicon-mars-stroke::before{content:""}.sharkicon-mars-stroke-v::before{content:""}.sharkicon-mars-stroke-h::before{content:""}.sharkicon-neuter::before{content:""}.sharkicon-genderless::before{content:""}.sharkicon-facebook-official::before{content:""}.sharkicon-pinterest-p::before{content:""}.sharkicon-whatsapp::before{content:""}.sharkicon-server::before{content:""}.sharkicon-user-plus::before{content:""}.sharkicon-user-times::before{content:""}.sharkicon-bed::before{content:""}.sharkicon-viacoin::before{content:""}.sharkicon-train::before{content:""}.sharkicon-subway::before{content:""}.sharkicon-medium::before{content:""}.sharkicon-y-combinator::before{content:""}.sharkicon-optin-monster::before{content:""}.sharkicon-opencart::before{content:""}.sharkicon-expeditedssl::before{content:""}.sharkicon-battery-4::before{content:""}.sharkicon-battery-3::before{content:""}.sharkicon-battery-2::before{content:""}.sharkicon-battery-1::before{content:""}.sharkicon-battery-0::before{content:""}.sharkicon-mouse-pointer::before{content:""}.sharkicon-i-cursor::before{content:""}.sharkicon-object-group::before{content:""}.sharkicon-object-ungroup::before{content:""}.sharkicon-sticky-note::before{content:""}.sharkicon-sticky-note-o::before{content:""}.sharkicon-cc-jcb::before{content:""}.sharkicon-cc-diners-club::before{content:""}.sharkicon-clone::before{content:""}.sharkicon-balance-scale::before{content:""}.sharkicon-hourglass-o::before{content:""}.sharkicon-hourglass-1::before{content:""}.sharkicon-hourglass-2::before{content:""}.sharkicon-hourglass-3::before{content:""}.sharkicon-hourglass::before{content:""}.sharkicon-hand-grab-o::before{content:""}.sharkicon-hand-paper-o::before{content:""}.sharkicon-hand-scissors-o::before{content:""}.sharkicon-hand-lizard-o::before{content:""}.sharkicon-hand-spock-o::before{content:""}.sharkicon-hand-pointer-o::before{content:""}.sharkicon-hand-peace-o::before{content:""}.sharkicon-trademark::before{content:""}.sharkicon-registered::before{content:""}.sharkicon-creative-commons::before{content:""}.sharkicon-gg::before{content:""}.sharkicon-gg-circle::before{content:""}.sharkicon-tripadvisor::before{content:""}.sharkicon-odnoklassniki::before{content:""}.sharkicon-odnoklassniki-square::before{content:""}.sharkicon-get-pocket::before{content:""}.sharkicon-wikipedia-w::before{content:""}.sharkicon-safari::before{content:""}.sharkicon-chrome::before{content:""}.sharkicon-firefox::before{content:""}.sharkicon-opera::before{content:""}.sharkicon-internet-explorer::before{content:""}.sharkicon-television::before{content:""}.sharkicon-contao::before{content:""}.sharkicon-500px::before{content:""}.sharkicon-amazon::before{content:""}.sharkicon-calendar-plus-o::before{content:""}.sharkicon-calendar-minus-o::before{content:""}.sharkicon-calendar-times-o::before{content:""}.sharkicon-calendar-check-o::before{content:""}.sharkicon-industry::before{content:""}.sharkicon-map-pin::before{content:""}.sharkicon-map-signs::before{content:""}.sharkicon-map-o::before{content:""}.sharkicon-map::before{content:""}.sharkicon-commenting::before{content:""}.sharkicon-commenting-o::before{content:""}.sharkicon-houzz::before{content:""}.sharkicon-vimeo::before{content:""}.sharkicon-black-tie::before{content:""}.sharkicon-fonticons::before{content:""}.sharkicon-lg{font-size:1.33333333em;line-height:0.75em;vertical-align:-15%}.sharkicon-2x{font-size:2em}.sharkicon-3x{font-size:3em}.sharkicon-4x{font-size:4em}.sharkicon-5x{font-size:5em}.sharkicon-fw{text-align:center;width:1.28571429em}.sharkicon-border{border-radius:.1em;padding:.2em .25em .15em;border:solid 0.08em}.sharkicon-pull-left{float:left;margin-right:.3em}.sharkicon-pull-right{float:right;margin-left:.3em}.sharkicon-rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.sharkicon-rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.sharkicon-rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.sharkicon-flip-horizontal{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.sharkicon-flip-vertical{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.sharkicon-inverse{-webkit-filter:invert(100%);filter:invert(100%)}.sharkicon-spin{-webkit-animation:sharkicon-animation-spin 2s infinite linear;-moz-animation:sharkicon-animation-spin 2s infinite linear;animation:sharkicon-animation-spin 2s infinite linear}.sharkicon-pulse{-webkit-animation:sharkicon-animation-spin 1s infinite steps(8);-moz-animation:sharkicon-animation-spin 1s infinite steps(8);animation:sharkicon-animation-spin 1s infinite steps(8)}.sharkicon-ul{padding-left:0;list-style-type:none;margin-left:2.14285714em}.sharkicon-ul>li{position:relative}.sharkicon-ul>li .sharkicon-li{text-align:center;position:absolute;left:-2.14285714em;width:2.14285714em;top:0.14285714em}.sharkicon-ul>li .sharkicon-li .sharkicon-lg{left:-1.85714286em}.sharkicon-stack{width:2em;height:2em;line-height:2em;vertical-align:middle;position:relative;display:inline-block}.sharkicon-stack .sharkicon-stack-1x,.sharkicon-stack .sharkicon-stack-2x{left:0;width:100%;text-align:center;position:absolute}.sharkicon-stack .sharkicon-stack-1x{line-height:inherit}.sharkicon-stack .sharkicon-stack-2x{font-size:2em}@-webkit-keyframes sharkicon-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-moz-keyframes sharkicon-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@keyframes sharkicon-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}
|
2 |
|
|
src/vendor/websharks/sharkicons/src/short-classes.min.css
CHANGED
@@ -1,3 +1,2 @@
|
|
1 |
@font-face{font-family:sharkicons;src:url("fonts/sharkicons.eot?v160221");src:url("fonts/sharkicons.eot?#iefix&v160221") format("embedded-opentype"),url("fonts/sharkicons.ttf?v160221") format("truetype"),url("fonts/sharkicons.woff?v160221") format("woff"),url("fonts/sharkicons.svg?v160221#sharkicons") format("svg");font-weight:normal;font-style:normal}.si::before{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none}.si-broom::before{content:""}.si-comment-mail-one::before{content:""}.si-comment-mail::before{content:""}.si-s2member::before{content:""}.si-websharks::before{content:""}.si-wp-kb-articles::before{content:""}.si-zencache-logo::before{content:""}.si-zencache::before{content:""}.si-wp-sharks::before{content:""}.si-wp-sharks-fin::before{content:""}.si-comet-cache::before{content:""}.si-comet-cache-logo::before{content:""}.si-comet-cache-comet::before{content:""}.si-feat-watch::before{content:""}.si-feat-server::before{content:""}.si-feat-layers::before{content:""}.si-feat-box::before{content:""}.si-feat-ellipsis::before{content:""}.si-typi-group::before{content:""}.si-enty-bookmark::before{content:""}.si-enty-bookmarks::before{content:""}.si-enty-open-book::before{content:""}.si-enty-archive::before{content:""}.si-enty-area-graph::before{content:""}.si-enty-bucket::before{content:""}.si-enty-colors::before{content:""}.si-enty-copy::before{content:""}.si-enty-drive::before{content:""}.si-enty-feather::before{content:""}.si-enty-gauge::before{content:""}.si-enty-hand::before{content:""}.si-enty-lab-flask::before{content:""}.si-enty-mask::before{content:""}.si-enty-medal::before{content:""}.si-enty-exclamation::before{content:""}.si-enty-palette::before{content:""}.si-enty-ruler::before{content:""}.si-enty-shop::before{content:""}.si-enty-basket::before{content:""}.si-enty-cart::before{content:""}.si-enty-traffic-cone::before{content:""}.si-enty-tree::before{content:""}.si-enty-trophy::before{content:""}.si-enty-v-card::before{content:""}.si-enty-google-hangouts::before{content:""}.si-eleg-line-graph::before{content:""}.si-eleg-male::before{content:""}.si-eleg-female::before{content:""}.si-eleg-atom::before{content:""}.si-broc-cart::before{content:""}.si-broc-crap::before{content:""}.si-broc-atom::before{content:""}.si-icom-headphones::before{content:""}.si-icom-barcode::before{content:""}.si-icom-user::before{content:""}.si-icom-users::before{content:""}.si-icom-user-plus::before{content:""}.si-icom-user-minus::before{content:""}.si-icom-user-check::before{content:""}.si-icom-user-tie::before{content:""}.si-icom-key::before{content:""}.si-icom-key2::before{content:""}.si-icom-happy::before{content:""}.si-icom-happy2::before{content:""}.si-icom-smile::before{content:""}.si-icom-smile2::before{content:""}.si-icom-tongue::before{content:""}.si-icom-tongue2::before{content:""}.si-icom-sad::before{content:""}.si-icom-sad2::before{content:""}.si-icom-wink::before{content:""}.si-icom-wink2::before{content:""}.si-icom-grin::before{content:""}.si-icom-grin2::before{content:""}.si-icom-cool::before{content:""}.si-icom-cool2::before{content:""}.si-icom-angry::before{content:""}.si-icom-angry2::before{content:""}.si-icom-evil::before{content:""}.si-icom-evil2::before{content:""}.si-icom-shocked::before{content:""}.si-icom-shocked2::before{content:""}.si-icom-baffled::before{content:""}.si-icom-baffled2::before{content:""}.si-icom-confused::before{content:""}.si-icom-confused2::before{content:""}.si-icom-neutral::before{content:""}.si-icom-neutral2::before{content:""}.si-icom-hipster::before{content:""}.si-icom-hipster2::before{content:""}.si-icom-wondering::before{content:""}.si-icom-wondering2::before{content:""}.si-icom-sleepy::before{content:""}.si-icom-sleepy2::before{content:""}.si-icom-frustrated::before{content:""}.si-icom-frustrated2::before{content:""}.si-icom-crying::before{content:""}.si-icom-crying2::before{content:""}.si-icom-spell-check::before{content:""}.si-icom-command-key::before{content:""}.si-icom-shift-key::before{content:""}.si-icom-control-key::before{content:""}.si-icom-option-key::before{content:""}.si-icom-wordpress::before{content:""}.si-icom-wordpress-square::before{content:""}.si-icom-yahoo::before{content:""}.si-icom-linux::before{content:""}.si-icom-finder::before{content:""}.si-icom-android::before{content:""}.si-icom-reddit::before{content:""}.si-icom-paypal::before{content:""}.si-icom-git::before{content:""}.si-octi-alignment-align::before{content:""}.si-octi-alignment-aligned-to::before{content:""}.si-octi-alignment-unalign::before{content:""}.si-octi-bookmark::before{content:""}.si-octi-broadcast::before{content:""}.si-octi-browser::before{content:""}.si-octi-checklist::before{content:""}.si-octi-circuit-board::before{content:""}.si-octi-clippy::before{content:""}.si-octi-cloud-download::before{content:""}.si-octi-cloud-upload::before{content:""}.si-octi-comment::before{content:""}.si-octi-comments::before{content:""}.si-octi-tach::before{content:""}.si-octi-device-camera::before{content:""}.si-octi-device-camera-video::before{content:""}.si-octi-device-desktop::before{content:""}.si-octi-diff::before{content:""}.si-octi-file-binary::before{content:""}.si-octi-file-media::before{content:""}.si-octi-file-submodule::before{content:""}.si-octi-file-symlink-directory::before{content:""}.si-octi-file-symlink-file::before{content:""}.si-octi-fold::before{content:""}.si-octi-git-branch::before{content:""}.si-octi-git-commit::before{content:""}.si-octi-git-compare::before{content:""}.si-octi-git-merge::before{content:""}.si-octi-git-pull-request::before{content:""}.si-octi-graph::before{content:""}.si-octi-home::before{content:""}.si-octi-horizontal-rule::before{content:""}.si-octi-key::before{content:""}.si-octi-light-bulb::before{content:""}.si-octi-link-external::before{content:""}.si-octi-lock::before{content:""}.si-octi-markdown::before{content:""}.si-octi-microscope::before{content:""}.si-octi-mirror::before{content:""}.si-octi-move-down::before{content:""}.si-octi-move-left::before{content:""}.si-octi-move-right::before{content:""}.si-octi-move-up::before{content:""}.si-octi-mute::before{content:""}.si-octi-organization::before{content:""}.si-octi-package::before{content:""}.si-octi-paintcan::before{content:""}.si-octi-person::before{content:""}.si-octi-plug::before{content:""}.si-octi-podium::before{content:""}.si-octi-pulse::before{content:""}.si-octi-puzzle::before{content:""}.si-octi-repo::before{content:""}.si-octi-repo-clone::before{content:""}.si-octi-repo-force-push::before{content:""}.si-octi-repo-forked::before{content:""}.si-octi-repo-pull::before{content:""}.si-octi-repo-push::before{content:""}.si-octi-rocket::before{content:""}.si-octi-ruby::before{content:""}.si-octi-screen-full::before{content:""}.si-octi-screen-normal::before{content:""}.si-octi-sign-in::before{content:""}.si-octi-sign-out::before{content:""}.si-octi-split::before{content:""}.si-octi-squirrel::before{content:""}.si-octi-steps::before{content:""}.si-octi-tag::before{content:""}.si-octi-telescope::before{content:""}.si-octi-terminal::before{content:""}.si-octi-unfold::before{content:""}.si-octi-versions::before{content:""}.si-glass::before{content:""}.si-music::before{content:""}.si-search::before{content:""}.si-envelope-o::before{content:""}.si-heart::before{content:""}.si-star::before{content:""}.si-star-o::before{content:""}.si-user::before{content:""}.si-film::before{content:""}.si-th-large::before{content:""}.si-th::before{content:""}.si-th-list::before{content:""}.si-check::before{content:""}.si-close::before{content:""}.si-search-plus::before{content:""}.si-search-minus::before{content:""}.si-power-off::before{content:""}.si-signal::before{content:""}.si-cog::before{content:""}.si-trash-o::before{content:""}.si-home::before{content:""}.si-file-o::before{content:""}.si-clock-o::before{content:""}.si-road::before{content:""}.si-download::before{content:""}.si-arrow-circle-o-down::before{content:""}.si-arrow-circle-o-up::before{content:""}.si-inbox::before{content:""}.si-play-circle-o::before{content:""}.si-repeat::before{content:""}.si-refresh::before{content:""}.si-list-alt::before{content:""}.si-lock::before{content:""}.si-flag::before{content:""}.si-headphones::before{content:""}.si-volume-off::before{content:""}.si-volume-down::before{content:""}.si-volume-up::before{content:""}.si-qrcode::before{content:""}.si-barcode::before{content:""}.si-tag::before{content:""}.si-tags::before{content:""}.si-book::before{content:""}.si-bookmark::before{content:""}.si-print::before{content:""}.si-camera::before{content:""}.si-font::before{content:""}.si-bold::before{content:""}.si-italic::before{content:""}.si-text-height::before{content:""}.si-text-width::before{content:""}.si-align-left::before{content:""}.si-align-center::before{content:""}.si-align-right::before{content:""}.si-align-justify::before{content:""}.si-list::before{content:""}.si-dedent::before{content:""}.si-indent::before{content:""}.si-video-camera::before{content:""}.si-image::before{content:""}.si-pencil::before{content:""}.si-map-marker::before{content:""}.si-adjust::before{content:""}.si-tint::before{content:""}.si-edit::before{content:""}.si-share-square-o::before{content:""}.si-check-square-o::before{content:""}.si-arrows::before{content:""}.si-step-backward::before{content:""}.si-fast-backward::before{content:""}.si-backward::before{content:""}.si-play::before{content:""}.si-pause::before{content:""}.si-stop::before{content:""}.si-forward::before{content:""}.si-fast-forward::before{content:""}.si-step-forward::before{content:""}.si-eject::before{content:""}.si-chevron-left::before{content:""}.si-chevron-right::before{content:""}.si-plus-circle::before{content:""}.si-minus-circle::before{content:""}.si-times-circle::before{content:""}.si-check-circle::before{content:""}.si-question-circle::before{content:""}.si-info-circle::before{content:""}.si-crosshairs::before{content:""}.si-times-circle-o::before{content:""}.si-check-circle-o::before{content:""}.si-ban::before{content:""}.si-arrow-left::before{content:""}.si-arrow-right::before{content:""}.si-arrow-up::before{content:""}.si-arrow-down::before{content:""}.si-mail-forward::before{content:""}.si-expand::before{content:""}.si-compress::before{content:""}.si-plus::before{content:""}.si-minus::before{content:""}.si-asterisk::before{content:""}.si-exclamation-circle::before{content:""}.si-gift::before{content:""}.si-leaf::before{content:""}.si-fire::before{content:""}.si-eye::before{content:""}.si-eye-slash::before{content:""}.si-exclamation-triangle::before{content:""}.si-plane::before{content:""}.si-calendar::before{content:""}.si-random::before{content:""}.si-comment::before{content:""}.si-magnet::before{content:""}.si-chevron-up::before{content:""}.si-chevron-down::before{content:""}.si-retweet::before{content:""}.si-shopping-cart::before{content:""}.si-folder::before{content:""}.si-folder-open::before{content:""}.si-arrows-v::before{content:""}.si-arrows-h::before{content:""}.si-bar-chart::before{content:""}.si-twitter-square::before{content:""}.si-facebook-square::before{content:""}.si-camera-retro::before{content:""}.si-key::before{content:""}.si-cogs::before{content:""}.si-comments::before{content:""}.si-thumbs-o-up::before{content:""}.si-thumbs-o-down::before{content:""}.si-star-half::before{content:""}.si-heart-o::before{content:""}.si-sign-out::before{content:""}.si-linkedin-square::before{content:""}.si-thumb-tack::before{content:""}.si-external-link::before{content:""}.si-sign-in::before{content:""}.si-trophy::before{content:""}.si-github-square::before{content:""}.si-upload::before{content:""}.si-lemon-o::before{content:""}.si-phone::before{content:""}.si-square-o::before{content:""}.si-bookmark-o::before{content:""}.si-phone-square::before{content:""}.si-twitter::before{content:""}.si-facebook::before{content:""}.si-github::before{content:""}.si-unlock::before{content:""}.si-credit-card::before{content:""}.si-feed::before{content:""}.si-hdd-o::before{content:""}.si-bullhorn::before{content:""}.si-bell-o::before{content:""}.si-certificate::before{content:""}.si-hand-o-right::before{content:""}.si-hand-o-left::before{content:""}.si-hand-o-up::before{content:""}.si-hand-o-down::before{content:""}.si-arrow-circle-left::before{content:""}.si-arrow-circle-right::before{content:""}.si-arrow-circle-up::before{content:""}.si-arrow-circle-down::before{content:""}.si-globe::before{content:""}.si-wrench::before{content:""}.si-tasks::before{content:""}.si-filter::before{content:""}.si-briefcase::before{content:""}.si-arrows-alt::before{content:""}.si-group::before{content:""}.si-chain::before{content:""}.si-cloud::before{content:""}.si-flask::before{content:""}.si-cut::before{content:""}.si-copy::before{content:""}.si-paperclip::before{content:""}.si-floppy-o::before{content:""}.si-square::before{content:""}.si-bars::before{content:""}.si-list-ul::before{content:""}.si-list-ol::before{content:""}.si-strikethrough::before{content:""}.si-underline::before{content:""}.si-table::before{content:""}.si-magic::before{content:""}.si-truck::before{content:""}.si-pinterest::before{content:""}.si-pinterest-square::before{content:""}.si-google-plus-square::before{content:""}.si-google-plus::before{content:""}.si-money::before{content:""}.si-caret-down::before{content:""}.si-caret-up::before{content:""}.si-caret-left::before{content:""}.si-caret-right::before{content:""}.si-columns::before{content:""}.si-sort::before{content:""}.si-sort-desc::before{content:""}.si-sort-asc::before{content:""}.si-envelope::before{content:""}.si-linkedin::before{content:""}.si-rotate-left::before{content:""}.si-gavel::before{content:""}.si-dashboard::before{content:""}.si-comment-o::before{content:""}.si-comments-o::before{content:""}.si-bolt::before{content:""}.si-sitemap::before{content:""}.si-umbrella::before{content:""}.si-clipboard::before{content:""}.si-lightbulb-o::before{content:""}.si-exchange::before{content:""}.si-cloud-download::before{content:""}.si-cloud-upload::before{content:""}.si-user-md::before{content:""}.si-stethoscope::before{content:""}.si-suitcase::before{content:""}.si-bell::before{content:""}.si-coffee::before{content:""}.si-cutlery::before{content:""}.si-file-text-o::before{content:""}.si-building-o::before{content:""}.si-hospital-o::before{content:""}.si-ambulance::before{content:""}.si-medkit::before{content:""}.si-fighter-jet::before{content:""}.si-beer::before{content:""}.si-h-square::before{content:""}.si-plus-square::before{content:""}.si-angle-double-left::before{content:""}.si-angle-double-right::before{content:""}.si-angle-double-up::before{content:""}.si-angle-double-down::before{content:""}.si-angle-left::before{content:""}.si-angle-right::before{content:""}.si-angle-up::before{content:""}.si-angle-down::before{content:""}.si-desktop::before{content:""}.si-laptop::before{content:""}.si-tablet::before{content:""}.si-mobile::before{content:""}.si-circle-o::before{content:""}.si-quote-left::before{content:""}.si-quote-right::before{content:""}.si-spinner::before{content:""}.si-circle::before{content:""}.si-mail-reply::before{content:""}.si-github-alt::before{content:""}.si-folder-o::before{content:""}.si-folder-open-o::before{content:""}.si-smile-o::before{content:""}.si-frown-o::before{content:""}.si-meh-o::before{content:""}.si-gamepad::before{content:""}.si-keyboard-o::before{content:""}.si-flag-o::before{content:""}.si-flag-checkered::before{content:""}.si-terminal::before{content:""}.si-code::before{content:""}.si-mail-reply-all::before{content:""}.si-star-half-empty::before{content:""}.si-location-arrow::before{content:""}.si-crop::before{content:""}.si-code-fork::before{content:""}.si-chain-broken::before{content:""}.si-question::before{content:""}.si-info::before{content:""}.si-exclamation::before{content:""}.si-superscript::before{content:""}.si-subscript::before{content:""}.si-eraser::before{content:""}.si-puzzle-piece::before{content:""}.si-microphone::before{content:""}.si-microphone-slash::before{content:""}.si-shield::before{content:""}.si-calendar-o::before{content:""}.si-fire-extinguisher::before{content:""}.si-rocket::before{content:""}.si-maxcdn::before{content:""}.si-chevron-circle-left::before{content:""}.si-chevron-circle-right::before{content:""}.si-chevron-circle-up::before{content:""}.si-chevron-circle-down::before{content:""}.si-html5::before{content:""}.si-css3::before{content:""}.si-anchor::before{content:""}.si-unlock-alt::before{content:""}.si-bullseye::before{content:""}.si-ellipsis-h::before{content:""}.si-ellipsis-v::before{content:""}.si-rss-square::before{content:""}.si-play-circle::before{content:""}.si-ticket::before{content:""}.si-minus-square::before{content:""}.si-minus-square-o::before{content:""}.si-level-up::before{content:""}.si-level-down::before{content:""}.si-check-square::before{content:""}.si-pencil-square::before{content:""}.si-external-link-square::before{content:""}.si-share-square::before{content:""}.si-compass::before{content:""}.si-caret-square-o-down::before{content:""}.si-caret-square-o-up::before{content:""}.si-caret-square-o-right::before{content:""}.si-eur::before{content:""}.si-gbp::before{content:""}.si-dollar::before{content:""}.si-inr::before{content:""}.si-cny::before{content:""}.si-rouble::before{content:""}.si-krw::before{content:""}.si-bitcoin::before{content:""}.si-file::before{content:""}.si-file-text::before{content:""}.si-sort-alpha-asc::before{content:""}.si-sort-alpha-desc::before{content:""}.si-sort-amount-asc::before{content:""}.si-sort-amount-desc::before{content:""}.si-sort-numeric-asc::before{content:""}.si-sort-numeric-desc::before{content:""}.si-thumbs-up::before{content:""}.si-thumbs-down::before{content:""}.si-youtube-square::before{content:""}.si-youtube::before{content:""}.si-xing::before{content:""}.si-xing-square::before{content:""}.si-youtube-play::before{content:""}.si-dropbox::before{content:""}.si-stack-overflow::before{content:""}.si-instagram::before{content:""}.si-flickr::before{content:""}.si-adn::before{content:""}.si-bitbucket::before{content:""}.si-bitbucket-square::before{content:""}.si-tumblr::before{content:""}.si-tumblr-square::before{content:""}.si-long-arrow-down::before{content:""}.si-long-arrow-up::before{content:""}.si-long-arrow-left::before{content:""}.si-long-arrow-right::before{content:""}.si-apple::before{content:""}.si-windows::before{content:""}.si-android::before{content:""}.si-linux::before{content:""}.si-dribbble::before{content:""}.si-skype::before{content:""}.si-foursquare::before{content:""}.si-trello::before{content:""}.si-female::before{content:""}.si-male::before{content:""}.si-gittip::before{content:""}.si-sun-o::before{content:""}.si-moon-o::before{content:""}.si-archive::before{content:""}.si-bug::before{content:""}.si-vk::before{content:""}.si-weibo::before{content:""}.si-renren::before{content:""}.si-pagelines::before{content:""}.si-stack-exchange::before{content:""}.si-arrow-circle-o-right::before{content:""}.si-arrow-circle-o-left::before{content:""}.si-caret-square-o-left::before{content:""}.si-dot-circle-o::before{content:""}.si-wheelchair::before{content:""}.si-vimeo-square::before{content:""}.si-try::before{content:""}.si-plus-square-o::before{content:""}.si-space-shuttle::before{content:""}.si-slack::before{content:""}.si-envelope-square::before{content:""}.si-wordpress::before{content:""}.si-openid::before{content:""}.si-bank::before{content:""}.si-graduation-cap::before{content:""}.si-yahoo::before{content:""}.si-google::before{content:""}.si-reddit::before{content:""}.si-reddit-square::before{content:""}.si-stumbleupon-circle::before{content:""}.si-stumbleupon::before{content:""}.si-delicious::before{content:""}.si-digg::before{content:""}.si-pied-piper::before{content:""}.si-pied-piper-alt::before{content:""}.si-drupal::before{content:""}.si-joomla::before{content:""}.si-language::before{content:""}.si-fax::before{content:""}.si-building::before{content:""}.si-child::before{content:""}.si-paw::before{content:""}.si-spoon::before{content:""}.si-cube::before{content:""}.si-cubes::before{content:""}.si-behance::before{content:""}.si-behance-square::before{content:""}.si-steam::before{content:""}.si-steam-square::before{content:""}.si-recycle::before{content:""}.si-automobile::before{content:""}.si-cab::before{content:""}.si-tree::before{content:""}.si-spotify::before{content:""}.si-deviantart::before{content:""}.si-soundcloud::before{content:""}.si-database::before{content:""}.si-file-pdf-o::before{content:""}.si-file-word-o::before{content:""}.si-file-excel-o::before{content:""}.si-file-powerpoint-o::before{content:""}.si-file-image-o::before{content:""}.si-file-archive-o::before{content:""}.si-file-audio-o::before{content:""}.si-file-movie-o::before{content:""}.si-file-code-o::before{content:""}.si-vine::before{content:""}.si-codepen::before{content:""}.si-jsfiddle::before{content:""}.si-life-bouy::before{content:""}.si-circle-o-notch::before{content:""}.si-ra::before{content:""}.si-empire::before{content:""}.si-git-square::before{content:""}.si-git::before{content:""}.si-hacker-news::before{content:""}.si-tencent-weibo::before{content:""}.si-qq::before{content:""}.si-wechat::before{content:""}.si-paper-plane::before{content:""}.si-paper-plane-o::before{content:""}.si-history::before{content:""}.si-circle-thin::before{content:""}.si-header::before{content:""}.si-paragraph::before{content:""}.si-sliders::before{content:""}.si-share-alt::before{content:""}.si-share-alt-square::before{content:""}.si-bomb::before{content:""}.si-futbol-o::before{content:""}.si-tty::before{content:""}.si-binoculars::before{content:""}.si-plug::before{content:""}.si-slideshare::before{content:""}.si-twitch::before{content:""}.si-yelp::before{content:""}.si-newspaper-o::before{content:""}.si-wifi::before{content:""}.si-calculator::before{content:""}.si-paypal::before{content:""}.si-google-wallet::before{content:""}.si-cc-visa::before{content:""}.si-cc-mastercard::before{content:""}.si-cc-discover::before{content:""}.si-cc-amex::before{content:""}.si-cc-paypal::before{content:""}.si-cc-stripe::before{content:""}.si-bell-slash::before{content:""}.si-bell-slash-o::before{content:""}.si-trash::before{content:""}.si-copyright::before{content:""}.si-at::before{content:""}.si-eyedropper::before{content:""}.si-paint-brush::before{content:""}.si-birthday-cake::before{content:""}.si-area-chart::before{content:""}.si-pie-chart::before{content:""}.si-line-chart::before{content:""}.si-lastfm::before{content:""}.si-lastfm-square::before{content:""}.si-toggle-off::before{content:""}.si-toggle-on::before{content:""}.si-bicycle::before{content:""}.si-bus::before{content:""}.si-ioxhost::before{content:""}.si-angellist::before{content:""}.si-cc::before{content:""}.si-ils::before{content:""}.si-meanpath::before{content:""}.si-buysellads::before{content:""}.si-connectdevelop::before{content:""}.si-dashcube::before{content:""}.si-forumbee::before{content:""}.si-leanpub::before{content:""}.si-sellsy::before{content:""}.si-shirtsinbulk::before{content:""}.si-simplybuilt::before{content:""}.si-skyatlas::before{content:""}.si-cart-plus::before{content:""}.si-cart-arrow-down::before{content:""}.si-diamond::before{content:""}.si-ship::before{content:""}.si-user-secret::before{content:""}.si-motorcycle::before{content:""}.si-street-view::before{content:""}.si-heartbeat::before{content:""}.si-venus::before{content:""}.si-mars::before{content:""}.si-mercury::before{content:""}.si-intersex::before{content:""}.si-transgender-alt::before{content:""}.si-venus-double::before{content:""}.si-mars-double::before{content:""}.si-venus-mars::before{content:""}.si-mars-stroke::before{content:""}.si-mars-stroke-v::before{content:""}.si-mars-stroke-h::before{content:""}.si-neuter::before{content:""}.si-genderless::before{content:""}.si-facebook-official::before{content:""}.si-pinterest-p::before{content:""}.si-whatsapp::before{content:""}.si-server::before{content:""}.si-user-plus::before{content:""}.si-user-times::before{content:""}.si-bed::before{content:""}.si-viacoin::before{content:""}.si-train::before{content:""}.si-subway::before{content:""}.si-medium::before{content:""}.si-y-combinator::before{content:""}.si-optin-monster::before{content:""}.si-opencart::before{content:""}.si-expeditedssl::before{content:""}.si-battery-4::before{content:""}.si-battery-3::before{content:""}.si-battery-2::before{content:""}.si-battery-1::before{content:""}.si-battery-0::before{content:""}.si-mouse-pointer::before{content:""}.si-i-cursor::before{content:""}.si-object-group::before{content:""}.si-object-ungroup::before{content:""}.si-sticky-note::before{content:""}.si-sticky-note-o::before{content:""}.si-cc-jcb::before{content:""}.si-cc-diners-club::before{content:""}.si-clone::before{content:""}.si-balance-scale::before{content:""}.si-hourglass-o::before{content:""}.si-hourglass-1::before{content:""}.si-hourglass-2::before{content:""}.si-hourglass-3::before{content:""}.si-hourglass::before{content:""}.si-hand-grab-o::before{content:""}.si-hand-paper-o::before{content:""}.si-hand-scissors-o::before{content:""}.si-hand-lizard-o::before{content:""}.si-hand-spock-o::before{content:""}.si-hand-pointer-o::before{content:""}.si-hand-peace-o::before{content:""}.si-trademark::before{content:""}.si-registered::before{content:""}.si-creative-commons::before{content:""}.si-gg::before{content:""}.si-gg-circle::before{content:""}.si-tripadvisor::before{content:""}.si-odnoklassniki::before{content:""}.si-odnoklassniki-square::before{content:""}.si-get-pocket::before{content:""}.si-wikipedia-w::before{content:""}.si-safari::before{content:""}.si-chrome::before{content:""}.si-firefox::before{content:""}.si-opera::before{content:""}.si-internet-explorer::before{content:""}.si-television::before{content:""}.si-contao::before{content:""}.si-500px::before{content:""}.si-amazon::before{content:""}.si-calendar-plus-o::before{content:""}.si-calendar-minus-o::before{content:""}.si-calendar-times-o::before{content:""}.si-calendar-check-o::before{content:""}.si-industry::before{content:""}.si-map-pin::before{content:""}.si-map-signs::before{content:""}.si-map-o::before{content:""}.si-map::before{content:""}.si-commenting::before{content:""}.si-commenting-o::before{content:""}.si-houzz::before{content:""}.si-vimeo::before{content:""}.si-black-tie::before{content:""}.si-fonticons::before{content:""}.si-lg{font-size:1.33333333em;line-height:0.75em;vertical-align:-15%}.si-2x{font-size:2em}.si-3x{font-size:3em}.si-4x{font-size:4em}.si-5x{font-size:5em}.si-fw{text-align:center;width:1.28571429em}.si-border{border-radius:.1em;padding:.2em .25em .15em;border:solid 0.08em}.si-pull-left{float:left;margin-right:.3em}.si-pull-right{float:right;margin-left:.3em}.si-rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.si-rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.si-rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.si-flip-horizontal{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.si-flip-vertical{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.si-inverse{-webkit-filter:invert(100%);filter:invert(100%)}.si-spin{-webkit-animation:si-animation-spin 2s infinite linear;-moz-animation:si-animation-spin 2s infinite linear;animation:si-animation-spin 2s infinite linear}.si-pulse{-webkit-animation:si-animation-spin 1s infinite steps(8);-moz-animation:si-animation-spin 1s infinite steps(8);animation:si-animation-spin 1s infinite steps(8)}.si-ul{padding-left:0;list-style-type:none;margin-left:2.14285714em}.si-ul>li{position:relative}.si-ul>li .si-li{text-align:center;position:absolute;left:-2.14285714em;width:2.14285714em;top:0.14285714em}.si-ul>li .si-li .si-lg{left:-1.85714286em}.si-stack{width:2em;height:2em;line-height:2em;vertical-align:middle;position:relative;display:inline-block}.si-stack .si-stack-1x,.si-stack .si-stack-2x{left:0;width:100%;text-align:center;position:absolute}.si-stack .si-stack-1x{line-height:inherit}.si-stack .si-stack-2x{font-size:2em}@-webkit-keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-moz-keyframes si-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}
|
2 |
|
3 |
-
/*# sourceMappingURL=short-classes.min.css.map */
|
1 |
@font-face{font-family:sharkicons;src:url("fonts/sharkicons.eot?v160221");src:url("fonts/sharkicons.eot?#iefix&v160221") format("embedded-opentype"),url("fonts/sharkicons.ttf?v160221") format("truetype"),url("fonts/sharkicons.woff?v160221") format("woff"),url("fonts/sharkicons.svg?v160221#sharkicons") format("svg");font-weight:normal;font-style:normal}.si::before{font:normal normal normal 14px/1 sharkicons;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;display:inline-block;font-size:inherit;text-decoration:inherit;text-transform:none}.si-broom::before{content:""}.si-comment-mail-one::before{content:""}.si-comment-mail::before{content:""}.si-s2member::before{content:""}.si-websharks::before{content:""}.si-wp-kb-articles::before{content:""}.si-zencache-logo::before{content:""}.si-zencache::before{content:""}.si-wp-sharks::before{content:""}.si-wp-sharks-fin::before{content:""}.si-comet-cache::before{content:""}.si-comet-cache-logo::before{content:""}.si-comet-cache-comet::before{content:""}.si-feat-watch::before{content:""}.si-feat-server::before{content:""}.si-feat-layers::before{content:""}.si-feat-box::before{content:""}.si-feat-ellipsis::before{content:""}.si-typi-group::before{content:""}.si-enty-bookmark::before{content:""}.si-enty-bookmarks::before{content:""}.si-enty-open-book::before{content:""}.si-enty-archive::before{content:""}.si-enty-area-graph::before{content:""}.si-enty-bucket::before{content:""}.si-enty-colors::before{content:""}.si-enty-copy::before{content:""}.si-enty-drive::before{content:""}.si-enty-feather::before{content:""}.si-enty-gauge::before{content:""}.si-enty-hand::before{content:""}.si-enty-lab-flask::before{content:""}.si-enty-mask::before{content:""}.si-enty-medal::before{content:""}.si-enty-exclamation::before{content:""}.si-enty-palette::before{content:""}.si-enty-ruler::before{content:""}.si-enty-shop::before{content:""}.si-enty-basket::before{content:""}.si-enty-cart::before{content:""}.si-enty-traffic-cone::before{content:""}.si-enty-tree::before{content:""}.si-enty-trophy::before{content:""}.si-enty-v-card::before{content:""}.si-enty-google-hangouts::before{content:""}.si-eleg-line-graph::before{content:""}.si-eleg-male::before{content:""}.si-eleg-female::before{content:""}.si-eleg-atom::before{content:""}.si-broc-cart::before{content:""}.si-broc-crap::before{content:""}.si-broc-atom::before{content:""}.si-icom-headphones::before{content:""}.si-icom-barcode::before{content:""}.si-icom-user::before{content:""}.si-icom-users::before{content:""}.si-icom-user-plus::before{content:""}.si-icom-user-minus::before{content:""}.si-icom-user-check::before{content:""}.si-icom-user-tie::before{content:""}.si-icom-key::before{content:""}.si-icom-key2::before{content:""}.si-icom-happy::before{content:""}.si-icom-happy2::before{content:""}.si-icom-smile::before{content:""}.si-icom-smile2::before{content:""}.si-icom-tongue::before{content:""}.si-icom-tongue2::before{content:""}.si-icom-sad::before{content:""}.si-icom-sad2::before{content:""}.si-icom-wink::before{content:""}.si-icom-wink2::before{content:""}.si-icom-grin::before{content:""}.si-icom-grin2::before{content:""}.si-icom-cool::before{content:""}.si-icom-cool2::before{content:""}.si-icom-angry::before{content:""}.si-icom-angry2::before{content:""}.si-icom-evil::before{content:""}.si-icom-evil2::before{content:""}.si-icom-shocked::before{content:""}.si-icom-shocked2::before{content:""}.si-icom-baffled::before{content:""}.si-icom-baffled2::before{content:""}.si-icom-confused::before{content:""}.si-icom-confused2::before{content:""}.si-icom-neutral::before{content:""}.si-icom-neutral2::before{content:""}.si-icom-hipster::before{content:""}.si-icom-hipster2::before{content:""}.si-icom-wondering::before{content:""}.si-icom-wondering2::before{content:""}.si-icom-sleepy::before{content:""}.si-icom-sleepy2::before{content:""}.si-icom-frustrated::before{content:""}.si-icom-frustrated2::before{content:""}.si-icom-crying::before{content:""}.si-icom-crying2::before{content:""}.si-icom-spell-check::before{content:""}.si-icom-command-key::before{content:""}.si-icom-shift-key::before{content:""}.si-icom-control-key::before{content:""}.si-icom-option-key::before{content:""}.si-icom-wordpress::before{content:""}.si-icom-wordpress-square::before{content:""}.si-icom-yahoo::before{content:""}.si-icom-linux::before{content:""}.si-icom-finder::before{content:""}.si-icom-android::before{content:""}.si-icom-reddit::before{content:""}.si-icom-paypal::before{content:""}.si-icom-git::before{content:""}.si-octi-alignment-align::before{content:""}.si-octi-alignment-aligned-to::before{content:""}.si-octi-alignment-unalign::before{content:""}.si-octi-bookmark::before{content:""}.si-octi-broadcast::before{content:""}.si-octi-browser::before{content:""}.si-octi-checklist::before{content:""}.si-octi-circuit-board::before{content:""}.si-octi-clippy::before{content:""}.si-octi-cloud-download::before{content:""}.si-octi-cloud-upload::before{content:""}.si-octi-comment::before{content:""}.si-octi-comments::before{content:""}.si-octi-tach::before{content:""}.si-octi-device-camera::before{content:""}.si-octi-device-camera-video::before{content:""}.si-octi-device-desktop::before{content:""}.si-octi-diff::before{content:""}.si-octi-file-binary::before{content:""}.si-octi-file-media::before{content:""}.si-octi-file-submodule::before{content:""}.si-octi-file-symlink-directory::before{content:""}.si-octi-file-symlink-file::before{content:""}.si-octi-fold::before{content:""}.si-octi-git-branch::before{content:""}.si-octi-git-commit::before{content:""}.si-octi-git-compare::before{content:""}.si-octi-git-merge::before{content:""}.si-octi-git-pull-request::before{content:""}.si-octi-graph::before{content:""}.si-octi-home::before{content:""}.si-octi-horizontal-rule::before{content:""}.si-octi-key::before{content:""}.si-octi-light-bulb::before{content:""}.si-octi-link-external::before{content:""}.si-octi-lock::before{content:""}.si-octi-markdown::before{content:""}.si-octi-microscope::before{content:""}.si-octi-mirror::before{content:""}.si-octi-move-down::before{content:""}.si-octi-move-left::before{content:""}.si-octi-move-right::before{content:""}.si-octi-move-up::before{content:""}.si-octi-mute::before{content:""}.si-octi-organization::before{content:""}.si-octi-package::before{content:""}.si-octi-paintcan::before{content:""}.si-octi-person::before{content:""}.si-octi-plug::before{content:""}.si-octi-podium::before{content:""}.si-octi-pulse::before{content:""}.si-octi-puzzle::before{content:""}.si-octi-repo::before{content:""}.si-octi-repo-clone::before{content:""}.si-octi-repo-force-push::before{content:""}.si-octi-repo-forked::before{content:""}.si-octi-repo-pull::before{content:""}.si-octi-repo-push::before{content:""}.si-octi-rocket::before{content:""}.si-octi-ruby::before{content:""}.si-octi-screen-full::before{content:""}.si-octi-screen-normal::before{content:""}.si-octi-sign-in::before{content:""}.si-octi-sign-out::before{content:""}.si-octi-split::before{content:""}.si-octi-squirrel::before{content:""}.si-octi-steps::before{content:""}.si-octi-tag::before{content:""}.si-octi-telescope::before{content:""}.si-octi-terminal::before{content:""}.si-octi-unfold::before{content:""}.si-octi-versions::before{content:""}.si-glass::before{content:""}.si-music::before{content:""}.si-search::before{content:""}.si-envelope-o::before{content:""}.si-heart::before{content:""}.si-star::before{content:""}.si-star-o::before{content:""}.si-user::before{content:""}.si-film::before{content:""}.si-th-large::before{content:""}.si-th::before{content:""}.si-th-list::before{content:""}.si-check::before{content:""}.si-close::before{content:""}.si-search-plus::before{content:""}.si-search-minus::before{content:""}.si-power-off::before{content:""}.si-signal::before{content:""}.si-cog::before{content:""}.si-trash-o::before{content:""}.si-home::before{content:""}.si-file-o::before{content:""}.si-clock-o::before{content:""}.si-road::before{content:""}.si-download::before{content:""}.si-arrow-circle-o-down::before{content:""}.si-arrow-circle-o-up::before{content:""}.si-inbox::before{content:""}.si-play-circle-o::before{content:""}.si-repeat::before{content:""}.si-refresh::before{content:""}.si-list-alt::before{content:""}.si-lock::before{content:""}.si-flag::before{content:""}.si-headphones::before{content:""}.si-volume-off::before{content:""}.si-volume-down::before{content:""}.si-volume-up::before{content:""}.si-qrcode::before{content:""}.si-barcode::before{content:""}.si-tag::before{content:""}.si-tags::before{content:""}.si-book::before{content:""}.si-bookmark::before{content:""}.si-print::before{content:""}.si-camera::before{content:""}.si-font::before{content:""}.si-bold::before{content:""}.si-italic::before{content:""}.si-text-height::before{content:""}.si-text-width::before{content:""}.si-align-left::before{content:""}.si-align-center::before{content:""}.si-align-right::before{content:""}.si-align-justify::before{content:""}.si-list::before{content:""}.si-dedent::before{content:""}.si-indent::before{content:""}.si-video-camera::before{content:""}.si-image::before{content:""}.si-pencil::before{content:""}.si-map-marker::before{content:""}.si-adjust::before{content:""}.si-tint::before{content:""}.si-edit::before{content:""}.si-share-square-o::before{content:""}.si-check-square-o::before{content:""}.si-arrows::before{content:""}.si-step-backward::before{content:""}.si-fast-backward::before{content:""}.si-backward::before{content:""}.si-play::before{content:""}.si-pause::before{content:""}.si-stop::before{content:""}.si-forward::before{content:""}.si-fast-forward::before{content:""}.si-step-forward::before{content:""}.si-eject::before{content:""}.si-chevron-left::before{content:""}.si-chevron-right::before{content:""}.si-plus-circle::before{content:""}.si-minus-circle::before{content:""}.si-times-circle::before{content:""}.si-check-circle::before{content:""}.si-question-circle::before{content:""}.si-info-circle::before{content:""}.si-crosshairs::before{content:""}.si-times-circle-o::before{content:""}.si-check-circle-o::before{content:""}.si-ban::before{content:""}.si-arrow-left::before{content:""}.si-arrow-right::before{content:""}.si-arrow-up::before{content:""}.si-arrow-down::before{content:""}.si-mail-forward::before{content:""}.si-expand::before{content:""}.si-compress::before{content:""}.si-plus::before{content:""}.si-minus::before{content:""}.si-asterisk::before{content:""}.si-exclamation-circle::before{content:""}.si-gift::before{content:""}.si-leaf::before{content:""}.si-fire::before{content:""}.si-eye::before{content:""}.si-eye-slash::before{content:""}.si-exclamation-triangle::before{content:""}.si-plane::before{content:""}.si-calendar::before{content:""}.si-random::before{content:""}.si-comment::before{content:""}.si-magnet::before{content:""}.si-chevron-up::before{content:""}.si-chevron-down::before{content:""}.si-retweet::before{content:""}.si-shopping-cart::before{content:""}.si-folder::before{content:""}.si-folder-open::before{content:""}.si-arrows-v::before{content:""}.si-arrows-h::before{content:""}.si-bar-chart::before{content:""}.si-twitter-square::before{content:""}.si-facebook-square::before{content:""}.si-camera-retro::before{content:""}.si-key::before{content:""}.si-cogs::before{content:""}.si-comments::before{content:""}.si-thumbs-o-up::before{content:""}.si-thumbs-o-down::before{content:""}.si-star-half::before{content:""}.si-heart-o::before{content:""}.si-sign-out::before{content:""}.si-linkedin-square::before{content:""}.si-thumb-tack::before{content:""}.si-external-link::before{content:""}.si-sign-in::before{content:""}.si-trophy::before{content:""}.si-github-square::before{content:""}.si-upload::before{content:""}.si-lemon-o::before{content:""}.si-phone::before{content:""}.si-square-o::before{content:""}.si-bookmark-o::before{content:""}.si-phone-square::before{content:""}.si-twitter::before{content:""}.si-facebook::before{content:""}.si-github::before{content:""}.si-unlock::before{content:""}.si-credit-card::before{content:""}.si-feed::before{content:""}.si-hdd-o::before{content:""}.si-bullhorn::before{content:""}.si-bell-o::before{content:""}.si-certificate::before{content:""}.si-hand-o-right::before{content:""}.si-hand-o-left::before{content:""}.si-hand-o-up::before{content:""}.si-hand-o-down::before{content:""}.si-arrow-circle-left::before{content:""}.si-arrow-circle-right::before{content:""}.si-arrow-circle-up::before{content:""}.si-arrow-circle-down::before{content:""}.si-globe::before{content:""}.si-wrench::before{content:""}.si-tasks::before{content:""}.si-filter::before{content:""}.si-briefcase::before{content:""}.si-arrows-alt::before{content:""}.si-group::before{content:""}.si-chain::before{content:""}.si-cloud::before{content:""}.si-flask::before{content:""}.si-cut::before{content:""}.si-copy::before{content:""}.si-paperclip::before{content:""}.si-floppy-o::before{content:""}.si-square::before{content:""}.si-bars::before{content:""}.si-list-ul::before{content:""}.si-list-ol::before{content:""}.si-strikethrough::before{content:""}.si-underline::before{content:""}.si-table::before{content:""}.si-magic::before{content:""}.si-truck::before{content:""}.si-pinterest::before{content:""}.si-pinterest-square::before{content:""}.si-google-plus-square::before{content:""}.si-google-plus::before{content:""}.si-money::before{content:""}.si-caret-down::before{content:""}.si-caret-up::before{content:""}.si-caret-left::before{content:""}.si-caret-right::before{content:""}.si-columns::before{content:""}.si-sort::before{content:""}.si-sort-desc::before{content:""}.si-sort-asc::before{content:""}.si-envelope::before{content:""}.si-linkedin::before{content:""}.si-rotate-left::before{content:""}.si-gavel::before{content:""}.si-dashboard::before{content:""}.si-comment-o::before{content:""}.si-comments-o::before{content:""}.si-bolt::before{content:""}.si-sitemap::before{content:""}.si-umbrella::before{content:""}.si-clipboard::before{content:""}.si-lightbulb-o::before{content:""}.si-exchange::before{content:""}.si-cloud-download::before{content:""}.si-cloud-upload::before{content:""}.si-user-md::before{content:""}.si-stethoscope::before{content:""}.si-suitcase::before{content:""}.si-bell::before{content:""}.si-coffee::before{content:""}.si-cutlery::before{content:""}.si-file-text-o::before{content:""}.si-building-o::before{content:""}.si-hospital-o::before{content:""}.si-ambulance::before{content:""}.si-medkit::before{content:""}.si-fighter-jet::before{content:""}.si-beer::before{content:""}.si-h-square::before{content:""}.si-plus-square::before{content:""}.si-angle-double-left::before{content:""}.si-angle-double-right::before{content:""}.si-angle-double-up::before{content:""}.si-angle-double-down::before{content:""}.si-angle-left::before{content:""}.si-angle-right::before{content:""}.si-angle-up::before{content:""}.si-angle-down::before{content:""}.si-desktop::before{content:""}.si-laptop::before{content:""}.si-tablet::before{content:""}.si-mobile::before{content:""}.si-circle-o::before{content:""}.si-quote-left::before{content:""}.si-quote-right::before{content:""}.si-spinner::before{content:""}.si-circle::before{content:""}.si-mail-reply::before{content:""}.si-github-alt::before{content:""}.si-folder-o::before{content:""}.si-folder-open-o::before{content:""}.si-smile-o::before{content:""}.si-frown-o::before{content:""}.si-meh-o::before{content:""}.si-gamepad::before{content:""}.si-keyboard-o::before{content:""}.si-flag-o::before{content:""}.si-flag-checkered::before{content:""}.si-terminal::before{content:""}.si-code::before{content:""}.si-mail-reply-all::before{content:""}.si-star-half-empty::before{content:""}.si-location-arrow::before{content:""}.si-crop::before{content:""}.si-code-fork::before{content:""}.si-chain-broken::before{content:""}.si-question::before{content:""}.si-info::before{content:""}.si-exclamation::before{content:""}.si-superscript::before{content:""}.si-subscript::before{content:""}.si-eraser::before{content:""}.si-puzzle-piece::before{content:""}.si-microphone::before{content:""}.si-microphone-slash::before{content:""}.si-shield::before{content:""}.si-calendar-o::before{content:""}.si-fire-extinguisher::before{content:""}.si-rocket::before{content:""}.si-maxcdn::before{content:""}.si-chevron-circle-left::before{content:""}.si-chevron-circle-right::before{content:""}.si-chevron-circle-up::before{content:""}.si-chevron-circle-down::before{content:""}.si-html5::before{content:""}.si-css3::before{content:""}.si-anchor::before{content:""}.si-unlock-alt::before{content:""}.si-bullseye::before{content:""}.si-ellipsis-h::before{content:""}.si-ellipsis-v::before{content:""}.si-rss-square::before{content:""}.si-play-circle::before{content:""}.si-ticket::before{content:""}.si-minus-square::before{content:""}.si-minus-square-o::before{content:""}.si-level-up::before{content:""}.si-level-down::before{content:""}.si-check-square::before{content:""}.si-pencil-square::before{content:""}.si-external-link-square::before{content:""}.si-share-square::before{content:""}.si-compass::before{content:""}.si-caret-square-o-down::before{content:""}.si-caret-square-o-up::before{content:""}.si-caret-square-o-right::before{content:""}.si-eur::before{content:""}.si-gbp::before{content:""}.si-dollar::before{content:""}.si-inr::before{content:""}.si-cny::before{content:""}.si-rouble::before{content:""}.si-krw::before{content:""}.si-bitcoin::before{content:""}.si-file::before{content:""}.si-file-text::before{content:""}.si-sort-alpha-asc::before{content:""}.si-sort-alpha-desc::before{content:""}.si-sort-amount-asc::before{content:""}.si-sort-amount-desc::before{content:""}.si-sort-numeric-asc::before{content:""}.si-sort-numeric-desc::before{content:""}.si-thumbs-up::before{content:""}.si-thumbs-down::before{content:""}.si-youtube-square::before{content:""}.si-youtube::before{content:""}.si-xing::before{content:""}.si-xing-square::before{content:""}.si-youtube-play::before{content:""}.si-dropbox::before{content:""}.si-stack-overflow::before{content:""}.si-instagram::before{content:""}.si-flickr::before{content:""}.si-adn::before{content:""}.si-bitbucket::before{content:""}.si-bitbucket-square::before{content:""}.si-tumblr::before{content:""}.si-tumblr-square::before{content:""}.si-long-arrow-down::before{content:""}.si-long-arrow-up::before{content:""}.si-long-arrow-left::before{content:""}.si-long-arrow-right::before{content:""}.si-apple::before{content:""}.si-windows::before{content:""}.si-android::before{content:""}.si-linux::before{content:""}.si-dribbble::before{content:""}.si-skype::before{content:""}.si-foursquare::before{content:""}.si-trello::before{content:""}.si-female::before{content:""}.si-male::before{content:""}.si-gittip::before{content:""}.si-sun-o::before{content:""}.si-moon-o::before{content:""}.si-archive::before{content:""}.si-bug::before{content:""}.si-vk::before{content:""}.si-weibo::before{content:""}.si-renren::before{content:""}.si-pagelines::before{content:""}.si-stack-exchange::before{content:""}.si-arrow-circle-o-right::before{content:""}.si-arrow-circle-o-left::before{content:""}.si-caret-square-o-left::before{content:""}.si-dot-circle-o::before{content:""}.si-wheelchair::before{content:""}.si-vimeo-square::before{content:""}.si-try::before{content:""}.si-plus-square-o::before{content:""}.si-space-shuttle::before{content:""}.si-slack::before{content:""}.si-envelope-square::before{content:""}.si-wordpress::before{content:""}.si-openid::before{content:""}.si-bank::before{content:""}.si-graduation-cap::before{content:""}.si-yahoo::before{content:""}.si-google::before{content:""}.si-reddit::before{content:""}.si-reddit-square::before{content:""}.si-stumbleupon-circle::before{content:""}.si-stumbleupon::before{content:""}.si-delicious::before{content:""}.si-digg::before{content:""}.si-pied-piper::before{content:""}.si-pied-piper-alt::before{content:""}.si-drupal::before{content:""}.si-joomla::before{content:""}.si-language::before{content:""}.si-fax::before{content:""}.si-building::before{content:""}.si-child::before{content:""}.si-paw::before{content:""}.si-spoon::before{content:""}.si-cube::before{content:""}.si-cubes::before{content:""}.si-behance::before{content:""}.si-behance-square::before{content:""}.si-steam::before{content:""}.si-steam-square::before{content:""}.si-recycle::before{content:""}.si-automobile::before{content:""}.si-cab::before{content:""}.si-tree::before{content:""}.si-spotify::before{content:""}.si-deviantart::before{content:""}.si-soundcloud::before{content:""}.si-database::before{content:""}.si-file-pdf-o::before{content:""}.si-file-word-o::before{content:""}.si-file-excel-o::before{content:""}.si-file-powerpoint-o::before{content:""}.si-file-image-o::before{content:""}.si-file-archive-o::before{content:""}.si-file-audio-o::before{content:""}.si-file-movie-o::before{content:""}.si-file-code-o::before{content:""}.si-vine::before{content:""}.si-codepen::before{content:""}.si-jsfiddle::before{content:""}.si-life-bouy::before{content:""}.si-circle-o-notch::before{content:""}.si-ra::before{content:""}.si-empire::before{content:""}.si-git-square::before{content:""}.si-git::before{content:""}.si-hacker-news::before{content:""}.si-tencent-weibo::before{content:""}.si-qq::before{content:""}.si-wechat::before{content:""}.si-paper-plane::before{content:""}.si-paper-plane-o::before{content:""}.si-history::before{content:""}.si-circle-thin::before{content:""}.si-header::before{content:""}.si-paragraph::before{content:""}.si-sliders::before{content:""}.si-share-alt::before{content:""}.si-share-alt-square::before{content:""}.si-bomb::before{content:""}.si-futbol-o::before{content:""}.si-tty::before{content:""}.si-binoculars::before{content:""}.si-plug::before{content:""}.si-slideshare::before{content:""}.si-twitch::before{content:""}.si-yelp::before{content:""}.si-newspaper-o::before{content:""}.si-wifi::before{content:""}.si-calculator::before{content:""}.si-paypal::before{content:""}.si-google-wallet::before{content:""}.si-cc-visa::before{content:""}.si-cc-mastercard::before{content:""}.si-cc-discover::before{content:""}.si-cc-amex::before{content:""}.si-cc-paypal::before{content:""}.si-cc-stripe::before{content:""}.si-bell-slash::before{content:""}.si-bell-slash-o::before{content:""}.si-trash::before{content:""}.si-copyright::before{content:""}.si-at::before{content:""}.si-eyedropper::before{content:""}.si-paint-brush::before{content:""}.si-birthday-cake::before{content:""}.si-area-chart::before{content:""}.si-pie-chart::before{content:""}.si-line-chart::before{content:""}.si-lastfm::before{content:""}.si-lastfm-square::before{content:""}.si-toggle-off::before{content:""}.si-toggle-on::before{content:""}.si-bicycle::before{content:""}.si-bus::before{content:""}.si-ioxhost::before{content:""}.si-angellist::before{content:""}.si-cc::before{content:""}.si-ils::before{content:""}.si-meanpath::before{content:""}.si-buysellads::before{content:""}.si-connectdevelop::before{content:""}.si-dashcube::before{content:""}.si-forumbee::before{content:""}.si-leanpub::before{content:""}.si-sellsy::before{content:""}.si-shirtsinbulk::before{content:""}.si-simplybuilt::before{content:""}.si-skyatlas::before{content:""}.si-cart-plus::before{content:""}.si-cart-arrow-down::before{content:""}.si-diamond::before{content:""}.si-ship::before{content:""}.si-user-secret::before{content:""}.si-motorcycle::before{content:""}.si-street-view::before{content:""}.si-heartbeat::before{content:""}.si-venus::before{content:""}.si-mars::before{content:""}.si-mercury::before{content:""}.si-intersex::before{content:""}.si-transgender-alt::before{content:""}.si-venus-double::before{content:""}.si-mars-double::before{content:""}.si-venus-mars::before{content:""}.si-mars-stroke::before{content:""}.si-mars-stroke-v::before{content:""}.si-mars-stroke-h::before{content:""}.si-neuter::before{content:""}.si-genderless::before{content:""}.si-facebook-official::before{content:""}.si-pinterest-p::before{content:""}.si-whatsapp::before{content:""}.si-server::before{content:""}.si-user-plus::before{content:""}.si-user-times::before{content:""}.si-bed::before{content:""}.si-viacoin::before{content:""}.si-train::before{content:""}.si-subway::before{content:""}.si-medium::before{content:""}.si-y-combinator::before{content:""}.si-optin-monster::before{content:""}.si-opencart::before{content:""}.si-expeditedssl::before{content:""}.si-battery-4::before{content:""}.si-battery-3::before{content:""}.si-battery-2::before{content:""}.si-battery-1::before{content:""}.si-battery-0::before{content:""}.si-mouse-pointer::before{content:""}.si-i-cursor::before{content:""}.si-object-group::before{content:""}.si-object-ungroup::before{content:""}.si-sticky-note::before{content:""}.si-sticky-note-o::before{content:""}.si-cc-jcb::before{content:""}.si-cc-diners-club::before{content:""}.si-clone::before{content:""}.si-balance-scale::before{content:""}.si-hourglass-o::before{content:""}.si-hourglass-1::before{content:""}.si-hourglass-2::before{content:""}.si-hourglass-3::before{content:""}.si-hourglass::before{content:""}.si-hand-grab-o::before{content:""}.si-hand-paper-o::before{content:""}.si-hand-scissors-o::before{content:""}.si-hand-lizard-o::before{content:""}.si-hand-spock-o::before{content:""}.si-hand-pointer-o::before{content:""}.si-hand-peace-o::before{content:""}.si-trademark::before{content:""}.si-registered::before{content:""}.si-creative-commons::before{content:""}.si-gg::before{content:""}.si-gg-circle::before{content:""}.si-tripadvisor::before{content:""}.si-odnoklassniki::before{content:""}.si-odnoklassniki-square::before{content:""}.si-get-pocket::before{content:""}.si-wikipedia-w::before{content:""}.si-safari::before{content:""}.si-chrome::before{content:""}.si-firefox::before{content:""}.si-opera::before{content:""}.si-internet-explorer::before{content:""}.si-television::before{content:""}.si-contao::before{content:""}.si-500px::before{content:""}.si-amazon::before{content:""}.si-calendar-plus-o::before{content:""}.si-calendar-minus-o::before{content:""}.si-calendar-times-o::before{content:""}.si-calendar-check-o::before{content:""}.si-industry::before{content:""}.si-map-pin::before{content:""}.si-map-signs::before{content:""}.si-map-o::before{content:""}.si-map::before{content:""}.si-commenting::before{content:""}.si-commenting-o::before{content:""}.si-houzz::before{content:""}.si-vimeo::before{content:""}.si-black-tie::before{content:""}.si-fonticons::before{content:""}.si-lg{font-size:1.33333333em;line-height:0.75em;vertical-align:-15%}.si-2x{font-size:2em}.si-3x{font-size:3em}.si-4x{font-size:4em}.si-5x{font-size:5em}.si-fw{text-align:center;width:1.28571429em}.si-border{border-radius:.1em;padding:.2em .25em .15em;border:solid 0.08em}.si-pull-left{float:left;margin-right:.3em}.si-pull-right{float:right;margin-left:.3em}.si-rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.si-rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.si-rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.si-flip-horizontal{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.si-flip-vertical{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.si-inverse{-webkit-filter:invert(100%);filter:invert(100%)}.si-spin{-webkit-animation:si-animation-spin 2s infinite linear;-moz-animation:si-animation-spin 2s infinite linear;animation:si-animation-spin 2s infinite linear}.si-pulse{-webkit-animation:si-animation-spin 1s infinite steps(8);-moz-animation:si-animation-spin 1s infinite steps(8);animation:si-animation-spin 1s infinite steps(8)}.si-ul{padding-left:0;list-style-type:none;margin-left:2.14285714em}.si-ul>li{position:relative}.si-ul>li .si-li{text-align:center;position:absolute;left:-2.14285714em;width:2.14285714em;top:0.14285714em}.si-ul>li .si-li .si-lg{left:-1.85714286em}.si-stack{width:2em;height:2em;line-height:2em;vertical-align:middle;position:relative;display:inline-block}.si-stack .si-stack-1x,.si-stack .si-stack-2x{left:0;width:100%;text-align:center;position:absolute}.si-stack .si-stack-1x{line-height:inherit}.si-stack .si-stack-2x{font-size:2em}@-webkit-keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-moz-keyframes si-animation-spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@keyframes si-animation-spin{0%{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);-moz-transform:rotate(359deg);-ms-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}
|
2 |
|
|
src/vendor/websharks/wp-i18n-tools/CHANGELOG.md
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
## v15xxxx
|
2 |
+
|
3 |
+
- Initial release.
|
src/vendor/websharks/wp-i18n-tools/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
## WP i18n Tools
|
2 |
+
|
3 |
+
Modified slightly by WebSharks, Inc.
|
4 |
+
|
5 |
+
#### Differences from original:
|
6 |
+
|
7 |
+
- Adding shebang line to the top of `makepot.php`.
|
8 |
+
- Now distributing a packaged PHAR binary w/ each release.
|
9 |
+
- Setting executable bit on `makepot.php` and preserving that with Git.
|
10 |
+
- Updated to support PHP/translations embedded into `.js` files too.
|
11 |
+
- Disabling line wrapping from final output to ensure better consistency.
|
12 |
+
- Adding support for plugin directories that use a `plugin.php` file instead of `[slug].php`.
|
13 |
+
- Adding `composer.json` and package on Packagist.org.
|
14 |
+
- Auto-exclude `(?:.+?/)?vendor/.*` in themes/plugins.
|
src/vendor/websharks/wp-i18n-tools/add-textdomain.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Console application, which adds textdomain argument
|
4 |
+
* to all i18n function calls
|
5 |
+
*
|
6 |
+
* @author
|
7 |
+
* @version $Id$
|
8 |
+
* @package wordpress-i18n
|
9 |
+
*/
|
10 |
+
error_reporting(E_ALL);
|
11 |
+
|
12 |
+
require_once dirname( __FILE__ ) . '/makepot.php';
|
13 |
+
|
14 |
+
class AddTextdomain {
|
15 |
+
|
16 |
+
var $modified_contents = '';
|
17 |
+
var $funcs;
|
18 |
+
|
19 |
+
function AddTextdomain() {
|
20 |
+
$makepot = new MakePOT;
|
21 |
+
$this->funcs = array_keys( $makepot->rules );
|
22 |
+
}
|
23 |
+
|
24 |
+
function usage() {
|
25 |
+
$usage = "Usage: php add-textdomain.php [-i] <domain> <file>\n\nAdds the string <domain> as a last argument to all i18n function calls in <file>\nand prints the modified php file on standard output.\n\nOptions:\n -i Modifies the PHP file in place, instead of printing it to standard output.\n";
|
26 |
+
fwrite(STDERR, $usage);
|
27 |
+
exit(1);
|
28 |
+
}
|
29 |
+
|
30 |
+
function process_token($token_text, $inplace) {
|
31 |
+
if ($inplace)
|
32 |
+
$this->modified_contents .= $token_text;
|
33 |
+
else
|
34 |
+
echo $token_text;
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
function process_file($domain, $source_filename, $inplace) {
|
39 |
+
|
40 |
+
$this->modified_contents = '';
|
41 |
+
$domain = addslashes($domain);
|
42 |
+
|
43 |
+
$source = file_get_contents($source_filename);
|
44 |
+
$tokens = token_get_all($source);
|
45 |
+
|
46 |
+
$in_func = false;
|
47 |
+
$args_started = false;
|
48 |
+
$parens_balance = 0;
|
49 |
+
$found_domain = false;
|
50 |
+
|
51 |
+
foreach($tokens as $token) {
|
52 |
+
$string_success = false;
|
53 |
+
if (is_array($token)) {
|
54 |
+
list($id, $text) = $token;
|
55 |
+
if (T_STRING == $id && in_array($text, $this->funcs)) {
|
56 |
+
$in_func = true;
|
57 |
+
$parens_balance = 0;
|
58 |
+
$args_started = false;
|
59 |
+
$found_domain = false;
|
60 |
+
} elseif (T_CONSTANT_ENCAPSED_STRING == $id && ("'$domain'" == $text || "\"$domain\"" == $text)) {
|
61 |
+
if ($in_func && $args_started) {
|
62 |
+
$found_domain = true;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
$token = $text;
|
66 |
+
} elseif ('(' == $token){
|
67 |
+
$args_started = true;
|
68 |
+
++$parens_balance;
|
69 |
+
} elseif (')' == $token) {
|
70 |
+
--$parens_balance;
|
71 |
+
if ($in_func && 0 == $parens_balance) {
|
72 |
+
$token = $found_domain? ')' : ", '$domain')";
|
73 |
+
$in_func = false;
|
74 |
+
$args_started = false;
|
75 |
+
$found_domain = false;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
$this->process_token($token, $inplace);
|
79 |
+
}
|
80 |
+
|
81 |
+
if ($inplace) {
|
82 |
+
$f = fopen($source_filename, 'w');
|
83 |
+
fwrite($f, $this->modified_contents);
|
84 |
+
fclose($f);
|
85 |
+
}
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
|
90 |
+
// run the CLI only if the file
|
91 |
+
// wasn't included
|
92 |
+
$included_files = get_included_files();
|
93 |
+
if ($included_files[0] == __FILE__) {
|
94 |
+
$adddomain = new AddTextdomain;
|
95 |
+
|
96 |
+
if (!isset($argv[1]) || !isset($argv[2])) {
|
97 |
+
$adddomain->usage();
|
98 |
+
}
|
99 |
+
|
100 |
+
$inplace = false;
|
101 |
+
if ('-i' == $argv[1]) {
|
102 |
+
$inplace = true;
|
103 |
+
if (!isset($argv[3])) $adddomain->usage();
|
104 |
+
array_shift($argv);
|
105 |
+
}
|
106 |
+
|
107 |
+
$adddomain->process_file($argv[1], $argv[2], $inplace);
|
108 |
+
}
|
109 |
+
|
110 |
+
?>
|
src/vendor/websharks/wp-i18n-tools/cron-svn-pots.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once dirname( __FILE__ ) . '/makepot.php';
|
3 |
+
|
4 |
+
function silent_system( $command ) {
|
5 |
+
global $at_least_one_error;
|
6 |
+
ob_start();
|
7 |
+
system( "$command 2>&1", $exit_code );
|
8 |
+
$output = ob_get_contents();
|
9 |
+
ob_end_clean();
|
10 |
+
if ( $exit_code != 0 ) {
|
11 |
+
echo "ERROR:\t$command\nCODE:\t$exit_code\nOUTPUT:\n";
|
12 |
+
echo $output."\n";
|
13 |
+
} else {
|
14 |
+
echo "OK:\t$command\n";
|
15 |
+
}
|
16 |
+
return $exit_code;
|
17 |
+
}
|
18 |
+
|
19 |
+
|
20 |
+
$options = getopt( 'c:p:m:n:sa:b:u:w:df' );
|
21 |
+
if ( empty( $options ) ) {
|
22 |
+
?>
|
23 |
+
-s No branch/version directories, it's all flat
|
24 |
+
-c Application svn checkout
|
25 |
+
-p POT svn checkout
|
26 |
+
-m MakePOT project
|
27 |
+
-n POT filename
|
28 |
+
-a Relative path of application inside version dir in -c
|
29 |
+
-b Relative patch of POT dir inside version dir in -p
|
30 |
+
-u SVN username (optional)
|
31 |
+
-w SVN password (optional)
|
32 |
+
-d Dry-run
|
33 |
+
-f Fast - do not update checkouts
|
34 |
+
<?php
|
35 |
+
die;
|
36 |
+
}
|
37 |
+
|
38 |
+
$application_svn_checkout = realpath( $options['c'] );
|
39 |
+
$pot_svn_checkout = realpath( $options['p'] );
|
40 |
+
$makepot_project = str_replace( '-', '_', $options['m'] );
|
41 |
+
$pot_name = $options['n'];
|
42 |
+
$no_branch_dirs = isset( $options['s'] );
|
43 |
+
$relative_application_path = isset( $options['a'] )? '/'.$options['a'] : '';
|
44 |
+
$relative_pot_path = isset( $options['b'] )? '/'.$options['b'] : '';
|
45 |
+
$dry_run = isset( $options['d'] );
|
46 |
+
|
47 |
+
$makepot = new MakePOT;
|
48 |
+
$svn_args = array('--non-interactive');
|
49 |
+
if ( isset( $options['u'] ) && isset( $options['w'] ) ) {
|
50 |
+
$svn_args[] = '--username='.$options['u'];
|
51 |
+
$svn_args[] = '--password='.$options['w'];
|
52 |
+
$svn_args[] = '--no-auth-cache';
|
53 |
+
}
|
54 |
+
$svn_args_str = implode( ' ', array_map( 'escapeshellarg', $svn_args ) );
|
55 |
+
$svn = 'svn '.$svn_args_str;
|
56 |
+
|
57 |
+
|
58 |
+
$versions = array();
|
59 |
+
|
60 |
+
chdir( $application_svn_checkout );
|
61 |
+
if ( ! isset( $options['f'] ) ) {
|
62 |
+
$exit = silent_system( "$svn cleanup" );
|
63 |
+
if ( 0 != $exit ) die();
|
64 |
+
$exit = silent_system( "$svn up" );
|
65 |
+
if ( 0 != $exit ) die();
|
66 |
+
}
|
67 |
+
if ( is_dir( 'trunk' ) ) $versions[] = 'trunk';
|
68 |
+
$branches = glob( 'branches/*' );
|
69 |
+
if ( false !== $branches ) $versions = array_merge( $versions, $branches );
|
70 |
+
$tags = glob( 'tags/*' );
|
71 |
+
if ( false !== $tags ) $versions = array_merge( $versions, $tags );
|
72 |
+
|
73 |
+
if ( $no_branch_dirs ) {
|
74 |
+
$versions = array( '.' );
|
75 |
+
}
|
76 |
+
|
77 |
+
chdir( $pot_svn_checkout );
|
78 |
+
if ( $application_svn_checkout != $pot_svn_checkout && ! isset( $options['f'] ) ) {
|
79 |
+
$exit = silent_system( "$svn cleanup" );
|
80 |
+
if ( 0 != $exit ) die();
|
81 |
+
$exit = silent_system( "$svn up" );
|
82 |
+
if ( 0 != $exit ) die();
|
83 |
+
}
|
84 |
+
$real_application_svn_checkout = realpath( $application_svn_checkout );
|
85 |
+
foreach( $versions as $version ) {
|
86 |
+
$application_path = "$real_application_svn_checkout/$version{$relative_application_path}";
|
87 |
+
if ( !is_dir( $application_path ) ) continue;
|
88 |
+
$pot = "$version{$relative_pot_path}/$pot_name";
|
89 |
+
$exists = is_file( $pot );
|
90 |
+
// do not update old tag pots
|
91 |
+
if ( 'tags/' == substr( $version, 0, 5 ) && $exists ) continue;
|
92 |
+
if ( !is_dir( $version ) ) {
|
93 |
+
$exit = silent_system( "$svn mkdir $version" );
|
94 |
+
if ( 0 != $exit ) continue;
|
95 |
+
}
|
96 |
+
if ( !is_dir(dirname("$pot_svn_checkout/$pot")) ) continue;
|
97 |
+
if ( !call_user_func( array( &$makepot, $makepot_project ), $application_path, "$pot_svn_checkout/$pot" ) ) continue;
|
98 |
+
if ( !file_exists( "$pot_svn_checkout/$pot" ) ) continue;
|
99 |
+
if ( !$exists ) {
|
100 |
+
$exit = silent_system( "$svn add $pot" );
|
101 |
+
if ( 0 != $exit ) continue;
|
102 |
+
}
|
103 |
+
// do not commit if the difference is only in the header, but always commit a new file
|
104 |
+
$real_differences = `svn diff $pot | wc -l` > 16;
|
105 |
+
$target = $exists ? $pot : $version;
|
106 |
+
if ( !$exists || $real_differences ) {
|
107 |
+
preg_match( '/Revision:\s+(\d+)/', `svn info $application_path`, $matches );
|
108 |
+
$logmsg = isset( $matches[1] ) && intval( $matches[1] )? "POT, generated from r".intval( $matches[1] ) : 'Automatic POT update';
|
109 |
+
$command = "$svn ci $target --non-interactive --message='$logmsg'";
|
110 |
+
if ( !$dry_run )
|
111 |
+
silent_system( $command );
|
112 |
+
else
|
113 |
+
echo "CMD:\t$command\n";
|
114 |
+
} else {
|
115 |
+
silent_system( "$svn revert $target" );
|
116 |
+
}
|
117 |
+
}
|
src/vendor/websharks/wp-i18n-tools/extract/ExtractTest.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once dirname( __FILE__ ) . '/extract.php';
|
4 |
+
|
5 |
+
class ExtractTest extends PHPUnit_Framework_TestCase {
|
6 |
+
|
7 |
+
function setUp() {
|
8 |
+
$this->extractor = new StringExtractor;
|
9 |
+
$this->extractor->rules = array(
|
10 |
+
'__' => array('string'),
|
11 |
+
);
|
12 |
+
}
|
13 |
+
|
14 |
+
function test_with_just_a_string() {
|
15 |
+
$expected = new Translation_Entry( array( 'singular' => 'baba', 'references' => array('baba.php:1') ) );
|
16 |
+
$result = $this->extractor->extract_entries('<?php __("baba"); ?>', 'baba.php' );
|
17 |
+
$this->assertEquals( $expected, $result->entries['baba'] );
|
18 |
+
}
|
19 |
+
|
20 |
+
function test_entry_from_call_simple() {
|
21 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba') ), 'baba.php' );
|
22 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba' ) ) );
|
23 |
+
}
|
24 |
+
|
25 |
+
function test_entry_from_call_nonexisting_function() {
|
26 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => 'f', 'args' => array('baba') ), 'baba.php' );
|
27 |
+
$this->assertEquals( $entry, null );
|
28 |
+
}
|
29 |
+
|
30 |
+
function test_entry_from_call_too_few_args() {
|
31 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array() ), 'baba.php' );
|
32 |
+
$this->assertEquals( $entry, null );
|
33 |
+
}
|
34 |
+
|
35 |
+
function test_entry_from_call_non_expected_null_arg() {
|
36 |
+
$this->extractor->rules = array( '_nx' => array( 'singular', 'plural', 'context' ) );
|
37 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '_nx', 'args' => array('%s baba', null, 'noun') ), 'baba.php' );
|
38 |
+
$this->assertEquals( $entry, null );
|
39 |
+
}
|
40 |
+
|
41 |
+
function test_entry_from_call_more_args_should_be_ok() {
|
42 |
+
$this->extractor->rules = array( '__' => array('string') );
|
43 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba', 5, 'pijo', null) ), 'baba.php' );
|
44 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba' ) ) );
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
function test_entry_from_call_context() {
|
49 |
+
$this->extractor->rules = array( '_x' => array( 'string', 'context' ) );
|
50 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '_x', 'args' => array('baba', 'noun') ), 'baba.php' );
|
51 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba', 'context' => 'noun' ) ) );
|
52 |
+
}
|
53 |
+
|
54 |
+
function test_entry_from_call_plural() {
|
55 |
+
$this->extractor->rules = array( '_n' => array( 'singular', 'plural' ) );
|
56 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '_n', 'args' => array('%s baba', '%s babas') ), 'baba.php' );
|
57 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => '%s baba', 'plural' => '%s babas' ) ) );
|
58 |
+
}
|
59 |
+
|
60 |
+
function test_entry_from_call_plural_and_context() {
|
61 |
+
$this->extractor->rules = array( '_nx' => array( 'singular', 'plural', 'context' ) );
|
62 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '_nx', 'args' => array('%s baba', '%s babas', 'noun') ), 'baba.php' );
|
63 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => '%s baba', 'plural' => '%s babas', 'context' => 'noun' ) ) );
|
64 |
+
}
|
65 |
+
|
66 |
+
function test_entry_from_call_extracted_comment() {
|
67 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba'), 'comment' => 'translators: give me back my pants!' ), 'baba.php' );
|
68 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba', 'extracted_comments' => "translators: give me back my pants!\n" ) ) );
|
69 |
+
}
|
70 |
+
|
71 |
+
function test_entry_from_call_line_number() {
|
72 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('baba'), 'line' => 10 ), 'baba.php' );
|
73 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => 'baba', 'references' => array('baba.php:10') ) ) );
|
74 |
+
}
|
75 |
+
|
76 |
+
function test_entry_from_call_zero() {
|
77 |
+
$entry = $this->extractor->entry_from_call( array( 'name' => '__', 'args' => array('0') ), 'baba.php' );
|
78 |
+
$this->assertEquals( $entry, new Translation_Entry( array( 'singular' => '0' ) ) );
|
79 |
+
}
|
80 |
+
|
81 |
+
function test_entry_from_call_multiple() {
|
82 |
+
$this->extractor->rules = array( 'c' => array( 'string', 'singular', 'plural' ) );
|
83 |
+
$entries = $this->extractor->entry_from_call( array( 'name' => 'c', 'args' => array('baba', 'dyado', 'dyados') ), 'baba.php' );
|
84 |
+
$this->assertEquals( array(
|
85 |
+
new Translation_Entry( array( 'singular' => 'baba' ) ), new Translation_Entry( array( 'singular' => 'dyado', 'plural' => 'dyados' ) ) ), $entries );
|
86 |
+
}
|
87 |
+
|
88 |
+
function test_entry_from_call_multiple_first_plural_then_two_strings() {
|
89 |
+
$this->extractor->rules = array( 'c' => array( 'singular', 'plural', null, 'string', 'string' ) );
|
90 |
+
$entries = $this->extractor->entry_from_call( array( 'name' => 'c', 'args' => array('dyado', 'dyados', 'baba', 'foo', 'bar') ), 'baba.php' );
|
91 |
+
$this->assertEquals( array(
|
92 |
+
new Translation_Entry( array( 'singular' => 'dyado', 'plural' => 'dyados' ) ),
|
93 |
+
new Translation_Entry( array( 'singular' => 'foo' ) ),
|
94 |
+
new Translation_Entry( array( 'singular' => 'bar' ) ) ), $entries );
|
95 |
+
}
|
96 |
+
|
97 |
+
function test_find_function_calls_one_arg_literal() {
|
98 |
+
$this->assertEquals( array( array( 'name' => '__', 'args' => array( 'baba' ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('__'), '<?php __("baba"); ?>' ) );
|
99 |
+
}
|
100 |
+
|
101 |
+
function test_find_function_calls_one_arg_zero() {
|
102 |
+
$this->assertEquals( array( array( 'name' => '__', 'args' => array( '0' ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('__'), '<?php __("0"); ?>' ) );
|
103 |
+
}
|
104 |
+
|
105 |
+
function test_find_function_calls_one_arg_non_literal() {
|
106 |
+
$this->assertEquals( array( array( 'name' => '__', 'args' => array( null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('__'), '<?php __("baba" . "dudu"); ?>' ) );
|
107 |
+
}
|
108 |
+
|
109 |
+
function test_find_function_calls_shouldnt_be_mistaken_by_a_class() {
|
110 |
+
$this->assertEquals( array(), $this->extractor->find_function_calls( array('__'), '<?php class __ { }; ("dyado");' ) );
|
111 |
+
}
|
112 |
+
|
113 |
+
function test_find_function_calls_2_args_bad_literal() {
|
114 |
+
$this->assertEquals( array( array( 'name' => 'f', 'args' => array( null, "baba" ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f(5, "baba" ); ' ) );
|
115 |
+
}
|
116 |
+
|
117 |
+
function test_find_function_calls_2_args_bad_literal_bad() {
|
118 |
+
$this->assertEquals( array( array( 'name' => 'f', 'args' => array( null, "baba", null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f(5, "baba", 5 ); ' ) );
|
119 |
+
}
|
120 |
+
|
121 |
+
function test_find_function_calls_1_arg_bad_concat() {
|
122 |
+
$this->assertEquals( array( array( 'name' => 'f', 'args' => array( null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( "baba" . "baba" ); ' ) );
|
123 |
+
}
|
124 |
+
|
125 |
+
function test_find_function_calls_1_arg_bad_function_call() {
|
126 |
+
$this->assertEquals( array( array( 'name' => 'f', 'args' => array( null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( g( "baba" ) ); ' ) );
|
127 |
+
}
|
128 |
+
|
129 |
+
function test_find_function_calls_2_arg_literal_bad() {
|
130 |
+
$this->assertEquals( array( array( 'name' => 'f', 'args' => array( "baba", null ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( "baba", null ); ' ) );
|
131 |
+
}
|
132 |
+
|
133 |
+
function test_find_function_calls_2_arg_bad_with_parens_literal() {
|
134 |
+
$this->assertEquals( array( array( 'name' => 'f', 'args' => array( null, "baba" ), 'line' => 1 ) ), $this->extractor->find_function_calls( array('f'), '<?php f( g( "dyado", "chicho", "lelya "), "baba" ); ' ) );
|
135 |
+
}
|
136 |
+
|
137 |
+
function test_find_function_calls_with_comment() {
|
138 |
+
$this->assertEquals(
|
139 |
+
array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'translators: let your ears fly!' ) ),
|
140 |
+
$this->extractor->find_function_calls( array('f'), '<?php /* translators: let your ears fly! */ f( "baba" ); ' ) );
|
141 |
+
}
|
142 |
+
|
143 |
+
function test_find_function_calls_with_not_immediate_comment() {
|
144 |
+
$this->assertEquals(
|
145 |
+
array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'translators: let your ears fly!' ) ),
|
146 |
+
$this->extractor->find_function_calls( array('f'), '<?php /* translators: let your ears fly! */ $foo = g ( f( "baba" ) ); ' ) );
|
147 |
+
}
|
148 |
+
|
149 |
+
function test_find_function_calls_with_not_immediate_comment_include_only_latest() {
|
150 |
+
$this->assertEquals(
|
151 |
+
array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'translators: let your ears fly!' ) ),
|
152 |
+
$this->extractor->find_function_calls( array('f'), '<?php /* translators: boo */ /* translators: let your ears fly! */ /* baba */ $foo = g ( f( "baba" ) ); ' ) );
|
153 |
+
}
|
154 |
+
|
155 |
+
function test_comment_prefix_should_be_case_insensitive() {
|
156 |
+
$this->assertEquals(
|
157 |
+
array( array( 'name' => 'f', 'args' => array( 'baba' ), 'line' => 1, 'comment' => 'Translators: let your ears fly!' ) ),
|
158 |
+
$this->extractor->find_function_calls( array('f'), '<?php /* Translators: let your ears fly! */ f( "baba" ); ' ) );
|
159 |
+
}
|
160 |
+
}
|
src/vendor/websharks/wp-i18n-tools/extract/TODO
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
* php-format
|
src/vendor/websharks/wp-i18n-tools/extract/extract.php
ADDED
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once dirname( __FILE__ ) . '/../pomo/entry.php';
|
3 |
+
require_once dirname( __FILE__ ) . '/../pomo/translations.php';
|
4 |
+
|
5 |
+
class StringExtractor {
|
6 |
+
|
7 |
+
var $rules = array();
|
8 |
+
var $comment_prefix = 'translators:';
|
9 |
+
|
10 |
+
function __construct( $rules = array() ) {
|
11 |
+
$this->rules = $rules;
|
12 |
+
}
|
13 |
+
|
14 |
+
function extract_from_directory( $dir, $excludes = array(), $includes = array(), $prefix = '' ) {
|
15 |
+
$old_cwd = getcwd();
|
16 |
+
chdir( $dir );
|
17 |
+
$translations = new Translations;
|
18 |
+
$file_names = (array) scandir( '.' );
|
19 |
+
foreach ( $file_names as $file_name ) {
|
20 |
+
if ( '.' == $file_name || '..' == $file_name ) continue;
|
21 |
+
if ( preg_match( '/\.(?:php|js)$/', $file_name ) && $this->does_file_name_match( $prefix . $file_name, $excludes, $includes ) ) {
|
22 |
+
$translations->merge_originals_with( $this->extract_from_file( $file_name, $prefix ) );
|
23 |
+
}
|
24 |
+
if ( is_dir( $file_name ) ) {
|
25 |
+
$translations->merge_originals_with( $this->extract_from_directory( $file_name, $excludes, $includes, $prefix . $file_name . '/' ) );
|
26 |
+
}
|
27 |
+
}
|
28 |
+
chdir( $old_cwd );
|
29 |
+
return $translations;
|
30 |
+
}
|
31 |
+
|
32 |
+
function extract_from_file( $file_name, $prefix ) {
|
33 |
+
$code = file_get_contents( $file_name );
|
34 |
+
return $this->extract_entries( $code, $prefix . $file_name );
|
35 |
+
}
|
36 |
+
|
37 |
+
function does_file_name_match( $path, $excludes, $includes ) {
|
38 |
+
if ( $includes ) {
|
39 |
+
$matched_any_include = false;
|
40 |
+
foreach( $includes as $include ) {
|
41 |
+
if ( preg_match( '|^'.$include.'$|', $path ) ) {
|
42 |
+
$matched_any_include = true;
|
43 |
+
break;
|
44 |
+
}
|
45 |
+
}
|
46 |
+
if ( !$matched_any_include ) return false;
|
47 |
+
}
|
48 |
+
if ( $excludes ) {
|
49 |
+
foreach( $excludes as $exclude ) {
|
50 |
+
if ( preg_match( '|^'.$exclude.'$|', $path ) ) {
|
51 |
+
return false;
|
52 |
+
}
|
53 |
+
}
|
54 |
+
}
|
55 |
+
return true;
|
56 |
+
}
|
57 |
+
|
58 |
+
function entry_from_call( $call, $file_name ) {
|
59 |
+
$rule = isset( $this->rules[$call['name']] )? $this->rules[$call['name']] : null;
|
60 |
+
if ( !$rule ) return null;
|
61 |
+
$entry = new Translation_Entry;
|
62 |
+
$multiple = array();
|
63 |
+
$complete = false;
|
64 |
+
for( $i = 0; $i < count( $rule ); ++$i ) {
|
65 |
+
if ( $rule[$i] && ( !isset( $call['args'][$i] ) || !is_string( $call['args'][$i] ) || '' == $call['args'][$i] ) ) return false;
|
66 |
+
switch( $rule[$i] ) {
|
67 |
+
case 'string':
|
68 |
+
if ( $complete ) {
|
69 |
+
$multiple[] = $entry;
|
70 |
+
$entry = new Translation_Entry;
|
71 |
+
$complete = false;
|
72 |
+
}
|
73 |
+
$entry->singular = $call['args'][$i];
|
74 |
+
$complete = true;
|
75 |
+
break;
|
76 |
+
case 'singular':
|
77 |
+
if ( $complete ) {
|
78 |
+
$multiple[] = $entry;
|
79 |
+
$entry = new Translation_Entry;
|
80 |
+
$complete = false;
|
81 |
+
}
|
82 |
+
$entry->singular = $call['args'][$i];
|
83 |
+
$entry->is_plural = true;
|
84 |
+
break;
|
85 |
+
case 'plural':
|
86 |
+
$entry->plural = $call['args'][$i];
|
87 |
+
$entry->is_plural = true;
|
88 |
+
$complete = true;
|
89 |
+
break;
|
90 |
+
case 'context':
|
91 |
+
$entry->context = $call['args'][$i];
|
92 |
+
foreach( $multiple as &$single_entry ) {
|
93 |
+
$single_entry->context = $entry->context;
|
94 |
+
}
|
95 |
+
break;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
if ( isset( $call['line'] ) && $call['line'] ) {
|
99 |
+
$references = array( $file_name . ':' . $call['line'] );
|
100 |
+
$entry->references = $references;
|
101 |
+
foreach( $multiple as &$single_entry ) {
|
102 |
+
$single_entry->references = $references;
|
103 |
+
}
|
104 |
+
}
|
105 |
+
if ( isset( $call['comment'] ) && $call['comment'] ) {
|
106 |
+
$comments = rtrim( $call['comment'] ) . "\n";
|
107 |
+
$entry->extracted_comments = $comments;
|
108 |
+
foreach( $multiple as &$single_entry ) {
|
109 |
+
$single_entry->extracted_comments = $comments;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
if ( $multiple && $entry ) {
|
113 |
+
$multiple[] = $entry;
|
114 |
+
return $multiple;
|
115 |
+
}
|
116 |
+
|
117 |
+
return $entry;
|
118 |
+
}
|
119 |
+
|
120 |
+
function extract_entries( $code, $file_name ) {
|
121 |
+
$translations = new Translations;
|
122 |
+
$function_calls = $this->find_function_calls( array_keys( $this->rules ), $code );
|
123 |
+
foreach( $function_calls as $call ) {
|
124 |
+
$entry = $this->entry_from_call( $call, $file_name );
|
125 |
+
if ( is_array( $entry ) )
|
126 |
+
foreach( $entry as $single_entry )
|
127 |
+
$translations->add_entry_or_merge( $single_entry );
|
128 |
+
elseif ( $entry)
|
129 |
+
$translations->add_entry_or_merge( $entry );
|
130 |
+
}
|
131 |
+
return $translations;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Finds all function calls in $code and returns an array with an associative array for each function:
|
136 |
+
* - name - name of the function
|
137 |
+
* - args - array for the function arguments. Each string literal is represented by itself, other arguments are represented by null.
|
138 |
+
* - line - line number
|
139 |
+
*/
|
140 |
+
function find_function_calls( $function_names, $code ) {
|
141 |
+
$tokens = token_get_all( $code );
|
142 |
+
$function_calls = array();
|
143 |
+
$latest_comment = false;
|
144 |
+
$in_func = false;
|
145 |
+
foreach( $tokens as $token ) {
|
146 |
+
$id = $text = null;
|
147 |
+
if ( is_array( $token ) ) list( $id, $text, $line ) = $token;
|
148 |
+
if ( T_WHITESPACE == $id ) continue;
|
149 |
+
if ( T_STRING == $id && in_array( $text, $function_names ) && !$in_func ) {
|
150 |
+
$in_func = true;
|
151 |
+
$paren_level = -1;
|
152 |
+
$args = array();
|
153 |
+
$func_name = $text;
|
154 |
+
$func_line = $line;
|
155 |
+
$func_comment = $latest_comment? $latest_comment : '';
|
156 |
+
|
157 |
+
$just_got_into_func = true;
|
158 |
+
$latest_comment = false;
|
159 |
+
continue;
|
160 |
+
}
|
161 |
+
if ( T_COMMENT == $id ) {
|
162 |
+
$text = trim( preg_replace( '%^/\*|//%', '', preg_replace( '%\*/$%', '', $text ) ) );
|
163 |
+
if ( 0 === stripos( $tex
|