PluginProbe
Docket Cache – Object Cache Accelerator / 22.07.05
Docket Cache – Object Cache Accelerator v22.07.05
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 22.07.05, at includes/src/Plugin.php

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