From ecbf5abf7e81543d383415d4bed9ef0bc4884d17 Mon Sep 17 00:00:00 2001 From: Raam Dev Date: Fri, 26 Jun 2015 20:03:51 -0400 Subject: [PATCH] = v150626 = MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - **Restructured Codebase**: The entire ZenCache codebase has been restructured to improve performance, enhance flexibility, and make it easier to build in new features! - **New Feature!** The free version of ZenCache now supports several new options that were previously only available in the Pro version. You can now toggle the Auto-Clear Cache routines for the Home Page, Posts Page, Author Page, Category Archives, Tag Archives, Custom Term Archives, RSS/RDF/Atom Feeds, and XML Sitemaps. This gives you more control over exactly when ZenCache purges the cache for these parts of your site. See _ZenCache → Plugin Options → Clearing the Cache_ for further details. - **New Feature!** URI Exclusion Patterns are now available in ZenCache Lite! This previously Pro-only feature is now available in the free version of ZenCache and allows you to exclude a list of URIs from being cached by ZenCache. See _ZenCache → Plugin Options → URI Exclusion Patterns_ for further details. - **New Feature!** HTTP Referrer Exclusion Patterns are now available in ZenCache Lite! This previously Pro-only feature is now available in the free version of ZenCache and allows you to define a list of referring URLs or domains that send you traffic. When ZenCache sees a request coming from one of those URLs or domains, it will not cache that particular request. See _ZenCache → Plugin Options → HTTP Referrer Exclusion Patterns_ for further details. - **New Pro Feature!**: HTML Compression now supports compressing JSON (in addition to the already supported HTML, JavaScript, and CSS compression). Props @jaswsinc. See [Issue #469](https://github.com/websharks/zencache/issues/469). - **New Pro Feature!**: Static CDN Filters now supports multiple CDN hostnames. This allows you to configure more than one CDN hostname, also referred to as Domain Sharding. This makes it possible for site owners to work around web browser concurrency limits, allowing the browser to download many resources simultaneously, which increases overall speed. Props to @isaumya and @jaswsinc. See [Issue #468](https://github.com/websharks/zencache/issues/468). - **Enhancement** (Pro): Static CDN Filters now includes proper support for WordPress Multisite Networks, including support for subdomains (full support for Domain Mapping coming in the next release). If you're running a WordPress Multisite Network and want to configure a CDN, see [this KB Article](http://zencache.com/kb-article/static-cdn-filters-for-wordpress-multisite-networks/) for further details. - **Enhancement** (Pro): Static CDN Filters now also apply to any static files that are referenced inside CSS files. Props @jaswsinc. See [Issue #461](https://github.com/websharks/zencache/issues/461). - **Enhancement**: Completed a major restructure of the entire codebase to improve modularity and dependency management. Props @jaswsinc. - **Enhancement** (Pro): Static CDN Filters now supports the ability to configure separate CDN hostname(s) for each domain (or subdomain) that you run in a WordPress Multisite Network. Props @jaswsinc. See [Issue #475](https://github.com/websharks/zencache/issues/475). - **Enhancement** (Pro): Static CDN Filters now support subdomains when ZenCache is running inside a WordPress Multisite Network. Props @jaswsinc. See [Issue #439](https://github.com/websharks/zencache/issues/439). - **Bug Fix** (Pro): Static CDN Filters were not being applied to the primary site on WP Multisite installations that used subdomains. Props to @isaumya for discovering this bug. See [Issue #470](https://github.com/websharks/zencache/issues/470). --- .build.properties | 16 + .build.xml | 883 ++++++ .gitchange | 1 + CHANGELOG.md | 12 +- README.md | 6 - apigen.neon | 11 - readme.txt | 17 +- src/client-s/images/keycdn-logo.png | Bin 0 -> 7061 bytes src/includes/classes/ApiBase.php | 16 + src/includes/classes/MenuPageOptions.php | 13 +- src/includes/closures/Plugin/WcpPostUtils.php | 1 + src/includes/closures/Plugin/WcpUtils.php | 3 + src/includes/stub.php | 2 +- src/includes/translations/zencache-pro.pot | 114 +- src/includes/translations/zencache.pot | 114 +- src/vendor/autoload.php | 2 +- src/vendor/composer/autoload_real.php | 8 +- zencache.php | 2 +- zencache/CHANGELOG | 314 --- zencache/client-s/css/menu-pages.css | 449 --- zencache/client-s/css/menu-pages.min.css | 1 - zencache/client-s/images/auto-clear-ss.png | Bin 14401 -> 0 bytes zencache/client-s/images/bg.png | Bin 5814 -> 0 bytes zencache/client-s/images/clear-cache-ss.png | Bin 4074 -> 0 bytes zencache/client-s/images/clear-response.png | Bin 2348 -> 0 bytes zencache/client-s/images/clear.png | Bin 702 -> 0 bytes zencache/client-s/images/cloudfront-logo.png | Bin 14879 -> 0 bytes zencache/client-s/images/gzip.png | Bin 13333 -> 0 bytes zencache/client-s/images/inline-icon-logo.svg | 12 - zencache/client-s/images/inline-icon.svg | 5 - zencache/client-s/images/maxcdn-logo.png | Bin 5730 -> 0 bytes zencache/client-s/images/options.png | Bin 10462 -> 0 bytes zencache/client-s/images/salt.png | Bin 17415 -> 0 bytes zencache/client-s/images/source-code-ss.png | Bin 45258 -> 0 bytes zencache/client-s/images/tach.png | Bin 19027 -> 0 bytes zencache/client-s/images/updater.png | Bin 10390 -> 0 bytes zencache/client-s/images/wipe-response.png | Bin 3452 -> 0 bytes zencache/client-s/images/wipe.png | Bin 898 -> 0 bytes zencache/client-s/js/menu-pages.js | 45 - zencache/client-s/js/menu-pages.min.js | 1 - zencache/includes/.htaccess | 6 - zencache/includes/ac-plugin.example.php | 43 - zencache/includes/actions.php | 188 -- zencache/includes/advanced-cache.tpl.php | 1217 -------- zencache/includes/api-class.php | 93 - zencache/includes/conflicts-check.php | 50 - zencache/includes/gzip-htaccess.tpl.txt | 10 - zencache/includes/menu-pages.php | 756 ----- zencache/includes/share.php | 2378 ---------------- zencache/includes/translations/zencache.pot | 1398 ---------- zencache/includes/utils-feed.php | 306 -- .../includes/version-specific-upgrade.php | 248 -- zencache/licensing/.htaccess | 6 - zencache/licensing/gpl.txt | 339 --- zencache/licensing/license.txt | 18 - zencache/readme.txt | 422 --- zencache/submodules/.htaccess | 15 - zencache/submodules/sharkicons | 1 - zencache/submodules/wp-php-rv | 1 - zencache/uninstall.inc.php | 46 - zencache/uninstall.php | 15 - zencache/zencache.inc.php | 2464 ----------------- zencache/zencache.php | 20 - 63 files changed, 1070 insertions(+), 11018 deletions(-) create mode 100644 .build.properties create mode 100644 .build.xml create mode 100644 .gitchange delete mode 100644 apigen.neon create mode 100644 src/client-s/images/keycdn-logo.png delete mode 100644 zencache/CHANGELOG delete mode 100644 zencache/client-s/css/menu-pages.css delete mode 100644 zencache/client-s/css/menu-pages.min.css delete mode 100644 zencache/client-s/images/auto-clear-ss.png delete mode 100644 zencache/client-s/images/bg.png delete mode 100644 zencache/client-s/images/clear-cache-ss.png delete mode 100644 zencache/client-s/images/clear-response.png delete mode 100644 zencache/client-s/images/clear.png delete mode 100644 zencache/client-s/images/cloudfront-logo.png delete mode 100644 zencache/client-s/images/gzip.png delete mode 100644 zencache/client-s/images/inline-icon-logo.svg delete mode 100644 zencache/client-s/images/inline-icon.svg delete mode 100644 zencache/client-s/images/maxcdn-logo.png delete mode 100644 zencache/client-s/images/options.png delete mode 100644 zencache/client-s/images/salt.png delete mode 100644 zencache/client-s/images/source-code-ss.png delete mode 100644 zencache/client-s/images/tach.png delete mode 100644 zencache/client-s/images/updater.png delete mode 100644 zencache/client-s/images/wipe-response.png delete mode 100644 zencache/client-s/images/wipe.png delete mode 100644 zencache/client-s/js/menu-pages.js delete mode 100644 zencache/client-s/js/menu-pages.min.js delete mode 100644 zencache/includes/.htaccess delete mode 100644 zencache/includes/ac-plugin.example.php delete mode 100644 zencache/includes/actions.php delete mode 100644 zencache/includes/advanced-cache.tpl.php delete mode 100644 zencache/includes/api-class.php delete mode 100644 zencache/includes/conflicts-check.php delete mode 100644 zencache/includes/gzip-htaccess.tpl.txt delete mode 100644 zencache/includes/menu-pages.php delete mode 100644 zencache/includes/share.php delete mode 100644 zencache/includes/translations/zencache.pot delete mode 100644 zencache/includes/utils-feed.php delete mode 100644 zencache/includes/version-specific-upgrade.php delete mode 100644 zencache/licensing/.htaccess delete mode 100644 zencache/licensing/gpl.txt delete mode 100644 zencache/licensing/license.txt delete mode 100644 zencache/readme.txt delete mode 100644 zencache/submodules/.htaccess delete mode 160000 zencache/submodules/sharkicons delete mode 160000 zencache/submodules/wp-php-rv delete mode 100644 zencache/uninstall.inc.php delete mode 100644 zencache/uninstall.php delete mode 100644 zencache/zencache.inc.php delete mode 100644 zencache/zencache.php diff --git a/.build.properties b/.build.properties new file mode 100644 index 0000000..46b4b29 --- /dev/null +++ b/.build.properties @@ -0,0 +1,16 @@ + +project_org = websharks + + + + +project_title = ZenCache +project_slug = zencache +project_ns = WebSharks\\ZenCache +project_sns = ZenCache + +project_version = %y%m%d +project_php_required_version = 5.3.2 +project_php_up_to_version = ${php.version} +project_wp_required_version = 4.1 +project_wp_up_to_version = 4.3-beta diff --git a/.build.xml b/.build.xml new file mode 100644 index 0000000..9a783c2 --- /dev/null +++ b/.build.xml @@ -0,0 +1,883 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitchange b/.gitchange new file mode 100644 index 0000000..5e5fb49 --- /dev/null +++ b/.gitchange @@ -0,0 +1 @@ +1435130761 diff --git a/CHANGELOG.md b/CHANGELOG.md index bae3039..afc85b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,17 @@ -= v150605 = - -**RELEASE CANDIDATE** += v150626 = +- **Restructured Codebase**: The entire ZenCache codebase has been restructured to improve performance, enhance flexibility, and make it easier to build in new features! - **New Feature!** The free version of ZenCache now supports several new options that were previously only available in the Pro version. You can now toggle the Auto-Clear Cache routines for the Home Page, Posts Page, Author Page, Category Archives, Tag Archives, Custom Term Archives, RSS/RDF/Atom Feeds, and XML Sitemaps. This gives you more control over exactly when ZenCache purges the cache for these parts of your site. See _ZenCache → Plugin Options → Clearing the Cache_ for further details. - **New Feature!** URI Exclusion Patterns are now available in ZenCache Lite! This previously Pro-only feature is now available in the free version of ZenCache and allows you to exclude a list of URIs from being cached by ZenCache. See _ZenCache → Plugin Options → URI Exclusion Patterns_ for further details. - **New Feature!** HTTP Referrer Exclusion Patterns are now available in ZenCache Lite! This previously Pro-only feature is now available in the free version of ZenCache and allows you to define a list of referring URLs or domains that send you traffic. When ZenCache sees a request coming from one of those URLs or domains, it will not cache that particular request. See _ZenCache → Plugin Options → HTTP Referrer Exclusion Patterns_ for further details. - **New Pro Feature!**: HTML Compression now supports compressing JSON (in addition to the already supported HTML, JavaScript, and CSS compression). Props @jaswsinc. See [Issue #469](https://github.com/websharks/zencache/issues/469). - **New Pro Feature!**: Static CDN Filters now supports multiple CDN hostnames. This allows you to configure more than one CDN hostname, also referred to as Domain Sharding. This makes it possible for site owners to work around web browser concurrency limits, allowing the browser to download many resources simultaneously, which increases overall speed. Props to @isaumya and @jaswsinc. See [Issue #468](https://github.com/websharks/zencache/issues/468). +- **Enhancement** (Pro): Static CDN Filters now includes proper support for WordPress Multisite Networks, including support for subdomains (full support for Domain Mapping coming in the next release). If you're running a WordPress Multisite Network and want to configure a CDN, see [this KB Article](http://zencache.com/kb-article/static-cdn-filters-for-wordpress-multisite-networks/) for further details. - **Enhancement** (Pro): Static CDN Filters now also apply to any static files that are referenced inside CSS files. Props @jaswsinc. See [Issue #461](https://github.com/websharks/zencache/issues/461). - **Enhancement**: Completed a major restructure of the entire codebase to improve modularity and dependency management. Props @jaswsinc. -- **Enhancement** (Pro): Static CDN Filters now supports the ability to configure separate CDN hostname(s) for each domain (or sub-domain) that you run in a WordPress Multisite Network. Props @jaswsinc. See [Issue #475](https://github.com/websharks/zencache/issues/475). -- **Enhancement** (Pro): Static CDN Filters now support sub-domains when ZenCache is running inside a WordPress Multisite Network. Props @jaswsinc. See [Issue #439](https://github.com/websharks/zencache/issues/439). -- **Bug Fix** (Pro): Static CDN Filters were not being applied to the primary site on WP Multisite installations that used subdomains. (While subdomains are not currently supported by Static CDN Filters, the primary site can still use this feature.) Props to @isaumya for discovering this bug. See [Issue #470](https://github.com/websharks/zencache/issues/470). +- **Enhancement** (Pro): Static CDN Filters now supports the ability to configure separate CDN hostname(s) for each domain (or subdomain) that you run in a WordPress Multisite Network. Props @jaswsinc. See [Issue #475](https://github.com/websharks/zencache/issues/475). +- **Enhancement** (Pro): Static CDN Filters now support subdomains when ZenCache is running inside a WordPress Multisite Network. Props @jaswsinc. See [Issue #439](https://github.com/websharks/zencache/issues/439). +- **Bug Fix** (Pro): Static CDN Filters were not being applied to the primary site on WP Multisite installations that used subdomains. Props to @isaumya for discovering this bug. See [Issue #470](https://github.com/websharks/zencache/issues/470). = v140829 = diff --git a/README.md b/README.md index 5ff5cb6..b80e28c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,3 @@ ## ZenCache Caching plugin for WordPress®. - ---- - -### Throughput Graph (powered by waffle.io) - -[![Throughput Graph](https://graphs.waffle.io/websharks/zencache/throughput.svg)](https://waffle.io/websharks/zencache/metrics) \ No newline at end of file diff --git a/apigen.neon b/apigen.neon deleted file mode 100644 index 858f6c7..0000000 --- a/apigen.neon +++ /dev/null @@ -1,11 +0,0 @@ -source: . -destination: codex -extensions: [php,phar] -title: ZenCache Lite -exclude: [*/externals/*,*/unit-tests/*,*example.php] -accessLevels: [public,protected,private] -deprecated: yes -todo: yes -download: yes -debug: yes -php: no \ No newline at end of file diff --git a/readme.txt b/readme.txt index 7a42096..cbab4cc 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ === ZenCache === -Stable tag: 150605 +Stable tag: 150626 Requires at least: 4.1 Tested up to: 4.3-beta Text Domain: zencache @@ -328,6 +328,21 @@ Requires PHP v5.3.2+. The latest version of ZenCache is a complete rewrite (OOP == Changelog == += v150626 = + +- **Restructured Codebase**: The entire ZenCache codebase has been restructured to improve performance, enhance flexibility, and make it easier to build in new features! +- **New Feature!** The free version of ZenCache now supports several new options that were previously only available in the Pro version. You can now toggle the Auto-Clear Cache routines for the Home Page, Posts Page, Author Page, Category Archives, Tag Archives, Custom Term Archives, RSS/RDF/Atom Feeds, and XML Sitemaps. This gives you more control over exactly when ZenCache purges the cache for these parts of your site. See _ZenCache → Plugin Options → Clearing the Cache_ for further details. +- **New Feature!** URI Exclusion Patterns are now available in ZenCache Lite! This previously Pro-only feature is now available in the free version of ZenCache and allows you to exclude a list of URIs from being cached by ZenCache. See _ZenCache → Plugin Options → URI Exclusion Patterns_ for further details. +- **New Feature!** HTTP Referrer Exclusion Patterns are now available in ZenCache Lite! This previously Pro-only feature is now available in the free version of ZenCache and allows you to define a list of referring URLs or domains that send you traffic. When ZenCache sees a request coming from one of those URLs or domains, it will not cache that particular request. See _ZenCache → Plugin Options → HTTP Referrer Exclusion Patterns_ for further details. +- **New Pro Feature!**: HTML Compression now supports compressing JSON (in addition to the already supported HTML, JavaScript, and CSS compression). Props @jaswsinc. See [Issue #469](https://github.com/websharks/zencache/issues/469). +- **New Pro Feature!**: Static CDN Filters now supports multiple CDN hostnames. This allows you to configure more than one CDN hostname, also referred to as Domain Sharding. This makes it possible for site owners to work around web browser concurrency limits, allowing the browser to download many resources simultaneously, which increases overall speed. Props to @isaumya and @jaswsinc. See [Issue #468](https://github.com/websharks/zencache/issues/468). +- **Enhancement** (Pro): Static CDN Filters now includes proper support for WordPress Multisite Networks, including support for subdomains (full support for Domain Mapping coming in the next release). If you're running a WordPress Multisite Network and want to configure a CDN, see [this KB Article](http://zencache.com/kb-article/static-cdn-filters-for-wordpress-multisite-networks/) for further details. +- **Enhancement** (Pro): Static CDN Filters now also apply to any static files that are referenced inside CSS files. Props @jaswsinc. See [Issue #461](https://github.com/websharks/zencache/issues/461). +- **Enhancement**: Completed a major restructure of the entire codebase to improve modularity and dependency management. Props @jaswsinc. +- **Enhancement** (Pro): Static CDN Filters now supports the ability to configure separate CDN hostname(s) for each domain (or subdomain) that you run in a WordPress Multisite Network. Props @jaswsinc. See [Issue #475](https://github.com/websharks/zencache/issues/475). +- **Enhancement** (Pro): Static CDN Filters now support subdomains when ZenCache is running inside a WordPress Multisite Network. Props @jaswsinc. See [Issue #439](https://github.com/websharks/zencache/issues/439). +- **Bug Fix** (Pro): Static CDN Filters were not being applied to the primary site on WP Multisite installations that used subdomains. Props to @isaumya for discovering this bug. See [Issue #470](https://github.com/websharks/zencache/issues/470). + = v150409 = - **Enhancement (includes improved CloudFlare support)**: Improvements to IP address detection, including added support for CloudFlare IP forwarding, multiple IPs in a single header, and the ability to customize the lookup order and/or add/remove sources that are searched when looking for the current IP address. It's also possible to revert to the old IP address detection behavior (see [How do I customize remote IP detection?](http://zencache.com/kb-article/how-do-i-customize-ip-address-detection/)). Props @jaswsinc. [Issue #449](https://github.com/websharks/zencache/pull/449) diff --git a/src/client-s/images/keycdn-logo.png b/src/client-s/images/keycdn-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9443dc7fd2957069194af74b4cd5faefcad93851 GIT binary patch literal 7061 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 literal 0 HcmV?d00001 diff --git a/src/includes/classes/ApiBase.php b/src/includes/classes/ApiBase.php index 939601a..0ba8af9 100644 --- a/src/includes/classes/ApiBase.php +++ b/src/includes/classes/ApiBase.php @@ -74,6 +74,22 @@ public static function clear() return $GLOBALS[GLOBAL_NS]->clearCache(); } + /** + * This erases the cache for a specific post ID. + * + * @since 150626 Adding support for new API methods. + * + * @param int $post_id Post ID. + * + * @return int Total files cleared (if any). + */ + public static function clearPost($post_id) + { + return $GLOBALS[GLOBAL_NS]->autoClearPostCache($post_id); + } + + + /** * This wipes out the entire cache. * diff --git a/src/includes/classes/MenuPageOptions.php b/src/includes/classes/MenuPageOptions.php index 6f7fa87..4500329 100644 --- a/src/includes/classes/MenuPageOptions.php +++ b/src/includes/classes/MenuPageOptions.php @@ -673,17 +673,18 @@ public function __construct() echo '

'.__('CDN Host Name (Required)', SLUG_TD).'

'."\n"; - echo '

'.// This note includes two graphics. One for MaxCDN; another for CloudFront. - ' '. - ' '. - ' '.__('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. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN and/or Amazon CloudFront, but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a CloudFront tutorial video that walks you through the process.', SLUG_TD).'

'."\n"; + echo '

'.// This note includes three graphics. One for MaxCDN; another for CloudFront, and another for KeyCDN. + ' '. + ' '. + ' '. + ' '.__('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. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN, Amazon CloudFront, KeyCDN, and/or CDN77 but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a MaxCDN tutorial, CloudFront tutorial, KeyCDN tutorial, and a CDN77 tutorial to walk you through the process.', SLUG_TD).'

'."\n"; echo '

plugin->options['cdn_hosts'] ? ' disabled="disabled"' : '').' />

'."\n"; echo '
'."\n"; - echo '

'.__('Or, Configure Multiple CDN Host Names (for Domain Sharding and Multisite Networks)', SLUG_TD).'

'."\n"; + echo '

'.__('Multiple CDN Host Names for Domain Sharding and Multisite Networks (Optional)', SLUG_TD).'

'."\n"; echo '

'.sprintf(__('%1$s also supports multiple CDN Host Names for any given domain. Using multiple CDN Host Names (instead of just one, as seen above) is referred to as Domain Sharding (click here to learn more). 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 <head> 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.', SLUG_TD), esc_html(NAME)).'

'."\n"; - echo '

'.sprintf(__('On WordPress Multisite Network installations, 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.', SLUG_TD), esc_html(NAME)).'

'."\n"; + echo '

'.sprintf(__('On WordPress Multisite Network installations, 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: Static CDN Filters for WordPress Multisite Networks.', SLUG_TD), esc_html(NAME)).'

'."\n"; echo '

'."\n"; echo '

'.sprintf(__('↑ Syntax: This is a line-delimited list of domain mappings. Each line should start with your WordPress domain name (e.g., %1$s), followed by an = 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.', SLUG_TD), esc_html($_SERVER['HTTP_HOST'])).'

'."\n"; diff --git a/src/includes/closures/Plugin/WcpPostUtils.php b/src/includes/closures/Plugin/WcpPostUtils.php index c9cab29..e660c0d 100644 --- a/src/includes/closures/Plugin/WcpPostUtils.php +++ b/src/includes/closures/Plugin/WcpPostUtils.php @@ -95,6 +95,7 @@ return $counter; }; +$self->auto_clear_post_cache = $self->autoClearPostCache; // Back compat. /* * Automatically clears cache files for a particular post when transitioning diff --git a/src/includes/closures/Plugin/WcpUtils.php b/src/includes/closures/Plugin/WcpUtils.php index 5b332dc..de4d81b 100644 --- a/src/includes/closures/Plugin/WcpUtils.php +++ b/src/includes/closures/Plugin/WcpUtils.php @@ -45,6 +45,7 @@ return $counter; }; +$self->wipe_cache = $self->wipeCache; // Back compat. /* * Clears cache files for the current host|blog. @@ -76,6 +77,7 @@ return $counter; }; +$self->clear_cache = $self->clearCache; // Back compat. /* * Purges expired cache files for the current host|blog. @@ -104,6 +106,7 @@ return $counter; }; +$self->purge_cache = $self->purgeCache; // Back compat. /* * Automatically wipes out all cache files in the cache directory. diff --git a/src/includes/stub.php b/src/includes/stub.php index 10b02fa..d891908 100644 --- a/src/includes/stub.php +++ b/src/includes/stub.php @@ -12,7 +12,7 @@ require_once dirname(dirname(__FILE__)).'/vendor/autoload.php'; require_once dirname(__FILE__).'/functions/i18n-utils.php'; -${__FILE__}['version'] = '150605'; //version// +${__FILE__}['version'] = '150626'; //version// ${__FILE__}['plugin'] = dirname(dirname(dirname(__FILE__))); ${__FILE__}['plugin'] .= '/'.basename(${__FILE__}['plugin']).'.php'; ${__FILE__}['ns_path'] = str_replace('\\', '/', __NAMESPACE__); // To dir/path. diff --git a/src/includes/translations/zencache-pro.pot b/src/includes/translations/zencache-pro.pot index 05b246b..3dd2ca2 100644 --- a/src/includes/translations/zencache-pro.pot +++ b/src/includes/translations/zencache-pro.pot @@ -2,9 +2,9 @@ # This file is distributed under the same license as the ZenCache Pro package. msgid "" msgstr "" -"Project-Id-Version: ZenCache Pro 150605\n" +"Project-Id-Version: ZenCache Pro 150626\n" "Report-Msgid-Bugs-To: http://wordpress.org/tag/zencache-pro\n" -"POT-Creation-Date: 2015-06-05 18:07:46+00:00\n" +"POT-Creation-Date: 2015-06-26 23:35:21+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -806,7 +806,7 @@ msgstr "" #: src/includes/classes/MenuPageOptions.php:513 #: src/includes/classes/MenuPageOptions.php:617 #: src/includes/classes/MenuPageOptions.php:621 -#: src/includes/classes/MenuPageOptions.php:731 +#: src/includes/classes/MenuPageOptions.php:732 msgid "Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line." msgstr "" @@ -1070,191 +1070,191 @@ msgstr "" msgid "CDN Host Name (Required)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:679 -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. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN and/or Amazon CloudFront, but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a CloudFront tutorial video that walks you through the process." +#: src/includes/classes/MenuPageOptions.php:680 +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. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN, Amazon CloudFront, KeyCDN, and/or CDN77 but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a MaxCDN tutorial, CloudFront tutorial, KeyCDN tutorial, and a CDN77 tutorial to walk you through the process." msgstr "" -#: src/includes/classes/MenuPageOptions.php:684 -msgid "Or, Configure Multiple CDN Host Names (for Domain Sharding and Multisite Networks)" +#: src/includes/classes/MenuPageOptions.php:685 +msgid "Multiple CDN Host Names for Domain Sharding and Multisite Networks (Optional)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:685 +#: src/includes/classes/MenuPageOptions.php:686 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 Domain Sharding (click here to learn more). 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 <head> 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:686 -msgid "On WordPress Multisite Network installations, 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." +#: src/includes/classes/MenuPageOptions.php:687 +msgid "On WordPress Multisite Network installations, 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: Static CDN Filters for WordPress Multisite Networks." msgstr "" -#: src/includes/classes/MenuPageOptions.php:688 +#: src/includes/classes/MenuPageOptions.php:689 msgid "↑ Syntax: This is a line-delimited list of domain mappings. Each line should start with your WordPress domain name (e.g., %1$s), followed by an = 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:692 +#: src/includes/classes/MenuPageOptions.php:693 msgid "CDN Supports HTTPS Connections?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:694 +#: src/includes/classes/MenuPageOptions.php:695 msgid "No, I don't serve content over https://; or I haven't configured my CDN w/ an SSL certificate." msgstr "" -#: src/includes/classes/MenuPageOptions.php:695 +#: src/includes/classes/MenuPageOptions.php:696 msgid "Yes, I've configured my CDN w/ an SSL certificate; I need https:// enabled." msgstr "" -#: src/includes/classes/MenuPageOptions.php:702 +#: src/includes/classes/MenuPageOptions.php:703 msgid "Additional Options (For Advanced Users)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:708 +#: src/includes/classes/MenuPageOptions.php:709 msgid "Everything else below is 100% completely optional; i.e. not required to enjoy the benefits of Static CDN Filters." msgstr "" -#: src/includes/classes/MenuPageOptions.php:712 +#: src/includes/classes/MenuPageOptions.php:713 msgid "Whitelisted File Extensions (Optional; Comma-Delimited)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:714 +#: src/includes/classes/MenuPageOptions.php:715 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:716 +#: src/includes/classes/MenuPageOptions.php:717 msgid "Blacklisted File Extensions (Optional; Comma-Delimited)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:718 +#: src/includes/classes/MenuPageOptions.php:719 msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain file extensions of your choosing. Please note, the php extension will never be considered a static resource; i.e. it is automatically blacklisted at all times." msgstr "" -#: src/includes/classes/MenuPageOptions.php:722 +#: src/includes/classes/MenuPageOptions.php:723 msgid "Whitelisted URI Inclusion Patterns (Optional; One Per Line)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:724 +#: src/includes/classes/MenuPageOptions.php:725 msgid "Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one inclusion pattern per line." msgstr "" -#: src/includes/classes/MenuPageOptions.php:725 +#: src/includes/classes/MenuPageOptions.php:726 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 * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/* here would indicate that you only want to filter URLs that lead to files located inside the wp-content directory. Adding an additional line with */wp-includes/* would filter URLs in the wp-includes directory also. If you leave this empty, ALL files matching a static file extension will be served from your CDN; i.e. the default behavior." msgstr "" -#: src/includes/classes/MenuPageOptions.php:726 +#: src/includes/classes/MenuPageOptions.php:727 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 /. To clarify, a URI is the portion of the URL which comes after the host name. For instance, given the following URL: http://example.com/path/to/style.css?ver=3, the URI you are matching against would be: /path/to/style.css?ver=3. To whitelist this URI, you could use a line that contains something like this: /path/to/*.css*" msgstr "" -#: src/includes/classes/MenuPageOptions.php:728 +#: src/includes/classes/MenuPageOptions.php:729 msgid "Blacklisted URI Exclusion Patterns (Optional; One Per Line)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:730 +#: src/includes/classes/MenuPageOptions.php:731 msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain URI patterns. URI patterns are caSe-insensitive. A wildcard * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/*/dynamic.pdf* would exclude a file with the name dynamic.pdf located anywhere inside a sub-directory of wp-content." msgstr "" -#: src/includes/classes/MenuPageOptions.php:735 +#: src/includes/classes/MenuPageOptions.php:736 msgid "Query String Invalidation Variable Name" msgstr "" -#: src/includes/classes/MenuPageOptions.php:737 +#: src/includes/classes/MenuPageOptions.php:738 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. Please note, the default value is adequate for most sites. You can change this if you like, but it's not necessary." msgstr "" -#: src/includes/classes/MenuPageOptions.php:738 +#: src/includes/classes/MenuPageOptions.php:739 msgid "Note: 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:753 +#: src/includes/classes/MenuPageOptions.php:754 msgid "Dynamic Version Salt" msgstr "" -#: src/includes/classes/MenuPageOptions.php:758 +#: src/includes/classes/MenuPageOptions.php:759 msgid " GEEK ALERT This is for VERY advanced users only..." msgstr "" -#: src/includes/classes/MenuPageOptions.php:759 +#: src/includes/classes/MenuPageOptions.php:760 msgid "Note: Understanding the %1$s Branched Cache Structure is a prerequisite to understanding how Dynamic Version Salts are added to the mix." msgstr "" -#: src/includes/classes/MenuPageOptions.php:760 +#: src/includes/classes/MenuPageOptions.php:761 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:761 +#: src/includes/classes/MenuPageOptions.php:762 msgid "A Version Salt can be a single variable like $_COOKIE['my_cookie'], or it can be a combination of multiple variables, like $_COOKIE['my_cookie'].$_COOKIE['my_other_cookie']. (When using multiple variables, please separate them with a dot, as shown in the example.)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:762 +#: src/includes/classes/MenuPageOptions.php:763 msgid "Experts could even use PHP ternary expressions that evaluate into something. For example: ((preg_match('/iPhone/i', $_SERVER['HTTP_USER_AGENT'])) ? 'iPhones' : ''). This would force a separate version of the cache to be created for iPhones (e.g., /cache/PROTOCOL/HOST/REQUEST-URI.v/iPhones.html)." msgstr "" -#: src/includes/classes/MenuPageOptions.php:763 +#: src/includes/classes/MenuPageOptions.php:764 msgid "For more documentation, please see Dynamic Version Salts." msgstr "" -#: src/includes/classes/MenuPageOptions.php:765 +#: src/includes/classes/MenuPageOptions.php:766 msgid "Create a Dynamic Version Salt For %1$s?       150%% OPTIONAL" msgstr "" -#: src/includes/classes/MenuPageOptions.php:767 +#: src/includes/classes/MenuPageOptions.php:768 msgid "Super Globals work here; $GLOBALS['table_prefix'] is a popular one.
Or, perhaps a PHP Constant defined in /wp-config.php; such as WPLANG or DB_HOST." msgstr "" -#: src/includes/classes/MenuPageOptions.php:768 +#: src/includes/classes/MenuPageOptions.php:769 msgid "Important: your Version Salt is scanned for PHP syntax errors via phpCodeChecker.com. If errors are found, you'll receive a notice in the Dashboard." msgstr "" -#: src/includes/classes/MenuPageOptions.php:769 +#: src/includes/classes/MenuPageOptions.php:770 msgid "If you've enabled a separate cache for each user (optional) that's perfectly OK. A Version Salt works with user caching too." msgstr "" -#: src/includes/classes/MenuPageOptions.php:779 +#: src/includes/classes/MenuPageOptions.php:780 msgid "Theme/Plugin Developers" msgstr "" -#: src/includes/classes/MenuPageOptions.php:784 +#: src/includes/classes/MenuPageOptions.php:785 msgid "Developing a Theme or Plugin for WordPress?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:785 +#: src/includes/classes/MenuPageOptions.php:786 msgid "Tip: %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: $_SERVER['ZENCACHE_ALLOWED'] = FALSE; or define('ZENCACHE_ALLOWED', FALSE). %1$s is also compatible with: define('DONOTCACHEPAGE', TRUE). 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:787 +#: src/includes/classes/MenuPageOptions.php:788 msgid "Writing \"Advanced Cache\" Plugins Specifically for %1$s" msgstr "" -#: src/includes/classes/MenuPageOptions.php:788 +#: src/includes/classes/MenuPageOptions.php:789 msgid "Theme/plugin developers can take advantage of the %1$s plugin architecture by creating PHP files inside this special directory: /wp-content/ac-plugins/. There is an example plugin file @ GitHub (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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:789 +#: src/includes/classes/MenuPageOptions.php:790 msgid "Why does %1$s have it's own plugin architecture? WordPress loads the advanced-cache.php 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 add_action(), do_action(), add_filter(), apply_filters()." msgstr "" -#: src/includes/classes/MenuPageOptions.php:800 +#: src/includes/classes/MenuPageOptions.php:801 msgid "Import/Export Options" msgstr "" -#: src/includes/classes/MenuPageOptions.php:805 +#: src/includes/classes/MenuPageOptions.php:806 msgid "Import Options from Another %1$s Installation?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:806 +#: src/includes/classes/MenuPageOptions.php:807 msgid "Upload your %1$s-options.json file and click \"Save All Changes\" below. The options provided by your import file will override any that exist currently." msgstr "" -#: src/includes/classes/MenuPageOptions.php:809 +#: src/includes/classes/MenuPageOptions.php:810 msgid "Export Existing Options from this %1$s Installation?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:812 +#: src/includes/classes/MenuPageOptions.php:813 msgid "%1$s-options.json" msgstr "" -#: src/includes/classes/MenuPageOptions.php:813 +#: src/includes/classes/MenuPageOptions.php:814 msgid "Download your existing options and import them all into another %1$s installation; saves time on future installs." msgstr "" -#: src/includes/classes/MenuPageOptions.php:821 +#: src/includes/classes/MenuPageOptions.php:822 msgid "Save All Changes" msgstr "" @@ -1595,19 +1595,19 @@ msgstr "" msgid "%1$s: detected changes. Found %2$s in the cache for user ID: %3$s; auto-clearing." msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:140 +#: src/includes/closures/Plugin/WcpUtils.php:143 msgid "%1$s: detected significant changes. Found %2$s in the cache; auto-wiping." msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:186 +#: src/includes/closures/Plugin/WcpUtils.php:189 msgid "%1$s: detected important site changes. Found %2$s in the cache for this site; auto-clearing." msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:206 +#: src/includes/closures/Plugin/WcpUtils.php:209 msgid "%1$s: detected significant changes that would normally trigger a wipe cache routine, however wipe cache routines have been disabled by a site administrator. [?]" msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:226 +#: src/includes/closures/Plugin/WcpUtils.php:229 msgid "%1$s: detected important site changes that would normally trigger a clear cache routine. However, clear cache routines have been disabled by a site administrator. [?]" msgstr "" diff --git a/src/includes/translations/zencache.pot b/src/includes/translations/zencache.pot index e20fb36..d6c2a73 100644 --- a/src/includes/translations/zencache.pot +++ b/src/includes/translations/zencache.pot @@ -2,9 +2,9 @@ # This file is distributed under the same license as the ZenCache package. msgid "" msgstr "" -"Project-Id-Version: ZenCache 150605\n" +"Project-Id-Version: ZenCache 150626\n" "Report-Msgid-Bugs-To: http://wordpress.org/tag/zencache\n" -"POT-Creation-Date: 2015-06-05 18:08:20+00:00\n" +"POT-Creation-Date: 2015-06-26 23:35:45+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -755,7 +755,7 @@ msgstr "" #: src/includes/classes/MenuPageOptions.php:513 #: src/includes/classes/MenuPageOptions.php:617 #: src/includes/classes/MenuPageOptions.php:621 -#: src/includes/classes/MenuPageOptions.php:731 +#: src/includes/classes/MenuPageOptions.php:732 msgid "Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line." msgstr "" @@ -1019,191 +1019,191 @@ msgstr "" msgid "CDN Host Name (Required)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:679 -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. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN and/or Amazon CloudFront, but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a CloudFront tutorial video that walks you through the process." +#: src/includes/classes/MenuPageOptions.php:680 +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. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN, Amazon CloudFront, KeyCDN, and/or CDN77 but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a MaxCDN tutorial, CloudFront tutorial, KeyCDN tutorial, and a CDN77 tutorial to walk you through the process." msgstr "" -#: src/includes/classes/MenuPageOptions.php:684 -msgid "Or, Configure Multiple CDN Host Names (for Domain Sharding and Multisite Networks)" +#: src/includes/classes/MenuPageOptions.php:685 +msgid "Multiple CDN Host Names for Domain Sharding and Multisite Networks (Optional)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:685 +#: src/includes/classes/MenuPageOptions.php:686 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 Domain Sharding (click here to learn more). 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 <head> 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:686 -msgid "On WordPress Multisite Network installations, 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." +#: src/includes/classes/MenuPageOptions.php:687 +msgid "On WordPress Multisite Network installations, 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: Static CDN Filters for WordPress Multisite Networks." msgstr "" -#: src/includes/classes/MenuPageOptions.php:688 +#: src/includes/classes/MenuPageOptions.php:689 msgid "↑ Syntax: This is a line-delimited list of domain mappings. Each line should start with your WordPress domain name (e.g., %1$s), followed by an = 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:692 +#: src/includes/classes/MenuPageOptions.php:693 msgid "CDN Supports HTTPS Connections?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:694 +#: src/includes/classes/MenuPageOptions.php:695 msgid "No, I don't serve content over https://; or I haven't configured my CDN w/ an SSL certificate." msgstr "" -#: src/includes/classes/MenuPageOptions.php:695 +#: src/includes/classes/MenuPageOptions.php:696 msgid "Yes, I've configured my CDN w/ an SSL certificate; I need https:// enabled." msgstr "" -#: src/includes/classes/MenuPageOptions.php:702 +#: src/includes/classes/MenuPageOptions.php:703 msgid "Additional Options (For Advanced Users)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:708 +#: src/includes/classes/MenuPageOptions.php:709 msgid "Everything else below is 100% completely optional; i.e. not required to enjoy the benefits of Static CDN Filters." msgstr "" -#: src/includes/classes/MenuPageOptions.php:712 +#: src/includes/classes/MenuPageOptions.php:713 msgid "Whitelisted File Extensions (Optional; Comma-Delimited)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:714 +#: src/includes/classes/MenuPageOptions.php:715 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:716 +#: src/includes/classes/MenuPageOptions.php:717 msgid "Blacklisted File Extensions (Optional; Comma-Delimited)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:718 +#: src/includes/classes/MenuPageOptions.php:719 msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain file extensions of your choosing. Please note, the php extension will never be considered a static resource; i.e. it is automatically blacklisted at all times." msgstr "" -#: src/includes/classes/MenuPageOptions.php:722 +#: src/includes/classes/MenuPageOptions.php:723 msgid "Whitelisted URI Inclusion Patterns (Optional; One Per Line)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:724 +#: src/includes/classes/MenuPageOptions.php:725 msgid "Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one inclusion pattern per line." msgstr "" -#: src/includes/classes/MenuPageOptions.php:725 +#: src/includes/classes/MenuPageOptions.php:726 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 * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/* here would indicate that you only want to filter URLs that lead to files located inside the wp-content directory. Adding an additional line with */wp-includes/* would filter URLs in the wp-includes directory also. If you leave this empty, ALL files matching a static file extension will be served from your CDN; i.e. the default behavior." msgstr "" -#: src/includes/classes/MenuPageOptions.php:726 +#: src/includes/classes/MenuPageOptions.php:727 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 /. To clarify, a URI is the portion of the URL which comes after the host name. For instance, given the following URL: http://example.com/path/to/style.css?ver=3, the URI you are matching against would be: /path/to/style.css?ver=3. To whitelist this URI, you could use a line that contains something like this: /path/to/*.css*" msgstr "" -#: src/includes/classes/MenuPageOptions.php:728 +#: src/includes/classes/MenuPageOptions.php:729 msgid "Blacklisted URI Exclusion Patterns (Optional; One Per Line)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:730 +#: src/includes/classes/MenuPageOptions.php:731 msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain URI patterns. URI patterns are caSe-insensitive. A wildcard * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/*/dynamic.pdf* would exclude a file with the name dynamic.pdf located anywhere inside a sub-directory of wp-content." msgstr "" -#: src/includes/classes/MenuPageOptions.php:735 +#: src/includes/classes/MenuPageOptions.php:736 msgid "Query String Invalidation Variable Name" msgstr "" -#: src/includes/classes/MenuPageOptions.php:737 +#: src/includes/classes/MenuPageOptions.php:738 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. Please note, the default value is adequate for most sites. You can change this if you like, but it's not necessary." msgstr "" -#: src/includes/classes/MenuPageOptions.php:738 +#: src/includes/classes/MenuPageOptions.php:739 msgid "Note: 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:753 +#: src/includes/classes/MenuPageOptions.php:754 msgid "Dynamic Version Salt" msgstr "" -#: src/includes/classes/MenuPageOptions.php:758 +#: src/includes/classes/MenuPageOptions.php:759 msgid " GEEK ALERT This is for VERY advanced users only..." msgstr "" -#: src/includes/classes/MenuPageOptions.php:759 +#: src/includes/classes/MenuPageOptions.php:760 msgid "Note: Understanding the %1$s Branched Cache Structure is a prerequisite to understanding how Dynamic Version Salts are added to the mix." msgstr "" -#: src/includes/classes/MenuPageOptions.php:760 +#: src/includes/classes/MenuPageOptions.php:761 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:761 +#: src/includes/classes/MenuPageOptions.php:762 msgid "A Version Salt can be a single variable like $_COOKIE['my_cookie'], or it can be a combination of multiple variables, like $_COOKIE['my_cookie'].$_COOKIE['my_other_cookie']. (When using multiple variables, please separate them with a dot, as shown in the example.)" msgstr "" -#: src/includes/classes/MenuPageOptions.php:762 +#: src/includes/classes/MenuPageOptions.php:763 msgid "Experts could even use PHP ternary expressions that evaluate into something. For example: ((preg_match('/iPhone/i', $_SERVER['HTTP_USER_AGENT'])) ? 'iPhones' : ''). This would force a separate version of the cache to be created for iPhones (e.g., /cache/PROTOCOL/HOST/REQUEST-URI.v/iPhones.html)." msgstr "" -#: src/includes/classes/MenuPageOptions.php:763 +#: src/includes/classes/MenuPageOptions.php:764 msgid "For more documentation, please see Dynamic Version Salts." msgstr "" -#: src/includes/classes/MenuPageOptions.php:765 +#: src/includes/classes/MenuPageOptions.php:766 msgid "Create a Dynamic Version Salt For %1$s?       150%% OPTIONAL" msgstr "" -#: src/includes/classes/MenuPageOptions.php:767 +#: src/includes/classes/MenuPageOptions.php:768 msgid "Super Globals work here; $GLOBALS['table_prefix'] is a popular one.
Or, perhaps a PHP Constant defined in /wp-config.php; such as WPLANG or DB_HOST." msgstr "" -#: src/includes/classes/MenuPageOptions.php:768 +#: src/includes/classes/MenuPageOptions.php:769 msgid "Important: your Version Salt is scanned for PHP syntax errors via phpCodeChecker.com. If errors are found, you'll receive a notice in the Dashboard." msgstr "" -#: src/includes/classes/MenuPageOptions.php:769 +#: src/includes/classes/MenuPageOptions.php:770 msgid "If you've enabled a separate cache for each user (optional) that's perfectly OK. A Version Salt works with user caching too." msgstr "" -#: src/includes/classes/MenuPageOptions.php:779 +#: src/includes/classes/MenuPageOptions.php:780 msgid "Theme/Plugin Developers" msgstr "" -#: src/includes/classes/MenuPageOptions.php:784 +#: src/includes/classes/MenuPageOptions.php:785 msgid "Developing a Theme or Plugin for WordPress?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:785 +#: src/includes/classes/MenuPageOptions.php:786 msgid "Tip: %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: $_SERVER['ZENCACHE_ALLOWED'] = FALSE; or define('ZENCACHE_ALLOWED', FALSE). %1$s is also compatible with: define('DONOTCACHEPAGE', TRUE). 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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:787 +#: src/includes/classes/MenuPageOptions.php:788 msgid "Writing \"Advanced Cache\" Plugins Specifically for %1$s" msgstr "" -#: src/includes/classes/MenuPageOptions.php:788 +#: src/includes/classes/MenuPageOptions.php:789 msgid "Theme/plugin developers can take advantage of the %1$s plugin architecture by creating PHP files inside this special directory: /wp-content/ac-plugins/. There is an example plugin file @ GitHub (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." msgstr "" -#: src/includes/classes/MenuPageOptions.php:789 +#: src/includes/classes/MenuPageOptions.php:790 msgid "Why does %1$s have it's own plugin architecture? WordPress loads the advanced-cache.php 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 add_action(), do_action(), add_filter(), apply_filters()." msgstr "" -#: src/includes/classes/MenuPageOptions.php:800 +#: src/includes/classes/MenuPageOptions.php:801 msgid "Import/Export Options" msgstr "" -#: src/includes/classes/MenuPageOptions.php:805 +#: src/includes/classes/MenuPageOptions.php:806 msgid "Import Options from Another %1$s Installation?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:806 +#: src/includes/classes/MenuPageOptions.php:807 msgid "Upload your %1$s-options.json file and click \"Save All Changes\" below. The options provided by your import file will override any that exist currently." msgstr "" -#: src/includes/classes/MenuPageOptions.php:809 +#: src/includes/classes/MenuPageOptions.php:810 msgid "Export Existing Options from this %1$s Installation?" msgstr "" -#: src/includes/classes/MenuPageOptions.php:812 +#: src/includes/classes/MenuPageOptions.php:813 msgid "%1$s-options.json" msgstr "" -#: src/includes/classes/MenuPageOptions.php:813 +#: src/includes/classes/MenuPageOptions.php:814 msgid "Download your existing options and import them all into another %1$s installation; saves time on future installs." msgstr "" -#: src/includes/classes/MenuPageOptions.php:821 +#: src/includes/classes/MenuPageOptions.php:822 msgid "Save All Changes" msgstr "" @@ -1456,19 +1456,19 @@ msgstr "" msgid "%1$s: detected changes. Found %2$s in the cache for %3$s: %4$s; auto-clearing." msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:136 +#: src/includes/closures/Plugin/WcpUtils.php:139 msgid "%1$s: detected significant changes. Found %2$s in the cache; auto-wiping." msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:182 +#: src/includes/closures/Plugin/WcpUtils.php:185 msgid "%1$s: detected important site changes. Found %2$s in the cache for this site; auto-clearing." msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:202 +#: src/includes/closures/Plugin/WcpUtils.php:205 msgid "%1$s: detected significant changes that would normally trigger a wipe cache routine, however wipe cache routines have been disabled by a site administrator. [?]" msgstr "" -#: src/includes/closures/Plugin/WcpUtils.php:222 +#: src/includes/closures/Plugin/WcpUtils.php:225 msgid "%1$s: detected important site changes that would normally trigger a clear cache routine. However, clear cache routines have been disabled by a site administrator. [?]" msgstr "" diff --git a/src/vendor/autoload.php b/src/vendor/autoload.php index bcab36d..bf01ad0 100644 --- a/src/vendor/autoload.php +++ b/src/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInit30315a3da8637794a95fea29a21b4c12::getLoader(); +return ComposerAutoloaderInit77d15b31d6f286485922a5e6b2b5d937::getLoader(); diff --git a/src/vendor/composer/autoload_real.php b/src/vendor/composer/autoload_real.php index b90fa89..d33bd70 100644 --- a/src/vendor/composer/autoload_real.php +++ b/src/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInit30315a3da8637794a95fea29a21b4c12 +class ComposerAutoloaderInit77d15b31d6f286485922a5e6b2b5d937 { private static $loader; @@ -19,9 +19,9 @@ public static function getLoader() return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInit30315a3da8637794a95fea29a21b4c12', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit77d15b31d6f286485922a5e6b2b5d937', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInit30315a3da8637794a95fea29a21b4c12', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit77d15b31d6f286485922a5e6b2b5d937', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -44,7 +44,7 @@ public static function getLoader() } } -function composerRequire30315a3da8637794a95fea29a21b4c12($file) +function composerRequire77d15b31d6f286485922a5e6b2b5d937($file) { require $file; } diff --git a/zencache.php b/zencache.php index 77e9c77..0969178 100644 --- a/zencache.php +++ b/zencache.php @@ -1,6 +1,6 @@ -- **New Feature**: 404 Page caching. It's now possible to enable/disable the caching of 404 requests. Enabling this feature generates a single cache file for your 404 Page and then symlinks future 404 requests to that cache file. See *Dashboard -> ZenCache -> Plugin Options -> 404 Requests*. -- **New Feature (Pro)**: HTML Compressor (experimental). This new experimental feature automatically combines and compresses CSS/JS/HTML code. See *Dashboard -> ZenCache -> Plugin Options -> HTML Compressor*. For more details about how this feature works, please see -- **New Feature (Pro)**: Auto-Cache Engine. When enabled, the Auto-Cache Engine will pre-cache your site at 15-minute intervals, rebuilding cache files when necessary (it will not rebuild cache files until they have expired). This helps eliminate the slowness a user may experience when visiting a page on your site that has not yet been cached. See *Dashboard -> ZenCache -> Plugin Options -> Auto-Cache Engine*. -- **New Feature**: Auto-Purge "Author Page". When a single Post/Page is changed in some way, ZenCache can also purge any existing cache files for the associated Author Page. See *Dashboard -> ZenCache -> Plugin Options -> Clearing the Cache*. (This option is enabled by default; disabling this requires ZenCache Pro.) -- **New Feature**: Auto-Purge "Category Archives". When a single Post/Page is changed in some way, ZenCache can also purge any existing cache files for the associated Category archive views. See *Dashboard -> ZenCache -> Plugin Options -> Clearing the Cache*. (This option is enabled by default; disabling this requires ZenCache Pro.) -- **New Feature**: Auto-Purge "Tag Archives". When a single Post/Page is changed in some way, ZenCache can also purge any existing cache files for the associated Tag archive views. See *Dashboard -> ZenCache -> Plugin Options -> Clearing the Cache*. (This option is enabled by default; disabling this requires ZenCache Pro.) -- **New Feature**: Auto-Purge "Custom Term Archives". When a single Post/Page is changed in some way, ZenCache can also purge any custom Terms that may have their own Term archive views. See *Dashboard -> ZenCache -> Plugin Options -> Clearing the Cache*. (This option is enabled by default; disabling this requires ZenCache Pro.) -- **Enhancement**: Improved conflict handling of other plugins using `ob_start()`. See -- **Enhancement**: Added a postload filter for `status_header` so that ZenCache can properly detect calls to the WP core function `status_header()` -- **Enhancement**: The ZenCache cache directory has been changed to `wp-content/cache/zencache/` to provide better organization of cache files and avoid interfering with another plugin that may also be writing to the `wp-content/cache/` directory. See -- **Enhancement**: New detailed debugging notes (see *Dashboard -> ZenCache -> Plugin Options -> Enable/Disable*). There is now an extra option to show detailed debugging information in addition to the ZenCache notes in the HTML source. For now, this feature only applies when the HTML Compressor is enabled. -- **Enhancement**: Better Debugging Notices. If ZenCache is not caching a particular page (such as when a logged-in user visits the site and logged-in user caching is not enabled), ZenCache will now report why that page is not being cached in the HTML notes. -- **Enhancement**: Improved compatibility with the Nav Menu Roles plugin. See -- **Bug Fix**: Obey custom content directories. If you have customized your `WP_CONTENT_DIR` and `WP_CONTENT_URL` constants to point somewhere other than the default, ZenCache will now obey those and use your custom directory for storing cache files. See -- **Bug Fix**: Scheduled posts now trigger the clearing of any associated archive views when those posts go live (assuming you have those archive views set to Auto-Purge in *Dashboard -> ZenCache -> Plugin Options -> Clearing the Cache*). See -- **Bug Fix**: Fixed a bug where saving a post as `draft` would trigger the Auto-Purge Post routine and clear the cache for that post. Now only purges post status `publish` and `private` and when transitioning from `publish` or `private` post status to `draft`, `future`, or `private`. See -- **Bug Fix**: Split/paginated comments and multi-page Posts/Page cache files are now purged properly when the post cache is purged. See - -= v140104 = - -* **New Options for Feed Caching**. It's now possible to control RSS, RDF, and Atom Feed caching. The new default is for feed caching to be disabled, which resolves an issue where new posts don't show up in the feed until the cache is cleared. This version of ZenCache disables feed caching to prevent this from happening. If you wish to cache feeds, you can enable feed caching in the options. See: -* **New Automatic Updater for ZenCache Pro**. ZenCache Pro now includes an automatic updater which lets you to keep ZenCache Pro updated right from within your WordPress Dashboard. To upgrade to a new version of ZenCache Pro using the Automatic Updater, simply fill in your WebSharks-Inc.com credentials in the new Plugin Updater sub-panel (**ZenCache Pro -› Plugin Updater**). See: - -= v131224 = - -* **New Lite Enhancement**. The Home Page cache and Posts Page cache are now automatically purged when necessary (such as when a new post is published). See: -* Improved ZenCache version check notice. -* Improved ZenCache options validation. -* **Bug Fix**. ZenCache was previously not properly excluding systematic WordPress areas reliably, e.g. any file that begins with `wp-` and/or the `xmlrpc` file. These are now properly auto-excluded. On Multisite installations, `/files/` is also auto-excluded from being cached. This bug required fixing incorrect instances of `[?$]` in regex patterns. See: -* **Multisite Enhancement**. When running ZenCache on Multisite Network installation, only allow the plugin to be "Network Activated" (becuase that is how ZenCache is designed to work). See: -* **Multisite Enhancement**. New 'Wipe' button allows a site owner to clear (wipe) the cache for all sites in a Multisite Network at once. See: -* **Multisite Bug Fix**. Clearing the cache on a Multisite Network configured to use sub-directories now works properly. See: -* **Multisite Bug Fix**. Fixed unmatched closing parenthesis in regex. See: -* **Multisite Bug Fix**. Added support for `PATH_CURRENT_SITE` and `$GLOBALS['base']`. -* **Multisite Bug Fix**. Removed depreciated VHOST code that was causing issues with clearing the cache. - -= v131206 = - -* **New Pro Feature**. It's now possible for developers to add custom PHP code to the cache clearing routines (e.g. custom code which might consider things like APC or memcache also). This requires [ZenCache Pro](http://www.websharks-inc.com/product/zencache/). Please check your Dashboard under: **ZenCache Pro -› Clearing the Cache**. See also: [this screenshot](https://f.cloud.github.com/assets/1563559/1692324/7ae902c4-5e78-11e3-98ba-acbb08b30585.png). -* **Multisite Bug Fix**. Unable to clear the cache when running sub-directories. See: -* **Multisite Bug Fix**. The "Clear Cache" button was not displayed for child blogs in a network. Fixed in this release. - -= v131205 = - -* Added hook to `wp_set_comment_status` to purge the comment cache when a comment status changes. -* Ignore `set_time_limit()` errors in case function is disabled in PHP configuration. This is a temporary fix and will be handled more appropriately in a future maintenance release. See also: -* Added Raam Dev to the contributors list. Raam will now be leading the development of ZenCache and ZenCache Pro. - -= v131128 = - -* **New Plugin Architecture for ZenCache.** This release introduces a new way for theme/plugin developers to modify the way ZenCache operates at the `advanced-cache.php` level (e.g. very early-on). For further details on this, please check your Dashboard under: `ZenCache -› Theme/Plugin Developers`. See also: -* **Compatibility.** This release further improves PHP v5.3 detection. ZenCache will now generate an administrative notice instead of a PHP exception; allowing the plugin to be activated, but without actually loading the plugin under this scenario. A notice to the site owner is helpful in cases where the plugin is NOT being updated through the Dashboard. This will remove the risk of crashing a site that's attempting to run ZenCache w/o PHP v5.3+ installed. See also: - -= v131127 = - -* **Compatibility.** This release improves PHP v5.3 detection. ZenCache will now generate an administrative notice instead of a PHP exception; allowing the plugin to be activated, but without actually loading the plugin under this scenario. A notice to the site owner is helpful in cases where the plugin is NOT being updated through the Dashboard. This will remove the risk of crashing a site that's attempting to run ZenCache w/o PHP v5.3+ installed. See also: -* **New Pro Feature.** Clear Home Page (and/or Posts Page) on auto-purge. See: -* **Bug Fix (Options -Indexes).** Removing unnecessary `.htaccess` file from the `/wp-content/plugins/zencache/` directory that prevented directory indexing, as this is not compatible in all hosting environents. See: -* **Bug Fix (ABSPATH).** Incorrect detection of the `/wp-config.php` file on sites that move this file up one directory. Fixed in this release. See: -* **Bug Fix (Parse Error).** Correcting code that deals with an edge case where the `/wp-config.php` file may become corrupted upon deactivation of the ZenCache plugin through the WP Dashboard. Fixed in this release. See: -* **Bug Fix (Error Reporting).** Improving error message via Dashboard whenever permissions are an issue in one specific scenario. See: -* **Enhancement (Pro Preview).** Adding a more visible way to disable Pro Preview mode in the Lite version of ZenCache. See: -* **Emergency Scenario** Adding notes in several sections of the `reamde.txt` file regarding "what to do in an emergency scenario". -* **See Also** - -= v131121 = - -* Updated to support all features and functionality of WordPress v3.7+ (this new release of ZenCache requires WordPress v3.7+). The ZenCache plugin is now being actively maintained and future updates and improvements will be released periodically by lead developer Jason Caldwell. The popularity of this plugin and recent acknowldegments at WordCamp in Boston have inspired Jason to revamp ZenCache! -* The latest version of ZenCache is a complete rewrite (OOP design). Faster! and even more dependable. NOTE: the free version of ZenCache (this new LITE version); while it remains fully functional and is more-than-adequate for most sites; is now limited in some ways. The following advanced features from the previous release are no longer available in the lite version: a custom MD5 Version Salt; custom Exclusion Patterns; the Clear Cache button in the admin bar. These, and MANY other brand new features are now available only in the pro version of the plugin. For further details, please see: . -* Bug fix. ZenCache now considers the `HTTPS` evironment variable in order to prevent cache collisions on sites that serve pages over SSL. Nothing to configure, this is now built into the ZenCache engine. -* UI updates. An improved user interface makes configuring this plugin a dream! ZenCache got an awesome makeover in this release. -* Improved support for multisite networks. It's never been easier to run ZenCache on a multisite network. For further details, please see: **Dashboard -› Network Admin -› ZenCache** when/if you have Multisite Networking enabled in WordPress. -* Update; PUT and DELETE requests are now considered by ZenCache. By default, ZenCache does NOT serve cached pages to users who are logged in, or to users who have left comments recently. ZenCache also excludes administrative pages, login pages, POST/PUT/DELETE/GET(w/ query string) requests and/or CLI processes. -* Dropping support for `ob_gzhandler()`; and the like. ZenCache will now throw PHP exceptions to warn you about this should it be an issue in your hosting environment. If you want to enable GZIP, please follow the instructions provided by ZenCache and avoid the use of `ob_gzhandler()` as this is not a recommended way to enable GZIP on any hosting platform. -* Truly atomic cache file write updates. Removing support for SEM vs. FLOCK for file locking. ZenCache no longer needs a mutex file. Cache file updates are written to a temp file and renamed for the best reliability and improved speed too! -* Localization. ZenCache is now translatable. This release adds support for gettext translations, a very popular method for translating WordPress plugins. All parts of the ZenCache plugin can be localized now. The source code was updated with calls to the `__` function and a new text domain was added: `zencache`. PO translation files should be placed in your plugins directory, example: `/wp-content/plugins/zencache-en_US.mo`; or in `WP_LANG_DIR/plugins/zencache-en_US.mo`. -* Capability requirement. This release of ZenCache requires that an Administrator be logged-in with the Capability of `activate_plugins`. This is a default Capability that comes with the Administrator Role in WordPress. So, unless you've modified your WordPress Roles/Capabilities in some extremely creative way, this should not impact you; just something to be aware of. -* **(Pro Version)** There is now a pro version of this plugin available. Please see: . The initial set of pro features include: the ability to cache logged-in users too! (VERY powerful, particularly for membership sites); a new improved "Clear Cache" button in the admin bar (along with an option to enable/disable this feature); the ability to disable Dashboard notifications related to automatic clearing/purging on change detections; Import/Export functionality for ZenCache configuration files; URI exclusion patterns (now supporting wildcards too); User-Agent exclusion patterns (now supporting wildcards too); HTTP referrer exclusion patterns (now supporting wildcards too); an MD5 Version Salt; and rockstar support for all ZenCache features. -* **(Pro Version)** Regarding URI/User-Agent/HTTP Referrer exclusion patterns. If you configured any of these options in the previous release and would like to continue to use them in this release, please upgrade to the pro version or contact lead developer Jason Caldwell for assistance. Note: if you had these options configured in the previous release, once you upgrade to the pro version they will come back just like they were. Either that, or you may choose to continue using the previous version of ZenCache where this functionality still exists. -* Lite version source code now available on GitHub also: . - -= v111203 = - -* Updated to support WordPress® v3.3. Backward compatibily remains for WordPress® v3.2.x. - -= v110720 = - -* Bug fix. Corrected XSS security issue associated with the handling of ``$_SERVER["REQUEST_URI"]`` inside the comment lines that ZenCache introduces at the bottom of the source code. -* Bug fix. Corrected cosmetic issue in WordPress v3.2 related to the positioning of the Clear Cache button. - -= v110709 = - -* Routine maintenance. No signifigant changes. - -= v110708 = - -* Routine maintenance. No signifigant changes. -* Compatibility with WordPress v3.2. - -= v110523 = - -* **Versioning.** Starting with this release, versions will follow this format: `yymmdd`. The version for this release is: `110523`. -* Routine maintenance. No signifigant changes. - -= v2.3.6 = - -* Routine maintenance. No signifigant changes. - -= v2.3.5 = - -* Bug fix. Under the right scenario, errors regarding the function `is_user_logged_in()` in the second phase of `advanced-cache.php` have been resolved in this release of ZenCache. -* Compatibility. ZenCache is now capable of dealing with themes/plugins that attempt to use `ob_start("ob_gzhandler")` inside a `header.php` file, or in other places that may create a problem in the nesting order of output buffers. For instance, this release of ZenCache resolves some incompatiblities with Headway themes for WordPress®. Please note that GZIP should be enabled at the Apache level ( i.e. with an .htaccess file ), or in PHP using `zlib.output_compression = on`. Both of these methods are preferred over `ob_start("ob_gzhandler")`. If you must use `ob_start("ob_gzhandler")`, please make this declaration inside your `/wp-config.php` file, and NOT inside `/header.php`, as this creates a problem that ZenCache must work around, and could ultimately prevent GZIP from working at all if you do it this way. For further details on how to enable GZIP with ZenCache, please see the included `/readme.txt` file. - -= v2.3.2 = - -* Compatiblity. References to `dirname()` that were processed by the ZenCache `/advanced-cache.php` handler should have been using `WP_CONTENT_DIR` for improved compatibility with WordPress® installations that may use non-standardized installation directories and/or symlinks. -* New Filter available for developers. Multisite Super Admins can now give their Child Blog owners the ability to manually clear the cache for their own site in the Network. ZenCache accomplishes this by making the "Clear Cache" button visible in the administrative header for Child Blog owners. If you wish to enable this, you can use this Filter: `add_filter("ws_plugin__qcache_ms_user_can_see_admin_header_controls", "__return_true");`. This button is always visible to Super Admins. Adding this Filter makes it visible to all child Blog Owners as well. - -= v2.3.1 = - -* Framework updated; general cleanup. -* Optimizations. Further internal optimizations applied through configuration checksums that allow ZenCache to load with even less overhead now. -* Bug fix. ZenCache was suffering from a bug regression related to stale Last-Modified headers being sent with cached copies. This has been resolved in ZenCache v2.3.1+. - -= v2.3 = - -* Framework updated; general cleanup. -* Updated with static class methods. ZenCache now uses PHP's SPL autoload functionality to further optimize all of its routines. - -= v2.2.8 = - -* Framework updated; general cleanup. -* Updated for compatibility with WordPress® 3.1. - -= v2.2.7 = - -* Framework updated. General cleanup. - -= v2.2.6 = - -* Updated to disable caching on database failures that do not trigger a `5xx` error code. ZenCache is now capable of disabling the cache engine dynamically on all database connection failures within WordPress®. - -= v2.2.5 = - -* Updated to support all `5xx` error codes. ZenCache now monitors the `status_header` function for `5xx` error codes. If a `5xx` status header is detected, caching is automatically disabled, as it should be. - -= v2.2.3 = - -* Framework updated. General cleanup. - -= v2.2.2 = - -* Minor updates to the Ajax clearing routines that were implemented in v2.2.1. -* This update also adds compatibility with (offline) localhost installations of WordPress® (WAMP/MAMP). - -= v2.2.1 = - -* Support for `glob()` has been added to ZenCache. In previous versions, it was impossible to pinpoint a specific cache file through Dynamic Pruning routines ( at least, not with 100% accuracy ). This was because an MD5 Version Salt *could* have been generated; based on arbitrary conditionals, set by the site owner. ZenCache now stores its cache files with three MD5 hash strings, producing longer file names; but with the added benefit of improved Multisite compatibility, and improvements in optimization overall. ZenCache can now handle dynamic pruning with 100% accuracy. Even supporting complex Multisite installations, with or without `SUBDOMAIN_INSTALL`. -* New feature. ZenCache now integrates a `Clear ZenCache` button into the WordPress® Dashboard. This makes it easy to force a "cache reset, via ajax", without having to navigate through the ZenCache menu for this simple task. Another great benefit to this new button, is that it works in all Dashboard views, even in a Multisite installation across different backends. If you're running a Multisite installation, you can use this new button to clear the cache for a particular site/blog in your network, without interrupting others. -* Bug fix. The Constant `ZENCACHE_ALLOWED` was being defined too early in the buffering routine. This has been resolved in v2.2.1. -* Optimization of `advanced-cache.php`. A few things have been streamlined even further. -* Added compatibility for the [WP Maintenance Mode](http://wordpress.org/extend/plugins/wp-maintenance-mode/) plugin, and also the [Maintenance Mode](http://wordpress.org/extend/plugins/maintenance-mode/) plugin. ZenCache will disable itself when these plugins are enabled for maintenance. -* Added compatibility for other Maintenance Mode plugins that are capable of sending a `Status: 503` header, or a `Retry-After:` header. -* Added compatibility for plugins that create PHP sessions. ZenCache will automatically disable itself when a PHP session is active. -* Added compatiblity for web hosts that insert a port number into the `$_SERVER["HTTP_HOST"]` variable. ZenCache is now capable of handling this gracefully. -* Improvement. Removed references to `$blog_id = 1` in favor of `is_main_site()`; providing support for Multisite Mode, where there are multiple sites, instead of just multiple blogs. -* Updated Dynamic Pruning Hooks for Custom Post Types, and Custom Taxonomies in WordPress® 3.0+. -* Extended compatiblity for ZenCache on SSL enabled blogs. - -= v2.1.9 = - -* Framework updated; general cleanup. -* Updated minimum requirements to WordPress® 3.0. - -= v2.1.8 = - -* Framework updated to WS-P-3.0. - -= v2.1.7 = - -* Bug fix. A bug related to gzinflate variations handled by the WP_Http class has been resolved. This was preventing ZenCache from validating a custom MD5 Version Salt on some servers. -* Framework updated to WS-P-2.3. - -= v2.1.6 = - -* Auto-Cache Engine. References to `ws_plugin__qcache_curl_get()`, have been replaced by `c_ws_plugin__qcache_utils_urls::remote()`, which makes use of `wp_remote_request()` through the WP_Http class. This removes an absolute dependency on the cURL extension for PHP. This also gives ZenCache/WordPress® the ability to decide with method of communication to use for HTTP requests; based on what the installation server has available. Note: this only affects the Auto-Cache Engine for ZenCache, which is completely optional. -* Compatibility. ZenCache is now smarter about the way it reports errors. For example, when/if there are directory permission issues with your `wp-content` directory; ZenCache can help with this, in a more intuitive fashion. -* Compatibility. Support has been added for WordPress® 3.0 with Multisite/Networking enabled. -* Updated minimum requirements to WordPress® 2.9.2. -* Framework updated to WS-P-2.2. - -= v2.1.5 = - -* A new option for Dynamic Cache Pruning was added. You can now choose `Single + Front Page`. This makes it possible to Create or Edit a Post/Page, and have the cache automatically updated for that specific Post/Page. And.. in addition, your Front Page ( aka: Home Page ) will also be refreshed at the same time. -* A minor bug was fixed in the Dynamic Cache Pruning routines. This bug was originally introduced in ZenCache v2.1.1, and has now been corrected in v2.1.5. This bug, under certain circumstances, was preventing ZenCache from locating an expired md5 cache file, for some Posts/Pages being updated. -* Advanced feature addition. ZenCache now comes bundled with a robust Auto-Cache Engine. This is an optional feature, for VERY advanced users. You'll find the new Auto-Cache Engine listed right along with all of the other ZenCache options. This works in conjunction with an XML Sitemap. - -= v2.1.4 = - -* Advanced feature addition. You can now prevent caching dynamically whenever pages on your site receive traffic from specific URLs, specific domains, or even specific word fragments found within the HTTP_REFERER. This feature is very advanced, and will NOT impact your site unless you decide to use it for one reason or another. - -= v2.1.3 = - -* Added `De-Activation Safeguards` to the ZenCache options panel. -* Updated the ZenCache options panel. It's been given a make-over. -* Stable tag updated in support of tagged releases within the repository at WordPress.org. - -= v2.1.2 = - -* WebSharks Framework for Plugins has been updated to P-2.1. -* Updated caching routines in support of hosting providers running with CGI/FastCGI. ZenCache has been tested with VPS.net, HostGator, BlueHost, (mt) Media Temple (gs) and (dv), The Rackspace Cloud, and several dedicated servers ( including some Amazon EC2 instances ) running with Apache; including support for both `mod_php` and also `CGI/FastCGI` implementations. ZenCache should work fine with any Apache/PHP combination. Please report all bugs through the [Support Forum](http://www.primothemes.com/forums/viewforum.php?f=5). -* An issue was discovered with WordPress® MU `/files/` being accessed through `htaccess/mod_rewrite`. ZenCache has been updated to exclude all `/files/` served under WordPress® MU, which is the way it should be. Requests that contain `/files/` are a reference to WordPress® Media, and there is no reason, to cache, or send no-cache headers, for Media. ZenCache now ignores all references to `/files/` under WordPress® MU. This problem was not affecting all installations of WPMU, because there already are/were scans in place for Content-Type headers. However, under some CGI/FastCGI implementations, this was not getting picked on WMPU with `mod_rewrite` rules. This has been resolved in v2.1.2. - -= v2.1.1 = - -* A WPMU bug was corrected in ZenCache v2.1.1. This bug was related to `HTTP_HOST` detection under WordPress® MU installations that were using sub-domains. Please thank `QuickSander` for reporting this important issue. - -= v2.1 = - -* ZenCache has added further support for themes and plugins that dynamically set `Content-Type` headers through PHP routines. ZenCache is now smart enough to automatically disable itself whenever a theme or plugin sends a `Content-Type` header that would be incompatible with ZenCache. In other words, any `Content-Type` header that is not a variation of `HTML, XHTML or XML`. -* ZenCache has also been upgraded to support the preservation of scripted headers sent by PHP routines. If a plugin or theme sends scripted headers ( using the `header()` function in PHP ), those headers will be preserved. They'll be stored along with the cache. This allows them to be sent back to the browser whenever a cached version is served on subsequent visits to the original file. -* Compatability checked against WordPress.org 2.9.1, 2.9.2 & WordPress MU 2.9.1, 2.9.2. Everything looks good. No changes required. - -= v2.0 = - -* A few tweaks to the options panel. -* Documentation updated, several small improvements in error reporting. -* Additional error checking to support an even wider range of hosting providers. -* Added automation routines for safe re-activation after an upgrade is performed. - -= v1.9 = - -* Additional support added for WordPress® MU 2.8.6+. -* Security file `zencache-mu.php` added specifically for MU installations. WordPress® MU is a special ( multi-user ) version of WordPress®. If you're running WordPress® MU, check the [readme.txt] file for WordPress® MU notations. - -= v1.8 = - -* Re-organized core framework. Updated to: P-2.0. -* Updated to support WP 2.9+. - -= v1.7 = - -* Updated documentation. Added some additional code samples. -* Tested with WP 2.8.5. Everything ok. - -= v1.6 = - -* We've added the ability to enable Double-Caching ( client-side caching ). Full documentation is provided in the ZenCache options panel. This feature is for those of you who just want blazing fast speed and are not concerned as much about reliability and control. We don't recommend turning this on unless you realize what you're doing. - -= v1.5 = - -* Support for Dynamic Cache Pruning has been improved. Full documentation is provided in the ZenCache options panel. -* Additional feature-specific documentation has been added to assist novice webmasters during configuration. - -= v1.4 = - -* Garbage collection has been further optimized for speed and performance on extremely high traffic sites. -* PHP Ternary expressions are now supported in your Version Salt. This takes your Version Salt to a whole new level. -* Additional code samples have been provided for Version Salts; showing you how to deal with mobile devices and other tricky situations. - -= v1.3 = - -* We've implemented both Semaphore ( `sem_get` ) and `flock()` mutex. If you're on a Cloud Computing Model ( such as the Rackspace® Cloud ), then you'll want to go with flock() unless they tell you otherwise. In all other cases we recommend the use of Semaphores over Flock because it is generally more reliable. The folks over at Rackspace® have suggested the use of flock() because of the way their Cloud handles multi-threading. In either case, flock() will be fully functional in any hosting environment, so it makes a great fallback in case you experience any problems. - -= v1.2 = - -* We've implemented a way for plugin developers to disallow caching during certain routines or on specific pages. You can set the following PHP Constant at runtime to disable caching. `define("ZENCACHE_ALLOWED", false)`. We have also added backward compatibility for WP Super Cache, so that `define("DONOTCACHEPAGE", true)` will also be supported by plugins that have previously been written for compatibility with Super Cache. In other words, ZenCache looks for either of these two Constants. - -= v1.1 = - -* Added the ability to create a Version Salt. This is a feature offered ONLY by ZenCache. Full documentation is provided in the ZenCache options panel. This can become very useful for sites that provide membership services or have lots and lots of plugins installed that makes their site incompatible with WP Super Cache. With ZenCache, you'll now have more control over the entire caching process using a custom Version Salt tailored to your specific needs. - -= v1.0 = - -* Initial release. \ No newline at end of file diff --git a/zencache/client-s/css/menu-pages.css b/zencache/client-s/css/menu-pages.css deleted file mode 100644 index 2f47268..0000000 --- a/zencache/client-s/css/menu-pages.css +++ /dev/null @@ -1,449 +0,0 @@ -@import url('//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css'); -@import url('../../submodules/sharkicons/styles.min.css'); - -/* -Wrap background. -*/ -#wpwrap -{ - position : relative; -} -#wpwrap::after -{ - top : 0; - left : 0; - bottom : 0; - right : 0; - z-index : -1; - position : absolute; - - content : ''; - background : url('../images/bg.png'); - opacity : 0.25; -} -/* -Align these with menu page. -*/ -div.updated, div.error -{ - margin : 1.25em 1.25em 1.25em .25em; -} -/* -Menu page styles. -*/ -.plugin-menu-page -{ - min-width : 800px; - margin : 1.25em 1.25em 1.25em .25em; -} -.plugin-menu-page, -.plugin-menu-page p -{ - font-size : 14px; -} -.plugin-menu-page a -{ - color : #23263E; -} -.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 : .1em .25em .1em .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%; - color : #EEEEEE; - background : #222222; - overflow-x : auto; - max-width : 100%; - - border-radius : 4px; - padding : 1em; - display : block; - box-shadow : 0 0 5px 1px #000000 inset; -} -.plugin-menu-page img -{ - border : 0; -} -.plugin-menu-page img.screenshot -{ - float : right; - margin : 0 0 2em 2em; - - border-radius : 4px; - border : 1px solid #AFAFAF; - - box-shadow : 0 0 5px 0 rgba(0, 0, 0, 0.2) inset; - background : #FFFFFF; - padding : .5em; -} -.plugin-menu-page hr -{ - border : 0; - padding : 0; - height : 1px; - margin : 1em 0 1em 0; - background : linear-gradient(to left, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0)); -} -.plugin-menu-page label -{ - -webkit-user-select : none; - -moz-user-select : none; - user-select : none; -} -.plugin-menu-page label.switch-primary -{ - display : inline; - font-size : 130%; - color : #000000; - - margin : 0; - padding : .5em; - - border-radius : 4px; - 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 #FFFFFF inset; -} -.plugin-menu-page input:not([type='radio']):not([type='checkbox']), -.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus, -.plugin-menu-page select, .plugin-menu-page select:focus, -.plugin-menu-page textarea, .plugin-menu-page textarea:focus -{ - width : 100%; - - margin : 0; - padding : .25em .5em .25em .5em; - - line-height : 1.3em; - border-radius : 4px; - box-sizing : border-box; - border : 1px solid #848484; - - color : #333333; - background : #E8E8E8; - 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 #FFFFFF inset, 0 -2px 3px 0 rgba(132, 132, 132, 0.25) inset; -} -.plugin-menu-page input:not([type='radio']):not([type='checkbox']), -.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus, -.plugin-menu-page select, .plugin-menu-page select:focus -{ - height : 2em; -} -.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus, -.plugin-menu-page select:focus, .plugin-menu-page textarea:focus -{ - color : #000000; - background : #e2e2e2; -} -.plugin-menu-page input::-webkit-input-placeholder -{ - font-style : italic; - color : rgba(0, 0, 0, 0.2); -} -.plugin-menu-page input::-moz-placeholder -{ - font-style : italic; - color : rgba(0, 0, 0, 0.2); -} -.plugin-menu-page input:-moz-placeholder -{ - font-style : italic; - color : rgba(0, 0, 0, 0.2); -} -.plugin-menu-page input:-ms-input-placeholder -{ - font-style : italic; - color : rgba(0, 0, 0, 0.2); -} -.plugin-menu-page input[disabled], -.plugin-menu-page select[disabled], -.plugin-menu-page textarea[disabled] -{ - opacity : 0.5; -} -.plugin-menu-page table -{ - margin : 1em 0 1em 0; -} -.plugin-menu-page button -{ - line-height : 1em; - font-size : 150%; - font-weight : bold; - color : #FFFFFF; - background : #23263E; - - border-radius : 4px; - 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; - - margin : 0; - box-sizing : border-box; - padding : .25em .5em .25em .5em; - - outline : none; - - cursor : pointer; - -webkit-user-select : none; - -moz-user-select : none; - user-select : none; -} -.plugin-menu-page button:hover -{ - background : #467629; -} -.plugin-menu-page button[type='submit'] -{ - background : #467629; -} -.plugin-menu-page button[type='submit']:hover -{ - background : #23263E; -} -.plugin-menu-page button:active -{ - -webkit-transform : scale(0.98, 0.98); - transform : scale(0.98, 0.98); -} -.plugin-menu-page .pro-preview -{ - opacity : 0.5; -} -.plugin-menu-page .info, -.plugin-menu-page .notice, -.plugin-menu-page .warning, -.plugin-menu-page .error -{ - border-radius : 4px; - padding : .5em; - margin : 1em 0 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 #D29A04; -} -.plugin-menu-page .error -{ - background : #FFC0CB; - 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; -} -/* -Heading styles. -*/ -.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 : #23263E !important; -} -.plugin-menu-page-heading .plugin-menu-page-upsells -{ - float : right; - clear : right; - - max-width : 350px; - margin : 1em 0 0 0; - - text-align : center; -} -.plugin-menu-page-heading .plugin-menu-page-upsells a -{ - line-height : 1.5em; - text-decoration : none; - margin : 0 .5em 0 .5em; - display : inline-block; -} -/* -Section heading styles. -*/ -.plugin-menu-page-section-heading -{ - margin : 1em 0 1em 0; -} -.plugin-menu-page-section-heading > small -{ - font-size : 65%; - opacity : 0.5; - font-style : italic; - display : block; - margin : .25em 0 0 0 !important; -} -/* -Panel styles. -*/ -.plugin-menu-page-panel -{ - margin : 1em 0 1em 0; -} -.plugin-menu-page-panel:first-child -{ - margin-top : 0; -} -.plugin-menu-page-panel-heading -{ - display : block; - text-decoration : none; - - padding : 10px; - font-size : 150%; - font-weight : bold; - background : #23263E; - color : #DDDDDD !important; - - border-radius : 4px; - box-shadow : 0 2px 2px 0 rgba(0, 0, 0, 0.25); - - cursor : pointer; - -webkit-user-select : none; - -moz-user-select : none; - user-select : none; -} -.plugin-menu-page-panel-heading:hover, -.plugin-menu-page-panel-heading.open -{ - color : #FFFFFF !important; -} -.plugin-menu-page-panel-heading:after -{ - font-size : 80%; - content : '\f078'; - font-weight : normal; - font-family : 'FontAwesome'; - - float : right; - margin : 0 0 0 5px; - display : inline-block; -} -.plugin-menu-page-panel-heading.open:after -{ - content : '\f077'; -} -.pro-preview .plugin-menu-page-panel-heading:after -{ - font-variant : small-caps !important; - font-family : sans-serif !important; - content : 'pro version only' !important; -} -.plugin-menu-page-panel-body -{ - width : 99%; - margin : 0 auto 0 auto; - box-sizing : border-box; - - display : none; - - padding : 1.2em; - color : #222222; - - border : 1px solid #848484; - background : #FFFFFF; - - border-bottom-left-radius : 4px; - border-bottom-right-radius : 4px; - - 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-body.open -{ - display : block; -} -.plugin-menu-page-panel-body p -{ - color: #666666; - font-size : 90%; -} -.plugin-menu-page-panel-body p.notice, -.plugin-menu-page-panel-body p.info, -.plugin-menu-page-panel-body p.warning, -.plugin-menu-page-panel-body p.error -{ - color: #000000; -} -.plugin-menu-page-panel-body h3 -{ - margin : 0 0 .5em 0; -} -.plugin-menu-page-panel-body h3:first-child -{ - margin-top : 0; -} -.plugin-menu-page-panel-body h3 + p -{ - margin-top : 0; -} -/* -Save button styles. -*/ -.plugin-menu-page-save -{ - margin-top : 2em; -} -.plugin-menu-page-save button[type='submit'] -{ - width : 100%; - line-height : 1.3em; -} diff --git a/zencache/client-s/css/menu-pages.min.css b/zencache/client-s/css/menu-pages.min.css deleted file mode 100644 index 8403a00..0000000 --- a/zencache/client-s/css/menu-pages.min.css +++ /dev/null @@ -1 +0,0 @@ -@import url('//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css');@import url('../../submodules/sharkicons/styles.min.css');#wpwrap{position:relative}#wpwrap::after{top:0;left:0;bottom:0;right:0;z-index:-1;position:absolute;content:'';background:url('../images/bg.png');opacity:.25}div.updated,div.error{margin:1.25em 1.25em 1.25em .25em}.plugin-menu-page{min-width:800px;margin:1.25em 1.25em 1.25em .25em}.plugin-menu-page,.plugin-menu-page p{font-size:14px}.plugin-menu-page a{color:#23263e}.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:.1em .25em .1em .25em;background:rgba(178,178,178,0.25);font-family:'Menlo','Monaco','Consolas','Courier New',monospace}.plugin-menu-page pre.code{padding:0;background:0}.plugin-menu-page pre.code>code{font-size:90%;color:#eee;background:#222;overflow-x:auto;max-width:100%;border-radius:4px;padding:1em;display:block;box-shadow:0 0 5px 1px #000 inset}.plugin-menu-page img{border:0}.plugin-menu-page img.screenshot{float:right;margin:0 0 2em 2em;border-radius:4px;border:1px solid #afafaf;box-shadow:0 0 5px 0 rgba(0,0,0,0.2) inset;background:#fff;padding:.5em}.plugin-menu-page hr{border:0;padding:0;height:1px;margin:1em 0 1em 0;background:linear-gradient(to left,rgba(0,0,0,0),rgba(0,0,0,0.75),rgba(0,0,0,0))}.plugin-menu-page label{-webkit-user-select:none;-moz-user-select:none;user-select:none}.plugin-menu-page label.switch-primary{display:inline;font-size:130%;color:#000;margin:0;padding:.5em;border-radius:4px;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 input:not([type='radio']):not([type='checkbox']),.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus,.plugin-menu-page select,.plugin-menu-page select:focus,.plugin-menu-page textarea,.plugin-menu-page textarea:focus{width:100%;margin:0;padding:.25em .5em .25em .5em;line-height:1.3em;border-radius:4px;box-sizing:border-box;border:1px solid #848484;color:#333;background:#e8e8e8;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 input:not([type='radio']):not([type='checkbox']),.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus,.plugin-menu-page select,.plugin-menu-page select:focus{height:2em}.plugin-menu-page input:not([type='radio']):not([type='checkbox']):focus,.plugin-menu-page select:focus,.plugin-menu-page textarea:focus{color:#000;background:#e2e2e2}.plugin-menu-page input::-webkit-input-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input::-moz-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input:-moz-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input:-ms-input-placeholder{font-style:italic;color:rgba(0,0,0,0.2)}.plugin-menu-page input[disabled],.plugin-menu-page select[disabled],.plugin-menu-page textarea[disabled]{opacity:.5}.plugin-menu-page table{margin:1em 0 1em 0}.plugin-menu-page button{line-height:1em;font-size:150%;font-weight:bold;color:#fff;background:#23263e;border-radius:4px;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;margin:0;box-sizing:border-box;padding:.25em .5em .25em .5em;outline:0;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.plugin-menu-page button:hover{background:#467629}.plugin-menu-page button[type='submit']{background:#467629}.plugin-menu-page button[type='submit']:hover{background:#23263e}.plugin-menu-page button:active{-webkit-transform:scale(0.98,0.98);transform:scale(0.98,0.98)}.plugin-menu-page .pro-preview{opacity:.5}.plugin-menu-page .info,.plugin-menu-page .notice,.plugin-menu-page .warning,.plugin-menu-page .error{border-radius:4px;padding:.5em;margin:1em 0 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 #d29a04}.plugin-menu-page .error{background:#ffc0cb;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:#23263e !important}.plugin-menu-page-heading .plugin-menu-page-upsells{float:right;clear:right;max-width:350px;margin:1em 0 0 0;text-align:center}.plugin-menu-page-heading .plugin-menu-page-upsells a{line-height:1.5em;text-decoration:none;margin:0 .5em 0 .5em;display:inline-block}.plugin-menu-page-section-heading{margin:1em 0 1em 0}.plugin-menu-page-section-heading>small{font-size:65%;opacity:.5;font-style:italic;display:block;margin:.25em 0 0 0 !important}.plugin-menu-page-panel{margin:1em 0 1em 0}.plugin-menu-page-panel:first-child{margin-top:0}.plugin-menu-page-panel-heading{display:block;text-decoration:none;padding:10px;font-size:150%;font-weight:bold;background:#23263e;color:#ddd !important;border-radius:4px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.25);cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.plugin-menu-page-panel-heading:hover,.plugin-menu-page-panel-heading.open{color:#fff !important}.plugin-menu-page-panel-heading:after{font-size:80%;content:'\f078';font-weight:normal;font-family:'FontAwesome';float:right;margin:0 0 0 5px;display:inline-block}.plugin-menu-page-panel-heading.open:after{content:'\f077'}.pro-preview .plugin-menu-page-panel-heading:after{font-variant:small-caps !important;font-family:sans-serif !important;content:'pro version only' !important}.plugin-menu-page-panel-body{width:99%;margin:0 auto 0 auto;box-sizing:border-box;display:none;padding:1.2em;color:#222;border:1px solid #848484;background:#fff;border-bottom-left-radius:4px;border-bottom-right-radius:4px;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-body.open{display:block}.plugin-menu-page-panel-body p{color:#666;font-size:90%}.plugin-menu-page-panel-body p.notice,.plugin-menu-page-panel-body p.info,.plugin-menu-page-panel-body p.warning,.plugin-menu-page-panel-body p.error{color:#000}.plugin-menu-page-panel-body h3{margin:0 0 .5em 0}.plugin-menu-page-panel-body h3:first-child{margin-top:0}.plugin-menu-page-panel-body h3+p{margin-top:0}.plugin-menu-page-save{margin-top:2em}.plugin-menu-page-save button[type='submit']{width:100%;line-height:1.3em} \ No newline at end of file diff --git a/zencache/client-s/images/auto-clear-ss.png b/zencache/client-s/images/auto-clear-ss.png deleted file mode 100644 index bcc264519c8bea407af6433ed49d293071eca52d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14401 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 diff --git a/zencache/client-s/images/clear-response.png b/zencache/client-s/images/clear-response.png deleted file mode 100644 index e490498462ab1cbe9aaf7e79b70ceb423a184fe7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2348 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 diff --git a/zencache/client-s/images/cloudfront-logo.png b/zencache/client-s/images/cloudfront-logo.png deleted file mode 100644 index dae82ee4d1e914d34ce1ab6b55def76d39b8a0d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14879 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 RFc1I$002ovPDHLkV1n!-&ei|` diff --git a/zencache/client-s/images/gzip.png b/zencache/client-s/images/gzip.png deleted file mode 100644 index dff8e6c0733022d999c3d1f1e24263c6048bb601..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13333 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 diff --git a/zencache/client-s/images/inline-icon-logo.svg b/zencache/client-s/images/inline-icon-logo.svg deleted file mode 100644 index 732a077..0000000 --- a/zencache/client-s/images/inline-icon-logo.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/zencache/client-s/images/inline-icon.svg b/zencache/client-s/images/inline-icon.svg deleted file mode 100644 index 3780fe2..0000000 --- a/zencache/client-s/images/inline-icon.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/zencache/client-s/images/maxcdn-logo.png b/zencache/client-s/images/maxcdn-logo.png deleted file mode 100644 index 51d1688769c622e428cd83748ee05ec401fc164d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5730 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 diff --git a/zencache/client-s/images/salt.png b/zencache/client-s/images/salt.png deleted file mode 100644 index e3c0ce43a9391cd699de6b8877263fdb736f74d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17415 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 diff --git a/zencache/client-s/images/tach.png b/zencache/client-s/images/tach.png deleted file mode 100644 index 2c2feda9929962dacfbe192ecf7980e1cba7dbaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19027 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 diff --git a/zencache/client-s/images/updater.png b/zencache/client-s/images/updater.png deleted file mode 100644 index 0da46617c82e06159e7bbfe7f92ab7d69f02995e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10390 zcmcI~Ra9Kd7A+RsU4y$f-e`ga5AGH`K^ynr8fYAXI|O%k2+~-9;BKLDZ=9EN?tSn7 ze!QPu`=eHkwN{OqHRl`^^-)zG3!NMt4h{}W;e(6@92`9O@4q7|^4~AoM_D{LI2L0C znRi-V@F&?QS%linuN6LY`s#QM!iXVpXnQ^3+GM?<)zR=95{QxJA*YA4rDn_SdR9Yy zwUzBh)hyP={u0Le=2$!-46T2pR6u=&IXL~^H~zDMh> zQ{u3NHQ1__c6fdfDhopNSGv6aX`n??9(spoyMszN-K}wF%e)%z?9@t;g#ihqfpZG& z3DF%;+KS&&+vKcG{JXM@loZtmq>udNzv-RfI9pLA5KmEJ3e$0>g4234DJN-y$gNAeJ5s;jU@fsU*Cq4 z3uCw#M+3&Uf-;(u$bA`J4cebn|6 zd2-de1ppN4=L8T^yAr9lOnd*|6wDy@IvBei@EW02q#QA24P&8~yZ6ML@!xz1gE-`+ ztjTsZN6*(e?Z2SiK$sqnIckf;@~01p{z-Yn5y_J8iSdp}PjI3k=#pnUzzhC3XMGI0 zV-ER0E5M_`i$p&Xa!@QU$*l3p*>@nkP@bay-y$sW5L!MdxezZkh&CG`K(L~?vfu3* z3vZ}QfBf5yzg@|*!ec4)A%of=j?OG;JBx5Ybidi*q7_mwA2$7GAEmD7X|mm#IWVYV zIJM7tgo&RM$KmUc_|@=iF;Fcba+Zd@^%G572Za!imClLN0gs!lV|@}!X+)9WrX|5| zQ|*ms*Y}nB1QnU1OfF`C3NYgj+H(%!x8L4xs@1Ogl_k?440S!MS)wS5*!_ta_c+Nh z0r*}5O~bT=t&rw|iZIPrG(Q>u8G4vnt&<(XPV3H}Z5)|onlr37Z-+40hBHc7(Uabk_FkH zP--})vwgr0B2XorsV)haaLbCYH?X-nE6jE<#JM>(7PK1y({_tyAx%SL#^uj<&XM%2 zsiS~6GSWh10aAJlB#O~ehB7pnqLIy!p7SksClBth{Z-W@R)HMjfoS}WhX>r^e~u#E034~bA76N2jjJK&6n z&1a^kS2OQ^ryq?(Zv@KOeqBaO3DVJcPBXo~v`LI>5m8vjgvmw|5o^5g-@U(M(0kjr zhV7w{%Ge#!6JFY{)(^N;CPC|drm|v3B^grZQ1eZpFVNV>jSwYh*HYS5x}(y2yUkp< z(wJbCDSzU1BfG36m`f+>#h>!bry9m|4;xtMs~_deJY(NNG#^bm>evD?tAdG_lZiQh z$l#3tknr7UaLi$9nM)o}8g7;P$u1UVs-WaE(svQU*ctw)XJ_YVp)CX2=ZNQ-&OaC) zHawEWlt~@D%hEeHdI!vF1~vh)mu-o08h6BcauWrbCSBhFzd}3`-_CJogp0(V!o+*_ z=*Cv$G8`5G($})hWMI*OonP6gtGjskr7mFCu7q=tSAlExWUpc=;CC^qB?dwi5S&`8 z3-s<`IB6q(`{rz)a9#NhUyRHI9uj$lqBmb`mAru{f!B?YIt+q&-f@S{EEUy1(O6l{ z(@^z{hm$7>r=#D=ExG~rI36Ljt6ylE0}vsVc9MEo*^8cB9CpKf)O|bVE>ar0S4not zhV{%m7`Klz6h?kMudH7pzbxL47-kyEYGueKa&H8hbB7)JAG$%_FW zZKw79^jL>TQ!V;{zu|VJGSI6q-QFkXNarAO0Gj*GaT>?74hy-*w4lEa9LBzsS zTK#uMh2$lK{E#!Ux%fe@*4#Odr%#ycH5Pg|eH$Qxf~P-xs@A*1cT~-RUX*RHYqfA{0{v59XuXmZ&dKP4pZc3OB zrRIGwtXN){ucNPU6XT5L9|(#aQ5A>Tl|$@>rj56Jx*-A!qT&r+Fl)Wc_PE^j{+a~5fY2$h7A46-ZIKnICzv-$!Jy$KKayY z6B<62D|?y9B+_R+zXDsn>BCUp?vUP`g0z@A&FTGoC@`^F;4;=?42cOXD=Ru4cRyMX z3&N(92gHEUw0BHVHTB~7V}THs(>15hcF^*HKNG&X*1zqTmjkq2o7S3bldQ=0>mT;I zu#bf7f2GZ?t2Mr3WJHXA+FyCF=?#09s}mO05gPIhMRgT)G!gD8DzZQ557XxJWRQDJ zR@WDtwjy;2u^1r;oqFI=luM!Rt-iWLyy&Z?{uAVd$jRt|z`;k5Z?VZNUAHT-x)d*p zxP&F()W0oe$y$XOfT}v@O|vWoi5kVU4o}jM6P}6sGEEqyu9EbgHE@rw{2hMbXn#SX z=BeP(aoZCb_xpIKKU+;vuP(YirD+Gw)Ym2QF(heOfW*RuBv0XZTMd1%BL(8;!_Pf= z7KfQ{=8J}qc+T)DTPj*JZqlMyIJlsJCevk^TflgkvBuEY<9EndzCJb5kbt)}FZRwf zGZ(LGyw|S%8$bEl)w_i$J+!~ z-|_Lb{FE>rI~msF5$Z_K0oo=Hr9T%-1L(QfP;B=?%$GtgRff7CW8E*4FInch*-y|_ z_+TgT1azLUE_G|-gv-@Ns_Z)Nc;D<3T8q`mcPjyMS&q#shXdVTt@LqHlCQa=wD(8o z)ofA*$>V1eo~J9Bk)_-E@}Bj6ZIx2vLKag!XzClU$XBt~F>!*5rInKhuX0aNd*0od zMiDDZsm^QGT#Q6nj9nQqle^mxUzWC!rwS@A51so7Q#Fz^(o@Q6ObtLkF3Y(`5+v*? zK+j>pRyx~XsPY>dE9o2JdX`fKe%GGlBu}B%u|0p_7*E+CbIMT@`$o5lS)6@YXLhvt`X8`&m*gZR$ zux(UcM0YMb$c;H)yc4(DnQxX<(T2sBl?%&*p1dSZ>LTymn|f|@!#+i8DwNV{US6#I z+t2#j4(|<{ImG$bAl52uqaP7WU}c!)j=W9dT(>L|_4cnHkVCV&?9$}MAh-NvgCnt` z-?KRdp2ZPEPMu>PlBdte8T=8KOCpIf(BI2)igsyPTPDcUK}Ku5hZj*v4(m z(Lw2F(4f7HE4O*nK%zg6r!h=%8}i9ukzbQ?s!6rpzE$#<7Q+eanHPV~Uex2aF}c7U zvM5uki`}(v-hB_XUj5%|{?Q#$^{D(Uh;1m+Y96uA1Y566=B*sGqa1Pv7Q)+eY{{A3 z@%m-UyJezuZ<d(QJ>AA{Pfp&?q`w<<4-B2p+H<5QgUr1!k}xqX(Q}ixbXn;)Vt zKIx*nd*oGi_%(iQ16zr8WQ8)-xoA^GyUQg?^g zFRIaKV$I7%rOL49x={_tH6OfMmvFaK6gyDoPzwK#gt0^lQU-!U>h4&F58XpArTVqf zoZEp920-vLCZnubnp~c-$!Xfkm!pUW^BBV=DS z6qgJ_ZyTEUf~|?7#v+q45mn7%$KuZ)kpPjst8JQ=ZP!bfI{7~uDE|pXUw$SiJt;)n zP$j@#CmTU`Q&mke(Qb&L>9uGQwXa$U$hRZ&w*{0!l|^^WNV;y{-Z)2Y(`L?9E;PNRbliAQ9*4Qh7Nl&jv6~ZR%4oZZQwpOKxNzdWWp6zm$m$r#VS<#jQ zer}bDnj=XaeQS)o-kt5R{cgg!&%c^u;kdoPSg!wQ&kwlpw-VhG0^>^76W{fyDn0-y zBgc{6da~)uvdDYzx#tcFx=nc;epd4;BUq5ai;RX_*_D@>n8W-Vdrnt7!9QWMvgZl( z+v@+3u^#*3LMyFyw^+6QjP?-^l$5v1!6JlZomi6JS)&;g>dL2|ap*{Z+Nkt{s6<52 z?E4v`cC$L|Ix>t@-W&EMxiT$UN*U?y+1M`Ky5vzywSiAf=v&Q0@@d;f@+e9H{{RE_pugCd_h9arv;U6(5?LB%vw(Kn0ByD@$1hTGEiebP zHH{T;0iG<41j2orx8}@+T>qWG30QCYiWsUz8JSg|s0%?K&9%2@NxjD*!yD5`jb#f& z_6)Idk}1cc`M6rKab_33s^E97ZtW#N=%Rd|IPK1m(ZJQb zKV)fo7P*Tjf#RDxe`IO*Urz^&_KzT=Dl@XC#CHtdOCBd~Eru#!di~~oFKANQ?+aWY z|E~pPi5nzC6*(?uiA?AArt>46{(BI@xc_FFaDt-VX`JqVQyif|h!V!t|B={*lh1qp zC13B>Z$x55Uc+?Ja{L;Oana^%@n-ZtD$pAwZqq9BoMt$$13c+_2nAOTPwSQKKV zk2M?obR*_dutn2>BP#s79wu0IuFdeh)`3J05}l$NLf6cylQEx_mf0~{o%WUu?MHb{ z_9TokKI$_sV8!#G!}505JpnWFk5qsfZQGf&t>=I}Y1u9>vtl6%^y>Nf8hj z2H408EMbfH=?9=xMen*7-2XHIZP%eq)45*0E7+tbifi+6k&lF)EE%_xd3NRFKRt&txWT_7?adLp;jIM zj2w6+AK<~R8_Pw0A-O)X_e;6|yUl@#-}45F9#^LAZTBD^<2H%4#MvVTyB%ntW!RW`;k%>92ep3112)yOZCoY|i}rJ&43%<+D5X z;LlUN4Mi~&{0jRoqe&S9$`OV!6P%y^WQk}?65p^rG8)R(G)2NIXn#f~E61t$@niXI z)!oy*wrh+pjQvklXkaW;k~_4dt(~XkT&V7N`3ua^v(mWdmSb5PUx};YQu%6&5reJN zDn(_&Y<&BTw%SGBG=~1zlRlqTS}L1f_YWhno=f%qvIhipSAL5$88c|Xj|FenyNPy6+B?KxBYD`k6f&Gm%}8*mEW>CcR#_oL07 zzt3%ZGTngAx!?OIPe-muK#o3QDBw?wu_CTHTdC;r5 zwq_uTeg#(X!}SsrXTo1|+2HlCvlo)DZ#2Vw_&u=l(%QrXn&_=bcdG9VAxg^vF~;oz zQnenZbwmb}h!_w7m>C0}H~4%d!`mV_yarSsbo|_x9Ap$m+p>jY6NnyBI?mRc4CL0K zQk8eD@3LKm=BQ0Rv%-M8+8X{ABkcc1)q+!VvY`tmqp9`37sU~kjs%3J8; z4ju|~g`h+A=Bik6f!z9eT8bsg$?LAZ!k)P? zZyn+Skr;-r(cU7tH;b7JxtHOKxz2RiX4SipyLE(E+|MO(RZ52wE_m!8=v+2A?^_JR z#g`3}Q7G00Z@QOx*BjjiA2$+7Ue1MP7d7)bgQ#un{>8dY%vB^yUev!GD?$rO=fee7 z)@DSAZD$5RCr8{@5TUJ;=lgFQu9T~L&P$q7y&`Vk#Lv&og?8Qjr2QlDzM58zcS zQU3HjQ*p?RCNknAp;qwY5tovH&JaNM?UWR@D~;H9VE!X`|^YA)RFZxxfj|H{`mVqH_IBIP*x5Y9_{HcZY zWv!P~L-tp_c;31f;?L+w1OZ1h4H-07V+vu`r|F|aE8Td$Pn-5j9)Es1oSQuU+T)B+ zxu|RWhMlvaD}B*_>piT(w$W~YKcgQAbQd74zzd0cInBz-YKg$1ehJ_g&hfh(C8+7V z9K$KxQ+fzRBk-A}&Be?ed_9**osT&>JX~jFx34`ulrmX2V|yManWMTXwyO54-x`b} zSgFx(*srUo>GmnB*nyVjt`{~pd!TzrNH5o{UhA0ytUf_w(nzL)2HA5{{kjJcDF~N- zV%=ER(l6)=6?xN@u4zm+tk>o+j}{rRL}aL^AtwNpQrEb!Ig11sm*w>G*PlRVzWQD&??N!dNzr8*tU%l9j4HqX$xCW3rp;O*T` zJj8dyX~*}8h8$N-{6-5e&Wv1jmmzCpm`+z;KcmBbslG5OM`kGrO|817W+TR#C>z8m zhW65F*y6~YNKChj5WA`N=lw%&&`3x8&yDj-2=|%i#Sls9o;HH$=au_5kCWxXGEsXt z3Acmko5f2J=w(hEkI#OF4RF(ltA8sLxzo|Q5>TxS9LNqVaQm#Ho@QtGr|^AuFVkSs z70N73mg)krIr&C|3VVNQ9Z4vzP$cJ0ZS4!%5vQh!NEBj}bhE!IJ(}cAx;5vC?LL}N!l`n3G(FlFj>3(lp=RMBWyVwkNpawi+YjM?^p z;BLwQY8zUbORZVnC-!UFzlqh_gUMT`B?jELssK;0h8AtuE~ zkjl+1TH+MGPWq@Yj@^neL%0Z7&#IrW2ujCJh3aGtiJ$NO>HyKu=NQ9)@QZ|LsWX?B zeh0e(S;m8S1l3RpIxYZ-Q$Aj#?vy3A{}* zyIk~-ucNM1+5aM0m%|_JW4)p?4yIJ~ljY4Smf~jqAClSaor0(JF2EsIyQfE+YSRBYo@xiJFK=|FkRNj3oegH8eAmLl&jgNO)Jje?Iwrs5=sq@z{Sj#KK~m4yXCum5I*O<|M_ z<}6XC<^lBsvqHzpKfXuZl-jl4jmJ;NyOz355>~|cMev1M))C7qow4Cre~dg*0$LXT zr=9tN`oJC*-+)7)BTjMYIgumoi{#6FwG<;VwH9-Mu7I*$ZQMaa@#5=oym*1)^mZ>? z^Ym5IF(FfR*>-!OpQ<+DaVECvT+*fbRhH#ZOl9l?upWkMgih~sL#RN|?@bwh<)3np zlaG{3%`5LK;a=WK2PQQ7u1VzeeEK^oU0J1o}U?%)cW>4DV@DoaHrE>0CMqrc999ZDUpqN%nVwT>-&o5 z4U^aSIq?a^AQ+pz%nWeHU{4CiDCetr7q6B{F=kh^gu7|$NaAGGY_6pnSCv#8!^BWp zJCdfZ_mf5EnXE#KNM7135U?JZ%KDdM&amF*xjwU{QhIxj$hgtCozDbT6(a`VW(eue z+ymmO)0Y{Q!$F&{TL%J{aW!a?HNb-DHE@jh91MWRH86uD@kqHb67}XB-7=0o! z;^^!C;27=W^@J=b&WY2r?o0*cB}@9IGZQhYk4$2bzQ!h|)mir9;`rBgZ(7kU*K;fl%9$3!EKE(ni{Y&ZaU@Jutn{Y^pdEaB^^0>Z@WVHxqH>L@tVx5Tz9k zL{7S?6vjyyg+P3F=M$c$Db3$v2v7jjW_%lLO@sr1CeGHfA}0gY8# z7u+M)dDGTYAS2z&9;*@%$_>_jo0-)vBxiR1<@s?TLK}Che*<%nzZs-y0z>uDP)Vfz zfas;Xdx;#!Vy4-|dZBktKylWjQM@oiFZe(*g)_NNBVUb zfdX@o+Th;1m0D2e86rtbYa{W*%Gx1ie!cgEJY*z&gmel zX24r4qyZI5&;cD(dc216nc$b5eK?fR%|gL0V^=tp^WmQ9MkTuRqha?YhKMPw+ZF-7 z)Jj{s(9&^5NDr2Wp&Elsl>_gD?-+7m0wK3!@CXX=N-vZjjNC`j;Kq7*y}*Xw1NkzI z=Y?TF$8?J)(Q0LOqS}e9Knjm%mYRDrf%F&Mk`kAwN6b&3k}9jUdKxI{(~@XJQwueJ z4?W*tIauD_b75celaOxTKcx($qA*PHBMP+x%IB$3)8*UR`ISWxUN?n&#Hr5Y?JWc4 zP+GaE&b?L1c3mxCFz3EI+p+vZz8vP9L*_^<=(wMbN|4ghz$E5m0>(ixm(sdwz0rE_oMl} z*aP-0k#Rw;LTqToW!nq*mO~Ea8L8+ypKxltmZ9o>)?_$wIufvB!jGPr+y_;antHq0 z66?{W_=K}~&fP-UZjEaihgDy>uR$^+{YdBdz7f0>xKipmCVHaZ)nsk9lM2$g_9Kpb z8OY2j7uxeavMq0gorG6oExlNOSWw0CbU-?Aj&UKBbqn37)9+3$og90{q4n7cBe|`t zt`107J;w)jmxX+E6Z;SZBem-}CHzJ@J&L>w?Y68QpdG1XWc|d=kej3hAP^y{Hb?Xo z^Qf^Dbcf5ncTTSELyJoruGuuQo>`KV`twp?s9&_lKa+zT0d2hD)t#h}V+*085^`Gi zqq~{Pe`zxDj^Y!Aa`Ev9Wf!+kt~5IwjcTlO2yq&;DhY!%RbFEAh}0dsa9y4 zoa&OOMT?qi&5A}Db`ht4<}z^)>L%&IaG@w^&%+FBysIzTqxH0%Bv`d8V?KpQNiV~3 zw*%&|I6?rB)0l$&I_ysZ6>;)(R{`T~Pv+fZ&2-<<7-mOoPC=RVKL=Dd`IB@EVh%oQ zgeRx%J1sVI%(NFIEL5+>CqWjRKvpZCSonAc7O~HYZapHfoV5IUyltX?{`bAx|BqoA dAK?`R4z$sTkxz;6_q`#Uf~=}c^?S46{{yW%_$>ec diff --git a/zencache/client-s/images/wipe-response.png b/zencache/client-s/images/wipe-response.png deleted file mode 100644 index 9f57015d856365a011c1fa2ea49a63900d5fa72d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3452 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 Y1Bn%6V(BcA2mk;807*qoM6N<$g6FieSO5S3 diff --git a/zencache/client-s/js/menu-pages.js b/zencache/client-s/js/menu-pages.js deleted file mode 100644 index a72ea4d..0000000 --- a/zencache/client-s/js/menu-pages.js +++ /dev/null @@ -1,45 +0,0 @@ -(function($) -{ - 'use strict'; // Standards. - - var plugin = {}, $window = $(window), $document = $(document); - - plugin.onReady = function() // jQuery DOM ready event handler. - { - var $menuPage = $('#plugin-menu-page'); - - $('.plugin-menu-page-panels-open', $menuPage).on('click', function() - { - $('.plugin-menu-page-panel-heading', $menuPage).addClass('open') - .next('.plugin-menu-page-panel-body').addClass('open'); - }); - $('.plugin-menu-page-panels-close', $menuPage).on('click', function() - { - $('.plugin-menu-page-panel-heading', $menuPage).removeClass('open') - .next('.plugin-menu-page-panel-body').removeClass('open'); - }); - $('.plugin-menu-page-panel-heading', $menuPage).on('click', function(e) - { - e.preventDefault(), // Prevent click event. - $(this).toggleClass('open').next('.plugin-menu-page-panel-body').toggleClass('open'); - }); - $('[data-action]', $menuPage).on('click', function() - { - var $this = $(this), data = $this.data(); - if(typeof data.confirmation !== 'string' || confirm(data.confirmation)) - location.href = data.action; - }); - $('select[name$="_enable\\]"], select[name$="_enable_flavor\\]"]', $menuPage).not('.no-if-enabled').on('change', function() - { - var $this = $(this), thisName = $this[0].name, thisValue = $this.val(), - $thisPanel = $this.closest('.plugin-menu-page-panel'); - - if((thisName.indexOf('_enable]') !== -1 && (thisValue === '' || thisValue === '1')) - || (thisName.indexOf('_flavor]') !== -1 && thisValue !== '0')) // Enabled? - $thisPanel.find('.plugin-menu-page-panel-if-enabled').css('opacity', 1).find(':input').removeAttr('readonly'); - else $thisPanel.find('.plugin-menu-page-panel-if-enabled').css('opacity', 0.4).find(':input').attr('readonly', 'readonly'); - }) - .trigger('change'); // Initialize. - }; - $document.ready(plugin.onReady); // On DOM ready. -})(jQuery); \ No newline at end of file diff --git a/zencache/client-s/js/menu-pages.min.js b/zencache/client-s/js/menu-pages.min.js deleted file mode 100644 index d79daae..0000000 --- a/zencache/client-s/js/menu-pages.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(b){var a={},d=b(window),c=b(document);a.onReady=function(){var e=b("#plugin-menu-page");b(".plugin-menu-page-panels-open",e).on("click",function(){b(".plugin-menu-page-panel-heading",e).addClass("open").next(".plugin-menu-page-panel-body").addClass("open")});b(".plugin-menu-page-panels-close",e).on("click",function(){b(".plugin-menu-page-panel-heading",e).removeClass("open").next(".plugin-menu-page-panel-body").removeClass("open")});b(".plugin-menu-page-panel-heading",e).on("click",function(f){f.preventDefault(),b(this).toggleClass("open").next(".plugin-menu-page-panel-body").toggleClass("open")});b("[data-action]",e).on("click",function(){var g=b(this),f=g.data();if(typeof f.confirmation!=="string"||confirm(f.confirmation)){location.href=f.action}});b('select[name$="_enable\\]"], select[name$="_enable_flavor\\]"]',e).not(".no-if-enabled").on("change",function(){var i=b(this),g=i[0].name,f=i.val(),h=i.closest(".plugin-menu-page-panel");if((g.indexOf("_enable]")!==-1&&(f===""||f==="1"))||(g.indexOf("_flavor]")!==-1&&f!=="0")){h.find(".plugin-menu-page-panel-if-enabled").css("opacity",1).find(":input").removeAttr("readonly")}else{h.find(".plugin-menu-page-panel-if-enabled").css("opacity",0.4).find(":input").attr("readonly","readonly")}}).trigger("change")};c.ready(a.onReady)})(jQuery); \ No newline at end of file diff --git a/zencache/includes/.htaccess b/zencache/includes/.htaccess deleted file mode 100644 index 910246c..0000000 --- a/zencache/includes/.htaccess +++ /dev/null @@ -1,6 +0,0 @@ - - Require all denied - - - deny from all - \ No newline at end of file diff --git a/zencache/includes/ac-plugin.example.php b/zencache/includes/ac-plugin.example.php deleted file mode 100644 index 766ab10..0000000 --- a/zencache/includes/ac-plugin.example.php +++ /dev/null @@ -1,43 +0,0 @@ -add_filter(get_class($ac).'__version_salt', 'my_ac_version_salt_shaker'); -} - -my_ac_plugin(); // Run this plugin. - -/* - * Any other function(s) that may support your plugin. - */ - -function my_ac_version_salt_shaker($version_salt) // Salt shaker. -{ - if(stripos($_SERVER['HTTP_USER_AGENT'], 'iphone') !== FALSE) - $version_salt .= 'iphones'; // Give iPhones their own variation of the cache. - - else if(stripos($_SERVER['HTTP_USER_AGENT'], 'android') !== FALSE) - $version_salt .= 'androids'; // Give Androids their own variation of the cache. - - else $version_salt .= 'other'; // A default group for all others. - - return $version_salt; -} - diff --git a/zencache/includes/actions.php b/zencache/includes/actions.php deleted file mode 100644 index f10cb94..0000000 --- a/zencache/includes/actions.php +++ /dev/null @@ -1,188 +0,0 @@ -plugin = plugin(); - - if(empty($_REQUEST[__NAMESPACE__])) return; - foreach((array)$_REQUEST[__NAMESPACE__] as $action => $args) - if(method_exists($this, $action)) $this->{$action}($args); - } - - public function wipe_cache($args) - { - if(!current_user_can($this->plugin->network_cap)) - return; // Nothing to do. - - if(empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) - return; // Unauthenticated POST data. - - $counter = $this->plugin->wipe_cache(TRUE); // Counter. - - $redirect_to = self_admin_url('/admin.php'); // Redirect preparations. - $query_args = array('page' => __NAMESPACE__, __NAMESPACE__.'__cache_wiped' => '1'); - $redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to); - - wp_redirect($redirect_to).exit(); // All done :-) - } - - public function clear_cache($args) - { - if(!current_user_can($this->plugin->cap)) - return; // Nothing to do. - - if(empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) - return; // Unauthenticated POST data. - - $counter = $this->plugin->clear_cache(TRUE); // Counter. - - $redirect_to = self_admin_url('/admin.php'); // Redirect preparations. - $query_args = array('page' => __NAMESPACE__, __NAMESPACE__.'__cache_cleared' => '1'); - $redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to); - - wp_redirect($redirect_to).exit(); // All done :-) - } - - public function save_options($args) - { - if(!current_user_can($this->plugin->cap)) - return; // Nothing to do. - - if(empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) - return; // Unauthenticated POST data. - - $args = array_map('trim', stripslashes_deep((array)$args)); - if(isset($args['base_dir'])) // No leading/trailing slashes please. - $args['base_dir'] = trim($args['base_dir'], '\\/'." \t\n\r\0\x0B"); - - $this->plugin->options = array_merge($this->plugin->default_options, $this->plugin->options, $args); - $this->plugin->options = array_intersect_key($this->plugin->options, $this->plugin->default_options); - - if(!trim($this->plugin->options['base_dir'], '\\/'." \t\n\r\0\x0B") // Empty? - || strpos(basename($this->plugin->options['base_dir']), 'wp-') === 0 // Reserved? - ) $this->plugin->options['base_dir'] = $this->plugin->default_options['base_dir']; - - update_option(__NAMESPACE__.'_options', $this->plugin->options); // Blog-specific. - if(is_multisite()) update_site_option(__NAMESPACE__.'_options', $this->plugin->options); - - $redirect_to = self_admin_url('/admin.php'); // Redirect preparations. - $query_args = array('page' => __NAMESPACE__, __NAMESPACE__.'__updated' => '1'); - - $this->plugin->auto_wipe_cache(); // May produce a notice. - - if($this->plugin->options['enable']) // Enable. - { - if(!($add_wp_cache_to_wp_config = $this->plugin->add_wp_cache_to_wp_config())) - $query_args[__NAMESPACE__.'__wp_config_wp_cache_add_failure'] = '1'; - - if(!($add_advanced_cache = $this->plugin->add_advanced_cache())) - $query_args[__NAMESPACE__.'__advanced_cache_add_failure'] - = ($add_advanced_cache === NULL) - ? 'zc-advanced-cache' : '1'; - - $this->plugin->update_blog_paths(); - } - else // We need to disable ZenCache in this case. - { - if(!($remove_wp_cache_from_wp_config = $this->plugin->remove_wp_cache_from_wp_config())) - $query_args[__NAMESPACE__.'__wp_config_wp_cache_remove_failure'] = '1'; - - if(!($remove_advanced_cache = $this->plugin->remove_advanced_cache())) - $query_args[__NAMESPACE__.'__advanced_cache_remove_failure'] = '1'; - } - $redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to); - - wp_redirect($redirect_to).exit(); // All done :-) - } - - public function restore_default_options($args) - { - if(!current_user_can($this->plugin->cap)) - return; // Nothing to do. - - if(empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) - return; // Unauthenticated POST data. - - delete_option(__NAMESPACE__.'_options'); // Blog-specific. - if(is_multisite()) delete_site_option(__NAMESPACE__.'_options'); - $this->plugin->options = $this->plugin->default_options; - - $redirect_to = self_admin_url('/admin.php'); // Redirect preparations. - $query_args = array('page' => __NAMESPACE__, __NAMESPACE__.'__restored' => '1'); - - $this->plugin->auto_wipe_cache(); // May produce a notice. - - if($this->plugin->options['enable']) // Enable. - { - if(!($add_wp_cache_to_wp_config = $this->plugin->add_wp_cache_to_wp_config())) - $query_args[__NAMESPACE__.'__wp_config_wp_cache_add_failure'] = '1'; - - if(!($add_advanced_cache = $this->plugin->add_advanced_cache())) - $query_args[__NAMESPACE__.'__advanced_cache_add_failure'] - = ($add_advanced_cache === NULL) - ? 'zc-advanced-cache' : '1'; - - $this->plugin->update_blog_paths(); - } - else // We need to disable ZenCache in this case. - { - if(!($remove_wp_cache_from_wp_config = $this->plugin->remove_wp_cache_from_wp_config())) - $query_args[__NAMESPACE__.'__wp_config_wp_cache_remove_failure'] = '1'; - - if(!($remove_advanced_cache = $this->plugin->remove_advanced_cache())) - $query_args[__NAMESPACE__.'__advanced_cache_remove_failure'] = '1'; - } - $redirect_to = add_query_arg(urlencode_deep($query_args), $redirect_to); - - wp_redirect($redirect_to).exit(); // All done :-) - } - - public function dismiss_notice($args) - { - if(!current_user_can($this->plugin->cap)) - return; // Nothing to do. - - if(empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) - return; // Unauthenticated POST data. - - $args = array_map('trim', stripslashes_deep((array)$args)); - if(empty($args['key'])) return; // Nothing to dismiss. - - $notices = (is_array($notices = get_option(__NAMESPACE__.'_notices'))) ? $notices : array(); - unset($notices[$args['key']]); // Dismiss this notice. - update_option(__NAMESPACE__.'_notices', $notices); - - wp_redirect(remove_query_arg(__NAMESPACE__)).exit(); - } - - public function dismiss_error($args) - { - if(!current_user_can($this->plugin->cap)) - return; // Nothing to do. - - if(empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'])) - return; // Unauthenticated POST data. - - $args = array_map('trim', stripslashes_deep((array)$args)); - if(empty($args['key'])) return; // Nothing to dismiss. - - $errors = (is_array($errors = get_option(__NAMESPACE__.'_errors'))) ? $errors : array(); - unset($errors[$args['key']]); // Dismiss this error. - update_option(__NAMESPACE__.'_errors', $errors); - - wp_redirect(remove_query_arg(__NAMESPACE__)).exit(); - } - } - - new actions(); // Initialize/handle actions. -} \ No newline at end of file diff --git a/zencache/includes/advanced-cache.tpl.php b/zencache/includes/advanced-cache.tpl.php deleted file mode 100644 index 5283421..0000000 --- a/zencache/includes/advanced-cache.tpl.php +++ /dev/null @@ -1,1217 +0,0 @@ - - * @license GNU General Public License, version 2 - */ -namespace zencache -{ - if(!defined('WPINC')) // MUST have WordPress. - exit('Do NOT access this file directly: '.basename(__FILE__)); - - advanced_cache_back_compat::QUICK_CACHE_constants(); - advanced_cache_back_compat::qcAC_qcABC_vars(); - - if(!defined('ZENCACHE_PRO')) - /** - * ZenCache Pro flag. - * - * @since 140422 First documented version. - * - * @var string|integer|boolean A boolean-ish value; e.g. `1` or `0`. - */ - define('ZENCACHE_PRO', FALSE); // Lite version. - - if(!defined('ZENCACHE_ENABLE')) - /** - * Is ZenCache enabled? - * - * @since 140422 First documented version. - * - * @var string|integer|boolean A boolean-ish value; e.g. `1` or `0`. - */ - define('ZENCACHE_ENABLE', '%%ZENCACHE_ENABLE%%'); - - if(!defined('ZENCACHE_DEBUGGING_ENABLE')) - /** - * Is ZenCache debugging enabled? - * - * @since 140422 First documented version. - * - * @var string|integer|boolean A boolean-ish value; e.g. `1` or `0`. - */ - define('ZENCACHE_DEBUGGING_ENABLE', '%%ZENCACHE_DEBUGGING_ENABLE%%'); - - if(!defined('ZENCACHE_ALLOW_BROWSER_CACHE')) - /** - * Allow browsers to cache each document? - * - * @since 140422 First documented version. - * - * @var string|integer|boolean A boolean-ish value; e.g. `1` or `0`. - * - * @note If this is a `FALSE` (or an empty) value; ZenCache will send no-cache headers. - * If `TRUE`, ZenCache will NOT send no-cache headers. - */ - define('ZENCACHE_ALLOW_BROWSER_CACHE', '%%ZENCACHE_ALLOW_BROWSER_CACHE%%'); - - if(!defined('ZENCACHE_GET_REQUESTS')) - /** - * Cache `$_GET` requests w/ a query string? - * - * @since 140422 First documented version. - * - * @var string|integer|boolean A boolean-ish value; e.g. `1` or `0`. - */ - define('ZENCACHE_GET_REQUESTS', '%%ZENCACHE_GET_REQUESTS%%'); - - if(!defined('ZENCACHE_CACHE_404_REQUESTS')) - /** - * Cache 404 errors? - * - * @since 140422 First documented version. - * - * @var string|integer|boolean A boolean-ish value; e.g. `1` or `0`. - */ - define('ZENCACHE_CACHE_404_REQUESTS', '%%ZENCACHE_CACHE_404_REQUESTS%%'); - - if(!defined('ZENCACHE_FEEDS_ENABLE')) - /** - * Cache XML/RSS/Atom feeds? - * - * @since 140422 First documented version. - * - * @var string|integer|boolean A boolean-ish value; e.g. `1` or `0`. - */ - define('ZENCACHE_FEEDS_ENABLE', '%%ZENCACHE_FEEDS_ENABLE%%'); - - if(!defined('ZENCACHE_DIR')) - /** - * Directory used to store cache files; relative to `WP_CONTENT_DIR`. - * - * @since 140422 First documented version. - * - * @var string Absolute server directory path. - */ - define('ZENCACHE_DIR', WP_CONTENT_DIR.'/'.'%%ZENCACHE_DIR%%'); - - if(!defined('ZENCACHE_MAX_AGE')) - /** - * Cache expiration time. - * - * @since 140422 First documented version. - * - * @var string Anything compatible with PHP's {@link \strtotime()}. - */ - define('ZENCACHE_MAX_AGE', '%%ZENCACHE_MAX_AGE%%'); - - if(!defined('ZENCACHE_404_CACHE_FILENAME')) - /** - * 404 file name (if applicable). - * - * @since 140422 First documented version. - * - * @var string A unique file name that will not conflict with real paths. - * This should NOT include the extension; basename only please. - */ - define('ZENCACHE_404_CACHE_FILENAME', '----404----'); - - if(!defined('ZENCACHE_PLUGIN_FILE')) - /** - * Plugin file path. - * - * @since 140725 Reorganizing class members. - * - * @var string Absolute server path to QC plugin file. - */ - define('ZENCACHE_PLUGIN_FILE', '%%ZENCACHE_PLUGIN_FILE%%'); - - /* - * Include shared methods between {@link advanced_cache} and {@link plugin}. - */ - if(defined('WP_DEBUG') && WP_DEBUG) - require_once dirname(ZENCACHE_PLUGIN_FILE).'/includes/share.php'; - else if((@require_once(dirname(ZENCACHE_PLUGIN_FILE).'/includes/share.php')) === FALSE) - return; // Unable to find class dependency. Fail softly. - - /** - * ZenCache (Advanced Cache Handler) - * - * @package zencache\advanced_cache - * @since 140422 First documented version. - */ - class advanced_cache extends share # `/wp-content/advanced-cache.php` - { - /** - * Microtime; defined by class constructor for debugging purposes. - * - * @since 140422 First documented version. - * - * @var float Result of a call to {@link \microtime()}. - */ - public $timer = 0; - - /** - * Flagged as `TRUE` if QC advanced cache is active & running. - * - * @since 140605 Improving output buffers - * - * @var boolean `TRUE` if QC advanced cache is active & running. - */ - public $is_running = FALSE; - - /** - * Calculated protocol; one of `http://` or `https://`. - * - * @since 140422 First documented version. - * - * @var float One of `http://` or `https://`. - */ - public $protocol = ''; - - /** - * Calculated version salt; set by site configuration data. - * - * @since 140422 First documented version. - * - * @var string|mixed Any scalar value does fine. - */ - public $version_salt = ''; - - /** - * Calculated cache path for the current request; - * absolute relative (no leading/trailing slashes). - * - * @since 140422 First documented version. - * - * @var string Absolute relative (no leading/trailing slashes). - * Defined by {@link maybe_start_output_buffering()}. - */ - public $cache_path = ''; - - /** - * Calculated cache file location for the current request; absolute path. - * - * @since 140422 First documented version. - * - * @var string Cache file location for the current request; absolute path. - * Defined by {@link maybe_start_output_buffering()}. - */ - public $cache_file = ''; - - /** - * Centralized 404 cache file location; absolute path. - * - * @since 140422 First documented version. - * - * @var string Centralized 404 cache file location; absolute path. - * Defined by {@link maybe_start_output_buffering()}. - */ - public $cache_file_404 = ''; - - /** - * A possible version salt (string value); followed by the current request location. - * - * @since 140422 First documented version. - * - * @var string Version salt (string value); followed by the current request location. - * Defined by {@link maybe_start_output_buffering()}. - */ - public $salt_location = ''; - - /** - * Array of data targeted at the postload phase. - * - * @since 140422 First documented version. - * - * @var array Data and/or flags that work with various postload handlers. - */ - public $postload = array( - 'filter_status_header' => TRUE, 'wp_main_query' => TRUE, - 'set_debug_info' => ZENCACHE_DEBUGGING_ENABLE, - ); - - /** - * An array of debug info. - * - * @since 140605 Improve output buffering. - * - * @var array An array of debug info; i.e. `reason_code` and `reason` (optional). - */ - public $debug_info = array('reason_code' => '', 'reason' => ''); - - /** - * Have we caught the main WP loaded being loaded yet? - * - * @since 140422 First documented version. - * - * @var boolean `TRUE` if main query has been loaded; else `FALSE`. - * - * @see wp_main_query_postload() - */ - public $is_wp_loaded_query = FALSE; - - /** - * Is the current request a WordPress 404 error? - * - * @since 140422 First documented version. - * - * @var boolean `TRUE` if is a 404 error; else `FALSE`. - * - * @see wp_main_query_postload() - */ - public $is_404 = FALSE; - - /** - * Last HTTP status code passed through {@link \status_header}. - * - * @since 140422 First documented version. - * - * @var integer Last HTTP status code (if applicable). - * - * @see maybe_filter_status_header_postload() - */ - public $http_status = 0; - - /** - * Is the current request a WordPress content type? - * - * @since 140605 Improving debug notes display. - * - * @var boolean `TRUE` if is a WP content type. - * - * @see wp_main_query_postload() - */ - public $is_a_wp_content_type = FALSE; - - /** - * Current WordPress {@link \content_url()}. - * - * @since 140725 Reorganizing class members. - * - * @var string Current WordPress {@link \content_url()}. - * - * @see wp_main_query_postload() - */ - public $content_url = ''; - - /** - * Flag for {@link \is_user_loged_in()}. - * - * @since 140422 First documented version. - * - * @var boolean `TRUE` if {@link \is_user_loged_in()}; else `FALSE`. - * - * @see wp_main_query_postload() - */ - public $is_user_logged_in = FALSE; - - /** - * Flag for {@link \is_maintenance()}. - * - * @since 140422 First documented version. - * - * @var boolean `TRUE` if {@link \is_maintenance()}; else `FALSE`. - * - * @see wp_main_query_postload() - */ - public $is_maintenance = FALSE; - - /** - * Value for {@link plugin::$file()}. - * - * @since 140422 First documented version. - * - * @var string The value of {@link plugin::$file()}. - * - * @see wp_main_query_postload() - */ - public $plugin_file = ZENCACHE_PLUGIN_FILE; - - /** - * No-cache because of the current {@link \PHP_SAPI}. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_PHP_SAPI_CLI = 'nc_debug_php_sapi_cli'; - - /** - * No-cache because the current request includes the `?zcAC=0` parameter. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_QCAC_GET_VAR = 'nc_debug_zcac_get_var'; - - /** - * No-cache because of a missing `$_SERVER['HTTP_HOST']`. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_NO_SERVER_HTTP_HOST = 'nc_debug_no_server_http_host'; - - /** - * No-cache because of a missing `$_SERVER['REQUEST_URI']`. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_NO_SERVER_REQUEST_URI = 'nc_debug_no_server_request_uri'; - - /** - * No-cache because the {@link \ZENCACHE_ALLOWED} constant says not to. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_ZENCACHE_ALLOWED_CONSTANT = 'nc_debug_zencache_allowed_constant'; - - /** - * No-cache because the `$_SERVER['ZENCACHE_ALLOWED']` environment variable says not to. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_ZENCACHE_ALLOWED_SERVER_VAR = 'nc_debug_zencache_allowed_server_var'; - - /** - * No-cache because the {@link \DONOTCACHEPAGE} constant says not to. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_DONOTCACHEPAGE_CONSTANT = 'nc_debug_donotcachepage_constant'; - - /** - * No-cache because the `$_SERVER['DONOTCACHEPAGE']` environment variable says not to. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR = 'nc_debug_donotcachepage_server_var'; - - /** - * No-cache because the current request method is uncacheable. - * - * @since 140725 Adding HEAD/OPTIONS/TRACE to the list of uncacheables. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_UNCACHEABLE_REQUEST = 'nc_debug_uncacheable_request'; - - /** - * No-cache because the current request originated from the server itself. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_SELF_SERVE_REQUEST = 'nc_debug_self_serve_request'; - - /** - * No-cache because the current request is for a feed. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_FEED_REQUEST = 'nc_debug_feed_request'; - - /** - * No-cache because the current request is systematic. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_WP_SYSTEMATICS = 'nc_debug_wp_systematics'; - - /** - * No-cache because the current request is for an administrative area. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_WP_ADMIN = 'nc_debug_wp_admin'; - - /** - * No-cache because the current request is multisite `/files/`. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_MS_FILES = 'nc_debug_ms_files'; - - /** - * No-cache because the current user is like a logged-in user. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_IS_LIKE_LOGGED_IN_USER = 'nc_debug_is_like_logged_in_user'; - - /** - * No-cache because the current user is logged into the site. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_IS_LOGGED_IN_USER = 'nc_debug_is_logged_in_user'; - - /** - * No-cache because the current request contains a query string. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_GET_REQUEST_QUERIES = 'nc_debug_get_request_queries'; - - /** - * No-cache because the current request is a 404 error. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_404_REQUEST = 'nc_debug_404_request'; - - /** - * No-cache because the requested page is currently in maintenance mode. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_MAINTENANCE_PLUGIN = 'nc_debug_maintenance_plugin'; - - /** - * No-cache because the current request is being compressed by an incompatible ZLIB coding type. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_OB_ZLIB_CODING_TYPE = 'nc_debug_ob_zlib_coding_type'; - - /** - * No-cache because the current request resulted in a WP error message. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_WP_ERROR_PAGE = 'nc_debug_wp_error_page'; - - /** - * No-cache because the current request is serving an uncacheable content type. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_UNCACHEABLE_CONTENT_TYPE = 'nc_debug_uncacheable_content_type'; - - /** - * No-cache because the current request sent a non-2xx & non-404 status code. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_UNCACHEABLE_STATUS = 'nc_debug_uncacheable_status'; - - /** - * No-cache because this is a new 404 error that we are symlinking. - * - * @since 140422 First documented version. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_1ST_TIME_404_SYMLINK = 'nc_debug_1st_time_404_symlink'; - - /** - * No-cache because we detected an early buffer termination. - * - * @since 140605 Improving output buffer. - * - * @var string A unique string identifier in the set of `NC_DEBUG_` constants. - */ - const NC_DEBUG_EARLY_BUFFER_TERMINATION = 'nc_debug_early_buffer_termination'; - - /** - * Class constructor/cache handler. - * - * @since 140422 First documented version. - */ - public function __construct() - { - parent::__construct(); // Shared constructor. - - if(!WP_CACHE || !ZENCACHE_ENABLE) - return; // Not enabled. - - if(defined('WP_INSTALLING') || defined('RELOCATE')) - return; // N/A; installing|relocating. - - $this->is_running = TRUE; - $this->timer = microtime(TRUE); - - $this->load_ac_plugins(); - $this->register_shutdown_flag(); - $this->maybe_stop_browser_caching(); - $this->maybe_start_output_buffering(); - } - - /** - * Loads any advanced cache plugin files found inside `/wp-content/ac-plugins`. - * - * @since 140422 First documented version. - */ - public function load_ac_plugins() - { - if(!is_dir(WP_CONTENT_DIR.'/ac-plugins')) - return; // Nothing to do here. - - $GLOBALS[__NAMESPACE__.'__advanced_cache'] - = $this; // Define now; so it's available for plugins. - - if(!isset($GLOBALS['quick_cache__advanced_cache'])) // Back compat. - $GLOBALS['quick_cache__advanced_cache'] = &$GLOBALS[__NAMESPACE__.'__advanced_cache']; - - foreach((array)glob(WP_CONTENT_DIR.'/ac-plugins/*.php') as $_ac_plugin) - if(is_file($_ac_plugin)) include_once $_ac_plugin; - unset($_ac_plugin); // Houskeeping. - } - - /** - * Registers a shutdown flag. - * - * @since 140605 Improving output buffer. - * - * @note In `/wp-settings.php`, ZenCache is loaded before WP registers its own shutdown function. - * Therefore, this flag is set before {@link shutdown_action_hook()} fires, and thus before {@link wp_ob_end_flush_all()}. - * - * @see http://www.php.net/manual/en/function.register-shutdown-function.php - */ - public function register_shutdown_flag() - { - register_shutdown_function(function () - { - $GLOBALS[__NAMESPACE__.'__shutdown_flag'] = -1; - }); - } - - /** - * Sends no-cache headers (if applicable). - * - * @since 140422 First documented version. - */ - public function maybe_stop_browser_caching() - { - if(ZENCACHE_ALLOW_BROWSER_CACHE) - return; // Allow in this case. - - if(!empty($_GET['zcABC']) && filter_var($_GET['zcABC'], FILTER_VALIDATE_BOOLEAN)) - return; // The query var says it's OK here. - - header_remove('Last-Modified'); - header('Expires: Wed, 11 Jan 1984 05:00:00 GMT'); - header('Cache-Control: no-cache, must-revalidate, max-age=0'); - header('Pragma: no-cache'); - } - - /** - * Start output buffering (if applicable); or serve a cache file (if possible). - * - * @since 140422 First documented version. - * - * @note This is a vital part of ZenCache. This method serves existing (fresh) cache files. - * It is also responsible for beginning the process of collecting the output buffer. - */ - public function maybe_start_output_buffering() - { - if(strcasecmp(PHP_SAPI, 'cli') === 0) - return $this->maybe_set_debug_info($this::NC_DEBUG_PHP_SAPI_CLI); - - if(empty($_SERVER['HTTP_HOST'])) - return $this->maybe_set_debug_info($this::NC_DEBUG_NO_SERVER_HTTP_HOST); - - if(empty($_SERVER['REQUEST_URI'])) - return $this->maybe_set_debug_info($this::NC_DEBUG_NO_SERVER_REQUEST_URI); - - if(isset($_GET['zcAC']) && !filter_var($_GET['zcAC'], FILTER_VALIDATE_BOOLEAN)) - return $this->maybe_set_debug_info($this::NC_DEBUG_QCAC_GET_VAR); - - if(defined('ZENCACHE_ALLOWED') && !ZENCACHE_ALLOWED) - return $this->maybe_set_debug_info($this::NC_DEBUG_ZENCACHE_ALLOWED_CONSTANT); - - if(isset($_SERVER['ZENCACHE_ALLOWED']) && !$_SERVER['ZENCACHE_ALLOWED']) - return $this->maybe_set_debug_info($this::NC_DEBUG_ZENCACHE_ALLOWED_SERVER_VAR); - - if(defined('DONOTCACHEPAGE')) - return $this->maybe_set_debug_info($this::NC_DEBUG_DONOTCACHEPAGE_CONSTANT); - - if(isset($_SERVER['DONOTCACHEPAGE'])) - return $this->maybe_set_debug_info($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR); - - if($this->is_uncacheable_request_method()) - return $this->maybe_set_debug_info($this::NC_DEBUG_UNCACHEABLE_REQUEST); - - if(isset($_SERVER['SERVER_ADDR']) && $this->current_ip() === $_SERVER['SERVER_ADDR']) - if(!$this->is_localhost()) // Allow for a localhost scenario; i.e., a developer testing. - return $this->maybe_set_debug_info($this::NC_DEBUG_SELF_SERVE_REQUEST); - - if(!ZENCACHE_FEEDS_ENABLE && $this->is_feed()) - return $this->maybe_set_debug_info($this::NC_DEBUG_FEED_REQUEST); - - if(preg_match('/\/(?:wp\-[^\/]+|xmlrpc)\.php(?:[?]|$)/i', $_SERVER['REQUEST_URI'])) - return $this->maybe_set_debug_info($this::NC_DEBUG_WP_SYSTEMATICS); - - if(is_admin() || preg_match('/\/wp-admin(?:[\/?]|$)/i', $_SERVER['REQUEST_URI'])) - return $this->maybe_set_debug_info($this::NC_DEBUG_WP_ADMIN); - - if(is_multisite() && preg_match('/\/files(?:[\/?]|$)/i', $_SERVER['REQUEST_URI'])) - return $this->maybe_set_debug_info($this::NC_DEBUG_MS_FILES); - - if($this->is_like_user_logged_in()) // Commenters, password-protected access, or actually logged-in. - return $this->maybe_set_debug_info($this::NC_DEBUG_IS_LIKE_LOGGED_IN_USER); - - if(!ZENCACHE_GET_REQUESTS && $this->is_get_request_w_query() && (!isset($_GET['zcAC']) || !filter_var($_GET['zcAC'], FILTER_VALIDATE_BOOLEAN))) - return $this->maybe_set_debug_info($this::NC_DEBUG_GET_REQUEST_QUERIES); - - $this->protocol = $this->is_ssl() ? 'https://' : 'http://'; - $this->version_salt = $this->apply_filters(__CLASS__.'__version_salt', ''); - $this->cache_path = $this->build_cache_path($this->protocol.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], '', $this->version_salt); - $this->cache_file = ZENCACHE_DIR.'/'.$this->cache_path; // NOT considering a user cache at all in the lite version. - $this->cache_file_404 = ZENCACHE_DIR.'/'.$this->build_cache_path($this->protocol.$_SERVER['HTTP_HOST'].'/'.ZENCACHE_404_CACHE_FILENAME); - $this->salt_location = ltrim($this->version_salt.' '.$this->protocol.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); - - if(is_file($this->cache_file) && filemtime($this->cache_file) >= strtotime('-'.ZENCACHE_MAX_AGE)) - { - list($headers, $cache) = explode('', file_get_contents($this->cache_file), 2); - - $headers_list = $this->headers_list(); // Headers already sent (or ready to be sent). - foreach(unserialize($headers) as $_header) // Preserves original headers sent with this file. - if(!in_array($_header, $headers_list, TRUE) && stripos($_header, 'Last-Modified:') !== 0) - header($_header); // Only cacheable/safe headers are stored in the cache. - unset($_header); // Just a little housekeeping. - - if(ZENCACHE_DEBUGGING_ENABLE && $this->is_html_xml_doc($cache)) // Only if HTML comments are possible. - { - $total_time = number_format(microtime(TRUE) - $this->timer, 5, '.', ''); - $cache .= "\n".''; - // translators: This string is actually NOT translatable because the `__()` function is not available at this point in the processing. - $cache .= "\n".''; - } - exit($cache); // Exit with cache contents. - } - else // Start buffering output; we may need to cache the HTML generated by this request. - { - ob_start(array($this, 'output_buffer_callback_handler')); // Start output buffering. - } - return NULL; // Return value not applicable. - } - - /** - * Used to setup debug info (if enabled). - * - * @since 140422 First documented version. - * - * @param string $reason_code One of the `NC_DEBUG_` constants. - * @param string $reason Optionally override the built-in description with a custom message. - */ - public function maybe_set_debug_info($reason_code, $reason = '') - { - if(!ZENCACHE_DEBUGGING_ENABLE) - return; // Nothing to do. - - $reason = (string)$reason; - if(!($reason_code = (string)$reason_code)) - return; // Not applicable. - - $this->debug_info = array('reason_code' => $reason_code, 'reason' => $reason); - } - - /** - * Filters WP {@link \status_header()} (if applicable). - * - * @since 140422 First documented version. - */ - public function maybe_filter_status_header_postload() - { - if(empty($this->postload['filter_status_header'])) - return; // Nothing to do in this case. - - $_this = $this; // Reference needed by the closure below. - add_filter('status_header', function ($status_header, $status_code) use ($_this) - { - if($status_code > 0) // Sending a status? - $_this->http_status = (integer)$status_code; - - return $status_header; // Pass through this filter. - - }, PHP_INT_MAX, 2); - } - - /** - * Hooks `NC_DEBUG_` info into the WordPress `shutdown` phase (if applicable). - * - * @since 140422 First documented version. - */ - public function maybe_set_debug_info_postload() - { - if(!ZENCACHE_DEBUGGING_ENABLE) - return; // Nothing to do. - - if(empty($this->postload['set_debug_info'])) - return; // Nothing to do in this case. - - if(is_admin()) return; // Not applicable. - - if(strcasecmp(PHP_SAPI, 'cli') === 0) - return; // Let's not run the risk here. - - add_action('shutdown', array($this, 'maybe_echo_nc_debug_info'), PHP_INT_MAX - 10); - } - - /** - * Grab details from WP and the ZenCache plugin itself, - * after the main query is loaded (if at all possible). - * - * This is where we have a chance to grab any values we need from WordPress; or from the QC plugin. - * It is EXTREMEMLY important that we NOT attempt to grab any object references here. - * Anything acquired in this phase should be stored as a scalar value. - * See {@link output_buffer_callback_handler()} for further details. - * - * @since 140422 First documented version. - * - * @attaches-to `wp` hook. - */ - public function wp_main_query_postload() - { - if(empty($this->postload['wp_main_query'])) - return; // Nothing to do in this case. - - if($this->is_wp_loaded_query || is_admin()) - return; // Nothing to do. - - if(!is_main_query()) return; // Not main query. - - $this->is_wp_loaded_query = TRUE; - $this->is_404 = is_404(); - $this->is_user_logged_in = is_user_logged_in(); - $this->content_url = rtrim(content_url(), '/'); - $this->is_maintenance = function_exists('is_maintenance') && is_maintenance(); - - $_this = $this; // Reference for the closure below. - add_action('template_redirect', function () use ($_this) - { // Move this AFTER `redirect_canonical` to avoid buggy WP behavior. - // See - $_this->is_a_wp_content_type = $_this->is_404 || $_this->is_maintenance - || is_front_page() // See - || is_home() || is_singular() || is_archive() || is_post_type_archive() || is_tax() || is_search() || is_feed(); - }, 11); - } - - /** - * Output buffer handler; i.e. the cache file generator. - * - * @note We CANNOT depend on any WP functionality here; it will cause problems. - * Anything we need from WP should be saved in the postload phase as a scalar value. - * - * @since 140422 First documented version. - * - * @param string $buffer The buffer from {@link \ob_start()}. - * @param integer $phase A set of bitmask flags. - * - * @return string|boolean The output buffer, or `FALSE` to indicate no change. - * - * @throws \exception If unable to handle output buffering for any reason. - * - * @attaches-to {@link \ob_start()} - */ - public function output_buffer_callback_handler($buffer, $phase) - { - if(!($phase & PHP_OUTPUT_HANDLER_END)) // We do NOT chunk the buffer; so this should NOT occur. - throw new \exception(sprintf(__('Unexpected OB phase: `%1$s`.', $this->text_domain), $phase)); - - # Exclusion checks; there are MANY of these... - - advanced_cache_back_compat::QUICK_CACHE_constants(); - - $cache = trim((string)$buffer); - if(!isset($cache[0])) // Allows a `0`. - return FALSE; // Don't cache an empty buffer. - - if(!isset($GLOBALS[__NAMESPACE__.'__shutdown_flag'])) - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_EARLY_BUFFER_TERMINATION); - - if(isset($_GET['zcAC']) && !filter_var($_GET['zcAC'], FILTER_VALIDATE_BOOLEAN)) - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_QCAC_GET_VAR); - - if(defined('ZENCACHE_ALLOWED') && !ZENCACHE_ALLOWED) - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_ZENCACHE_ALLOWED_CONSTANT); - - if(isset($_SERVER['ZENCACHE_ALLOWED']) && !$_SERVER['ZENCACHE_ALLOWED']) - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_ZENCACHE_ALLOWED_SERVER_VAR); - - if(defined('DONOTCACHEPAGE')) // WP Super Cache compatible. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_DONOTCACHEPAGE_CONSTANT); - - if(isset($_SERVER['DONOTCACHEPAGE'])) // WP Super Cache compatible. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR); - - if($this->is_user_logged_in) // Actually logged into the site. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_IS_LOGGED_IN_USER); - - if($this->is_like_user_logged_in()) // Commenters, password-protected access, or actually logged-in. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_IS_LIKE_LOGGED_IN_USER); // Separate debug notice. - - if($this->is_404 && !ZENCACHE_CACHE_404_REQUESTS) // Not caching 404 errors. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_404_REQUEST); - - if(stripos($cache, '') !== FALSE) // A WordPress-generated error? - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_WP_ERROR_PAGE); - - if(!$this->function_is_possible('http_response_code')) // Unable to reliably detect HTTP status code? - if(stripos($cache, 'database error') !== FALSE) // Fallback on this hackety hack. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_WP_ERROR_PAGE); - - if(!$this->has_a_cacheable_content_type()) // Exclude non-HTML/XML content types. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_UNCACHEABLE_CONTENT_TYPE); - - if(!$this->has_a_cacheable_status()) // This will catch WP Maintenance Mode too. - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_UNCACHEABLE_STATUS); - - if($this->is_maintenance) // - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_MAINTENANCE_PLUGIN); - - if($this->function_is_possible('zlib_get_coding_type') && zlib_get_coding_type() - && (!($zlib_oc = ini_get('zlib.output_compression')) || !filter_var($zlib_oc, FILTER_VALIDATE_BOOLEAN)) - ) return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_OB_ZLIB_CODING_TYPE); - - # Lock the cache directory while writes take place here. - - $cache_lock = $this->cache_lock(); // Lock cache directory. - - # Construct a temp file for atomic cache writes. - - $cache_file_tmp = $this->add_tmp_suffix($this->cache_file); - - # Cache directory checks. The cache file directory is created here if necessary. - - if(!is_dir(ZENCACHE_DIR) && mkdir(ZENCACHE_DIR, 0775, TRUE) && !is_file(ZENCACHE_DIR.'/.htaccess')) - file_put_contents(ZENCACHE_DIR.'/.htaccess', $this->htaccess_deny); // We know it's writable here. - - if(!is_dir($cache_file_dir = dirname($this->cache_file))) $cache_file_dir_writable = mkdir($cache_file_dir, 0775, TRUE); - if(empty($cache_file_dir_writable) && !is_writable($cache_file_dir)) // Only check if it's writable, if we didn't just successfully create it. - 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.', $this->text_domain), $this->name, $cache_file_dir)); - - # This is where a new 404 request might be detected for the first time; and where the 404 error file already exists in this case. - - if($this->is_404 && is_file($this->cache_file_404)) - { - if(!(symlink($this->cache_file_404, $cache_file_tmp) && rename($cache_file_tmp, $this->cache_file))) - 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`.', $this->text_domain), $this->cache_file, $this->cache_file_404, ZENCACHE_DIR)); - - $this->cache_unlock($cache_lock); // Unlock cache directory. - - return (boolean)$this->maybe_set_debug_info($this::NC_DEBUG_1ST_TIME_404_SYMLINK); - } - /* ------- Otherwise, we need to construct & store a new cache file. ----------------------------------------------- */ - - if(ZENCACHE_DEBUGGING_ENABLE && $this->is_html_xml_doc($cache)) // Only if HTML comments are possible. - { - $total_time = number_format(microtime(TRUE) - $this->timer, 5, '.', ''); - $cache .= "\n".''; - $cache .= "\n".''; - $cache .= "\n".''; - } - # NOT a 404, or it is 404 and the 404 cache file doesn't yet exist (so we need to create it). - - if($this->is_404) // This is a 404; let's create 404 cache file and symlink to it. - { - if(file_put_contents($cache_file_tmp, serialize($this->cacheable_headers_list()).''.$cache) && rename($cache_file_tmp, $this->cache_file_404)) - { - if(!(symlink($this->cache_file_404, $cache_file_tmp) && rename($cache_file_tmp, $this->cache_file))) - 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`.', $this->text_domain), $this->cache_file, $this->cache_file_404, ZENCACHE_DIR)); - - $this->cache_unlock($cache_lock); // Unlock cache directory. - - return $cache; // Return the newly built cache; with possible debug information also. - } - } // NOT a 404; let's write a new cache file! This is where pages get cached. The cache is served back out on this first-time access. - else if(file_put_contents($cache_file_tmp, serialize($this->cacheable_headers_list()).''.$cache) && rename($cache_file_tmp, $this->cache_file)) - { - $this->cache_unlock($cache_lock); // Unlock cache directory. - - return $cache; // Return the newly built cache; with possible debug information also. - } - @unlink($cache_file_tmp); // Clean this up (if it exists); and throw an exception with information for the site owner. - - 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`.', $this->text_domain), $this->name, $_SERVER['REQUEST_URI'], ZENCACHE_DIR)); - } - - /** - * Echoes `NC_DEBUG_` info in the WordPress `shutdown` phase (if applicable). - * - * @since 140605 Improving debug info output phase. - * - * @attaches-to `shutdown` hook in WordPress w/ a late priority. - */ - public function maybe_echo_nc_debug_info() // Debug info in the shutdown phase. - { - if(!ZENCACHE_DEBUGGING_ENABLE) - return; // Nothing to do. - - if(is_admin()) return; // Not applicable. - - if(strcasecmp(PHP_SAPI, 'cli') === 0) - return; // Let's not run the risk here. - - if($this->debug_info && $this->has_a_cacheable_content_type() && $this->is_a_wp_content_type) - echo (string)$this->maybe_get_nc_debug_info($this->debug_info['reason_code'], $this->debug_info['reason']); - } - - /** - * Gets `NC_DEBUG_` info (if applicable). - * - * @since 140422 First documented version. - * - * @param string $reason_code One of the `NC_DEBUG_` constants. - * @param string $reason Optional; to override the default description with a custom message. - * - * @return string The debug info; i.e. full description (if applicable). - */ - public function maybe_get_nc_debug_info($reason_code = '', $reason = '') - { - if(!ZENCACHE_DEBUGGING_ENABLE) - return ''; // Not applicable. - - $reason = (string)$reason; - if(!($reason_code = (string)$reason_code)) - return ''; // Not applicable. - - if(!$reason) switch($reason_code) - { - case $this::NC_DEBUG_PHP_SAPI_CLI: - $reason = __('because `PHP_SAPI` reports that you are currently running from the command line.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_QCAC_GET_VAR: - $reason = __('because `$_GET[\'zcAC\']` is set to a boolean-ish FALSE value.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_NO_SERVER_HTTP_HOST: - $reason = __('because `$_SERVER[\'HTTP_HOST\']` is missing from your server configuration.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_NO_SERVER_REQUEST_URI: - $reason = __('because `$_SERVER[\'REQUEST_URI\']` is missing from your server configuration.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_ZENCACHE_ALLOWED_CONSTANT: - $reason = __('because the PHP constant `ZENCACHE_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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_ZENCACHE_ALLOWED_SERVER_VAR: - $reason = __('because the environment variable `$_SERVER[\'ZENCACHE_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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_DONOTCACHEPAGE_CONSTANT: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_DONOTCACHEPAGE_SERVER_VAR: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_UNCACHEABLE_REQUEST: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_SELF_SERVE_REQUEST: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_FEED_REQUEST: - $reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a `/feed`; and the configuration of this site says not to cache XML-based feeds.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_WP_SYSTEMATICS: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_WP_ADMIN: - $reason = __('because `$_SERVER[\'REQUEST_URI\']` or the `is_admin()` function indicates this is an administrative area of the site.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_MS_FILES: - $reason = __('because `$_SERVER[\'REQUEST_URI\']` indicates this is a Multisite Network; and this was a request for `/files/*`, not a page.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_IS_LOGGED_IN_USER: - case $this::NC_DEBUG_IS_LIKE_LOGGED_IN_USER: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_GET_REQUEST_QUERIES: - $reason = __('because `$_GET` contains query string data. The current configuration says NOT to cache GET requests with a query string.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_404_REQUEST: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_MAINTENANCE_PLUGIN: - $reason = __('because a plugin running on this installation says this page is in Maintenance Mode; i.e. is not available publicly at this time.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_OB_ZLIB_CODING_TYPE: - $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.', $this->text_domain), $this->name); - break; // Break switch handler. - - case $this::NC_DEBUG_WP_ERROR_PAGE: - $reason = __('because the contents of this document contain ``, which indicates this is an auto-generated WordPress error message.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_UNCACHEABLE_CONTENT_TYPE: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_UNCACHEABLE_STATUS: - $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.', $this->text_domain); - break; // Break switch handler. - - case $this::NC_DEBUG_1ST_TIME_404_SYMLINK: - $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.', $this->text_domain), $this->name); - break; // Break switch handler. - - case $this::NC_DEBUG_EARLY_BUFFER_TERMINATION: - $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.', $this->text_domain), $this->name); - break; // Break switch handler. - - default: // Default case handler. - $reason = __('due to an unexpected behavior in the application. Please report this as a bug!', $this->text_domain); - break; // Break switch handler. - } - return "\n".''; - } - } - - class advanced_cache_back_compat // No extender; we need this up above. - { - /** - * Back compat. with `qcAC` and `qcABC`. - * - * @since 150218 First documented version. - */ - public static function qcAC_qcABC_vars() - { - $super_gs = array( - '_GET' => &$_GET, - '_REQUEST' => &$_REQUEST, - ); - $qc_suffixes = array('AC', 'ABC'); - - foreach($super_gs as $_super_g_key => &$_super_g_value) foreach($qc_suffixes as $_qc_suffix) - if(array_key_exists('qc'.$_qc_suffix, $_super_g_value)) - { - if($_super_g_key === '_GET' && !isset($_GET['zc'.$_qc_suffix])) - $_GET['zc'.$_qc_suffix] = $_super_g_value['qc'.$_qc_suffix]; - - foreach($super_gs as $__super_g_key => &$__super_g_value) - unset($__super_g_value['qc'.$_qc_suffix]); - unset($__super_g_key, $__super_g_value); // Housekeeping. - } - unset($_super_g_key, $_super_g_value, $_qc_suffix); - } - - /** - * Back compat. with `QUICK_CACHE_` constants. - * - * @since 150218 First documented version. - */ - public static function QUICK_CACHE_constants() - { - if(!($constants = get_defined_constants(TRUE)) || empty($constants['user'])) - return; // Nothing to do; i.e. no user-defined constants. - - foreach($constants['user'] as $_constant => $_value) - { - if(stripos($_constant, 'QUICK_CACHE_') !== 0) - continue; // Nothing to do here. - - if(!($_constant_sub_name = substr($_constant, 12))) - continue; // Nothing to do here. - - if(!defined('ZENCACHE_'.$_constant_sub_name)) - define('ZENCACHE_'.$_constant_sub_name, $_value); - } - unset($_constant, $_value); // Housekeeping. - - if(isset($_SERVER['QUICK_CACHE_ALLOWED']) && !isset($_SERVER['ZENCACHE_ALLOWED'])) - $_SERVER['ZENCACHE_ALLOWED'] = $_SERVER['QUICK_CACHE_ALLOWED']; - } - } - - /** - * Global ZenCache {@link advanced_cache} instance. - * - * @since 140422 First documented version. - * - * @var advanced_cache Global instance reference. - */ - $GLOBALS[__NAMESPACE__.'__advanced_cache'] = new advanced_cache(); - - if(!isset($GLOBALS['quick_cache__advanced_cache'])) // Back compat. - $GLOBALS['quick_cache__advanced_cache'] = &$GLOBALS[__NAMESPACE__.'__advanced_cache']; -} -namespace // Global namespace. -{ - /** - * Postload event handler; overrides core WP function. - * - * @since 140422 First documented version. - * - * @note See `/wp-settings.php` around line #226. - */ - function wp_cache_postload() // See: `wp-settings.php`. - { - $advanced_cache = $GLOBALS['zencache__advanced_cache']; - /** @var $advanced_cache \zencache\advanced_cache */ - if(!$advanced_cache->is_running) return; - - if(!empty($advanced_cache->postload['filter_status_header'])) - $advanced_cache->maybe_filter_status_header_postload(); - - if(!empty($advanced_cache->postload['set_debug_info'])) - $advanced_cache->maybe_set_debug_info_postload(); - - if(!empty($advanced_cache->postload['wp_main_query'])) - add_action('wp', array($advanced_cache, 'wp_main_query_postload'), PHP_INT_MAX); - } -} diff --git a/zencache/includes/api-class.php b/zencache/includes/api-class.php deleted file mode 100644 index d8aae39..0000000 --- a/zencache/includes/api-class.php +++ /dev/null @@ -1,93 +0,0 @@ - - * @license GNU General Public License, version 2 - */ -namespace // Global namespace. -{ - if(!defined('WPINC')) // MUST have WordPress. - exit('Do NOT access this file directly: '.basename(__FILE__)); - - /** - * ZenCache API Class. - */ - class zencache - { - /** - * Current QC plugin instance. - * - * @return \zencache\plugin instance. - */ - public static function plugin() - { - return $GLOBALS[__CLASS__]; - } - - /** - * Gives you the current version string. - * - * @return string Current version string. - */ - public static function version() - { - return static::plugin()->version; - } - - /** - * Gives you the current array of configured options. - * - * @return array Current array of options. - */ - public static function options() - { - return static::plugin()->options; - } - - /** - * Purges expired cache files, leaving all others intact. - * - * @note This occurs automatically over time via WP Cron; - * but this will force an immediate purge if you so desire. - * - * @return integer Total files purged (if any). - */ - public static function purge() - { - return static::plugin()->purge_cache(); - } - - /** - * This erases the entire cache for the current blog. - * - * @note In a multisite network this impacts only the current blog, - * it does not clear the cache for other child blogs. - * - * @return integer Total files cleared (if any). - */ - public static function clear() - { - return static::plugin()->clear_cache(); - } - - /** - * This wipes out the entire cache. - * - * @note On a standard WP installation this is the same as zencache::clear(); - * but on a multisite installation it impacts the entire network - * (i.e. wipes the cache for all blogs in the network). - * - * @return integer Total files wiped (if any). - */ - public static function wipe() - { - return static::plugin()->wipe_cache(); - } - } - - if(!class_exists('\\quick_cache')) - class_alias('\\zencache', '\\quick_cache'); -} \ No newline at end of file diff --git a/zencache/includes/conflicts-check.php b/zencache/includes/conflicts-check.php deleted file mode 100644 index 8010686..0000000 --- a/zencache/includes/conflicts-check.php +++ /dev/null @@ -1,50 +0,0 @@ - - * @license GNU General Public License, version 2 - */ -namespace zencache -{ - if(!defined('WPINC')) // MUST have WordPress. - exit('Do NOT access this file directly: '.basename(__FILE__)); - - ${__FILE__}['check'] = function () - { - $plugin_slug = str_replace('_', '-', __NAMESPACE__); - $plugin_lite_slug = $plugin_slug; // i.e. the same. - $plugin_pro_slug = $plugin_slug.'-pro'; - - if(class_exists('\\'.__NAMESPACE__.'\\plugin')) - return $plugin_slug; // Lite/Pro conflict exists. - - $conflicting_plugin_slugs = array( - $plugin_pro_slug, // Exclude lite version; i.e. self. - 'quick-cache', 'quick-cache-pro', // Old plugin slugs. - 'wp-super-cache', 'w3-total-cache', 'hyper-cache', 'wp-rocket', - ); - $active_plugins = (array)get_option('active_plugins', array()); - $active_sitewide_plugins = is_multisite() ? array_keys((array)get_site_option('active_sitewide_plugins', array())) : array(); - $active_plugins = array_unique(array_merge($active_plugins, $active_sitewide_plugins)); - - foreach($active_plugins as $_active_plugin_basename) - { - if(!($_active_plugin_slug = strstr($_active_plugin_basename, '/', TRUE))) - continue; // Nothing to check in this case. - - if(in_array($_active_plugin_slug, $conflicting_plugin_slugs, TRUE)) - if(in_array($_active_plugin_slug, array('quick-cache', 'quick-cache-pro'), TRUE)) - add_action('admin_init', function () use ($_active_plugin_basename) - { - if(function_exists('deactivate_plugins')) - deactivate_plugins($_active_plugin_basename, TRUE); - }, -1000); - else return $_active_plugin_slug; - } - return ''; // i.e. No conflicting plugin found above. - }; - return ($GLOBALS[__NAMESPACE__.'_conflicting_plugin'] = ${__FILE__}['check']()); -} \ No newline at end of file diff --git a/zencache/includes/gzip-htaccess.tpl.txt b/zencache/includes/gzip-htaccess.tpl.txt deleted file mode 100644 index e4c7349..0000000 --- a/zencache/includes/gzip-htaccess.tpl.txt +++ /dev/null @@ -1,10 +0,0 @@ - - - AddOutputFilterByType DEFLATE text/plain text/html - AddOutputFilterByType DEFLATE text/xml application/xml application/xhtml+xml application/xml-dtd - AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml image/svg+xml - AddOutputFilterByType DEFLATE text/css text/javascript application/javascript application/x-javascript - AddOutputFilterByType DEFLATE font/otf font/opentype application/font-otf application/x-font-otf - AddOutputFilterByType DEFLATE font/ttf font/truetype application/font-ttf application/x-font-ttf - - \ No newline at end of file diff --git a/zencache/includes/menu-pages.php b/zencache/includes/menu-pages.php deleted file mode 100644 index 8bce4fc..0000000 --- a/zencache/includes/menu-pages.php +++ /dev/null @@ -1,756 +0,0 @@ -plugin = plugin(); - } - - public function options() - { - echo ''; - } - } -} diff --git a/zencache/includes/share.php b/zencache/includes/share.php deleted file mode 100644 index f5c0101..0000000 --- a/zencache/includes/share.php +++ /dev/null @@ -1,2378 +0,0 @@ -slug = $this->text_domain = str_replace('_', '-', __NAMESPACE__); - } - - /* -------------------------------------------------------------------------------------- - * Cache directory/path/URL utilities. - -------------------------------------------------------------------------------------- */ - - /** - * Absolute server path to the cache directory. - * - * @since 140725 Reorganizing class members. - * - * @param string $rel_path Optional; a relative path within the cache directory. - * - * @return string Absolute server path to the cache directory. - * - * @throws \exception If unable to determine the cache directory location. - */ - public function cache_dir($rel_path = '') - { - if(method_exists($this, 'wp_content_base_dir_to') && isset($this->cache_sub_dir)) - $cache_dir = $this->wp_content_base_dir_to($this->cache_sub_dir); - - else if(defined('ZENCACHE_DIR') && ZENCACHE_DIR) - $cache_dir = ZENCACHE_DIR; // Global constant. - - if(empty($cache_dir)) // No cache directory? - throw new \exception(__('Unable to determine cache directory location.', $this->text_domain)); - - return $cache_dir.($rel_path ? '/'.ltrim((string)$rel_path) : ''); - } - - /** - * Converts a URL into a relative `cache/path`; i.e. relative to the cache directory. - * - * @since 140422 First documented version. - * - * @param string $url The input URL to convert. - * @param string $with_user_token Optional user token (if applicable). - * @param string $with_version_salt Optional version salt (if applicable). - * @param integer $flags Optional flags; a bitmask provided by `CACHE_PATH_*` constants. - * - * @return string The resulting relative `cache/path` based on the input `$url`; i.e. relative to the cache directory. - */ - public function build_cache_path($url, $with_user_token = '', $with_version_salt = '', $flags = 0) - { - $cache_path = ''; // Initialize. - $url = trim((string)$url); - $with_user_token = trim((string)$with_user_token); - $with_version_salt = trim((string)$with_version_salt); - - if($url && strpos($url, '://') === FALSE) - $url = '//'.ltrim($url, '/'); - - if($url && strpos($url, '&') !== FALSE) - $url = str_replace('&', '&', $url); - - if(!$url || !($url = parse_url($url))) - return ''; // Invalid URL. - - if(!($flags & $this::CACHE_PATH_NO_SCHEME)) - { - if(!empty($url['scheme'])) - $cache_path .= $url['scheme'].'/'; - else $cache_path .= $this->is_ssl() ? 'https/' : 'http/'; - } - if(!($flags & $this::CACHE_PATH_NO_HOST)) - { - if(!empty($url['host'])) - $cache_path .= $url['host'].'/'; - else $cache_path .= $_SERVER['HTTP_HOST'].'/'; - } - if(!($flags & $this::CACHE_PATH_NO_PATH)) - { - if(isset($url['path'][201])) // Extremely long? - { - $url['_path_tmp'] = '/'; // Initialize tmp path. - foreach(explode('/', $url['path']) as $_path_component) - { - if(!isset($_path_component[0])) - continue; // Empty. - - if(isset($_path_component[201])) - $_path_component = 'lpc-'.sha1($_path_component); - $url['_path_tmp'] .= $_path_component.'/'; - } - $url['path'] = $url['_path_tmp']; // Shorter components. - unset($_path_component, $url['_path_tmp']); // Housekeeping. - - if(isset($url['path'][2001])) // Overall path length is very long? - $url['path'] = '/lp-'.sha1($url['path']).'/'; - } - if(!empty($url['path']) && strlen($url['path'] = trim($url['path'], '\\/'." \t\n\r\0\x0B"))) - $cache_path .= $url['path'].'/'; // Has a path, let's use it :-) - else if(!($flags & $this::CACHE_PATH_NO_PATH_INDEX)) $cache_path .= 'index/'; - } - if($this->is_extension_loaded('mbstring') && mb_check_encoding($cache_path, 'UTF-8')) - $cache_path = mb_strtolower($cache_path, 'UTF-8'); - $cache_path = str_replace('.', '-', strtolower($cache_path)); - - if(!($flags & $this::CACHE_PATH_NO_QUV)) - { - if(!($flags & $this::CACHE_PATH_NO_QUERY)) - if(isset($url['query']) && $url['query'] !== '') - $cache_path = rtrim($cache_path, '/').'.q/'.md5($url['query']).'/'; - - if(!($flags & $this::CACHE_PATH_NO_USER)) - if($with_user_token !== '') // Allow a `0` value if desirable. - $cache_path = rtrim($cache_path, '/').'.u/'.str_replace(array('/', '\\'), '-', $with_user_token).'/'; - - if(!($flags & $this::CACHE_PATH_NO_VSALT)) - if($with_version_salt !== '') // Allow a `0` value if desirable. - $cache_path = rtrim($cache_path, '/').'.v/'.str_replace(array('/', '\\'), '-', $with_version_salt).'/'; - } - $cache_path = trim(preg_replace(array('/\/+/', '/\.+/'), array('/', '.'), $cache_path), '/'); - - if($flags & $this::CACHE_PATH_ALLOW_WILDCARDS) // Allow `*`? - $cache_path = preg_replace('/[^a-z0-9\/.*]/i', '-', $cache_path); - else $cache_path = preg_replace('/[^a-z0-9\/.]/i', '-', $cache_path); - - if(!($flags & $this::CACHE_PATH_NO_EXT)) - $cache_path .= '.html'; - - return $cache_path; // Do not filter. - } - - /** - * Variation of {@link build_cache_path()} for relative regex. - * - * This converts a URL into a relative `cache/path`; i.e. relative to the cache directory, - * and then converts that into a regex pattern w/ an optional custom `$regex_suffix_frag`. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $url The input URL to convert. This CAN be left empty when necessary. - * If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`. - * If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`. - * - * @param string $regex_suffix_frag Regex fragment to come after the relative cache/path. - * Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`. - * Note: this should NOT have delimiters; i.e. do NOT start or end with `/`. - * See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}. - * - * @return string The resulting relative `cache/path` based on the input `$url`; converted to regex pattern. - * Note that `http://` or `https://` is automatically converted to `\/https?\/` here. - * This allows the pattern to pick up either scheme. - * - * @note This variation of {@link build_cache_path()} automatically forces the following flags. - * - * - {@link CACHE_PATH_NO_PATH_INDEX} - * - {@link CACHE_PATH_NO_QUV} - * - {@link CACHE_PATH_NO_EXT} - * - * @see CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG - */ - public function build_cache_path_regex($url, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) - { - $url = trim((string)$url); - $regex_suffix_frag = (string)$regex_suffix_frag; - $abs_relative_cache_path_regex = ''; // Initialize. - - if($url) // Only necessary if there is a URL to deal with here. - { - $flags = $this::CACHE_PATH_NO_PATH_INDEX - | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT; - - $relative_cache_path = $this->build_cache_path($url, '', '', $flags); - $abs_relative_cache_path = isset($relative_cache_path[0]) ? '/'.$relative_cache_path : ''; - $abs_relative_cache_path_regex = preg_quote($abs_relative_cache_path, '/'); - - if($abs_relative_cache_path_regex) $abs_relative_cache_path_regex = // `http` and `https` schemes. - preg_replace('/^\\\\\/https?\\\\\//i', '\/https?\/', $abs_relative_cache_path_regex); - } - return '/^'.$abs_relative_cache_path_regex.$regex_suffix_frag.'/i'; - } - - /** - * Variation of {@link build_cache_path()} for relative regex. - * - * This converts a URL into a relative `cache/path`; i.e. relative to the current host|blog directory, - * and then converts that into a regex pattern w/ an optional custom `$regex_suffix_frag`. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $url The input URL to convert. This CAN be left empty when necessary. - * If empty, the final regex pattern will be `/^'.$regex_suffix_frag.'/i`. - * If empty, it's a good idea to start `$regex_suffix_frag` with `.*?`. - * - * @param string $regex_suffix_frag Regex fragment to come after the relative cache/path. - * Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`. - * Note: this should NOT have delimiters; i.e. do NOT start or end with `/`. - * See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}. - * - * @return string The resulting relative `cache/path` based on the input `$url`; converted to regex pattern. - * - * @note This variation of {@link build_cache_path()} automatically forces the following flags. - * - * - {@link CACHE_PATH_NO_SCHEME} - * - {@link CACHE_PATH_NO_HOST} - * - {@link CACHE_PATH_NO_PATH_INDEX} - * - {@link CACHE_PATH_NO_QUV} - * - {@link CACHE_PATH_NO_EXT} - * - * @see CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG - */ - public function build_host_cache_path_regex($url, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) - { - $url = trim((string)$url); - $regex_suffix_frag = (string)$regex_suffix_frag; - $abs_relative_cache_path_regex = ''; // Initialize. - - if($url) // Only necessary if there is a URL to deal with here. - { - $flags = $this::CACHE_PATH_NO_SCHEME | $this::CACHE_PATH_NO_HOST | $this::CACHE_PATH_NO_PATH_INDEX - | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT; - - $host = $_SERVER['HTTP_HOST']; - $host_base_dir_tokens = $this->host_base_dir_tokens(); - $host_url = rtrim('http://'.$host.$host_base_dir_tokens, '/'); - $host_cache_path = $this->build_cache_path($host_url, '', '', $flags); - - $cache_path = $this->build_cache_path($url, '', '', $flags); - $relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $cache_path); - $abs_relative_cache_path = isset($relative_cache_path[0]) ? '/'.$relative_cache_path : ''; - $abs_relative_cache_path_regex = preg_quote($abs_relative_cache_path, '/'); - } - return '/^'.$abs_relative_cache_path_regex.$regex_suffix_frag.'/i'; - } - - /** - * Variation of {@link build_cache_path()} for relative regex fragments. - * - * This converts URIs into relative `cache/paths`; i.e. relative to the current host|blog directory, - * and then converts those into `(?:regex|fragments)` with piped `|` alternatives. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $uris A line-delimited list of URIs. These may contain `*` wildcards also. - * - * @param string $regex_suffix_frag Regex fragment to come after each relative cache/path. - * Defaults to: `(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])`. - * Note: this should NOT have delimiters; i.e. do NOT start or end with `/`. - * See also: {@link CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG}. - * - * @return string The resulting `cache/paths` based on the input `$uris`; converted to `(?:regex|fragments)`. - * - * @note This variation of {@link build_cache_path()} automatically forces the following flags. - * - * - {@link CACHE_PATH_ALLOW_WILDCARDS} - * - {@link CACHE_PATH_NO_SCHEME} - * - {@link CACHE_PATH_NO_HOST} - * - {@link CACHE_PATH_NO_PATH_INDEX} - * - {@link CACHE_PATH_NO_QUV} - * - {@link CACHE_PATH_NO_EXT} - */ - public function build_host_cache_path_regex_frags_from_wc_uris($uris, $regex_suffix_frag = self::CACHE_PATH_REGEX_DEFAULT_SUFFIX_FRAG) - { - if(!($uris = trim((string)$uris))) - return ''; // Nothing to do. - - $_this = $this; // Reference for the closure below. - $regex_suffix_frag = (string)$regex_suffix_frag; // Force a string value. - $flags = $this::CACHE_PATH_ALLOW_WILDCARDS | $this::CACHE_PATH_NO_SCHEME | $this::CACHE_PATH_NO_HOST - | $this::CACHE_PATH_NO_PATH_INDEX | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT; - - $host = $_SERVER['HTTP_HOST']; - $host_base_dir_tokens = $this->host_base_dir_tokens(); - $host_url = rtrim('http://'.$host.$host_base_dir_tokens, '/'); - $host_cache_path = $this->build_cache_path($host_url, '', '', $flags); - - return '(?:'.implode('|', array_map(function ($pattern) use ($_this, $regex_suffix_frag, $flags, $host_url, $host_cache_path) - { - $cache_path = $_this->build_cache_path($host_url.'/'.trim($pattern, '/'), '', '', $flags); - $relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $cache_path); - - return preg_replace('/\\\\\*/', '.*?', preg_quote($relative_cache_path, '/')).$regex_suffix_frag; # - - }, preg_split('/['."\r\n".']+/', $uris, NULL, PREG_SPLIT_NO_EMPTY))).')'; - } - - /* -------------------------------------------------------------------------------------- - * Token generation utilities. - -------------------------------------------------------------------------------------- */ - - /** - * Produces a token based on the current `$_SERVER['HTTP_HOST']`. - * - * @since 140422 First documented version. - * - * @param boolean $dashify Optional, defaults to a `FALSE` value. - * If `TRUE`, the token is returned with dashes in place of `[^a-z0-9\/]`. - * - * @return string Token based on the current `$_SERVER['HTTP_HOST']`. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function host_token($dashify = FALSE) - { - $dashify = (integer)$dashify; - - if(isset(static::$static[__FUNCTION__][$dashify])) - return static::$static[__FUNCTION__][$dashify]; - - $host = strtolower($_SERVER['HTTP_HOST']); - $token_value = $dashify ? trim(preg_replace('/[^a-z0-9\/]/i', '-', $host), '-') : $host; - - return (static::$static[__FUNCTION__][$dashify] = $token_value); - } - - /** - * Produces a token based on the current site's base directory. - * - * @since 140605 First documented version. - * - * @param boolean $dashify Optional, defaults to a `FALSE` value. - * If `TRUE`, the token is returned with dashes in place of `[^a-z0-9\/]`. - * - * @return string Produces a token based on the current site's base directory; - * (i.e. in the case of a sub-directory multisite network). - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - * - * @see plugin::clear_cache() - * @see plugin::update_blog_paths() - */ - public function host_base_token($dashify = FALSE) - { - $dashify = (integer)$dashify; - - if(isset(static::$static[__FUNCTION__][$dashify])) - return static::$static[__FUNCTION__][$dashify]; - - $host_base_token = '/'; // Assume NOT multisite; or own domain. - - if(is_multisite() && (!defined('SUBDOMAIN_INSTALL') || !SUBDOMAIN_INSTALL)) - { // Multisite w/ sub-directories; need a valid sub-directory token. - - if(defined('PATH_CURRENT_SITE')) - $host_base_token = PATH_CURRENT_SITE; - - else if(!empty($GLOBALS['base'])) - $host_base_token = $GLOBALS['base']; - - $host_base_token = trim($host_base_token, '\\/'." \t\n\r\0\x0B"); - $host_base_token = isset($host_base_token[0]) ? '/'.$host_base_token.'/' : '/'; - } - $token_value = $dashify ? trim(preg_replace('/[^a-z0-9\/]/i', '-', $host_base_token), '-') : $host_base_token; - - return (static::$static[__FUNCTION__][$dashify] = $token_value); - } - - /** - * Produces a token based on the current blog's sub-directory. - * - * @since 140422 First documented version. - * - * @param boolean $dashify Optional, defaults to a `FALSE` value. - * If `TRUE`, the token is returned with dashes in place of `[^a-z0-9\/]`. - * - * @return string Produces a token based on the current blog sub-directory - * (i.e. in the case of a sub-directory multisite network). - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - * - * @see plugin::clear_cache() - * @see plugin::update_blog_paths() - */ - public function host_dir_token($dashify = FALSE) - { - $dashify = (integer)$dashify; - - if(isset(static::$static[__FUNCTION__][$dashify])) - return static::$static[__FUNCTION__][$dashify]; - - $host_dir_token = '/'; // Assume NOT multisite; or own domain. - - if(is_multisite() && (!defined('SUBDOMAIN_INSTALL') || !SUBDOMAIN_INSTALL)) - { // Multisite w/ sub-directories; need a valid sub-directory token. - - $uri_minus_base = // Supports `/sub-dir/child-blog-sub-dir/` also. - preg_replace('/^'.preg_quote($this->host_base_token(), '/').'/', '', $_SERVER['REQUEST_URI']); - - list($host_dir_token) = explode('/', trim($uri_minus_base, '/')); - $host_dir_token = isset($host_dir_token[0]) ? '/'.$host_dir_token.'/' : '/'; - - if($host_dir_token !== '/' // Perhaps NOT the main site? - && (!is_file(($cache_dir = $this->cache_dir()).'/zc-blog-paths') // NOT a read/valid blog path? - || !in_array($host_dir_token, unserialize(file_get_contents($cache_dir.'/zc-blog-paths')), TRUE)) - ) $host_dir_token = '/'; // Main site; e.g. this is NOT a real/valid child blog path. - } - $token_value = $dashify ? trim(preg_replace('/[^a-z0-9\/]/i', '-', $host_dir_token), '-') : $host_dir_token; - - return (static::$static[__FUNCTION__][$dashify] = $token_value); - } - - /** - * Produces tokens for the current site's base directory & current blog's sub-directory. - * - * @since 140422 First documented version. - * - * @param boolean $dashify Optional, defaults to a `FALSE` value. - * If `TRUE`, the tokens are returned with dashes in place of `[^a-z0-9\/]`. - * - * @return string Tokens for the current site's base directory & current blog's sub-directory. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - * - * @see plugin::clear_cache() - * @see plugin::update_blog_paths() - */ - public function host_base_dir_tokens($dashify = FALSE) - { - $dashify = (integer)$dashify; - - if(isset(static::$static[__FUNCTION__][$dashify])) - return static::$static[__FUNCTION__][$dashify]; - - $tokens = preg_replace('/\/{2,}/', '/', $this->host_base_token($dashify).$this->host_dir_token($dashify)); - - return (static::$static[__FUNCTION__][$dashify] = $tokens); - } - - /** - * Produces a token based on the current user. - * - * @since 140422 First documented version. - * - * @return string Produces a token based on the current user; - * else an empty string if that's not possible to do. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - * - * @note This routine may trigger a flag which indicates that the current user was logged-in at some point, - * but now the login cookie can no longer be validated by WordPress; i.e. they are NOT actually logged in any longer. - * See {@link $user_login_cookie_expired_or_invalid} - * - * @warning Do NOT call upon this method until WordPress reaches it's cache postload phase. - */ - public function user_token() // When/if possible. - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - $wp_validate_auth_cookie_possible = $this->function_is_possible('wp_validate_auth_cookie'); - if($wp_validate_auth_cookie_possible && ($user_id = (integer)wp_validate_auth_cookie('', 'logged_in'))) - return (static::$static[__FUNCTION__] = $user_id); // A real user in this case. - - else if(!empty($_COOKIE['comment_author_email_'.COOKIEHASH]) && is_string($_COOKIE['comment_author_email_'.COOKIEHASH])) - return (static::$static[__FUNCTION__] = md5(strtolower(stripslashes($_COOKIE['comment_author_email_'.COOKIEHASH])))); - - else if(!empty($_COOKIE['wp-postpass_'.COOKIEHASH]) && is_string($_COOKIE['wp-postpass_'.COOKIEHASH])) - return (static::$static[__FUNCTION__] = md5(stripslashes($_COOKIE['wp-postpass_'.COOKIEHASH]))); - - else if(defined('SID') && SID) return (static::$static[__FUNCTION__] = preg_replace('/[^a-z0-9]/i', '', SID)); - - if($wp_validate_auth_cookie_possible // We were unable to validate the login cookie? - && !empty($_COOKIE['wordpress_logged_in_'.COOKIEHASH]) && is_string($_COOKIE['wordpress_logged_in_'.COOKIEHASH]) - ) $this->user_login_cookie_expired_or_invalid = TRUE; // Flag as `TRUE`. - - return (static::$static[__FUNCTION__] = ''); - } - - /* -------------------------------------------------------------------------------------- - * Conditional utilities. - -------------------------------------------------------------------------------------- */ - - /** - * Does the current request include a query string? - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if request includes a query string. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_get_request_w_query() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(!empty($_GET) || isset($_SERVER['QUERY_STRING'][0])) - if(!(isset($_GET['zcABC']) && count($_GET) === 1)) // Special case. - return (static::$static[__FUNCTION__] = TRUE); - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Is the current request method `POST`, `PUT` or `DELETE`? - * - * @since 150218 Updating `is_uncacheable_request_method()` and restoring this one. - * - * @return boolean `TRUE` if current request method is `POST`, `PUT` or `DELETE`. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_post_put_delete_request() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(!empty($_POST)) // Being thorough. - return (static::$static[__FUNCTION__] = TRUE); - - if(!empty($_SERVER['REQUEST_METHOD'])) - if(in_array(strtoupper($_SERVER['REQUEST_METHOD']), array('POST', 'PUT', 'DELETE'), TRUE)) - return (static::$static[__FUNCTION__] = TRUE); - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Is the current request method is uncacheable? - * - * @since 150218 Reversing logic; only allow `GET` requests to be cached. - * @since 140725 Adding HEAD/OPTIONS/TRACE/CONNECT to the list of uncacheables. - * - * @return boolean `TRUE` if current request method is uncacheable. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_uncacheable_request_method() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(!empty($_POST)) // Being thorough. - return (static::$static[__FUNCTION__] = TRUE); - - if(!empty($_SERVER['REQUEST_METHOD'])) - if(!in_array(strtoupper($_SERVER['REQUEST_METHOD']), array('GET'), TRUE)) - return (static::$static[__FUNCTION__] = TRUE); - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Should the current user should be considered a logged-in user? - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if current user should be considered a logged-in user. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_like_user_logged_in() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(defined('SID') && SID) // Session ID. - return (static::$static[__FUNCTION__] = TRUE); - - $logged_in_cookies[] = 'comment_author_'; // Comment (and/or reply) authors. - $logged_in_cookies[] = 'wp-postpass_'; // Password access to protected posts. - - $logged_in_cookies[] = (defined('AUTH_COOKIE')) ? AUTH_COOKIE : 'wordpress_'; - $logged_in_cookies[] = (defined('SECURE_AUTH_COOKIE')) ? SECURE_AUTH_COOKIE : 'wordpress_sec_'; - $logged_in_cookies[] = (defined('LOGGED_IN_COOKIE')) ? LOGGED_IN_COOKIE : 'wordpress_logged_in_'; - $logged_in_cookies = '/^(?:'.implode('|', array_map(function ($logged_in_cookie) - { - return preg_quote($logged_in_cookie, '/'); // Escape. - - }, $logged_in_cookies)).')/'; - $test_cookie = (defined('TEST_COOKIE')) ? TEST_COOKIE : 'wordpress_test_cookie'; - - foreach($_COOKIE as $_key => $_value) if($_key !== $test_cookie) - if(preg_match($logged_in_cookies, $_key) && $_value) - return (static::$static[__FUNCTION__] = TRUE); - unset($_key, $_value); // Housekeeping. - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Are we in a LOCALHOST environment? - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if we are in a LOCALHOST environment. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_localhost() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(defined('LOCALHOST') && LOCALHOST) - return (static::$static[__FUNCTION__] = TRUE); - - if(!defined('LOCALHOST') && !empty($_SERVER['HTTP_HOST'])) - if(preg_match('/localhost|127\.0\.0\.1/i', $_SERVER['HTTP_HOST'])) - return (static::$static[__FUNCTION__] = TRUE); - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Is the current request for the Auto-Cache Engine? - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if the current request is for the Auto-Cache Engine. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_auto_cache_engine() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(!empty($_SERVER['HTTP_USER_AGENT'])) - if(stripos($_SERVER['HTTP_USER_AGENT'], __NAMESPACE__) !== FALSE) - return (static::$static[__FUNCTION__] = TRUE); - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Is the current request for a feed? - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if the current request is for a feed. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_feed() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(preg_match('/\/feed(?:[\/?]|$)/', $_SERVER['REQUEST_URI'])) - return (static::$static[__FUNCTION__] = TRUE); - - if(isset($_REQUEST['feed'])) // Query var? - return (static::$static[__FUNCTION__] = TRUE); - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Is the current request over SSL? - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if the current request is over SSL. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_ssl() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(!empty($_SERVER['SERVER_PORT'])) - if($_SERVER['SERVER_PORT'] === '443') - return (static::$static[__FUNCTION__] = TRUE); - - if(!empty($_SERVER['HTTPS'])) - if($_SERVER['HTTPS'] === '1' || strcasecmp($_SERVER['HTTPS'], 'on') === 0) - return (static::$static[__FUNCTION__] = TRUE); - - if(!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) - if(strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0) - return (static::$static[__FUNCTION__] = TRUE); - - return (static::$static[__FUNCTION__] = FALSE); - } - - /** - * Is a document/string an HTML/XML doc; or no? - * - * @since 140422 First documented version. - * - * @param string $doc Input string/document to check. - * - * @return boolean `TRUE` if `$doc` is an HTML/XML doc type. - */ - public function is_html_xml_doc($doc) - { - if(($doc = (string)$doc)) - if(stripos($doc, '') !== FALSE || stripos($doc, 'headers_list() as $_header) - if(stripos($_header, 'Content-Type:') === 0) - $content_type = $_header; // Last one. - unset($_header); // Just a little housekeeping. - - if(isset($content_type[0]) && stripos($content_type, 'html') === FALSE && stripos($content_type, 'xml') === FALSE && stripos($content_type, __NAMESPACE__) === FALSE) - return (static::$static[__FUNCTION__] = FALSE); // Do NOT cache data sent by scripts serving other MIME types. - - return (static::$static[__FUNCTION__] = TRUE); // Assume that it is by default. - } - - /** - * Does the current request have a cacheable HTTP status code? - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if the current request has a cacheable HTTP status code. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - * - * @warning Do NOT call upon this method until the end of a script execution. - */ - public function has_a_cacheable_status() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - if(($http_status = (string)$this->http_status()) && $http_status[0] !== '2' && $http_status !== '404') - return (static::$static[__FUNCTION__] = FALSE); // A non-2xx & non-404 status code. - - foreach($this->headers_list() as $_header) - if(preg_match('/^(?:Retry\-After\:\s+(?P.+)|Status\:\s+(?P[0-9]+)|HTTP\/[0-9]+\.[0-9]+\s+(?P[0-9]+))/i', $_header, $_m)) - if(!empty($_m['retry']) || (!empty($_m['status']) && $_m['status'][0] !== '2' && $_m['status'] !== '404') - || (!empty($_m['http_status']) && $_m['http_status'][0] !== '2' && $_m['http_status'] !== '404') - ) return (static::$static[__FUNCTION__] = FALSE); // Not a cacheable status. - unset($_header); // Just a little housekeeping. - - return (static::$static[__FUNCTION__] = TRUE); // Assume that it is by default. - } - - /* -------------------------------------------------------------------------------------- - * IP address utilities. - -------------------------------------------------------------------------------------- */ - - /** - * Get the current visitor's real IP address. - * - * @return string Real IP address, else `unknown` on failure. - * - * @note This supports both IPv4 and IPv6 addresses. - * @note See my tests against this here: http://3v4l.org/fVWUp - */ - public function current_ip() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - static::$static[__FUNCTION__] = ''; // Initialize. - $ip = &static::$static[__FUNCTION__]; - - if(!empty($_SERVER['REMOTE_ADDR']) && $this->apply_filters(__METHOD__.'_prioritize_remote_addr', FALSE)) - if(($_valid_public_ip = $this->valid_public_ip($_SERVER['REMOTE_ADDR']))) - return ($ip = $_valid_public_ip); - - $sources = array( - 'HTTP_CF_CONNECTING_IP', - 'HTTP_CLIENT_IP', - 'HTTP_X_FORWARDED_FOR', - 'HTTP_X_FORWARDED', - 'HTTP_X_CLUSTER_CLIENT_IP', - 'HTTP_FORWARDED_FOR', - 'HTTP_FORWARDED', - 'HTTP_VIA', - 'REMOTE_ADDR', - ); - $sources = $this->apply_filters(__METHOD__.'_sources', $sources); - - foreach($sources as $_source) // Try each of these; in order. - { - if(!empty($_SERVER[$_source])) // Does the source key exist at all? - if(($_valid_public_ip = $this->valid_public_ip($_SERVER[$_source]))) - return ($ip = $_valid_public_ip); // A valid public IPv4 or IPv6 address. - } - unset($_source, $_valid_public_ip); // Housekeeping. - - if(!empty($_SERVER['REMOTE_ADDR']) && is_string($_SERVER['REMOTE_ADDR'])) - return ($ip = strtolower($_SERVER['REMOTE_ADDR'])); - - return ($ip = 'unknown'); // Not possible. - } - - /** - * Gets a valid/public IP address. - * - * @param string $list_of_possible_ips A single IP, or a comma-delimited list of IPs. - * - * @return string A valid/public IP address (if one is found), else an empty string. - * - * @note This supports both IPv4 and IPv6 addresses. - * @note See my tests against this here: http://3v4l.org/fVWUp - */ - public function valid_public_ip($list_of_possible_ips) - { - if(!$list_of_possible_ips || !is_string($list_of_possible_ips)) - return ''; // Empty or invalid data. - - if(!($list_of_possible_ips = trim($list_of_possible_ips))) - return ''; // Not possible; i.e., empty string. - - foreach(preg_split('/[\s;,]+/', $list_of_possible_ips, NULL, PREG_SPLIT_NO_EMPTY) as $_possible_ip) - if(($_valid_public_ip = filter_var(strtolower($_possible_ip), FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))) - return $_valid_public_ip; // A valid public IPv4 or IPv6 address. - unset($_possible_ip, $_valid_public_ip); // Housekeeping. - - return ''; // Default return value. - } - - /* -------------------------------------------------------------------------------------- - * Function/extension utilities. - -------------------------------------------------------------------------------------- */ - - /** - * Checks if a PHP extension is loaded up. - * - * @since 140422 First documented version. - * - * @param string $extension A PHP extension slug (i.e. extension name). - * - * @return boolean `TRUE` if the extension is loaded. - * - * @note The return value of this function is cached to reduce overhead on repeat calls. - */ - public function is_extension_loaded($extension) - { - if(isset(static::$static[__FUNCTION__][$extension])) - return static::$static[__FUNCTION__][$extension]; - return (static::$static[__FUNCTION__][$extension] = extension_loaded($extension)); - } - - /** - * Is a particular function possible in every way? - * - * @since 140422 First documented version. - * - * @param string $function A PHP function (or user function) to check. - * - * @return string `TRUE` if the function is possible. - * - * @note This checks (among other things) if the function exists and that it's callable. - * It also checks the currently configured `disable_functions` and `suhosin.executor.func.blacklist`. - */ - public function function_is_possible($function) - { - if(isset(static::$static[__FUNCTION__][$function])) - return static::$static[__FUNCTION__][$function]; - - if(isset(static::$static[__FUNCTION__]['___disabled_functions'])) - $disabled_functions =& static::$static[__FUNCTION__]['___disabled_functions']; - - else // We need to collect the disabled functions and cache them now. - { - static::$static[__FUNCTION__]['___disabled_functions'] = array(); // `$disabled_functions` =& reference. - $disabled_functions =& static::$static[__FUNCTION__]['___disabled_functions']; - - if(function_exists('ini_get')) // Only if {@link ini_get()} is possible itself. - { - if(($disable_functions = trim(ini_get('disable_functions')))) - $disabled_functions = array_merge($disabled_functions, preg_split('/[\s;,]+/', strtolower($disable_functions), NULL, PREG_SPLIT_NO_EMPTY)); - - if(($blacklist_functions = trim(ini_get('suhosin.executor.func.blacklist')))) - $disabled_functions = array_merge($disabled_functions, preg_split('/[\s;,]+/', strtolower($blacklist_functions), NULL, PREG_SPLIT_NO_EMPTY)); - } - } - $possible = TRUE; // Assume it is.. (intialize). - - if(!function_exists($function) || !is_callable($function) - || ($disabled_functions && in_array(strtolower($function), $disabled_functions, TRUE)) - ) $possible = FALSE; // Not possible. - - return (static::$static[__FUNCTION__][$function] = $possible); - } - - /* -------------------------------------------------------------------------------------- - * HTTP protocol/status utility methods. - -------------------------------------------------------------------------------------- */ - - /** - * Current HTTP protocol; i.e. `HTTP/1.0` or `HTTP/1.1`. - * - * @since 140725 Correcting 404 cache response status code. - * - * @return string Current HTTP protocol; i.e. `HTTP/1.0` or `HTTP/1.1`. - */ - public function http_protocol() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - $protocol = !empty($_SERVER['SERVER_PROTOCOL']) - ? strtoupper((string)$_SERVER['SERVER_PROTOCOL']) : 'HTTP/1.0'; - - if($protocol !== 'HTTP/1.1' && $protocol !== 'HTTP/1.0') - $protocol = 'HTTP/1.0'; // Default value. - - return (static::$static[__FUNCTION__] = $protocol); - } - - /** - * An array of all headers sent via PHP; and the current HTTP status header too. - * - * @since 140725 Correcting 404 cache response status code. - * - * @return array PHP {@link headers_list()} supplemented with - * HTTP status code when possible. - * - * @warning Do NOT call upon this method until the end of a script execution. - */ - public function headers_list() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - $headers_list = headers_list(); // Lacks HTTP status header. - - if(($http_status = (string)$this->http_status())) - $headers_list[] = $this->http_protocol().' '.$http_status; - - return (static::$static[__FUNCTION__] = $headers_list); - } - - /** - * An array of all cacheable/safe headers sent via PHP; and the current HTTP status header too. - * - * @since 140829 Correcting security issue related to headers with cookies. - * - * @return array PHP {@link headers_list()} supplemented with - * HTTP status code when possible. - * - * @warning Do NOT call upon this method until the end of a script execution. - * - * @see http://www.websharks-inc.com/r/wikipedia-http-header-response-fields/ - */ - public function cacheable_headers_list() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - $headers_list = headers_list(); // Lacks HTTP status header. - - $cacheable_headers = array( - 'Access-Control-Allow-Origin', - 'Accept-Ranges', - 'Age', - 'Allow', - 'Cache-Control', - 'Connection', - 'Content-Encoding', - 'Content-Language', - 'Content-Length', - 'Content-Location', - 'Content-MD5', - 'Content-Disposition', - 'Content-Range', - 'Content-Type', - 'Date', - 'ETag', - 'Expires', - 'Last-Modified', - 'Link', - 'Location', - 'P3P', - 'Pragma', - 'Proxy-Authenticate', - 'Refresh', - 'Retry-After', - 'Server', - 'Status', - 'Strict-Transport-Security', - 'Trailer', - 'Transfer-Encoding', - 'Upgrade', - 'Vary', - 'Via', - 'Warning', - 'WWW-Authenticate', - 'X-Frame-Options', - 'Public-Key-Pins', - 'X-XSS-Protection', - 'Content-Security-Policy', - 'X-Content-Security-Policy', - 'X-WebKit-CSP', - 'X-Content-Type-Options', - 'X-Powered-By', - 'X-UA-Compatible', - ); - $cacheable_headers = array_map('strtolower', $cacheable_headers); - - foreach($headers_list as $_key => $_header) - { - $_header = strtolower((string)strstr($_header, ':', TRUE)); - if(!$_header || !in_array($_header, $cacheable_headers, TRUE)) - unset($headers_list[$_key]); - } - unset($_key, $_header); // Housekeeping. - - if(($http_status = (string)$this->http_status())) - array_unshift($headers_list, $this->http_protocol().' '.$http_status); - - return (static::$static[__FUNCTION__] = $headers_list); - } - - /** - * HTTP status code if at all possible. - * - * @since 140725 Correcting 404 cache response status code. - * - * @return integer HTTP status code if at all possible; else `0`. - * - * @warning Do NOT call upon this method until the end of a script execution. - */ - public function http_status() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - $http_status = 0; // Initialize. - $has_property__is_404 = property_exists($this, 'is_404'); - $has_property__http_status = property_exists($this, 'http_status'); - - // Determine current HTTP status code. - - if($has_property__is_404 && $this->{'is_404'}) - $http_status = 404; // WordPress said so. - - else if($this->function_is_possible('http_response_code') && ($http_response_code = (integer)http_response_code())) - $http_status = $http_response_code; // {@link \http_response_code()} available since PHP v5.4. - - else if($has_property__http_status && (integer)$this->{'http_status'}) - $http_status = (integer)$this->{'http_status'}; // {@link \status_header()} filter. - - // Dynamically update class property flags related to the HTTP status code. - - if($http_status && $has_property__http_status) // Update {@link $http_status}? - $this->{'http_status'} = $http_status; // Prefer over {@link status_header()}. - - if($http_status === 404 && $has_property__is_404) // Update {@link $is_404}? - $this->{'is_404'} = TRUE; // Prefer over {@link is_404()}. - - return (static::$static[__FUNCTION__] = $http_status); - } - - /* -------------------------------------------------------------------------------------- - * Misc. utility methods. - -------------------------------------------------------------------------------------- */ - - /** - * Escape single quotes. - * - * @since 140422 First documented version. - * - * @param string $string Input string to escape. - * @param integer $times Optional. Defaults to one escape char; e.g. `\'`. - * If you need to escape more than once, set this to something > `1`. - * - * @return string Escaped string; e.g. `Raam\'s the lead developer`. - */ - public function esc_sq($string, $times = 1) - { - return str_replace("'", str_repeat('\\', abs($times))."'", (string)$string); - } - - /** - * String replace ONE time. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $needle A string to search/replace. - * @param string $replace What to replace `$needle` with. - * @param string $haystack The string/haystack to search in. - * - * @param boolean $caSe_insensitive Defaults to a `FALSE` value. - * Pass this as `TRUE` to a caSe-insensitive search/replace. - * - * @return string The `$haystack`, with `$needle` replaced with `$replace` ONE time only. - */ - public function str_replace_once($needle, $replace, $haystack, $caSe_insensitive = FALSE) - { - $needle = (string)$needle; - $replace = (string)$replace; - $haystack = (string)$haystack; - $caSe_strpos = $caSe_insensitive ? 'stripos' : 'strpos'; - - if(($needle_strpos = $caSe_strpos($haystack, $needle)) === FALSE) - return $haystack; // Nothing to replace. - - return (string)substr_replace($haystack, $replace, $needle_strpos, strlen($needle)); - } - - /** - * String replace ONE time (caSe-insensitive). - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $needle A string to search/replace. - * @param string $replace What to replace `$needle` with. - * @param string $haystack The string/haystack to search in. - * - * @return string The `$haystack`, with `$needle` replaced with `$replace` ONE time only. - */ - public function str_ireplace_once($needle, $replace, $haystack) - { - return $this->str_replace_once($needle, $replace, $haystack, TRUE); - } - - /** - * Normalizes directory/file separators. - * - * @since 140829 Implementing XML/RSS feed clearing. - * - * @param string $dir_file Directory/file path. - * - * @param boolean $allow_trailing_slash Defaults to FALSE. - * If TRUE; and `$dir_file` contains a trailing slash; we'll leave it there. - * - * @return string Normalized directory/file path. - */ - public function n_dir_seps($dir_file, $allow_trailing_slash = FALSE) - { - $dir_file = (string)$dir_file; // Force string value. - if(!isset($dir_file[0])) return ''; // Catch empty string. - - if(strpos($dir_file, '://' !== FALSE)) // A possible stream wrapper? - { - if(preg_match('/^(?P[a-zA-Z0-9]+)\:\/\//', $dir_file, $stream_wrapper)) - $dir_file = preg_replace('/^(?P[a-zA-Z0-9]+)\:\/\//', '', $dir_file); - } - if(strpos($dir_file, ':' !== FALSE)) // Might have a Windows® drive letter? - { - if(preg_match('/^(?P[a-zA-Z])\:[\/\\\\]/', $dir_file)) // It has a Windows® drive letter? - $dir_file = preg_replace_callback('/^(?P[a-zA-Z])\:[\/\\\\]/', create_function('$m', 'return strtoupper($m[0]);'), $dir_file); - } - $dir_file = preg_replace('/\/+/', '/', str_replace(array(DIRECTORY_SEPARATOR, '\\', '/'), '/', $dir_file)); - $dir_file = ($allow_trailing_slash) ? $dir_file : rtrim($dir_file, '/'); // Strip trailing slashes. - - if(!empty($stream_wrapper[0])) // Stream wrapper (force lowercase). - $dir_file = strtolower($stream_wrapper[0]).$dir_file; - - return $dir_file; // Normalized now. - } - - /** - * Adds a tmp name suffix to a directory/file path. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $dir_file An input directory or file path. - * - * @return string The original `$dir_file` with a tmp name suffix. - */ - public function add_tmp_suffix($dir_file) - { - return (string)rtrim($dir_file, DIRECTORY_SEPARATOR.'\\/').'-'.str_replace('.', '', uniqid('', TRUE)).'-tmp'; - } - - /** - * Acquires system tmp directory path. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @return string System tmp directory path; else an empty string. - */ - public function get_tmp_dir() - { - if(isset(static::$static[__FUNCTION__])) - return static::$static[__FUNCTION__]; - - static::$static[__FUNCTION__] = ''; // Initialize. - $tmp_dir = &static::$static[__FUNCTION__]; - - if(defined('WP_TEMP_DIR')) - $possible_tmp_dirs[] = WP_TEMP_DIR; - - if($this->function_is_possible('sys_get_temp_dir')) - $possible_tmp_dirs[] = sys_get_temp_dir(); - - if($this->function_is_possible('ini_get')) - $possible_tmp_dirs[] = ini_get('upload_tmp_dir'); - - if(!empty($_SERVER['TEMP'])) - $possible_tmp_dirs[] = $_SERVER['TEMP']; - - if(!empty($_SERVER['TMPDIR'])) - $possible_tmp_dirs[] = $_SERVER['TMPDIR']; - - if(!empty($_SERVER['TMP'])) - $possible_tmp_dirs[] = $_SERVER['TMP']; - - if(stripos(PHP_OS, 'win') === 0) - $possible_tmp_dirs[] = 'C:/Temp'; - - if(stripos(PHP_OS, 'win') !== 0) - $possible_tmp_dirs[] = '/tmp'; - - if(defined('WP_CONTENT_DIR')) - $possible_tmp_dirs[] = WP_CONTENT_DIR; - - if(!empty($possible_tmp_dirs)) foreach($possible_tmp_dirs as $_tmp_dir) - if(($_tmp_dir = trim((string)$_tmp_dir)) && @is_dir($_tmp_dir) && @is_writable($_tmp_dir)) - return ($tmp_dir = $this->n_dir_seps($_tmp_dir)); - unset($_tmp_dir); // Housekeeping. - - return ($tmp_dir = ''); // Failed to locate. - } - - /** - * Finds absolute server path to `/wp-config.php` file. - * - * @since 140422 First documented version. - * - * @return string Absolute server path to `/wp-config.php` file; - * else an empty string if unable to locate the file. - */ - public function find_wp_config_file() - { - if(is_file($abspath_wp_config = ABSPATH.'wp-config.php')) - $wp_config_file = $abspath_wp_config; - - else if(is_file($dirname_abspath_wp_config = dirname(ABSPATH).'/wp-config.php')) - $wp_config_file = $dirname_abspath_wp_config; - - else $wp_config_file = ''; // Unable to find `/wp-config.php` file. - - return $wp_config_file; - } - - /* -------------------------------------------------------------------------------------- - * File/directory iteration utilities for ZenCache. - -------------------------------------------------------------------------------------- */ - - /** - * Recursive directory iterator based on a regex pattern. - * - * @since 140422 First documented version. - * - * @param string $dir An absolute server directory path. - * @param string $regex A regex pattern; compares to each full file path. - * - * @return \RegexIterator Navigable with {@link \foreach()}; where each item - * is a {@link \RecursiveDirectoryIterator}. - */ - public function dir_regex_iteration($dir, $regex) - { - $dir_iterator = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_SELF | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS); - $iterator_iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::CHILD_FIRST); - $regex_iterator = new \RegexIterator($iterator_iterator, $regex, \RegexIterator::MATCH, \RegexIterator::USE_KEY); - - return $regex_iterator; - } - - /** - * Clear files from the cache directory (for all hosts/blogs); - * i.e. those that match a specific regex pattern. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $regex A regex pattern; see {@link delete_files_from_cache_dir()}. - * - * @return integer Total files cleared by this routine (if any). - * - * @see delete_files_from_cache_dir() - */ - public function clear_files_from_cache_dir($regex) - { - return $this->delete_files_from_cache_dir($regex); - } - - /** - * Clear files from the cache directory (for the current host); - * i.e. those that match a specific regex pattern. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $regex A regex pattern; see {@link delete_files_from_host_cache_dir()}. - * - * @return integer Total files cleared by this routine (if any). - * - * @see delete_files_from_host_cache_dir() - */ - public function clear_files_from_host_cache_dir($regex) - { - return $this->delete_files_from_host_cache_dir($regex); - } - - /** - * Purge files from the cache directory (for all hosts/blogs); - * i.e. those that match a specific regex pattern. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $regex A regex pattern; see {@link delete_files_from_cache_dir()}. - * - * @return integer Total files purged by this routine (if any). - * - * @see delete_files_from_cache_dir() - */ - public function purge_files_from_cache_dir($regex) - { - return $this->delete_files_from_cache_dir($regex, TRUE); - } - - /** - * Purge files from the cache directory (for the current host); - * i.e. those that match a specific regex pattern. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $regex A regex pattern; see {@link delete_files_from_host_cache_dir()}. - * - * @return integer Total files purged by this routine (if any). - * - * @see delete_files_from_host_cache_dir() - */ - public function purge_files_from_host_cache_dir($regex) - { - return $this->delete_files_from_host_cache_dir($regex, TRUE); - } - - /** - * Delete files from the cache directory (for all hosts/blogs); - * i.e. those that match a specific regex pattern. - * - * @since 141110 Refactoring cache clear/purge routines. - * - * @param string $regex A `/[regex pattern]/`; relative to the cache directory. - * e.g. `/^http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/` - * - * Or, this can also be a full/absolute regex pattern against an absolute path; - * provided that it always starts with `/^`; including the full absolute cache/host directory path. - * e.g. `/^\/cache\/dir\/http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/` - * - * NOTE: Paths used in any/all regex patterns should be generated with {@link build_cache_path()}. - * Recommended flags to {@link build_cache_path()} include the following. - * - * - {@link CACHE_PATH_NO_PATH_INDEX} - * - {@link CACHE_PATH_NO_QUV} - * - {@link CACHE_PATH_NO_EXT} - * - * **TIP:** There is a variation of {@link build_cache_path()} to assist with this. - * Please see: {@link build_cache_path_regex()}. It is much easier to work with :-) - * - * @param boolean $check_max_age Check max age? i.e. use purge behavior? - * - * @return integer Total files deleted by this routine (if any). - * - * @throws \exception If unable to delete a file for any reason. - */ - public function delete_files_from_cache_dir($regex, $check_max_age = FALSE) - { - $counter = 0; // Initialize. - - if(!($regex = (string)$regex)) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - $cache_dir = $this->n_dir_seps($cache_dir); - - if($check_max_age && (empty($this->options) || !is_array($this->options) || !isset($this->options['cache_max_age']))) - throw new \exception(__('The `options` property w/ a `cache_max_age` key is not defined in this class.', $this->text_domain)); - - if($check_max_age && !($max_age = strtotime('-'.$this->options['cache_max_age']))) - return $counter; // Invalid cache expiration time. - - /* ------- Begin lock state... ----------- */ - - $cache_lock = $this->cache_lock(); // Lock cache writes. - - clearstatcache(); // Clear stat cache to be sure we have a fresh start below. - - $cache_dir_tmp = $this->add_tmp_suffix($cache_dir); // Temporary directory. - $cache_dir_tmp_regex = $regex; // Initialize host-specific regex pattern for the tmp directory. - - $cache_dir_tmp_regex = '\\/'.ltrim($cache_dir_tmp_regex, '^\\/'); // Make sure it begins with an escaped `/`. - $cache_dir_tmp_regex = $this->str_ireplace_once(preg_quote($cache_dir.'/', '/'), '', $cache_dir_tmp_regex); - - $cache_dir_tmp_regex = ltrim($cache_dir_tmp_regex, '^\\/'); - if(strpos($cache_dir_tmp_regex, '(?:\/') === 0 || strpos($cache_dir_tmp_regex, '(\/') === 0) - $cache_dir_tmp_regex = '/^'.preg_quote($cache_dir_tmp, '/').$cache_dir_tmp_regex; - else $cache_dir_tmp_regex = '/^'.preg_quote($cache_dir_tmp.'/', '/').$cache_dir_tmp_regex; - - # if(WP_DEBUG) file_put_contents(WP_CONTENT_DIR.'/zc-debug.log', print_r($regex, TRUE)."\n".print_r($cache_dir_tmp_regex, TRUE)."\n\n", FILE_APPEND); - // Uncomment the above line to debug regex pattern matching used by this routine; and others that call upon it. - - if(!rename($cache_dir, $cache_dir_tmp)) // Work from tmp directory so deletions are atomic. - throw new \exception(sprintf(__('Unable to delete files. Rename failure on directory: `%1$s`.', $this->text_domain), $cache_dir)); - - /** @var $_resource \RecursiveDirectoryIterator Regex iterator reference for IDEs. */ - foreach(($_dir_regex_iteration = $this->dir_regex_iteration($cache_dir_tmp, $cache_dir_tmp_regex)) as $_resource) - { - $_resource_type = $_resource->getType(); - $_sub_path_name = $_resource->getSubpathname(); - $_path_name = $_resource->getPathname(); - - if($_resource_type !== 'dir' && strpos($_sub_path_name, '/') === FALSE) - continue; // Don't delete links/files in the immediate directory; e.g. `zc-advanced-cache` or `.htaccess`, etc. - // Actual `http|https/...` cache links/files are nested. Links/files in the immediate directory are for other purposes. - - switch($_resource_type) // Based on type; i.e. `link`, `file`, `dir`. - { - case 'link': // Symbolic links; i.e. 404 errors. - - if($check_max_age && !empty($max_age) && is_file($_resource->getLinkTarget())) - if(($_lstat = lstat($_path_name)) && !empty($_lstat['mtime'])) - if($_lstat['mtime'] >= $max_age) // Still valid? - break; // Break switch handler. - - if(!unlink($_path_name)) // Throw exception if unable to delete. - throw new \exception(sprintf(__('Unable to delete symlink: `%1$s`.', $this->text_domain), $_path_name)); - $counter++; // Increment counter for each link we delete. - - break; // Break switch handler. - - case 'file': // Regular files; i.e. not symlinks. - - if($check_max_age && !empty($max_age)) // Should check max age? - if($_resource->getMTime() >= $max_age) // Still valid? - break; // Break switch handler. - - if(!unlink($_path_name)) // Throw exception if unable to delete. - throw new \exception(sprintf(__('Unable to delete file: `%1$s`.', $this->text_domain), $_path_name)); - $counter++; // Increment counter for each file we delete. - - break; // Break switch handler. - - case 'dir': // A regular directory; i.e. not a symlink. - - if($regex !== '/^.+/i') // Deleting everything? - break; // Break switch handler. Not deleting everything. - - if($check_max_age && !empty($max_age)) // Should check max age? - break; // Break switch handler. Not deleting everything in this case. - - if(!rmdir($_path_name)) // Throw exception if unable to delete the directory itself. - throw new \exception(sprintf(__('Unable to delete dir: `%1$s`.', $this->text_domain), $_path_name)); - # $counter++; // Increment counter for each directory we delete. ~ NO don't do that here. - - break; // Break switch handler. - - default: // Something else that is totally unexpected here. - throw new \exception(sprintf(__('Unexpected resource type: `%1$s`.', $this->text_domain), $_resource_type)); - } - } - unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name, $_lstat); // Housekeeping. - - if(!rename($cache_dir_tmp, $cache_dir)) // Deletions are atomic; restore original directory now. - throw new \exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', $this->text_domain), $cache_dir_tmp)); - - /* ------- End lock state... ------------- */ - - $this->cache_unlock($cache_lock); // Unlock cache directory. - - return $counter; // Total files deleted by this routine. - } - - /** - * Delete files from the cache directory (for the current host); - * i.e. those that match a specific regex pattern. - * - * @since 141110 Refactoring cache clear/purge routines. - * - * @param string $regex A `/[regex pattern]/`; relative to the host cache directory. - * e.g. `/^my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/` - * - * Or, this can also be a full/absolute regex pattern against an absolute path; - * provided that it always starts with `/^`; including the full absolute cache/host directory path. - * e.g. `/^\/cache\/dir\/http\/example\.com\/my\-slug(?:\/index)?(?:\.|\/(?:page\/[0-9]+|comment\-page\-[0-9]+)[.\/])/` - * - * NOTE: Paths used in any/all regex patterns should be generated with {@link build_cache_path()}. - * Recommended flags to {@link build_cache_path()} include the following. - * - * - {@link CACHE_PATH_NO_SCHEME} - * - {@link CACHE_PATH_NO_HOST} - * - {@link CACHE_PATH_NO_PATH_INDEX} - * - {@link CACHE_PATH_NO_QUV} - * - {@link CACHE_PATH_NO_EXT} - * - * **TIP:** There is a variation of {@link build_cache_path()} to assist with this. - * Please see: {@link build_host_cache_path_regex()}. It is much easier to work with :-) - * - * @param boolean $check_max_age Check max age? i.e. use purge behavior? - * - * @return integer Total files deleted by this routine (if any). - * - * @throws \exception If unable to delete a file for any reason. - */ - public function delete_files_from_host_cache_dir($regex, $check_max_age = FALSE) - { - $counter = 0; // Initialize. - - if(!($regex = (string)$regex)) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - $host = $_SERVER['HTTP_HOST']; - $host_base_dir_tokens = $this->host_base_dir_tokens(); - $cache_dir = $this->n_dir_seps($cache_dir); - - if($check_max_age && (empty($this->options) || !is_array($this->options) || !isset($this->options['cache_max_age']))) - throw new \exception(__('The `options` property w/ a `cache_max_age` key is not defined in this class.', $this->text_domain)); - - if($check_max_age && !($max_age = strtotime('-'.$this->options['cache_max_age']))) - return $counter; // Invalid cache expiration time. - - /* ------- Begin lock state... ----------- */ - - $cache_lock = $this->cache_lock(); // Lock cache writes. - - clearstatcache(); // Clear stat cache to be sure we have a fresh start below. - - foreach(array('http', 'https') as $_host_scheme) // Consider `http|https` schemes. - - /* This multi-scheme iteration could (alternatively) be accomplished via regex `\/https?\/`. - HOWEVER, since this operation is supposed to impact only a single host in a network, and because - we want to do atomic deletions, we iterate and rename `$_host_cache_dir` for each scheme. - - It's also worth noting that most high traffic sites will not be in the habit of serving - pages over SSL all the time; so this really should not have a significant performance hit. - In fact, it may improve performance since we are traversing each sub-directory separately; - i.e. we don't need to glob both `http` and `https` traffic into a single directory scan. */ - { - $_host_url = $_host_scheme.'://'.$host.$host_base_dir_tokens; // Base URL for this host|blog. - $_host_cache_path_flags = $this::CACHE_PATH_NO_PATH_INDEX | $this::CACHE_PATH_NO_QUV | $this::CACHE_PATH_NO_EXT; - $_host_cache_path = $this->build_cache_path($_host_url, '', '', $_host_cache_path_flags); - $_host_cache_dir = $this->n_dir_seps($cache_dir.'/'.$_host_cache_path); // Normalize. - - if(!$_host_cache_dir || !is_dir($_host_cache_dir)) continue; // Nothing to do. - - $_host_cache_dir_tmp = $this->add_tmp_suffix($_host_cache_dir); // Temporary directory. - $_host_cache_dir_tmp_regex = $regex; // Initialize host-specific regex pattern for the tmp directory. - - $_host_cache_dir_tmp_regex = '\\/'.ltrim($_host_cache_dir_tmp_regex, '^\\/'); // Make sure it begins with an escaped `/`. - $_host_cache_dir_tmp_regex = $this->str_ireplace_once(preg_quote($_host_cache_path.'/', '/'), '', $_host_cache_dir_tmp_regex); - $_host_cache_dir_tmp_regex = $this->str_ireplace_once(preg_quote($_host_cache_dir.'/', '/'), '', $_host_cache_dir_tmp_regex); - - $_host_cache_dir_tmp_regex = ltrim($_host_cache_dir_tmp_regex, '^\\/'); - if(strpos($_host_cache_dir_tmp_regex, '(?:\/') === 0 || strpos($_host_cache_dir_tmp_regex, '(\/') === 0) - $_host_cache_dir_tmp_regex = '/^'.preg_quote($_host_cache_dir_tmp, '/').$_host_cache_dir_tmp_regex; - else $_host_cache_dir_tmp_regex = '/^'.preg_quote($_host_cache_dir_tmp.'/', '/').$_host_cache_dir_tmp_regex; - - # if(WP_DEBUG) file_put_contents(WP_CONTENT_DIR.'/zc-debug.log', print_r($regex, TRUE)."\n".print_r($_host_cache_dir_tmp_regex, TRUE)."\n\n", FILE_APPEND); - // Uncomment the above line to debug regex pattern matching used by this routine; and others that call upon it. - - if(!rename($_host_cache_dir, $_host_cache_dir_tmp)) // Work from tmp directory so deletions are atomic. - throw new \exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', $this->text_domain), $_host_cache_dir)); - - /** @var $_file_dir \RecursiveDirectoryIterator Regex iterator reference for IDEs. */ - foreach(($_dir_regex_iteration = $this->dir_regex_iteration($_host_cache_dir_tmp, $_host_cache_dir_tmp_regex)) as $_resource) - { - $_resource_type = $_resource->getType(); - $_sub_path_name = $_resource->getSubpathname(); - $_path_name = $_resource->getPathname(); - - if($_host_cache_dir === $cache_dir && $_resource_type !== 'dir' && strpos($_sub_path_name, '/') === FALSE) - continue; // Don't delete links/files in the immediate directory; e.g. `zc-advanced-cache` or `.htaccess`, etc. - // Actual `http|https/...` cache links/files are nested. Links/files in the immediate directory are for other purposes. - - switch($_resource_type) // Based on type; i.e. `link`, `file`, `dir`. - { - case 'link': // Symbolic links; i.e. 404 errors. - - if($check_max_age && !empty($max_age) && is_file($_resource->getLinkTarget())) - if(($_lstat = lstat($_path_name)) && !empty($_lstat['mtime'])) - if($_lstat['mtime'] >= $max_age) // Still valid? - break; // Break switch handler. - - if(!unlink($_path_name)) // Throw exception if unable to delete. - throw new \exception(sprintf(__('Unable to delete symlink: `%1$s`.', $this->text_domain), $_path_name)); - $counter++; // Increment counter for each link we delete. - - break; // Break switch handler. - - case 'file': // Regular files; i.e. not symlinks. - - if($check_max_age && !empty($max_age)) // Should check max age? - if($_resource->getMTime() >= $max_age) // Still valid? - break; // Break switch handler. - - if(!unlink($_path_name)) // Throw exception if unable to delete. - throw new \exception(sprintf(__('Unable to delete file: `%1$s`.', $this->text_domain), $_path_name)); - $counter++; // Increment counter for each file we delete. - - break; // Break switch handler. - - case 'dir': // A regular directory; i.e. not a symlink. - - if($regex !== '/^.+/i') // Deleting everything? - break; // Break switch handler. Not deleting everything. - - if($check_max_age && !empty($max_age)) // Should check max age? - break; // Break switch handler. Not deleting everything in this case. - - if(!rmdir($_path_name)) // Throw exception if unable to delete the directory itself. - throw new \exception(sprintf(__('Unable to delete dir: `%1$s`.', $this->text_domain), $_path_name)); - # $counter++; // Increment counter for each directory we delete. ~ NO don't do that here. - - break; // Break switch handler. - - default: // Something else that is totally unexpected here. - throw new \exception(sprintf(__('Unexpected resource type: `%1$s`.', $this->text_domain), $_resource_type)); - } - } - unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name, $_lstat); // Housekeeping. - - if(!rename($_host_cache_dir_tmp, $_host_cache_dir)) // Deletions are atomic; restore original directory now. - throw new \exception(sprintf(__('Unable to delete files. Rename failure on tmp directory: `%1$s`.', $this->text_domain), $_host_cache_dir_tmp)); - } - unset($_host_scheme, $_host_url, $_host_cache_path_flags, $_host_cache_path, - $_host_cache_dir, $_host_cache_dir_tmp, $_host_cache_dir_tmp_regex); // Housekeeping. - - /* ------- End lock state... ------------- */ - - $this->cache_unlock($cache_lock); // Unlock cache directory. - - return $counter; // Total files deleted by this routine. - } - - /** - * Delete all files/dirs from a directory (for all schemes/hosts); - * including `zc-` prefixed files; or anything else for that matter. - * - * @since 141110 Refactoring cache clear/purge routines. - * - * @param string $dir The directory from which to delete files/dirs. - * - * SECURITY: This directory MUST be located inside the `/wp-content/` directory. - * Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself. - * Also, it cannot be: `mu-plugins`, `themes`, or `plugins`. - * - * @param boolean $delete_dir_too Delete parent? i.e. delete the `$dir` itself also? - * - * @return integer Total files/directories deleted by this routine (if any). - * - * @throws \exception If unable to delete a file/directory for any reason. - */ - public function delete_all_files_dirs_in($dir, $delete_dir_too = FALSE) - { - $counter = 0; // Initialize. - - if(!($dir = trim((string)$dir)) || !is_dir($dir)) - return $counter; // Nothing to do. - - $dir = $this->n_dir_seps($dir); // Normalize separators. - $dir_temp = $this->add_tmp_suffix($dir); // Temporary directory. - $wp_content_dir_regex = preg_quote($this->n_dir_seps(WP_CONTENT_DIR), '/'); - - if(!preg_match('/^'.$wp_content_dir_regex.'\/[^\/]+/i', $dir)) - return $counter; // Security flag; do nothing in this case. - - if(preg_match('/^'.$wp_content_dir_regex.'\/(?:mu\-plugins|themes|plugins)(?:\/|$)/i', $dir)) - return $counter; // Security flag; do nothing in this case. - - /* ------- Begin lock state... ----------- */ - - $cache_lock = $this->cache_lock(); // Lock cache writes. - - clearstatcache(); // Clear stat cache to be sure we have a fresh start below. - - if(!rename($dir, $dir_temp)) // Work from tmp directory so deletions are atomic. - throw new \exception(sprintf(__('Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`.', $this->text_domain), $dir)); - - /** @var $_file_dir \RecursiveDirectoryIterator for IDEs. */ - foreach(($_dir_regex_iteration = $this->dir_regex_iteration($dir_temp, '/.+/')) as $_resource) - { - $_resource_type = $_resource->getType(); - $_sub_path_name = $_resource->getSubpathname(); - $_path_name = $_resource->getPathname(); - - switch($_resource_type) // Based on type; i.e. `link`, `file`, `dir`. - { - case 'link': // Symbolic links; i.e. 404 errors. - - if(!unlink($_path_name)) // Throw exception if unable to delete. - throw new \exception(sprintf(__('Unable to delete symlink: `%1$s`.', $this->text_domain), $_path_name)); - $counter++; // Increment counter for each link we delete. - - break; // Break switch handler. - - case 'file': // Regular files; i.e. not symlinks. - - if(!unlink($_path_name)) // Throw exception if unable to delete. - throw new \exception(sprintf(__('Unable to delete file: `%1$s`.', $this->text_domain), $_path_name)); - $counter++; // Increment counter for each file we delete. - - break; // Break switch handler. - - case 'dir': // A regular directory; i.e. not a symlink. - - if(!rmdir($_path_name)) // Throw exception if unable to delete the directory itself. - throw new \exception(sprintf(__('Unable to delete dir: `%1$s`.', $this->text_domain), $_path_name)); - $counter++; // Increment counter for each directory we delete. - - break; // Break switch handler. - - default: // Something else that is totally unexpected here. - throw new \exception(sprintf(__('Unexpected resource type: `%1$s`.', $this->text_domain), $_resource_type)); - } - } - unset($_dir_regex_iteration, $_resource, $_resource_type, $_sub_path_name, $_path_name); // Housekeeping. - - if(!rename($dir_temp, $dir)) // Deletions are atomic; restore original directory now. - throw new \exception(sprintf(__('Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`.', $this->text_domain), $dir_temp)); - - if($delete_dir_too) // Delete parent? i.e. delete the `$dir` itself also? - { - if(!rmdir($dir)) // Throw exception if unable to delete. - throw new \exception(sprintf(__('Unable to delete directory: `%1$s`.', $this->text_domain), $dir)); - $counter++; // Increment counter for each directory we delete. - } - /* ------- End lock state... ------------- */ - - $this->cache_unlock($cache_lock); // Unlock cache directory. - - return $counter; // Total files deleted by this routine. - } - - /* -------------------------------------------------------------------------------------- - * Cache locking utilities. - -------------------------------------------------------------------------------------- */ - - /** - * Get an exclusive lock on the cache directory. - * - * @since 140422 First documented version. - * - * @return array Lock type & resource handle needed to unlock later or FALSE if disabled by filter. - * - * @throws \exception If {@link \sem_get()} not available and there's - * no writable tmp directory for {@link \flock()} either. - * - * @throws \exception If unable to obtain an exclusive lock by any available means. - * - * @note This call is blocking; i.e. it will not return a lock until a lock becomes possible. - * In short, this will block the caller until such time as write access becomes possible. - */ - public function cache_lock() - { - if($this->apply_wp_filters(__CLASS__.'_disable_cache_locking', FALSE)) - return FALSE; - - if(!($wp_config_file = $this->find_wp_config_file())) - throw new \exception(__('Unable to find the wp-config.php file.', $this->text_domain)); - - $locking_method = $this->apply_wp_filters(__METHOD__.'_lock_type', 'flock'); - - if(!in_array($locking_method, array('flock', 'sem'))) - $locking_method = 'flock'; - - if($locking_method === 'sem') - if($this->function_is_possible('sem_get')) - if(($ipc_key = ftok($wp_config_file, 'w'))) - if(($resource = sem_get($ipc_key, 1)) && sem_acquire($resource)) - return array('type' => 'sem', 'resource' => $resource); - - // Use `flock()` as a decent fallback when `sem_get()` is not not forced or is not possible. - - if(!($tmp_dir = $this->get_tmp_dir())) - throw new \exception(__('No writable tmp directory.', $this->text_domain)); - - $inode_key = fileinode($wp_config_file); - $mutex = $tmp_dir.'/'.$this->slug.'-'.$inode_key.'.lock'; - if(!($resource = fopen($mutex, 'w')) || !flock($resource, LOCK_EX)) - throw new \exception(__('Unable to obtain an exclusive lock.', $this->text_domain)); - - return array('type' => 'flock', 'resource' => $resource); - } - - /** - * Release an exclusive lock on the cache directory. - * - * @since 140422 First documented version. - * - * @param array $lock Type & resource that we are unlocking. - */ - public function cache_unlock(array $lock) - { - if($this->apply_wp_filters(__CLASS__.'_disable_cache_locking', FALSE)) - return; - - if(!is_array($lock)) - return; // Not possible. - - if(empty($lock['type']) || empty($lock['resource'])) - return; // Not possible. - - if(!is_resource($lock['resource'])) - return; // Not possible. - - if($lock['type'] === 'sem') - sem_release($lock['resource']); - - else if($lock['type'] === 'flock') - { - flock($lock['resource'], LOCK_UN); - fclose($lock['resource']); - } - } - - /* -------------------------------------------------------------------------------------- - * Translation utilities for ZenCache. - -------------------------------------------------------------------------------------- */ - - /** - * `X file` or `X files`, translated w/ singlular/plural context. - * - * @since 140422 First documented version. - * - * @param integer $counter Total files; i.e. the counter. - * - * @return string The phrase `X file` or `X files`. - */ - public function i18n_files($counter) - { - $counter = (integer)$counter; // Force integer. - - return sprintf(_n('%1$s file', '%1$s files', $counter, $this->text_domain), $counter); - } - - /** - * `X directory` or `X directories`, translated w/ singlular/plural context. - * - * @since 140422 First documented version. - * - * @param integer $counter Total directories; i.e. the counter. - * - * @return string The phrase `X directory` or `X directories`. - */ - public function i18n_dirs($counter) - { - $counter = (integer)$counter; // Force integer. - - return sprintf(_n('%1$s directory', '%1$s directories', $counter, $this->text_domain), $counter); - } - - /** - * `X file/directory` or `X files/directories`, translated w/ singlular/plural context. - * - * @since 140422 First documented version. - * - * @param integer $counter Total files/directories; i.e. the counter. - * - * @return string The phrase `X file/directory` or `X files/directories`. - */ - public function i18n_files_dirs($counter) - { - $counter = (integer)$counter; // Force integer. - - return sprintf(_n('%1$s file/directory', '%1$s files/directories', $counter, $this->text_domain), $counter); - } - - /* -------------------------------------------------------------------------------------- - * Hook/filter API for ZenCache. - -------------------------------------------------------------------------------------- */ - - /** - * Assigns an ID to each callable attached to a hook/filter. - * - * @since 140422 First documented version. - * - * @param string|callable|mixed $function A string or a callable. - * - * @return string Hook ID for the given `$function`. - * - * @throws \exception If the hook/function is invalid (i.e. it's not possible to generate an ID). - */ - public function hook_id($function) - { - if(is_string($function)) - return $function; - - if(is_object($function)) // Closure. - $function = array($function, ''); - else $function = (array)$function; - - if(is_object($function[0])) - return spl_object_hash($function[0]).$function[1]; - - else if(is_string($function[0])) - return $function[0].'::'.$function[1]; - - throw new \exception(__('Invalid hook.', $this->text_domain)); - } - - /** - * Adds a new hook (works with both actions & filters). - * - * @since 140422 First documented version. - * - * @param string $hook The name of a hook to attach to. - * @param string|callable|mixed $function A string or a callable. - * @param integer $priority Hook priority; defaults to `10`. - * @param integer $accepted_args Max number of args that should be passed to the `$function`. - * - * @return boolean This always returns a `TRUE` value. - */ - public function add_hook($hook, $function, $priority = 10, $accepted_args = 1) - { - $this->hooks[$hook][$priority][$this->hook_id($function)] - = array('function' => $function, 'accepted_args' => (integer)$accepted_args); - return TRUE; // Always returns true. - } - - /** - * Adds a new action hook. - * - * @since 140422 First documented version. - * - * @return boolean This always returns a `TRUE` value. - * - * @see add_hook() - */ - public function add_action() // Simple `add_hook()` alias. - { - return call_user_func_array(array($this, 'add_hook'), func_get_args()); - } - - /** - * Adds a new filter. - * - * @since 140422 First documented version. - * - * @return boolean This always returns a `TRUE` value. - * - * @see add_hook() - */ - public function add_filter() // Simple `add_hook()` alias. - { - return call_user_func_array(array($this, 'add_hook'), func_get_args()); - } - - /** - * Removes a hook (works with both actions & filters). - * - * @since 140422 First documented version. - * - * @param string $hook The name of a hook to remove. - * @param string|callable|mixed $function A string or a callable. - * @param integer $priority Hook priority; defaults to `10`. - * - * @return boolean `TRUE` if removed; else `FALSE` if not removed for any reason. - */ - public function remove_hook($hook, $function, $priority = 10) - { - if(!isset($this->hooks[$hook][$priority][$this->hook_id($function)])) - return FALSE; // Nothing to remove in this case. - - unset($this->hooks[$hook][$priority][$this->hook_id($function)]); - if(!$this->hooks[$hook][$priority]) unset($this->hooks[$hook][$priority]); - return TRUE; // Existed before it was removed in this case. - } - - /** - * Removes an action. - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if removed; else `FALSE` if not removed for any reason. - * - * @see remove_hook() - */ - public function remove_action() // Simple `remove_hook()` alias. - { - return call_user_func_array(array($this, 'remove_hook'), func_get_args()); - } - - /** - * Removes a filter. - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` if removed; else `FALSE` if not removed for any reason. - * - * @see remove_hook() - */ - public function remove_filter() // Simple `remove_hook()` alias. - { - return call_user_func_array(array($this, 'remove_hook'), func_get_args()); - } - - /** - * Runs any callables attached to an action. - * - * @since 140422 First documented version. - * - * @param string $hook The name of an action hook. - */ - public function do_action($hook) - { - if(empty($this->hooks[$hook])) - return; // No hooks. - - $hook_actions = $this->hooks[$hook]; - ksort($hook_actions); // Sort by priority. - - $args = func_get_args(); // We'll need these below. - foreach($hook_actions as $_hook_action) foreach($_hook_action as $_action) - { - if(!isset($_action['function'], $_action['accepted_args'])) - continue; // Not a valid filter in this case. - - call_user_func_array($_action['function'], array_slice($args, 1, $_action['accepted_args'])); - } - unset($_hook_action, $_action); // Housekeeping. - } - - /** - * Runs any callables attached to a filter. - * - * @since 140422 First documented version. - * - * @param string $hook The name of a filter hook. - * @param mixed $value The value to filter. - * - * @return mixed The filtered `$value`. - */ - public function apply_filters($hook, $value) - { - if(empty($this->hooks[$hook])) - return $value; // No hooks. - - $hook_filters = $this->hooks[$hook]; - ksort($hook_filters); // Sort by priority. - - $args = func_get_args(); // We'll need these below. - foreach($hook_filters as $_hook_filter) foreach($_hook_filter as $_filter) - { - if(!isset($_filter['function'], $_filter['accepted_args'])) - continue; // Not a valid filter in this case. - - $args[1] = $value; // Continously update the argument `$value`. - $value = call_user_func_array($_filter['function'], array_slice($args, 1, $_filter['accepted_args'])); - } - unset($_hook_filter, $_filter); // Housekeeping. - - return $value; // With applied filters. - } - - /** - * Does an action w/ back compat. for Quick Cache. - * - * @since 150218 First documented version. - * - * @param string $hook The hook to apply. - */ - public function do_wp_action($hook) - { - $hook = (string)$hook; // Force string value. - $args = func_get_args(); // Including `$hook`. - call_user_func_array('do_action', $args); - - if(stripos($hook, __NAMESPACE__) === 0) // Do Quick Cache back compat? - { - $quick_cache_filter = 'quick_cache'.substr($hook, strlen(__NAMESPACE__)); - $quick_cache_args = $args; // Use a copy of the args. - $quick_cache_args[0] = $quick_cache_filter; - - call_user_func_array('do_action', $quick_cache_args); - } - } - - /** - * Applies filters w/ back compat. for Quick Cache. - * - * @since 150218 First documented version. - * - * @param string $hook The hook to apply. - * - * @return mixed The filtered value. - */ - public function apply_wp_filters($hook) - { - $hook = (string)$hook; // Force string value. - $args = func_get_args(); // Including `$hook`. - $value = call_user_func_array('apply_filters', $args); - - if(stripos($hook, __NAMESPACE__) === 0) // Do Quick Cache back compat? - { - $quick_cache_hook = 'quick_cache'.substr($hook, strlen(__NAMESPACE__)); - $quick_cache_args = $args; // Use a copy of the args. - $quick_cache_args[0] = $quick_cache_hook; - $quick_cache_args[1] = $value; - - $value = call_user_func_array('apply_filters', $quick_cache_args); - } - return $value; // Filtered value. - } - - /* -------------------------------------------------------------------------------------- - * Misc. long property values. - -------------------------------------------------------------------------------------- */ - - /** - * Apache `.htaccess` rules that deny public access to the contents of a directory. - * - * @since 140422 First documented version. - * - * @var string `.htaccess` fules. - */ - public $htaccess_deny = "\n\tRequire all denied\n\n\n\tdeny from all\n"; - } - - if(!function_exists('\\'.__NAMESPACE__.'\\__')) - { - /** - * Polyfill for {@link \__()}. - * - * @since 140422 First documented version. - * - * @param string $string String to translate. - * @param string $text_domain Plugin text domain. - * - * @return string Possibly translated string. - */ - function __($string, $text_domain) - { - static $exists; // Static cache. - - if($exists || ($exists = function_exists('__'))) - return \__($string, $text_domain); - - return $string; // Not possible (yet). - } - } - } -} diff --git a/zencache/includes/translations/zencache.pot b/zencache/includes/translations/zencache.pot deleted file mode 100644 index f76ef9a..0000000 --- a/zencache/includes/translations/zencache.pot +++ /dev/null @@ -1,1398 +0,0 @@ -# Copyright (C) 2015 ZenCache -# This file is distributed under the same license as the ZenCache package. -msgid "" -msgstr "" -"Project-Id-Version: ZenCache 150409\n" -"Report-Msgid-Bugs-To: http://wordpress.org/tag/zencache\n" -"POT-Creation-Date: 2015-04-09 23:12:44+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2015-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" - -#. translators: This string is actually NOT translatable because the `__()` -#. function is not available at this point in the processing. -#: includes/advanced-cache.tpl.php:726 -msgid "%1$s fully functional :-) Cache file served for (%2$s) in %3$s seconds, on: %4$s." -msgstr "" - -#: includes/advanced-cache.tpl.php:858 -msgid "Unexpected OB phase: `%1$s`." -msgstr "" - -#: includes/advanced-cache.tpl.php:930 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:937 includes/advanced-cache.tpl.php:960 -msgid "Unable to create symlink: `%1$s` » `%2$s`. Possible permissions issue (or race condition), please check your cache directory: `%3$s`." -msgstr "" - -#: includes/advanced-cache.tpl.php:948 -msgid "%1$s file path: %2$s" -msgstr "" - -#: includes/advanced-cache.tpl.php:949 -msgid "%1$s file built for (%2$s) in %3$s seconds, on: %4$s." -msgstr "" - -#: includes/advanced-cache.tpl.php:951 -msgid "This %1$s file will auto-expire (and be rebuilt) on: %2$s (based on your configured expiration time)." -msgstr "" - -#: includes/advanced-cache.tpl.php:975 -msgid "%1$s: failed to write cache file for: `%2$s`; possible permissions issue (or race condition), please check your cache directory: `%3$s`." -msgstr "" - -#: includes/advanced-cache.tpl.php:1021 -msgid "because `PHP_SAPI` reports that you are currently running from the command line." -msgstr "" - -#: includes/advanced-cache.tpl.php:1025 -msgid "because `$_GET['zcAC']` is set to a boolean-ish FALSE value." -msgstr "" - -#: includes/advanced-cache.tpl.php:1029 -msgid "because `$_SERVER['HTTP_HOST']` is missing from your server configuration." -msgstr "" - -#: includes/advanced-cache.tpl.php:1033 -msgid "because `$_SERVER['REQUEST_URI']` is missing from your server configuration." -msgstr "" - -#: includes/advanced-cache.tpl.php:1037 -msgid "because the PHP constant `ZENCACHE_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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1041 -msgid "because the environment variable `$_SERVER['ZENCACHE_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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1045 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1049 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1053 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1057 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1061 -msgid "because `$_SERVER['REQUEST_URI']` indicates this is a `/feed`; and the configuration of this site says not to cache XML-based feeds." -msgstr "" - -#: includes/advanced-cache.tpl.php:1065 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1069 -msgid "because `$_SERVER['REQUEST_URI']` or the `is_admin()` function indicates this is an administrative area of the site." -msgstr "" - -#: includes/advanced-cache.tpl.php:1073 -msgid "because `$_SERVER['REQUEST_URI']` indicates this is a Multisite Network; and this was a request for `/files/*`, not a page." -msgstr "" - -#: includes/advanced-cache.tpl.php:1078 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1082 -msgid "because `$_GET` contains query string data. The current configuration says NOT to cache GET requests with a query string." -msgstr "" - -#: includes/advanced-cache.tpl.php:1086 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1090 -msgid "because a plugin running on this installation says this page is in Maintenance Mode; i.e. is not available publicly at this time." -msgstr "" - -#: includes/advanced-cache.tpl.php:1094 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1098 -msgid "because the contents of this document contain ``, which indicates this is an auto-generated WordPress error message." -msgstr "" - -#: includes/advanced-cache.tpl.php:1102 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1106 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1110 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1114 -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." -msgstr "" - -#: includes/advanced-cache.tpl.php:1118 -msgid "due to an unexpected behavior in the application. Please report this as a bug!" -msgstr "" - -#: includes/advanced-cache.tpl.php:1121 -msgid "%1$s is NOT caching this page, %2$s" -msgstr "" - -#: includes/menu-pages.php:26 -msgid "Wipe Cache (Start Fresh); clears the cache for all sites in this network at once!" -msgstr "" - -#: includes/menu-pages.php:28 -msgid "Wipe" -msgstr "" - -#: includes/menu-pages.php:30 -msgid "Clear Cache (Start Fresh)" -msgstr "" - -#: includes/menu-pages.php:30 -msgid "; affects the current site only." -msgstr "" - -#: includes/menu-pages.php:32 -msgid "Clear" -msgstr "" - -#: includes/menu-pages.php:35 -msgid "Restore default plugin options? You will lose all of your current settings! Are you absolutely sure about this?" -msgstr "" - -#: includes/menu-pages.php:37 -msgid "Restore" -msgstr "" - -#: includes/menu-pages.php:39 -msgid "All Panels" -msgstr "" - -#: includes/menu-pages.php:46 -msgid "Pro Upgrade" -msgstr "" - -#: includes/menu-pages.php:47 -msgid "Newsletter (Subscribe)" -msgstr "" - -#: includes/menu-pages.php:48 -msgid "Beta Testers (Signup)" -msgstr "" - -#: includes/menu-pages.php:51 -msgid "Plugin Options" -msgstr "" - -#: includes/menu-pages.php:64 -msgid "Options updated successfully." -msgstr "" - -#: includes/menu-pages.php:70 -msgid "Default options successfully restored." -msgstr "" - -#: includes/menu-pages.php:76 -msgid "Cache wiped across all sites; recreation will occur automatically over time." -msgstr "" - -#: includes/menu-pages.php:82 -msgid "Cache cleared for this site; recreation will occur automatically over time." -msgstr "" - -#: includes/menu-pages.php:88 -msgid "Failed to update your /wp-config.php file automatically. Please add the following line to your /wp-config.php file (right after the opening <?php tag; on it's own line).
<?php
define('WP_CACHE', TRUE);
" -msgstr "" - -#: includes/menu-pages.php:94 -msgid "Failed to update your /wp-config.php file automatically. Please remove the following line from your /wp-config.php file, or set WP_CACHE to a FALSE value.
define('WP_CACHE', TRUE);
" -msgstr "" - -#: includes/menu-pages.php:101 -msgid "Failed to update your /wp-content/advanced-cache.php file. Cannot write stat file: %1$s/zc-advanced-cache. Please be sure this directory exists (and that it's writable): %1$s. Please use directory permissions 755 or higher (perhaps 777). Once you've done this, please try again." -msgstr "" - -#: includes/menu-pages.php:102 -msgid "Failed to update your /wp-content/advanced-cache.php file. Most likely a permissions error. Please create an empty file here: /wp-content/advanced-cache.php (just an empty PHP file, with nothing in it); give it permissions 644 or higher (perhaps 666). Once you've done this, please try again." -msgstr "" - -#: includes/menu-pages.php:108 -msgid "Failed to remove your /wp-content/advanced-cache.php file. Most likely a permissions error. Please delete (or empty the contents of) this file: /wp-content/advanced-cache.php." -msgstr "" - -#: includes/menu-pages.php:114 -msgid "close" -msgstr "" - -#: includes/menu-pages.php:115 -msgid "Pro Features (Preview) ~ New option panels below. Please explore before upgrading .
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." -msgstr "" - -#: includes/menu-pages.php:121 -msgid "%1$s is currently disabled; please review options below." -msgstr "" - -#: includes/menu-pages.php:131 -msgid "Basic Configuration (Required)" -msgstr "" - -#: includes/menu-pages.php:132 -msgid "Review these basic options and %1$s™ will be ready-to-go!" -msgstr "" - -#: includes/menu-pages.php:140 -msgid "Enable/Disable" -msgstr "" - -#: includes/menu-pages.php:145 -msgid "%1$s™ = SPEED!!" -msgstr "" - -#: includes/menu-pages.php:146 -msgid "Yes, enable %1$s™" -msgstr "" - -#: includes/menu-pages.php:146 -msgid "No, disable." -msgstr "" - -#: includes/menu-pages.php:147 -msgid "HUGE Time-Saver: Approx. 95%% of all WordPress sites running %1$s, simply enable it here; and that's it :-) No further configuration is necessary (really). 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 . 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." -msgstr "" - -#: includes/menu-pages.php:150 -msgid "How Can I Tell %1$s is Working?" -msgstr "" - -#: includes/menu-pages.php:151 -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." -msgstr "" - -#: includes/menu-pages.php:152 -msgid "Once %1$s has been enabled, you'll need to log out (and/or clear browser cookies). 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." -msgstr "" - -#: includes/menu-pages.php:153 -msgid "To verify that %1$s is working, 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 lightning fast now that %1$s is running; and it gets faster over time!" -msgstr "" - -#: includes/menu-pages.php:155 -msgid "Yes, enable notes in the source code so I can see it's working (recommended)." -msgstr "" - -#: includes/menu-pages.php:156 -msgid "Yes, enable notes in the source code AND show debugging details (not recommended for production)." -msgstr "" - -#: includes/menu-pages.php:157 -msgid "No, I don't want my source code to contain any of these notes." -msgstr "" - -#: includes/menu-pages.php:168 -msgid "Plugin Deletion Safeguards" -msgstr "" - -#: includes/menu-pages.php:173 -msgid "Uninstall on Plugin Deletion; or Safeguard Options?" -msgstr "" - -#: includes/menu-pages.php:174 -msgid "Tip: 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 Yes and THEN 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 advanced-cache.php file, terminate CRON jobs, etc. It erases itself from existence completely." -msgstr "" - -#: includes/menu-pages.php:176 -msgid "Safeguard my options and the cache (recommended)." -msgstr "" - -#: includes/menu-pages.php:177 -msgid "Yes, uninstall (completely erase) %1$s on plugin deletion." -msgstr "" - -#: includes/menu-pages.php:186 -msgid "Advanced Configuration (All Optional)" -msgstr "" - -#: includes/menu-pages.php:187 -msgid "Recommended for advanced site owners only; already pre-configured for most WP installs." -msgstr "" - -#: includes/menu-pages.php:197 -msgid "Clearing the Cache" -msgstr "" - -#: includes/menu-pages.php:201 -msgid "Clearing the Cache Manually" -msgstr "" - -#: includes/menu-pages.php:203 -msgid "Once %1$s is enabled, you will find this new option in your WordPress Admin Bar (see 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)." -msgstr "" - -#: includes/menu-pages.php:204 -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)." -msgstr "" - -#: includes/menu-pages.php:206 -msgid "Yes, enable the "Clear Cache" button in the WordPress admin bar." -msgstr "" - -#: includes/menu-pages.php:207 -msgid "No, I don't intend to clear the cache manually; exclude from admin bar." -msgstr "" - -#: includes/menu-pages.php:210 -msgid "Running the s2Clean Theme by WebSharks?" -msgstr "" - -#: includes/menu-pages.php:211 -msgid "If s2Clean is installed, %1$s can be configured to clear the Markdown cache too (if you've enabled Markdown processing with s2Clean). The s2Clean Markdown cache is only cleared when you manually clear the cache (with %1$s); and only if you enable this option here. Note: s2Clean's Markdown cache is extremely dynamic. Just like the rest of your site, s2Clean caches do NOT need to be cleared away at all, as this happens automatically when your content changes. However, some developers find this feature useful while developing their site; just to force a refresh." -msgstr "" - -#: includes/menu-pages.php:213 -msgid "Yes, if the s2Clean theme is installed; also clear s2Clean-related caches." -msgstr "" - -#: includes/menu-pages.php:214 -msgid "No, I don't use s2Clean; or, I don't want s2Clean-related caches cleared." -msgstr "" - -#: includes/menu-pages.php:216 -msgid "Process Other Custom PHP Code?" -msgstr "" - -#: includes/menu-pages.php:217 -msgid "If you have other custom routines you'd like to process when the cache is cleared manually, please type your custom PHP code here. The PHP code that you provide is only evaluated when you manually clear the cache (with %1$s); and only if the field below contains PHP code. Note: if your PHP code outputs a message (e.g. if you have echo '<p>My message</p>';); your message will be displayed along with any other notes from %1$s itself. This could be useful to developers that need to clear server caches too (such as APC or memcache)." -msgstr "" - -#: includes/menu-pages.php:219 -msgid "Example: <?php apc_clear_cache(); echo '<p>Also cleared APC cache.</p>'; ?>" -msgstr "" - -#: includes/menu-pages.php:221 -msgid "Clearing the Cache Automatically" -msgstr "" - -#: includes/menu-pages.php:223 -msgid "This is built into the %1$s plugin; e.g. 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. Notifications in the Dashboard regarding these detections can be enabled/disabled below." -msgstr "" - -#: includes/menu-pages.php:225 -msgid "Yes, enable %1$s notifications in the Dashboard when changes are detected & one or more cache files are cleared automatically." -msgstr "" - -#: includes/menu-pages.php:226 -msgid "No, I don't want to know (don't really care) what %1$s is doing behind-the-scene." -msgstr "" - -#: includes/menu-pages.php:228 -msgid "Auto-Clear Designated \"Home Page\" Too?" -msgstr "" - -#: includes/menu-pages.php:229 -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\"?" -msgstr "" - -#: includes/menu-pages.php:231 -msgid "Yes, if any single Post/Page is cleared/reset; also purge the \"Home Page\"." -msgstr "" - -#: includes/menu-pages.php:232 -msgid "No, my Home Page does not provide a list of Posts/Pages; e.g. this is not necessary." -msgstr "" - -#: includes/menu-pages.php:234 -msgid "Auto-Clear Designated \"Posts Page\" Too?" -msgstr "" - -#: includes/menu-pages.php:235 -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\"?" -msgstr "" - -#: includes/menu-pages.php:237 -msgid "Yes, if any single Post/Page is cleared/reset; also purge the \"Posts Page\"." -msgstr "" - -#: includes/menu-pages.php:238 -msgid "No, I don't use a separate Posts Page; e.g. my Home Page IS my Posts Page." -msgstr "" - -#: includes/menu-pages.php:240 -msgid "Auto-Clear \"Author Page\" Too?" -msgstr "" - -#: includes/menu-pages.php:241 -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\"?" -msgstr "" - -#: includes/menu-pages.php:243 -msgid "Yes, if any single Post/Page is cleared/reset; also purge the \"Author Page\"." -msgstr "" - -#: includes/menu-pages.php:244 -msgid "No, my site doesn't use multiple authors and/or I don't have any \"Author Page\" archive views." -msgstr "" - -#: includes/menu-pages.php:246 -msgid "Auto-Clear \"Category Archives\" Too?" -msgstr "" - -#: includes/menu-pages.php:247 -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?" -msgstr "" - -#: includes/menu-pages.php:249 -msgid "Yes, if any single Post/Page is cleared/reset; also clear the associated Category archive views." -msgstr "" - -#: includes/menu-pages.php:250 -msgid "No, my site doesn't use Categories and/or I don't have any Category archive views." -msgstr "" - -#: includes/menu-pages.php:252 -msgid "Auto-Clear \"Tag Archives\" Too?" -msgstr "" - -#: includes/menu-pages.php:253 -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?" -msgstr "" - -#: includes/menu-pages.php:255 -msgid "Yes, if any single Post/Page is cleared/reset; also clear the associated Tag archive views." -msgstr "" - -#: includes/menu-pages.php:256 -msgid "No, my site doesn't use Tags and/or I don't have any Tag archive views." -msgstr "" - -#: includes/menu-pages.php:258 -msgid "Auto-Clear \"Custom Term Archives\" Too?" -msgstr "" - -#: includes/menu-pages.php:259 -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?" -msgstr "" - -#: includes/menu-pages.php:261 -msgid "Yes, if any single Post/Page is cleared/reset; also purge any associated custom Term archive views." -msgstr "" - -#: includes/menu-pages.php:262 -msgid "No, my site doesn't use any custom Terms and/or I don't have any custom Term archive views." -msgstr "" - -#: includes/menu-pages.php:264 -msgid "Auto-Clear \"Custom Post Type Archives\" Too?" -msgstr "" - -#: includes/menu-pages.php:265 -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?" -msgstr "" - -#: includes/menu-pages.php:267 -msgid "Yes, if any single Post with a Custom Post Type is cleared/reset; also clear any associated Custom Post Type archive views." -msgstr "" - -#: includes/menu-pages.php:268 -msgid "No, my site doesn't use any Custom Post Types and/or I don't have any Custom Post Type archive views." -msgstr "" - -#: includes/menu-pages.php:279 -msgid "Directory / Expiration Time" -msgstr "" - -#: includes/menu-pages.php:283 -msgid "Base Cache Directory (Must be Writable; e.g. Permissions 755 or Higher)" -msgstr "" - -#: includes/menu-pages.php:284 -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." -msgstr "" - -#: includes/menu-pages.php:288 -msgid "Automatic Expiration Time (Max Age)" -msgstr "" - -#: includes/menu-pages.php:289 -msgid "If you don't update your site much, you could set this to 6 months 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 7 days (recommended); is a good conservative middle-ground." -msgstr "" - -#: includes/menu-pages.php:290 -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." -msgstr "" - -#: includes/menu-pages.php:291 -msgid "All of that being said, you could set this to just 60 seconds 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 30 minutes, 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 ." -msgstr "" - -#: includes/menu-pages.php:293 -msgid "Tip: the value that you specify here MUST be compatible with PHP's strtotime() function. Examples: 30 seconds, 2 hours, 7 days, 6 months, 1 year." -msgstr "" - -#: includes/menu-pages.php:294 -msgid "Note: %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 daily); purging expired cache files periodically. This prevents a HUGE cache from building up over time, creating a potential storage issue." -msgstr "" - -#: includes/menu-pages.php:304 -msgid "Client-Side Cache" -msgstr "" - -#: includes/menu-pages.php:309 -msgid "Allow Double-Caching In The Client-Side Browser?" -msgstr "" - -#: includes/menu-pages.php:310 -msgid "Recommended setting: No (for membership sites, very important). Otherwise, Yes would be better (if users do NOT log in/out of your site)." -msgstr "" - -#: includes/menu-pages.php:311 -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." -msgstr "" - -#: includes/menu-pages.php:312 -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 Yes (recommended in this case). Allowing a client-side browser cache will improve speed and reduce outgoing bandwidth when this option is feasible." -msgstr "" - -#: includes/menu-pages.php:314 -msgid "No, prevent a client-side browser cache (safest option)." -msgstr "" - -#: includes/menu-pages.php:315 -msgid "Yes, I will allow a client-side browser cache of pages on the site." -msgstr "" - -#: includes/menu-pages.php:317 -msgid "Tip: Setting this to No is highly recommended when running a membership plugin like s2Member (as one example). In fact, many plugins like s2Member will send nocache_headers() 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." -msgstr "" - -#: includes/menu-pages.php:318 -msgid "Tip: Setting this to No 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." -msgstr "" - -#: includes/menu-pages.php:319 -msgid "Advanced Tip: if you have this set to No, but you DO want to allow a few special URLs to be cached by the browser; you can add this parameter to your URL ?zcABC=1. This tells %1$s that it's OK for the browser to cache that particular URL. In other words, the zcABC=1 parameter tells %1$s NOT to send no-cache headers to the browser." -msgstr "" - -#: includes/menu-pages.php:331 -msgid "Logged-In Users" -msgstr "" - -#: includes/menu-pages.php:336 -msgid "Caching Enabled for Logged-In Users & Comment Authors?" -msgstr "" - -#: includes/menu-pages.php:337 -msgid "This should almost ALWAYS be set to No. 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." -msgstr "" - -#: includes/menu-pages.php:339 -msgid "Exception (Membership Sites): If you run a site with many users and the majority of your traffic comes from users who ARE logged-in, please choose: Yes (maintain separate cache). %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 option|meta 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." -msgstr "" - -#: includes/menu-pages.php:341 -msgid "No, do NOT cache; or serve a cache file when a user is logged-in (safest option)." -msgstr "" - -#: includes/menu-pages.php:342 -msgid "Yes, and maintain a separate cache for each user (recommended for membership sites)." -msgstr "" - -#: includes/menu-pages.php:343 -msgid "Yes, but DON'T maintain a separate cache for each user (I know what I'm doing)." -msgstr "" - -#: includes/menu-pages.php:345 -msgid "Note: 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." -msgstr "" - -#: includes/menu-pages.php:346 -msgid "Note: 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." -msgstr "" - -#: includes/menu-pages.php:356 -msgid "GET Requests" -msgstr "" - -#: includes/menu-pages.php:361 -msgid "Caching Enabled for GET (Query String) Requests?" -msgstr "" - -#: includes/menu-pages.php:362 -msgid "This should almost ALWAYS be set to No. UNLESS, you're using unfriendly Permalinks. In other words, if all of your URLs contain a query string (e.g. /?key=value); 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 Yes; and don't worry too much, the sky won't fall on your head :-)" -msgstr "" - -#: includes/menu-pages.php:364 -msgid "No, do NOT cache (or serve a cache file) when a query string is present." -msgstr "" - -#: includes/menu-pages.php:365 -msgid "Yes, I would like to cache URLs that contain a query string." -msgstr "" - -#: includes/menu-pages.php:367 -msgid "Note: POST requests (i.e. forms with method="post") are always excluded from the cache, which is the way it should be. Any POST/PUT/DELETE 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." -msgstr "" - -#: includes/menu-pages.php:368 -msgid "Advanced Tip: 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 ?zcAC=1. 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 ?zcAC=0." -msgstr "" - -#: includes/menu-pages.php:378 -msgid "404 Requests" -msgstr "" - -#: includes/menu-pages.php:383 -msgid "Caching Enabled for 404 Requests?" -msgstr "" - -#: includes/menu-pages.php:384 -msgid "When this is set to No, %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 Yes, %1$s will cache the 404 page (see Creating an Error 404 Page) and then serve that single cache file to all future 404 requests." -msgstr "" - -#: includes/menu-pages.php:386 -msgid "No, do NOT cache (or serve a cache file) for 404 requests." -msgstr "" - -#: includes/menu-pages.php:387 -msgid "Yes, I would like to cache the 404 page and serve the cached file for 404 requests." -msgstr "" - -#: includes/menu-pages.php:389 -msgid "How does %1$s cache 404 requests? %1$s will create a special cache file (----404----.html, see Advanced Tip below) for the first 404 request and then symlink 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." -msgstr "" - -#: includes/menu-pages.php:390 -msgid "Advanced Tip: The default 404 cache filename (----404----.html) 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 define('ZENCACHE_404_CACHE_FILENAME', 'your-404-cache-filename'); to your wp-config.php file (note that the .html extension should be excluded when defining a new filename)." -msgstr "" - -#: includes/menu-pages.php:400 -msgid "RSS, RDF, and Atom Feeds" -msgstr "" - -#: includes/menu-pages.php:405 -msgid "Caching Enabled for RSS, RDF, Atom Feeds?" -msgstr "" - -#: includes/menu-pages.php:406 -msgid "This should almost ALWAYS be set to No. 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 Yes, you may experience delays in the detection of new posts. NOTE: If you do enable this, it is highly recommended that you also enable automatic Feed Clearing too. Please see the section above: \"Clearing the Cache\". Find the sub-section titled: \"Auto-Clear RSS/RDF/ATOM Feeds\" (available only in the pro version)." -msgstr "" - -#: includes/menu-pages.php:408 -msgid "No, do NOT cache (or serve a cache file) when displaying a feed." -msgstr "" - -#: includes/menu-pages.php:409 -msgid "Yes, I would like to cache feed URLs." -msgstr "" - -#: includes/menu-pages.php:411 -msgid "Note: 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: WordPress Feeds." -msgstr "" - -#: includes/menu-pages.php:423 -msgid "URI Exclusion Patterns" -msgstr "" - -#: includes/menu-pages.php:427 -msgid "Don't Cache These Special URI Exclusion Patterns?" -msgstr "" - -#: includes/menu-pages.php:428 -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 REQUEST_URI; i.e. /path/?query (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 * character can also be used when necessary; e.g. /category/abc-followed-by-*; (where * = anything, 0 or more characters in length)." -msgstr "" - -#: includes/menu-pages.php:430 -msgid "Tip: let's use this example URL: http://www.example.com/post/example-post-123. To exclude this URL, you would put this line into the field above: /post/example-post-123. Or, you could also just put in a small fragment, like: example or example-*-123 and that would exclude any URI containing that word fragment." -msgstr "" - -#: includes/menu-pages.php:431 includes/menu-pages.php:451 -#: includes/menu-pages.php:471 includes/menu-pages.php:575 -#: includes/menu-pages.php:579 includes/menu-pages.php:661 -msgid "Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line." -msgstr "" - -#: includes/menu-pages.php:443 -msgid "HTTP Referrer Exclusion Patterns" -msgstr "" - -#: includes/menu-pages.php:447 -msgid "Don't Cache These Special HTTP Referrer Exclusion Patterns?" -msgstr "" - -#: includes/menu-pages.php:448 -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 HTTP_REFERER (caSe insensitive). A wildcard * character can also be used when necessary; e.g. *.domain.com; (where * = anything, 0 or more characters in length)." -msgstr "" - -#: includes/menu-pages.php:450 -msgid "Tip: let's use this example URL: http://www.referring-domain.com/search/?q=search+terms. To exclude this referring URL, you could put this line into the field above: www.referring-domain.com. Or, you could also just put in a small fragment, like: /search/ or q=*; and that would exclude any referrer containing that word fragment." -msgstr "" - -#: includes/menu-pages.php:463 -msgid "User-Agent Exclusion Patterns" -msgstr "" - -#: includes/menu-pages.php:467 -msgid "Don't Cache These Special User-Agent Exclusion Patterns?" -msgstr "" - -#: includes/menu-pages.php:468 -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 HTTP_USER_AGENT (caSe insensitive). A wildcard * character can also be used when necessary; e.g. Android *; Chrome/* Mobile; (where * = anything, 0 or more characters in length)." -msgstr "" - -#: includes/menu-pages.php:470 -msgid "Tip: if you wanted to exclude iPhones put this line into the field above: iPhone;*AppleWebKit. Or, you could also just put in a small fragment, like: iphone; 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)." -msgstr "" - -#: includes/menu-pages.php:483 -msgid "Auto-Cache Engine" -msgstr "" - -#: includes/menu-pages.php:488 -msgid "Enable the Auto-Cache Engine?" -msgstr "" - -#: includes/menu-pages.php:489 -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." -msgstr "" - -#: includes/menu-pages.php:490 -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 First-Come Slow-Load Issue. 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 WP-Cron (already built into WordPress). The Auto-Cache Engine runs at 15-minute intervals via WP-Cron. It also uses the WP_Http class, which is also built into WordPress already." -msgstr "" - -#: includes/menu-pages.php:491 -msgid "The Auto-Cache Engine obtains its list of URLs to auto-cache, from two different sources. It can read an XML Sitemap 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." -msgstr "" - -#: includes/menu-pages.php:493 -msgid "No, leave the Auto-Cache Engine disabled please." -msgstr "" - -#: includes/menu-pages.php:494 -msgid "Yes, I want the Auto-Cache Engine to keep pages cached automatically." -msgstr "" - -#: includes/menu-pages.php:498 -msgid "XML Sitemap URL (or an XML Sitemap Index)" -msgstr "" - -#: includes/menu-pages.php:500 -msgid "In a Multisite Network, each child blog will be auto-cached too. %1$s will dynamically change the leading %2$s as necessary; for each child blog in the network. %1$s supports both sub-directory & sub-domain networks; including domain mapping plugins." -msgstr "" - -#: includes/menu-pages.php:501 -msgid "A List of URLs to Auto-Cache (One Per Line)" -msgstr "" - -#: includes/menu-pages.php:504 -msgid "Auto-Cache Delay Timer (in Milliseconds)" -msgstr "" - -#: includes/menu-pages.php:505 -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 500 milliseconds is suggested here (half a second). If you experience problems, you can bump this up a little at a time, in increments of 500 milliseconds; until you find a happy place for your server. Please note that 1000 milliseconds = 1 full second." -msgstr "" - -#: includes/menu-pages.php:508 -msgid "Auto-Cache User-Agent String" -msgstr "" - -#: includes/menu-pages.php:510 -msgid "This is how the Auto-Cache Engine identifies itself when connecting to URLs. See User Agent in the Wikipedia." -msgstr "" - -#: includes/menu-pages.php:523 -msgid "HTML Compression" -msgstr "" - -#: includes/menu-pages.php:528 -msgid "Enable WebSharks™ HTML Compression?" -msgstr "" - -#: includes/menu-pages.php:529 -msgid "This is an experimental feature, however it offers a potentially HUGE speed boost. You can learn more here. Please use with caution." -msgstr "" - -#: includes/menu-pages.php:531 -msgid "No, do NOT compress HTML/CSS/JS code at runtime." -msgstr "" - -#: includes/menu-pages.php:532 -msgid "Yes, I want to compress HTML/CSS/JS for blazing fast speeds." -msgstr "" - -#: includes/menu-pages.php:534 -msgid "Note: This is experimental. Please report issues here." -msgstr "" - -#: includes/menu-pages.php:537 -msgid "HTML Compression Options" -msgstr "" - -#: includes/menu-pages.php:538 -msgid "You can learn more about all of these options here." -msgstr "" - -#: includes/menu-pages.php:540 -msgid "Yes, combine CSS from <head> and <body> into fewer files." -msgstr "" - -#: includes/menu-pages.php:541 -msgid "No, do not combine CSS from <head> and <body> into fewer files." -msgstr "" - -#: includes/menu-pages.php:544 -msgid "Yes, compress the code in any unified CSS files." -msgstr "" - -#: includes/menu-pages.php:545 -msgid "No, do not compress the code in any unified CSS files." -msgstr "" - -#: includes/menu-pages.php:548 -msgid "Yes, combine JS from <head> into fewer files." -msgstr "" - -#: includes/menu-pages.php:549 -msgid "No, do not combine JS from <head> into fewer files." -msgstr "" - -#: includes/menu-pages.php:552 -msgid "Yes, combine JS footer scripts into fewer files." -msgstr "" - -#: includes/menu-pages.php:553 -msgid "No, do not combine JS footer scripts into fewer files." -msgstr "" - -#: includes/menu-pages.php:556 -msgid "Yes, combine CSS/JS from remote resources too." -msgstr "" - -#: includes/menu-pages.php:557 -msgid "No, do not combine CSS/JS from remote resources." -msgstr "" - -#: includes/menu-pages.php:560 -msgid "Yes, compress the code in any unified JS files." -msgstr "" - -#: includes/menu-pages.php:561 -msgid "No, do not compress the code in any unified JS files." -msgstr "" - -#: includes/menu-pages.php:564 -msgid "Yes, compress inline JavaScript snippets." -msgstr "" - -#: includes/menu-pages.php:565 -msgid "No, do not compress inline JavaScript snippets." -msgstr "" - -#: includes/menu-pages.php:568 -msgid "Yes, compress (remove extra whitespace) in the final HTML code too." -msgstr "" - -#: includes/menu-pages.php:569 -msgid "No, do not compress the final HTML code." -msgstr "" - -#: includes/menu-pages.php:572 -msgid "CSS Exclusion Patterns?" -msgstr "" - -#: includes/menu-pages.php:573 -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 <link href=""> value, and also against the contents of any inline <style> tags (caSe insensitive). A wildcard * character can also be used when necessary; e.g. xy*-framework; (where * = anything, 0 or more characters in length)." -msgstr "" - -#: includes/menu-pages.php:576 -msgid "JavaScript Exclusion Patterns?" -msgstr "" - -#: includes/menu-pages.php:577 -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 <script src=""> value, and also against the contents of any inline <script> tags (caSe insensitive). A wildcard * character can also be used when necessary; e.g. xy*-framework; (where * = anything, 0 or more characters in length)." -msgstr "" - -#: includes/menu-pages.php:581 -msgid "HTML Compression Cache Expiration" -msgstr "" - -#: includes/menu-pages.php:583 -msgid "Tip: the value that you specify here MUST be compatible with PHP's strtotime() function. Examples: 2 hours, 7 days, 6 months, 1 year." -msgstr "" - -#: includes/menu-pages.php:584 -msgid "Note: 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 filemtime() 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 learn more here. We recommend setting this value to at least double that of your overall %1$s expiration time." -msgstr "" - -#: includes/menu-pages.php:595 -msgid "GZIP Compression" -msgstr "" - -#: includes/menu-pages.php:600 -msgid "GZIP Compression (Optional; Highly Recommended)" -msgstr "" - -#: includes/menu-pages.php:601 -msgid "You don't have to use an .htaccess 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 .htaccess file to accomplish that part." -msgstr "" - -#: includes/menu-pages.php:602 -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 php.ini 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!" -msgstr "" - -#: includes/menu-pages.php:603 -msgid "If you want to enable GZIP, create an .htaccess file in your WordPress® installation directory, and put the following few lines in it. Alternatively, if you already have an .htaccess 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: video about GZIP Compression." -msgstr "" - -#: includes/menu-pages.php:618 -msgid "Static CDN Filters" -msgstr "" - -#: includes/menu-pages.php:623 -msgid "Enable Static CDN Filters (e.g. MaxCDN/CloudFront)?" -msgstr "" - -#: includes/menu-pages.php:624 -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 click here for a general set of instructions." -msgstr "" - -#: includes/menu-pages.php:625 -msgid "What's a CDN? 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." -msgstr "" - -#: includes/menu-pages.php:627 -msgid "No, I do NOT want CDN filters applied at runtime." -msgstr "" - -#: includes/menu-pages.php:628 -msgid "Yes, I want CDN filters applied w/ my configuration below." -msgstr "" - -#: includes/menu-pages.php:632 -msgid "CDN Host Name (Absolutely Required)" -msgstr "" - -#: includes/menu-pages.php:636 -msgid "This one 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. One you configure a CDN, you'll receive a host name (provided by your CDN), which you'll enter here; e.g. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN and/or Amazon CloudFront, but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a CloudFront tutorial video that walks you through the process." -msgstr "" - -#: includes/menu-pages.php:638 -msgid "CDN Host Supports HTTPS Connections?" -msgstr "" - -#: includes/menu-pages.php:640 -msgid "No, I don't serve content over https://; or I haven't configured my CDN w/ an SSL certificate." -msgstr "" - -#: includes/menu-pages.php:641 -msgid "Yes, I've configured my CDN w/ an SSL certificate; I need https:// enabled." -msgstr "" - -#: includes/menu-pages.php:644 -msgid "Everything else below is 100% completely optional; i.e. not required to enjoy the benefits of Static CDN Filters." -msgstr "" - -#: includes/menu-pages.php:646 -msgid "Whitelisted File Extensions (Optional; Comma-Delimited)" -msgstr "" - -#: includes/menu-pages.php:648 -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." -msgstr "" - -#: includes/menu-pages.php:649 -msgid "Blacklisted File Extensions (Optional; Comma-Delimited)" -msgstr "" - -#: includes/menu-pages.php:651 -msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain file extensions of your choosing. Please note, the php extension will never be considered a static resource; i.e. it is automatically blacklisted at all times." -msgstr "" - -#: includes/menu-pages.php:653 -msgid "Whitelisted URI Inclusion Patterns (Optional; One Per Line)" -msgstr "" - -#: includes/menu-pages.php:655 -msgid "Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one inclusion pattern per line." -msgstr "" - -#: includes/menu-pages.php:656 -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 * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/* here would indicate that you only want to filter URLs that lead to files located inside the wp-content directory. Adding an additional line with */wp-includes/* would filter URLs in the wp-includes directory also. If you leave this empty, ALL files matching a static file extension will be served from your CDN; i.e. the default behavior." -msgstr "" - -#: includes/menu-pages.php:657 -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 /. To clarify, a URI is the portion of the URL which comes after the host name. For instance, given the following URL: http://example.com/path/to/style.css?ver=3, the URI you are matching against would be: /path/to/style.css?ver=3. To whitelist this URI, you could use a line that contains something like this: /path/to/*.css*" -msgstr "" - -#: includes/menu-pages.php:658 -msgid "Blacklisted URI Exclusion Patterns (Optional; One Per Line)" -msgstr "" - -#: includes/menu-pages.php:660 -msgid "With or without a whitelist, you can force exclusions by explicitly blacklisting certain URI patterns. URI patterns are caSe-insensitive. A wildcard * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/*/dynamic.pdf* would exclude a file with the name dynamic.pdf located anywhere inside a sub-directory of wp-content." -msgstr "" - -#: includes/menu-pages.php:663 -msgid "Query String Invalidation Variable Name" -msgstr "" - -#: includes/menu-pages.php:665 -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. Please note, the default value is adequate for most sites. You can change this if you like, but it's not necessary." -msgstr "" - -#: includes/menu-pages.php:666 -msgid "Note: 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." -msgstr "" - -#: includes/menu-pages.php:679 -msgid "Dynamic Version Salt" -msgstr "" - -#: includes/menu-pages.php:684 -msgid " GEEK ALERT This is for VERY advanced users only..." -msgstr "" - -#: includes/menu-pages.php:685 -msgid "Note: Understanding the %1$s Branched Cache Structure is a prerequisite to understanding how Dynamic Version Salts are added to the mix." -msgstr "" - -#: includes/menu-pages.php:686 -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." -msgstr "" - -#: includes/menu-pages.php:687 -msgid "A Version Salt can be a single variable like $_COOKIE['my_cookie'], or it can be a combination of multiple variables, like $_COOKIE['my_cookie'].$_COOKIE['my_other_cookie']. (When using multiple variables, please separate them with a dot, as shown in the example.)" -msgstr "" - -#: includes/menu-pages.php:688 -msgid "Experts could even use PHP ternary expressions that evaluate into something. For example: ((preg_match('/iPhone/i', $_SERVER['HTTP_USER_AGENT'])) ? 'iPhones' : ''). This would force a separate version of the cache to be created for iPhones (e.g., /cache/PROTOCOL/HOST/REQUEST-URI.v/iPhones.html)." -msgstr "" - -#: includes/menu-pages.php:689 -msgid "For more documentation, please see Dynamic Version Salts." -msgstr "" - -#: includes/menu-pages.php:691 -msgid "Create a Dynamic Version Salt For %1$s?       150%% OPTIONAL" -msgstr "" - -#: includes/menu-pages.php:693 -msgid "Super Globals work here; $GLOBALS['table_prefix'] is a popular one. Or, perhaps a PHP Constant defined in /wp-config.php; such as WPLANG or DB_HOST." -msgstr "" - -#: includes/menu-pages.php:694 -msgid "Important: your Version Salt is scanned for PHP syntax errors via phpCodeChecker.com. If errors are found, you'll receive a notice in the Dashboard." -msgstr "" - -#: includes/menu-pages.php:695 -msgid "If you've enabled a separate cache for each user (optional) that's perfectly OK. A Version Salt works with user caching too." -msgstr "" - -#: includes/menu-pages.php:705 -msgid "Theme/Plugin Developers" -msgstr "" - -#: includes/menu-pages.php:710 -msgid "Developing a Theme or Plugin for WordPress?" -msgstr "" - -#: includes/menu-pages.php:711 -msgid "Tip: %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: $_SERVER['ZENCACHE_ALLOWED'] = FALSE; or define('ZENCACHE_ALLOWED', FALSE). %1$s is also compatible with: define('DONOTCACHEPAGE', TRUE). 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." -msgstr "" - -#: includes/menu-pages.php:713 -msgid "Writing \"Advanced Cache\" Plugins Specifically for %1$s" -msgstr "" - -#: includes/menu-pages.php:714 -msgid "Theme/plugin developers can take advantage of the %1$s plugin architecture by creating PHP files inside this special directory: /wp-content/ac-plugins/. There is an example plugin file @ GitHub (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." -msgstr "" - -#: includes/menu-pages.php:715 -msgid "Why does %1$s have it's own plugin architecture? WordPress loads the advanced-cache.php 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 add_action(), do_action(), add_filter(), apply_filters()." -msgstr "" - -#: includes/menu-pages.php:727 -msgid "Import/Export Options" -msgstr "" - -#: includes/menu-pages.php:732 -msgid "Import Options from Another %1$s Installation?" -msgstr "" - -#: includes/menu-pages.php:733 -msgid "Upload your %1$s-options.json file and click \"Save All Changes\" below. The options provided by your import file will override any that exist currently." -msgstr "" - -#: includes/menu-pages.php:736 -msgid "Export Existing Options from this %1$s Installation?" -msgstr "" - -#: includes/menu-pages.php:738 -msgid "%1$s-options.json" -msgstr "" - -#: includes/menu-pages.php:739 -msgid "Download your existing options and import them all into another %1$s installation; saves time on future installs." -msgstr "" - -#: includes/menu-pages.php:747 -msgid "Save All Changes" -msgstr "" - -#: includes/share.php:265 -msgid "Unable to determine cache directory location." -msgstr "" - -#: includes/share.php:1611 includes/share.php:1753 -msgid "The `options` property w/ a `cache_max_age` key is not defined in this class." -msgstr "" - -#: includes/share.php:1637 -msgid "Unable to delete files. Rename failure on directory: `%1$s`." -msgstr "" - -#: includes/share.php:1660 includes/share.php:1821 includes/share.php:1927 -msgid "Unable to delete symlink: `%1$s`." -msgstr "" - -#: includes/share.php:1672 includes/share.php:1833 includes/share.php:1935 -msgid "Unable to delete file: `%1$s`." -msgstr "" - -#: includes/share.php:1686 includes/share.php:1847 includes/share.php:1943 -msgid "Unable to delete dir: `%1$s`." -msgstr "" - -#: includes/share.php:1692 includes/share.php:1853 includes/share.php:1949 -msgid "Unexpected resource type: `%1$s`." -msgstr "" - -#: includes/share.php:1698 includes/share.php:1798 includes/share.php:1859 -msgid "Unable to delete files. Rename failure on tmp directory: `%1$s`." -msgstr "" - -#: includes/share.php:1913 includes/share.php:1955 -msgid "Unable to delete all files/dirs. Rename failure on tmp directory: `%1$s`." -msgstr "" - -#: includes/share.php:1960 -msgid "Unable to delete directory: `%1$s`." -msgstr "" - -#: includes/share.php:1995 -msgid "Unable to find the wp-config.php file." -msgstr "" - -#: includes/share.php:2011 -msgid "No writable tmp directory." -msgstr "" - -#: includes/share.php:2016 -msgid "Unable to obtain an exclusive lock." -msgstr "" - -#: includes/share.php:2069 -msgid "%1$s file" -msgid_plural "%1$s files" -msgstr[0] "" -msgstr[1] "" - -#: includes/share.php:2085 -msgid "%1$s directory" -msgid_plural "%1$s directories" -msgstr[0] "" -msgstr[1] "" - -#: includes/share.php:2101 -msgid "%1$s file/directory" -msgid_plural "%1$s files/directories" -msgstr[0] "" -msgstr[1] "" - -#: includes/share.php:2134 -msgid "Invalid hook." -msgstr "" - -#: includes/version-specific-upgrade.php:68 -msgid "%1$s: this version is a complete rewrite of Quick Cache :-) Please review your %1$s options carefully!" -msgstr "" - -#: includes/version-specific-upgrade.php:78 -msgid "%1$s Feature Notice: This version of %1$s adds new options for Feed caching. Feed caching is now disabled by default. If you wish to enable feed caching, please visit the %1$s options panel." -msgstr "" - -#: includes/version-specific-upgrade.php:117 -msgid "%1$s Feature Notice: This version of %1$s introduces a new Branched Cache Structure and several other new features." -msgstr "" - -#: includes/version-specific-upgrade.php:150 -msgid "%1$s Notice: This version of %1$s changes the default base directory that it uses, from ABSPATH to WP_CONTENT_DIR. This is for improved compatibility with installations that choose to use a custom WP_CONTENT_DIR location." -msgstr "" - -#: includes/version-specific-upgrade.php:151 -msgid "%1$s has detected that your previously configured cache directory may have been in conflict with this change. As a result, your %1$s configuration has been updated to the new default value; just to keep things running smoothly for you :-). If you would like to review this change, please see: Dashboard ⥱ %1$s ⥱ Directory & Expiration Time; where you may customize it further if necessary." -msgstr "" - -#: includes/version-specific-upgrade.php:240 -msgid "Woohoo! %1$s activated. :-)" -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:124 -msgid "extension" -msgid_plural "extensions" -msgstr[0] "" -msgstr[1] "" - -#: submodules/wp-php-rv/wp-php-rv.php:132 -msgid "%1$s is NOT active. It requires PHP v%2$s+." -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:133 -msgid "↳ You're currently running an older copy of PHP v%1$s." -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:136 -msgid "↳ You are also missing the following required PHP %1$s: %2$s." -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:138 -#: submodules/wp-php-rv/wp-php-rv.php:146 -msgid "A simple update is necessary. Please ask your hosting company to help resolve this quickly." -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:139 -msgid "To remove this message, please upgrade PHP. Or, remove %1$s from WordPress." -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:144 -msgid "%1$s is NOT active. PHP %2$s missing." -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:145 -msgid "↳ You are missing the following required PHP %1$s: %2$s." -msgstr "" - -#: submodules/wp-php-rv/wp-php-rv.php:147 -msgid "To remove this message, please install the required PHP %1$s. Or, remove %2$s from WordPress." -msgstr "" - -#: zencache.inc.php:382 -msgid "%1$s: detected a new version of itself. Recompiling w/ latest version... wiping the cache... all done :-)" -msgstr "" - -#: zencache.inc.php:578 -msgid "Settings" -msgstr "" - -#: zencache.inc.php:579 -msgid "Preview Pro Features" -msgstr "" - -#: zencache.inc.php:580 -msgid "Upgrade" -msgstr "" - -#: zencache.inc.php:676 zencache.inc.php:753 -msgid "dismiss ×" -msgstr "" - -#: zencache.inc.php:811 -msgid "Every 15 Minutes" -msgstr "" - -#: zencache.inc.php:938 -msgid "%1$s: detected significant changes. Found %2$s in the cache; auto-wiping." -msgstr "" - -#: zencache.inc.php:982 -msgid "%1$s: detected important site changes. Found %2$s in the cache for this site; auto-clearing." -msgstr "" - -#: zencache.inc.php:1063 -msgid "Post" -msgstr "" - -#: zencache.inc.php:1071 -msgid "%1$s: detected changes. Found %2$s in the cache for %3$s ID: %4$s; auto-clearing." -msgstr "" - -#: zencache.inc.php:1245 -msgid "%1$s: detected changes. Found %2$s in the cache, for XML feeds of type: %3$s; auto-clearing." -msgstr "" - -#: zencache.inc.php:1288 -msgid "%1$s: detected changes. Found %2$s in the cache for XML sitemaps; auto-clearing." -msgstr "" - -#: zencache.inc.php:1331 -msgid "%1$s: detected changes. Found %2$s in the cache for the designated \"Home Page\"; auto-clearing." -msgstr "" - -#: zencache.inc.php:1389 -msgid "%1$s: detected changes. Found %2$s in the cache for the designated \"Posts Page\"; auto-clearing." -msgstr "" - -#: zencache.inc.php:1444 -msgid "Untitled" -msgstr "" - -#: zencache.inc.php:1455 -msgid "%1$s: detected changes. Found %2$s in the cache for Custom Post Type: %3$s; auto-clearing." -msgstr "" - -#: zencache.inc.php:1545 -msgid "%1$s: detected changes. Found %2$s in the cache for Author Page: %3$s; auto-clearing." -msgstr "" - -#: zencache.inc.php:1697 -msgid "%1$s: detected changes. Found %2$s in the cache for %3$s: %4$s; auto-clearing." -msgstr "" - -#: zencache.inc.php:1986 zencache.inc.php:2014 -msgid "Doing it wrong! Missing `base_dir` option value. MUST call this method after `setup()`." -msgstr "" - -#: zencache.inc.php:2453 -msgid "Lite" -msgstr "" - -#: zencache.inc.php:2454 -msgid "Pro" -msgstr "" - -#: zencache.inc.php:2460 -msgid "%1$s is NOT running. A conflicting plugin, %2$s, is currently active. Please deactivate the %2$s plugin to clear this message." -msgstr "" - -#. Plugin Name of the plugin/theme -msgid "ZenCache" -msgstr "" - -#. Plugin URI of the plugin/theme -msgid "http://zencache.com/" -msgstr "" - -#. Description of the plugin/theme -msgid "ZenCache is an advanced WordPress caching plugin inspired by simplicity. Speed up your site (BIG time!) with a reliable and fast WordPress cache." -msgstr "" - -#. Author of the plugin/theme -msgid "WebSharks, Inc." -msgstr "" - -#. Author URI of the plugin/theme -msgid "http://www.websharks-inc.com/" -msgstr "" diff --git a/zencache/includes/utils-feed.php b/zencache/includes/utils-feed.php deleted file mode 100644 index 2eb40ce..0000000 --- a/zencache/includes/utils-feed.php +++ /dev/null @@ -1,306 +0,0 @@ - - * @license GNU General Public License, version 2 - */ -namespace zencache // Root namespace. -{ - if(!defined('WPINC')) // MUST have WordPress. - exit('Do NOT access this file directly: '.basename(__FILE__)); - - /** - * Feed Utilities - */ - class utils_feed - { - /** - * @var plugin ZenCache instance. - * - * @since 150218 Refactoring cache clear/purge routines. - */ - protected $plugin; - - /** - * @var string WordPress `home_url('/')`. - * - * @since 150218 Refactoring cache clear/purge routines. - */ - protected $home_url; - - /** - * @var string Default feed type; e.g. `rss2`. - * - * @since 150218 Refactoring cache clear/purge routines. - */ - protected $default_feed; - - /** - * @var boolean Using SEO-friendly permalinks? - * - * @since 150218 Refactoring cache clear/purge routines. - */ - protected $seo_friendly_permalinks; - - /** - * @var array All unique feed types. - * - * @since 150218 Refactoring cache clear/purge routines. - */ - protected $feed_types; - - /** - * Class constructor. - * - * @since 150218 Refactoring cache clear/purge routines. - */ - public function __construct() - { - $this->plugin = plugin(); - - $this->home_url = home_url('/'); - $this->default_feed = get_default_feed(); - $this->seo_friendly_permalinks = (boolean)get_option('permalink_structure'); - $this->feed_types = array_unique(array($this->default_feed, 'rdf', 'rss', 'rss2', 'atom')); - } - - /** - * Feed link variations. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param string $type_prefix A feed type prefix; optional. - * - * @return array An array of all feed link variations. - */ - public function feed_link_variations($type_prefix = '') - { - $variations = array(); // Initialize. - - foreach($this->feed_types as $_feed_type) - $variations[] = get_feed_link((string)$type_prefix.$_feed_type); - unset($_feed_type); // Housekeeping. - - return $variations; - } - - /** - * Post comments; feed link variations. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param \WP_Post A WordPress post class instance. - * - * @return array An array of all feed link variations. - */ - public function post_comments_feed_link_variations(\WP_Post $post) - { - $variations = array(); // Initialize. - - foreach($this->feed_types as $_feed_type) - $variations[] = get_post_comments_feed_link($post->ID, $_feed_type); - unset($_feed_type); // Housekeeping. - - return $variations; - } - - /** - * Post author; feed link variations. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param \WP_Post A WordPress post class instance. - * - * @return array An array of all feed link variations. - */ - public function post_author_feed_link_variations(\WP_Post $post) - { - $variations = array(); // Initialize. - - foreach($this->feed_types as $_feed_type) - $variations[] = get_author_feed_link($post->post_author, $_feed_type); - - if($this->seo_friendly_permalinks && ($post_author = get_userdata($post->post_author))) - foreach($this->feed_types as $_feed_type) - { - $variations[] = add_query_arg(urlencode_deep(array('author' => $post->post_author)), $this->home_url.'feed/'.urlencode($_feed_type).'/'); - $variations[] = add_query_arg(urlencode_deep(array('author' => $post_author->user_nicename)), $this->home_url.'feed/'.urlencode($_feed_type).'/'); - } - unset($_feed_type); // Housekeeping. - - return $variations; - } - - /** - * Post type archive; feed link variations. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param \WP_Post A WordPress post class instance. - * - * @return array An array of all feed link variations. - */ - public function post_type_archive_link_variations(\WP_Post $post) - { - $variations = array(); // Initialize. - - foreach($this->feed_types as $_feed_type) - $variations[] = get_post_type_archive_feed_link($post->post_type, $_feed_type); - unset($_feed_type); // Housekeeping. - - return $variations; - } - - /** - * Post terms; feed link variations. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param \WP_Post A WordPress post class instance. - * - * @param boolean $include_regex_wildcard_keys Defaults to a `FALSE` value. - * If `TRUE`, some associative array keys will be returned also. - * - * @return array An array of all feed link variations. - * - * @note If `$include_regex_wildcard_keys` is `TRUE`... - * This particular method may return some associative keys also. - * For string/associative keys, each key is `[feed type]::[regex]`, and the feed link/URL - * will contain a single `*` wildcard character where the `[regex]` pattern should go. - */ - public function post_term_feed_link_variations(\WP_Post $post, $include_regex_wildcard_keys = FALSE) - { - $variations = array(); // Initialize. - $post_terms = array(); // Initialize. - - if(!is_array($post_taxonomies = get_object_taxonomies($post, 'objects')) || !$post_taxonomies) - return $variations; // Nothing to do here; post has no terms. - - foreach($post_taxonomies as $_post_taxonomy) // Collect terms for each taxonomy. - if(is_array($_post_taxonomy_terms = wp_get_post_terms($post->ID, $_post_taxonomy->name)) && $_post_taxonomy_terms) - $post_terms = array_merge($post_terms, $_post_taxonomy_terms); - unset($_post_taxonomy, $_post_taxonomy_terms); // Housekeeping. - - foreach($post_terms as $_post_term) // Iterate all post terms. - { - foreach($this->feed_types as $_feed_type) - { - $_term_feed_link = get_term_feed_link($_post_term->term_id, $_post_term->taxonomy, $_feed_type); - $variations[] = $_term_feed_link; // Add this variation; always. - - if($include_regex_wildcard_keys && $_term_feed_link && strpos($_term_feed_link, '?') === FALSE) - { - // Quick example: `(?:123|slug)`; to consider both. - $_term_id_or_slug = '(?:'.preg_quote($_post_term->term_id, '/'). - '|'.preg_quote(preg_replace('/[^a-z0-9\/.]/i', '-', $_post_term->slug), '/').')'; - - // Quick example: `http://www.example.com/tax/term/feed`; - // with a wildcard this becomes: `http://www.example.com/tax/*/feed`. - $_term_feed_link_with_wildcard = preg_replace('/\/[^\/]+\/feed([\/?#]|$)/', '/*/feed'.'${1}', $_term_feed_link); - - // Quick example: `http://www.example.com/tax/*/feed`; - // becomes: `\/http\/www\.example\.com\/tax\/.*?(?=[\/\-]?(?:123|slug)[\/\-]).*?\/feed` - // ... this covers variations that use: `/tax/term,term/feed/`. - // ... also covers variations that use: `/tax/term/tax/term/feed/`. - $variations[$_feed_type.'::.*?(?=[\/\-]?'.$_term_id_or_slug.'[\/\-]).*?'] = $_term_feed_link_with_wildcard; - // NOTE: This may also pick up false-positives. Not much we can do about this. - // For instance, if another feed has the same word/slug in what is actually a longer/different term. - // Or, if another feed has the same word/slug in what is actually the name of a taxonomy. - } - } - unset($_feed_type, $_term_feed_link, $_term_id_or_slug, $_term_feed_link_with_wildcard); // Housekeeping. - - if($this->seo_friendly_permalinks && is_object($_taxonomy = get_taxonomy($_post_term->taxonomy))) - { - if($_taxonomy->name === 'category') - $_taxonomy_query_var = 'cat'; // Special case. - else $_taxonomy_query_var = $_taxonomy->query_var; - - foreach($this->feed_types as $_feed_type) - $variations[] = add_query_arg(urlencode_deep(array($_taxonomy_query_var => $_post_term->term_id)), $this->home_url.'feed/'.urlencode($_feed_type).'/'); - unset($_feed_type); // Housekeeping. - - foreach($this->feed_types as $_feed_type) - $variations[] = add_query_arg(urlencode_deep(array($_taxonomy_query_var => $_post_term->slug)), $this->home_url.'feed/'.urlencode($_feed_type).'/'); - unset($_feed_type); // Housekeeping. - } - unset($_taxonomy, $_taxonomy_query_var); // Housekeeping. - } - unset($_post_term); // Housekeeping. - - return $variations; - } - - /** - * Convert variations into regex fragments; relative to the current host|blog directory. - * - * @since 150218 Refactoring cache clear/purge routines. - * - * @param array $variations An array of variations built by other class members. - * - * @return array An array of all feed link variations; converted to regex fragments. - * Regex fragments are relative to the current host|blog directory. - * - * @note This automatically forces the following {@link build_cache_path()} flags. - * - * - {@link CACHE_PATH_NO_SCHEME} - * - {@link CACHE_PATH_NO_HOST} - * - {@link CACHE_PATH_NO_USER} - * - {@link CACHE_PATH_NO_VSALT} - * - {@link CACHE_PATH_NO_EXT} - * - {@link CACHE_PATH_ALLOW_WILDCARDS}; when applicable. - */ - public function convert_variations_to_host_cache_path_regex_frags(array $variations) - { - $plugin = $this->plugin; // For proper syntax. - $regex_frags = array(); // Initialize regex variation frags. - - $flags = $plugin::CACHE_PATH_NO_SCHEME | $plugin::CACHE_PATH_NO_HOST - | $plugin::CACHE_PATH_NO_USER | $plugin::CACHE_PATH_NO_VSALT - | $plugin::CACHE_PATH_NO_EXT; - - $host = $_SERVER['HTTP_HOST']; - $host_base_dir_tokens = $this->plugin->host_base_dir_tokens(); - $host_url = rtrim('http://'.$host.$host_base_dir_tokens, '/'); - $host_cache_path_flags = $flags | $plugin::CACHE_PATH_NO_QUV; // Add one more flag here. - $host_cache_path = $this->plugin->build_cache_path($host_url, '', '', $host_cache_path_flags); - - foreach($variations as $_key => $_variation) - { - if(!$_variation || !is_string($_variation)) - continue; // Invalid variation. - - if(is_string($_key) && strpos($_key, '::') !== FALSE && strpos($_variation, '*') !== FALSE) - { - $_flags = $flags | $plugin::CACHE_PATH_ALLOW_WILDCARDS; - list($_feed_type, $_wildcard_regex) = explode('::', $_key, 2); - - $_cache_path = $this->plugin->build_cache_path($_variation, '', '', $_flags); - $_relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $_cache_path); - $_relative_cache_path_regex = preg_replace('/\\\\\*/', $_wildcard_regex, preg_quote($_relative_cache_path, '/')); - - $regex_frags[] = $_relative_cache_path_regex; // Add variation now. - - unset($_flags, $_feed_type, $_wildcard_regex);// Housekeeping. - unset($_cache_path, $_relative_cache_path, $_relative_cache_path_regex); - } - else // This is just a regular variation; i.e. a URL without any regex/wildcard to parse. - { - $_cache_path = $this->plugin->build_cache_path($_variation, '', '', $flags); - $_relative_cache_path = preg_replace('/^'.preg_quote($host_cache_path, '/').'(?:\/|$)/i', '', $_cache_path); - $_relative_cache_path_regex = preg_quote($_relative_cache_path, '/'); - - $regex_frags[] = $_relative_cache_path_regex; // Add variation now. - - unset($_cache_path, $_relative_cache_path, $_relative_cache_path_regex); - } - } - unset($_key, $_variation); // Housekeeping. - - return $regex_frags; - } - } -} \ No newline at end of file diff --git a/zencache/includes/version-specific-upgrade.php b/zencache/includes/version-specific-upgrade.php deleted file mode 100644 index 29f00fe..0000000 --- a/zencache/includes/version-specific-upgrade.php +++ /dev/null @@ -1,248 +0,0 @@ -plugin = plugin(); - $this->prev_version = (string)$prev_version; - $this->run_handlers(); // Run upgrade(s). - } - - /** - * Runs upgrade handlers in the proper order. - */ - public function run_handlers() - { - $this->from_lt_v110523(); - $this->from_lt_v140104(); - $this->from_lt_v140605(); - $this->from_lt_v140612(); - $this->from_lt_v141009(); - $this->from_quick_cache(); - } - - /* - * Upgrading from a version prior to our rewrite. - */ - public function from_lt_v110523() - { - if(version_compare($this->prev_version, '110523', '<')) - { - delete_option('ws_plugin__qcache_options'); // Ditch these. - delete_option('ws_plugin__qcache_notices'); // Ditch these. - delete_option('ws_plugin__qcache_configured'); // Ditch this too. - - wp_clear_scheduled_hook('ws_plugin__qcache_garbage_collector__schedule'); // Ditch old CRON job. - wp_clear_scheduled_hook('ws_plugin__qcache_auto_cache_engine__schedule'); // Ditch old CRON job. - - $this->plugin->enqueue_notice(sprintf(__('%1$s: this version is a complete rewrite of Quick Cache :-) Please review your %1$s options carefully!', $this->plugin->text_domain), esc_html($this->plugin->name))); - } - } - - /* - * Upgrading from a version prior to v140104 where we introduced feed caching. - */ - public function from_lt_v140104() - { - if(version_compare($this->prev_version, '140104', '<')) // When this sort of update occurs, we issue a notice about this new feature. - $this->plugin->enqueue_notice(sprintf(__('%1$s Feature Notice: This version of %1$s adds new options for Feed caching. Feed caching is now disabled by default. If you wish to enable feed caching, please visit the %1$s options panel.', $this->plugin->text_domain), esc_html($this->plugin->name))); - } - - /* - * Upgrading from a version prior to v140605, where we introduced a branched cache structure. - * See - * We also also moved to a base directory layout. - */ - public function from_lt_v140605() - { - if(version_compare($this->prev_version, '140605', '<')) - { - if((is_multisite() && is_array($existing_options = get_site_option(__NAMESPACE__.'_options'))) - || is_array($existing_options = get_option(__NAMESPACE__.'_options')) - - || (is_multisite() && is_array($existing_options = get_site_option('quick_cache_options'))) - || is_array($existing_options = get_option('quick_cache_options')) - - ) // Upgrading from a version before we introduced a branched cache structure? - { - if(!empty($existing_options['cache_dir'])) - { - $wp_content_dir_relative = // We considered custom locations. - trim(str_replace(ABSPATH, '', WP_CONTENT_DIR), '\\/'." \t\n\r\0\x0B"); - - $this->plugin->options['base_dir'] = $existing_options['cache_dir'] = trim($existing_options['cache_dir'], '\\/'." \t\n\r\0\x0B"); - - if(!$this->plugin->options['base_dir'] || $this->plugin->options['base_dir'] === $wp_content_dir_relative.'/cache') - $this->plugin->options['base_dir'] = $this->plugin->default_options['base_dir']; - - if($existing_options['cache_dir']) // Wipe old files? - $this->plugin->wipe_cache(FALSE, ABSPATH.$existing_options['cache_dir']); - unset($this->plugin->options['cache_dir']); // Just to be sure. - - update_option(__NAMESPACE__.'_options', $this->plugin->options); - if(is_multisite()) update_site_option(__NAMESPACE__.'_options', $this->plugin->options); - - $this->plugin->activate(); // Reactivate plugin w/ new options. - } - $this->plugin->enqueue_notice(sprintf(__('%1$s Feature Notice: This version of %1$s introduces a new Branched Cache Structure and several other new features.', $this->plugin->text_domain), esc_html($this->plugin->name))); - } - } - } - - /** - * Upgrading from a version before we changed base directory from `ABSPATH` to `WP_CONTENT_DIR`. - * If so, we need to reset the cache location on sites - * that have `wp-content` in their base directory. - */ - public function from_lt_v140612() - { - if(version_compare($this->prev_version, '140612', '<')) - { - if((is_multisite() && is_array($existing_options = get_site_option(__NAMESPACE__.'_options'))) - || is_array($existing_options = get_option(__NAMESPACE__.'_options')) - - || (is_multisite() && is_array($existing_options = get_site_option('quick_cache_options'))) - || is_array($existing_options = get_option('quick_cache_options')) - - ) // Upgrading from a version before we changed base directory from `ABSPATH` to `WP_CONTENT_DIR`? - { - if(!empty($existing_options['base_dir']) && stripos($existing_options['base_dir'], basename(WP_CONTENT_DIR)) !== FALSE) - { - $this->plugin->wipe_cache(FALSE, ABSPATH.$existing_options['base_dir']); - $this->plugin->options['base_dir'] = $this->plugin->default_options['base_dir']; - - update_option(__NAMESPACE__.'_options', $this->plugin->options); - if(is_multisite()) update_site_option(__NAMESPACE__.'_options', $this->plugin->options); - - $this->plugin->activate(); // Reactivate plugin w/ new options. - - $this->plugin->enqueue_notice( // Give site owners a quick heads up about this. - '

'.sprintf(__('%1$s Notice: This version of %1$s changes the default base directory that it uses, from ABSPATH to WP_CONTENT_DIR. This is for improved compatibility with installations that choose to use a custom WP_CONTENT_DIR location.', $this->plugin->text_domain), esc_html($this->plugin->name)). - ' '.sprintf(__('%1$s has detected that your previously configured cache directory may have been in conflict with this change. As a result, your %1$s configuration has been updated to the new default value; just to keep things running smoothly for you :-). If you would like to review this change, please see: Dashboard ⥱ %1$s ⥱ Directory & Expiration Time; where you may customize it further if necessary.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

' - ); - } - } - } - } - - /** - * Upgrading from a version before we changed several `cache_purge_*` options to `cache_clear_*`. - * If so, we need to use the existing options to fill the new keys. - * And, of course, then we save the updated options. - */ - public function from_lt_v141009() - { - if(version_compare($this->prev_version, '141009', '<')) - { - if((is_multisite() && is_array($existing_options = get_site_option(__NAMESPACE__.'_options'))) - || is_array($existing_options = get_option(__NAMESPACE__.'_options')) - - || (is_multisite() && is_array($existing_options = get_site_option('quick_cache_options'))) - || is_array($existing_options = get_option('quick_cache_options')) - - ) // Update old purge keys; which now use `clear` instead of `purge`. - { - foreach(array('cache_purge_home_page_enable', - 'cache_purge_posts_page_enable', - 'cache_purge_author_page_enable', - 'cache_purge_term_category_enable', - 'cache_purge_term_post_tag_enable', - 'cache_purge_term_other_enable', - ) as $_old_purge_option) - if(isset($existing_options[$_old_purge_option][0])) - { - $found_old_purge_options = TRUE; - $this->plugin->options[str_replace('purge', 'clear', $_old_purge_option)] = $existing_options[$_old_purge_option][0]; - } - unset($_old_purge_option); // Housekeeping. - - if(!empty($found_old_purge_options)) - { - update_option(__NAMESPACE__.'_options', $this->plugin->options); - if(is_multisite()) update_site_option(__NAMESPACE__.'_options', $this->plugin->options); - } - } - } - } - - /** - * Upgrading from a version before we changed the name to ZenCache. - */ - public function from_quick_cache() - { - if((is_multisite() && is_array($quick_cache_options = get_site_option('quick_cache_options'))) - || is_array($quick_cache_options = get_option('quick_cache_options')) - - ) // Automatically uninstall Quick Cache; for the most part anyway. - { - delete_option('quick_cache_options'); - if(is_multisite()) // Delete network options too. - delete_site_option('quick_cache_options'); - - delete_option('quick_cache_notices'); - delete_option('quick_cache_errors'); - - wp_clear_scheduled_hook('_cron_quick_cache_auto_cache'); - wp_clear_scheduled_hook('_cron_quick_cache_cleanup'); - - deactivate_plugins(array('quick-cache/quick-cache.php', 'quick-cache-pro/quick-cache-pro.php'), TRUE); - - // Use the new base dir for ZenCache; remove the old base dir for Quick Cache. - - if(!empty($quick_cache_options['base_dir'])) - $this->plugin->delete_all_files_dirs_in(WP_CONTENT_DIR.'/'.trim($quick_cache_options['base_dir'], '/'), TRUE); - $this->plugin->remove_base_dir(); // Let's be extra sure that the old base directory is gone. - - $this->plugin->options['base_dir'] = $this->plugin->default_options['base_dir']; - - // Reset CRONs. We need CRONs to be set up again for ZenCache. - - $this->plugin->options['crons_setup'] = $this->plugin->default_options['crons_setup']; - - // Save revised options; reactive the plugin with the new options. - - update_option(__NAMESPACE__.'_options', $this->plugin->options); - if(is_multisite()) update_site_option(__NAMESPACE__.'_options', $this->plugin->options); - - $this->plugin->activate(); // Reactivate plugin w/ new options. - - $this->plugin->enqueue_notice( // Give site owners a quick heads up about this. - '

'.sprintf(__('Woohoo! %1$s activated. :-)', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'. - '

'.sprintf(__('NOTE: Your Quick Cache options were preserved by %1$s (for more details, visit the Migration FAQ).'.'', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'. - '

'.sprintf(__('To review your configuration, please see: %1$s ⥱ Plugin Options.'.'', $this->plugin->text_domain), esc_html($this->plugin->name), esc_attr(add_query_arg(urlencode_deep(array('page' => __NAMESPACE__)), self_admin_url('/admin.php')))).'

' - ); - } - } - } - } -} \ No newline at end of file diff --git a/zencache/licensing/.htaccess b/zencache/licensing/.htaccess deleted file mode 100644 index 910246c..0000000 --- a/zencache/licensing/.htaccess +++ /dev/null @@ -1,6 +0,0 @@ - - Require all denied - - - deny from all - \ No newline at end of file diff --git a/zencache/licensing/gpl.txt b/zencache/licensing/gpl.txt deleted file mode 100644 index 7e14f38..0000000 --- a/zencache/licensing/gpl.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. \ No newline at end of file diff --git a/zencache/licensing/license.txt b/zencache/licensing/license.txt deleted file mode 100644 index f73f1ee..0000000 --- a/zencache/licensing/license.txt +++ /dev/null @@ -1,18 +0,0 @@ -Copyright: © 2013 [WebSharks, Inc.](http://www.websharks-inc.com/bizdev/) (coded in the USA) - -Released under the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl-2.0.html). - -= Credits / Additional Acknowledgments = - -* Software designed for WordPress®. - - GPL License - - WordPress® -* Some JavaScript extensions require jQuery. - - GPL-Compatible License - - jQuery -* CSS framework and some JavaScript functionality provided by Bootstrap. - - GPL-Compatible License - - Bootstrap -* Icons provided by Font Awesome. - - GPL-Compatible License - - Font Awesome \ No newline at end of file diff --git a/zencache/readme.txt b/zencache/readme.txt deleted file mode 100644 index dfdb214..0000000 --- a/zencache/readme.txt +++ /dev/null @@ -1,422 +0,0 @@ -=== ZenCache === - -Stable tag: 150409 -Requires at least: 3.7 -Tested up to: 4.2 -Text Domain: zencache - -License: GPLv2 or later -License URI: http://www.gnu.org/licenses/gpl-2.0.html - -Contributors: WebSharks, JasWSInc, raamdev -Donate link: http://www.websharks-inc.com/r/wp-theme-plugin-donation/ -Tags: cache, quick cache, zencache, zen cache, quickcache, speed, performance, fast, loading, generation, execution, benchmark, benchmarking, debug, debugging, caching, cash, caching, cacheing, super cache, advanced cache, advanced-cache, wp-cache, wp cache, rocket, static, client-side cache, rss cache, feed cache, gzip compression, query string, get request, page cache, options panel included, w3c validated code, highly extensible - -ZenCache is an advanced WordPress caching plugin inspired by simplicity. Speed up your site (BIG time!) with a reliable and fast WordPress cache. - -== Description == - -If you care about the speed of your site, ZenCache is one of those plugins that you absolutely MUST have installed :-) ZenCache takes a real-time snapshot (building a cache) of every Page, Post, Category, Link, etc. These snapshots are then stored (cached) intuitively, so they can be referenced later, in order to save all of that processing time that has been dragging your site down and costing you money. - -The ZenCache plugin uses configuration options that you select from the options panel. See: **ZenCache -› Options** in your Dashboard. Once a file has been cached, ZenCache uses advanced techniques that allow it to recognize when it should and should not serve a cached version of the file. By default, ZenCache does not serve cached pages to users who are logged in, or to users who have left comments recently. ZenCache also excludes administrative pages, login pages, POST/PUT/DELETE/GET(w/ query string) requests and/or CLI processes. - -= Features = - -- SIMPLE and well-documented configuration (just enable and you're all set!). -- The ability to set an automatic expiration time for cache files. -- Client-Side Caching (to allow double-caching in the client-side browser). -- Caching for 404 requests to reduce the impact of those requests on the server. -- RSS, RDF, and Atom Feed caching. -- The ability to cache or ignore URLs that contain query strings (GET Requests). -- An Advanced Cache Plugin system for theme and plugin developers. - -= Pro Features = - -- The ability to cache logged-in users too! (VERY powerful, particularly for membership sites). -- A new improved "Clear Cache" button in the admin bar (along with an option to enable/disable this feature). -- The ability to disable Dashboard notifications related to automatic clearing/purging on change detections. -- The ability to clear Markdown-related cache files generated by the s2Clean theme for WordPress (if installed). -- Import/Export functionality for ZenCache configuration files. -- URI exclusion patterns (now supporting wildcards too). -- User-Agent exclusion patterns (now supporting wildcards too). -- HTTP referrer exclusion patterns (now supporting wildcards too). -- A Dynamic Version Salt (customize the caching engine). -- HTML Compressor to automatically combine and compresses CSS/JS/HTML code. -- Auto-Cache Engine to pre-cache your site at 15-minute intervals. -- Static CDN Filters to serve some and/or ALL static files on your site from a CDN of your choosing. -- An Automatic Updater to update ZenCache Pro from your WordPress Dashboard. -- Rockstar support for all ZenCache features. - -TIP: you can preview Pro features in the free version by clicking the "Preview Pro Features" link at the top of your ZenCache options. - -== Screenshots == - -1. ZenCache Screenshot #1 -2. ZenCache Screenshot #2 -3. ZenCache Screenshot #3 -4. ZenCache Screenshot #4 -5. ZenCache Screenshot #5 -6. ZenCache Screenshot #6 -7. ZenCache Screenshot #7 -8. ZenCache Screenshot #8 -9. ZenCache Screenshot #9 -10. ZenCache Screenshot #10 - -== Installation == - -**Quick Tip:** WordPress® can only deal with one cache plugin being activated at a time. Please uninstall any existing cache plugins that you've tried in the past. In other words, if you've installed W3 Total Cache, WP Super Cache, DB Cache Reloaded, or any other caching plugin, uninstall them all before installing ZenCache. One way to check, is to make sure this file: `wp-content/advanced-cache.php` and/or `wp-content/object-cache.php` are NOT present; and if they are, delete these files BEFORE installing ZenCache. Those files will only be present if you have a caching plugin already installed. If you don't see them, you're ready to install ZenCache :-). - -**A note for existing Quick Cache users:** ZenCache is the successor to Quick Cache and will automatically detect any existing Quick Cache options and migrate that options over to ZenCache. For further details, please see the [migration FAQ](http://zencache.com/kb-article/how-to-migrate-from-quick-cache-lite-to-zencache-lite/). - -= ZenCache is Very Easy to Install = - -1. Upload the `/zencache` folder to your `/wp-content/plugins/` directory. -2. Activate the plugin through the Plugins menu in WordPress®. -3. Navigate to the **ZenCache** panel & enable it. - -= How will I know ZenCache is Working? = - -First of all, make sure that you've enabled ZenCache. After you activate the plugin in WordPress, go to the ZenCache options panel and enable caching (you can't miss the big yellow checkbox). Then scroll to the bottom and click Save All Changes. All of the other options on that page are already pre-configured for typical usage. Skip them all for now. You can go back through all of these later and fine-tune things the way you like them. - -Once ZenCache has been enabled, **you'll need to log out** (and/or clear browser cookies). Cache files are NOT served to visitors who are logged in, and that includes you too :-) Cache files are NOT served to recent commenters either. If you've commented (or replied to a comment lately); please clear your browser cookies before testing. - -**To verify that ZenCache is working**, 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 ZenCache stats and information. You should also notice that page-to-page navigation is lightning fast compared to what you experienced prior to installing ZenCache. - -= Running ZenCache On A WordPress® Multisite Installation = - -WordPress® Multisite Networking is a special consideration in WordPress®. If ZenCache is installed under a Multisite Network installation, it will be enabled for ALL blogs the same way. The centralized config options for ZenCache, can only be modified by a Super Administrator operating on the main site. ZenCache has internal processing routines that prevent configuration changes, including menu displays; for anyone other than a Super Administrator operating on the main site. - -= EMERGENCY: If All Else Fails (How-To Remove ZenCache) = - -Ordinarily you can just deactivate ZenCache from the plugins menu in WordPress. However, if you're having a more serious issue, please follow the instructions here. - -1. Log into your site via FTP; perhaps using [FileZilla](http://www.youtube.com/watch?v=joXUMhr8PhU). -2. Delete this file: `/wp-content/advanced-cache.php` -3. Delete this directory: `/wp-content/plugins/zencache/` -4. Remove this line from your `/wp-config.php` file: `define('WP_CACHE', TRUE);` - -ZenCache is now completely uninstalled and you can start fresh :-) - -== Frequently Asked Questions == - -= I already have Quick Cache installed; how do I install ZenCache? = - -ZenCache is the successor to Quick Cache and will automatically detect any existing Quick Cache options and migrate those options over to ZenCache. For further details, please see the [migration FAQ](http://zencache.com/kb-article/how-to-migrate-from-quick-cache-lite-to-zencache-lite/). - -= How do I know that ZenCache is working the way it should be? = - -First of all, make sure that you've enabled ZenCache. After you activate the plugin, go to the ZenCache options panel and enable it, then scroll to the bottom and click Save All Changes. All of the other options on that page are already pre-configured for typical usage. Skip them all for now. You can go back through all of them later and fine-tune things the way you like them. - -Once ZenCache has been enabled, **you'll need to log out** (and/or clear browser cookies). Cache files are NOT served to visitors who are logged in, and that includes you too :-) Cache files are NOT served to recent commenters either. If you've commented (or replied to a comment lately); please clear your browser cookies before testing. - -**To verify that ZenCache is working**, 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 ZenCache stats and information. You should also notice that page-to-page navigation is lightning fast compared to what you experienced prior to installing ZenCache. - -= What is the down side to running ZenCache? = - -There is NOT one! ZenCache is a MUST HAVE for every WordPress® powered site. In fact, we really can't think of any site running WordPress® that would want to be without it. To put it another way, the WordPress® software itself comes with a built in action reference for an `advanced-cache.php` file, because WordPress® developers realize the importance of such as plugin. The `/wp-content/advanced-cache.php` file is named as such, because the WordPress® developers expect it to be there when caching is enabled by a plugin. If you don't have the `/wp-content/advanced-cache.php` file yet, it is because you have not enabled ZenCache from the options panel yet. - -= So why does WordPress® need to be cached? = - -To understand how ZenCache works, first you have to understand what a cached file is, and why it is absolutely necessary for your site and every visitor that comes to it. WordPress® (by its very definition) is a database-driven publishing platform. That means you have all these great tools on the back-end of your site to work with, but it also means that every time a Post/Page/Category is accessed on your site, dozens of connections to the database have to be made, and literally thousands of PHP routines run in harmony behind-the-scenes to make everything jive. The problem is, for every request that a browser sends to your site, all of these routines and connections have to be made (yes, every single time). Geesh, what a waste of processing power, memory, and other system resources. After all, most of the content on your site remains the same for at least a few minutes at a time. If you've been using WordPress® for very long, you've probably noticed that (on average) your site does not load up as fast as other sites on the web. Now you know why! - -In computer science, a cache (pronounced /kash/) is a collection of data duplicating original values stored elsewhere or computed earlier, where the original data is expensive to fetch (owing to longer access time) or to compute, compared to the cost of reading the cache. In other words, a cache is a temporary storage area where frequently accessed data can be stored for rapid access. Once the data is stored in the cache, it can be used in the future by accessing the cached copy rather than re-fetching or recomputing the original data. - -= Where & why are the cache files stored on my server? = - -The cache files are stored in a special directory: `/wp-content/cache/zencache`. This directory needs to remain writable, just like the `/wp-content/uploads` directory on many WordPress® installations. The `/zencache/cache` directory is where cache files reside. These files are stored using an intutive directory structure that named based on the request URL (`HTTPS/HTTP_HOST/REQUEST_URI`). See also: **Dashboard -› ZenCache -› Cache Directory/Expiration Time** for further details. - -Whenever a request comes in from someone on the web, ZenCache checks to see if it can serve a cached file; e.g. it looks at the `HTTPS/HTTP_HOST/REQUEST_URI` environent variables, then it checks the `/zencache/cache` directory. If a cache file has been built already, and it matches an existing `HTTPS.HTTP_HOST.REQUEST_URI` combination; and it is not too old (see: **Dashboard -› ZenCache -› Cache Directory/Expiration Time**), then it will serve that file instead of asking WordPress® to regenerate it. This adds tremendous speed to your site and reduces server load. - -If you have GZIP compression enabled, then the cache file is also sent to the browser with compression (recommended). Modern web browsers that support this technique will definitely take advantage of it. After all, if it is easier to email a zip file, it's also easier to download a web page that way. That is why on-the-fly GZIP compression for web pages is recommended. This is supported by all modern browsers. - -If you want to enable GZIP, create an `.htaccess` file in your WordPress® installation directory and put the following few lines in it. Alternatively, if you already have an `.htaccess` file, just add these lines to it, and that is all there is to it. GZIP is now enabled! - - - - AddOutputFilterByType DEFLATE text/plain text/html - AddOutputFilterByType DEFLATE text/xml application/xml application/xhtml+xml application/xml-dtd - AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml image/svg+xml - AddOutputFilterByType DEFLATE text/css text/javascript application/javascript application/x-javascript - AddOutputFilterByType DEFLATE font/otf font/opentype application/font-otf application/x-font-otf - AddOutputFilterByType DEFLATE font/ttf font/truetype application/font-ttf application/x-font-ttf - - - -If your installation of Apache does not have `mod_deflate` installed. You can also enable GZIP compression using PHP configuration alone. In your `php.ini` file, you can simply add the following line anywhere: `zlib.output_compression = on` - -= What happens if a user logs in? Are cache files used then? = - -By default, ZenCache does NOT serve cached pages to users who are logged in, or to users who have left comments recently. ZenCache also excludes administrative pages, login pages, POST/PUT/DELETE/GET(w/ query string) requests and/or CLI processes. That being said, the Pro version of ZenCache DOES make it possible to cache pages even when users ARE logged-in; adding even more speed! This is particularly helpful on membership sites; e.g. sites that run plugins like s2Member™ for instance. - -= Will comments and other dynamic parts of my blog update immediately? = - -It depends on your configuration of ZenCache. There is an automatic expiration system (the garbage collector), which runs through WordPress® behind-the-scene, according to your Expiration setting (see: **Dashboard -› ZenCache -› Cache Directory/Expiration Time**). There is also a built-in expiration time on existing files that is checked before any cache file is served up, which also uses your Expiration setting. In addition; whenever you update a Post or a Page, ZenCache can automatically prune that particular file from the cache so it instantly becomes fresh again. Otherwise, your visitors would need to wait for the previous cached version to expire. - -By default, ZenCache does NOT serve cached pages to users who are logged in, or to users who have left comments recently. ZenCache also excludes administrative pages, login pages, POST/PUT/DELETE/GET(w/ query string) requests and/or CLI processes. - -= How do I enable GZIP compression? Is GZIP supported? = - -There is no need to use an `.htaccess` file with this plugin; caching is handled by WordPress®/PHP alone. That being said, if you also want to take advantage of GZIP compression (and we do recommend this), then you WILL need an `.htaccess` file to accomplish that part. This plugin 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 `php.ini` 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! - -If you want to enable GZIP, create an `.htaccess` file in your WordPress® installation directory and put the following few lines in it. Alternatively, if you already have an `.htaccess` file, just add these lines to it, and that is all there is to it. GZIP is now enabled! - - - - AddOutputFilterByType DEFLATE text/plain text/html - AddOutputFilterByType DEFLATE text/xml application/xml application/xhtml+xml application/xml-dtd - AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml image/svg+xml - AddOutputFilterByType DEFLATE text/css text/javascript application/javascript application/x-javascript - AddOutputFilterByType DEFLATE font/otf font/opentype application/font-otf application/x-font-otf - AddOutputFilterByType DEFLATE font/ttf font/truetype application/font-ttf application/x-font-ttf - - - -If your installation of Apache does not have `mod_deflate` installed. You can also enable gzip compression using PHP configuration alone. In your `php.ini` file, you can simply add the following line anywhere: `zlib.output_compression = on` - -= I'm a plugin developer. How can I prevent certain files from being cached? = - - - - AddOutputFilterByType DEFLATE text/plain text/html - AddOutputFilterByType DEFLATE text/xml application/xml application/xhtml+xml application/xml-dtd - AddOutputFilterByType DEFLATE application/rdf+xml application/rss+xml application/atom+xml image/svg+xml - AddOutputFilterByType DEFLATE text/css text/javascript application/javascript application/x-javascript - AddOutputFilterByType DEFLATE font/otf font/opentype application/font-otf application/x-font-otf - AddOutputFilterByType DEFLATE font/ttf font/truetype application/font-ttf application/x-font-ttf - - - -If your installation of Apache does not have `mod_deflate` installed. You can also enable GZIP compression using PHP configuration alone. In your `php.ini` file, you can simply add the following line anywhere: `zlib.output_compression = on` - -= EMERGENCY: If All Else Fails (How-To Remove ZenCache) = - -Ordinarily you can just deactivate ZenCache from the plugins menu in WordPress. However, if you're having a more serious issue, please follow the instructions here. - -1. Log into your site via FTP; perhaps using [FileZilla](http://www.youtube.com/watch?v=joXUMhr8PhU). -2. Delete this file: `/wp-content/advanced-cache.php` -3. Delete this directory: `/wp-content/plugins/zencache/` -4. Remove this line from your `/wp-config.php` file: `define('WP_CACHE', TRUE);` - -ZenCache is now completely uninstalled and you can start fresh :-) - -== Pro Features == - -= ZenCache Pro Features = - -- The ability to cache logged-in users too! (VERY powerful, particularly for membership sites). -- A new improved "Clear Cache" button in the admin bar (along with an option to enable/disable this feature). -- The ability to disable Dashboard notifications related to automatic clearing/purging on change detections. -- The ability to clear Markdown-related cache files generated by the s2Clean theme for WordPress (if installed). -- Import/Export functionality for ZenCache configuration files. -- URI exclusion patterns (now supporting wildcards too). -- User-Agent exclusion patterns (now supporting wildcards too). -- HTTP referrer exclusion patterns (now supporting wildcards too). -- A Dynamic Version Salt (customize the caching engine). -- HTML Compressor to automatically combine and compresses CSS/JS/HTML code. -- Auto-Cache Engine to pre-cache your site at 15-minute intervals. -- Static CDN Filters to serve some and/or ALL static files on your site from a CDN of your choosing. -- An Automatic Updater to update ZenCache Pro from your WordPress Dashboard. -- Rockstar support for all ZenCache features. - -**TIP:** you can preview Pro features in the free version by clicking the "**Preview Pro Features**" link at the top of your ZenCache options. - -== Pro Installation == - -ZenCache Pro is a wholly contained plugin that _does not_ require ZenCache Lite to be installed. To install ZenCache Pro, - -1. Deactivate and delete ZenCache Lite, if it is currently installed -1. Download ZenCache Pro from your account at WebSharks-Inc.com -1. From your WordPress Dashboard, go to **Dashboard -> Plugins -> Add New** and then click on the **Upload Plugin** button at the top -1. Select the ZenCache Pro zip file you downloaded in step 2 and click "Install Now" -1. After the plugin finishes installing, click the "Activate Plugin" link - -Once the plugin is active, you can go to **Dashboard -> ZenCache -> Plugin Options -> Enable/Disable** and Enable ZenCache. - -Also, to stay updated with the latest version of ZenCache Pro, be sure to also configure **Dashboard -> ZenCache -> Plugin Updater**. - -== Software Requirements == - -In addition to the [WordPress Requirements](http://wordpress.org/about/requirements/), ZenCache requires the following minimum versions: - -- PHP 5.3.2+ -- Apache 2.1+ - -== License == - -Copyright: © 2013 [WebSharks, Inc.](http://www.websharks-inc.com/bizdev/) (coded in the USA) - -Released under the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl-2.0.html). - -= Credits / Additional Acknowledgments = - -* Software designed for WordPress®. - - GPL License - - WordPress® -* Some JavaScript extensions require jQuery. - - GPL-Compatible License - - jQuery -* CSS framework and some JavaScript functionality provided by Bootstrap. - - GPL-Compatible License - - Bootstrap -* Icons provided by Font Awesome. - - GPL-Compatible License - - Font Awesome - -== Upgrade Notice == - -= v140104 = - -Requires PHP v5.3.2+. The latest version of ZenCache is a complete rewrite (OOP design). Faster! and even more dependable. NOTE: the free version of Quick Cache (this new LITE version); while it remains fully functional and is more-than-adequate for most sites; is now limited in some ways. The following advanced features from the previous release are no longer available in the lite version: a custom MD5 Version Salt, custom Exclusion Patterns, a Clear Cache button in admin bar. These, and other features; are now available only in the pro version of the plugin. For further details, please see: . - -== Changelog == - -= v150409 = - -- **Enhancement (includes improved CloudFlare support)**: Improvements to IP address detection, including added support for CloudFlare IP forwarding, multiple IPs in a single header, and the ability to customize the lookup order and/or add/remove sources that are searched when looking for the current IP address. It's also possible to revert to the old IP address detection behavior (see [How do I customize remote IP detection?](http://zencache.com/kb-article/how-do-i-customize-ip-address-detection/)). Props @jaswsinc. [Issue #449](https://github.com/websharks/zencache/pull/449) -- **Enhancement** (Pro): Files being served by the HTML Compressor were being sent without a `Vary: Accept-Encoding` header, which caused some page speed testing services to give a lower rating to sites using ZenCache. ZenCache now ensures this header is sent via an `.htaccess` file inside the HTML Compressor cache directory (requires Apache 2.1+). Props @jaswsinc. [Issue #436](https://github.com/websharks/zencache/issues/436). -- **Enhancement** (Pro): Static CDN Filters now also filter any static resources inside Text Widgets, so that those resources can be cached by your CDN. Props @jaswsinc. [Issue #430](https://github.com/websharks/zencache/issues/430) -- **Enhancement** (Pro): Static CDN Filters now apply to minified and compressed CSS/JS files generated by the HTML Compressor; these files will now be cached by your CDN. Props @jaswsinc. [Issue #429](https://github.com/websharks/zencache/issues/429) -- **Bug Fix**: Fixed a bug related to the Quick Cache migration that resulted in caching being disabled despite ZenCache being enabled. Uninstalling Quick Cache was removing `define('WP_CACHE', TRUE);` from the `wp-config.php` file. ZenCache now makes sure that caching remains enabled after uninstalling Quick Cache during the ZenCache migration process. [Issue #450](https://github.com/websharks/zencache/issues/450). -- **Bug Fix**: Fixed a minor UI issue where the ZenCache Dashboard icon would occasionally flash to a black color when refreshing the Dashboard. Props @jaswsinc. [Issue #453](https://github.com/websharks/zencache/issues/453). -- **Bug Fix**: When ZenCache was running on an installation of PHP with `open_basedir` restrictions applied, calls to `is_dir()` were triggering a PHP Warning while looking for a writable temporary directory. This bug has been fixed. [Issue #456](https://github.com/websharks/zencache/issues/456). -- **Bug Fix**: Fixed a bug where changing the permalink for a published post would result in the cache file for the old permalink being left behind and as a result both the old and the new permalink would be accessible, instead of WordPress redirecting the old permalink to the new one. This has been fixed and ZenCache now properly clears the old cache file when changing the permalink on a published post. [Issue #359](https://github.com/websharks/zencache/issues/359). -- **Bug Fix**: Fixed a bug where transitioning a Published post back to Pending or Draft would not automatically clear the cache file. This resulted in the post remaining accessible on the frontend despite being set as Pending or Draft. ZenCache now properly clears the cache file automatically when transitioning from Published to Pending or Draft, which prevents access to the post as expected. [Issue #441](https://github.com/websharks/zencache/issues/441). -- **Bug Fix** (Pro): Some users reported seeing `Warning: trim() expects parameter 1 to be string`. This was produced by a low-impact bug that has been fixed in this release. [Issue #455](https://github.com/websharks/zencache/issues/455). -- **Bug Fix** (Pro): Some users running the HTML Compressor reported seeing 403 Forbidden errors related to loading the compressed/minified files. This was a permissions-related issue that has been resolved in this release. Props @superian and @jaswsinc. See [Issue #50](https://github.com/websharks/html-compressor/issues/50). -- **Bug Fix** (Pro): Some HTTP requests made by the HTML Compressor to servers configured to reject HTTP requests that don't include a User-Agent were failing. A User-Agent is now always used in all requests. Props @jaswsinc. See [Issue #49](https://github.com/websharks/html-compressor/issues/49). -- **Minimum Required PHP Version Bumped to PHP v5.3.2+:** The minimum PHP version required for ZenCache has been bumped up to PHP v5.3.2+ (from PHP v5.3+). The ZenCache cache locking mechanism, specifically the use of `flock()`, requires behavior introduced in PHP v5.3.2. [Issue #444](https://github.com/websharks/zencache/issues/444). - -= v150314 = - -- **Bug Fix**: Fixed a bug in the Quick Cache back compat. method `\zencache\share\apply_wp_filters()`. It was not passing the ZenCache-filtered value through the Quick Cache back compat. routine. This bug affected sites that had disabled automatic cache clearing routines via a filter. -- **Bug Fix** (Pro): Updated Static CDN Filters whitelist to include font file extensions `eot,ttf,otf,woff`, as site owners may wish to serve fonts with these extensions from the CDN (this would require a custom CORS configuration; see [this article](http://davidwalsh.name/cdn-fonts) for instructions). See [#427](https://github.com/websharks/zencache/issues/427). -- **Bug Fix** (Pro): Updated Static CDN Filters blacklist to exclude font file extensions `eot,ttf,otf,woff` by default, as they require custom CORS configuration to display properly. See [#427](https://github.com/websharks/zencache/issues/427). -- **Bug Fix** (Pro): The Static CDN Filters feature was calling a protected method that was requiring PHP v5.4+ but now the Static CDN Filters feature works with PHP v5.3+. See [#426](https://github.com/websharks/zencache/issues/426). -- **Bug Fix**: Fixed a zero-byte `advanced-cache.php` bug related to migrating from Quick Cache. When you deleted/uninstalled Quick Cache after upgrading to ZenCache, the Quick Cache uninstallation process would empty the `advanced-cache.php` file, resulting in the site no longer being cached, despite ZenCache being active. ZenCache now continuously checks to make sure that `advanced-cache.php` is installed properly. See [#432](https://github.com/websharks/zencache/issues/432). - -= v150218 = - -**Announcing ZenCache, formerly Quick Cache!** - -We are very excited to announce the release of [ZenCache](http://zencache.com), an advanced WordPress caching plugin inspired by simplicity. ZenCache is the successor to Quick Cache, a very popular WordPress caching plugin that has been downloaded over 1 million times and won acclaim for its speed, simplicity, and ease of configuration. [Read the full announcement here](http://zencache.com/announcing-zencache-formerly-quick-cache/). - -ZenCache is an evolution of Quick Cache. It comes with a completely refactored codebase, subtle UI enhancements, internal optimizations; along with full backward compatibility with all previous versions of Quick Cache Lite and Quick Cache Pro. In fact, installing ZenCache on a site that was previously running Quick Cache is a piece of cake! Watch [this video](http://zencache.com/kb-article/how-to-migrate-from-quick-cache-lite-to-zencache-lite/) to learn more. All configuration options are preserved. - -- **New Pro Feature: CDN Integration:** With the announcement and release of ZenCache we are excited to also announce a new, highly-requested feature: Static CDN Filters. This feature allows you to serve some and/or ALL static files on your site from a CDN of your choosing. See also: [Introduction to Static CDN Filters](http://zencache.com/kb-article/introduction-to-static-cdn-filters/). -- **Full Backwards Compatibility with Quick Cache and Quick Cache Pro:** ZenCache is fully backwards compatible with all previous versions of Quick Cache Lite and Quick Cache Pro. Simply install ZenCache and your existing Quick Cache options will preserved by ZenCache. - -= v150129 = - -- **Bug Fix** (Pro): Fixed a bug where the Pro Updater would fail when FTP or SFTP details via the WordPress Dashboard are required to perform updates. Props @jaswsinc. See [#389](https://github.com/websharks/quick-cache/issues/389). -- **Bug Fix**: Several fixes for a stubborn bug related to "Fatal Error: 'Unable to clear dir'" error messages and errors referencing "SplFileInfo::getMTime(): stat failed". Props @jaswsinc. See [#397](https://github.com/websharks/quick-cache/issues/397). -- **Bug Fix** (Pro): Fixed a bug where the `qcAC` variable (used to force-enable/disable GET Request caching) was not respected properly whenever a URL contained a query string and a user was currently logged into the site. Props @jaswsinc. See [#401](https://github.com/websharks/quick-cache/issues/401). - -= v141231 = - -- **Bug Fix**: Addressed another issue related to "Fatal Error: 'Unable to clear dir'" and tmp directories that don't get cleared by Quick Cache. This fix discards iteration references before renaming the tmp directories. Props @jaswsinc. See [#288](https://github.com/websharks/quick-cache/issues/288). -- **Bug Fix**: We have had a few reports of getMTime Stat failing when clearing the cache. This fix clears the Stat Cache before iteration when deleting files from the cache directory. Props @jaswsinc. See [#385](https://github.com/websharks/quick-cache/issues/385). -- **Enhancement**: Added a new filter (`quick_cache\\share_disable_cache_locking`) to allow disabling cache locking. Simply return boolean `TRUE` to this filter to disable cache locking. This may be useful for site owners who are experiencing issues with cache locking on web hosting platforms with filesystems that don't properly support locking. Note that this filter must be applied using an Advanced Cache Plugin (see **Dashboard → Quick Cache → Plugin Options → Theme/Plugin Developers**). See also [#387](https://github.com/websharks/quick-cache/issues/387). -- **Enhancement**: Added a new filter that allows forcing Semaphore cache locking on hosting platforms where `sem_get()` is available and would result in improved performance. Return `sem` to the `quick_cache\\share::cache_lock_lock_type` filter to force Semaphore cache locking, or `flock` to use the default method that uses `flock()`. Note that this filter must be applied using an Advanced Cache Plugin (see **Dashboard → Quick Cache → Plugin Options → Theme/Plugin Developers**). See also [#387](https://github.com/websharks/quick-cache/issues/387). - -= v141205 = - -- **Bug Fix**: Addressed another issue with "Fatal Error: 'Unable to clear dir'" messages by adding new blocking methods for cache lock and unlock, making it so that cache writes (including clearing, purging, wiping) all gain an exclusive lock on the cache directory while work is underway. Props @jaswsinc. See [#288](https://github.com/websharks/quick-cache/issues/288). -- **Bug Fix**: Fixed a Home Page clearing bug that arose in the previous release as the result of an extra leading `\/` in one of our regex patterns. Props @jaswsinc. See [#365](https://github.com/websharks/quick-cache/issues/365). - -= v141110 = - -- **Quick Cache is changing its name to ZenCache!** See [the blog post](http://www.websharks-inc.com/post/quick-cache-is-changing-its-name/) for full details. -- **Enhancement**: All dashboard notices will now include the number of files cleared for each notice. Props @jaswsinc. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Enhancement**: Quick Cache is now capable of doing atomic clearing/purging/wiping. On a Multisite network, this is now accomplished on a blog-specific basis, without needing to scan the entire network-wide cache directory. This should improve performance considerably on large networks (i.e. those with VERY large cache directories). Props @jaswsinc. See [#288](https://github.com/websharks/quick-cache/issues/288) and [#351](https://github.com/websharks/quick-cache/pull/351). -- **Enhancement**: Added a new class file (`/includes/utils-feed.php`) and refactored the XML feed clearing routine. With these utilities in place, the `auto_clear_xml_feeds_cache()` method is now much easier to deal with and comprehend. Props @jaswsinc. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Enhancement**: Quick Cache now scans each scheme sub-directory, i.e. `/http/` and `/https/`, separately to help break apart what was previously a much larger directory scan for sites that serve pages over both schemes. This will improve performance on both standard and Multisite network installs. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Enhancement**: Refactored codebase to improve modularity by creating new methods in `includes/share.php` for network-wide clearing/purging/wiping, host/blog-specific clearing/purging/wiping, recursively deleting a directory, assisting in translations, and several new string utilities. Props @jaswsinc. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Enhancement**: Renamed all `\quick_cache\plugin::auto_purge_*` methods, giving them the proper prefix of `auto_clear_*` instead to reflect proper Wipe/Clear/Purge terminology. Along with this, all of the `auto_purge_` option keys have been renamed as well. See new [Wipe/Clear/Purge wiki article](http://www.websharks-inc.com/r/quick-cache-wipeclearpurge-terminology-wiki/) for a description of these terms. Props @jaswsinc. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Enhancement**: All URI and Referrer exclusion patterns are now caSe insensitive. WordPress v4.0 will serve URIs without cAse sensitivity. All of the Quick Cache codebase has been updated to support caSe insensitive clearing/purging/wiping; along with caSe insensitive pattern matching against URIs. Props @jaswsinc. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Bug Fix (Pro)**: Fixed a bug with the Auto-Clear Author Cache routine that was presenting dashboard notices even when `change_notifications_enable` was off. Props @jaswsinc. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Bug Fix (Pro)**: Fixed a bug with the HTML Compressor where `style`, `link` and/or `script` tags could become out of order in certain scenarios. See: [#45](https://github.com/websharks/html-compressor/issues/45) -- **Bug Fix (Pro)**: Several HTML Compressor bug fixes related to JavaScript compression routines. See [#38](https://github.com/websharks/html-compressor/issues/38) -- **Bug Fix**: Fixed a bug that was occasionally generating "Fatal Error: 'Unable to clear dir'" messages. The root cause of this is believed to be non-atomic purging of cache directories which, on a busy site, could result in new cache files being created before a purging routine was finished clearing the directory. Clearing/purging/wiping is now atomic in all scenarios. Props @jaswsinc. See [#288](https://github.com/websharks/quick-cache/issues/288) and [#351](https://github.com/websharks/quick-cache/pull/351). -- **Bug Fix**: Fixed a bug in the Auto-Clear Custom Post Type Archive Cache that was not checking for the `$post_id` in `$this->static[__FUNCTION__]`. Props @jaswsinc. See [#351](https://github.com/websharks/quick-cache/pull/351). -- **Bug Fix**: Fixed a bug with the uninstaller whereby attempting to uninstall after receiving a notice that PHP 5.3+ is required would result in a blank screen and require manual removal of the plugin. See [#334](https://github.com/websharks/quick-cache/issues/334). -- **Bug Fix**: Fixed an issue with detecting cacheable requests that was, in rare instances, resulting in blank white pages for some site owners. See [#279](https://github.com/websharks/quick-cache/issues/279). - -= v141001 = - -- **Enhancement**: Improved Dashboard messaging for the `auto_clear_cache()` routine. See [#328](https://github.com/websharks/quick-cache/issues/328). -- **Enhancement (Pro)**: Improved consistency of Auto-Cache Engine User-Agent string by removing WordPress-version-specific identifier. See [#315](https://github.com/websharks/quick-cache/issues/315). -- **Enhancement (Pro)**: It is now possible to disable the automatic clear and wipe cache routines. If you have a very large site with many cache files, this feature allows you manual control over when the cache gets cleared or wiped. For complete documentation on this feature, see [Quick Cache Wiki - Clear and Wipe Cache Routines](https://github.com/websharks/quick-cache/wiki/Clear-Cache-and-Wipe-Cache-Routines). See also [#23](https://github.com/websharks/quick-cache/issues/23). -- **Bug Fix**: Fixes an issue with the Pro Preview mode where saving the plugin options may inadvertently save Pro-only options that could later cause issues if the plugin is upgraded to the Pro version. See [#311](https://github.com/websharks/quick-cache/pull/311#issuecomment-54491922). -- **Bug Fix**: Fixes an edge-case where the proper cache files do not get purged when a user with the Editor role publishes a new post with both a category and a tag associated with the post. See [#313](https://github.com/websharks/quick-cache/issues/313). -- **Bug Fix**: When Quick Cache purges/resets the cache for a post with a Custom Post Type, any cache files for the associated Custom Post Type archive view are now auto-purged, along with any associated XML feed cache files. See [#280](https://github.com/websharks/quick-cache/issues/280). -- **Bug Fix**: Fixed missing trailing slash in Directory / Expiration Time configuration panel. This was purely a visual inconsistency and had no effect on Quick Cache's functionality. See [#267](https://github.com/websharks/quick-cache/issues/267). -- **Bug Fix**: When saving custom CSS using JetPack's Custom CSS module, Quick Cache now properly purges the site cache to ensure that outdated cache files are not served to visitors. See [#246](https://github.com/websharks/quick-cache/issues/246). -- **Bug Fix**: When changes are made to WordPress General, Reading, Discussion, or Permalink settings (Dashboard -> Settings), Quick Cache now clears the cache to prevent an outdated cache file from being served to visitors. See [#223](https://github.com/websharks/quick-cache/issues/223). -- **Bug Fix**: When an active plugin is updated, or when an active theme or the parent theme for an active child theme is updated, or when WordPress Core is updated, Quick Cache now properly clears the cache to ensure that an outdated cache file does not get served to a visitor. See [#145](https://github.com/websharks/quick-cache/issues/145) and [#327](https://github.com/websharks/quick-cache/issues/327). -- **Bug Fix**: When a new comment is posted, Quick Cache now properly purges the cache files for any paginated comment pages. See [#336](https://github.com/websharks/quick-cache/issues/336). -- **Bug Fix (Pro)**: Fixed a bug where the HTML Compressor, when enabled with the "remove extra whitespace in the final HTML" option, would incorrectly remove ``. See [#299](https://github.com/websharks/quick-cache/issues/299). -- **Bug Fix (Pro)**: Fixed a bug in the HTML Compressor that would, in certain scenarios, leave behind fragments of HTML comments. See [#295](https://github.com/websharks/quick-cache/issues/295). -- **Bug Fix (Pro)**: The Auto-Cache Engine now has an option to configure a delay between each request when pre-caching the site. There were some reports of the Auto-Cache Engine causing load issues with large sites on servers that sometimes had trouble handling many requests. See [#294](https://github.com/websharks/quick-cache/issues/294). -- **Bug Fix (Pro)**: Fixes an Auto-Cache Engine scheduling issue that may, in some scenarios, prevent it from running as expected. See [#291](https://github.com/websharks/quick-cache/issues/291). -- **Bug Fix (Pro)**: Fixed a bug with the HTML Compressor where `style`, `link` and/or `script` tags could end up out of order in certain scenarios. See [#45](https://github.com/websharks/html-compressor/issues/45). -- **Bug Fix (Pro)**: Fixed a bug in the HTML Compressor related to JavaScript compression routines. See [#38](https://github.com/websharks/html-compressor/issues/38). - -For older Changelog entries, please see the `CHANGELOG` file. diff --git a/zencache/submodules/.htaccess b/zencache/submodules/.htaccess deleted file mode 100644 index f1f5bd3..0000000 --- a/zencache/submodules/.htaccess +++ /dev/null @@ -1,15 +0,0 @@ - - Require all denied - - - deny from all - - - - - Require all granted - - - allow from all - - \ No newline at end of file diff --git a/zencache/submodules/sharkicons b/zencache/submodules/sharkicons deleted file mode 160000 index 2754bb8..0000000 --- a/zencache/submodules/sharkicons +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2754bb8b929390658fdf25d6d04b8e2b65cead89 diff --git a/zencache/submodules/wp-php-rv b/zencache/submodules/wp-php-rv deleted file mode 160000 index d2ba136..0000000 --- a/zencache/submodules/wp-php-rv +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d2ba1363b38b149a9020809c74828e4cfc1a2e73 diff --git a/zencache/uninstall.inc.php b/zencache/uninstall.inc.php deleted file mode 100644 index aba4481..0000000 --- a/zencache/uninstall.inc.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @license GNU General Public License, version 2 - */ -namespace zencache -{ - if(!defined('WPINC')) // MUST have WordPress. - exit('Do NOT access this file directly: '.basename(__FILE__)); - - $GLOBALS[__NAMESPACE__.'_uninstalling'] = TRUE; - $GLOBALS[__NAMESPACE__.'_autoload_plugin'] = FALSE; - - require_once dirname(__FILE__).'/zencache.inc.php'; - - if(!class_exists('\\'.__NAMESPACE__.'\\uninstall')) - { - class uninstall // Uninstall handler. - { - /** - * @since 141001 Adding uninstaller. - * - * @var plugin Primary plugin class instance. - */ - protected $plugin; // Set by constructor. - - /** - * Uninstall constructor. - * - * @since 141001 Adding uninstall handler. - */ - public function __construct() - { - $GLOBALS[__NAMESPACE__] // Without hooks. - = $this->plugin = new plugin(FALSE); - - $this->plugin->uninstall(); - } - } - } - new uninstall(); // Run the uninstaller. -} \ No newline at end of file diff --git a/zencache/uninstall.php b/zencache/uninstall.php deleted file mode 100644 index 44c7436..0000000 --- a/zencache/uninstall.php +++ /dev/null @@ -1,15 +0,0 @@ - - * @license GNU General Public License, version 2 - */ -if(!defined('WPINC')) // MUST have WordPress. - exit('Do NOT access this file directly: '.basename(__FILE__)); - -$GLOBALS['wp_php_rv'] = '5.3.2'; // Require PHP v5.3.2+. -if(require(dirname(__FILE__).'/submodules/wp-php-rv/wp-php-rv.php')) - require_once dirname(__FILE__).'/uninstall.inc.php'; \ No newline at end of file diff --git a/zencache/zencache.inc.php b/zencache/zencache.inc.php deleted file mode 100644 index a9ad4f3..0000000 --- a/zencache/zencache.inc.php +++ /dev/null @@ -1,2464 +0,0 @@ - - * @license GNU General Public License, version 2 - */ -namespace zencache -{ - if(!defined('WPINC')) // MUST have WordPress. - exit('Do NOT access this file directly: '.basename(__FILE__)); - - require_once dirname(__FILE__).'/includes/share.php'; - require dirname(__FILE__).'/includes/conflicts-check.php'; - - if(!class_exists('\\'.__NAMESPACE__.'\\plugin') && empty($GLOBALS[__NAMESPACE__.'_conflicting_plugin'])) - { - /** - * ZenCache Plugin - * - * @package zencache\plugin - * @since 140422 First documented version. - */ - class plugin extends share - { - /** - * Stub `__FILE__` location. - * - * @since 140422 First documented version. - * - * @var string Current `__FILE__` from the stub; NOT from this file. - * Note that ZenCache has a stub loader that checks for PHP v5.3 compat; - * which is why we have this property. This is the stub `__FILE__`. - */ - public $file = ''; - - /** - * An array of all default option values. - * - * @since 140422 First documented version. - * - * @var array Default options array; set by constructor. - */ - public $default_options = array(); - - /** - * Configured option values. - * - * @since 140422 First documented version. - * - * @var array Options configured by site owner; set by constructor. - */ - public $options = array(); - - /** - * General capability requirement. - * - * @since 140422 First documented version. - * - * @var string WordPress capability required to - * administer QC in any environment; i.e. in multisite or otherwise. - */ - public $cap = ''; - - /** - * Network capability requirement. - * - * @since 140422 First documented version. - * - * @var string WordPress capability required to - * administer QC in a multisite network. - */ - public $network_cap = ''; - - /** - * Uninstall capability requirement. - * - * @since 140829 Adding uninstall handler. - * - * @var string WordPress capability required to - * completely uninstall/delete QC. - */ - public $uninstall_cap = ''; - - /** - * Cache directory. - * - * @since 140605 Moving to a base directory. - * - * @var string Cache directory; relative to the configured base directory. - */ - public $cache_sub_dir = 'cache'; - - /** - * Used by methods in this class to help optimize performance. - * - * @since 140725 Reducing auto-purge overhead. - * - * @var array An instance-based cache used by methods in this class. - */ - public $cache = array(); - - /** - * Used for temporarily storing the permalink for posts transitioning from - * `publish` or `private` post status to `pending` or `draft` post status. - * - * @since 150409 - * - * @var array An associative array with the Post ID as the named key containing the post permalink before the post has been transitioned - * - * @see auto_clear_post_cache() - * @see auto_clear_post_cache_transition() - */ - protected $pre_post_update_post_permalink = array(); - - /** - * Used by the plugin's uninstall handler. - * - * @since 140829 Adding uninstall handler. - * - * @var boolean If FALSE, run without any hooks. - */ - public $enable_hooks = TRUE; - - /** - * ZenCache plugin constructor. - * - * @param boolean $enable_hooks Defaults to a TRUE value. - * If FALSE, setup runs but without adding any hooks. - * - * @since 140422 First documented version. - */ - public function __construct($enable_hooks = TRUE) - { - parent::__construct(); // Shared constructor. - - /* -------------------------------------------------------------- */ - - $this->enable_hooks = (boolean)$enable_hooks; - $this->file = preg_replace('/\.inc\.php$/', '.php', __FILE__); - - /* -------------------------------------------------------------- */ - - if(!$this->enable_hooks) // Without hooks? - return; // Stop here; construct without hooks. - - /* -------------------------------------------------------------- */ - - add_action('after_setup_theme', array($this, 'setup')); - register_activation_hook($this->file, array($this, 'activate')); - register_deactivation_hook($this->file, array($this, 'deactivate')); - } - - /** - * Setup the ZenCache plugin. - * - * @since 140422 First documented version. - */ - public function setup() - { - if(isset($this->cache[__FUNCTION__])) - return; // Already setup. Once only! - $this->cache[__FUNCTION__] = -1; - - if($this->enable_hooks) // Hooks enabled? - $this->do_wp_action('before__'.__METHOD__, get_defined_vars()); - - /* -------------------------------------------------------------- */ - - load_plugin_textdomain($this->text_domain); - - $this->default_options = array( - /* Core/systematic plugin options. */ - - 'version' => $this->version, - 'crons_setup' => '0', // `0` or timestamp. - - /* Primary switch; enable? */ - - 'enable' => '0', // `0|1`. - - /* Related to debugging. */ - - 'debugging_enable' => '1', - // `0|1|2` // 2 indicates greater debugging detail. - - /* Related to cache directory. */ - - 'base_dir' => 'cache/zencache', // Relative to `WP_CONTENT_DIR`. - 'cache_max_age' => '7 days', // `strtotime()` compatible. - - /* Related to automatic cache clearing. */ - - 'cache_clear_home_page_enable' => '1', // `0|1`. - 'cache_clear_posts_page_enable' => '1', // `0|1`. - - 'cache_clear_author_page_enable' => '1', // `0|1`. - - 'cache_clear_term_category_enable' => '1', // `0|1`. - 'cache_clear_term_post_tag_enable' => '1', // `0|1`. - 'cache_clear_term_other_enable' => '0', // `0|1`. - - /* Misc. cache behaviors. */ - - 'allow_browser_cache' => '0', // `0|1`. - 'get_requests' => '0', // `0|1`. - 'feeds_enable' => '0', // `0|1`. - 'cache_404_requests' => '0', // `0|1`. - - /* Related to uninstallation routines. */ - - 'uninstall_on_deletion' => '0', // `0|1`. - - ); // Default options are merged with those defined by the site owner. - $options = is_array($options = get_option(__NAMESPACE__.'_options')) ? $options : array(); - if(is_multisite() && is_array($site_options = get_site_option(__NAMESPACE__.'_options'))) - $options = array_merge($options, $site_options); // Multisite network options. - - if(!$options && is_multisite() && is_array($quick_cache_site_options = get_site_option('quick_cache_options'))) - { // Old Multisite Network options from Quick Cache. - $options = $quick_cache_site_options; - $options['crons_setup'] = $this->default_options['crons_setup']; - } - if(!$options && is_array($quick_cache_options = get_option('quick_cache_options'))) - { // Old options from Quick Cache standard installation. - $options = $quick_cache_options; - $options['crons_setup'] = $this->default_options['crons_setup']; - } - $this->default_options = $this->apply_wp_filters(__METHOD__.'__default_options', $this->default_options, get_defined_vars()); - $this->options = array_merge($this->default_options, $options); // This considers old options also. - $this->options = $this->apply_wp_filters(__METHOD__.'__options', $this->options, get_defined_vars()); - $this->options = array_intersect_key($this->options, $this->default_options); - - $this->options['base_dir'] = trim($this->options['base_dir'], '\\/'." \t\n\r\0\x0B"); - if(!$this->options['base_dir']) // Security enhancement; NEVER allow this to be empty. - $this->options['base_dir'] = $this->default_options['base_dir']; - - $this->cap = $this->apply_wp_filters(__METHOD__.'__cap', 'activate_plugins'); - $this->network_cap = $this->apply_wp_filters(__METHOD__.'__network_cap', 'manage_network_plugins'); - $this->uninstall_cap = $this->apply_wp_filters(__METHOD__.'__uninstall_cap', 'delete_plugins'); - - /* -------------------------------------------------------------- */ - - if(!$this->enable_hooks) // Without hooks? - return; // Stop here; setup without hooks. - - /* -------------------------------------------------------------- */ - - add_action('init', array($this, 'check_advanced_cache')); - add_action('init', array($this, 'check_blog_paths')); - add_action('wp_loaded', array($this, 'actions')); - - add_action('admin_init', array($this, 'check_version')); - add_action('admin_init', array($this, 'maybe_auto_clear_cache')); - - add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles')); - add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); - - add_action('all_admin_notices', array($this, 'all_admin_notices')); - add_action('all_admin_notices', array($this, 'all_admin_errors')); - - add_action('network_admin_menu', array($this, 'add_network_menu_pages')); - add_action('admin_menu', array($this, 'add_menu_pages')); - - add_action('upgrader_process_complete', array($this, 'upgrader_process_complete'), 10, 2); - add_action('safecss_save_pre', array($this, 'jetpack_custom_css'), 10, 1); - - add_action('switch_theme', array($this, 'auto_clear_cache')); - add_action('wp_create_nav_menu', array($this, 'auto_clear_cache')); - add_action('wp_update_nav_menu', array($this, 'auto_clear_cache')); - add_action('wp_delete_nav_menu', array($this, 'auto_clear_cache')); - - add_action('save_post', array($this, 'auto_clear_post_cache')); - add_action('delete_post', array($this, 'auto_clear_post_cache')); - add_action('clean_post_cache', array($this, 'auto_clear_post_cache')); - add_action('post_updated', array($this, 'auto_clear_author_page_cache'), 10, 3); - add_action('pre_post_update', array($this, 'auto_clear_post_cache_transition'), 10, 2); - - add_action('added_term_relationship', array($this, 'auto_clear_post_terms_cache'), 10, 1); - add_action('delete_term_relationships', array($this, 'auto_clear_post_terms_cache'), 10, 1); - - add_action('trackback_post', array($this, 'auto_clear_comment_post_cache')); - add_action('pingback_post', array($this, 'auto_clear_comment_post_cache')); - add_action('comment_post', array($this, 'auto_clear_comment_post_cache')); - add_action('transition_comment_status', array($this, 'auto_clear_comment_transition'), 10, 3); - - add_action('create_term', array($this, 'auto_clear_cache')); - add_action('edit_terms', array($this, 'auto_clear_cache')); - add_action('delete_term', array($this, 'auto_clear_cache')); - - add_action('add_link', array($this, 'auto_clear_cache')); - add_action('edit_link', array($this, 'auto_clear_cache')); - add_action('delete_link', array($this, 'auto_clear_cache')); - - add_filter('enable_live_network_counts', array($this, 'update_blog_paths')); - - add_filter('plugin_action_links_'.plugin_basename($this->file), array($this, 'add_settings_link')); - - /* -------------------------------------------------------------- */ - - add_filter('cron_schedules', array($this, 'extend_cron_schedules')); - - if((integer)$this->options['crons_setup'] < 1382523750) - { - wp_clear_scheduled_hook('_cron_'.__NAMESPACE__.'_cleanup'); - wp_schedule_event(time() + 60, 'daily', '_cron_'.__NAMESPACE__.'_cleanup'); - - $this->options['crons_setup'] = (string)time(); - update_option(__NAMESPACE__.'_options', $this->options); // Blog-specific. - if(is_multisite()) update_site_option(__NAMESPACE__.'_options', $this->options); - } - add_action('_cron_'.__NAMESPACE__.'_cleanup', array($this, 'purge_cache')); - - /* -------------------------------------------------------------- */ - - $this->do_wp_action('after__'.__METHOD__, get_defined_vars()); - $this->do_wp_action(__METHOD__.'_complete', get_defined_vars()); - } - - /** - * WordPress database instance. - * - * @since 140422 First documented version. - * - * @return \wpdb Reference for IDEs. - */ - public function wpdb() // Shortcut for other routines. - { - return $GLOBALS['wpdb']; - } - - /** - * Plugin activation hook. - * - * @since 140422 First documented version. - * - * @attaches-to {@link \register_activation_hook()} - */ - public function activate() - { - $this->setup(); // Setup routines. - - if(!$this->options['enable']) - return; // Nothing to do. - - $this->add_wp_cache_to_wp_config(); - $this->add_advanced_cache(); - $this->update_blog_paths(); - $this->auto_clear_cache(); - } - - /** - * Check current plugin version that installed in WP. - * - * @since 140422 First documented version. - * - * @attaches-to `admin_init` hook. - */ - public function check_version() - { - $current_version = $prev_version = $this->options['version']; - if(version_compare($current_version, $this->version, '>=')) - return; // Nothing to do; we've already upgraded them. - - $current_version = $this->options['version'] = $this->version; - update_option(__NAMESPACE__.'_options', $this->options); // Updates version. - if(is_multisite()) update_site_option(__NAMESPACE__.'_options', $this->options); - - require_once dirname(__FILE__).'/includes/version-specific-upgrade.php'; - new version_specific_upgrade($prev_version); - - if($this->options['enable']) // Recompile. - { - $this->add_wp_cache_to_wp_config(); - $this->add_advanced_cache(); - $this->update_blog_paths(); - } - $this->wipe_cache(); // Always wipe the cache; no exceptions. - - $this->enqueue_notice(sprintf(__('%1$s: detected a new version of itself. Recompiling w/ latest version... wiping the cache... all done :-)', $this->text_domain), esc_html($this->name)), '', TRUE); - } - - /** - * Plugin deactivation hook. - * - * @since 140422 First documented version. - * - * @attaches-to {@link \register_deactivation_hook()} - */ - public function deactivate() - { - $this->setup(); // Setup routines. - - $this->remove_wp_cache_from_wp_config(); - $this->remove_advanced_cache(); - $this->clear_cache(); - } - - /** - * Plugin uninstall hook. - * - * @since 140829 Adding uninstall handler. - * - * @attaches-to {@link \register_uninstall_hook()} ~ via {@link uninstall()} - */ - public function uninstall() - { - $this->setup(); // Setup routines. - - if(!defined('WP_UNINSTALL_PLUGIN')) - return; // Disallow. - - if(empty($GLOBALS[__NAMESPACE__.'_uninstalling'])) - return; // Not uninstalling. - - if(!class_exists('\\'.__NAMESPACE__.'\\uninstall')) - return; // Expecting the uninstall class. - - if(!current_user_can($this->uninstall_cap)) - return; // Extra layer of security. - - $this->remove_wp_cache_from_wp_config(); - $this->remove_advanced_cache(); - $this->wipe_cache(); - - if(!$this->options['uninstall_on_deletion']) - return; // Nothing to do here. - - $this->delete_advanced_cache(); - $this->remove_base_dir(); - - delete_option(__NAMESPACE__.'_options'); - if(is_multisite()) // Delete network options too. - delete_site_option(__NAMESPACE__.'_options'); - - delete_option(__NAMESPACE__.'_notices'); - delete_option(__NAMESPACE__.'_errors'); - - wp_clear_scheduled_hook('_cron_'.__NAMESPACE__.'_cleanup'); - } - - /** - * Current request is for a pro version preview? - * - * @since 140422 First documented version. - * - * @return boolean TRUE if the current request is for a pro preview. - */ - public function is_pro_preview() - { - static $is; - if(isset($is)) return $is; - - if(!empty($_REQUEST[__NAMESPACE__.'_pro_preview'])) - return ($is = TRUE); - - return ($is = FALSE); - } - - /** - * URL to a ZenCache plugin file. - * - * @since 140422 First documented version. - * - * @param string $file Optional file path; relative to plugin directory. - * @param string $scheme Optional URL scheme; defaults to the current scheme. - * - * @return string URL to plugin directory; or to the specified `$file` if applicable. - */ - public function url($file = '', $scheme = '') - { - if(!isset(static::$static[__FUNCTION__]['plugin_dir'])) - static::$static[__FUNCTION__]['plugin_dir'] = rtrim(plugin_dir_url($this->file), '/'); - $plugin_dir =& static::$static[__FUNCTION__]['plugin_dir']; - - $url = $plugin_dir.(string)$file; - - if($scheme) // A specific URL scheme? - $url = set_url_scheme($url, (string)$scheme); - - return $this->apply_wp_filters(__METHOD__, $url, get_defined_vars()); - } - - /** - * Plugin action handler. - * - * @since 140422 First documented version. - * - * @attaches-to `wp_loaded` hook. - */ - public function actions() - { - if(!empty($_REQUEST[__NAMESPACE__])) - require_once dirname(__FILE__).'/includes/actions.php'; - } - - /** - * Adds CSS for administrative menu pages. - * - * @since 140422 First documented version. - * - * @attaches-to `admin_enqueue_scripts` hook. - */ - public function enqueue_admin_styles() - { - if(empty($_GET['page']) || strpos($_GET['page'], __NAMESPACE__) !== 0) - return; // Nothing to do; NOT a plugin page in the administrative area. - - $deps = array(); // Plugin dependencies. - - wp_enqueue_style(__NAMESPACE__, $this->url('/client-s/css/menu-pages.min.css'), $deps, $this->version, 'all'); - } - - /** - * Adds JS for administrative menu pages. - * - * @since 140422 First documented version. - * - * @attaches-to `admin_enqueue_scripts` hook. - */ - public function enqueue_admin_scripts() - { - if(empty($_GET['page']) || strpos($_GET['page'], __NAMESPACE__) !== 0) - return; // Nothing to do; NOT a plugin page in the administrative area. - - $deps = array('jquery'); // Plugin dependencies. - - wp_enqueue_script(__NAMESPACE__, $this->url('/client-s/js/menu-pages.min.js'), $deps, $this->version, TRUE); - } - - /** - * Creates network admin menu pages. - * - * @since 140422 First documented version. - * - * @attaches-to `network_admin_menu` hook. - */ - public function add_network_menu_pages() - { - $icon = file_get_contents(dirname(__FILE__).'/client-s/images/inline-icon.svg'); - $icon = 'data:image/svg+xml;base64,'.base64_encode($this->color_svg_menu_icon($icon)); - - add_menu_page($this->name, $this->name, $this->network_cap, __NAMESPACE__, array($this, 'menu_page_options'), $icon); - } - - /** - * Creates admin menu pages. - * - * @since 140422 First documented version. - * - * @attaches-to `admin_menu` hook. - */ - public function add_menu_pages() - { - if(is_multisite()) return; // Multisite networks MUST use network admin area. - - $icon = file_get_contents(dirname(__FILE__).'/client-s/images/inline-icon.svg'); - $icon = 'data:image/svg+xml;base64,'.base64_encode($this->color_svg_menu_icon($icon)); - - add_menu_page($this->name, $this->name, $this->cap, __NAMESPACE__, array($this, 'menu_page_options'), $icon); - } - - /** - * Adds link(s) to ZenCache row on the WP plugins page. - * - * @since 140422 First documented version. - * - * @attaches-to `plugin_action_links_'.plugin_basename($this->file)` filter. - * - * @param array $links An array of the existing links provided by WordPress. - * - * @return array Revised array of links. - */ - public function add_settings_link($links) - { - $links[] = ''.__('Settings', $this->text_domain).''; - $links[] = '
'.__('Preview Pro Features', $this->text_domain).''; - $links[] = ''.__('Upgrade', $this->text_domain).''; - - return $this->apply_wp_filters(__METHOD__, $links, get_defined_vars()); - } - - /** - * Fills menu page inline SVG icon color. - * - * @since 150409 Fixing bug in SVG icons. - * - * @param string $svg Inline SVG icon markup. - * - * @return string Inline SVG icon markup. - */ - public function color_svg_menu_icon($svg) - { - if(!($color = get_user_option('admin_color'))) - $color = 'fresh'; // Default color scheme. - - if(empty($this->wp_admin_icon_colors[$color])) - return $svg; // Not possible. - - $icon_colors = $this->wp_admin_icon_colors[$color]; - $use_icon_fill_color = $icon_colors['base']; // Default base. - - $current_pagenow = !empty($GLOBALS['pagenow']) ? $GLOBALS['pagenow'] : ''; - $current_page = !empty($_REQUEST['page']) ? $_REQUEST['page'] : ''; - - if(strpos($current_pagenow, __NAMESPACE__) === 0 || strpos($current_page, __NAMESPACE__) === 0) - $use_icon_fill_color = $icon_colors['current']; - - return str_replace(' fill="currentColor"', ' fill="'.esc_attr($use_icon_fill_color).'"', $svg); - } - - /** - * WordPress admin icon color schemes. - * - * @since 150409 Fixing bug in SVG icons. - * - * @var array WP admin icon colors. - * - * @note These must be hard-coded, because they don't become available - * in core until `admin_init`; i.e., too late for `admin_menu`. - */ - public $wp_admin_icon_colors = array( - 'fresh' => array('base' => '#999999', 'focus' => '#2EA2CC', 'current' => '#FFFFFF'), - 'light' => array('base' => '#999999', 'focus' => '#CCCCCC', 'current' => '#CCCCCC'), - 'blue' => array('base' => '#E5F8FF', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'), - 'midnight' => array('base' => '#F1F2F3', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'), - 'sunrise' => array('base' => '#F3F1F1', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'), - 'ectoplasm' => array('base' => '#ECE6F6', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'), - 'ocean' => array('base' => '#F2FCFF', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'), - 'coffee' => array('base' => '#F3F2F1', 'focus' => '#FFFFFF', 'current' => '#FFFFFF'), - ); - - /** - * Loads the admin menu page options. - * - * @since 140422 First documented version. - * - * @see add_network_menu_pages() - * @see add_menu_pages() - */ - public function menu_page_options() - { - require_once dirname(__FILE__).'/includes/menu-pages.php'; - $menu_pages = new menu_pages(); - $menu_pages->options(); - } - - /** - * Render admin notices; across all admin dashboard views. - * - * @since 140422 First documented version. - * - * @attaches-to `all_admin_notices` hook. - */ - public function all_admin_notices() - { - if(($notices = (is_array($notices = get_option(__NAMESPACE__.'_notices'))) ? $notices : array())) - { - $notices = $updated_notices = array_unique($notices); // De-dupe. - - foreach(array_keys($updated_notices) as $_key) if(strpos($_key, 'persistent-') !== 0) - unset($updated_notices[$_key]); // Leave persistent notices; ditch others. - unset($_key); // Housekeeping after updating notices. - - update_option(__NAMESPACE__.'_notices', $updated_notices); - } - if(current_user_can($this->cap)) foreach($notices as $_key => $_notice) - { - $_dismiss = ''; // Initialize empty string; e.g. reset value on each pass. - if(strpos($_key, 'persistent-') === 0) // A dismissal link is needed in this case? - { - $_dismiss_css = 'display:inline-block; float:right; margin:0 0 0 15px; text-decoration:none; font-weight:bold;'; - $_dismiss = add_query_arg(urlencode_deep(array(__NAMESPACE__ => array('dismiss_notice' => array('key' => $_key)), '_wpnonce' => wp_create_nonce()))); - $_dismiss = ''.__('dismiss ×', $this->text_domain).''; - } - if(strpos($_key, 'class-update-nag') !== FALSE) - $_class = 'update-nag'; - else if(strpos($_key, 'class-error') !== FALSE) - $_class = 'error'; - else - $_class = 'updated'; - echo $this->apply_wp_filters(__METHOD__.'__notice', '

'.$_notice.$_dismiss.'

', get_defined_vars()); - } - unset($_key, $_notice, $_dismiss_css, $_dismiss); // Housekeeping. - } - - /** - * Enqueue an administrative notice. - * - * @since 140605 Adding enqueue notice/error methods. - * - * @param string $notice HTML markup containing the notice itself. - * - * @param string $persistent_key Optional. A unique key which identifies a particular type of persistent notice. - * This defaults to an empty string. If this is passed, the notice is persistent; i.e. it continues to be displayed until dismissed by the site owner. - * - * @param boolean $push_to_top Optional. Defaults to a `FALSE` value. - * If `TRUE`, the notice is pushed to the top of the stack; i.e. displayed above any others. - */ - public function enqueue_notice($notice, $persistent_key = '', $push_to_top = FALSE) - { - $notice = (string)$notice; - $persistent_key = (string)$persistent_key; - - $notices = get_option(__NAMESPACE__.'_notices'); - if(!is_array($notices)) $notices = array(); - - if($persistent_key) // A persistent notice? - { - if(strpos($persistent_key, 'persistent-') !== 0) - $persistent_key = 'persistent-'.$persistent_key; - - if($push_to_top) // Push this notice to the top? - $notices = array($persistent_key => $notice) + $notices; - else $notices[$persistent_key] = $notice; - } - else if($push_to_top) // Push to the top? - array_unshift($notices, $notice); - - else $notices[] = $notice; // Default behavior. - - update_option(__NAMESPACE__.'_notices', $notices); - } - - /** - * Render admin errors; across all admin dashboard views. - * - * @since 140422 First documented version. - * - * @attaches-to `all_admin_notices` hook. - */ - public function all_admin_errors() - { - if(($errors = (is_array($errors = get_option(__NAMESPACE__.'_errors'))) ? $errors : array())) - { - $errors = $updated_errors = array_unique($errors); // De-dupe. - - foreach(array_keys($updated_errors) as $_key) if(strpos($_key, 'persistent-') !== 0) - unset($updated_errors[$_key]); // Leave persistent errors; ditch others. - unset($_key); // Housekeeping after updating notices. - - update_option(__NAMESPACE__.'_errors', $updated_errors); - } - if(current_user_can($this->cap)) foreach($errors as $_key => $_error) - { - $_dismiss = ''; // Initialize empty string; e.g. reset value on each pass. - if(strpos($_key, 'persistent-') === 0) // A dismissal link is needed in this case? - { - $_dismiss_css = 'display:inline-block; float:right; margin:0 0 0 15px; text-decoration:none; font-weight:bold;'; - $_dismiss = add_query_arg(urlencode_deep(array(__NAMESPACE__ => array('dismiss_error' => array('key' => $_key)), '_wpnonce' => wp_create_nonce()))); - $_dismiss = ''.__('dismiss ×', $this->text_domain).''; - } - echo $this->apply_wp_filters(__METHOD__.'__error', '

'.$_error.$_dismiss.'

', get_defined_vars()); - } - unset($_key, $_error, $_dismiss_css, $_dismiss); // Housekeeping. - } - - /** - * Enqueue an administrative error. - * - * @since 140605 Adding enqueue notice/error methods. - * - * @param string $error HTML markup containing the error itself. - * - * @param string $persistent_key Optional. A unique key which identifies a particular type of persistent error. - * This defaults to an empty string. If this is passed, the error is persistent; i.e. it continues to be displayed until dismissed by the site owner. - * - * @param boolean $push_to_top Optional. Defaults to a `FALSE` value. - * If `TRUE`, the error is pushed to the top of the stack; i.e. displayed above any others. - */ - public function enqueue_error($error, $persistent_key = '', $push_to_top = FALSE) - { - $error = (string)$error; - $persistent_key = (string)$persistent_key; - - $errors = get_option(__NAMESPACE__.'_errors'); - if(!is_array($errors)) $errors = array(); - - if($persistent_key) // A persistent notice? - { - if(strpos($persistent_key, 'persistent-') !== 0) - $persistent_key = 'persistent-'.$persistent_key; - - if($push_to_top) // Push this notice to the top? - $errors = array($persistent_key => $error) + $errors; - else $errors[$persistent_key] = $error; - } - else if($push_to_top) // Push to the top? - array_unshift($errors, $error); - - else $errors[] = $error; // Default behavior. - - update_option(__NAMESPACE__.'_errors', $errors); - } - - /** - * Extends WP-Cron schedules. - * - * @since 140422 First documented version. - * - * @attaches-to `cron_schedules` filter. - * - * @param array $schedules An array of the current schedules. - * - * @return array Revised array of WP-Cron schedules. - */ - public function extend_cron_schedules($schedules) - { - $schedules['every15m'] = array('interval' => 900, 'display' => __('Every 15 Minutes', $this->text_domain)); - - return $this->apply_wp_filters(__METHOD__, $schedules, get_defined_vars()); - } - - /** - * Wipes out all cache files in the cache directory. - * - * @since 140422 First documented version. - * - * @param boolean $manually Defaults to a `FALSE` value. - * Pass as TRUE if the wipe is done manually by the site owner. - * - * @param string $also_wipe_dir Defaults to an empty string. - * By default (i.e. when this is empty) we only wipe {@link $cache_sub_dir} files. - * - * WARNING: If this is passed, EVERYTHING inside this directory is deleted recursively; - * in addition to deleting all of the {@link $cache_sub_dir} files. - * - * SECURITY: This directory MUST be located inside the `/wp-content/` directory. - * Also, it MUST be a sub-directory of `/wp-content/`, NOT the directory itself. - * Also, it cannot be: `mu-plugins`, `themes`, or `plugins`. - * - * @return integer Total files wiped by this routine (if any). - * - * @throws \exception If a wipe failure occurs. - */ - public function wipe_cache($manually = FALSE, $also_wipe_dir = '') - { - $counter = 0; // Initialize. - - $also_wipe_dir = trim((string)$also_wipe_dir); - - @set_time_limit(1800); // @TODO When disabled, display a warning. - - if(is_dir($cache_dir = $this->cache_dir())) - $counter += $this->delete_all_files_dirs_in($cache_dir); - - if($also_wipe_dir && is_dir($also_wipe_dir)) // Also wipe another directory? - // This is called w/ version-specific upgrades. That's the only use at this time. - $counter += $this->delete_all_files_dirs_in($also_wipe_dir); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Clears cache files for the current host|blog. - * - * @since 140422 First documented version. - * - * @param boolean $manually Defaults to a `FALSE` value. - * Pass as TRUE if the clearing is done manually by the site owner. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clearing failure occurs. - */ - public function clear_cache($manually = FALSE) - { - $counter = 0; // Initialize. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - @set_time_limit(1800); // @TODO When disabled, display a warning. - - $regex = $this->build_host_cache_path_regex('', '.+'); - $counter += $this->clear_files_from_host_cache_dir($regex); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Purges expired cache files for the current host|blog. - * - * @since 140422 First documented version. - * - * @param boolean $manually Defaults to a `FALSE` value. - * Pass as TRUE if the purging is done manually by the site owner. - * - * @return integer Total files purged by this routine (if any). - * - * @attaches-to `'_cron_'.__NAMESPACE__.'_cleanup'` via CRON job. - * - * @throws \exception If a purge failure occurs. - */ - public function purge_cache($manually = FALSE) - { - $counter = 0; // Initialize. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - @set_time_limit(1800); // @TODO When disabled, display a warning. - - $regex = $this->build_host_cache_path_regex('', '.+'); - $counter += $this->purge_files_from_host_cache_dir($regex); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically wipes out all cache files in the cache directory. - * - * @since 140422 First documented version. - * - * @return integer Total files wiped by this routine (if any). - * - * @note Unlike many of the other `auto_` methods, this one is NOT currently attached to any hooks. - * This is called upon whenever QC options are saved and/or restored though. - */ - public function auto_wipe_cache() - { - $counter = 0; // Initialize. - - if(isset($this->cache[__FUNCTION__])) - return $counter; // Already did this. - $this->cache[__FUNCTION__] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - $counter += $this->wipe_cache(); - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected significant changes. Found %2$s in the cache; auto-wiping.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)))); - } - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears all cache files for the current blog. - * - * @attaches-to `switch_theme` hook. - * - * @attaches-to `wp_create_nav_menu` hook. - * @attaches-to `wp_update_nav_menu` hook. - * @attaches-to `wp_delete_nav_menu` hook. - * - * @attaches-to `create_term` hook. - * @attaches-to `edit_terms` hook. - * @attaches-to `delete_term` hook. - * - * @attaches-to `add_link` hook. - * @attaches-to `edit_link` hook. - * @attaches-to `delete_link` hook. - * - * @since 140422 First documented version. - * - * @return integer Total files cleared by this routine (if any). - * - * @note This is also called upon during plugin activation. - */ - public function auto_clear_cache() - { - $counter = 0; // Initialize. - - if(isset($this->cache[__FUNCTION__])) - return $counter; // Already did this. - $this->cache[__FUNCTION__] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - $counter += $this->clear_cache(); - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - $this->enqueue_notice(''. - sprintf(__('%1$s: detected important site changes. Found %2$s in the cache for this site; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)))); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for a particular post. - * - * @attaches-to `save_post` hook. - * @attaches-to `delete_post` hook. - * @attaches-to `clean_post_cache` hook. - * - * @since 140422 First documented version. - * - * @param integer $post_id A WordPress post ID. - * - * @param bool $force Defaults to a `FALSE` value. - * Pass as TRUE if clearing should be done for `draft`, `pending`, - * `future`, or `trash` post statuses. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note This is also called upon by other routines which listen for - * events that are indirectly associated with a post ID. - * - * @see auto_clear_comment_post_cache() - * @see auto_clear_post_cache_transition() - */ - public function auto_clear_post_cache($post_id, $force = FALSE) - { - $counter = 0; // Initialize. - - if(!($post_id = (integer)$post_id)) - return $counter; // Nothing to do. - - if(isset($this->cache[__FUNCTION__][$post_id][(integer)$force])) - return $counter; // Already did this. - $this->cache[__FUNCTION__][$post_id][(integer)$force] = -1; - - if(isset(static::$static['___allow_auto_clear_post_cache']) && static::$static['___allow_auto_clear_post_cache'] === FALSE) - { - static::$static['___allow_auto_clear_post_cache'] = TRUE; // Reset state. - return $counter; // Nothing to do. - } - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - if(!empty($this->pre_post_update_post_permalink[$post_id]) && ($permalink = $this->pre_post_update_post_permalink[$post_id])) - $this->pre_post_update_post_permalink[$post_id] = ''; // Reset; only used for post status transitions - elseif(!($permalink = get_permalink($post_id))) - return $counter; // Nothing we can do. - - if(!($post_status = get_post_status($post_id))) - return $counter; // Nothing to do. - - if($post_status === 'auto-draft') - return $counter; // Nothing to do. - - if($post_status === 'draft' && !$force) - return $counter; // Nothing to do. - - if($post_status === 'pending' && !$force) - return $counter; // Nothing to do. - - if($post_status === 'future' && !$force) - return $counter; // Nothing to do. - - if($post_status === 'trash' && !$force) - return $counter; // Nothing to do. - - if(($type = get_post_type($post_id)) && ($type = get_post_type_object($type)) && !empty($type->labels->singular_name)) - $type_singular_name = $type->labels->singular_name; // Singular name for the post type. - else $type_singular_name = __('Post', $this->text_domain); // Default value. - - $regex = $this->build_host_cache_path_regex($permalink); - $counter += $this->clear_files_from_host_cache_dir($regex); - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache for %3$s ID: %4$s; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)), esc_html($type_singular_name), esc_html($post_id))); - } - $counter += $this->auto_clear_xml_feeds_cache('blog'); - $counter += $this->auto_clear_xml_feeds_cache('post-terms', $post_id); - $counter += $this->auto_clear_xml_feeds_cache('post-authors', $post_id); - - $counter += $this->auto_clear_xml_sitemaps_cache(); - $counter += $this->auto_clear_home_page_cache(); - $counter += $this->auto_clear_posts_page_cache(); - $counter += $this->auto_clear_post_terms_cache($post_id, $force); - - // Also clear a possible custom post type archive view. - $counter += $this->auto_clear_custom_post_type_archive_cache($post_id); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for a particular post when transitioning - * from `publish` or `private` post status to `draft`, `future`, `private`, or `trash`. - * - * @attaches-to `pre_post_update` hook. - * - * @since 140605 First documented version. - * - * @param int $post_ID Post ID. - * @param array $data Array of unslashed post data. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note This is also called upon by other routines which listen for - * events that are indirectly associated with a post ID. - * - * @see auto_clear_post_cache() - */ - public function auto_clear_post_cache_transition($post_ID, $data) - { - $old_status = (string)get_post_status($post_ID); - $new_status = (string)$data['post_status']; - - /* - * When a post has a status of `pending` or `draft`, the `get_permalink()` function - * does not return a friendly permalink and therefore `auto_clear_post_cache()` will - * have no way of building a path to the cache file that should be cleared as part of - * this post status transition. To get around this, we temporarily store the permalink - * in $this->pre_post_update_post_permalink for `auto_clear_post_cache()` to use. - * - * See also: https://github.com/websharks/zencache/issues/441 - */ - if($old_status === 'publish' && in_array($data['post_status'], array('pending', 'draft', TRUE))) - $this->pre_post_update_post_permalink[$post_ID] = get_permalink($post_ID); - - $counter = 0; // Initialize. - - if(isset($this->cache[__FUNCTION__][$new_status][$old_status][$post_ID])) - return $counter; // Already did this. - $this->cache[__FUNCTION__][$new_status][$old_status][$post_ID] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if($old_status !== 'publish' && $old_status !== 'private') - return $counter; // Nothing to do. We MUST be transitioning FROM one of these statuses. - - if(in_array($new_status, array('draft', 'future', 'pending', 'private', 'trash'), TRUE)) - $counter = $this->auto_clear_post_cache($post_ID, TRUE); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files related to XML feeds. - * - * @since 140829 Working to improve compatibility with feeds. - * - * @param string $type Type of feed(s) to auto-clear. - * @param integer $post_id A Post ID (when applicable). - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note Unlike many of the other `auto_` methods, this one is NOT currently - * attached to any hooks. However, it is called upon by other routines attached to hooks. - */ - public function auto_clear_xml_feeds_cache($type, $post_id = 0) - { - $counter = 0; // Initialize. - - if(!($type = (string)$type)) - return $counter; // Nothing we can do. - $post_id = (integer)$post_id; // Force integer. - - if(isset($this->cache[__FUNCTION__][$type][$post_id])) - return $counter; // Already did this. - $this->cache[__FUNCTION__][$type][$post_id] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!$this->options['feeds_enable']) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - $variations = $variation_regex_frags = array(); // Initialize. - require_once dirname(__FILE__).'/includes/utils-feed.php'; - $utils = new utils_feed(); // Feed utilities. - - switch($type) // Handle clearing based on the `$type`. - { - case 'blog': // The blog feed; i.e. `/feed/` on most WP installs. - - $variations = array_merge($variations, $utils->feed_link_variations()); - break; // Break switch handler. - - case 'blog-comments': // The blog comments feed; i.e. `/comments/feed/` on most WP installs. - - $variations = array_merge($variations, $utils->feed_link_variations('comments_')); - break; // Break switch handler. - - case 'post-comments': // Feeds related to comments that a post has. - - if(!$post_id) break; // Nothing to do. - if(!($post = get_post($post_id))) break; - $variations = array_merge($variations, $utils->post_comments_feed_link_variations($post)); - break; // Break switch handler. - - case 'post-authors': // Feeds related to authors that a post has. - - if(!$post_id) break; // Nothing to do. - if(!($post = get_post($post_id))) break; - $variations = array_merge($variations, $utils->post_author_feed_link_variations($post)); - break; // Break switch handler. - - case 'post-terms': // Feeds related to terms that a post has. - - if(!$post_id) break; // Nothing to do. - if(!($post = get_post($post_id))) break; - $variations = array_merge($variations, $utils->post_term_feed_link_variations($post, TRUE)); - break; // Break switch handler. - - case 'custom-post-type': // Feeds related to a custom post type archive view. - - if(!$post_id) break; // Nothing to do. - if(!($post = get_post($post_id))) break; - $variations = array_merge($variations, $utils->post_type_archive_link_variations($post)); - break; // Break switch handler. - - // @TODO Possibly consider search-related feeds in the future. - // See: - } - $variation_regex_frags = $utils->convert_variations_to_host_cache_path_regex_frags($variations); - - if(!$variation_regex_frags // Have regex pattern variations? - || !($variation_regex_frags = array_unique($variation_regex_frags)) - ) return $counter; // Nothing to do here. - - $in_sets_of = $this->apply_wp_filters(__METHOD__.'__in_sets_of', 10, get_defined_vars()); - for($_i = 0; $_i < count($variation_regex_frags); $_i = $_i + $in_sets_of) - { - $_variation_regex_frags = array_slice($variation_regex_frags, $_i, $in_sets_of); - $_regex = '/^\/(?:'.implode('|', $_variation_regex_frags).')\./i'; - $counter += $this->clear_files_from_host_cache_dir($_regex); - } - unset($_i, $_variation_regex_frags, $_regex); // Housekeeping. - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache, for XML feeds of type: %3$s; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)), esc_html($type))); - } - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files related to XML sitemaps. - * - * @since 140725 Working to improve compatibility with sitemaps. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note Unlike many of the other `auto_` methods, this one is NOT currently - * attached to any hooks. However, it is called upon by {@link auto_clear_post_cache()}. - * - * @see auto_clear_post_cache() - */ - public function auto_clear_xml_sitemaps_cache() - { - $counter = 0; // Initialize. - - if(isset($this->cache[__FUNCTION__])) - return $counter; // Already did this. - $this->cache[__FUNCTION__] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - if(!($regex_frags = $this->build_host_cache_path_regex_frags_from_wc_uris('/sitemap*.xml', ''))) - return $counter; // There are no patterns to look for. - - $regex = $this->build_host_cache_path_regex('', '\/'.$regex_frags.'\.'); - $counter += $this->clear_files_from_host_cache_dir($regex); - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache for XML sitemaps; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)))); - } - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for the home page. - * - * @since 140422 First documented version. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note Unlike many of the other `auto_` methods, this one is NOT currently - * attached to any hooks. However, it is called upon by {@link auto_clear_post_cache()}. - * - * @see auto_clear_post_cache() - */ - public function auto_clear_home_page_cache() - { - $counter = 0; // Initialize. - - if(isset($this->cache[__FUNCTION__])) - return $counter; // Already did this. - $this->cache[__FUNCTION__] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!$this->options['cache_clear_home_page_enable']) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - $regex = $this->build_host_cache_path_regex(home_url('/')); - $counter += $this->clear_files_from_host_cache_dir($regex); - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache for the designated "Home Page"; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)))); - } - $counter += $this->auto_clear_xml_feeds_cache('blog'); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for the posts page. - * - * @since 140422 First documented version. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note Unlike many of the other `auto_` methods, this one is NOT currently - * attached to any hooks. However, it is called upon by {@link auto_clear_post_cache()}. - * - * @see auto_clear_post_cache() - */ - public function auto_clear_posts_page_cache() - { - $counter = 0; // Initialize. - - if(isset($this->cache[__FUNCTION__])) - return $counter; // Already did this. - $this->cache[__FUNCTION__] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!$this->options['cache_clear_posts_page_enable']) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - $show_on_front = get_option('show_on_front'); - $page_for_posts = get_option('page_for_posts'); - - if(!in_array($show_on_front, array('posts', 'page'), TRUE)) - return $counter; // Nothing we can do in this case. - - if($show_on_front === 'page' && !$page_for_posts) - return $counter; // Nothing we can do. - - if($show_on_front === 'posts') $posts_page = home_url('/'); - else if($show_on_front === 'page') $posts_page = get_permalink($page_for_posts); - if(empty($posts_page)) return $counter; // Nothing we can do. - - $regex = $this->build_host_cache_path_regex($posts_page); - $counter += $this->clear_files_from_host_cache_dir($regex); - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache for the designated "Posts Page"; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)))); - } - $counter += $this->auto_clear_xml_feeds_cache('blog'); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for a custom post type archive view. - * - * @since 140918 First documented version. - * - * @param integer $post_id A WordPress post ID. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note Unlike many of the other `auto_` methods, this one is NOT currently - * attached to any hooks. However, it is called upon by {@link auto_clear_post_cache()}. - * - * @see auto_clear_post_cache() - */ - public function auto_clear_custom_post_type_archive_cache($post_id) - { - $counter = 0; // Initialize. - - if(!($post_id = (integer)$post_id)) - return $counter; // Nothing to do. - - if(isset($this->cache[__FUNCTION__][$post_id])) - return $counter; // Already did this. - $this->cache[__FUNCTION__][$post_id] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - if(!($post_type = get_post_type($post_id))) - return $counter; // Nothing to do. - - if(!($all_custom_post_types = get_post_types(array('_builtin' => FALSE)))) - return $counter; // No custom post types. - - if(!in_array($post_type, array_keys($all_custom_post_types), TRUE)) - return $counter; // This is NOT a custom post type. - - if(!($custom_post_type = get_post_type_object($post_type))) - return $counter; // Unable to retrieve post type. - - if(empty($custom_post_type->labels->name) - || !($custom_post_type_name = $custom_post_type->labels->name) - ) $custom_post_type_name = __('Untitled', $this->text_domain); - - if(!($custom_post_type_archive_link = get_post_type_archive_link($post_type))) - return $counter; // Nothing to do; no link to work from in this case. - - $regex = $this->build_host_cache_path_regex($custom_post_type_archive_link); - $counter += $this->clear_files_from_host_cache_dir($regex); - - if($counter && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache for Custom Post Type: %3$s; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($counter)), esc_html($custom_post_type_name))); - } - $counter += $this->auto_clear_xml_feeds_cache('custom-post-type', $post_id); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for the author page(s). - * - * @attaches-to `post_updated` hook. - * - * @since 140605 First documented version. - * - * @param integer $post_id A WordPress post ID. - * @param \WP_Post $post_after WP_Post object following the update. - * @param \WP_Post $post_before WP_Post object before the update. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note If the author for the post is being changed, both the previous author - * and current author pages are cleared, if the post status is applicable. - */ - public function auto_clear_author_page_cache($post_id, \WP_Post $post_after, \WP_Post $post_before) - { - $counter = 0; // Initialize. - $enqueued_notices = 0; // Initialize. - $authors = array(); // Initialize. - $authors_to_clear = array(); // Initialize. - - if(!($post_id = (integer)$post_id)) - return $counter; // Nothing to do. - - if(isset($this->cache[__FUNCTION__][$post_id][$post_after->ID][$post_before->ID])) - return $counter; // Already did this. - $this->cache[__FUNCTION__][$post_id][$post_after->ID][$post_before->ID] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!$this->options['cache_clear_author_page_enable']) - return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - /* - * If we're changing the post author AND - * the previous post status was either 'published' or 'private' - * then clear the author page for both authors. - * - * Else if the old post status was 'published' or 'private' OR - * the new post status is 'published' or 'private' - * then clear the author page for the current author. - * - * Else return the counter; post status does not warrant clearing author page cache. - */ - if($post_after->post_author !== $post_before->post_author && - ($post_before->post_status === 'publish' || $post_before->post_status === 'private') - ) // Clear both authors in this case. - { - $authors[] = (integer)$post_before->post_author; - $authors[] = (integer)$post_after->post_author; - } - else if(($post_before->post_status === 'publish' || $post_before->post_status === 'private') || - ($post_after->post_status === 'publish' || $post_after->post_status === 'private') - ) - $authors[] = (integer)$post_after->post_author; - - if(!$authors) // Have no authors to clear? - return $counter; // Nothing to do. - - foreach($authors as $_author_id) // Get author posts URL and display name. - { - $authors_to_clear[$_author_id]['posts_url'] = get_author_posts_url($_author_id); - $authors_to_clear[$_author_id]['display_name'] = get_the_author_meta('display_name', $_author_id); - } - unset($_author_id); // Housekeeping. - - foreach($authors_to_clear as $_author) - { - $_author_regex = $this->build_host_cache_path_regex($_author['posts_url']); - $_author_counter = $this->clear_files_from_host_cache_dir($_author_regex); - $counter += $_author_counter; // Add to overall counter. - - if($_author_counter && $enqueued_notices < 100 && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache for Author Page: %3$s; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($_author_counter)), esc_html($_author['display_name']))); - $enqueued_notices++; // Increment enqueued notices counter. - } - } - unset($_author, $_author_regex, $_author_counter); // Housekeeping. - - $counter += $this->auto_clear_xml_feeds_cache('blog'); - $counter += $this->auto_clear_xml_feeds_cache('post-authors', $post_id); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for terms associated with a post. - * - * @attaches-to `added_term_relationship` hook. - * @attaches-to `delete_term_relationships` hook. - * - * @since 140605 First documented version. - * - * @param integer $post_id A WordPress post ID. - * - * @param bool $force Defaults to a `FALSE` value. - * Pass as TRUE if clearing should be done for `draft`, `pending`, - * or `future` post statuses. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note In addition to the hooks this is attached to, it is also - * called upon by {@link auto_clear_post_cache()}. - * - * @see auto_clear_post_cache() - */ - public function auto_clear_post_terms_cache($post_id, $force = FALSE) - { - $counter = 0; // Initialize. - $enqueued_notices = 0; // Initialize. - - if(!($post_id = (integer)$post_id)) - return $counter; // Nothing to do. - - if(isset($this->cache[__FUNCTION__][$post_id][(integer)$force])) - return $counter; // Already did this. - $this->cache[__FUNCTION__][$post_id][(integer)$force] = -1; - - if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) - return $counter; // Nothing to do. - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!$this->options['cache_clear_term_category_enable'] && - !$this->options['cache_clear_term_post_tag_enable'] && - !$this->options['cache_clear_term_other_enable'] - ) return $counter; // Nothing to do. - - if(!is_dir($cache_dir = $this->cache_dir())) - return $counter; // Nothing to do. - - $post_status = get_post_status($post_id); // Cache this. - - if($post_status === 'draft' && isset($GLOBALS['pagenow'], $_POST['publish']) - && is_admin() && $GLOBALS['pagenow'] === 'post.php' && current_user_can('publish_posts') - && strpos(wp_get_referer(), '/post-new.php') !== FALSE - ) $post_status = 'publish'; // A new post being published now. - - if($post_status === 'auto-draft') - return $counter; // Nothing to do. - - if($post_status === 'draft' && !$force) - return $counter; // Nothing to do. - - if($post_status === 'pending' && !$force) - return $counter; // Nothing to do. - - if($post_status === 'future' && !$force) - return $counter; // Nothing to do. - /* - * Build an array of available taxonomies for this post (as taxonomy objects). - */ - $taxonomies = get_object_taxonomies(get_post($post_id), 'objects'); - - if(!is_array($taxonomies)) // No taxonomies? - return $counter; // Nothing to do. - /* - * Build an array of terms associated with this post for each taxonomy. - * Also save taxonomy label information for Dashboard messaging later. - */ - $terms = array(); - $taxonomy_labels = array(); - - foreach($taxonomies as $_taxonomy) - { - if( // Check if this is a taxonomy/term that we should clear. - ($_taxonomy->name === 'category' && !$this->options['cache_clear_term_category_enable']) - || ($_taxonomy->name === 'post_tag' && !$this->options['cache_clear_term_post_tag_enable']) - || ($_taxonomy->name !== 'category' && $_taxonomy->name !== 'post_tag' && !$this->options['cache_clear_term_other_enable']) - ) continue; // Continue; nothing to do for this taxonomy. - - if(is_array($_terms = wp_get_post_terms($post_id, $_taxonomy->name))) - { - $terms = array_merge($terms, $_terms); - - // Improve Dashboard messaging by getting the Taxonomy label (e.g., "Tag" instead of "post_tag") - // If we don't have a Singular Name for this taxonomy, use the taxonomy name itself - if(empty($_taxonomy->labels->singular_name) || $_taxonomy->labels->singular_name === '') - $taxonomy_labels[$_taxonomy->name] = $_taxonomy->name; - else - $taxonomy_labels[$_taxonomy->name] = $_taxonomy->labels->singular_name; - } - } - unset($_taxonomy, $_terms); - - if(empty($terms)) // No taxonomy terms? - return $counter; // Nothing to do. - /* - * Build an array of terms with term names, - * permalinks, and associated taxonomy labels. - */ - $terms_to_clear = array(); - $_i = 0; - - foreach($terms as $_term) - { - if(($_link = get_term_link($_term))) - { - $terms_to_clear[$_i]['permalink'] = $_link; // E.g., "http://jason.websharks-inc.net/category/uncategorized/" - $terms_to_clear[$_i]['term_name'] = $_term->name; // E.g., "Uncategorized" - if(!empty($taxonomy_labels[$_term->taxonomy])) // E.g., "Tag" or "Category" - $terms_to_clear[$_i]['taxonomy_label'] = $taxonomy_labels[$_term->taxonomy]; - else - $terms_to_clear[$_i]['taxonomy_label'] = $_term->taxonomy; // e.g., "post_tag" or "category" - } - $_i++; // Array index counter. - } - unset($_term, $_link, $_i); - - if(empty($terms_to_clear)) - return $counter; // Nothing to do. - - foreach($terms_to_clear as $_term) - { - $_term_regex = $this->build_host_cache_path_regex($_term['permalink']); - $_term_counter = $this->clear_files_from_host_cache_dir($_term_regex); - $counter += $_term_counter; // Add to overall counter. - - if($_term_counter && $enqueued_notices < 100 && is_admin() /* && $this->options['change_notifications_enable'] */) - { - $this->enqueue_notice(''. - sprintf(__('%1$s: detected changes. Found %2$s in the cache for %3$s: %4$s; auto-clearing.', $this->text_domain), - esc_html($this->name), esc_html($this->i18n_files($_term_counter)), esc_html($_term['taxonomy_label']), esc_html($_term['term_name']))); - $enqueued_notices++; // Increment enqueued notices counter. - } - } - unset($_term, $_term_regex, $_term_counter); // Housekeeping. - - $counter += $this->auto_clear_xml_feeds_cache('post-terms', $post_id); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for a post associated with a particular comment. - * - * @since 140422 First documented version. - * - * @attaches-to `trackback_post` hook. - * @attaches-to `pingback_post` hook. - * @attaches-to `comment_post` hook. - * - * @param integer $comment_id A WordPress comment ID. - * - * @return integer Total files cleared by this routine (if any). - * - * @see auto_clear_post_cache() - */ - public function auto_clear_comment_post_cache($comment_id) - { - $counter = 0; // Initialize. - - if(!($comment_id = (integer)$comment_id)) - return $counter; // Nothing to do. - - if(isset($this->cache[__FUNCTION__][$comment_id])) - return $counter; // Already did this. - $this->cache[__FUNCTION__][$comment_id] = -1; - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!is_object($comment = get_comment($comment_id))) - return $counter; // Nothing we can do. - - if(empty($comment->comment_post_ID)) - return $counter; // Nothing we can do. - - if($comment->comment_approved === 'spam' || $comment->comment_approved === '0') - // Don't allow next `auto_clear_post_cache()` call to clear post cache. - // Also, don't allow spam to clear cache. - { - static::$static['___allow_auto_clear_post_cache'] = FALSE; - return $counter; // Nothing to do here. - } - $counter += $this->auto_clear_xml_feeds_cache('blog-comments'); - $counter += $this->auto_clear_xml_feeds_cache('post-comments', $comment->comment_post_ID); - $counter += $this->auto_clear_post_cache($comment->comment_post_ID); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears cache files for a post associated with a particular comment. - * - * @since 140711 First documented version. - * - * @attaches-to `transition_comment_status` hook. - * - * @param string $new_status New comment status. - * @param string $old_status Old comment status. - * @param \WP_Post $comment Comment object. - * - * @return integer Total files cleared by this routine (if any). - * - * @throws \exception If a clear failure occurs. - * - * @note This is also called upon by other routines which listen for - * events that are indirectly associated with a comment ID. - * - * @see auto_clear_comment_post_cache() - */ - public function auto_clear_comment_transition($new_status, $old_status, $comment) - { - $counter = 0; // Initialize. - - if(!$this->options['enable']) - return $counter; // Nothing to do. - - if(!is_object($comment)) - return $counter; // Nothing we can do. - - if(empty($comment->comment_post_ID)) - return $counter; // Nothing we can do. - - if(!($old_status === 'approved' || ($old_status === 'unapproved' && $new_status === 'approved'))) - // If excluded here, don't allow next `auto_clear_post_cache()` call to clear post cache. - { - static::$static['___allow_auto_clear_post_cache'] = FALSE; - return $counter; // Nothing to do here. - } - $counter += $this->auto_clear_xml_feeds_cache('blog-comments'); - $counter += $this->auto_clear_xml_feeds_cache('post-comments', $comment->comment_post_ID); - $counter += $this->auto_clear_post_cache($comment->comment_post_ID); - - return $this->apply_wp_filters(__METHOD__, $counter, get_defined_vars()); - } - - /** - * Automatically clears all cache files for current blog under various conditions; - * used to check for conditions that don't have a hook that we can attach to. - * - * @since 140922 First documented version. - * - * @attaches-to `admin_init` hook. - * - * @see auto_clear_cache() - */ - public function maybe_auto_clear_cache() - { - $_pagenow = $GLOBALS['pagenow']; - if(isset($this->cache[__FUNCTION__][$_pagenow])) - return; // Already did this. - $this->cache[__FUNCTION__][$_pagenow] = -1; - - // If Dashboard → Settings → General options are updated - if($GLOBALS['pagenow'] === 'options-general.php' && !empty($_REQUEST['settings-updated'])) - $this->auto_clear_cache(); - - // If Dashboard → Settings → Reading options are updated - if($GLOBALS['pagenow'] === 'options-reading.php' && !empty($_REQUEST['settings-updated'])) - $this->auto_clear_cache(); - - // If Dashboard → Settings → Discussion options are updated - if($GLOBALS['pagenow'] === 'options-discussion.php' && !empty($_REQUEST['settings-updated'])) - $this->auto_clear_cache(); - - // If Dashboard → Settings → Permalink options are updated - if($GLOBALS['pagenow'] === 'options-permalink.php' && !empty($_REQUEST['settings-updated'])) - $this->auto_clear_cache(); - } - - /** - * Automatically clears all cache files for current blog when JetPack Custom CSS is saved. - * - * @since 140919 First documented version. - * - * @attaches-to `safecss_save_pre` hook. - * - * @param array $args Args passed in by hook. - * - * @see auto_clear_cache() - */ - public function jetpack_custom_css($args) - { - if(class_exists('\\Jetpack') && empty($args['is_preview'])) - $this->auto_clear_cache(); - } - - /** - * Automatically clears all cache files for current blog when WordPress core, or an active component, is upgraded. - * - * @since 141001 Clearing the cache on WP upgrades. - * - * @attaches-to `upgrader_process_complete` hook. - * - * @param \WP_Upgrader $upgrader_instance An instance of \WP_Upgrader. - * Or, any class that extends \WP_Upgrader. - * - * @param array $data Array of bulk item update data. - * - * This array may include one or more of the following keys: - * - * - `string` `$action` Type of action. Default 'update'. - * - `string` `$type` Type of update process; e.g. 'plugin', 'theme', 'core'. - * - `boolean` `$bulk` Whether the update process is a bulk update. Default true. - * - `array` `$packages` Array of plugin, theme, or core packages to update. - * - * @see auto_clear_cache() - */ - public function upgrader_process_complete(\WP_Upgrader $upgrader_instance, array $data) - { - switch(!empty($data['type']) ? $data['type'] : '') - { - case 'plugin': // Plugin upgrade. - - /** @var $skin \Plugin_Upgrader_Skin * */ - $skin = $upgrader_instance->skin; - $multi_plugin_update = $single_plugin_update = FALSE; - $upgrading_active_plugin = FALSE; // Initialize. - - if(!empty($data['bulk']) && !empty($data['plugins']) && is_array($data['plugins'])) - $multi_plugin_update = TRUE; - - else if(!empty($data['plugin']) && is_string($data['plugin'])) - $single_plugin_update = TRUE; - - if($multi_plugin_update) - { - foreach($data['plugins'] as $_plugin) - if($_plugin && is_string($_plugin) && is_plugin_active($_plugin)) - { - $upgrading_active_plugin = TRUE; - break; // Got what we need here. - } - unset($_plugin); // Housekeeping. - } - else if($single_plugin_update && $skin->plugin_active == TRUE) - $upgrading_active_plugin = TRUE; - - if($upgrading_active_plugin) - $this->auto_clear_cache(); // Yes, clear the cache. - - break; // Break switch. - - case 'theme': // Theme upgrade. - - $current_active_theme = wp_get_theme(); - $current_active_theme_parent = $current_active_theme->parent(); - $multi_theme_update = $single_theme_update = FALSE; - $upgrading_active_parent_theme = $upgrading_active_theme = FALSE; - - if(!empty($data['bulk']) && !empty($data['themes']) && is_array($data['themes'])) - $multi_theme_update = TRUE; - - else if(!empty($data['theme']) && is_string($data['theme'])) - $single_theme_update = TRUE; - - if($multi_theme_update) - { - foreach($data['themes'] as $_theme) - { - if(!$_theme || !is_string($_theme) || !($_theme_obj = wp_get_theme($_theme))) - continue; // Unable to acquire theme object instance. - - if($current_active_theme_parent && $current_active_theme_parent->get_stylesheet() === $_theme_obj->get_stylesheet()) - { - $upgrading_active_parent_theme = TRUE; - break; // Got what we needed here. - } - else if($current_active_theme->get_stylesheet() === $_theme_obj->get_stylesheet()) - { - $upgrading_active_theme = TRUE; - break; // Got what we needed here. - } - } - unset($_theme, $_theme_obj); // Housekeeping. - } - else if($single_theme_update && ($_theme_obj = wp_get_theme($data['theme']))) - { - if($current_active_theme_parent && $current_active_theme_parent->get_stylesheet() === $_theme_obj->get_stylesheet()) - $upgrading_active_parent_theme = TRUE; - - else if($current_active_theme->get_stylesheet() === $_theme_obj->get_stylesheet()) - $upgrading_active_theme = TRUE; - } - unset($_theme_obj); // Housekeeping. - - if($upgrading_active_theme || $upgrading_active_parent_theme) - $this->auto_clear_cache(); // Yes, clear the cache. - - break; // Break switch. - - case 'core': // Core upgrade. - default: // Or any other sort of upgrade. - - $this->auto_clear_cache(); // Yes, clear the cache. - - break; // Break switch. - } - } - - /** - * This constructs an absolute server directory path (no trailing slashes); - * which is always nested into {@link \WP_CONTENT_DIR} and the configured `base_dir` option value. - * - * @since 140605 Moving to a base directory structure. - * - * @param string $rel_dir_file A sub-directory or file; relative location please. - * - * @return string The full absolute server path to `$rel_dir_file`. - * - * @throws \exception If `base_dir` is empty when this method is called upon; - * i.e. if you attempt to call upon this method before {@link setup()} runs. - */ - public function wp_content_base_dir_to($rel_dir_file) - { - $rel_dir_file = trim((string)$rel_dir_file, '\\/'." \t\n\r\0\x0B"); - - if(empty($this->options) || !is_array($this->options) || empty($this->options['base_dir'])) - throw new \exception(__('Doing it wrong! Missing `base_dir` option value. MUST call this method after `setup()`.', $this->text_domain)); - - $wp_content_base_dir_to = WP_CONTENT_DIR.'/'.$this->options['base_dir']; - - if(isset($rel_dir_file[0])) // Do we have this also? - $wp_content_base_dir_to .= '/'.$rel_dir_file; - - return $this->apply_wp_filters(__METHOD__, $wp_content_base_dir_to, get_defined_vars()); - } - - /** - * This constructs a relative/base directory path (no leading/trailing slashes). - * Always relative to {@link \WP_CONTENT_DIR}. Depends on the configured `base_dir` option value. - * - * @since 140605 Moving to a base directory structure. - * - * @param string $rel_dir_file A sub-directory or file; relative location please. - * - * @return string The relative/base directory path to `$rel_dir_file`. - * - * @throws \exception If `base_dir` is empty when this method is called upon; - * i.e. if you attempt to call upon this method before {@link setup()} runs. - */ - public function base_path_to($rel_dir_file) - { - $rel_dir_file = trim((string)$rel_dir_file, '\\/'." \t\n\r\0\x0B"); - - if(empty($this->options) || !is_array($this->options) || empty($this->options['base_dir'])) - throw new \exception(__('Doing it wrong! Missing `base_dir` option value. MUST call this method after `setup()`.', $this->text_domain)); - - $base_path_to = $this->options['base_dir']; - - if(isset($rel_dir_file[0])) // Do we have this also? - $base_path_to .= '/'.$rel_dir_file; - - return $this->apply_wp_filters(__METHOD__, $base_path_to, get_defined_vars()); - } - - /** - * Adds `define('WP_CACHE', TRUE);` to the `/wp-config.php` file. - * - * @since 140422 First documented version. - * - * @return string The new contents of the updated `/wp-config.php` file; - * else an empty string if unable to add the `WP_CACHE` constant. - */ - public function add_wp_cache_to_wp_config() - { - if(!$this->options['enable']) - return ''; // Nothing to do. - - if(!($wp_config_file = $this->find_wp_config_file())) - return ''; // Unable to find `/wp-config.php`. - - if(!is_readable($wp_config_file)) return ''; // Not possible. - if(!($wp_config_file_contents = file_get_contents($wp_config_file))) - return ''; // Failure; could not read file. - - if(preg_match('/define\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:\-?[1-9][0-9\.]*|TRUE|([\'"])(?:[^0\'"]|[^\'"]{2,})\\2)\s*\)\s*;/i', $wp_config_file_contents)) - return $wp_config_file_contents; // It's already in there; no need to modify this file. - - if(!($wp_config_file_contents = $this->remove_wp_cache_from_wp_config())) - return ''; // Unable to remove previous value. - - if(!($wp_config_file_contents = preg_replace('/^\s*(\<\?php|\<\?)\s+/i', '${1}'."\n"."define('WP_CACHE', TRUE);"."\n", $wp_config_file_contents, 1))) - return ''; // Failure; something went terribly wrong here. - - if(strpos($wp_config_file_contents, "define('WP_CACHE', TRUE);") === FALSE) - return ''; // Failure; unable to add; unexpected PHP code. - - if(defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) - return ''; // We may NOT edit any files. - - if(!is_writable($wp_config_file)) return ''; // Not possible. - if(!file_put_contents($wp_config_file, $wp_config_file_contents)) - return ''; // Failure; could not write changes. - - return $this->apply_wp_filters(__METHOD__, $wp_config_file_contents, get_defined_vars()); - } - - /** - * Removes `define('WP_CACHE', TRUE);` from the `/wp-config.php` file. - * - * @since 140422 First documented version. - * - * @return string The new contents of the updated `/wp-config.php` file; - * else an empty string if unable to remove the `WP_CACHE` constant. - */ - public function remove_wp_cache_from_wp_config() - { - if(!($wp_config_file = $this->find_wp_config_file())) - return ''; // Unable to find `/wp-config.php`. - - if(!is_readable($wp_config_file)) return ''; // Not possible. - if(!($wp_config_file_contents = file_get_contents($wp_config_file))) - return ''; // Failure; could not read file. - - if(!preg_match('/([\'"])WP_CACHE\\1/i', $wp_config_file_contents)) - return $wp_config_file_contents; // Already gone. - - if(preg_match('/define\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:0|FALSE|NULL|([\'"])0?\\2)\s*\)\s*;/i', $wp_config_file_contents)) - return $wp_config_file_contents; // It's already disabled; no need to modify this file. - - if(!($wp_config_file_contents = preg_replace('/define\s*\(\s*([\'"])WP_CACHE\\1\s*,\s*(?:\-?[0-9\.]+|TRUE|FALSE|NULL|([\'"])[^\'"]*\\2)\s*\)\s*;/i', '', $wp_config_file_contents))) - return ''; // Failure; something went terribly wrong here. - - if(preg_match('/([\'"])WP_CACHE\\1/i', $wp_config_file_contents)) - return ''; // Failure; perhaps the `/wp-config.php` file contains syntax we cannot remove safely. - - if(defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) - return ''; // We may NOT edit any files. - - if(!is_writable($wp_config_file)) return ''; // Not possible. - if(!file_put_contents($wp_config_file, $wp_config_file_contents)) - return ''; // Failure; could not write changes. - - return $this->apply_wp_filters(__METHOD__, $wp_config_file_contents, get_defined_vars()); - } - - /** - * Checks to make sure the `zc-advanced-cache` file still exists; - * and if it doesn't, the `advanced-cache.php` is regenerated automatically. - * - * @since 140422 First documented version. - * - * @attaches-to `init` hook. - * - * @note This runs so that remote deployments which completely wipe out an - * existing set of website files (like the AWS Elastic Beanstalk does) will NOT cause ZenCache - * to stop functioning due to the lack of an `advanced-cache.php` file, which is generated by ZenCache. - * - * For instance, if you have a Git repo with all of your site files; when you push those files - * to your website to deploy them, you most likely do NOT have the `advanced-cache.php` file. - * ZenCache creates this file on its own. Thus, if it's missing (and QC is active) - * we simply regenerate the file automatically to keep ZenCache running. - */ - public function check_advanced_cache() - { - if(!$this->options['enable']) - return; // Nothing to do. - - if(!empty($_REQUEST[__NAMESPACE__])) - return; // Skip on plugin actions. - - $cache_dir = $this->cache_dir(); // Current cache directory. - $advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php'; - - // Fixes zero-byte advanced-cache.php bug related to migrating from Quick Cache - // See https://github.com/websharks/zencache/issues/432 - // Also fixes a missing define('WP_CACHE', TRUE) bug related to migrating from Quick Cache - // See https://github.com/websharks/zencache/issues/450 - if(!is_file($cache_dir.'/zc-advanced-cache') - || !is_file($advanced_cache_file) || filesize($advanced_cache_file) === 0 - ) - { - $this->add_advanced_cache(); - $this->add_wp_cache_to_wp_config(); - } - } - - /** - * Creates and adds the `advanced-cache.php` file. - * - * @since 140422 First documented version. - * - * @note Many of the ZenCache option values become PHP Constants in the `advanced-cache.php` file. - * We take an option key (e.g. `version_salt`) and prefix it with `zencache_`. - * Then we convert it to uppercase (e.g. `ZENCACHE_VERSION_SALT`) and wrap - * it with double percent signs to form a replacement codes. - * ex: `%%ZENCACHE_VERSION_SALT%%` - * - * @note There are a few special options considered by this routine which actually - * get converted to regex patterns before they become replacement codes. - * - * @note In the case of a version salt, a PHP syntax is performed also. - * - * @return boolean|null `TRUE` on success. `FALSE` or `NULL` on failure. - * A special `NULL` return value indicates success with a single failure - * that is specifically related to the `zc-advanced-cache` file. - */ - public function add_advanced_cache() - { - if(!$this->remove_advanced_cache()) - return FALSE; // Still exists. - - $cache_dir = $this->cache_dir(); - $advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php'; - $advanced_cache_template = dirname(__FILE__).'/includes/advanced-cache.tpl.php'; - - if(is_file($advanced_cache_file) && !is_writable($advanced_cache_file)) - return FALSE; // Not possible to create. - - if(!is_file($advanced_cache_file) && !is_writable(dirname($advanced_cache_file))) - return FALSE; // Not possible to create. - - if(!is_file($advanced_cache_template) || !is_readable($advanced_cache_template)) - return FALSE; // Template file is missing; or not readable. - - if(!($advanced_cache_contents = file_get_contents($advanced_cache_template))) - return FALSE; // Template file is missing; or is not readable. - - $possible_advanced_cache_constant_key_values = array_merge( - $this->options, // The following additional keys are dynamic. - array('cache_dir' => $this->base_path_to($this->cache_sub_dir) - )); - foreach($possible_advanced_cache_constant_key_values as $_option => $_value) - { - $_value = (string)$_value; // Force string. - - switch($_option) // Some values need tranformations. - { - default: // Default case handler. - - $_value = "'".$this->esc_sq($_value)."'"; - - break; // Break switch handler. - } - $advanced_cache_contents = // Fill replacement codes. - str_ireplace(array("'%%".__NAMESPACE__.'_'.$_option."%%'", - "'%%".__NAMESPACE__.'_'.preg_replace('/^cache_/i', '', $_option)."%%'"), - $_value, $advanced_cache_contents); - } - unset($_option, $_value, $_values, $_response); // Housekeeping. - - if(strpos($this->file, WP_CONTENT_DIR) === 0) - $plugin_file = "WP_CONTENT_DIR.'".$this->esc_sq(str_replace(WP_CONTENT_DIR, '', $this->file))."'"; - else $plugin_file = "'".$this->esc_sq($this->file)."'"; // Else use full absolute path. - // Make it possible for the `advanced-cache.php` handler to find the plugin directory reliably. - $advanced_cache_contents = str_ireplace("'%%".__NAMESPACE__."_PLUGIN_FILE%%'", $plugin_file, $advanced_cache_contents); - - // Ignore; this is created by ZenCache; and we don't need to obey in this case. - #if(defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) - # return FALSE; // We may NOT edit any files. - - if(!file_put_contents($advanced_cache_file, $advanced_cache_contents)) - return FALSE; // Failure; could not write file. - - $cache_lock = $this->cache_lock(); // Lock cache. - - if(!is_dir($cache_dir)) mkdir($cache_dir, 0775, TRUE); - - if(is_writable($cache_dir) && !is_file($cache_dir.'/.htaccess')) - file_put_contents($cache_dir.'/.htaccess', $this->htaccess_deny); - - if(!is_dir($cache_dir) || !is_writable($cache_dir) || !is_file($cache_dir.'/.htaccess') || !file_put_contents($cache_dir.'/zc-advanced-cache', time())) - { - $this->cache_unlock($cache_lock); // Unlock cache. - return NULL; // Special return value (NULL) in this case. - } - $this->cache_unlock($cache_lock); // Unlock cache. - - return TRUE; // Success! - } - - /** - * Removes the `advanced-cache.php` file. - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` on success. `FALSE` on failure. - * - * @note The `advanced-cache.php` file is NOT actually deleted by this routine. - * Instead of deleting the file, we simply empty it out so that it's `0` bytes in size. - * - * The reason for this is to preserve any file permissions set by the site owner. - * If the site owner previously allowed this specific file to become writable, we don't want to - * lose that permission by deleting the file; forcing the site owner to do it all over again later. - * - * An example of where this is useful is when a site owner deactivates the QC plugin, - * but later they decide that QC really is the most awesome plugin in the world and they turn it back on. - * - * @see delete_advanced_cache() - */ - public function remove_advanced_cache() - { - $advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php'; - - if(!is_file($advanced_cache_file)) return TRUE; // Already gone. - - if(is_readable($advanced_cache_file) && filesize($advanced_cache_file) === 0) - return TRUE; // Already gone; i.e. it's empty already. - - if(!is_writable($advanced_cache_file)) return FALSE; // Not possible. - - // Ignore; this is created by ZenCache; and we don't need to obey in this case. - #if(defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) - # return FALSE; // We may NOT edit any files. - - /* Empty the file only. This way permissions are NOT lost in cases where - a site owner makes this specific file writable for ZenCache. */ - if(file_put_contents($advanced_cache_file, '') !== 0) - return FALSE; // Failure. - - return TRUE; // Removal success. - } - - /** - * Deletes the `advanced-cache.php` file. - * - * @since 140422 First documented version. - * - * @return boolean `TRUE` on success. `FALSE` on failure. - * - * @note The `advanced-cache.php` file is deleted by this routine. - * - * @see remove_advanced_cache() - */ - public function delete_advanced_cache() - { - $advanced_cache_file = WP_CONTENT_DIR.'/advanced-cache.php'; - - if(!is_file($advanced_cache_file)) return TRUE; // Already gone. - - // Ignore; this is created by ZenCache; and we don't need to obey in this case. - #if(defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) - # return FALSE; // We may NOT edit any files. - - if(!is_writable($advanced_cache_file) || !unlink($advanced_cache_file)) - return FALSE; // Not possible; or outright failure. - - return TRUE; // Deletion success. - } - - /** - * Checks to make sure the `zc-blog-paths` file still exists; - * and if it doesn't, the `zc-blog-paths` file is regenerated automatically. - * - * @since 140422 First documented version. - * - * @attaches-to `init` hook. - * - * @note This runs so that remote deployments which completely wipe out an - * existing set of website files (like the AWS Elastic Beanstalk does) will NOT cause ZenCache - * to stop functioning due to the lack of a `zc-blog-paths` file, which is generated by ZenCache. - * - * For instance, if you have a Git repo with all of your site files; when you push those files - * to your website to deploy them, you most likely do NOT have the `zc-blog-paths` file. - * ZenCache creates this file on its own. Thus, if it's missing (and QC is active) - * we simply regenerate the file automatically to keep ZenCache running. - */ - public function check_blog_paths() - { - if(!$this->options['enable']) - return; // Nothing to do. - - if(!is_multisite()) return; // N/A. - - if(!empty($_REQUEST[__NAMESPACE__])) - return; // Skip on plugin actions. - - $cache_dir = $this->cache_dir(); // Current cache directory. - - if(!is_file($cache_dir.'/zc-blog-paths')) - $this->update_blog_paths(); - } - - /** - * Creates and/or updates the `zc-blog-paths` file. - * - * @since 140422 First documented version. - * - * @attaches-to `enable_live_network_counts` filter. - * - * @param mixed $enable_live_network_counts Optional, defaults to a `NULL` value. - * - * @return mixed The value of `$enable_live_network_counts` (passes through). - * - * @note While this routine is attached to a WP filter, we also call upon it directly at times. - */ - public function update_blog_paths($enable_live_network_counts = NULL) - { - $value = // This hook actually rides on a filter. - $enable_live_network_counts; // Filter value. - - if(!$this->options['enable']) - return $value; // Nothing to do. - - if(!is_multisite()) return $value; // N/A. - - $cache_dir = $this->cache_dir(); // Cache dir. - $cache_lock = $this->cache_lock(); // Lock. - - if(!is_dir($cache_dir)) mkdir($cache_dir, 0775, TRUE); - - if(is_writable($cache_dir) && !is_file($cache_dir.'/.htaccess')) - file_put_contents($cache_dir.'/.htaccess', $this->htaccess_deny); - - if(is_dir($cache_dir) && is_writable($cache_dir)) - { - $paths = // Collect child blog paths from the WordPress database. - $this->wpdb()->get_col("SELECT `path` FROM `".esc_sql($this->wpdb()->blogs)."` WHERE `deleted` <= '0'"); - - foreach($paths as &$_path) // Strip base; these need to match `$host_dir_token`. - $_path = '/'.ltrim(preg_replace('/^'.preg_quote($this->host_base_token(), '/').'/', '', $_path), '/'); - unset($_path); // Housekeeping. - - file_put_contents($cache_dir.'/zc-blog-paths', serialize($paths)); - } - $this->cache_unlock($cache_lock); // Unlock cache directory. - - return $value; // Pass through untouched (always). - } - - /** - * Removes the entire base directory. - * - * @since 140422 First documented version. - * - * @return integer Total files removed by this routine (if any). - */ - public function remove_base_dir() - { - $counter = 0; // Initialize. - - @set_time_limit(1800); // @TODO When disabled, display a warning. - - return ($counter += $this->delete_all_files_dirs_in($this->wp_content_base_dir_to(''), TRUE)); - } - } - - /** - * Used internally by other ZenCache classes as an easy way to reference - * the core {@link plugin} class instance for ZenCache. - * - * @since 140422 First documented version. - * - * @return plugin Class instance. - */ - function plugin() // Easy reference. - { - return $GLOBALS[__NAMESPACE__]; - } - - /** - * A global reference to the ZenCache plugin. - * - * @since 140422 First documented version. - * - * @var plugin Main plugin class. - */ - if(!isset($GLOBALS[__NAMESPACE__.'_autoload_plugin']) || $GLOBALS[__NAMESPACE__.'_autoload_plugin']) - $GLOBALS[__NAMESPACE__] = $GLOBALS['quick_cache'] = new plugin(); // Load plugin automatically. - require_once dirname(__FILE__).'/includes/api-class.php'; // API class. - } - else if(!empty($GLOBALS[__NAMESPACE__.'_conflicting_plugin']) && empty($GLOBALS[__NAMESPACE__.'_uninstalling'])) add_action('all_admin_notices', function () - { - if(!empty($GLOBALS[__NAMESPACE__.'_conflicting_plugin_lite_pro'])) - return; // Already detected this in one plugin or the other. - - $construct_name = function ($slug_or_ns) - { - $slug_or_ns = trim(strtolower((string)$slug_or_ns)); - - if(preg_match('/^'.preg_quote(__NAMESPACE__, '/').'[_\-]pro$/', $slug_or_ns)) - $slug_or_ns = strtolower(__NAMESPACE__); // Strip `-pro` suffix. - - $name = preg_replace('/[^a-z0-9]/', ' ', $slug_or_ns); - $name = str_replace('cache', 'Cache', ucwords($name)); - - return $name; // e.g. `x-cache` becomes `X Cache`. - }; - $text_domain = str_replace('_', '-', __NAMESPACE__); - $conflicting_plugin_name = $construct_name($GLOBALS[__NAMESPACE__.'_conflicting_plugin']); - $plugin_name = $construct_name(__NAMESPACE__); // e.g. `zencache` becomes `ZenCache`. - - if(strcasecmp($conflicting_plugin_name, $plugin_name) === 0) // Conflict between lite/pro editions? - { - $conflicting_plugin_name = $plugin_name.' '.__('Lite', $text_domain); - $plugin_name = $plugin_name.' '.__('Pro', $text_domain); - - $GLOBALS[__NAMESPACE__.'_conflicting_plugin_lite_pro'] = TRUE; - } - echo '
'. - '

'. // Running multiple versions of this plugin at same time. - ' '.sprintf(__('%1$s is NOT running. A conflicting plugin, %2$s, is currently active. Please deactivate the %2$s plugin to clear this message.', $text_domain), esc_html($plugin_name), esc_html($conflicting_plugin_name)). - '

'. - '
'; - }); -} \ No newline at end of file diff --git a/zencache/zencache.php b/zencache/zencache.php deleted file mode 100644 index 42638e0..0000000 --- a/zencache/zencache.php +++ /dev/null @@ -1,20 +0,0 @@ -
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo ''."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - if(!empty($_REQUEST[__NAMESPACE__.'__updated'])) // Options updated successfully? - { - echo '
'."\n"; - echo ' '.__('Options updated successfully.', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'__restored'])) // Restored default options? - { - echo '
'."\n"; - echo ' '.__('Default options successfully restored.', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'__cache_wiped'])) - { - echo '
'."\n"; - echo ' '.__('Cache wiped across all sites; recreation will occur automatically over time.', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'__cache_cleared'])) - { - echo '
'."\n"; - echo ' '.__('Cache cleared for this site; recreation will occur automatically over time.', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'__wp_config_wp_cache_add_failure'])) - { - echo '
'."\n"; - echo ' '.__('Failed to update your /wp-config.php file automatically. Please add the following line to your /wp-config.php file (right after the opening <?php tag; on it\'s own line).
<?php
define(\'WP_CACHE\', TRUE);
', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'__wp_config_wp_cache_remove_failure'])) - { - echo '
'."\n"; - echo ' '.__('Failed to update your /wp-config.php file automatically. Please remove the following line from your /wp-config.php file, or set WP_CACHE to a FALSE value.
define(\'WP_CACHE\', TRUE);
', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'__advanced_cache_add_failure'])) - { - echo '
'."\n"; - if($_REQUEST[__NAMESPACE__.'__advanced_cache_add_failure'] === 'zc-advanced-cache') - echo ' '.sprintf(__('Failed to update your /wp-content/advanced-cache.php file. Cannot write stat file: %1$s/zc-advanced-cache. Please be sure this directory exists (and that it\'s writable): %1$s. Please use directory permissions 755 or higher (perhaps 777). Once you\'ve done this, please try again.', $this->plugin->text_domain), esc_html($this->plugin->cache_dir()))."\n"; - else echo ' '.__('Failed to update your /wp-content/advanced-cache.php file. Most likely a permissions error. Please create an empty file here: /wp-content/advanced-cache.php (just an empty PHP file, with nothing in it); give it permissions 644 or higher (perhaps 666). Once you\'ve done this, please try again.', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'__advanced_cache_remove_failure'])) - { - echo '
'."\n"; - echo ' '.__('Failed to remove your /wp-content/advanced-cache.php file. Most likely a permissions error. Please delete (or empty the contents of) this file: /wp-content/advanced-cache.php.', $this->plugin->text_domain)."\n"; - echo '
'."\n"; - } - if(!empty($_REQUEST[__NAMESPACE__.'_pro_preview'])) - { - echo '
'."\n"; - echo ''.__('close', $this->plugin->text_domain).' '."\n"; - echo ' '.sprintf(__('Pro Features (Preview) ~ New option panels below. Please explore before upgrading .
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.', $this->plugin->text_domain), esc_html($this->plugin->name))."\n"; - echo '
'."\n"; - } - if(!$this->plugin->options['enable']) // Not enabled yet? - { - echo '
'."\n"; - echo ' '.sprintf(__('%1$s is currently disabled; please review options below.', $this->plugin->text_domain), esc_html($this->plugin->name))."\n"; - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '

'. - ' '.__('Basic Configuration (Required)', $this->plugin->text_domain). - ' '.sprintf(__('Review these basic options and %1$s™ will be ready-to-go!', $this->plugin->text_domain), esc_html($this->plugin->name)).''. - '

'; - - /* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Enable/Disable', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.sprintf(__('%1$s™ = SPEED!!', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

   

'."\n"; - echo '

'.sprintf(__('HUGE Time-Saver: Approx. 95%% of all WordPress sites running %1$s, simply enable it here; and that\'s it :-) No further configuration is necessary (really). 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 . 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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - echo ' '."\n"; - echo '

'.sprintf(__('How Can I Tell %1$s is Working?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('Once %1$s has been enabled, you\'ll need to log out (and/or clear browser cookies). 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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('To verify that %1$s is working, 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 lightning fast now that %1$s is running; and it gets faster over time!', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Plugin Deletion Safeguards', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Uninstall on Plugin Deletion; or Safeguard Options?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Tip: 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 Yes and THEN 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 advanced-cache.php file, terminate CRON jobs, etc. It erases itself from existence completely.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '

'. - ' '.__('Advanced Configuration (All Optional)', $this->plugin->text_domain). - ' '.__('Recommended for advanced site owners only; already pre-configured for most WP installs.', $this->plugin->text_domain).''. - '

'; - - /* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Clearing the Cache', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo '

'.__('Clearing the Cache Manually', $this->plugin->text_domain).'

'."\n"; - echo ' '."\n"; - echo '

'.sprintf(__('Once %1$s is enabled, you will find this new option in your WordPress Admin Bar (see 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).', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('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).', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '

'.__('Running the s2Clean Theme by WebSharks?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('If s2Clean is installed, %1$s can be configured to clear the Markdown cache too (if you\'ve enabled Markdown processing with s2Clean). The s2Clean Markdown cache is only cleared when you manually clear the cache (with %1$s); and only if you enable this option here. Note: s2Clean\'s Markdown cache is extremely dynamic. Just like the rest of your site, s2Clean caches do NOT need to be cleared away at all, as this happens automatically when your content changes. However, some developers find this feature useful while developing their site; just to force a refresh.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Process Other Custom PHP Code?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('If you have other custom routines you\'d like to process when the cache is cleared manually, please type your custom PHP code here. The PHP code that you provide is only evaluated when you manually clear the cache (with %1$s); and only if the field below contains PHP code. Note: if your PHP code outputs a message (e.g. if you have echo \'<p>My message</p>\';); your message will be displayed along with any other notes from %1$s itself. This could be useful to developers that need to clear server caches too (such as APC or memcache).', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Example: <?php apc_clear_cache(); echo \'<p>Also cleared APC cache.</p>\'; ?>', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '

'.__('Clearing the Cache Automatically', $this->plugin->text_domain).'

'."\n"; - echo ' '."\n"; - echo '

'.sprintf(__('This is built into the %1$s plugin; e.g. 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. Notifications in the Dashboard regarding these detections can be enabled/disabled below.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Auto-Clear Designated "Home Page" Too?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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"?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Auto-Clear Designated "Posts Page" Too?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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"?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Auto-Clear "Author Page" Too?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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"?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Auto-Clear "Category Archives" Too?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Auto-Clear "Tag Archives" Too?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Auto-Clear "Custom Term Archives" Too?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Most sites do not use any custom Terms so it should be safe to leave this disabled. However, if your site uses custom Terms and they have their own Term archive views, you may want to clear those when the associated post is cleared. Therefore, if a single Post/Page is changed in some way; and %1$s clears/resets the cache for a single Post/Page, would you like %1$s to also clear any existing cache files for the associated Tag archive views?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Auto-Clear "Custom Post Type Archives" Too?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Directory / Expiration Time', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo '

'.__('Base Cache Directory (Must be Writable; e.g. Permissions 755 or Higher)', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('This is where %1$s will store the cached version of your site. If you\'re not sure how to deal with directory permissions, don\'t worry too much about this. If there is a problem, %1$s will let you know about it. By default, this directory is created by %1$s and the permissions are setup automatically. In most cases there is nothing more you need to do.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'.esc_html(WP_CONTENT_DIR).'//
'."\n"; - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Automatic Expiration Time (Max Age)', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('If you don\'t update your site much, you could set this to 6 months 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 7 days (recommended); is a good conservative middle-ground.', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('All of that being said, you could set this to just 60 seconds 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 30 minutes, 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 .', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Tip: the value that you specify here MUST be compatible with PHP\'s strtotime() function. Examples: 30 seconds, 2 hours, 7 days, 6 months, 1 year.', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Note: %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 daily); purging expired cache files periodically. This prevents a HUGE cache from building up over time, creating a potential storage issue.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Client-Side Cache', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Allow Double-Caching In The Client-Side Browser?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Recommended setting: No (for membership sites, very important). Otherwise, Yes would be better (if users do NOT log in/out of your site).', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('%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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.__('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 Yes (recommended in this case). Allowing a client-side browser cache will improve speed and reduce outgoing bandwidth when this option is feasible.', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Tip: Setting this to No is highly recommended when running a membership plugin like s2Member (as one example). In fact, many plugins like s2Member will send nocache_headers() 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.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Tip: Setting this to No 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.', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Advanced Tip: if you have this set to No, but you DO want to allow a few special URLs to be cached by the browser; you can add this parameter to your URL ?zcABC=1. This tells %1$s that it\'s OK for the browser to cache that particular URL. In other words, the zcABC=1 parameter tells %1$s NOT to send no-cache headers to the browser.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Logged-In Users', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Caching Enabled for Logged-In Users & Comment Authors?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('This should almost ALWAYS be set to No. 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.', $this->plugin->text_domain).'

'."\n"; - echo ' '."\n"; - echo '

'.sprintf(__('Exception (Membership Sites): If you run a site with many users and the majority of your traffic comes from users who ARE logged-in, please choose: Yes (maintain separate cache). %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 option|meta 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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Note: 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.', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Note: 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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('GET Requests', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Caching Enabled for GET (Query String) Requests?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('This should almost ALWAYS be set to No. UNLESS, you\'re using unfriendly Permalinks. In other words, if all of your URLs contain a query string (e.g. /?key=value); 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 Yes; and don\'t worry too much, the sky won\'t fall on your head :-)', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Note: POST requests (i.e. forms with method="post") are always excluded from the cache, which is the way it should be. Any POST/PUT/DELETE 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.', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Advanced Tip: 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 ?zcAC=1. 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 ?zcAC=0.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('404 Requests', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Caching Enabled for 404 Requests?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('When this is set to No, %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 Yes, %1$s will cache the 404 page (see Creating an Error 404 Page) and then serve that single cache file to all future 404 requests.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'."\n"; - echo '

'.sprintf(__('How does %1$s cache 404 requests? %1$s will create a special cache file (----404----.html, see Advanced Tip below) for the first 404 request and then symlink 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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.__('Advanced Tip: The default 404 cache filename (----404----.html) 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 define(\'ZENCACHE_404_CACHE_FILENAME\', \'your-404-cache-filename\'); to your wp-config.php file (note that the .html extension should be excluded when defining a new filename).', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('RSS, RDF, and Atom Feeds', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Caching Enabled for RSS, RDF, Atom Feeds?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('This should almost ALWAYS be set to No. 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 Yes, you may experience delays in the detection of new posts. NOTE: If you do enable this, it is highly recommended that you also enable automatic Feed Clearing too. Please see the section above: "Clearing the Cache". Find the sub-section titled: "Auto-Clear RSS/RDF/ATOM Feeds" (available only in the pro version).', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Note: 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: WordPress Feeds.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('URI Exclusion Patterns', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo '

'.__('Don\'t Cache These Special URI Exclusion Patterns?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 REQUEST_URI; i.e. /path/?query (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 * character can also be used when necessary; e.g. /category/abc-followed-by-*; (where * = anything, 0 or more characters in length).', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Tip: let\'s use this example URL: http://www.example.com/post/example-post-123. To exclude this URL, you would put this line into the field above: /post/example-post-123. Or, you could also just put in a small fragment, like: example or example-*-123 and that would exclude any URI containing that word fragment.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('HTTP Referrer Exclusion Patterns', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo '

'.__('Don\'t Cache These Special HTTP Referrer Exclusion Patterns?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 HTTP_REFERER (caSe insensitive). A wildcard * character can also be used when necessary; e.g. *.domain.com; (where * = anything, 0 or more characters in length).', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Tip: let\'s use this example URL: http://www.referring-domain.com/search/?q=search+terms. To exclude this referring URL, you could put this line into the field above: www.referring-domain.com. Or, you could also just put in a small fragment, like: /search/ or q=*; and that would exclude any referrer containing that word fragment.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('User-Agent Exclusion Patterns', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo '

'.__('Don\'t Cache These Special User-Agent Exclusion Patterns?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 HTTP_USER_AGENT (caSe insensitive). A wildcard * character can also be used when necessary; e.g. Android *; Chrome/* Mobile; (where * = anything, 0 or more characters in length).', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.sprintf(__('Tip: if you wanted to exclude iPhones put this line into the field above: iPhone;*AppleWebKit. Or, you could also just put in a small fragment, like: iphone; 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).', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.__('Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Auto-Cache Engine', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Enable the Auto-Cache Engine?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.__('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 First-Come Slow-Load Issue. 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 WP-Cron (already built into WordPress). The Auto-Cache Engine runs at 15-minute intervals via WP-Cron. It also uses the WP_Http class, which is also built into WordPress already.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('The Auto-Cache Engine obtains its list of URLs to auto-cache, from two different sources. It can read an XML Sitemap 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.', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '
'."\n"; - echo '

'.__('XML Sitemap URL (or an XML Sitemap Index)', $this->plugin->text_domain).'

'."\n"; - echo '
'.esc_html(home_url('/')).'
'."\n"; - if(is_multisite()) echo '

'.sprintf(__('In a Multisite Network, each child blog will be auto-cached too. %1$s will dynamically change the leading %2$s as necessary; for each child blog in the network. %1$s supports both sub-directory & sub-domain networks; including domain mapping plugins.', $this->plugin->text_domain), esc_html($this->plugin->name), esc_html(home_url('/'))).'

'."\n"; - echo '

'.__('A List of URLs to Auto-Cache (One Per Line)', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '

'.__('Auto-Cache Delay Timer (in Milliseconds)', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 500 milliseconds is suggested here (half a second). If you experience problems, you can bump this up a little at a time, in increments of 500 milliseconds; until you find a happy place for your server. Please note that 1000 milliseconds = 1 full second.', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '

'.__('Auto-Cache User-Agent String', $this->plugin->text_domain).'

'."\n"; - echo '
; '.esc_html(__NAMESPACE__.' '.$this->plugin->version).'
'."\n"; - echo '

'.__('This is how the Auto-Cache Engine identifies itself when connecting to URLs. See User Agent in the Wikipedia.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('HTML Compression', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Enable WebSharks™ HTML Compression?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('This is an experimental feature, however it offers a potentially HUGE speed boost. You can learn more here. Please use with caution.', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Note: This is experimental. Please report issues here.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '
'."\n"; - echo '

'.__('HTML Compression Options', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('You can learn more about all of these options here.', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'."\n"; - echo '

'."\n"; - echo '

'."\n"; - echo '

'."\n"; - echo '

'."\n"; - echo '

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '

'.__('CSS Exclusion Patterns?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 <link href=""> value, and also against the contents of any inline <style> tags (caSe insensitive). A wildcard * character can also be used when necessary; e.g. xy*-framework; (where * = anything, 0 or more characters in length).', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('JavaScript Exclusion Patterns?', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 <script src=""> value, and also against the contents of any inline <script> tags (caSe insensitive). A wildcard * character can also be used when necessary; e.g. xy*-framework; (where * = anything, 0 or more characters in length).', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '

'.__('HTML Compression Cache Expiration', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Tip: the value that you specify here MUST be compatible with PHP\'s strtotime() function. Examples: 2 hours, 7 days, 6 months, 1 year.', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Note: 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 filemtime() 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 learn more here. We recommend setting this value to at least double that of your overall %1$s expiration time.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('GZIP Compression', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('GZIP Compression (Optional; Highly Recommended)', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('You don\'t have to use an .htaccess 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 .htaccess file to accomplish that part.', $this->plugin->text_domain).'

'."\n"; - echo '

'.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 php.ini 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!', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.__('If you want to enable GZIP, create an .htaccess file in your WordPress® installation directory, and put the following few lines in it. Alternatively, if you already have an .htaccess 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: video about GZIP Compression.', $this->plugin->text_domain).'

'."\n"; - echo '
'.esc_html(file_get_contents(dirname(__FILE__).'/gzip-htaccess.tpl.txt')).'
'."\n"; - echo '
'."\n"; - echo '

Or, if your server is missing mod_deflate/mod_filter; open your php.ini file and add this line: zlib.output_compression = on

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Static CDN Filters', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Enable Static CDN Filters (e.g. MaxCDN/CloudFront)?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('This feature allows you to serve some and/or ALL static files on your site from a CDN of your choosing. This is made possible through content/URL filters exposed by WordPress and implemented by %1$s. All it requires is that you setup a CDN host name sourced by your WordPress installation domain. You enter that CDN host name below and %1$s will do the rest! Super easy, and it doesn\'t require any DNS changes either. :-) Please click here for a general set of instructions.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.__('What\'s a CDN? 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.', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '
'."\n"; - echo '

'.__('CDN Host Name (Absolutely Required)', $this->plugin->text_domain).'

'."\n"; - echo '

'. // This note includes two graphics. One for MaxCDN; another for CloudFront. - ' '. - ' '. - ' '.__('This one 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. One you configure a CDN, you\'ll receive a host name (provided by your CDN), which you\'ll enter here; e.g. js9dgjsl4llqpp.cloudfront.net. We recommend MaxCDN and/or Amazon CloudFront, but this should work with many of the most popular CDNs. Please read this article for a general set of instructions. We also have a CloudFront tutorial video that walks you through the process.', $this->plugin->text_domain).''."\n"; - echo '

'."\n"; - echo '

'.__('CDN Host Supports HTTPS Connections?', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '

'.__('Everything else below is 100% completely optional; i.e. not required to enjoy the benefits of Static CDN Filters.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '

'.__('Whitelisted File Extensions (Optional; Comma-Delimited)', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('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.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Blacklisted File Extensions (Optional; Comma-Delimited)', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('With or without a whitelist, you can force exclusions by explicitly blacklisting certain file extensions of your choosing. Please note, the php extension will never be considered a static resource; i.e. it is automatically blacklisted at all times.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '

'.__('Whitelisted URI Inclusion Patterns (Optional; One Per Line)', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one inclusion pattern per line.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/* here would indicate that you only want to filter URLs that lead to files located inside the wp-content directory. Adding an additional line with */wp-includes/* would filter URLs in the wp-includes directory also. If you leave this empty, ALL files matching a static file extension will be served from your CDN; i.e. the default behavior.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('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 /. To clarify, a URI is the portion of the URL which comes after the host name. For instance, given the following URL: http://example.com/path/to/style.css?ver=3, the URI you are matching against would be: /path/to/style.css?ver=3. To whitelist this URI, you could use a line that contains something like this: /path/to/*.css*', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Blacklisted URI Exclusion Patterns (Optional; One Per Line)', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.__('With or without a whitelist, you can force exclusions by explicitly blacklisting certain URI patterns. URI patterns are caSe-insensitive. A wildcard * will match zero or more characters in any of your patterns. A caret ^ symbol will match zero or more characters that are NOT the / character. For instance, */wp-content/*/dynamic.pdf* would exclude a file with the name dynamic.pdf located anywhere inside a sub-directory of wp-content.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Note: please remember that your entries here should be formatted as a line-delimited list; e.g. one exclusion pattern per line.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '

'.__('Query String Invalidation Variable Name', $this->plugin->text_domain).'

'."\n"; - echo '

'."\n"; - echo '

'.sprintf(__('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. Please note, the default value is adequate for most sites. You can change this if you like, but it\'s not necessary.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('Note: 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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Dynamic Version Salt', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__(' GEEK ALERT This is for VERY advanced users only...', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Note: Understanding the %1$s Branched Cache Structure is a prerequisite to understanding how Dynamic Version Salts are added to the mix.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.__('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.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('A Version Salt can be a single variable like $_COOKIE[\'my_cookie\'], or it can be a combination of multiple variables, like $_COOKIE[\'my_cookie\'].$_COOKIE[\'my_other_cookie\']. (When using multiple variables, please separate them with a dot, as shown in the example.)', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Experts could even use PHP ternary expressions that evaluate into something. For example: ((preg_match(\'/iPhone/i\', $_SERVER[\'HTTP_USER_AGENT\'])) ? \'iPhones\' : \'\'). This would force a separate version of the cache to be created for iPhones (e.g., /cache/PROTOCOL/HOST/REQUEST-URI.v/iPhones.html).', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('For more documentation, please see Dynamic Version Salts.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - echo '

'.sprintf(__('Create a Dynamic Version Salt For %1$s?       150%% OPTIONAL', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
/cache/PROTOCOL/HOST/REQUEST-URI.v/
'."\n"; - echo '

'.__('Super Globals work here; $GLOBALS[\'table_prefix\'] is a popular one. Or, perhaps a PHP Constant defined in /wp-config.php; such as WPLANG or DB_HOST.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('Important: your Version Salt is scanned for PHP syntax errors via phpCodeChecker.com. If errors are found, you\'ll receive a notice in the Dashboard.', $this->plugin->text_domain).'

'."\n"; - echo '

'.__('If you\'ve enabled a separate cache for each user (optional) that\'s perfectly OK. A Version Salt works with user caching too.', $this->plugin->text_domain).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Theme/Plugin Developers', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.__('Developing a Theme or Plugin for WordPress?', $this->plugin->text_domain).'

'."\n"; - echo '

'.sprintf(__('Tip: %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: $_SERVER[\'ZENCACHE_ALLOWED\'] = FALSE; or define(\'ZENCACHE_ALLOWED\', FALSE). %1$s is also compatible with: define(\'DONOTCACHEPAGE\', TRUE). 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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - echo '

'.sprintf(__('Writing "Advanced Cache" Plugins Specifically for %1$s', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('Theme/plugin developers can take advantage of the %1$s plugin architecture by creating PHP files inside this special directory: /wp-content/ac-plugins/. There is an example plugin file @ GitHub (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.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('Why does %1$s have it\'s own plugin architecture? WordPress loads the advanced-cache.php 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 add_action(), do_action(), add_filter(), apply_filters().', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - if($this->plugin->is_pro_preview()) - { - echo '
'."\n"; - - echo ' '."\n"; - echo ' '.__('Import/Export Options', $this->plugin->text_domain)."\n"; - echo ' '."\n"; - - echo '
'."\n"; - echo ' '."\n"; - echo '

'.sprintf(__('Import Options from Another %1$s Installation?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '

'.sprintf(__('Upload your %1$s-options.json file and click "Save All Changes" below. The options provided by your import file will override any that exist currently.', $this->plugin->text_domain), __NAMESPACE__).'

'."\n"; - echo '

'."\n"; - echo '
'."\n"; - echo '

'.sprintf(__('Export Existing Options from this %1$s Installation?', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo ' '."\n"; - echo '

'.sprintf(__('Download your existing options and import them all into another %1$s installation; saves time on future installs.', $this->plugin->text_domain), esc_html($this->plugin->name)).'

'."\n"; - echo '
'."\n"; - - echo '
'."\n"; - } - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - echo ' '."\n"; - echo '
'."\n"; - - /* ----------------------------------------------------------------------------------------- */ - - echo '
'."\n"; - echo '