diff --git a/changelog.txt b/changelog.txt
index 6c157a8..e76565e 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,4 +1,29 @@
+= v22.07.04 (2023-03-01) =
+
+- Fixed: Advanced Post Cache -> Only visible to wp < 6.1.1 as it is already implemented in wp core (WP_Query caching).
+- Fixed: Filesystem::shutdown_cleanup() -> Avoid cleanup on shutdown if a file is empty.
+- Fixed: Plugin::register_plugin_hooks() -> Do not load the CronAgent class if cronbot is disabled.
+- Fixed: TermCount() -> Invalid usage of clean_term_cache.
+- Fixed: WP_Object_Cache::$cache_hits, WP_Object_Cache::$cache_misses -> Retain same as non persistent.
+- Fixed: Prevent performance-lab from overwriting the object cache drop-in.
+- Fixed: Becache::export_alloptions() -> Only export option with autoload 'yes' and not transient.
+- Fixed: Becache::store_cache() -> Miss match array_serialize.
+- Added: WP_Object_Cache::$persistent_cache_hits -> Stats hits from cache file.
+- Added: Tweaks::wpquery() -> wp_allow_query_attachment_by_filename for wp > 6.0.1.
+- Added: Configuration -> Cache Options, Retain Transients in Db.
+- Added: Configuration -> Optimisations, Limit Bulk Edit Actions.
+- Added: Configuration -> Wp Tweaks, Deactivate Post Via Email.
+- Added: DOCKET_CACHE_TRANSIENTDB constant to enable retaining Transients in the database.
+- Added: DOCKET_CACHE_IGNORED_TRANSIENTDB constant. A list of cache keys that remain in the object cache instead of the db.
+- Added: DOCKET_CACHE_POSTVIAEMAIL constant to enable deactivation Post Via Email.
+- Added: DOCKET_CACHE_LIMITBULKEDIT constant to enable Limit Bulk Edit Actions.
+- Added: DOCKET_CACHE_LIMITBULKEDIT_LIMIT constant to change bulk edit limit. By default it is set as 100..
+- Changed: Advanced Post Cache, some part of the code has been moved to Tweaks::wpquery().
+- Removed: WP_Object_Cache::is_data_uptodate() -> No longer needed.
+- Updated: Symfony component -> symfony/var-exporter v5.4.21.
+
= v22.07.03 (2023-02-07) =
+
- Fixed: Tweaks::woocommerce_misc() -> Check if action_scheduler_migration_status is complete to prevent the list on the Scheduled Actions page from disappearing.
- Fixed: Tweaks::woocommerce_widget_remove() -> The classic widget is not disabled.
- Fixed: Plugin::get_precache_maxfile() -> Invalid constant, replace maxfile with precache_maxfile.
@@ -29,6 +54,7 @@
Thanks to Kevin Shenk of Avunu LLC for providing access to the staging server for testing purposes.
= v22.07.02 (2022-12-10) =
+
- Fixed: Tweaks::cache_http_response() -> Default TTL.
- Fixed: Tweaks::wpservehappy() -> missing array key.
- Added: wp_cache_supports() function.
@@ -38,25 +64,30 @@ Thanks to Kevin Shenk of Avunu LLC for providing access to the staging server fo
- Tested up to 6.1.
= v22.07.01 (2022-07-15) =
+
- Fixed: Plugin:cleanuppost() -> Invalid index for trashbin.
- Fixed: MoCache() -> Add $entries, $headers properties to avoid warning on get_translations_for_domain.
- Updated: Symfony component -> symfony/var-exporter.
= v21.08.11 (2022-05-30) =
+
- Fixed: Avoid calling Filesystem::close_buffer() if a process involved accessing a disk.
- Fixed: Removed handling stale cache on shutdown.
- Added: Garbage Collector Status -> Cleanup Stale Cache.
- Improved: Collected stale cache will be handled by Garbage Collector.
= v21.08.10 (2022-05-20) =
+
- Changed: Disable "CHUNKCACHEDIR" by default. Let's users choose it depending on their hosting environment.
= v21.08.09 (2022-05-20) =
+
- Fixed: WP_Object_Cache::maybe_expire() -> missing preg_match parameter.
Thanks to @carmpocalypse for bug report.
= v21.08.08 (2022-05-19) =
+
- Fixed: Don't remove cron event without a hook, let's WordPress handles it.
- Fixed: WP_Object_Cache::dc_close() -> Only run one time per instance.
- Fixed: WP_Object_Cache::maybe_expire() -> Check cache key.
@@ -64,6 +95,7 @@ Thanks to @carmpocalypse for bug report.
- Changed: Disable "Auto Remove Stale Cache" by default. Let's users choose it depending on their cpu/storage speeds limit.
= v21.08.07 (2022-05-13) =
+
- Fixed: Tweaks::wpembed() -> body_class missing seconds arguments that require by some themes.
- Fixed: Tweaks::wpembed() -> Disable body_class filter, cause unpredictable syntax error on some themes.
diff --git a/credits.txt b/credits.txt
index 238f43c..04168ba 100644
--- a/credits.txt
+++ b/credits.txt
@@ -1,17 +1,22 @@
The portion of following projects has been used in Docket Cache. Thank you for all the great works!.
List in alphabetical order:
-1) Advanced Post Cache
- https://github.com/Automattic/vip-go-mu-plugins-built/blob/master/advanced-post-cache/advanced-post-cache.php.
-
-2) Lightweight Term Count Update
- https://github.com/Automattic/lightweight-term-count-update.
+1) EventList(): includes/src/EventList.php
+ - plugins/wp-crontrol/src/event-list-table.php
+ - plugins/wp-crontrol/src/event.php
+ - plugins/query-monitor/classes/Util.php
-3) MonoDB
- https://github.com/nawawi/MonoDB
+1) LimitBulkedit(): includes/src/LimitBulkedit.php
+ https://github.com/Automattic/vip-go-mu-plugins/blob/develop/performance/bulk-edit.php
-4) Software Testing Isometric Banner Functional Test
- Designed by upklyak / Freepik -- http://www.freepik.com
+2) PostCache(): includes/src/PostCache.php
+ https://github.com/Automattic/vip-go-mu-plugins-built/blob/master/advanced-post-cache/advanced-post-cache.php.
-5) Symfony VarExporter Component
+3) Filesystem::export_var(): include/src/Filesystem.php
https://github.com/symfony/var-exporter
+
+4) TermCount(): includes/src/TermCount.php
+ https://github.com/Automattic/lightweight-term-count-update.
+
+--
+Updated: 26-Feb-2023
diff --git a/dist/docket-cache.zip b/dist/docket-cache.zip
index ad21303..c665364 100644
Binary files a/dist/docket-cache.zip and b/dist/docket-cache.zip differ
diff --git a/docket-cache.php b/docket-cache.php
index 9fb6c8a..c468a3b 100644
--- a/docket-cache.php
+++ b/docket-cache.php
@@ -12,8 +12,8 @@
* @wordpress-plugin
* Plugin Name: Docket Cache
* Plugin URI: https://docketcache.com/?utm_source=wp-plugins&utm_campaign=plugin-uri&utm_medium=wp-dash
- * Version: 22.07.03
- * VerPrev: 22.07.02
+ * Version: 22.07.04
+ * VerPrev: 22.07.03
* Description: A persistent object cache stored as a plain PHP code, accelerates caching with OPcache backend.
* GitHub Plugin URI: https://github.com/nawawi/docket-cache
* Author: Nawawi Jamili
diff --git a/includes/admin/config.php b/includes/admin/config.php
index 0035253..ef04de4 100644
--- a/includes/admin/config.php
+++ b/includes/admin/config.php
@@ -24,22 +24,18 @@
- tooltip('cronbot');
-?>
+ opt_title('cronbot'); ?>
|
- config_select_bool('cronbot'); ?>
+ config_select_bool_e('cronbot'); ?>
|
- tooltip('opcviewer');
-?>
+ opt_title('opcviewer'); ?>
|
- config_select_bool('opcviewer'); ?>
+ config_select_bool_e('opcviewer'); ?>
|
@@ -47,12 +43,10 @@
- tooltip('log');
-?>
+ opt_title('log'); ?>
|
- config_select_bool('log'); ?>
+ config_select_bool_e('log'); ?>
|
@@ -60,43 +54,50 @@
+
- tooltip('advcpost'); ?> |
+ opt_title('advcpost'); ?> |
- config_select_bool('advcpost'); ?>
+ config_select_bool_e('advcpost'); ?>
|
vcf()->is_dctrue('advcpost')) : ?>
- tooltip('advpost_posttype_all'); ?> |
+ opt_title('advpost_posttype_all'); ?> |
- config_select_bool('advpost_posttype_all'); ?>
+ config_select_bool_e('advpost_posttype_all'); ?>
|
-
+
- tooltip('precache'); ?> |
+ opt_title('precache'); ?> |
- config_select_bool('precache'); ?>
+ config_select_bool_e('precache'); ?>
|
- tooltip('mocache'); ?> |
+ opt_title('mocache'); ?> |
- config_select_bool('mocache'); ?>
+ config_select_bool_e('mocache'); ?>
|
- tooltip('preload'); ?> |
+ opt_title('preload'); ?> |
+
+ config_select_bool_e('preload'); ?>
+ |
+
+
+ opt_title('transientdb'); ?> |
- config_select_bool('preload'); ?>
+ config_select_bool_e('transientdb'); ?>
|
@@ -105,50 +106,56 @@
- tooltip('optwpquery'); ?> |
+ opt_title('optwpquery'); ?> |
- config_select_bool('optwpquery'); ?>
+ config_select_bool_e('optwpquery'); ?>
|
- tooltip('optermcount'); ?> |
+ opt_title('optermcount'); ?> |
- config_select_bool('optermcount'); ?>
+ config_select_bool_e('optermcount'); ?>
|
- tooltip('cronoptmzdb'); ?> |
+ opt_title('cronoptmzdb'); ?> |
config_select_set(
- 'cronoptmzdb',
- [
- 'default' => __('Default', 'docket-cache'),
- 'daily' => __('Daily', 'docket-cache'),
- 'weekly' => __('Weekly', 'docket-cache'),
- 'monthly' => __('Monthly', 'docket-cache'),
- 'never' => __('Never', 'docket-cache'),
- ]
-);
+ $this->config_select_set_e(
+ 'cronoptmzdb',
+ [
+ 'default' => __('Default', 'docket-cache'),
+ 'daily' => __('Daily', 'docket-cache'),
+ 'weekly' => __('Weekly', 'docket-cache'),
+ 'monthly' => __('Monthly', 'docket-cache'),
+ 'never' => __('Never', 'docket-cache'),
+ ]
+ );
?>
|
- tooltip('wpoptaload'); ?> |
+ opt_title('wpoptaload'); ?> |
- config_select_bool('wpoptaload'); ?>
+ config_select_bool_e('wpoptaload'); ?>
|
- tooltip('postmissedschedule'); ?> |
+ opt_title('postmissedschedule'); ?> |
- config_select_bool('postmissedschedule'); ?>
+ config_select_bool_e('postmissedschedule'); ?>
+ |
+
+
+ opt_title('limitbulkedit'); ?> |
+
+ config_select_bool_e('limitbulkedit'); ?>
|
- tooltip('misc_tweaks'); ?> |
+ opt_title('misc_tweaks'); ?> |
- config_select_bool('misc_tweaks'); ?>
+ config_select_bool_e('misc_tweaks'); ?>
|
@@ -157,45 +164,45 @@
- tooltip('wootweaks'); ?> |
+ opt_title('wootweaks'); ?> |
- config_select_bool('wootweaks'); ?>
+ config_select_bool_e('wootweaks'); ?>
|
- tooltip('wooadminoff'); ?> |
+ opt_title('wooadminoff'); ?> |
- config_select_bool('wooadminoff'); ?>
+ config_select_bool_e('wooadminoff'); ?>
|
- tooltip('woowidgetoff'); ?> |
+ opt_title('woowidgetoff'); ?> |
- config_select_bool('woowidgetoff'); ?>
+ config_select_bool_e('woowidgetoff'); ?>
|
- tooltip('woowpdashboardoff'); ?> |
+ opt_title('woowpdashboardoff'); ?> |
- config_select_bool('woowpdashboardoff'); ?>
+ config_select_bool_e('woowpdashboardoff'); ?>
|
- tooltip('wooextensionpageoff'); ?> |
+ opt_title('wooextensionpageoff'); ?> |
- config_select_bool('wooextensionpageoff'); ?>
+ config_select_bool_e('wooextensionpageoff'); ?>
|
- tooltip('woocartfragsoff'); ?> |
+ opt_title('woocartfragsoff'); ?> |
- config_select_bool('woocartfragsoff'); ?>
+ config_select_bool_e('woocartfragsoff'); ?>
|
- tooltip('wooaddtochartcrawling'); ?> |
+ opt_title('wooaddtochartcrawling'); ?> |
- config_select_bool('wooaddtochartcrawling'); ?>
+ config_select_bool_e('wooaddtochartcrawling'); ?>
|
@@ -204,82 +211,88 @@
- tooltip('pingback'); ?> |
+ opt_title('pingback'); ?> |
- config_select_bool('pingback'); ?>
+ config_select_bool_e('pingback'); ?>
|
- tooltip('wpemoji'); ?> |
+ opt_title('wpemoji'); ?> |
- config_select_bool('wpemoji'); ?>
+ config_select_bool_e('wpemoji'); ?>
|
- tooltip('wpfeed'); ?> |
+ opt_title('wpfeed'); ?> |
- config_select_bool('wpfeed'); ?>
+ config_select_bool_e('wpfeed'); ?>
|
- tooltip('wpembed'); ?> |
+ opt_title('wpembed'); ?> |
- config_select_bool('wpembed'); ?>
+ config_select_bool_e('wpembed'); ?>
|
- tooltip('wplazyload'); ?> |
+ opt_title('wplazyload'); ?> |
- config_select_bool('wplazyload'); ?>
+ config_select_bool_e('wplazyload'); ?>
|
- tooltip('wpsitemap'); ?> |
+ opt_title('wpsitemap'); ?> |
- config_select_bool('wpsitemap'); ?>
+ config_select_bool_e('wpsitemap'); ?>
|
- tooltip('wpapppassword'); ?> |
+ opt_title('wpapppassword'); ?> |
- config_select_bool('wpapppassword'); ?>
+ config_select_bool_e('wpapppassword'); ?>
|
- tooltip('wpdashboardnews'); ?> |
+ opt_title('wpdashboardnews'); ?> |
+
+ config_select_bool_e('wpdashboardnews'); ?>
+ |
+
+
+ opt_title('postviaemail'); ?> |
- config_select_bool('wpdashboardnews'); ?>
+ config_select_bool_e('postviaemail'); ?>
|
- tooltip('wpbrowsehappy'); ?> |
+ opt_title('wpbrowsehappy'); ?> |
- config_select_bool('wpbrowsehappy'); ?>
+ config_select_bool_e('wpbrowsehappy'); ?>
|
- tooltip('wpservehappy'); ?> |
+ opt_title('wpservehappy'); ?> |
- config_select_bool('wpservehappy'); ?>
+ config_select_bool_e('wpservehappy'); ?>
|
- tooltip('limithttprequest'); ?> |
+ opt_title('limithttprequest'); ?> |
- config_select_bool('limithttprequest'); ?>
+ config_select_bool_e('limithttprequest'); ?>
|
@@ -290,10 +303,10 @@
- tooltip('rtpostautosave'); ?> |
+ opt_title('rtpostautosave'); ?> |
config_select_set(
+$this->config_select_set_e(
'rtpostautosave',
[
'default' => __('Default', 'docket-cache'),
@@ -307,10 +320,10 @@
|
- tooltip('rtpostrevision'); ?> |
+ opt_title('rtpostrevision'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtpostrevision',
[
'default' => __('Default', 'docket-cache'),
@@ -324,10 +337,10 @@
|
- tooltip('rtpostemptytrash'); ?> |
+ opt_title('rtpostemptytrash'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtpostemptytrash',
[
'default' => __('Default', 'docket-cache'),
@@ -341,10 +354,10 @@
|
- tooltip('rtimageoverwrite'); ?> |
+ opt_title('rtimageoverwrite'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtimageoverwrite',
[
'default' => __('Default', 'docket-cache'),
@@ -357,10 +370,10 @@
|
- tooltip('rtwpcoreupdate'); ?> |
+ opt_title('rtwpcoreupdate'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtwpcoreupdate',
[
'default' => __('Default', 'docket-cache'),
@@ -373,10 +386,10 @@
|
- tooltip('rtpluginthemeeditor'); ?> |
+ opt_title('rtpluginthemeeditor'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtpluginthemeeditor',
[
'default' => __('Default', 'docket-cache'),
@@ -389,10 +402,10 @@
|
- tooltip('rtpluginthemeinstall'); ?> |
+ opt_title('rtpluginthemeinstall'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtpluginthemeinstall',
[
'default' => __('Default', 'docket-cache'),
@@ -405,10 +418,10 @@
|
- tooltip('rtconcatenatescripts'); ?> |
+ opt_title('rtconcatenatescripts'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtconcatenatescripts',
[
'default' => __('Default', 'docket-cache'),
@@ -421,10 +434,10 @@
|
- tooltip('rtdisablewpcron'); ?> |
+ opt_title('rtdisablewpcron'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtdisablewpcron',
[
'default' => __('Default', 'docket-cache'),
@@ -440,10 +453,10 @@
$rtwpdebug_default = !empty($GLOBALS[$this->vcf()->px('rtwpdebug_false')]) && WP_DEBUG ? 'on' : $this->vcf()->dcvalue('rtwpdebug');
?>
|
- >tooltip('rtwpdebug'); ?> |
+ >opt_title('rtwpdebug'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtwpdebug',
[
'default' => __('Default', 'docket-cache'),
@@ -457,10 +470,10 @@
|
- tooltip('rtwpdebugdisplay'); ?> |
+ opt_title('rtwpdebugdisplay'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtwpdebugdisplay',
[
'default' => __('Default', 'docket-cache'),
@@ -477,10 +490,10 @@
$error_log = \ini_get('error_log');
?>
|
- tooltip('rtwpdebuglog'); ?> |
+ opt_title('rtwpdebuglog'); ?> |
config_select_set(
+ $this->config_select_set_e(
'rtwpdebuglog',
[
'default' => __('Default', 'docket-cache'),
@@ -506,7 +519,7 @@
|
- tooltip('maxfile'); ?> |
+ opt_title('maxfile'); ?> |
config_select_set(
+$this->config_select_set_e(
'maxfile',
[
'default' => __('Default', 'docket-cache'),
@@ -535,7 +548,7 @@
|
- tooltip('maxsize_disk'); ?> |
+ opt_title('maxsize_disk'); ?> |
config_select_set(
+$this->config_select_set_e(
'maxsize_disk',
[
'default' => __('Default', 'docket-cache'),
@@ -564,36 +577,36 @@
|
- tooltip('chunkcachedir'); ?> |
+ opt_title('chunkcachedir'); ?> |
- config_select_bool('chunkcachedir'); ?>
+ config_select_bool_e('chunkcachedir'); ?>
|
- tooltip('maxfile_livecheck'); ?> |
+ opt_title('maxfile_livecheck'); ?> |
- config_select_bool('maxfile_livecheck'); ?>
+ config_select_bool_e('maxfile_livecheck'); ?>
|
- tooltip('flush_stalecache'); ?> |
+ opt_title('flush_stalecache'); ?> |
- config_select_bool('flush_stalecache'); ?>
+ config_select_bool_e('flush_stalecache'); ?>
|
- tooltip('stalecache_ignore'); ?> |
+ opt_title('stalecache_ignore'); ?> |
- config_select_bool('stalecache_ignore'); ?>
+ config_select_bool_e('stalecache_ignore'); ?>
|
*/
?>
- tooltip('emptycache_ignore'); ?> |
+ opt_title('emptycache_ignore'); ?> |
- config_select_bool('emptycache_ignore'); ?>
+ config_select_bool_e('emptycache_ignore'); ?>
|
@@ -602,27 +615,27 @@
- tooltip('pageloader'); ?> |
+ opt_title('pageloader'); ?> |
- config_select_bool('pageloader'); ?>
+ config_select_bool_e('pageloader'); ?>
|
- tooltip('stats'); ?> |
+ opt_title('stats'); ?> |
- config_select_bool('stats'); ?>
+ config_select_bool_e('stats'); ?>
|
- tooltip('gcaction'); ?> |
+ opt_title('gcaction'); ?> |
- config_select_bool('gcaction'); ?>
+ config_select_bool_e('gcaction'); ?>
|
- tooltip('flushaction'); ?> |
+ opt_title('flushaction'); ?> |
- config_select_bool('flushaction'); ?>
+ config_select_bool_e('flushaction'); ?>
|
@@ -631,27 +644,27 @@
- tooltip('autoupdate_toggle'); ?> |
+ opt_title('autoupdate_toggle'); ?> |
- config_select_bool('autoupdate_toggle'); ?>
+ config_select_bool_e('autoupdate_toggle'); ?>
|
- tooltip('checkversion'); ?> |
+ opt_title('checkversion'); ?> |
- config_select_bool('checkversion'); ?>
+ config_select_bool_e('checkversion'); ?>
|
- tooltip('flush_shutdown'); ?> |
+ opt_title('flush_shutdown'); ?> |
- config_select_bool('flush_shutdown'); ?>
+ config_select_bool_e('flush_shutdown'); ?>
|
- tooltip('opcshutdown'); ?> |
+ opt_title('opcshutdown'); ?> |
- config_select_bool('opcshutdown'); ?>
+ config_select_bool_e('opcshutdown'); ?>
|
diff --git a/includes/admin/docket.js b/includes/admin/docket.js
index 66d603e..cd72c4e 100644
--- a/includes/admin/docket.js
+++ b/includes/admin/docket.js
@@ -85,6 +85,12 @@
}
);
+ var close_notice = function() {
+ $selector.find( 'div.is-dismissible' )
+ .find( 'button.notice-dismiss' )
+ .trigger( 'click' );
+ };
+
window.dospinner = false;
var spinner = function() {
if ( !window.dospinner ) {
@@ -170,6 +176,8 @@
.on(
'change.dc-select-config',
function() {
+ close_notice();
+ window.dospinner = true;
spinner();
var $self = $( this );
var link = $self.children( 'option:selected' )
diff --git a/includes/cache.php b/includes/cache.php
index b32362c..464bfc9 100644
--- a/includes/cache.php
+++ b/includes/cache.php
@@ -42,6 +42,13 @@ class WP_Object_Cache
*/
public $cache_misses = 0;
+ /**
+ * The amount of times the cached data was fetched from the cache file.
+ *
+ * @var int
+ */
+ public $persistent_cache_hits = 0;
+
/**
* List of global cache groups.
*
@@ -75,7 +82,7 @@ class WP_Object_Cache
*
* @var array
*/
- protected $bypass_precache = [];
+ private $bypass_precache = [];
/**
* The blog prefix to prepend to keys in non-global groups.
@@ -231,6 +238,20 @@ class WP_Object_Cache
*/
private $ignore_emptycache = false;
+ /**
+ * Store Transients in DB.
+ *
+ * @var bool
+ */
+ private $use_transientdb = false;
+
+ /**
+ * List of transient exclude from store in DB.
+ *
+ * @var array
+ */
+ private $bypass_transientdb = [];
+
/**
* Sets up object properties.
*/
@@ -269,12 +290,12 @@ protected function _exists($key, $group, $force = false)
$is_exists = !$force && !empty($this->cache) && isset($this->cache[$group]) && (isset($this->cache[$group][$key]) || \array_key_exists($key, $this->cache[$group]));
if (!$is_exists && !$this->is_non_persistent_groups($group) && !$this->is_non_persistent_keys($key) && !$this->is_non_persistent_groupkey($group, $key) && !$this->is_stalecache_ignored($key, $group)) {
- $data = $this->dc_get($key, $group, false);
+ $data = $this->dc_get($key, $group, false, $codestub_false);
if (false !== $data) {
$is_exists = true;
$this->cache[$group][$key] = $data;
- if ($this->is_precache && !$this->fs()->suspend_cache_write() && !$this->is_bypass_precache($group, $key)) {
+ if ($this->is_precache && !$codestub_false && !$this->fs()->suspend_cache_write() && !$this->is_bypass_precache($group, $key)) {
if (empty($this->precache[$group])) {
$this->precache[$group][$key] = 1;
} elseif (\count($this->precache[$group]) < $this->precache_maxkey && \count($this->precache) < $this->precache_maxgroup) {
@@ -461,7 +482,7 @@ public function set_multiple(array $data, $group = '', $expire = 0)
*
* @return mixed|false the cache contents on success, false on failure to retrieve contents
*/
- public function get($key, $group = 'default', $force = false, &$found = null)
+ public function get($key, $group = 'default', $force = false, &$found = null, $doing_precache = false)
{
if (!$this->is_valid_key($key)) {
return false;
@@ -474,6 +495,9 @@ public function get($key, $group = 'default', $force = false, &$found = null)
$cache_key = $this->dc_key($key, $group);
if ($this->_exists($cache_key, $group, $force)) {
+ if (!$doing_precache) {
+ ++$this->cache_hits;
+ }
$found = true;
if (\is_object($this->cache[$group][$cache_key])) {
return clone $this->cache[$group][$cache_key];
@@ -483,6 +507,9 @@ public function get($key, $group = 'default', $force = false, &$found = null)
}
$found = false;
+ if (!$doing_precache) {
+ ++$this->cache_misses;
+ }
return false;
}
@@ -535,10 +562,7 @@ public function delete($key, $group = 'default', $deprecated = false)
unset($this->cache[$group][$key]);
unset($this->precache[$group][$key]);
- $this->dc_remove($key, $group);
-
- // always true
- return true;
+ return $this->dc_remove($key, $group);
}
/**
@@ -698,6 +722,7 @@ public function stats()
$ret = '';
$ret .= '';
$ret .= "Cache Hits: {$this->cache_hits}
";
+ $ret .= "Persistent Cache Hits: {$this->persistent_cache_hits}
";
$ret .= "Cache Misses: {$this->cache_misses}
";
$ret .= '
';
$ret .= '';
@@ -788,9 +813,9 @@ protected function is_non_persistent_groupkey($group, $key)
* @param bool $group cache group
* @param bool $key cache key
*/
- protected function is_bypass_precache($group, $key)
+ private function is_bypass_precache($group, $key)
{
- if ($this->fs()->is_docketcachegroup($group, $key) || $this->fs()->is_transient($group) || $this->is_non_persistent_groups($group) || $this->is_non_persistent_keys($key) || $this->has_stalecache($key, $group)) {
+ if ($this->fs()->is_docketcachegroup($group, $key) || $this->fs()->is_transient($group) || $this->has_stalecache($key, $group)) {
return true;
}
@@ -901,14 +926,14 @@ private function maybe_expire($group, $expire = 0, $key = '')
$maxttl = $this->cache_maxttl;
if (0 === $expire && $maxttl < 2419200) {
- if (\in_array($group, ['site-transient', 'transient'])) {
+ if ($this->fs()->is_transient($group)) {
if ('site-transient' === $group && \in_array($key, ['update_plugins', 'update_themes', 'update_core', '_woocommerce_helper_updates'])) {
$expire = $maxttl < 2419200 ? 2419200 : $maxttl; // 28d
} else {
// $expire = $maxttl < 604800 ? 604800 : $maxttl; // 7d
$expire = $maxttl < 86400 ? $maxttl : 86400; // 1d
}
- } elseif (\in_array($group, ['options', 'site-options'])) {
+ } elseif ($this->fs()->is_wp_options($group)) {
$expire = $maxttl < 1209600 ? 1209600 : $maxttl; // 14d
} elseif (\in_array($group, ['terms', 'posts', 'post_meta', 'comments', 'comment_feed', 'sites', 'networks'])) {
$expire = $maxttl < 1209600 ? 1209600 : $maxttl; // 14d
@@ -1028,28 +1053,6 @@ private function skip_stats($group, $key = '')
return $this->cf()->is_dcfalse('LOG_ALL') && $this->fs()->is_docketcachegroup($group);
}
- /**
- * is_data_uptodate.
- */
- private function is_data_uptodate($key, $group, $data)
- {
- $file = $this->get_file_path($key, $group);
- $data_p = $this->fs()->cache_get($file);
- if (false === $data_p || !isset($data_p['data'])) {
- return false;
- }
-
- $data_p = $data_p['data'];
-
- if (\function_exists('nwdcx_arraysimilar') && nwdcx_arraysimilar($data_p, $data)) {
- nwdcx_debuglog(__FUNCTION__.': '.$this->get_item_hash($file).' No data changes.');
-
- return true;
- }
-
- return false;
- }
-
/**
* has_stalecache.
*/
@@ -1112,6 +1115,19 @@ private function cf()
return $inst;
}
+ /**
+ * transientdb.
+ */
+ private function transient_db()
+ {
+ static $inst;
+ if (!\is_object($inst)) {
+ $inst = new Nawawi\DocketCache\TransientDb();
+ }
+
+ return $inst;
+ }
+
/**
* dc_key.
*/
@@ -1204,9 +1220,16 @@ private function dc_flush()
*/
private function dc_remove($key, $group)
{
+ $result = true;
+ if ($this->use_transientdb && $this->fs()->is_transient($group)) {
+ $result = $this->transient_db()->delete($key, $group);
+ }
+
$file = $this->get_file_path($key, $group);
$this->fs()->unlink($file, false);
$this->dc_log('del', $this->get_item_hash($file), $group.':'.$key);
+
+ return $result;
}
/**
@@ -1261,6 +1284,10 @@ public function dc_remove_group($group)
$this->fs()->suspend_cache_write(false);
+ if ($this->use_transientdb && $this->fs()->is_transient(explode(',', $group)) && \function_exists('nwdcx_cleanuptransient')) {
+ $total += nwdcx_cleanuptransient();
+ }
+
return $total;
}
@@ -1329,18 +1356,32 @@ public function dc_remove_group_match($group)
/**
* dc_get.
*/
- private function dc_get($key, $group, $is_raw = false)
+ private function dc_get($key, $group, $is_raw = false, &$codestub_false = false)
{
$file = $this->get_file_path($key, $group);
$logkey = $this->get_item_hash($file);
+ if ($this->use_transientdb && !\in_array($key, $this->bypass_transientdb)) {
+ if ($this->fs()->is_transient($group)) {
+ return $this->transient_db()->get($key, $group);
+ }
+
+ if ($this->fs()->is_wp_options($group) && $this->transient_db()->match_key($key)) {
+ return false;
+ }
+ }
+
$data = $this->fs()->cache_get($file);
if (false === $data) {
- if (!$this->skip_stats($group)) {
+ if (!$this->skip_stats($group) && !$this->fs()->is_transient($group)) {
+ $this->dc_log('miss', $logkey, $group.':'.$key);
+ }
+
+ /*if (!$this->skip_stats($group) && !$this->fs()->is_transient($group)) {
++$this->cache_misses;
$this->dc_log('miss', $logkey, $group.':'.$key);
- }
+ }*/
return false;
}
@@ -1362,7 +1403,7 @@ private function dc_get($key, $group, $is_raw = false)
}
if (!$this->skip_stats($group)) {
- ++$this->cache_hits;
+ ++$this->persistent_cache_hits;
$this->dc_log('hit', $logkey, $group.':'.$key);
}
@@ -1384,6 +1425,11 @@ private function dc_get($key, $group, $is_raw = false)
}
clearstatcache();
+ // skip precache.
+ if (isset($GLOBALS['DOCKET_CACHE_CODESTUB_FALSE']) && isset($GLOBALS['DOCKET_CACHE_CODESTUB_FALSE'][$file])) {
+ $codestub_false = true;
+ }
+
return $is_raw ? $data : $data['data'];
}
@@ -1395,17 +1441,7 @@ private function dc_code($file, $arr)
$logkey = $this->get_item_hash($file);
$logpref = __FUNCTION__.'():';
- // use (object) instead of VarExporter.
- if (\PHP_VERSION_ID >= 70433 && \in_array($arr['type'], ['object', 'array'])) {
- $arr_data = var_export($arr, true);
- if (!empty($arr_data) && false != strpos($arr_data, '(object) array(') && false === strpos($arr_data, '::__set_state')) {
- $data = $arr_data;
- }
- }
-
- if (!isset($data)) {
- $data = $this->fs()->export_var($arr, $error);
- }
+ $data = $this->fs()->export_var($arr, $error);
if (false === $data) {
$this->dc_log('err', $logkey, $logpref.' Failed to export var -> '.$error);
@@ -1444,12 +1480,27 @@ private function dc_save($cache_key, $data, $group = 'default', $expire = 0, $ke
$logkey = $this->item_hash($group).'-'.$this->item_hash($cache_key);
$logpref = __FUNCTION__.'():';
- // skip save to disk, return true;
- /*if ('' === $data && $this->fs()->is_transient($group)) {
- nwdcx_debuglog(__FUNCTION__.': '.$logkey.': Process aborted. No data availale.');
+ if ($this->use_transientdb && !\in_array($cache_key, $this->bypass_transientdb)) {
+ if ($this->fs()->is_transient($group)) {
+ if (!$expire) {
+ $expire = 86400;
+ }
- return true;
- }*/
+ return $this->transient_db()->set($cache_key, $data, $group, time() + $expire);
+ }
+
+ if ($this->fs()->is_wp_options($group) && $this->transient_db()->match_key($cache_key)) {
+ return false;
+ }
+
+ if (\in_array($cache_key, ['notoptions', 'alloptions']) && \is_array($data) && !empty($data)) {
+ foreach ($data as $m => $n) {
+ if ($this->transient_db()->match_key($m)) {
+ unset($data[$m]);
+ }
+ }
+ }
+ }
if (!$this->fs()->mkdir_p($this->cache_path)) {
return false;
@@ -1459,7 +1510,7 @@ private function dc_save($cache_key, $data, $group = 'default', $expire = 0, $ke
$file = $this->get_file_path($cache_key, $group);
- // skip save to disk, return true;
+ // Skip save to disk, return true.
if (('' === $data || (\is_array($data) && empty($data))) && ($this->fs()->is_transient($group) || $this->ignore_emptycache)) {
nwdcx_debuglog(__FUNCTION__.': '.$logkey.': Process aborted. No data availale.');
$this->fs()->unlink($file, false);
@@ -1467,12 +1518,12 @@ private function dc_save($cache_key, $data, $group = 'default', $expire = 0, $ke
return true;
}
- // chunk dir
+ // Chunk dir.
if ($this->cf()->is_dctrue('CHUNKCACHEDIR', true) && !$this->fs()->mkdir_p(\dirname($file))) {
return false;
}
- // if $expire is larger than 0, convert it to timestamp
+ // If $expire is larger than 0, convert it to timestamp.
$timeout = ($expire > 0 ? time() + $expire : 0);
$type = \gettype($data);
@@ -1480,8 +1531,26 @@ private function dc_save($cache_key, $data, $group = 'default', $expire = 0, $ke
$data = '';
}
- // unserialize content
if (!empty($data)) {
+ // Abort if object too large.
+ $len = 0;
+ $nwdcx_suppresserrors = nwdcx_suppresserrors(true);
+ if (\function_exists('maybe_serialize')) {
+ $len = \strlen(@maybe_serialize($data));
+ } else {
+ $len = \strlen(@serialize($data));
+ }
+ nwdcx_suppresserrors($nwdcx_suppresserrors);
+
+ if ($len >= $this->cache_maxsize) {
+ $this->dc_log('err', $logkey, $group.':'.$cache_key.' '.$logpref.' Object too large -> '.$len.'/'.$this->cache_maxsize);
+
+ nwdcx_debuglog(__FUNCTION__.': '.$logkey.': Process aborted. Object too large ('.$len.'/'.$this->cache_maxsize.')');
+
+ return false;
+ }
+
+ // Unserialize content first.
if ('string' === $type) {
$data = nwdcx_unserialize($data);
} elseif ('array' === $type) {
@@ -1494,22 +1563,6 @@ private function dc_save($cache_key, $data, $group = 'default', $expire = 0, $ke
}
}
- // abort if object too large
- $len = \strlen(serialize($data));
- if ($len >= $this->cache_maxsize) {
- $this->dc_log('err', $logkey, $group.':'.$cache_key.' '.$logpref.' Object too large -> '.$len.'/'.$this->cache_maxsize);
-
- nwdcx_debuglog(__FUNCTION__.': '.$logkey.': Process aborted. Object too large ('.$len.'/'.$this->cache_maxsize.')');
-
- return false;
- }
-
- // since timeout set to timestamp.
- /*clearstatcache(true, $file);
- if (0 === $expire && !empty($key) && @is_file($file) && $this->is_data_uptodate($key, $group, $data)) {
- return false;
- }*/
-
$meta = [];
$meta['timestamp'] = time();
@@ -1520,17 +1573,32 @@ private function dc_save($cache_key, $data, $group = 'default', $expire = 0, $ke
$final_type = \gettype($data);
if ('string' === $final_type && nwdcx_serialized($data)) {
$final_type = 'string_serialize';
- } elseif ('array' === $final_type && (!\defined('DOCKET_CACHE_USE_CLASSMAP') || !DOCKET_CACHE_USE_CLASSMAP)) {
- // may lead to __PHP_Incomplete_Class
- // headers => Requests_Utility_CaseInsensitiveDictionary Object
- // headers => Requests_Utility_CaseInsensitiveDictionary Object
- // if (!empty($data['headers']) && \is_object($data['headers']) && false !== strpos(var_export($data['headers'], 1), 'Requests_Utility_CaseInsensitiveDictionary::__set_state')) {
- if (false !== strpos(var_export($data, 1), 'Requests_Utility_CaseInsensitiveDictionary::__set_state')) {
- $data = @serialize($data);
- if (nwdcx_serialized($data)) {
- $final_type = 'array_serialize';
+ } elseif ('array' === $final_type) {
+ // The Data needs to be serialized.
+ // The cache always returns false if the object has a class instance
+ // other than stdClass since the class has not been loaded yet.
+ $nwdcx_suppresserrors = nwdcx_suppresserrors(true);
+ $export_data = @var_export($data, 1);
+ if (!empty($export_data)) {
+ // 1st priority. If has the "Request" instance.
+ if (false !== strpos($export_data, 'Requests_Utility_CaseInsensitiveDictionary::__set_state')) {
+ $data = @serialize($data);
+ if (nwdcx_serialized($data)) {
+ $final_type = 'array_serialize';
+ }
+ }
+
+ // 2nd priority. If Transients and has class instance.
+ if ('array' === $final_type && $this->fs()->is_transient($group) && false !== strpos($export_data, '::__set_state')) {
+ $data = @serialize($data);
+ if (nwdcx_serialized($data)) {
+ $final_type = 'array_serialize';
+ }
}
}
+ unset($export_data);
+ nwdcx_suppresserrors($nwdcx_suppresserrors);
+ // Pass to code_stub.
}
$meta['site_id'] = get_current_blog_id();
@@ -1538,14 +1606,14 @@ private function dc_save($cache_key, $data, $group = 'default', $expire = 0, $ke
$meta['key'] = $cache_key;
$meta['type'] = $final_type;
- // if 0 let gc handle it by comparing file mtime
+ // If 0 let gc handle it by comparing file mtime
// and maxttl constants.
$meta['timeout'] = $timeout;
- // final data
+ // Before code_stub.
$meta['data'] = $data;
- // only count new file.
+ // Only count new file.
clearstatcache(true, $file);
$has_cache_file = is_file($file);
if (true === $this->dc_code($file, $meta)) {
@@ -1591,14 +1659,8 @@ private function dc_update($cache_key, $data, $group)
private function dc_precache_load($hash)
{
static $is_done = false;
- $logkey = $this->item_hash('docketcache-precache').'-'.$this->item_hash(__FUNCTION__);
- $logpref = __FUNCTION__.'():';
if ($is_done) {
- if ($this->is_dev) {
- $this->dc_log('debug', $logkey, $logpref.' Precache Ignored: Already loaded');
- }
-
return;
}
@@ -1610,9 +1672,7 @@ private function dc_precache_load($hash)
return;
}
- if ($this->is_dev) {
- $this->dc_log('debug', $logkey, $logpref.' Precache Load: Start');
- }
+ nwdcx_debuglog(__FUNCTION__.': Process started.');
$this->precache_loaded[$hash] = $keys;
@@ -1625,7 +1685,10 @@ private function dc_precache_load($hash)
break 2;
}
- if (!isset($cached[$cache_key.$cache_group]) && false !== $this->get($cache_key, $cache_group)) {
+ $force = false;
+ $found = false;
+ $doing_precache = true;
+ if (!isset($cached[$cache_key.$cache_group]) && false !== $this->get($cache_key, $cache_group, $force, $found, $doing_precache)) {
$cached[$cache_key.$cache_group] = 1;
}
@@ -1644,9 +1707,7 @@ private function dc_precache_load($hash)
}
}
- if ($this->is_dev) {
- $this->dc_log('debug', $logkey, $logpref.' Precache Load: End -> '.\count($cached));
- }
+ nwdcx_debuglog(__FUNCTION__.': Process ended. Loaded '.\count($cached));
unset($keys, $cached);
$is_done = true;
@@ -1750,9 +1811,6 @@ private function dc_precache_init()
return;
}
- $logkey = $this->item_hash('docketcache-precache').'-'.$this->item_hash(__FUNCTION__);
- $logpref = __FUNCTION__.'():';
-
$req_uri = $_SERVER['REQUEST_URI'];
$dostrip = !empty($_SERVER['QUERY_STRING']);
@@ -1766,14 +1824,10 @@ private function dc_precache_init()
];
if ($dostrip && !empty($_GET) && array_intersect_key($intersect_key, $_GET)) {
- $this->dc_log('info', $logkey, $logpref.' Bypass GET key');
-
return;
}
if (false !== strpos($req_uri, '/wp-json/') || false !== strpos($req_uri, '/wp-admin/admin-ajax.php') || false !== strpos($req_uri, '/xmlrpc.php') || false !== strpos($req_uri, '/wp-cron.php') || false !== strpos($req_uri, '/robots.txt') || false !== strpos($req_uri, '/favicon.ico')) {
- $this->dc_log('info', $logkey, $logpref.' Bypass Request');
-
return;
}
@@ -1813,11 +1867,10 @@ private function dc_precache_init()
*/
public function dc_close()
{
- // $this->fs()->close_buffer();
static $is_done = false;
if (!$is_done) {
- if ($this->is_precache && !empty($this->precache_hashkey) && !$this->fs()->suspend_cache_write() /* && $this->fs()->close_buffer() */) {
+ if ($this->is_precache && !empty($this->precache_hashkey) && !$this->fs()->suspend_cache_write()) {
$this->dc_precache_set($this->precache_hashkey);
}
@@ -1870,6 +1923,13 @@ private function dc_init()
$this->bypass_precache = $dcvalue;
}
+ if (class_exists('Nawawi\\DocketCache\\TransientDb')) {
+ $this->use_transientdb = $this->cf()->is_dctrue('TRANSIENTDB');
+ if ($this->cf()->is_dcarray('IGNORED_TRANSIENTDB', $dcvalue)) {
+ $this->bypass_transientdb = $dcvalue;
+ }
+ }
+
$this->cache_path = $this->fs()->define_cache_path($this->cf()->dcvalue('PATH'));
if ($this->multisite) {
$this->cache_path = nwdcx_network_dirpath($this->cache_path);
@@ -1995,59 +2055,6 @@ function ($post_id) {
);
}
- if ($this->cf()->is_dctrue('OPTWPQUERY')) {
- add_action(
- 'pre_get_posts',
- function (&$args) {
- if (\is_object($args)) {
- $args->no_found_rows = true;
- $args->order = 'ASC';
- } elseif (\is_array($args)) {
- $args['no_found_rows'] = true;
- $args['order'] = 'ASC';
- }
- },
- \PHP_INT_MIN
- );
-
- add_action(
- 'parse_query',
- function (&$args) {
- if (\is_object($args)) {
- $args->no_found_rows = true;
- $args->order = 'ASC';
- } elseif (\is_array($args)) {
- $args['no_found_rows'] = true;
- $args['order'] = 'ASC';
- }
- },
- \PHP_INT_MIN
- );
-
- add_action(
- 'pre_get_users',
- function ($wpq) {
- if (nwdcx_wpdb($wpdb) && !empty($wpq->query_vars['count_total'])) {
- $wpq->query_vars['count_total'] = false;
- $wpq->query_vars['nwdcx_count_total'] = true;
- }
- },
- \PHP_INT_MIN
- );
-
- add_action(
- 'pre_user_query',
- function ($wpq) {
- if (nwdcx_wpdb($wpdb) && !empty($wpq->query_vars['nwdcx_count_total'])) {
- unset($wpq->query_vars['nwdcx_count_total']);
- $sql = "SELECT COUNT(*) {$wpq->query_from} {$wpq->query_where}";
- $wpq->total_users = $wpdb->get_var($sql);
- }
- },
- \PHP_INT_MIN
- );
- }
-
// html comment
$this->add_signature = false;
if ($this->cf()->is_dctrue('SIGNATURE')) {
@@ -2066,7 +2073,6 @@ function () {
function () {
if ($this->add_signature && !$this->is_user_logged_in()) {
echo apply_filters('docketcache/filter/signature/htmlfooter', "\n\n");
- // $this->fs()->close_buffer();
}
},
\PHP_INT_MAX
diff --git a/includes/compat.php b/includes/compat.php
index 17879e2..2d67d96 100644
--- a/includes/compat.php
+++ b/includes/compat.php
@@ -19,6 +19,64 @@ class_alias('Nawawi\Symfony\Component\VarExporter\Internal\Hydrator', 'Nawawi\Do
class_alias('Nawawi\Symfony\Component\VarExporter\Internal\Registry', 'Nawawi\DocketCache\Exporter\Registry', false);
}
+if (!\function_exists('nwdcx_constfx')) {
+ function nwdcx_constfx($name, $is_strip = false)
+ {
+ if (!$is_strip) {
+ return strtoupper('docket_cache_'.$name);
+ }
+
+ // strip prefix, see Canopt().
+ return substr($name, 13);
+ }
+}
+
+if (!\function_exists('nwdcx_construe')) {
+ function nwdcx_construe($name)
+ {
+ $name = nwdcx_constfx($name);
+ if (\defined($name)) {
+ $value = (bool) \constant($name);
+ if (true === $value || 1 === $value) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
+if (!\function_exists('nwdcx_consfalse')) {
+ function nwdcx_consfalse($name)
+ {
+ $name = nwdcx_constfx($name);
+
+ return !\defined($name) || !\constant($name);
+ }
+}
+
+if (!\function_exists('nwdcx_constval')) {
+ function nwdcx_constval($name)
+ {
+ $name = nwdcx_constfx($name);
+ $value = '';
+ if (\defined($name)) {
+ $value = \constant($name);
+ }
+
+ return $value;
+ }
+}
+
+if (!\function_exists('nwdcx_consdef')) {
+ function nwdcx_consdef($name, $value)
+ {
+ $name = nwdcx_constfx($name);
+
+ return !\defined($name) && \define($name, $value);
+ }
+}
+
if (!\function_exists('nwdcx_arraymap')) {
function nwdcx_arraymap($func, $arr)
{
@@ -103,7 +161,7 @@ function nwdcx_unserialize($data)
}
}
- // make query-monitor happy.
+ // To make query monitor happy.
$nwdcx_suppresserrors = nwdcx_suppresserrors(true);
$data = @unserialize(trim($data));
@@ -187,12 +245,14 @@ function nwdcx_cleanuptransient()
return false;
}
+ $count = 0;
+ $qlimit = 1000;
$suppress = $wpdb->suppress_errors(true);
$collect = [];
// $results = $wpdb->get_results('SELECT `option_id`,`option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE `option_name` LIKE "_transient_%" OR `option_name` LIKE "_site_transient_%" ORDER BY `option_id` ASC LIMIT 1000', ARRAY_A);
- $results = $wpdb->get_results('SELECT `option_id`,`option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE `option_name` RLIKE "^(_site)?(_transient)(_timeout)?_.*?" ORDER BY `option_id` ASC LIMIT 5000', ARRAY_A);
+ $results = $wpdb->get_results('SELECT `option_id`,`option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE `option_name` RLIKE "^(_site)?(_transient)(_timeout)?_.*?" ORDER BY `option_id` ASC LIMIT '.$qlimit, ARRAY_A);
if (!empty($results) && \is_array($results)) {
while ($row = @array_shift($results)) {
@@ -211,6 +271,7 @@ function nwdcx_cleanuptransient()
$wpdb->query("DELETE FROM `{$wpdb->options}` WHERE `option_name`='_transient_timeout_{$key}'");
$wpdb->query("DELETE FROM `{$wpdb->options}` WHERE `option_name`='_site_transient_{$key}'");
$wpdb->query("DELETE FROM `{$wpdb->options}` WHERE `option_name`='_site_transient_timeout_{$key}'");
+ ++$count;
}
$wpdb->query('COMMIT');
}
@@ -220,7 +281,7 @@ function nwdcx_cleanuptransient()
if (is_multisite() && isset($wpdb->sitemeta)) {
// $results = $wpdb->get_results('SELECT `meta_id`,`meta_key`,`meta_value` FROM `'.$wpdb->sitemeta.'` WHERE `meta_key` LIKE "_site_transient_%" ORDER BY `meta_id` ASC LIMIT 1000', ARRAY_A);
- $results = $wpdb->get_results('SELECT `meta_id`,`meta_key`,`meta_value` FROM `'.$wpdb->sitemeta.'` WHERE `meta_key` RLIKE "^(_site_transient)(_timeout)?_.*?" ORDER BY `meta_id` ASC LIMIT 5000', ARRAY_A);
+ $results = $wpdb->get_results('SELECT `meta_id`,`meta_key`,`meta_value` FROM `'.$wpdb->sitemeta.'` WHERE `meta_key` RLIKE "^(_site_transient)(_timeout)?_.*?" ORDER BY `meta_id` ASC LIMIT '.$qlimit, ARRAY_A);
if (!empty($results) && \is_array($results)) {
while ($row = @array_shift($results)) {
$key = @preg_replace('@^(_site)?(_transient)(_timeout)?_@', '', $row['meta_key']);
@@ -236,6 +297,7 @@ function nwdcx_cleanuptransient()
foreach ($collect as $key) {
$wpdb->query("DELETE FROM `{$wpdb->sitemeta}` WHERE `meta_key`='_site_transient_{$key}'");
$wpdb->query("DELETE FROM `{$wpdb->sitemeta}` WHERE `meta_key`='_site_transient_timeout_{$key}'");
+ ++$count;
}
$wpdb->query('COMMIT');
}
@@ -245,7 +307,7 @@ function nwdcx_cleanuptransient()
unset($collect, $results);
$wpdb->suppress_errors($suppress);
- return true;
+ return $count;
}
}
@@ -265,10 +327,7 @@ function () use ($args) {
function nwdcx_throwable($name, $error)
{
if (\defined('WP_DEBUG') && WP_DEBUG) {
- if (!isset($GLOBALS['docketcache_throwable'])) {
- $GLOBALS['docketcache_throwable'] = [];
- }
- $GLOBALS['docketcache_throwable'][$name] = $error;
+ do_action('docketcache/action/nwdcx/throwable', $name, $error);
}
}
}
@@ -276,7 +335,7 @@ function nwdcx_throwable($name, $error)
if (!\function_exists('nwdcx_debuglog')) {
function nwdcx_debuglog($text)
{
- if (\defined('DOCKET_CACHE_DEV') && DOCKET_CACHE_DEV) {
+ if (nwdcx_construe('dev')) {
$logfile = WP_CONTENT_DIR.'/dcdev-debug.log';
error_log('['.date('Y-m-d H:i:s').'] '.$text."\n", 3, $logfile);
}
@@ -292,7 +351,7 @@ function nwdcx_cliverbose($text)
$is_verbose = 'cli' === \PHP_SAPI && !empty($_SERVER['argv']) && \in_array('--verbose', $_SERVER['argv']) && !\in_array('--quiet', $_SERVER['argv']);
}
- if ($is_verbose) {
+ if ($is_verbose && \defined('STDOUT')) {
fwrite(\STDOUT, $text);
}
}
@@ -307,63 +366,6 @@ function nwdcx_microtimetofloat($second)
}
}
-if (!\function_exists('nwdcx_constfx')) {
- function nwdcx_constfx($name, $is_strip = false)
- {
- if (!$is_strip) {
- return strtoupper('docket_cache_'.$name);
- }
-
- return substr($name, 13);
- }
-}
-
-if (!\function_exists('nwdcx_construe')) {
- function nwdcx_construe($name)
- {
- $name = nwdcx_constfx($name);
- if (\defined($name)) {
- $value = (bool) \constant($name);
- if (true === $value || 1 === $value) {
- return true;
- }
- }
-
- return false;
- }
-}
-
-if (!\function_exists('nwdcx_consfalse')) {
- function nwdcx_consfalse($name)
- {
- $name = nwdcx_constfx($name);
-
- return !\defined($name) || !\constant($name);
- }
-}
-
-if (!\function_exists('nwdcx_constval')) {
- function nwdcx_constval($name)
- {
- $name = nwdcx_constfx($name);
- $value = '';
- if (\defined($name)) {
- $value = \constant($name);
- }
-
- return $value;
- }
-}
-
-if (!\function_exists('nwdcx_consdef')) {
- function nwdcx_consdef($name, $value)
- {
- $name = nwdcx_constfx($name);
-
- return !\defined($name) && \define($name, $value);
- }
-}
-
if (!\function_exists('nwdcx_suppresserrors')) {
function nwdcx_suppresserrors($level = true)
{
diff --git a/includes/object-cache.php b/includes/object-cache.php
index 96efc15..2df2a8b 100644
--- a/includes/object-cache.php
+++ b/includes/object-cache.php
@@ -3,7 +3,7 @@
* @wordpress-plugin
* Plugin Name: Docket Cache Drop-in
* Plugin URI: https://wordpress.org/plugins/docket-cache/
- * Version: 22.07.03
+ * Version: 22.07.04
* Description: A persistent object cache stored as a plain PHP code, accelerates caching with OPcache backend.
* Author: Nawawi Jamili
* Author URI: https://docketcache.com
@@ -140,8 +140,8 @@ function ($option, $value) {
);
}
- // early cache transient/alloptions
if (class_exists('Nawawi\\DocketCache\\Becache')) {
+ // early cache transient/alloptions
add_action(
'shutdown',
function () {
@@ -152,13 +152,16 @@ function () {
},
\PHP_INT_MIN
);
- }
- // early cleanup transient
- if (\function_exists('nwdcx_cleanuptransient')) {
+ // early cleanup transient
add_action(
'shutdown',
- 'nwdcx_cleanuptransient',
+ function () {
+ try {
+ Nawawi\DocketCache\Becache::cleanup_transient();
+ } catch (\Throwable $e) {
+ }
+ },
\PHP_INT_MAX - 1
);
}
diff --git a/includes/src/Becache.php b/includes/src/Becache.php
index 7396fa2..be6cf70 100644
--- a/includes/src/Becache.php
+++ b/includes/src/Becache.php
@@ -9,7 +9,7 @@
*/
/*
- * This class is a minimal version of cache.php, only use for object-cache.php.
+ * This class is a minimal version of cache.php, only used for object-cache.php.
*
* Reference:
* wp-content/plugins/docket-cache/includes/cache.php
@@ -20,15 +20,16 @@
\defined('ABSPATH') || exit;
-class Becache
+final class Becache
{
private $cache_path;
private $cache_maxsize = 3145728;
private $cache_maxttl = 345600;
private $multisite = false;
private $blog_prefix;
- private $qlimit = 5000;
+ private $qlimit = 1000;
private static $inst;
+ private $network_id = 1;
private $max_execution_time = 0;
public function __construct()
@@ -53,6 +54,7 @@ public function __construct()
}
}
+ $this->network_id = (int) nwdcx_network_id();
$this->max_execution_time = $this->fs()->get_max_execution_time();
}
@@ -122,18 +124,7 @@ private function get_file_path($key, $group)
private function dump_code($file, $arr)
{
- // use (object) instead of VarExporter.
- if (\PHP_VERSION_ID >= 70433 && \in_array($arr['type'], ['object', 'array'])) {
- $arr_data = var_export($arr, true);
- if (!empty($arr_data) && false != strpos($arr_data, '(object) array(') && false === strpos($arr_data, '::__set_state')) {
- $data = $arr_data;
- }
- }
-
- if (!isset($data)) {
- $data = $this->fs()->export_var($arr, $error);
- }
-
+ $data = $this->fs()->export_var($arr, $error);
if (false === $data) {
return false;
}
@@ -183,6 +174,19 @@ private function store_cache($key, $data, $group, $expire = 0)
}
if (!empty($data)) {
+ $len = 0;
+ $nwdcx_suppresserrors = nwdcx_suppresserrors(true);
+ if (\function_exists('maybe_serialize')) {
+ $len = \strlen(@maybe_serialize($data));
+ } else {
+ $len = \strlen(@serialize($data));
+ }
+ nwdcx_suppresserrors($nwdcx_suppresserrors);
+
+ if ($len >= $this->cache_maxsize) {
+ return false;
+ }
+
if ('string' === $type) {
$data = nwdcx_unserialize($data);
} elseif ('array' === $type) {
@@ -195,32 +199,36 @@ private function store_cache($key, $data, $group, $expire = 0)
}
}
- $len = \strlen(serialize($data));
- if ($len >= $this->cache_maxsize) {
- return false;
- }
-
$meta = [];
$meta['timestamp'] = time();
if ($this->multisite) {
- try {
- $meta['network_id'] = get_current_network_id();
- } catch (\Throwable $e) {
- $meta['network_id'] = 0;
- }
+ $meta['network_id'] = $this->network_id;
}
$final_type = \gettype($data);
if ('string' === $final_type && nwdcx_serialized($data)) {
$final_type = 'string_serialize';
- } elseif ('array' === $final_type && (!\defined('DOCKET_CACHE_USE_CLASSMAP') || !DOCKET_CACHE_USE_CLASSMAP)) {
- if (false !== strpos(var_export($data, 1), 'Requests_Utility_CaseInsensitiveDictionary::__set_state')) {
- $data = @serialize($data);
- if (nwdcx_serialized($data)) {
- $final_type = 'array_serialize';
+ } elseif ('array' === $final_type) {
+ $nwdcx_suppresserrors = nwdcx_suppresserrors(true);
+ $export_data = @var_export($data, 1);
+ if (!empty($export_data)) {
+ if (false !== strpos($export_data, 'Requests_Utility_CaseInsensitiveDictionary::__set_state')) {
+ $data = @serialize($data);
+ if (nwdcx_serialized($data)) {
+ $final_type = 'array_serialize';
+ }
+ }
+
+ if ('array' === $final_type && $this->fs()->is_transient($group) && false !== strpos($export_data, '::__set_state')) {
+ $data = @serialize($data);
+ if (nwdcx_serialized($data)) {
+ $final_type = 'array_serialize';
+ }
}
}
+ unset($export_data);
+ nwdcx_suppresserrors($nwdcx_suppresserrors);
}
$meta['site_id'] = get_current_blog_id();
@@ -239,6 +247,10 @@ private function store_cache($key, $data, $group, $expire = 0)
public function export_transient()
{
+ if ($this->cf()->is_dctrue('TRANSIENTDB')) {
+ return false;
+ }
+
if (!nwdcx_wpdb($wpdb)) {
return false;
}
@@ -339,24 +351,41 @@ public function export_transient()
return true;
}
+ public static function cleanup_transient()
+ {
+ if (nwdcx_construe('TRANSIENTDB')) {
+ return false;
+ }
+
+ if (\function_exists('nwdcx_cleanuptransient')) {
+ return nwdcx_cleanuptransient();
+ }
+
+ return false;
+ }
+
public function export_alloptions()
{
if (!nwdcx_wpdb($wpdb) || $this->multisite) {
return false;
}
+ // Only export if autoload=yes and not transient.
$suppress = $wpdb->suppress_errors(true);
- $alloptions_db = $wpdb->get_results('SELECT `option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE autoload = \'yes\'', ARRAY_A);
+ $alloptions_db = $wpdb->get_results('SELECT `option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE autoload = \'yes\' AND `option_name` NOT LIKE "_transient_%" AND `option_name` NOT LIKE "_site_transient_%"', ARRAY_A);
if (empty($alloptions_db)) {
- $alloptions_db = $wpdb->get_results('SELECT `option_name`,`option_value` FROM `'.$wpdb->options.'`', ARRAY_A);
+ return false;
}
$wpdb->suppress_errors($suppress);
$alloptions = [];
- if (!empty($alloptions_db) && \is_array($alloptions_db)) {
- $wp_options = $this->fs()->keys_alloptions();
+ if (\is_array($alloptions_db)) {
$is_filter = $this->cf()->is_dctrue('WPOPTALOAD', true);
+ $wp_options = [];
+ if ($is_filter) {
+ $wp_options = $this->fs()->keys_alloptions();
+ }
foreach ($alloptions_db as $num => $options) {
if ($this->max_execution_time > 0 && \defined('WP_START_TIMESTAMP') && (microtime(true) - WP_START_TIMESTAMP) > $this->max_execution_time) {
$alloptions = [];
diff --git a/includes/src/Bepart.php b/includes/src/Bepart.php
index 88fe3bd..d3e0f36 100644
--- a/includes/src/Bepart.php
+++ b/includes/src/Bepart.php
@@ -14,6 +14,43 @@
class Bepart extends Filesystem
{
+ /**
+ * is_request_from_theme_editor.
+ */
+ public function is_request_from_theme_editor()
+ {
+ if (!empty($_POST)) {
+ if (!empty($_POST['_wp_http_referer'])) {
+ $wp_referer = $_POST['_wp_http_referer'];
+ if ((false !== strpos($wp_referer, '/theme-editor.php?file=') || false !== strpos($wp_referer, '/plugin-editor.php?file=')) && (!empty($_POST['newcontent']) && false !== strpos($_POST['newcontent'], 'is_request_from_theme_editor()) {
+ return @fastcgi_finish_request();
+ }
+
+ return false;
+ }
+
/**
* close_exit.
*/
diff --git a/includes/src/Canopt.php b/includes/src/Canopt.php
index 0d6cca3..c065edb 100644
--- a/includes/src/Canopt.php
+++ b/includes/src/Canopt.php
@@ -83,8 +83,6 @@ public function keys($key = false)
'log_time' => esc_html__('Log Timestamp', 'docket-cache'),
'log_all' => esc_html__('Log All', 'docket-cache'),
'preload' => esc_html__('Admin Page Cache Preloading', 'docket-cache'),
- 'advcpost' => esc_html__('Advanced Post Caching', 'docket-cache'),
- 'advpost_posttype_all' => esc_html__('Post Caching Any Post Type', 'docket-cache'),
'menucache' => esc_html__('WordPress Menu Caching', 'docket-cache'),
'optermcount' => esc_html__('Optimize Term Count Queries', 'docket-cache'),
'precache' => esc_html__('Object Cache Precaching', 'docket-cache'),
@@ -106,10 +104,10 @@ public function keys($key = false)
'stats' => esc_html__('Object Cache Data Stats', 'docket-cache'),
'gcaction' => esc_html__('Garbage Collector Action Button', 'docket-cache'),
'flushaction' => esc_html__('Additional Flush Cache Action Button', 'docket-cache'),
- /* 'autoupdate' => esc_html__('Docket Cache Auto Update', 'docket-cache'), */
'autoupdate_toggle' => esc_html__('Docket Cache Auto Update', 'docket-cache'),
'checkversion' => esc_html__('Critical Version Checking', 'docket-cache'),
'optwpquery' => esc_html__('Optimize WP Query', 'docket-cache'),
+ 'limitbulkedit' => esc_html__('Limit Bulk Edit Actions', 'docket-cache'),
'pingback' => esc_html__('Deactivate XML-RPC / Pingbacks', 'docket-cache'),
'headerjunk' => esc_html__('Deactivate WP Header Junk', 'docket-cache'),
'wpemoji' => esc_html__('Deactivate WP Emoji', 'docket-cache'),
@@ -121,6 +119,7 @@ public function keys($key = false)
'wpdashboardnews' => esc_html__('Deactivate WP Events & News Feed Dashboard', 'docket-cache'),
'wpbrowsehappy' => esc_html__('Deactivate Browse Happy Checking', 'docket-cache'),
'wpservehappy' => esc_html__('Deactivate Serve Happy Checking', 'docket-cache'),
+ 'postviaemail' => esc_html__('Deactivate Post Via Email', 'docket-cache'),
'objectcacheoff' => esc_html__('Suspend Object Cache', 'docket-cache'),
'flush_shutdown' => esc_html__('Flush Object Cache During Deactivation', 'docket-cache'),
'opcshutdown' => esc_html__('Flush OPcache During Deactivation', 'docket-cache'),
@@ -131,8 +130,8 @@ public function keys($key = false)
'flush_stalecache' => esc_html__('Auto Remove Stale Cache', 'docket-cache'),
'stalecache_ignore' => esc_html__('Exclude Stale Cache', 'docket-cache'),
'emptycache_ignore' => esc_html__('Exclude Empty Object Data', 'docket-cache'),
+ 'transientdb' => esc_html__('Retain Transients in Db', 'docket-cache'),
'limithttprequest' => esc_html__('Limit WP-Admin HTTP requests', 'docket-cache'),
- 'httpheadersexpect' => esc_html__('HTTP Request Expect header tweaks', 'docket-cache'),
'rtpostautosave' => esc_html__('Auto Save Interval', 'docket-cache'),
'rtpostrevision' => esc_html__('Post Revisions', 'docket-cache'),
'rtpostemptytrash' => esc_html__('Trash Bin', 'docket-cache'),
@@ -147,6 +146,15 @@ public function keys($key = false)
'rtdisablewpcron' => esc_html__('Deactivate WP Cron', 'docket-cache'),
];
+ if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
+ $data['advcpost'] = esc_html__('Advanced Post Caching', 'docket-cache');
+ $data['advpost_posttype_all'] = esc_html__('Post Caching Any Post Type', 'docket-cache');
+ }
+
+ if (version_compare($GLOBALS['wp_version'], '5.8', '<')) {
+ $data['httpheadersexpect'] = esc_html__('HTTP Request Expect header tweaks', 'docket-cache');
+ }
+
$data = apply_filters('docketcache/filter/optionkeys', $data);
if (false !== $key) {
@@ -456,6 +464,8 @@ public function reset()
}
}
+ clearstatcache(true);
+
return $ok;
}
}
diff --git a/includes/src/Command.php b/includes/src/Command.php
index 60ea490..0e6fc67 100644
--- a/includes/src/Command.php
+++ b/includes/src/Command.php
@@ -342,7 +342,7 @@ public function runtime_install()
public function flush_precache()
{
if (!\function_exists('wp_cache_flush_group') || !method_exists('WP_Object_Cache', 'dc_remove_group')) {
- $this->halt_error(__('Object Precache could not be flushed. This action require Docket Cache object-cache.php Drop-in.', 'docket-cache'));
+ $this->halt_error(__('Object Precache could not be flushed. Docket Cache object-cache.php Drop-in is inactive.', 'docket-cache'));
}
$this->print_stdout(__('Flushing precache. Please wait..', 'docket-cache'), false);
@@ -369,7 +369,7 @@ public function flush_precache()
public function flush_transient()
{
if (!\function_exists('wp_cache_flush_group') || !method_exists('WP_Object_Cache', 'dc_remove_group')) {
- $this->halt_error(__('Transient could not be flushed. This action require Docket Cache object-cache.php Drop-in.', 'docket-cache'));
+ $this->halt_error(__('Transient could not be flushed. Docket Cache object-cache.php Drop-in is inactive.', 'docket-cache'));
}
$this->print_stdout(__('Flushing transient. Please wait..', 'docket-cache'), false);
@@ -396,7 +396,7 @@ public function flush_transient()
public function flush_advcpost()
{
if (!\function_exists('wp_cache_flush_group_match') || !method_exists('WP_Object_Cache', 'dc_remove_group')) {
- $this->halt_error(__('Advanced Post Cache could not be flushed. This action require Docket Cache object-cache.php Drop-in.', 'docket-cache'));
+ $this->halt_error(__('Advanced Post Cache could not be flushed. Docket Cache object-cache.php Drop-in is inactive.', 'docket-cache'));
}
$this->print_stdout(__('Flushing Advanced Post Cache. Please wait..', 'docket-cache'), false);
@@ -423,7 +423,7 @@ public function flush_advcpost()
public function flush_menucache()
{
if (!\function_exists('wp_cache_flush_group') || !method_exists('WP_Object_Cache', 'dc_remove_group')) {
- $this->halt_error(__('Menu Cache could not be flushed. This action require Docket Cache object-cache.php Drop-in.', 'docket-cache'));
+ $this->halt_error(__('Menu Cache could not be flushed. Docket Cache object-cache.php Drop-in is inactive.', 'docket-cache'));
}
$this->print_stdout(__('Flushing Menu Cache. Please wait..', 'docket-cache'), false);
@@ -450,7 +450,7 @@ public function flush_menucache()
public function flush_mocache()
{
if (!\function_exists('wp_cache_flush_group') || !method_exists('WP_Object_Cache', 'dc_remove_group')) {
- $this->halt_error(__('Translation Cache could not be flushed. This action require Docket Cache object-cache.php Drop-in.', 'docket-cache'));
+ $this->halt_error(__('Translation Cache could not be flushed. Docket Cache object-cache.php Drop-in is inactive.', 'docket-cache'));
}
$this->print_stdout(__('Flushing Translation Cache. Please wait..', 'docket-cache'), false);
diff --git a/includes/src/Constans.php b/includes/src/Constans.php
index 8710cc9..9f6fc60 100644
--- a/includes/src/Constans.php
+++ b/includes/src/Constans.php
@@ -318,6 +318,19 @@ public function register_default()
]
);
+ // transient in DB.
+ $this->maybe_define($this->px('TRANSIENTDB'), false);
+
+ // exclude transient in DB.
+ $this->maybe_define($this->px('IGNORED_TRANSIENTDB'),
+ [
+ 'doing_cron',
+ 'update_plugins',
+ 'update_themes',
+ 'update_core',
+ ]
+ );
+
// misc tweaks
$this->maybe_define($this->px('MISC_TWEAKS'), true);
@@ -345,33 +358,6 @@ public function register_default()
// post missed schedule
$this->maybe_define($this->px('POSTMISSEDSCHEDULE'), false);
- // advanced post cache
- $this->maybe_define($this->px('ADVCPOST'), false);
-
- // advanced post cache allow post type
- $this->maybe_define(
- $this->px('ADVCPOST_POSTTYPE'),
- [
- 'post',
- 'page',
- 'attachment',
- 'revision',
- 'nav_menu_item',
- 'custom_css',
- 'customize_changeset',
- 'oembed_cache',
- 'user_request',
- 'wp_block',
- 'wp_template',
- 'wp_template_part',
- 'wp_global_styles',
- 'wp_navigation',
- ]
- );
-
- // advanced post cache allow all post type
- $this->maybe_define($this->px('ADVCPOST_POSTTYPE_ALL'), false);
-
// optimize term count
$this->maybe_define($this->px('OPTERMCOUNT'), true);
@@ -430,6 +416,12 @@ public function register_default()
// optimize post query
$this->maybe_define($this->px('OPTWPQUERY'), true);
+ // limit bulk edit
+ $this->maybe_define($this->px('LIMITBULKEDIT'), false);
+
+ // limit bulk edit bulk limit
+ $this->maybe_define($this->px('LIMITBULKEDIT_LIMIT'), 100);
+
// xmlrpc pingbacks
$this->maybe_define($this->px('PINGBACK'), true);
@@ -463,15 +455,15 @@ public function register_default()
// whitelist host from limit http request.
$this->maybe_define($this->px('LIMITHTTPREQUEST_WHITELIST'), []/* ['feeds.feedburner.com'] */);
- // curl "Expect" header performance tweak
- $this->maybe_define($this->px('HTTPHEADERSEXPECT'), false);
-
// wp browse-happy
$this->maybe_define($this->px('WPBROWSEHAPPY'), false);
// wp serve-happy
$this->maybe_define($this->px('WPSERVEHAPPY'), false);
+ // post vis email
+ $this->maybe_define($this->px('POSTVIAEMAIL'), false);
+
// cache http response from wp_remote_request.
$this->maybe_define($this->px('CACHEHTTPRESPONSE'), false);
@@ -484,6 +476,43 @@ public function register_default()
// cache http exclude list.
$this->maybe_define($this->px('CACHEHTTPRESPONS_EXCLUDE'), []);
+ // @compat: wp version < 6.1 || < 5.8
+ if (isset($GLOBALS['wp_version'])) {
+ if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
+ // advanced post cache
+ $this->maybe_define($this->px('ADVCPOST'), false);
+
+ // advanced post cache allow post type
+ $this->maybe_define(
+ $this->px('ADVCPOST_POSTTYPE'),
+ [
+ 'post',
+ 'page',
+ 'attachment',
+ 'revision',
+ 'nav_menu_item',
+ 'custom_css',
+ 'customize_changeset',
+ 'oembed_cache',
+ 'user_request',
+ 'wp_block',
+ 'wp_template',
+ 'wp_template_part',
+ 'wp_global_styles',
+ 'wp_navigation',
+ ]
+ );
+
+ // advanced post cache allow all post type
+ $this->maybe_define($this->px('ADVCPOST_POSTTYPE_ALL'), false);
+ }
+
+ if (version_compare($GLOBALS['wp_version'], '5.8', '<')) {
+ // curl "Expect" header performance tweak
+ $this->maybe_define($this->px('HTTPHEADERSEXPECT'), false);
+ }
+ }
+
// @private: auto save interval.
$this->maybe_define($this->px('RTPOSTAUTOSAVE'), 1);
diff --git a/includes/src/Crawler.php b/includes/src/Crawler.php
index 4120e69..fe84922 100644
--- a/includes/src/Crawler.php
+++ b/includes/src/Crawler.php
@@ -14,7 +14,7 @@
final class Crawler
{
- private static $version = '22.07.03';
+ private static $version = '22.07.04';
public static $send_cookie = false;
private static function default_args($param = [])
diff --git a/includes/src/CronAgent.php b/includes/src/CronAgent.php
index 8aba342..cf92c42 100644
--- a/includes/src/CronAgent.php
+++ b/includes/src/CronAgent.php
@@ -520,15 +520,7 @@ private function check_connection()
}
// only main site
- if (!is_main_site()) {
- return;
- }
-
- if ($this->is_ping_request()) {
- return;
- }
-
- if ($this->pt->cf()->is_true('WP_IMPORTING')) {
+ if (!is_main_site() || $this->pt->cf()->is_true('WP_IMPORTING') || $this->pt->is_request_from_theme_editor() || $this->is_ping_request()) {
return;
}
diff --git a/includes/src/Event.php b/includes/src/Event.php
index d610f6e..8c21d0d 100644
--- a/includes/src/Event.php
+++ b/includes/src/Event.php
@@ -565,7 +565,7 @@ public function garbage_collector($force = false)
// release
$this->pt->suspend_cache_write(false);
- if (\function_exists('nwdcx_cleanuptransient')) {
+ if ($this->pt->cf()->is_dcfalse('TRANSIENTDB') && \function_exists('nwdcx_cleanuptransient')) {
nwdcx_cliverbose("run-gc: cleanup expired transients in DB\n");
nwdcx_cleanuptransient();
}
@@ -649,7 +649,7 @@ public function delete_expired_transients_db()
return false;
}
- if (\function_exists('nwdcx_cleanuptransient')) {
+ if ($this->pt->cf()->is_dcfalse('TRANSIENTDB') && \function_exists('nwdcx_cleanuptransient')) {
nwdcx_cleanuptransient();
} elseif (\function_exists('delete_expired_transients')) {
delete_expired_transients(true);
diff --git a/includes/src/Filesystem.php b/includes/src/Filesystem.php
index 16de391..ea8a2ef 100644
--- a/includes/src/Filesystem.php
+++ b/includes/src/Filesystem.php
@@ -16,55 +16,6 @@
class Filesystem
{
- /**
- * is_request_from_theme_editor.
- */
- public function is_request_from_theme_editor()
- {
- if (!empty($_POST)) {
- if (!empty($_POST['_wp_http_referer'])) {
- $wp_referer = $_POST['_wp_http_referer'];
- if ((false !== strpos($wp_referer, '/theme-editor.php?file=') || false !== strpos($wp_referer, '/plugin-editor.php?file=')) && (!empty($_POST['newcontent']) && false !== strpos($_POST['newcontent'], 'is_request_from_theme_editor()) {
- return @fastcgi_finish_request();
- }
-
- return false;
- }
-
- /**
- * close_buffer.
- */
- public function close_buffer()
- {
- if (!@ob_get_level() && $this->fastcgi_close()) {
- return true;
- }
-
- return false;
- }
-
/**
* is_docketcachedir.
*/
@@ -135,9 +86,25 @@ public function is_docketcachegroup($group, $key = '')
*/
public function is_transient($group)
{
+ if (\is_array($group)) {
+ return \in_array($group, ['transient', 'site-transient']);
+ }
+
return 'transient' === $group || 'site-transient' === $group;
}
+ /**
+ * is_wp_options.
+ */
+ public function is_wp_options($group)
+ {
+ if (\is_array($group)) {
+ return \in_array($group, ['options', 'site-options']);
+ }
+
+ return 'options' === $group || 'site-options' === $group;
+ }
+
/**
* is_dirempty.
*/
@@ -249,8 +216,14 @@ public function chmod($file, $mode = false)
clearstatcache();
$nwdcx_suppresserrors = nwdcx_suppresserrors(true);
-
- $ok = @chmod($file, $mode);
+ $ok = false;
+ try {
+ if (@is_file($file)) {
+ $ok = @chmod($file, $mode);
+ }
+ } catch (\Throwable $e) {
+ nwdcx_throwable(__METHOD__, $e);
+ }
nwdcx_suppresserrors($nwdcx_suppresserrors);
@@ -389,15 +362,36 @@ public function validate_file($filename)
*/
public function export_var($data, &$error = '')
{
+ // 28022023, self-note to future me.
+ // We use native var_export to improve cache writing, since VarExporter::export will use preg_replace_callback on string types and
+ // ReflectionClass to resolve class instances. Cached data may look not pretty.
+ try {
+ if (version_compare(\PHP_VERSION, '7.3.0', '>=') && !empty($data['type']) && \in_array($data['type'], ['object', 'array', 'string', 'string_serialize', 'array_serialize', 'integer', 'boolean'])) {
+ $nwdcx_suppresserrors = nwdcx_suppresserrors(true);
+ $arr_data = @var_export($data, true);
+ nwdcx_suppresserrors($nwdcx_suppresserrors);
+ // Return exported data, if doesn't have a class instance.
+ if (!empty($arr_data) && false === strpos($arr_data, '::__set_state')) {
+ return $arr_data;
+ }
+ }
+ } catch (\Throwable $e) {
+ nwdcx_throwable(__METHOD__, $e);
+ }
+
+ // If native var_export failed or not from cache.
try {
$data = VarExporter::export($data);
} catch (\Throwable $e) {
nwdcx_throwable(__METHOD__, $e);
$error = $e->getMessage();
+ // php < 7.3
if (false !== strpos($error, 'Cannot export value of type "stdClass"')) {
- $data = var_export($data, 1);
+ $nwdcx_suppresserrors = nwdcx_suppresserrors(true);
+ $data = @var_export($data, true);
$data = str_replace('stdClass::__set_state', '(object)', $data);
+ nwdcx_suppresserrors($nwdcx_suppresserrors);
} else {
$this->log('err', '000000000000-000000000000', 'export_var: '.$error);
@@ -421,6 +415,11 @@ public function export_var($data, &$error = '')
*/
public function shutdown_cleanup($file, $seq = 10)
{
+ // for dump().
+ if (empty($this->filesize($file))) {
+ return false;
+ }
+
// dont use register_shutdown_function to avoid issue with page cache plugin
add_action(
'shutdown',
@@ -434,6 +433,8 @@ function () use ($file) {
},
$seq
);
+
+ return true;
}
/**
@@ -949,8 +950,6 @@ public function opcache_cleanup()
add_action(
'shutdown',
function () {
- // anything involve disk, don't go into background
- // $this->close_buffer();
$this->opcache_reset();
},
\PHP_INT_MAX
@@ -1316,44 +1315,38 @@ public function code_stub($data = '')
{
$is_debug = \defined('WP_DEBUG') && WP_DEBUG;
$is_data = !empty($data);
-
- $class_map = [
- 'Requests_Utility_CaseInsensitiveDictionary' => 'Requests/Utility/CaseInsensitiveDictionary.php',
- 'Requests_Response' => ' Requests/Response.php',
- 'Requests_Response_Headers' => 'Requests/Response/Headers.php',
- 'Requests_Cookie_Jar' => 'Requests/Cookie/Jar.php',
- 'WP_HTTP_Requests_Response' => 'class-wp-http-requests-response.php',
- 'WP_Post' => 'class-wp-post.php',
- ];
+ $is_precache = nwdcx_construe('PRECACHE');
+ // capture class not exist.
+ if (($is_debug || $is_precache) && empty($GLOBALS['DOCKET_CACHE_CODESTUB_FALSE'])) {
+ $GLOBALS['DOCKET_CACHE_CODESTUB_FALSE'] = [];
+ }
$ucode = '';
if ($is_data && false !== strpos($data, 'Registry::p(')) {
- if (@preg_match_all('@Registry::p\(\'([a-zA-Z_]+)\'\)@', $data, $mm)) {
+ if (@preg_match_all('@Registry::p\(\'([a-zA-Z0-9_]+)\'\)@', $data, $mm)) {
if (!empty($mm) && isset($mm[1]) && \is_array($mm[1])) {
$cls = $mm[1];
foreach ($cls as $clsname) {
if ('stdClass' !== $clsname) {
- if (\defined('DOCKET_CACHE_USE_CLASSMAP') && DOCKET_CACHE_USE_CLASSMAP) {
- $clspath = '';
- if (\defined('DOCKET_CACHE_USE_REFLECTIONCLASS') && DOCKET_CACHE_USE_REFLECTIONCLASS) {
- $reflector = new \ReflectionClass($clsname);
- $clsfname = $reflector->getFileName();
- if (false !== $clsfname) {
- $clspath = str_replace(ABSPATH, '', $clsfname);
- }
- }
-
- if (empty($clspath) && !empty($class_map[$clsname])) {
- $clspath = WPINC.'/'.$class_map[$clsname];
- }
-
- if (!empty($clspath)) {
- $clsfname = $clspath;
- $ucode .= "if ( !@class_exists('".$clsname."', false) && @file_exists(ABSPATH.'".$clsfname."') ) { @include_once(ABSPATH.'".$clsfname."'); }".\PHP_EOL;
+ $clsfname = false;
+ if ($is_debug) {
+ $reflector = new \ReflectionClass($clsname);
+ $clsfname = $reflector->getFileName();
+ if (false !== $clsfname) {
+ $clsfname = str_replace(ABSPATH, '', $clsfname);
+ $ucode .= '/* f: '.$clsfname.' */'.\PHP_EOL;
}
}
- $ucode .= "if ( !@class_exists('".$clsname."', false) ) { return false; }".\PHP_EOL;
+ // 13022023, self-note to future me.
+ // The logic here, we can't just "include_once" a class if it doesn't exist
+ // because if the main code uses "include" or "require" it will throw an error
+ // since the class has already been loaded by us.
+ $ucode .= "if(!@class_exists('".$clsname."',false)){";
+ if ($is_debug || $is_precache) {
+ $ucode .= "\$GLOBALS['DOCKET_CACHE_CODESTUB_FALSE'][__FILE__]=['".$clsname."','".$clsfname."'];";
+ }
+ $ucode .= 'return false;}'.\PHP_EOL;
}
}
unset($cls, $clsname);
@@ -1365,7 +1358,7 @@ public function code_stub($data = '')
$code = ' 20) {
+ $this->limit = $limit;
+ }
+ }
+
+ public function register()
+ {
+ // min 20.
+ if ($this->limit > 20) {
+ add_action('wp_loaded', [$this, 'limit_bulk_edit_for_registered_post_types']);
+ }
+ }
+
+ public function limit_bulk_edit_for_registered_post_types()
+ {
+ $types = get_post_types([
+ 'show_ui' => true,
+ ]);
+
+ foreach ($types as $type) {
+ add_filter('bulk_actions-edit-'.$type, [$this, 'limit_bulk_edit']);
+ add_action('admin_notices', [$this, 'bulk_edit_admin_notice']);
+ }
+ }
+
+ private function cleanup_dismissed_pointers()
+ {
+ $id = $this->notice_id;
+ $user_id = get_current_user_id();
+ $pointers = array_filter(explode(',', (string) get_user_meta($user_id, 'dismissed_wp_pointers', true)));
+ if (\in_array($id, $pointers, true)) {
+ $index = array_search($id, $pointers);
+ unset($pointers[$index]);
+ $pointers = implode(',', $pointers);
+ update_user_meta($user_id, 'dismissed_wp_pointers', $pointers);
+ }
+ }
+
+ private function bulk_editing_is_limited()
+ {
+ if (isset($GLOBALS['wp_query']) && ($GLOBALS['wp_query'] instanceof WP_Query)) {
+ $total_posts = $GLOBALS['wp_query']->found_posts;
+
+ if (isset($total_posts) && $this->limit > $total_posts) {
+ $this->cleanup_dismissed_pointers();
+
+ return false;
+ }
+ }
+
+ // Get default per page.
+ if (!empty($_GET['post_type'])) {
+ $post_type = filter_var($_GET['post_type'], \FILTER_SANITIZE_STRING);
+ // See wp-admin/includes/post.php -> wp_edit_posts_query().
+ $option = 'edit_'.$post_type.'_per_page';
+ $per_page = (int) get_user_option($option);
+ if (empty($per_page) || $per_page < 1) {
+ $per_page = 20;
+ }
+ } else {
+ $per_page = get_query_var('posts_per_page');
+ }
+
+ // Get per page when use wp_list_table.
+ if (isset($GLOBALS['wp_list_table']) && ($GLOBALS['wp_list_table'] instanceof WP_Posts_List_Table)) {
+ $per_page = isset($GLOBALS['wp_list_table']->_pagination_args['per_page']) ? $GLOBALS['wp_list_table']->_pagination_args['per_page'] : $per_page;
+ }
+
+ if (-1 === $per_page || $per_page > $this->limit) {
+ return true;
+ }
+
+ $this->cleanup_dismissed_pointers();
+
+ return false;
+ }
+
+ public function limit_bulk_edit($bulk_actions)
+ {
+ if ($this->bulk_editing_is_limited()) {
+ $bulk_actions = [];
+ }
+
+ return $bulk_actions;
+ }
+
+ public function bulk_edit_admin_notice()
+ {
+ if (!$this->bulk_editing_is_limited()) {
+ return;
+ }
+
+ $id = $this->notice_id;
+
+ $dismissed_pointers = array_filter(explode(',', (string) get_user_meta(get_current_user_id(), 'dismissed_wp_pointers', true)));
+ if (\in_array($id, $dismissed_pointers, true)) {
+ return;
+ }
+
+ $msg = sprintf(
+ /* translators: %d = number of items */
+ __('Docket Cache: Bulk actions are disabled because more than %d items have been listed. To re-enable bulk editing, please adjust the "Number of items" setting under "Screen Options".', 'docket-cache'),
+ (int) $this->limit
+ );
+ $js_id = esc_js($id);
+ $code = '';
+
+ echo Resc::boxmsg(['id' => $id, 'text' => $msg, 'extra_after' => $code], 'error', true, false, false);
+ }
+}
diff --git a/includes/src/MenuCache.php b/includes/src/MenuCache.php
index 721e1eb..afe242a 100644
--- a/includes/src/MenuCache.php
+++ b/includes/src/MenuCache.php
@@ -14,24 +14,28 @@
final class MenuCache
{
- public function __construct()
- {
- }
-
public function register()
{
if ($this->is_front_end()) {
- add_action('init', function () {
- add_filter('pre_wp_nav_menu', [$this, 'pre_wp_nav_menu'], \PHP_INT_MAX, 2);
- add_filter('wp_nav_menu', [$this, 'wp_nav_menu'], \PHP_INT_MAX, 2);
- }, \PHP_INT_MAX);
+ add_action(
+ 'init',
+ function () {
+ add_filter('pre_wp_nav_menu', [$this, 'pre_wp_nav_menu'], \PHP_INT_MAX, 2);
+ add_filter('wp_nav_menu', [$this, 'wp_nav_menu'], \PHP_INT_MAX, 2);
+ },
+ \PHP_INT_MAX
+ );
}
- add_action('admin_init', function () {
- add_action('wp_update_nav_menu', [$this, 'wp_update_nav_menu'], \PHP_INT_MAX);
- add_action('wp_delete_nav_menu', [$this, 'wp_update_nav_menu'], \PHP_INT_MAX);
- add_filter('pre_set_theme_mod_nav_menu_locations', [$this, 'pre_set_theme_mod_nav_menu_locations'], \PHP_INT_MAX, 2);
- }, \PHP_INT_MAX);
+ add_action(
+ 'admin_init',
+ function () {
+ add_action('wp_update_nav_menu', [$this, 'wp_update_nav_menu'], \PHP_INT_MAX);
+ add_action('wp_delete_nav_menu', [$this, 'wp_update_nav_menu'], \PHP_INT_MAX);
+ add_filter('pre_set_theme_mod_nav_menu_locations', [$this, 'pre_set_theme_mod_nav_menu_locations'], \PHP_INT_MAX, 2);
+ },
+ \PHP_INT_MAX
+ );
}
private function is_front_end()
diff --git a/includes/src/MoCache.php b/includes/src/MoCache.php
index b07bfbe..b2b1369 100644
--- a/includes/src/MoCache.php
+++ b/includes/src/MoCache.php
@@ -36,6 +36,10 @@ public function __construct($mofile, $domain, $override)
$cache_key = $domain.'-'.basename($this->mofile, '.mo');
$cache_group = 'docketcache-mo';
+ if (\function_exists('wp_cache_add_global_groups')) {
+ wp_cache_add_global_groups($cache_group);
+ }
+
$mtime = @filemtime($this->mofile);
$cache = wp_cache_get($cache_key, $cache_group);
if (false !== $cache && !empty($cache['data'])) {
@@ -80,7 +84,8 @@ public function translate_plural($singular, $plural, $count, $context = null)
private function text_key($args)
{
- return substr(md5(serialize([$args, $this->domain])), 0, 12);
+ // return substr(md5(serialize([$args, $this->domain])), 0, 12);
+ return md5(serialize([$args, $this->domain]));
}
private function get_translation($text_key, $text, $args)
diff --git a/includes/src/Plugin.php b/includes/src/Plugin.php
index 49efeb2..444f409 100644
--- a/includes/src/Plugin.php
+++ b/includes/src/Plugin.php
@@ -1045,7 +1045,7 @@ private function register_init()
$this->notice = '';
$this->inruntime = false;
- add_filter(
+ /*add_filter(
'perflab_oc_site_status_available_object_cache_services',
function ($services) {
$services[] = 'docket-cache';
@@ -1053,7 +1053,9 @@ function ($services) {
return $services;
},
\PHP_INT_MAX
- );
+ );*/
+
+ add_filter('perflab_disable_object_cache_dropin', '__return_true');
}
/**
@@ -1081,8 +1083,6 @@ private function plugin_upgrade()
add_action(
'shutdown',
function () {
- // $this->close_buffer();
-
if ($this->cf()->is_dcfalse('OBJECTCACHEOFF', true)) {
$this->cx()->install(true);
if (is_multisite()) {
@@ -1244,6 +1244,7 @@ function () {
);
}
+ // low priority
add_action(
'plugins_loaded',
function () {
@@ -1322,6 +1323,16 @@ function ($option, $auto_updates, $old_auto_updates, $network_id) {
4
);
+ // fix index.
+ add_filter(
+ 'pre_update_site_option_auto_update_plugins',
+ function ($value, $old_value, $option, $network_id) {
+ return array_values($value);
+ },
+ 10,
+ 4
+ );
+
add_filter(
'auto_update_plugin',
function ($update, $item) {
@@ -1337,7 +1348,7 @@ function ($update, $item) {
2
);
- if (class_exists('Nawawi\\DocketCache\\CronAgent')) {
+ if ($this->cf()->is_dctrue('CRONBOT') && class_exists('Nawawi\\DocketCache\\CronAgent')) {
( new CronAgent($this) )->register();
}
@@ -1660,7 +1671,8 @@ function () {
if (isset($message)) {
echo Resc::boxmsg($message, 'warning', false, false, false);
}
- }
+ },
+ \PHP_INT_MAX
);
},
\PHP_INT_MAX
@@ -1696,6 +1708,31 @@ function ($hook) {
}
);
+ add_filter(
+ 'script_loader_tag',
+ function ($tag, $handle) {
+ if (\in_array($handle, ['docket-cache-core', 'docket-cache-worker', 'docket-cache-loader'])) {
+ $tag = str_replace('