PluginProbe
Docket Cache – Object Cache Accelerator / 24.07.07
Docket Cache – Object Cache Accelerator v24.07.07
26.04.05 trunk 22.07.01 22.07.02 22.07.03 22.07.04 22.07.05 23.08.01 23.08.02 24.07.01 24.07.02 24.07.03 24.07.04 24.07.05 24.07.06 24.07.07 26.04.03 26.04.04
docket-cache / includes / src / Canopt.php

Canopt.php in Docket Cache – Object Cache Accelerator 24.07.07, at includes/src/Canopt.php

554 lines 16.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Docket Cache.
4 *
5 * @author Nawawi Jamili
6 * @license MIT
7 *
8 * @see https://github.com/nawawi/docket-cache
9 */
10
11 namespace Nawawi\DocketCache;
12
13 \defined('ABSPATH') || exit;
14
15 final class Canopt extends Bepart
16 {
17 public $file;
18 public $path;
19 public $path_lock;
20
21 private static $inst;
22
23 public function __construct()
24 {
25 $this->define_path();
26 }
27
28 private function define_path()
29 {
30 $path = '';
31 $constfx = nwdcx_constfx('DATA_PATH');
32 if (\defined($constfx)) {
33 $path = \constant($constfx);
34 }
35
36 if (!empty($path)) {
37 if ('docket-cache-data' !== basename($path)) {
38 $path = rtrim($path, '/\\').'/docket-cache-data';
39 }
40 } else {
41 $path = rtrim(DOCKET_CACHE_CONTENT_PATH, '/\\').'/docket-cache-data';
42 }
43
44 $path = wp_normalize_path($path);
45
46 if (is_multisite()) {
47 $path = nwdcx_network_dirpath($path);
48 }
49
50 $this->path = rtrim($path, '/\\');
51
52 $this->file = $this->path.'/options.php';
53 $this->path_lock = $this->path.'/lock';
54 }
55
56 public static function init()
57 {
58 if (!isset(self::$inst)) {
59 self::$inst = new self();
60 }
61
62 return self::$inst;
63 }
64
65 public function is_options_writable()
66 {
67 if (@is_file($this->file)) {
68 return @is_writable($this->file);
69 }
70
71 if (@is_dir($this->path)) {
72 return @is_writable($this->path);
73 }
74
75 return @is_writable(\dirname($this->path));
76 }
77
78 private function key_names()
79 {
80 $names = [
81 'log',
82 'log_time',
83 'log_all',
84 'preload',
85 'menucache',
86 'optermcount',
87 'precache',
88 'mocache',
89 'misc_tweaks',
90 'postmissedschedule',
91 'wootweaks',
92 'wooadminoff',
93 'woowidgetoff',
94 'woowpdashboardoff',
95 'wooextensionpageoff',
96 'woocartfragsoff',
97 'wooaddtochartcrawling',
98 'pageloader',
99 'wpoptaload',
100 'cronoptmzdb',
101 'cronbot',
102 'opcviewer',
103 'stats',
104 'gcaction',
105 'flushaction',
106 'autoupdate_toggle',
107 'checkversion',
108 'optwpquery',
109 'limitbulkedit',
110 'pingback',
111 'headerjunk',
112 'wpemoji',
113 'wpembed',
114 'wpfeed',
115 'wplazyload',
116 'wpsitemap',
117 'wpapppassword',
118 'wpdashboardnews',
119 'wpbrowsehappy',
120 'wpservehappy',
121 'postviaemail',
122 'objectcacheoff',
123 'flush_shutdown',
124 'opcshutdown',
125 'maxsize_disk',
126 'maxfile',
127 'maxfile_livecheck',
128 'chunkcachedir',
129 'flush_stalecache',
130 'stalecache_ignore',
131 'emptycache_ignore',
132 'transientdb',
133 'limithttprequest',
134 'rtpostautosave',
135 'rtpostrevision',
136 'rtpostemptytrash',
137 'rtpluginthemeeditor',
138 'rtpluginthemeinstall',
139 'rtimageoverwrite',
140 'rtwpdebug',
141 'rtwpdebugdisplay',
142 'rtwpdebuglog',
143 'rtwpcoreupdate',
144 'rtconcatenatescripts',
145 'rtdisablewpcron',
146 ];
147
148 if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
149 $names[] = 'advcpost';
150 $names[] = 'advpost_posttype_all';
151 }
152
153 if (version_compare($GLOBALS['wp_version'], '5.8', '<')) {
154 $names[] = 'httpheadersexpect';
155 }
156
157 return $names;
158 }
159
160 public function keys($key = false)
161 {
162 // key = title
163 $data = [
164 'log' => esc_html__('Cache Log', 'docket-cache'),
165 'log_time' => esc_html__('Log Timestamp', 'docket-cache'),
166 'log_all' => esc_html__('Log All', 'docket-cache'),
167 'preload' => esc_html__('Admin Page Cache Preloading', 'docket-cache'),
168 'menucache' => esc_html__('WordPress Menu Caching', 'docket-cache'),
169 'optermcount' => esc_html__('Optimize Term Count Queries', 'docket-cache'),
170 'precache' => esc_html__('Object Cache Precaching', 'docket-cache'),
171 'mocache' => esc_html__('WordPress Translation Caching', 'docket-cache'),
172 'misc_tweaks' => esc_html__('Misc Performance Tweaks', 'docket-cache'),
173 'postmissedschedule' => esc_html__('Post Missed Schedule Tweaks', 'docket-cache'),
174 'wootweaks' => esc_html__('Misc WooCommerce Tweaks', 'docket-cache'),
175 'wooadminoff' => esc_html__('Deactivate WooCommerce Admin', 'docket-cache'),
176 'woowidgetoff' => esc_html__('Deactivate WooCommerce Classic Widget', 'docket-cache'),
177 'woowpdashboardoff' => esc_html__('Deactivate WooCommerce WP Dashboard', 'docket-cache'),
178 'wooextensionpageoff' => esc_html__('Deactivate WooCommerce Extensions Page', 'docket-cache'),
179 'woocartfragsoff' => esc_html__('Deactivate WooCommerce Cart Fragments', 'docket-cache'),
180 'wooaddtochartcrawling' => esc_html__('Prevent robots crawling add-to-cart links', 'docket-cache'),
181 'pageloader' => esc_html__('Admin Page Loader', 'docket-cache'),
182 'wpoptaload' => esc_html__('Suspend WP Options Autoload', 'docket-cache'),
183 'cronoptmzdb' => esc_html__('Optimize Database Tables', 'docket-cache'),
184 'cronbot' => esc_html__('Cronbot Service', 'docket-cache'),
185 'opcviewer' => esc_html__('OPcache Viewer', 'docket-cache'),
186 'stats' => esc_html__('Object Cache Data Stats', 'docket-cache'),
187 'gcaction' => esc_html__('Garbage Collector Action Button', 'docket-cache'),
188 'flushaction' => esc_html__('Additional Flush Cache Action Button', 'docket-cache'),
189 'autoupdate_toggle' => esc_html__('Docket Cache Auto Update', 'docket-cache'),
190 'checkversion' => esc_html__('Critical Version Checking', 'docket-cache'),
191 'optwpquery' => esc_html__('Optimize WP Query', 'docket-cache'),
192 'limitbulkedit' => esc_html__('Limit Bulk Edit Actions', 'docket-cache'),
193 'pingback' => esc_html__('Deactivate XML-RPC / Pingbacks', 'docket-cache'),
194 'headerjunk' => esc_html__('Deactivate WP Header Junk', 'docket-cache'),
195 'wpemoji' => esc_html__('Deactivate WP Emoji', 'docket-cache'),
196 'wpembed' => esc_html__('Deactivate WP Embed', 'docket-cache'),
197 'wpfeed' => esc_html__('Deactivate WP Feed', 'docket-cache'),
198 'wplazyload' => esc_html__('Deactivate WP Lazy Load', 'docket-cache'),
199 'wpsitemap' => esc_html__('Deactivate WP Sitemap', 'docket-cache'),
200 'wpapppassword' => esc_html__('Deactivate WP Application Passwords', 'docket-cache'),
201 'wpdashboardnews' => esc_html__('Deactivate WP Events & News Feed Dashboard', 'docket-cache'),
202 'wpbrowsehappy' => esc_html__('Deactivate Browse Happy Checking', 'docket-cache'),
203 'wpservehappy' => esc_html__('Deactivate Serve Happy Checking', 'docket-cache'),
204 'postviaemail' => esc_html__('Deactivate Post Via Email', 'docket-cache'),
205 'objectcacheoff' => esc_html__('Suspend Object Cache', 'docket-cache'),
206 'flush_shutdown' => esc_html__('Flush Object Cache During Deactivation', 'docket-cache'),
207 'opcshutdown' => esc_html__('Flush OPcache During Deactivation', 'docket-cache'),
208 'maxsize_disk' => esc_html__('Cache Disk Limit', 'docket-cache'),
209 'maxfile' => esc_html__('Cache Files Limit', 'docket-cache'),
210 'maxfile_livecheck' => esc_html__('Real-time File Limit Checking', 'docket-cache'),
211 'chunkcachedir' => esc_html__('Chunk Cache Directory', 'docket-cache'),
212 'flush_stalecache' => esc_html__('Auto Remove Stale Cache', 'docket-cache'),
213 'stalecache_ignore' => esc_html__('Exclude Stale Cache', 'docket-cache'),
214 'emptycache_ignore' => esc_html__('Exclude Empty Object Data', 'docket-cache'),
215 'transientdb' => esc_html__('Retain Transients in Db', 'docket-cache'),
216 'limithttprequest' => esc_html__('Limit WP-Admin HTTP requests', 'docket-cache'),
217 'rtpostautosave' => esc_html__('Auto Save Interval', 'docket-cache'),
218 'rtpostrevision' => esc_html__('Post Revisions', 'docket-cache'),
219 'rtpostemptytrash' => esc_html__('Trash Bin', 'docket-cache'),
220 'rtpluginthemeeditor' => esc_html__('Disallows Plugin / Theme Editor', 'docket-cache'),
221 'rtpluginthemeinstall' => esc_html__('Disallows Plugin / Theme Update and Installation', 'docket-cache'),
222 'rtimageoverwrite' => esc_html__('Cleanup Image Edits', 'docket-cache'),
223 'rtwpdebug' => esc_html__('WP Debug', 'docket-cache'),
224 'rtwpdebugdisplay' => esc_html__('WP Debug Display', 'docket-cache'),
225 'rtwpdebuglog' => esc_html__('WP Debug Log', 'docket-cache'),
226 'rtwpcoreupdate' => esc_html__('Disallows WP Auto Update Core', 'docket-cache'),
227 'rtconcatenatescripts' => esc_html__('Deactivate Concatenate WP-Admin Scripts', 'docket-cache'),
228 'rtdisablewpcron' => esc_html__('Deactivate WP Cron', 'docket-cache'),
229 ];
230
231 if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
232 $data['advcpost'] = esc_html__('Advanced Post Caching', 'docket-cache');
233 $data['advpost_posttype_all'] = esc_html__('Post Caching Any Post Type', 'docket-cache');
234 }
235
236 if (version_compare($GLOBALS['wp_version'], '5.8', '<')) {
237 $data['httpheadersexpect'] = esc_html__('HTTP Request Expect header tweaks', 'docket-cache');
238 }
239
240 $data = apply_filters('docketcache/filter/optionkeys', $data);
241
242 if (false !== $key) {
243 if (!empty($data[$key])) {
244 return $data[$key];
245 }
246
247 return false;
248 }
249
250 return array_keys($data);
251 }
252
253 public function read_config($file = '', $force = false)
254 {
255 $file = empty($file) ? $this->file : $file;
256 $config = [];
257 if (@is_file($file) && is_readable($file)) {
258 // fresh
259 if ($force) {
260 $this->opcache_flush($file);
261 }
262
263 try {
264 $config = @include $file;
265 } catch (\Throwable $e) {
266 nwdcx_throwable(__METHOD__, $e);
267 }
268 }
269
270 return $config;
271 }
272
273 public function put_config($config, $file = '')
274 {
275 $file = empty($file) ? $this->file : $file;
276 if (empty($config) || !\is_array($config)) {
277 if (@is_file($file) && @is_writable($file)) {
278 @unlink($file);
279 }
280
281 clearstatcache();
282
283 return false;
284 }
285
286 $data = $this->export_var($config);
287 $code = $this->code_stub($data);
288
289 return $this->dump($file, $code);
290 }
291
292 public function config_cleanup($config)
293 {
294 if (!empty($config) && \is_array($config)) {
295 $names = $this->key_names();
296 foreach ($config as $name => $value) {
297 $nx = strtolower(nwdcx_constfx($name, true));
298 if (!\in_array($nx, $names) || (\is_string($value) && 'default' === $value)) {
299 unset($config[$name]);
300 }
301 }
302 }
303
304 return $config;
305 }
306
307 public function get($name)
308 {
309 $config = $this->read_config();
310
311 if (!empty($config) && !empty($config[$name])) {
312 return $config[$name];
313 }
314
315 return false;
316 }
317
318 public function save($name, $value, $do_action = true)
319 {
320 if (!$this->mkdir_p($this->path)) {
321 return false;
322 }
323
324 $this->placeholder($this->path);
325
326 $config = $this->read_config();
327 $config = $this->config_cleanup($config);
328
329 if (\in_array($name, $this->key_names())) {
330 $nx = nwdcx_constfx($name);
331
332 if ('default' === $value) {
333 unset($config[$nx]);
334 } else {
335 $config[$nx] = $value;
336 }
337 }
338
339 $ret = $this->put_config($config);
340
341 if ($do_action) {
342 do_action('docketcache/action/saveoption', $name, $value, $ret);
343 }
344
345 return $ret;
346 }
347
348 public function save_part($data, $file = 'part')
349 {
350 $file = $this->path.'/'.$file.'.php';
351
352 return $this->put_config($data, $file);
353 }
354
355 public function get_part($file = 'part', $force = false)
356 {
357 $file = $this->path.'/'.$file.'.php';
358
359 return $this->read_config($file, $force);
360 }
361
362 public function clear_part($file)
363 {
364 $file = $this->path.'/'.$file.'.php';
365 if (!@is_file($file)) {
366 return true;
367 }
368
369 $ret = @unlink($file);
370 clearstatcache();
371
372 return $ret;
373 }
374
375 public function clear_lock()
376 {
377 $path = $this->path_lock;
378 if (!@is_dir($path)) {
379 return false;
380 }
381
382 $files = @glob($path.'/lock-*.txt', \GLOB_MARK | \GLOB_NOSORT);
383 if (!empty($files) && \is_array($files)) {
384 foreach ($files as $file) {
385 if (@is_file($file) && @is_writable($file)) {
386 nwdcx_cliverbose(basename($file)."\n");
387 @unlink($file);
388 }
389 }
390 }
391
392 $files = @glob($path.'/dump_*.txt', \GLOB_MARK | \GLOB_NOSORT);
393 if (!empty($files) && \is_array($files)) {
394 foreach ($files as $file) {
395 if (@is_file($file) && @is_writable($file)) {
396 @unlink($file);
397 }
398 }
399 }
400
401 clearstatcache();
402
403 return true;
404 }
405
406 private function lock_file($key)
407 {
408 $key = substr(md5($key), 0, 12);
409 $path = $this->path_lock;
410 if (!$this->mkdir_p($path.'/')) {
411 return false;
412 }
413 $this->placeholder($path);
414
415 return $path.'/lock-'.$key.'.txt';
416 }
417
418 public function setlock($key, $value)
419 {
420 $file = $this->lock_file($key);
421 if (!$file) {
422 return false;
423 }
424
425 if (true === $this->dump($file, $value)) {
426 return true;
427 }
428
429 return false;
430 }
431
432 public function unlock($key)
433 {
434 $file = $this->lock_file($key);
435 if (!$file || !@is_file($file)) {
436 return true;
437 }
438
439 $ret = @unlink($file);
440 clearstatcache();
441
442 return $ret;
443 }
444
445 public function locked($key, &$value = '')
446 {
447 clearstatcache();
448
449 $file = $this->lock_file($key);
450 if (!$file || !@is_file($file)) {
451 return false;
452 }
453
454 $value = @file_get_contents($file);
455
456 return true;
457 }
458
459 // locked and not expire
460 public function lockexp($key)
461 {
462 if ($this->locked($key, $locked)) {
463 if (!empty($locked) && (int) $locked > time()) {
464 return true;
465 }
466 }
467
468 return false;
469 }
470
471 // lock process
472 public function lockproc($key, $value)
473 {
474 // if locked and not expire
475 if ($this->lockexp($key)) {
476 return true;
477 }
478
479 // if expire set new lock
480 $this->setlock($key, $value);
481
482 return false;
483 }
484
485 public function lockreset($key)
486 {
487 return $this->setlock($key, 0);
488 }
489
490 // lookup
491 public function lookup_set($key, $value)
492 {
493 $fkey = 'lockup-'.$key;
494
495 return $this->setlock($fkey, maybe_serialize($value));
496 }
497
498 public function lookup_get($key, $forget = false)
499 {
500 $fkey = 'lockup-'.$key;
501 if ($this->locked($fkey, $value)) {
502 if (!empty($value)) {
503 if ($forget) {
504 $this->lookup_delete($key);
505 }
506
507 return maybe_unserialize($value);
508 }
509 }
510
511 if ($forget) {
512 $this->lookup_delete($key);
513 }
514
515 return false;
516 }
517
518 public function lookup_delete($key)
519 {
520 $fkey = 'lockup-'.$key;
521
522 return $this->unlock($fkey);
523 }
524
525 public function reset()
526 {
527 $this->clear_lock();
528
529 $parts = [
530 'options',
531 'runtime',
532 'pings',
533 'cronbot',
534 'checkversion',
535 'cachestats',
536 'gc',
537 ];
538
539 $ok = true;
540 foreach ($parts as $part) {
541 $file = $this->path.'/'.$part.'.php';
542 if (@is_file($file) && is_writable($file)) {
543 if (!@unlink($file)) {
544 $ok = false;
545 }
546 }
547 }
548
549 clearstatcache(true);
550
551 return $ok;
552 }
553 }
554