PluginProbe
Docket Cache – Object Cache Accelerator / 24.07.03
Docket Cache – Object Cache Accelerator v24.07.03
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 / Plugin.php

Plugin.php in Docket Cache – Object Cache Accelerator 24.07.03, at includes/src/Plugin.php

2,376 lines 79.3 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 Plugin extends Bepart
16 {
17 /**
18 * Plugin file.
19 *
20 * @var string
21 */
22 public $file;
23
24 /**
25 * Plugin slug.
26 *
27 * @var string
28 */
29 public $slug;
30
31 /**
32 * Plugin hook.
33 *
34 * @var string
35 */
36 public $hook;
37
38 /**
39 * Plugin path.
40 *
41 * @var string
42 */
43 public $path;
44
45 /**
46 * Plugin valid page uri.
47 *
48 * @var string
49 */
50 public $page;
51
52 /**
53 * Plugin action token.
54 *
55 * @var string
56 */
57 public $token;
58
59 /**
60 * Plugin action notice.
61 *
62 * @var string
63 */
64 public $notice;
65
66 /**
67 * Plugin screen name.
68 *
69 * @var string
70 */
71 public $screen;
72
73 /**
74 * The cache path.
75 *
76 * @var string
77 */
78 public $cache_path;
79
80 /**
81 * API Endpoint.
82 *
83 * @var string
84 */
85 public $api_endpoint;
86
87 /**
88 * Cronbot Endpoint.
89 *
90 * @var string
91 */
92 public $cronbot_endpoint;
93
94 /**
95 * WpConfig runtime notice.
96 *
97 * @var bool
98 */
99 public $inruntime = false;
100
101 /**
102 * constructor.
103 */
104 public function __construct()
105 {
106 $this->slug = 'docket-cache';
107 $this->file = nwdcx_constval('FILE');
108 $this->hook = plugin_basename($this->file);
109 $this->path = realpath(plugin_dir_path($this->file));
110 $this->register_init();
111 }
112
113 /**
114 * Dropino().
115 */
116 public function cx()
117 {
118 static $inst;
119 if (!\is_object($inst)) {
120 $inst = new Dropino($this->path);
121 }
122
123 return $inst;
124 }
125
126 /**
127 * Canopt().
128 */
129 public function co()
130 {
131 static $inst;
132 if (!\is_object($inst)) {
133 $inst = new Canopt();
134 }
135
136 return $inst;
137 }
138
139 /**
140 * Constans().
141 */
142 public function cf()
143 {
144 static $inst;
145 if (!\is_object($inst)) {
146 $inst = new Constans();
147 }
148
149 return $inst;
150 }
151
152 /**
153 * get_version.
154 */
155 public function version()
156 {
157 static $version = false;
158
159 if (!empty($version)) {
160 return $version;
161 }
162
163 $version = $this->plugin_meta($this->file)['Version'];
164
165 return $version;
166 }
167
168 /**
169 * get_info.
170 */
171 public function get_info()
172 {
173 $status_code = [
174 0 => esc_html__('Disabled', 'docket-cache'),
175 1 => esc_html__('Enabled', 'docket-cache'),
176 2 => esc_html__('Not Available', 'docket-cache'),
177 3 => esc_html__('Unknown', 'docket-cache'),
178 ];
179
180 $yesno = [
181 0 => esc_html__('No', 'docket-cache'),
182 1 => esc_html__('Yes', 'docket-cache'),
183 ];
184
185 $force_stats = $this->cf()->is_dctrue('WPCLI');
186 $cache_stats = $this->get_cache_stats($force_stats);
187
188 $status = $this->get_status();
189 $status_text_stats = '';
190 $status_text = '';
191
192 switch ($status) {
193 case 1:
194 if ($this->cf()->is_dctrue('STATS')) {
195 /* translators: %1$s = size, %2$s number of file */
196 $status_text_stats = sprintf(esc_html__(_n('%1$s object of %2$s file', '%1$s object of %2$s files', $cache_stats->files < 1 ? 1 : $cache_stats->files, 'docket-cache')), $this->normalize_size($cache_stats->size), $cache_stats->files);
197 }
198 $status_text = $status_code[1];
199 break;
200 case 2:
201 $status_text = esc_html__('Disabled at runtime.', 'docket-cache');
202 break;
203 default:
204 $status_text = $status_code[$status];
205 }
206
207 $opcache = $this->get_opcache_status();
208 $opcache_text_stats = '';
209 $opcache_text = '';
210
211 $opcache_dc_stats = '';
212 $opcache_wp_stats = '';
213 switch ($opcache->status) {
214 case 1:
215 /* translators: %1$s = size, %2$s number of file */
216 $opcache_text_stats = sprintf(esc_html__(_n('%1$s memory of %2$s file', '%1$s memory of %2$s files', $opcache->files, 'docket-cache')), $this->normalize_size($opcache->size), $opcache->files);
217
218 if ($opcache->dcfiles > 1) {
219 /* translators: %1$s = size, %2$s number of file */
220 $opcache_dc_stats = sprintf(esc_html__(_n('%1$s memory of %2$s file', '%1$s memory of %2$s files', $opcache->dcfiles, 'docket-cache')), $this->normalize_size($opcache->dcsize), $opcache->dcfiles);
221
222 /* translators: %1$s = size, %2$s number of file */
223 $opcache_wp_stats = sprintf(esc_html__(_n('%1$s memory of %2$s file', '%1$s memory of %2$s files', $opcache->wpfiles, 'docket-cache')), $this->normalize_size($opcache->wpsize), $opcache->wpfiles);
224 }
225 break;
226 case 2:
227 $opcache_text = $status_code[1];
228 break;
229 case 3:
230 $opcache_text = $status_code[1].' (<a href="https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.file-cache-only" rel="noopener" target="new">'.esc_html__('File cache only', 'docket-cache').'</a>)';
231 break;
232 case 4:
233 if ($opcache->files > 0) {
234 /* translators: %1$s = size, %2$s number of file */
235 $opcache_text_stats = sprintf(esc_html__(_n('%1$s size of %2$s file', '%1$s size of %2$s files', $opcache->files, 'docket-cache')), $this->normalize_size($opcache->size), $opcache->files);
236
237 if ($opcache->dcfiles > 1) {
238 /* translators: %1$s = size, %2$s number of file */
239 $opcache_dc_stats = sprintf(esc_html__(_n('%1$s size of %2$s file', '%1$s size of %2$s files', $opcache->dcfiles, 'docket-cache')), $this->normalize_size($opcache->dcsize), $opcache->dcfiles);
240
241 /* translators: %1$s = size, %2$s number of file */
242 $opcache_wp_stats = sprintf(esc_html__(_n('%1$s size of %2$s file', '%1$s size of %2$s files', $opcache->wpfiles, 'docket-cache')), $this->normalize_size($opcache->wpsize), $opcache->wpfiles);
243 }
244 } else {
245 $opcache_text = $status_code[1].' (<a href="https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.file-cache-only" rel="noopener" target="new">'.esc_html__('File cache only', 'docket-cache').'</a>)';
246 }
247
248 break;
249 default:
250 $opcache_text = $status_code[2];
251 }
252
253 $log_enable = $this->cf()->is_dctrue('LOG') ? 1 : 0;
254 $log_file = $this->cf()->dcvalue('LOG_FILE');
255
256 if (is_multisite()) {
257 $log_file = nwdcx_network_filepath($log_file);
258 }
259
260 $multisite_text = $status_code[3];
261 $multinets_lock = '';
262
263 if (is_multisite()) {
264 $netcount = get_networks(['count' => 1]);
265 $this->get_network_sites($sitecount, true);
266
267 /* translators: %s = sites */
268 $multisite_text = sprintf(esc_html__(_n('%s Site', '%s Sites', $sitecount, 'docket-cache')), $sitecount);
269
270 if ($netcount > 1) {
271 /* translators: %s = networks */
272 $multisite_text = $multisite_text.' '.sprintf(esc_html__(_n('of %s Network', 'of %s Networks', $netcount, 'docket-cache')), $netcount);
273
274 $multinets_lock = $this->sanitize_rootpath($this->cx()->multinet_tag());
275 }
276 }
277
278 $file_dropin = $this->cx()->resc()->dst;
279 if (@is_file($file_dropin)) {
280 $write_dropin = @is_writable($file_dropin);
281 } else {
282 $write_dropin = @is_writable($this->cx()->condir.'/');
283 }
284
285 $file_dropin_wp = $this->cx()->resc()->wpdst;
286 $dropin_wp_exist = false;
287
288 $is_dropin_alternative = $this->cx()->is_alternative();
289 if ($is_dropin_alternative) {
290 $dropin_wp_exist = @is_file($file_dropin_wp) || @is_link($file_dropin_wp);
291 }
292
293 $file_max = $this->get_cache_maxfile();
294 $disk_max = $this->normalize_size($this->get_cache_maxsize_disk());
295
296 $file_stats = $file_max;
297 $disk_stats = $disk_max;
298
299 if (isset($cache_stats->files) && !empty($cache_stats->files)) {
300 $file_stats = $cache_stats->files.' / '.$file_max;
301 }
302
303 if (isset($cache_stats->filesize) && !empty($cache_stats->filesize)) {
304 $disk_stats = $this->normalize_size($cache_stats->filesize).' / '.$disk_max;
305 }
306
307 return [
308 'status_code' => $status,
309 'status_text' => $status_text,
310 'status_text_stats' => $status_text_stats,
311 'opcache_code' => $opcache->status,
312 'opcache_text' => $opcache_text,
313 'opcache_text_stats' => $opcache_text_stats,
314 'opcache_dc_stats' => $opcache_dc_stats,
315 'opcache_wp_stats' => $opcache_wp_stats,
316 'php_memory_limit' => $this->normalize_size(@\ini_get('memory_limit')),
317 'wp_memory_limit' => $this->normalize_size(WP_MEMORY_LIMIT),
318 'wp_max_memory_limit' => $this->normalize_size(WP_MAX_MEMORY_LIMIT),
319 'write_dropin' => $yesno[$write_dropin],
320 'dropin_path' => $this->sanitize_rootpath($file_dropin),
321 'dropin_isalt' => $is_dropin_alternative,
322 'dropin_alt' => $yesno[$is_dropin_alternative],
323 'dropin_wp' => $this->sanitize_rootpath($file_dropin_wp),
324 'dropin_wp_isexist' => $dropin_wp_exist,
325 'dropin_wp_exist' => $yesno[$dropin_wp_exist],
326 'write_cache' => $yesno[is_writable($this->cache_path)],
327 'cache_chunkdir' => $yesno[$this->cf()->dcvalue('CHUNKCACHEDIR')],
328 'cache_size' => $this->normalize_size($cache_stats->size),
329 'cache_path_real' => $this->cache_path,
330 'cache_path' => $this->sanitize_rootpath($this->cache_path),
331 'cache_maxfile' => $file_max,
332 'cache_file_stats' => $file_stats,
333 'cache_maxsize_disk' => $this->normalize_size($this->get_cache_maxsize_disk()),
334 'cache_disk_stats' => $disk_stats,
335 'log_file_real' => $log_file,
336 'log_file' => $this->sanitize_rootpath($log_file),
337 'log_enable' => $log_enable,
338 'log_enable_text' => $status_code[$log_enable],
339 'config_path' => $this->sanitize_rootpath($this->co()->path),
340 'write_config' => $yesno[$this->co()->is_options_writable()],
341 'wp_multisite' => $multisite_text,
342 'wp_multinetlock' => $multinets_lock,
343 'wp_multinetmain' => $yesno[is_main_network()],
344 ];
345 }
346
347 /**
348 * sanitize_rootpath.
349 */
350 public function sanitize_rootpath($path)
351 {
352 $wp_content_dir = wp_normalize_path(WP_CONTENT_DIR);
353 $abspath = wp_normalize_path(ABSPATH);
354
355 return rtrim(str_replace([$wp_content_dir, $abspath], ['/'.basename($wp_content_dir), '/'], $path), '/');
356 }
357
358 /**
359 * get_status.
360 */
361 public function get_status()
362 {
363 if ($this->cf()->is_dctrue('DISABLED')) {
364 return 2;
365 }
366
367 if (!$this->cx()->exists()) {
368 return 0;
369 }
370
371 if ($this->cx()->validate() && $this->cx()->multinet_me()) {
372 if ($this->cf()->is_dctrue('OBJECTCACHEOFF', true)) {
373 $this->co()->save('objectcacheoff', 'default');
374 }
375
376 return 1;
377 }
378
379 if (!$this->cx()->multinet_me()) {
380 return 0;
381 }
382
383 return 3;
384 }
385
386 /**
387 * get_logsize.
388 */
389 public function get_logsize()
390 {
391 if ($this->has_log($logfile)) {
392 return $this->normalize_size($this->filesize($logfile));
393 }
394
395 return 0;
396 }
397
398 /**
399 * get_opcache_status.
400 */
401 public function get_opcache_status($is_raw = false)
402 {
403 $total_bytes = 0;
404 $total_files = 0;
405 $status = 0;
406
407 $dcfiles = 0;
408 $dcbytes = 0;
409
410 $wpfiles = 0;
411 $wpbytes = 0;
412
413 $stale = 0;
414
415 $data = [];
416 if ($this->is_opcache_enable()) {
417 if (!$this->opcache_function_exists('opcache_get_status')) {
418 $status = 2;
419 } else {
420 $nwdcx_suppresserrors = nwdcx_suppresserrors(true);
421 $data = opcache_get_status();
422 nwdcx_suppresserrors($nwdcx_suppresserrors);
423
424 if (!empty($data) && \is_array($data)) {
425 if (!empty($data['opcache_enabled'])) {
426 if ($is_raw) {
427 return $data;
428 }
429
430 $status = 1;
431
432 if (!empty($data['memory_usage']['used_memory'])) {
433 $total_bytes = $data['memory_usage']['used_memory'];
434 }
435 if (!empty($data['opcache_statistics']['num_cached_scripts'])) {
436 $total_files = $data['opcache_statistics']['num_cached_scripts'];
437 }
438
439 if (!empty($data['scripts']) && \is_array($data['scripts'])) {
440 foreach ($data['scripts'] as $script => $arr) {
441 $cpath = $arr['full_path'];
442 if (!@is_file($cpath)) {
443 ++$stale;
444 }
445 $cfile = basename($cpath);
446 $cdir = \dirname($cpath);
447 if (false !== strpos($script, $this->cache_path) && $this->is_docketcachedir($cdir) && @preg_match('@^([a-z0-9]{12})\-([a-z0-9]{12})\.php$@', $cfile)) {
448 ++$dcfiles;
449 if (isset($arr['memory_consumption'])) {
450 $dcbytes += $arr['memory_consumption'];
451 }
452 } else {
453 ++$wpfiles;
454 if (isset($arr['memory_consumption'])) {
455 $wpbytes += $arr['memory_consumption'];
456 }
457 }
458 }
459 }
460 } elseif (!empty($data['file_cache_only'])) {
461 $status = 3;
462
463 if (!empty($data['file_cache']) && is_dir($data['file_cache']) && is_readable($data['file_cache'])) {
464 $dir = nwdcx_normalizepath(realpath($data['file_cache']));
465 $cnt = 0;
466
467 // dummy
468 $cdata = [
469 'opcache_statistics' => [
470 'num_cached_scripts' => 0,
471 ],
472 'scripts' => [],
473 ];
474
475 foreach ($this->opcache_filecache_scanfiles($dir) as $object) {
476 try {
477 if (!$object->isFile()) {
478 continue;
479 }
480
481 $cpath = nwdcx_normalizepath($object->getPathName());
482 if (false === strpos($cpath, nwdcx_normalizepath(ABSPATH))) {
483 continue;
484 }
485
486 $cfile = basename($cpath);
487 $cdir = \dirname($cpath);
488 $fs = $object->getSize();
489
490 if (false !== strpos($cpath, $this->cache_path) && $this->is_docketcachedir($cdir) && @preg_match('@^([a-z0-9]{12})\-([a-z0-9]{12})\.php\.bin$@', $cfile)) {
491 ++$dcfiles;
492 $dcbytes += $fs;
493 } else {
494 ++$wpfiles;
495 $wpbytes += $fs;
496 }
497
498 ++$cnt;
499
500 $total_bytes += $fs;
501
502 $cdata['scripts'][$cpath] = [
503 'full_path' => $cpath,
504 'memory_consumption' => $fs,
505 'last_used_timestamp' => $object->getATime(),
506 'hits' => 1,
507 ];
508 } catch (\Throwable $e) {
509 nwdcx_throwable(__METHOD__, $e);
510 continue;
511 }
512 }
513
514 if ($cnt > 0) {
515 $status = 4;
516 $total_files = $cnt;
517 }
518 }
519
520 if ($is_raw) {
521 $cdata['opcache_statistics']['num_cached_scripts'] = $cnt;
522 $data = array_merge($data, $cdata);
523 $data['_numfile'] = $cnt;
524 $data['_sizefile'] = $total_bytes;
525
526 return $data;
527 }
528 }
529 }
530 }
531 }
532
533 $arr = [
534 'status' => (int) $status,
535 'size' => $total_bytes,
536 'files' => (int) $total_files,
537 'wpfiles' => (int) $wpfiles,
538 'wpsize' => (int) $wpbytes,
539 'dcfiles' => (int) $dcfiles,
540 'dcsize' => (int) $dcbytes,
541 'stale' => (int) $stale,
542 ];
543
544 return (object) $arr;
545 }
546
547 /**
548 * get_cache_maxfile.
549 */
550 public function get_cache_maxfile()
551 {
552 $maxfile = $this->cf()->dcvalue('MAXFILE', true);
553
554 return $this->sanitize_maxfile($maxfile);
555 }
556
557 /**
558 * get_cache_maxttl.
559 */
560 public function get_cache_maxttl()
561 {
562 $maxttl = $this->cf()->dcvalue('MAXTTL');
563
564 return $this->sanitize_maxttl($maxttl);
565 }
566
567 /**
568 * get_cache_maxsize_disk.
569 */
570 public function get_cache_maxsize_disk()
571 {
572 $maxsizedisk = $this->cf()->dcvalue('MAXSIZE_DISK');
573
574 return $this->sanitize_maxsizedisk($maxsizedisk);
575 }
576
577 /**
578 * get_precache_maxfile.
579 */
580 public function get_precache_maxfile()
581 {
582 if ($this->cf()->is_dcfalse('PRECACHE')) {
583 return 0;
584 }
585
586 $maxfile = $this->cf()->dcvalue('PRECACHE_MAXFILE', true);
587
588 return $this->sanitize_precache_maxfile($maxfile);
589 }
590
591 /**
592 * get_cache_stats.
593 */
594 public function get_cache_stats($force = false)
595 {
596 $cache_stats = false;
597
598 if ($this->cf()->is_dctrue('STATS')) {
599 if ($force) {
600 $cache_stats = $this->cache_size($this->cache_path);
601 $this->co()->save_part($cache_stats, 'cachestats');
602 } else {
603 $cache_stats = $this->co()->get_part('cachestats');
604 }
605 }
606
607 if (empty($cache_stats) || !\is_array($cache_stats)) {
608 $cache_stats = [
609 'size' => 0,
610 'filesize' => 0,
611 'files' => 0,
612 ];
613 }
614
615 return (object) $cache_stats;
616 }
617
618 /**
619 * normalize_size.
620 */
621 public function normalize_size($size, $showb = true)
622 {
623 $size = wp_convert_hr_to_bytes($size);
624 $size = str_replace([',', ' ', 'B'], '', size_format($size));
625 if ($showb && is_numeric($size)) {
626 $size = $size.'B';
627 }
628
629 return $size;
630 }
631
632 public function site_url_scheme($site_url)
633 {
634 $site_url = trim($site_url);
635 if ('https://' !== substr($site_url, 0, 8) && $this->is_ssl()) {
636 $site_url = nwdcx_fixscheme($site_url, 'https://');
637 } elseif (!@preg_match('@^(https?:)?//@', $site_url)) {
638 $site_url = nwdcx_fixscheme($site_url, 'http://');
639 }
640
641 return rtrim($site_url, '/\\');
642 }
643
644 public function site_url($current = false, $is_home = false)
645 {
646 $option = $is_home ? 'home' : 'siteurl';
647 $site_url = get_option($option);
648 if (!$current && is_multisite()) {
649 $blog_id = get_main_site_id();
650 switch_to_blog($blog_id);
651 $site_url = get_option($option);
652 restore_current_blog();
653 }
654
655 return $this->site_url_scheme($site_url);
656 }
657
658 public function site_meta($short = false)
659 {
660 $m = '0,0';
661 if (is_multisite()) {
662 $n = get_networks(['count' => 1]);
663 $s = get_sites(['count' => 1]);
664 $m = $n.','.$s;
665 }
666
667 if ($short) {
668 $meta = $m.','.$this->version();
669 $meta = str_replace('0,0,', '', $meta);
670 $meta = str_replace('0', '', $meta);
671 } else {
672 $meta = $m.','.$this->version().','.$GLOBALS['wp_version'];
673 }
674
675 return str_replace('.', '', $meta);
676 }
677
678 /**
679 * flush_cache.
680 */
681 public function flush_cache($cleanup = false, &$is_timeout = false)
682 {
683 $this->co()->clear_part('cachestats');
684 $this->cx()->delay();
685
686 if (\function_exists('nwdcx_cleanuptransient')) {
687 nwdcx_cleanuptransient();
688 } else {
689 delete_expired_transients(true);
690 }
691
692 $cnt = $this->cachedir_flush($this->cache_path, $cleanup, $is_timeout);
693 if (false === $cnt) {
694 $this->cx()->undelay();
695
696 return $cnt;
697 }
698
699 $this->co()->clear_lock();
700
701 return $cnt;
702 }
703
704 /**
705 * flush_fcache.
706 */
707 public function flush_fcache(&$file = '')
708 {
709 if (!empty($_GET['idxv'])) {
710 $fx = sanitize_text_field($_GET['idxv']);
711 $file = $this->cache_path.$fx.'.php';
712 if (@is_file($file)) {
713 $this->co()->clear_part('cachestats');
714
715 return $this->unlink($file, true);
716 }
717 }
718
719 return true;
720 }
721
722 /**
723 * has_log.
724 */
725 public function has_log(&$logfile = '')
726 {
727 $logfile = $this->cf()->dcvalue('LOG_FILE');
728
729 if (is_multisite()) {
730 $logfile = nwdcx_network_filepath($logfile);
731 }
732
733 return @is_file($logfile) && is_readable($logfile);
734 }
735
736 /**
737 * flush_log.
738 */
739 public function flush_log()
740 {
741 if ($this->has_log($logfile)) {
742 return @unlink($logfile);
743 }
744
745 return false;
746 }
747
748 public function switch_cron_site()
749 {
750 if (is_multisite()) {
751 $cronbot_siteid = $this->get_cron_siteid();
752 if (!empty($cronbot_siteid) && (int) $cronbot_siteid > 0) {
753 switch_to_blog($cronbot_siteid);
754
755 return true;
756 }
757 }
758
759 return false;
760 }
761
762 public function delete_cron_siteid($userid = false)
763 {
764 if (empty($userid)) {
765 $userid = get_current_user_id();
766 }
767
768 $key = 'cronbot-siteid-'.get_current_user_id();
769
770 return $this->co()->lookup_delete($key);
771 }
772
773 public function set_cron_siteid($id)
774 {
775 $key = 'cronbot-siteid-'.get_current_user_id();
776
777 return $this->co()->lookup_set($key, $id);
778 }
779
780 public function get_cron_siteid()
781 {
782 $key = 'cronbot-siteid-'.get_current_user_id();
783 $siteid = $this->co()->lookup_get($key);
784 if (empty($siteid)) {
785 $siteid = is_multisite() ? get_main_site_id() : get_current_blog_id();
786 }
787
788 return $siteid;
789 }
790
791 public function cleanuppost()
792 {
793 if (!nwdcx_wpdb($wpdb)) {
794 return false;
795 }
796
797 $sites = $this->get_network_sites();
798 $is_multisite = is_multisite();
799
800 $collect = [
801 'revision' => 0,
802 'autodraft' => 0,
803 'trashbin' => 0,
804 ];
805
806 $siteid = 0;
807 if ($is_multisite) {
808 $collect['site'] = \count($sites);
809
810 if (isset($_GET['siteid'])) {
811 $siteid = (int) sanitize_text_field($_GET['siteid']);
812 $this->set_current_select_siteid($siteid);
813 }
814 }
815
816 $max_execution_time = $this->get_max_execution_time();
817 $suppress = $wpdb->suppress_errors(true);
818 $doflush = false;
819 foreach ($sites as $num => $site) {
820 if ($is_multisite) {
821 if (!empty($siteid) && $siteid !== (int) $site['id']) {
822 continue;
823 }
824
825 switch_to_blog($site['id']);
826 }
827
828 $query = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_type = %s ORDER BY ID ASC LIMIT 1000", 'revision'));
829 if ($query) {
830 foreach ($query as $id) {
831 $id = (int) $id;
832 wp_delete_post_revision($id);
833 $doflush = true;
834 }
835 $collect['revision'] += \count($query);
836 }
837
838 $query = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_status = %s ORDER BY ID ASC LIMIT 1000", 'auto-draft'));
839 if ($query) {
840 foreach ($query as $id) {
841 $id = (int) $id;
842 wp_delete_post($id, true);
843 $doflush = true;
844 }
845 $collect['autodraft'] += \count($query);
846 }
847
848 $query = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_status = %s ORDER BY ID ASC LIMIT 1000", 'trash'));
849 if ($query) {
850 foreach ($query as $id) {
851 $id = (int) $id;
852 wp_delete_post($id, true);
853 $doflush = true;
854 }
855 $collect['trashbin'] += \count($query);
856 }
857
858 if ($is_multisite) {
859 restore_current_blog();
860 }
861
862 if ($max_execution_time > 0 && \defined('WP_START_TIMESTAMP') && (microtime(true) - WP_START_TIMESTAMP) > $max_execution_time) {
863 $is_timeout = true;
864 break;
865 }
866 }
867
868 $wpdb->suppress_errors($suppress);
869
870 if ($doflush) {
871 $this->flush_cache(false);
872 }
873
874 return (object) $collect;
875 }
876
877 public function delete_current_select_siteid($userid = false)
878 {
879 if (empty($userid)) {
880 $userid = get_current_user_id();
881 }
882
883 $key = 'current-select-siteid-'.get_current_user_id();
884
885 return $this->co()->lookup_delete($key);
886 }
887
888 public function get_current_select_siteid()
889 {
890 $key = 'current-select-siteid-'.get_current_user_id();
891
892 return (int) $this->co()->lookup_get($key);
893 }
894
895 public function set_current_select_siteid($id)
896 {
897 $key = 'current-select-siteid-'.get_current_user_id();
898
899 return $this->co()->lookup_set($key, $id);
900 }
901
902 /**
903 * compat_notice.
904 */
905 private function compat_notice()
906 {
907 if (!(\PHP_VERSION_ID >= 70205)) {
908 $text = __('Docket Cache plugin requires PHP 7.2.5 or greater.', 'docket-cache');
909
910 add_action(
911 'all_admin_notices',
912 function () use ($text) {
913 echo '<div id="docket-cache-notice" class="notice notice-warning is-dismissible"><p>'.$text.'</p></div>';
914 deactivate_plugins($this->hook);
915 wp_cache_flush();
916 },
917 \PHP_INT_MIN
918 );
919
920 if (\defined('WP_CLI') && WP_CLI) {
921 if (!\function_exists('deactivate_plugins')) {
922 include_once ABSPATH.'/wp-admin/includes/plugin.php';
923 }
924
925 if (\function_exists('deactivate_plugins')) {
926 deactivate_plugins($this->hook);
927 wp_cache_flush();
928
929 \WP_CLI::error($text, false);
930 \WP_CLI::halt(1);
931 }
932 }
933
934 return false;
935 }
936
937 return true;
938 }
939
940 /**
941 * cleanup.
942 */
943 private function deactivate_cleanup($is_uninstall = false)
944 {
945 WpConfig::unlink_runtime();
946
947 if ($this->cx()->validate()) {
948 $this->cx()->uninstall();
949 }
950
951 $this->cx()->undelay();
952
953 if ($this->cf()->is_dctrue('FLUSH_SHUTDOWN', true)) {
954 $this->cachedir_flush($this->cache_path, true);
955 }
956
957 $this->flush_log();
958
959 if ($is_uninstall) {
960 WpConfig::runtime_remove();
961
962 // reset on/off button
963 $this->co()->save('objectcacheoff', 'default');
964
965 // stats
966 $this->co()->clear_part('cachestats');
967
968 // cronbot/etc
969 $this->co()->save('cronbot', 'default');
970 $this->co()->clear_part('cronbot');
971 $this->co()->clear_part('pings');
972 $this->co()->clear_part('checkversion');
973
974 // clear all network if available
975 if (is_multisite()) {
976 $this->cx()->multinet_clear($this->cache_path, $this->cf()->dcvalue('LOG_FILE'));
977 }
978 }
979
980 if ($this->cf()->is_dctrue('OPCSHUTDOWN', true)) {
981 $this->opcache_cleanup();
982 }
983
984 $this->co()->clear_lock();
985 }
986
987 /**
988 * uninstall.
989 */
990 public static function uninstall()
991 {
992 ( new self() )->deactivate_cleanup(true);
993 }
994
995 /**
996 * deactivate.
997 */
998 public function deactivate()
999 {
1000 $this->deactivate_cleanup();
1001 $this->unregister_cronjob();
1002 }
1003
1004 /**
1005 * activate.
1006 */
1007 public function activate()
1008 {
1009 if (!$this->compat_notice()) {
1010 return;
1011 }
1012
1013 $this->flush_cache(false);
1014
1015 if ($this->cf()->is_dcfalse('OBJECTCACHEOFF', true)) {
1016 $this->cx()->install(true);
1017 }
1018
1019 $this->unregister_cronjob();
1020 }
1021
1022 /**
1023 * register_init.
1024 */
1025 private function register_init()
1026 {
1027 // unofficial constant: possible to disable nag notices
1028 !\defined('DISABLE_NAG_NOTICES') && \define('DISABLE_NAG_NOTICES', true);
1029
1030 $this->page = 'admin.php?page='.$this->slug;
1031 $this->screen = 'toplevel_page_docket-cache';
1032 $this->cache_path = $this->define_cache_path($this->cf()->dcvalue('PATH'));
1033
1034 if (is_multisite()) {
1035 $this->cache_path = nwdcx_network_dirpath($this->cache_path);
1036 }
1037
1038 $this->api_endpoint = 'https://api.docketcache.com';
1039 $this->cronbot_endpoint = 'https://cronbot.docketcache.com';
1040
1041 // use Constans() to trigger default
1042 if ($this->cf()->is_dctrue('DEV')) {
1043 $this->api_endpoint = 'http://api.docketcache.local';
1044 $this->cronbot_endpoint = 'http://cronbot.docketcache.local';
1045 }
1046
1047 $this->token = '';
1048 $this->notice = '';
1049 $this->inruntime = false;
1050
1051 /*add_filter(
1052 'perflab_oc_site_status_available_object_cache_services',
1053 function ($services) {
1054 $services[] = 'docket-cache';
1055
1056 return $services;
1057 },
1058 \PHP_INT_MAX
1059 );*/
1060
1061 add_filter('perflab_disable_object_cache_dropin', '__return_true');
1062 }
1063
1064 /**
1065 * critical_version.
1066 */
1067 private function critical_version()
1068 {
1069 $checkdata = $this->co()->get_part('checkversion', true);
1070 if (!empty($checkdata) && \is_array($checkdata) && !empty($checkdata['doversion'])) {
1071 $current_version = $this->plugin_meta($this->file)['Version'];
1072 if (0 === strcmp($checkdata['doversion'], $current_version)) {
1073 $this->flush_cache(true);
1074 }
1075 }
1076 unset($checkdata);
1077
1078 return true;
1079 }
1080
1081 /**
1082 * plugin_upgrade.
1083 */
1084 private function plugin_upgrade()
1085 {
1086 add_action(
1087 'shutdown',
1088 function () {
1089 if ($this->cf()->is_dcfalse('OBJECTCACHEOFF', true)) {
1090 $this->cx()->install(true);
1091 if (is_multisite()) {
1092 $this->cx()->multinet_install($this->hook);
1093 }
1094 }
1095
1096 // put last
1097 $this->critical_version();
1098 },
1099 \PHP_INT_MAX
1100 );
1101 }
1102
1103 private function toggle_auto_update($toggle = false)
1104 {
1105 $auto_updates = (array) get_site_option('auto_update_plugins', []);
1106 if (true === $toggle) {
1107 $auto_updates[] = $this->hook;
1108
1109 return update_site_option('auto_update_plugins', array_unique($auto_updates));
1110 }
1111
1112 return update_site_option('auto_update_plugins', array_diff($auto_updates, [$this->hook]));
1113 }
1114
1115 /**
1116 * register_plugin_hooks.
1117 */
1118 private function register_plugin_hooks()
1119 {
1120 add_action(
1121 'init',
1122 function () {
1123 load_plugin_textdomain(
1124 'docket-cache',
1125 false,
1126 $this->path.'/languages/'
1127 );
1128 },
1129 0
1130 );
1131
1132 add_action(
1133 'upgrader_process_complete',
1134 function ($wp_upgrader, $options) {
1135 if ('update' !== $options['action']) {
1136 return;
1137 }
1138
1139 if ('plugin' === $options['type'] && !empty($options['plugins'])) {
1140 if (!\is_array($options['plugins'])) {
1141 return;
1142 }
1143
1144 foreach ($options['plugins'] as $plugin) {
1145 if ($plugin === $this->hook) {
1146 $this->plugin_upgrade();
1147 break;
1148 }
1149 }
1150 }
1151 },
1152 \PHP_INT_MAX,
1153 2
1154 );
1155
1156 // wp 5.5 >=
1157 if (\function_exists('wp_is_maintenance_mode')) {
1158 add_action(
1159 'upgrader_overwrote_package',
1160 function ($package, $package_data, $package_type = 'plugin') {
1161 if (!empty($package_data) && \is_array($package_data) && !empty($package_data['TextDomain']) && $this->slug === $package_data['TextDomain']) {
1162 $this->plugin_upgrade();
1163 }
1164 },
1165 \PHP_INT_MAX,
1166 3
1167 );
1168 }
1169
1170 add_action(
1171 'admin_footer',
1172 function () {
1173 $output = $this->cx()->after_delay();
1174 if (!empty($output)) {
1175 echo $output;
1176 }
1177 },
1178 \PHP_INT_MAX
1179 );
1180
1181 if (!is_admin() && $this->cf()->is_dctrue('SIGNATURE')) {
1182 add_action(
1183 'send_headers',
1184 function () {
1185 $status = $this->cx()->validate() ? 'on' : 'off';
1186 header('x-'.$this->slug.': '.$status.'; '.$this->site_meta(true));
1187 },
1188 \PHP_INT_MAX
1189 );
1190 }
1191
1192 if (!empty($_SERVER['REQUEST_URI']) && false !== strpos($_SERVER['REQUEST_URI'], '/admin.php?page=docket-cache')) {
1193 add_action(
1194 'plugins_loaded',
1195 function () {
1196 if (!headers_sent() && !empty($_SERVER['REQUEST_URI'])) {
1197 if ($this->cf()->is_dctrue('LOG')) {
1198 $req = $_SERVER['REQUEST_URI'];
1199 if ((false !== strpos($req, '?page=docket-cache&idx=log&dl=0') || false !== strpos($req, '?page=docket-cache-log&idx=log&dl=0'))
1200 && preg_match('@log\&dl=\d+$@', $req)) {
1201 $file = $this->cf()->dcvalue('LOG_FILE');
1202
1203 if (is_multisite()) {
1204 $file = nwdcx_network_filepath($file);
1205 }
1206
1207 @header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
1208 @header('Content-Type: text/plain; charset=UTF-8');
1209 if (@is_file($file) && @is_readable($file)) {
1210 if (@readfile($file) > 0) {
1211 $this->close_exit();
1212 }
1213 }
1214
1215 $this->close_exit(__('The log is empty. No data is available.', 'docket-cache'));
1216 }
1217 }
1218
1219 if ($this->cf()->is_true('WP_DEBUG') && $this->cf()->is_true('WP_DEBUG_LOG')) {
1220 $req = $_SERVER['REQUEST_URI'];
1221 if ((false !== strpos($req, '?page=docket-cache&idx=config&wplog=0') || false !== strpos($req, '?page=docket-cache-config&idx=config&wplog=0'))
1222 && preg_match('@config\&wplog=\d+(\&dd=\d+)?$@', $req)) {
1223 $file = \ini_get('error_log');
1224
1225 @header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
1226 @header('Content-Type: text/plain; charset=UTF-8');
1227 if (@is_file($file) && @is_readable($file)) {
1228 if ($this->cf()->is_dctrue('TRYREADWPDEBUGLOG') || !empty($_GET['dd']) && 1 === (int) $_GET['dd']) {
1229 $log = file_get_contents($file);
1230 if (!empty($log)) {
1231 $log = str_replace(['undefined function', 'Stack trace'], ['undefined-function', 'Stack-trace'], $log);
1232 }
1233 $this->close_exit($log);
1234 }
1235
1236 if (@readfile($file) > 0) {
1237 $this->close_exit();
1238 }
1239 }
1240
1241 $this->close_exit(__('The log is empty. No data is available.', 'docket-cache'));
1242 }
1243 }
1244 }
1245 },
1246 \PHP_INT_MIN
1247 );
1248 }
1249
1250 // low priority
1251 add_action(
1252 'plugins_loaded',
1253 function () {
1254 if (nwdcx_wpdb($wpdb)) {
1255 if ($this->co()->lockexp('sqlbigselect')) {
1256 return;
1257 }
1258
1259 $suppress = $wpdb->suppress_errors(true);
1260 $ok = $wpdb->get_var('SELECT @@SESSION.SQL_BIG_SELECTS LIMIT 1');
1261 if (empty($ok)) {
1262 $wpdb->query('SET SESSION SQL_BIG_SELECTS=1');
1263 } else {
1264 // already big select, lock 28d
1265 $locktime = time() + 2419200;
1266 $this->co()->setlock('sqlbigselect', $locktime);
1267 }
1268
1269 $wpdb->suppress_errors($suppress);
1270 }
1271 },
1272 \PHP_INT_MIN
1273 );
1274
1275 add_action(
1276 'plugins_loaded',
1277 function () {
1278 $dc_option = $this->co()->get('DOCKET_CACHE_AUTOUPDATE');
1279 if (!empty($dc_option)) {
1280 $cache_hash_group = substr(md5('options'), 0, 12);
1281 $cache_hash_key = substr(md5('auto_update_plugins'), 0, 12);
1282 if (is_multisite()) {
1283 $cache_hash_group = substr(md5('site-options'), 0, 12);
1284 $cache_hash_key = substr(md5(get_current_network_id().':auto_update_plugins'), 0, 12);
1285 }
1286
1287 $file_cache = $this->cache_path.$cache_hash_group.'-'.$cache_hash_key.'.php';
1288 if (is_file($file_cache)) {
1289 @unlink($file_cache);
1290 }
1291
1292 clearstatcache();
1293
1294 if ('enable' === $dc_option) {
1295 $this->co()->save('autoupdate_toggle', 'enable');
1296 } elseif ('disable' === $dc_option) {
1297 $this->co()->save('autoupdate_toggle', 'disable');
1298 }
1299
1300 $this->co()->save('AUTOUPDATE', false);
1301 }
1302 },
1303 \PHP_INT_MAX
1304 );
1305
1306 add_action(
1307 'update_site_option',
1308 function ($option, $auto_updates, $old_auto_updates, $network_id) {
1309 if ('auto_update_plugins' === $option) {
1310 if (\in_array($this->hook, (array) $auto_updates, true) && !\in_array($this->hook, (array) $old_auto_updates, true)) {
1311 $this->co()->save('autoupdate_toggle', 'enable', false);
1312
1313 return;
1314 }
1315
1316 if (\in_array($this->hook, (array) $old_auto_updates, true) && !\in_array($this->hook, (array) $auto_updates, true)) {
1317 $this->co()->save('autoupdate_toggle', 'disable', false);
1318
1319 return;
1320 }
1321
1322 return;
1323 }
1324 },
1325 \PHP_INT_MAX,
1326 4
1327 );
1328
1329 // fix index.
1330 add_filter(
1331 'pre_update_site_option_auto_update_plugins',
1332 function ($value, $old_value, $option, $network_id) {
1333 if (\is_array($value) && !empty($value)) {
1334 return array_values($value);
1335 }
1336
1337 return $value;
1338 },
1339 10,
1340 4
1341 );
1342
1343 add_filter(
1344 'auto_update_plugin',
1345 function ($update, $item) {
1346 if (\is_object($item) && isset($item->slug) && 'docket-cache' === $item->slug) {
1347 if (\defined('DOCKET_CACHE_AUTOUPDATE') && \is_bool(DOCKET_CACHE_AUTOUPDATE)) {
1348 return DOCKET_CACHE_AUTOUPDATE;
1349 }
1350 }
1351
1352 return $update;
1353 },
1354 \PHP_INT_MAX,
1355 2
1356 );
1357
1358 if ($this->cf()->is_dctrue('CRONBOT') && class_exists('Nawawi\\DocketCache\\CronAgent')) {
1359 ( new CronAgent($this) )->register();
1360 }
1361
1362 register_activation_hook($this->hook, [$this, 'activate']);
1363 register_deactivation_hook($this->hook, [$this, 'deactivate']);
1364 register_uninstall_hook($this->hook, [__CLASS__, 'uninstall']);
1365 }
1366
1367 /**
1368 * action_query.
1369 */
1370 public function action_query($key, $args_extra = [])
1371 {
1372 $key = str_replace('docket-', '', $key);
1373 $key = 'docket-'.$key;
1374
1375 $args = array_merge(
1376 [
1377 'action' => $key,
1378 ],
1379 $args_extra
1380 );
1381
1382 // last
1383 $args['st'] = time();
1384
1385 $page = $this->page;
1386 if (!empty($args['idx']) && $this->is_subpage($args['idx'])) {
1387 $page = $page.'-'.$args['idx'];
1388 }
1389
1390 $query = add_query_arg($args, $page);
1391
1392 return wp_nonce_url(network_admin_url($query), $key);
1393 }
1394
1395 /**
1396 * action_field. Use at addons.
1397 */
1398 public function action_field($key, $args = [])
1399 {
1400 $key = str_replace('docket-', '', $key);
1401 $key = 'docket-'.$key;
1402
1403 $field = wp_nonce_field($key, '_wpnonce', false, false);
1404 $field .= '<input type="hidden" name="action" value="'.$key.'">';
1405 if (!empty($args) && \is_array($args)) {
1406 foreach ($args as $n => $v) {
1407 if ('page' === $n) {
1408 $v = 'docket-cache-'.$v;
1409 }
1410 $field .= '<input type="hidden" name="'.$n.'" value="'.$v.'">';
1411 }
1412 }
1413
1414 return $field;
1415 }
1416
1417 /**
1418 * is_subpage.
1419 */
1420 public function is_subpage($index)
1421 {
1422 if ('mods' === substr($index, 0, 4)) {
1423 return true;
1424 }
1425
1426 $subpage = [
1427 'config' => 1,
1428 'log' => 1,
1429 'cronbot' => 1,
1430 'opcviewer' => 1,
1431 ];
1432
1433 return \array_key_exists($index, $subpage);
1434 }
1435
1436 /**
1437 * get_subpage.
1438 */
1439 public function get_subpage()
1440 {
1441 if (!empty($_GET['page'])) {
1442 if ('docket-cache-' === substr($_GET['page'], 0, 13)) {
1443 $index = substr($_GET['page'], 13);
1444 if (!empty($index) && $this->is_subpage($index)) {
1445 return $index;
1446 }
1447 } elseif ('docket-cache' === $_GET['page'] && !empty($_GET['idx']) && 'mods' === substr($_GET['idx'], 0, 4)) {
1448 return $_GET['idx'];
1449 }
1450 }
1451
1452 return false;
1453 }
1454
1455 /**
1456 * get_screen.
1457 */
1458 public function get_screen()
1459 {
1460 $screen = $this->screen;
1461 $index = $this->get_subpage();
1462 if (!empty($index)) {
1463 $screen = $this->slug.'_page_'.$this->slug.'-'.$index;
1464 }
1465
1466 return $screen;
1467 }
1468
1469 /**
1470 * get_page.
1471 */
1472 public function get_page($args = [])
1473 {
1474 $page = $this->page;
1475 $index = $this->get_subpage();
1476 if (!empty($index)) {
1477 $page = $page.'-'.$index;
1478 }
1479
1480 if (!empty($args) && \is_array($args)) {
1481 $query = http_build_query($args);
1482 if (false !== strpos($page, '?')) {
1483 $page = rtrim($page, '&').'&'.$query;
1484 } else {
1485 $page = $page.'?'.$query;
1486 }
1487 }
1488
1489 return $page;
1490 }
1491
1492 /**
1493 * our_screen.
1494 */
1495 public function our_screen()
1496 {
1497 $current_screen = get_current_screen()->id;
1498 if (substr($current_screen, 0, \strlen($this->screen)) === $this->screen) {
1499 return true;
1500 }
1501
1502 $subsplug = $this->slug.'_page_'.$this->slug.'-';
1503 if (substr($current_screen, 0, \strlen($subsplug)) === $subsplug) {
1504 return true;
1505 }
1506
1507 return false;
1508 }
1509
1510 /**
1511 * register_admin_hooks.
1512 */
1513 private function register_admin_hooks()
1514 {
1515 $action_name = is_multisite() ? 'network_admin_menu' : 'admin_menu';
1516 add_action(
1517 $action_name,
1518 function () {
1519 $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
1520 $order = is_multisite() ? '25.1' : '80.1';
1521 $view = new View($this);
1522
1523 add_menu_page(
1524 'Docket Cache',
1525 'Docket Cache',
1526 $cap,
1527 $this->slug,
1528 [$view, 'index'],
1529 Resc::iconmenu(),
1530 $order
1531 );
1532
1533 $title = esc_html__('Overview', 'docket-cache');
1534 add_submenu_page(
1535 $this->slug,
1536 $title,
1537 $title,
1538 $cap,
1539 $this->slug,
1540 [$view, 'index']
1541 );
1542
1543 if ($this->cf()->is_dctrue('CRONBOT')) {
1544 $title = esc_html__('Cronbot', 'docket-cache');
1545 add_submenu_page(
1546 $this->slug,
1547 $title,
1548 $title,
1549 $cap,
1550 $this->slug.'-cronbot',
1551 [$view, 'index']
1552 );
1553 }
1554
1555 if ($this->cf()->is_dctrue('OPCVIEWER')) {
1556 $title = esc_html__('OPcache', 'docket-cache');
1557 add_submenu_page(
1558 $this->slug,
1559 $title,
1560 $title,
1561 $cap,
1562 $this->slug.'-opcviewer',
1563 [$view, 'index']
1564 );
1565 }
1566
1567 do_action('docketcache/view/submenubefore', $this->slug, $cap, $view);
1568
1569 if ($this->cf()->is_dctrue('LOG')) {
1570 $title = esc_html__('Cache Log', 'docket-cache');
1571 add_submenu_page(
1572 $this->slug,
1573 $title,
1574 $title,
1575 $cap,
1576 $this->slug.'-log',
1577 [$view, 'index']
1578 );
1579 }
1580
1581 $title = esc_html__('Configuration', 'docket-cache');
1582 add_submenu_page(
1583 $this->slug,
1584 $title,
1585 $title,
1586 $cap,
1587 $this->slug.'-config',
1588 [$view, 'index']
1589 );
1590
1591 do_action('docketcache/view/submenuafter', $this->slug, $cap, $view);
1592 }
1593 );
1594
1595 add_action(
1596 'admin_bar_menu',
1597 function ($admin_bar) {
1598 if (!is_multisite() || !current_user_can('manage_network_options')) {
1599 return;
1600 }
1601
1602 $admin_bar->add_menu(
1603 [
1604 'id' => 'network-admin-docketcache',
1605 'parent' => 'network-admin',
1606 'group' => null,
1607 'title' => 'Docket Cache',
1608 'href' => network_admin_url($this->page),
1609 'meta' => [
1610 'title' => 'Docket Cache',
1611 ],
1612 ]
1613 );
1614
1615 if (nwdcx_network_multi()) {
1616 $networks = get_networks();
1617 if (!empty($networks) && \is_array($networks)) {
1618 foreach ($networks as $network) {
1619 $id = $network->id;
1620 $url = $this->site_url_scheme('http://'.$network->domain.$network->path);
1621 $admin_bar->add_menu(
1622 [
1623 'id' => 'network-admin-docketcache-'.$id,
1624 'parent' => 'network-admin-'.$id,
1625 'group' => null,
1626 'title' => 'Docket Cache',
1627 'href' => $url.'/wp-admin/network/'.$this->page,
1628 'meta' => [
1629 'title' => 'Docket Cache',
1630 ],
1631 ]
1632 );
1633 }
1634 }
1635 }
1636 },
1637 \PHP_INT_MAX
1638 );
1639
1640 add_action(
1641 'in_admin_header',
1642 function () {
1643 if ($this->our_screen()) {
1644 remove_all_actions('admin_notices');
1645 remove_all_actions('all_admin_notices');
1646 }
1647
1648 add_action(
1649 'all_admin_notices',
1650 function () {
1651 if (!current_user_can(is_multisite() ? 'manage_network_options' : 'manage_options')) {
1652 return;
1653 }
1654
1655 if (!$this->our_screen() && false === strpos($_SERVER['REQUEST_URI'], '/plugins.php') && false === strpos($_SERVER['REQUEST_URI'], '/update-core.php')) {
1656 return;
1657 }
1658
1659 if ($this->cx()->exists()) {
1660 $url = $this->action_query('update-dropino');
1661 $urld = $this->action_query('dismiss-dropino');
1662
1663 if ($this->cx()->validate()) {
1664 if ($this->cx()->is_outdated() && !$this->cx()->install(true)) {
1665 /* translators: %s: url */
1666 $message = sprintf(__('The object-cache.php Drop-In is outdated. Please click <strong>Re-Install</strong> to update it now. <br><br><a href="%s" style="min-width:100px;text-align:center;font-wight:bold;" class="button button-primary">Re-Install</a>', 'docket-cache'), $url);
1667 }
1668 } else {
1669 /* translators: %1$s: url install, %2$s = url dismiss */
1670 $message = $this->cf()->is_dctrue('OBJECTCACHEOFF', true) ? '' : sprintf(__('An unknown object-cache.php Drop-In was found. Please click <strong>Install</strong> to use <strong>Docket Cache</strong>. <br><br><a href="%1$s" style="min-width:100px;text-align:center;font-weight:bold;" class="button button-primary button-small">Install</a>&nbsp;<a href="%2$s" style="min-width:100px;text-align:center;font-weight:bold;" class="button button-secondary button-small">Dismiss</a>', 'docket-cache'), $url, $urld);
1671 }
1672 }
1673
1674 if (2 === $this->get_status() && $this->our_screen()) {
1675 $message = esc_html__('The Object Cache feature has been disabled at runtime.', 'docket-cache');
1676 }
1677
1678 if (isset($message)) {
1679 echo Resc::boxmsg($message, 'warning', false, false, false);
1680 }
1681 },
1682 \PHP_INT_MAX
1683 );
1684 },
1685 \PHP_INT_MAX
1686 );
1687
1688 add_action(
1689 'admin_enqueue_scripts',
1690 function ($hook) {
1691 $is_debug = $this->cf()->is_true('WP_DEBUG');
1692 $plugin_url = plugin_dir_url($this->file);
1693 $version = str_replace('.', '', $this->version()).'xe'.($is_debug ? date('his') : date('yd'));
1694 wp_enqueue_script($this->slug.'-worker', $plugin_url.'includes/admin/worker.js', ['jquery'], $version, false);
1695 wp_localize_script(
1696 $this->slug.'-worker',
1697 'docket_cache_config',
1698 [
1699 'ajaxurl' => admin_url('admin-ajax.php'),
1700 'token' => wp_create_nonce('docketcache-token-nonce'),
1701 'slug' => $this->slug,
1702 'debug' => $is_debug ? 'true' : 'false',
1703 ]
1704 );
1705
1706 if ($hook === $this->screen || $this->our_screen()) {
1707 wp_enqueue_style($this->slug.'-core', $plugin_url.'includes/admin/docket.css', null, $version);
1708 wp_enqueue_script($this->slug.'-core', $plugin_url.'includes/admin/docket.js', ['jquery'], $version, true);
1709 }
1710
1711 if ($this->cf()->is_dctrue('PAGELOADER')) {
1712 wp_enqueue_style($this->slug.'-loader', $plugin_url.'includes/admin/pageloader.css', null, $version);
1713 wp_enqueue_script($this->slug.'-loader', $plugin_url.'includes/admin/pageloader.js', ['jquery'], $version, true);
1714 }
1715 }
1716 );
1717
1718 add_filter(
1719 'script_loader_tag',
1720 function ($tag, $handle) {
1721 if (\in_array($handle, ['docket-cache-core', 'docket-cache-worker', 'docket-cache-loader'])) {
1722 $tag = str_replace('<script ', '<script data-cfasync="false" data-noptimize="1" data-no-minify="1" ', $tag);
1723 }
1724
1725 return $tag;
1726 },
1727 10,
1728 2
1729 );
1730
1731 add_filter(
1732 'style_loader_tag',
1733 function ($tag, $handle, $href, $media) {
1734 if (\in_array($handle, ['docket-cache-core', 'docket-cache-loader'])) {
1735 $tag = str_replace('<link ', '<link data-noptimize="1" data-no-minify="1" ', $tag);
1736 }
1737
1738 return $tag;
1739 },
1740 10,
1741 4
1742 );
1743 // refresh user_meta: after logout
1744 add_action(
1745 'wp_logout',
1746 function () {
1747 add_action(
1748 'shutdown',
1749 function ($user_id) {
1750 wp_cache_delete($user_id, 'user_meta');
1751 $this->delete_cron_siteid($user_id);
1752 $this->delete_current_select_siteid($user_id);
1753 },
1754 \PHP_INT_MAX
1755 );
1756 },
1757 \PHP_INT_MAX
1758 );
1759
1760 add_action(
1761 'wp_ajax_docket_worker',
1762 function () {
1763 if (!check_ajax_referer('docketcache-token-nonce', 'token', false) && !isset($_POST['type'])) {
1764 wp_send_json_error('Invalid security token sent.');
1765 exit;
1766 }
1767
1768 $type = sanitize_text_field($_POST['type']);
1769
1770 if ($this->cx()->validate()) {
1771 if ('preload' === $type) {
1772 $this->send_json_continue($this->slug.':worker: pong '.$type);
1773 $this->cx()->undelay();
1774 do_action('docketcache/action/preload/objectcache');
1775 exit;
1776 }
1777
1778 if ('fetch' === $type) {
1779 $this->send_json_continue($this->slug.':worker: pong '.$type);
1780 @Crawler::fetch_home();
1781 exit;
1782 }
1783
1784 if ('countcachesize' === $type) {
1785 do_action('docketcache/action/countcachesize');
1786
1787 $info = (object) $this->get_info();
1788
1789 $cache_stats = 1 === $info->status_code && !empty($info->status_text_stats) ? $info->status_text_stats : $info->status_text;
1790 $opcache_stats = 1 === $info->opcache_code && !empty($info->opcache_text_stats) ? $info->opcache_text_stats : $info->opcache_text;
1791 $opcache_dc_stats = !empty($info->opcache_dc_stats) ? $info->opcache_dc_stats : esc_html__('Not Available', 'docket-cache');
1792 $opcache_wp_stats = !empty($info->opcache_wp_stats) ? $info->opcache_wp_stats : esc_html__('Not Available', 'docket-cache');
1793
1794 $response = [];
1795 $response = ['success' => true];
1796 $response['data'] = $this->slug.':worker: pong '.$type;
1797
1798 $stats = [];
1799 $stats['obc'] = '0B' !== substr($cache_stats, 0, 2) ? $cache_stats : esc_html__('Not Available', 'docket-cache');
1800 $stats['opc'] = $opcache_stats;
1801 $stats['obcs'] = '0B' !== substr($info->status_text_stats, 0, 2) ? $info->status_text_stats : esc_html__('Not Available', 'docket-cache');
1802 $stats['opcs'] = $info->opcache_text_stats;
1803 $stats['opcdc'] = $opcache_dc_stats;
1804 $stats['opcwp'] = $opcache_wp_stats;
1805
1806 $stats['ofile'] = $info->cache_file_stats;
1807 $stats['odisk'] = $info->cache_disk_stats;
1808
1809 $response['cachestats'] = $stats;
1810 wp_send_json($response);
1811 exit;
1812 }
1813 }
1814
1815 if ('flush' === $type) {
1816 $this->send_json_continue($this->slug.':worker: pong '.$type);
1817 delete_expired_transients(true);
1818 exit;
1819 }
1820
1821 wp_send_json_error($this->slug.':worker: "'.$type.'" not available');
1822 exit;
1823 }
1824 );
1825
1826 add_filter(
1827 'admin_footer_text',
1828 function ($text) {
1829 if ($this->our_screen()) {
1830 $meta = $this->plugin_meta($this->file);
1831 /* translators: %s: version */
1832 $text = $meta['Name'].' '.sprintf(__('Version %s', 'docket-cache'), $meta['Version']);
1833 $text = apply_filters('docketcache/filter/footerversion', $text);
1834 }
1835
1836 return $text;
1837 },
1838 \PHP_INT_MAX
1839 );
1840
1841 foreach (['update_footer', 'core_update_footer'] as $fn) {
1842 add_filter(
1843 $fn,
1844 function ($text) {
1845 if ($this->our_screen()) {
1846 /* translators: %s: version */
1847 $text = 'WordPress '.' '.sprintf(__('Version %s', 'docket-cache'), $GLOBALS['wp_version']);
1848 }
1849
1850 return $text;
1851 },
1852 \PHP_INT_MAX
1853 );
1854 }
1855
1856 $filter_name = sprintf('%splugin_action_links_%s', is_multisite() ? 'network_admin_' : '', $this->hook);
1857 add_filter(
1858 $filter_name,
1859 function ($links) {
1860 $new = [
1861 'docket-cache-overview' => sprintf('<a href="%s">%s</a>', network_admin_url($this->page), __('Overview', 'docket-cache')),
1862 'docket-cache-configuration' => sprintf('<a href="%s">%s</a>', network_admin_url($this->page.'-config'), __('Configure', 'docket-cache')),
1863 ];
1864
1865 return array_merge($new, $links);
1866 }
1867 );
1868
1869 add_filter(
1870 'plugin_row_meta',
1871 function ($plugin_meta, $plugin_file) {
1872 if ($plugin_file === $this->hook) {
1873 $row_meta = [
1874 'docs' => '<a href="https://docs.docketcache.com/?utm_source=wp-plugins&utm_campaign=doc-uri&utm_medium=wp-dash" target="new" rel="noopener">'.__('Docs', 'docket-cache').'</a>',
1875 'sponsor' => '<a href="https://docketcache.com/sponsorship/?utm_source=wp-plugins&utm_campaign=sponsor-uri&utm_medium=wp-dash" target="new" rel="noopener"><span class="dashicons dashicons-star-filled" aria-hidden="true" style="font-size:14px;line-height:1.3"></span>'.__('Sponsor', 'docket-cache').'</a>',
1876 ];
1877 $plugin_meta = array_merge($plugin_meta, $row_meta);
1878 }
1879
1880 return $plugin_meta;
1881 },
1882 10,
1883 2
1884 );
1885
1886 /*add_filter(
1887 'plugin_auto_update_setting_html',
1888 function ($html, $plugin_file, $plugin_data) {
1889 if ($plugin_file === $this->hook) {
1890 $html .= sprintf('<p><a href="%s"><span class="label">%s</label></a></p>', network_admin_url($this->page.'-config&idx=config&nx=autoupdate'), __('Configure auto-updates', 'docket-cache'));
1891 }
1892
1893 return $html;
1894 },
1895 10,
1896 3
1897 );*/
1898
1899 // reference: Canopt::save()
1900 add_action(
1901 'docketcache/action/saveoption',
1902 function ($name, $value, $status = true) {
1903 switch ($name) {
1904 case 'log':
1905 if (true === $status) {
1906 $this->flush_log();
1907 }
1908 if ('enable' === $value) {
1909 @Crawler::fetch_home();
1910 }
1911 break;
1912 case 'wpoptaload':
1913 add_action(
1914 'shutdown',
1915 function () {
1916 if (\function_exists('wp_cache_flush_group') && method_exists('WP_Object_Cache', 'dc_remove_group')) {
1917 wp_cache_flush_group(['options', 'site-options', 'docketcache-precache', 'docketcache-precache-gc']);
1918 }
1919 },
1920 \PHP_INT_MAX
1921 );
1922
1923 break;
1924 case 'cronoptmzdb':
1925 $this->unregister_cronjob();
1926 break;
1927 case 'cronbot':
1928 $action = 'enable' === $value ? true : false;
1929 add_action(
1930 'shutdown',
1931 function () use ($action) {
1932 if (!$action) {
1933 apply_filters('docketcache/filter/active/cronbot', $action);
1934 }
1935 },
1936 \PHP_INT_MAX
1937 );
1938 break;
1939 case 'rtwpdebug':
1940 case 'rtwpdebuglog':
1941 $error_log = \ini_get('error_log');
1942 if ('off' === $value && @is_file($error_log) && @is_writable($error_log)) {
1943 @unlink($error_log);
1944 clearstatcache();
1945 }
1946 break;
1947 case 'menucache':
1948 if (\function_exists('wp_cache_flush_group') && method_exists('WP_Object_Cache', 'dc_remove_group')) {
1949 wp_cache_flush_group('docketcache-menu');
1950 }
1951 break;
1952 case 'autoupdate_toggle':
1953 if ('enable' === $value) {
1954 $this->toggle_auto_update(true);
1955 } else {
1956 $this->toggle_auto_update(false);
1957 }
1958 break;
1959 case 'transientdb':
1960 add_action(
1961 'shutdown',
1962 function () {
1963 if (\function_exists('wp_cache_flush_group') && method_exists('WP_Object_Cache', 'dc_remove_group')) {
1964 wp_cache_flush_group(['transient', 'site-transient', 'options', 'site-options']);
1965 }
1966
1967 if (\function_exists('nwdcx_cleanuptransient')) {
1968 nwdcx_cleanuptransient();
1969 }
1970 },
1971 \PHP_INT_MAX
1972 );
1973 break;
1974 }
1975
1976 if (WpConfig::is_runtimeconst($name)) {
1977 WpConfig::write_runtime();
1978 }
1979 },
1980 -1,
1981 3
1982 );
1983
1984 add_action(
1985 'docketcache/action/preload/objectcache',
1986 function () {
1987 if ($this->cf()->is_dctrue('WPCLI')) {
1988 return;
1989 }
1990
1991 // lock opcache reset
1992 $this->co()->setlock('preload_lock_opcache_reset', time() + 20);
1993
1994 // warmup: see Dropino::after_delay
1995 if ($this->cf()->is_dcfalse('PRELOAD', true)) {
1996 add_action(
1997 'shutdown',
1998 function () {
1999 if ($this->co()->lockproc('preload', time() + 3600)) {
2000 return false;
2001 }
2002 // wp_load_alloptions();
2003 wp_count_comments(0);
2004 wp_count_posts();
2005 @Crawler::fetch_home(['blocking' => true]);
2006
2007 $this->co()->lockreset('preload');
2008 },
2009 \PHP_INT_MAX
2010 );
2011
2012 return;
2013 }
2014
2015 // preload
2016 add_action(
2017 'shutdown',
2018 function () {
2019 if ($this->co()->lockproc('preload', time() + 3600)) {
2020 return false;
2021 }
2022
2023 wp_load_alloptions();
2024 wp_count_comments(0);
2025 wp_count_posts();
2026
2027 @Crawler::fetch_home(['blocking' => true]);
2028
2029 $preload_admin = [
2030 'index.php',
2031 'options-general.php',
2032 'options-writing.php',
2033 'options-reading.php',
2034 'options-discussion.php',
2035 'options-media.php',
2036 'options-permalink.php',
2037 'edit-comments.php',
2038 'profile.php',
2039 'users.php',
2040 'upload.php',
2041 'plugins.php',
2042 'edit.php',
2043 'edit-tags.php?taxonomy=category',
2044 'edit-tags.php?taxonomy=post_tag',
2045 'edit.php?post_type=page',
2046 'post-new.php?post_type=page',
2047 'themes.php',
2048 'widgets.php',
2049 'nav-menus.php',
2050 'tools.php',
2051 'import.php',
2052 'export.php',
2053 'site-health.php',
2054 'update-core.php',
2055 ];
2056
2057 $preload_network = [
2058 'index.php',
2059 'update-core.php',
2060 'sites.php',
2061 'users.php',
2062 'themes.php',
2063 'plugins.php',
2064 'settings.php',
2065 ];
2066
2067 if ($this->cf()->is_dcarray('PRELOAD_ADMIN')) {
2068 $preload_admin = $this->cf()->dcvalue('PRELOAD_ADMIN');
2069 }
2070
2071 if ($this->cf()->is_dcarray('PRELOAD_NETWORK')) {
2072 $preload_network = $this->cf()->dcvalue('PRELOAD_NETWORK');
2073 }
2074
2075 if (\is_array($preload_admin) && !empty($preload_admin)) {
2076 foreach ($preload_admin as $path) {
2077 $url = admin_url('/'.$path);
2078 @Crawler::fetch_admin($url, ['blocking' => true]);
2079 usleep(500000);
2080 }
2081 }
2082
2083 if (is_multisite() && \is_array($preload_network) && !empty($preload_network)) {
2084 foreach ($preload_network as $path) {
2085 $url = network_admin_url('/'.$path);
2086 @Crawler::fetch_admin($url, ['blocking' => true]);
2087 usleep(500000);
2088 }
2089 }
2090
2091 $this->co()->lockreset('preload');
2092 },
2093 \PHP_INT_MAX
2094 );
2095 }
2096 );
2097
2098 add_action(
2099 'docketcache/action/countcachesize',
2100 function () {
2101 // gc is running
2102 if ($this->co()->locked('garbage_collector')) {
2103 return;
2104 }
2105
2106 if ($this->co()->lockproc('doing_countcachesize', time() + $this->get_max_execution_time())) {
2107 return;
2108 }
2109
2110 $cache_stats = $this->cache_size($this->cache_path);
2111 $this->co()->save_part($cache_stats, 'cachestats');
2112
2113 $this->co()->lockreset('doing_countcachesize');
2114 },
2115 \PHP_INT_MAX
2116 );
2117
2118 add_action(
2119 'docketcache/action/flushcache/object',
2120 function () {
2121 $this->flush_cache(true);
2122 }
2123 );
2124
2125 // page action
2126 if (class_exists('Nawawi\\DocketCache\\ReqAction')) {
2127 ( new ReqAction($this) )->register();
2128 }
2129 }
2130
2131 /**
2132 * register_tweaks.
2133 */
2134 private function register_tweaks()
2135 {
2136 if (\defined('AUTOSAVE_INTERVAL') && false === AUTOSAVE_INTERVAL) {
2137 add_action(
2138 'init',
2139 function () {
2140 wp_deregister_script('autosave');
2141 },
2142 \PHP_INT_MAX
2143 );
2144 }
2145
2146 if (class_exists('Nawawi\\DocketCache\\Tweaks')) {
2147 $tweaks = new Tweaks();
2148
2149 if ($this->cf()->is_dctrue('OPTWPQUERY')) {
2150 $tweaks->wpquery();
2151 }
2152
2153 if ($this->cf()->is_dctrue('WOOTWEAKS')) {
2154 $tweaks->woocommerce_misc();
2155 }
2156
2157 if ($this->cf()->is_dctrue('WOOADMINOFF')) {
2158 $tweaks->woocommerce_admin_disabled();
2159 }
2160
2161 if ($this->cf()->is_dctrue('WOOWPDASHBOARDOFF')) {
2162 $tweaks->woocommerce_dashboard_status_remove();
2163 }
2164
2165 if ($this->cf()->is_dctrue('WOOWIDGETOFF')) {
2166 $tweaks->woocommerce_widget_remove();
2167 }
2168
2169 if ($this->cf()->is_dctrue('WOOCARTFRAGSOFF')) {
2170 $tweaks->woocommerce_cart_fragments_remove();
2171 }
2172
2173 if ($this->cf()->is_dctrue('WOOADDTOCHARTCRAWLING')) {
2174 $tweaks->woocommerce_crawling_addtochart_links();
2175 }
2176
2177 if ($this->cf()->is_dctrue('WOOEXTENSIONPAGEOFF')) {
2178 $tweaks->woocommerce_extensionpage_remove();
2179 }
2180
2181 if ($this->cf()->is_dctrue('MISC_TWEAKS')) {
2182 $tweaks->misc();
2183 }
2184
2185 if ($this->cf()->is_dctrue('HEADERJUNK')) {
2186 $tweaks->headerjunk();
2187 }
2188
2189 if ($this->cf()->is_dctrue('PINGBACK')) {
2190 $tweaks->pingback();
2191 }
2192
2193 if ($this->cf()->is_dctrue('WPEMOJI')) {
2194 $tweaks->wpemoji();
2195 }
2196
2197 if ($this->cf()->is_dctrue('WPFEED')) {
2198 $tweaks->wpfeed();
2199 }
2200
2201 if ($this->cf()->is_dctrue('WPEMBED')) {
2202 $tweaks->wpembed();
2203 }
2204
2205 if ($this->cf()->is_dctrue('WPLAZYLOAD')) {
2206 $tweaks->wplazyload();
2207 }
2208
2209 if ($this->cf()->is_dctrue('WPSITEMAP')) {
2210 $tweaks->wpsitemap();
2211 }
2212
2213 if ($this->cf()->is_dctrue('WPAPPPASSWORD')) {
2214 $tweaks->wpapppassword();
2215 }
2216
2217 if ($this->cf()->is_dctrue('WPDASHBOARDNEWS')) {
2218 $tweaks->wpdashboardnews();
2219 }
2220
2221 if ($this->cf()->is_dctrue('POSTVIAEMAIL')) {
2222 $tweaks->postviaemail();
2223 }
2224
2225 if ($this->cf()->is_dctrue('WPBROWSEHAPPY')) {
2226 $tweaks->wpbrowsehappy();
2227 }
2228
2229 if ($this->cf()->is_dctrue('WPSERVEHAPPY')) {
2230 $tweaks->wpservehappy();
2231 }
2232
2233 if ($this->cf()->is_dctrue('LIMITHTTPREQUEST')) {
2234 $tweaks->limit_http_request();
2235 }
2236
2237 if (version_compare($GLOBALS['wp_version'], '5.8', '<')) {
2238 if ($this->cf()->is_dctrue('HTTPHEADERSEXPECT')) {
2239 $tweaks->http_headers_expect();
2240 }
2241 }
2242
2243 if ($this->cf()->is_dctrue('POSTMISSEDSCHEDULE')) {
2244 add_action(
2245 'shutdown',
2246 function () use ($tweaks) {
2247 if ($this->co()->lockproc('post_missed_schedule', time() + 180)) {
2248 return false;
2249 }
2250 $tweaks->post_missed_schedule();
2251 $this->co()->lockreset('post_missed_schedule');
2252 },
2253 \PHP_INT_MAX
2254 );
2255 }
2256
2257 if ($this->cf()->is_dctrue('CACHEHTTPRESPONSE')) {
2258 $tweaks->cache_http_response();
2259 }
2260 }
2261
2262 // only if dropin exists
2263 if (wp_using_ext_object_cache()) {
2264 // wp_cache: advanced cache post
2265 if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
2266 if ($this->cf()->is_dctrue('ADVCPOST') && class_exists('Nawawi\\DocketCache\\PostCache')) {
2267 ( new PostCache() )->register();
2268 }
2269 }
2270
2271 // wp_cache: translation mo file cache
2272 if ($this->cf()->is_dctrue('MOCACHE') && class_exists('Nawawi\\DocketCache\\MoCache')) {
2273 add_filter(
2274 'override_load_textdomain',
2275 function ($plugin_override, $domain, $mofile) {
2276 if (!@is_file($mofile) || !@is_readable($mofile) || !isset($GLOBALS['l10n'])) {
2277 return false;
2278 }
2279
2280 $l10n = $GLOBALS['l10n'];
2281 $upstream = empty($l10n[$domain]) ? null : $l10n[$domain];
2282 $mo = new MoCache($mofile, $domain, $upstream);
2283 $l10n[$domain] = $mo;
2284
2285 $GLOBALS['l10n'] = $l10n;
2286
2287 return true;
2288 },
2289 \PHP_INT_MAX,
2290 3
2291 );
2292 }
2293
2294 // wp_cache: menu cache
2295 if ($this->cf()->is_dctrue('MENUCACHE') && class_exists('Nawawi\\DocketCache\\MenuCache')) {
2296 ( new MenuCache() )->register();
2297 }
2298 }
2299
2300 // optimize term count
2301 if ($this->cf()->is_dctrue('OPTERMCOUNT') && class_exists('Nawawi\\DocketCache\\TermCount')) {
2302 ( new TermCount() )->register();
2303 }
2304
2305 if ($this->cf()->is_dctrue('LIMITBULKEDIT') && class_exists('Nawawi\\DocketCache\\LimitBulkedit')) {
2306 ( new LimitBulkedit() )->register();
2307 }
2308 }
2309
2310 /**
2311 * register_cronjob.
2312 */
2313 private function register_cronjob()
2314 {
2315 ( new Event($this) )->register();
2316 }
2317
2318 /**
2319 * unregister_cronjob.
2320 */
2321 private function unregister_cronjob()
2322 {
2323 ( new Event($this) )->unregister();
2324 }
2325
2326 private function register_cli()
2327 {
2328 if ($this->cf()->is_dctrue('WPCLI') && $this->cf()->is_false('DocketCache_CLI')) {
2329 \define('DocketCache_CLI', true);
2330 $cli = new Command($this);
2331
2332 \WP_CLI::add_command('cache dropin:update', [$cli, 'dropino_update']);
2333 \WP_CLI::add_command('cache dropin:enable', [$cli, 'dropino_enable']);
2334 \WP_CLI::add_command('cache dropin:disable', [$cli, 'dropino_disable']);
2335 \WP_CLI::add_command('cache run:gc', [$cli, 'run_gc']);
2336 \WP_CLI::add_command('cache run:cron', [$cli, 'run_cron']);
2337 \WP_CLI::add_command('cache run:stats', [$cli, 'run_stats']);
2338 \WP_CLI::add_command('cache run:optimizedb', [$cli, 'run_optimizedb']);
2339 \WP_CLI::add_command('cache reset:lock', [$cli, 'reset_lock']);
2340 \WP_CLI::add_command('cache reset:cron', [$cli, 'reset_cron']);
2341
2342 if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
2343 \WP_CLI::add_command('cache flush:advcpost', [$cli, 'flush_advcpost']);
2344 }
2345
2346 \WP_CLI::add_command('cache flush:precache', [$cli, 'flush_precache']);
2347 \WP_CLI::add_command('cache flush:menucache', [$cli, 'flush_menucache']);
2348 \WP_CLI::add_command('cache flush:mocache', [$cli, 'flush_mocache']);
2349 \WP_CLI::add_command('cache flush:transient', [$cli, 'flush_transient']);
2350 \WP_CLI::add_command('cache flush', [$cli, 'flush_cache']);
2351 \WP_CLI::add_command('cache runtime:install', [$cli, 'runtime_install']);
2352 \WP_CLI::add_command('cache runtime:remove', [$cli, 'runtime_remove']);
2353 \WP_CLI::add_command('cache status', [$cli, 'status']);
2354 \WP_CLI::add_command('cache type', [$cli, 'type']);
2355 nwdcx_runaction('docketcache/init/cli', $this, $cli);
2356 }
2357 }
2358
2359 /**
2360 * register.
2361 */
2362 public function register()
2363 {
2364 if (!$this->compat_notice()) {
2365 return;
2366 }
2367 $this->register_plugin_hooks();
2368 $this->register_admin_hooks();
2369 $this->register_tweaks();
2370 $this->register_cronjob();
2371 $this->register_cli();
2372
2373 nwdcx_runaction('docketcache/init', $this);
2374 }
2375 }
2376