PluginProbe
Docket Cache – Object Cache Accelerator / 24.07.06
Docket Cache – Object Cache Accelerator v24.07.06
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.06, at includes/src/Plugin.php

2,387 lines 79.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Docket Cache.
4 *
5 * @author Nawawi Jamili
6 * @license MIT
7 *
8 * @see https://github.com/nawawi/docket-cache
9 */
10
11 namespace Nawawi\DocketCache;
12
13 \defined('ABSPATH') || exit;
14
15 final class 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 $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
1692 if (!current_user_can($cap)) {
1693 return;
1694 }
1695
1696 $is_debug = $this->cf()->is_true('WP_DEBUG');
1697 $plugin_url = plugin_dir_url($this->file);
1698 $version = str_replace('.', '', $this->version()).'xe'.($is_debug ? date('his') : date('yd'));
1699 wp_enqueue_script($this->slug.'-worker', $plugin_url.'includes/admin/worker.js', ['jquery'], $version, false);
1700 wp_localize_script(
1701 $this->slug.'-worker',
1702 'docket_cache_config',
1703 [
1704 'ajaxurl' => admin_url('admin-ajax.php'),
1705 'token' => wp_create_nonce('docketcache-token-nonce'),
1706 'slug' => $this->slug,
1707 'debug' => $is_debug ? 'true' : 'false',
1708 ]
1709 );
1710
1711 if ($hook === $this->screen || $this->our_screen()) {
1712 wp_enqueue_style($this->slug.'-core', $plugin_url.'includes/admin/docket.css', null, $version);
1713 wp_enqueue_script($this->slug.'-core', $plugin_url.'includes/admin/docket.js', ['jquery'], $version, true);
1714 }
1715
1716 if ($this->cf()->is_dctrue('PAGELOADER')) {
1717 wp_enqueue_style($this->slug.'-loader', $plugin_url.'includes/admin/pageloader.css', null, $version);
1718 wp_enqueue_script($this->slug.'-loader', $plugin_url.'includes/admin/pageloader.js', ['jquery'], $version, true);
1719 }
1720 }
1721 );
1722
1723 add_filter(
1724 'script_loader_tag',
1725 function ($tag, $handle) {
1726 if (\in_array($handle, ['docket-cache-core', 'docket-cache-worker', 'docket-cache-loader'])) {
1727 $tag = str_replace('<script ', '<script data-cfasync="false" data-noptimize="1" data-no-minify="1" ', $tag);
1728 }
1729
1730 return $tag;
1731 },
1732 10,
1733 2
1734 );
1735
1736 add_filter(
1737 'style_loader_tag',
1738 function ($tag, $handle, $href, $media) {
1739 if (\in_array($handle, ['docket-cache-core', 'docket-cache-loader'])) {
1740 $tag = str_replace('<link ', '<link data-noptimize="1" data-no-minify="1" ', $tag);
1741 }
1742
1743 return $tag;
1744 },
1745 10,
1746 4
1747 );
1748 // refresh user_meta: after logout
1749 add_action(
1750 'wp_logout',
1751 function () {
1752 add_action(
1753 'shutdown',
1754 function ($user_id) {
1755 wp_cache_delete($user_id, 'user_meta');
1756 $this->delete_cron_siteid($user_id);
1757 $this->delete_current_select_siteid($user_id);
1758 },
1759 \PHP_INT_MAX
1760 );
1761 },
1762 \PHP_INT_MAX
1763 );
1764
1765 add_action(
1766 'wp_ajax_docket_worker',
1767 function () {
1768 if (!check_ajax_referer('docketcache-token-nonce', 'token', false) || !isset($_POST['type'])) {
1769 wp_send_json_error('Invalid security token sent.');
1770 exit;
1771 }
1772
1773 $cap = is_multisite() ? 'manage_network_options' : 'manage_options';
1774 if (!current_user_can($cap)) {
1775 wp_send_json_error('Unauthorized access.');
1776 exit;
1777 }
1778
1779 $type = sanitize_text_field($_POST['type']);
1780
1781 if ($this->cx()->validate()) {
1782 if ('preload' === $type) {
1783 $this->send_json_continue($this->slug.':worker: pong '.$type);
1784 $this->cx()->undelay();
1785 do_action('docketcache/action/preload/objectcache');
1786 exit;
1787 }
1788
1789 if ('fetch' === $type) {
1790 $this->send_json_continue($this->slug.':worker: pong '.$type);
1791 @Crawler::fetch_home();
1792 exit;
1793 }
1794
1795 if ('countcachesize' === $type) {
1796 do_action('docketcache/action/countcachesize');
1797
1798 $info = (object) $this->get_info();
1799
1800 $cache_stats = 1 === $info->status_code && !empty($info->status_text_stats) ? $info->status_text_stats : $info->status_text;
1801 $opcache_stats = 1 === $info->opcache_code && !empty($info->opcache_text_stats) ? $info->opcache_text_stats : $info->opcache_text;
1802 $opcache_dc_stats = !empty($info->opcache_dc_stats) ? $info->opcache_dc_stats : esc_html__('Not Available', 'docket-cache');
1803 $opcache_wp_stats = !empty($info->opcache_wp_stats) ? $info->opcache_wp_stats : esc_html__('Not Available', 'docket-cache');
1804
1805 $response = [];
1806 $response = ['success' => true];
1807 $response['data'] = $this->slug.':worker: pong '.$type;
1808
1809 $stats = [];
1810 $stats['obc'] = '0B' !== substr($cache_stats, 0, 2) ? $cache_stats : esc_html__('Not Available', 'docket-cache');
1811 $stats['opc'] = $opcache_stats;
1812 $stats['obcs'] = '0B' !== substr($info->status_text_stats, 0, 2) ? $info->status_text_stats : esc_html__('Not Available', 'docket-cache');
1813 $stats['opcs'] = $info->opcache_text_stats;
1814 $stats['opcdc'] = $opcache_dc_stats;
1815 $stats['opcwp'] = $opcache_wp_stats;
1816
1817 $stats['ofile'] = $info->cache_file_stats;
1818 $stats['odisk'] = $info->cache_disk_stats;
1819
1820 $response['cachestats'] = $stats;
1821 wp_send_json($response);
1822 exit;
1823 }
1824 }
1825
1826 if ('flush' === $type) {
1827 $this->send_json_continue($this->slug.':worker: pong '.$type);
1828 delete_expired_transients(true);
1829 exit;
1830 }
1831
1832 wp_send_json_error($this->slug.':worker: "'.$type.'" not available');
1833 exit;
1834 }
1835 );
1836
1837 add_filter(
1838 'admin_footer_text',
1839 function ($text) {
1840 if ($this->our_screen()) {
1841 $meta = $this->plugin_meta($this->file);
1842 /* translators: %s: version */
1843 $text = $meta['Name'].' '.sprintf(__('Version %s', 'docket-cache'), $meta['Version']);
1844 $text = apply_filters('docketcache/filter/footerversion', $text);
1845 }
1846
1847 return $text;
1848 },
1849 \PHP_INT_MAX
1850 );
1851
1852 foreach (['update_footer', 'core_update_footer'] as $fn) {
1853 add_filter(
1854 $fn,
1855 function ($text) {
1856 if ($this->our_screen()) {
1857 /* translators: %s: version */
1858 $text = 'WordPress '.' '.sprintf(__('Version %s', 'docket-cache'), $GLOBALS['wp_version']);
1859 }
1860
1861 return $text;
1862 },
1863 \PHP_INT_MAX
1864 );
1865 }
1866
1867 $filter_name = sprintf('%splugin_action_links_%s', is_multisite() ? 'network_admin_' : '', $this->hook);
1868 add_filter(
1869 $filter_name,
1870 function ($links) {
1871 $new = [
1872 'docket-cache-overview' => sprintf('<a href="%s">%s</a>', network_admin_url($this->page), __('Overview', 'docket-cache')),
1873 'docket-cache-configuration' => sprintf('<a href="%s">%s</a>', network_admin_url($this->page.'-config'), __('Configure', 'docket-cache')),
1874 ];
1875
1876 return array_merge($new, $links);
1877 }
1878 );
1879
1880 add_filter(
1881 'plugin_row_meta',
1882 function ($plugin_meta, $plugin_file) {
1883 if ($plugin_file === $this->hook) {
1884 $row_meta = [
1885 '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>',
1886 '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>',
1887 ];
1888 $plugin_meta = array_merge($plugin_meta, $row_meta);
1889 }
1890
1891 return $plugin_meta;
1892 },
1893 10,
1894 2
1895 );
1896
1897 /*add_filter(
1898 'plugin_auto_update_setting_html',
1899 function ($html, $plugin_file, $plugin_data) {
1900 if ($plugin_file === $this->hook) {
1901 $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'));
1902 }
1903
1904 return $html;
1905 },
1906 10,
1907 3
1908 );*/
1909
1910 // reference: Canopt::save()
1911 add_action(
1912 'docketcache/action/saveoption',
1913 function ($name, $value, $status = true) {
1914 switch ($name) {
1915 case 'log':
1916 if (true === $status) {
1917 $this->flush_log();
1918 }
1919 if ('enable' === $value) {
1920 @Crawler::fetch_home();
1921 }
1922 break;
1923 case 'wpoptaload':
1924 add_action(
1925 'shutdown',
1926 function () {
1927 if (\function_exists('wp_cache_flush_group') && method_exists('WP_Object_Cache', 'dc_remove_group')) {
1928 wp_cache_flush_group(['options', 'site-options', 'docketcache-precache', 'docketcache-precache-gc']);
1929 }
1930 },
1931 \PHP_INT_MAX
1932 );
1933
1934 break;
1935 case 'cronoptmzdb':
1936 $this->unregister_cronjob();
1937 break;
1938 case 'cronbot':
1939 $action = 'enable' === $value ? true : false;
1940 add_action(
1941 'shutdown',
1942 function () use ($action) {
1943 if (!$action) {
1944 apply_filters('docketcache/filter/active/cronbot', $action);
1945 }
1946 },
1947 \PHP_INT_MAX
1948 );
1949 break;
1950 case 'rtwpdebug':
1951 case 'rtwpdebuglog':
1952 $error_log = \ini_get('error_log');
1953 if ('off' === $value && @is_file($error_log) && @is_writable($error_log)) {
1954 @unlink($error_log);
1955 clearstatcache();
1956 }
1957 break;
1958 case 'menucache':
1959 if (\function_exists('wp_cache_flush_group') && method_exists('WP_Object_Cache', 'dc_remove_group')) {
1960 wp_cache_flush_group('docketcache-menu');
1961 }
1962 break;
1963 case 'autoupdate_toggle':
1964 if ('enable' === $value) {
1965 $this->toggle_auto_update(true);
1966 } else {
1967 $this->toggle_auto_update(false);
1968 }
1969 break;
1970 case 'transientdb':
1971 add_action(
1972 'shutdown',
1973 function () {
1974 if (\function_exists('wp_cache_flush_group') && method_exists('WP_Object_Cache', 'dc_remove_group')) {
1975 wp_cache_flush_group(['transient', 'site-transient', 'options', 'site-options']);
1976 }
1977
1978 if (\function_exists('nwdcx_cleanuptransient')) {
1979 nwdcx_cleanuptransient();
1980 }
1981 },
1982 \PHP_INT_MAX
1983 );
1984 break;
1985 }
1986
1987 if (WpConfig::is_runtimeconst($name)) {
1988 WpConfig::write_runtime();
1989 }
1990 },
1991 -1,
1992 3
1993 );
1994
1995 add_action(
1996 'docketcache/action/preload/objectcache',
1997 function () {
1998 if ($this->cf()->is_dctrue('WPCLI')) {
1999 return;
2000 }
2001
2002 // lock opcache reset
2003 $this->co()->setlock('preload_lock_opcache_reset', time() + 20);
2004
2005 // warmup: see Dropino::after_delay
2006 if ($this->cf()->is_dcfalse('PRELOAD', true)) {
2007 add_action(
2008 'shutdown',
2009 function () {
2010 if ($this->co()->lockproc('preload', time() + 3600)) {
2011 return false;
2012 }
2013 // wp_load_alloptions();
2014 wp_count_comments(0);
2015 wp_count_posts();
2016 @Crawler::fetch_home(['blocking' => true]);
2017
2018 $this->co()->lockreset('preload');
2019 },
2020 \PHP_INT_MAX
2021 );
2022
2023 return;
2024 }
2025
2026 // preload
2027 add_action(
2028 'shutdown',
2029 function () {
2030 if ($this->co()->lockproc('preload', time() + 3600)) {
2031 return false;
2032 }
2033
2034 wp_load_alloptions();
2035 wp_count_comments(0);
2036 wp_count_posts();
2037
2038 @Crawler::fetch_home(['blocking' => true]);
2039
2040 $preload_admin = [
2041 'index.php',
2042 'options-general.php',
2043 'options-writing.php',
2044 'options-reading.php',
2045 'options-discussion.php',
2046 'options-media.php',
2047 'options-permalink.php',
2048 'edit-comments.php',
2049 'profile.php',
2050 'users.php',
2051 'upload.php',
2052 'plugins.php',
2053 'edit.php',
2054 'edit-tags.php?taxonomy=category',
2055 'edit-tags.php?taxonomy=post_tag',
2056 'edit.php?post_type=page',
2057 'post-new.php?post_type=page',
2058 'themes.php',
2059 'widgets.php',
2060 'nav-menus.php',
2061 'tools.php',
2062 'import.php',
2063 'export.php',
2064 'site-health.php',
2065 'update-core.php',
2066 ];
2067
2068 $preload_network = [
2069 'index.php',
2070 'update-core.php',
2071 'sites.php',
2072 'users.php',
2073 'themes.php',
2074 'plugins.php',
2075 'settings.php',
2076 ];
2077
2078 if ($this->cf()->is_dcarray('PRELOAD_ADMIN')) {
2079 $preload_admin = $this->cf()->dcvalue('PRELOAD_ADMIN');
2080 }
2081
2082 if ($this->cf()->is_dcarray('PRELOAD_NETWORK')) {
2083 $preload_network = $this->cf()->dcvalue('PRELOAD_NETWORK');
2084 }
2085
2086 if (\is_array($preload_admin) && !empty($preload_admin)) {
2087 foreach ($preload_admin as $path) {
2088 $url = admin_url('/'.$path);
2089 @Crawler::fetch_admin($url, ['blocking' => true]);
2090 usleep(500000);
2091 }
2092 }
2093
2094 if (is_multisite() && \is_array($preload_network) && !empty($preload_network)) {
2095 foreach ($preload_network as $path) {
2096 $url = network_admin_url('/'.$path);
2097 @Crawler::fetch_admin($url, ['blocking' => true]);
2098 usleep(500000);
2099 }
2100 }
2101
2102 $this->co()->lockreset('preload');
2103 },
2104 \PHP_INT_MAX
2105 );
2106 }
2107 );
2108
2109 add_action(
2110 'docketcache/action/countcachesize',
2111 function () {
2112 // gc is running
2113 if ($this->co()->locked('garbage_collector')) {
2114 return;
2115 }
2116
2117 if ($this->co()->lockproc('doing_countcachesize', time() + $this->get_max_execution_time())) {
2118 return;
2119 }
2120
2121 $cache_stats = $this->cache_size($this->cache_path);
2122 $this->co()->save_part($cache_stats, 'cachestats');
2123
2124 $this->co()->lockreset('doing_countcachesize');
2125 },
2126 \PHP_INT_MAX
2127 );
2128
2129 add_action(
2130 'docketcache/action/flushcache/object',
2131 function () {
2132 $this->flush_cache(true);
2133 }
2134 );
2135
2136 // page action
2137 if (class_exists('Nawawi\\DocketCache\\ReqAction')) {
2138 ( new ReqAction($this) )->register();
2139 }
2140 }
2141
2142 /**
2143 * register_tweaks.
2144 */
2145 private function register_tweaks()
2146 {
2147 if (\defined('AUTOSAVE_INTERVAL') && false === AUTOSAVE_INTERVAL) {
2148 add_action(
2149 'init',
2150 function () {
2151 wp_deregister_script('autosave');
2152 },
2153 \PHP_INT_MAX
2154 );
2155 }
2156
2157 if (class_exists('Nawawi\\DocketCache\\Tweaks')) {
2158 $tweaks = new Tweaks();
2159
2160 if ($this->cf()->is_dctrue('OPTWPQUERY')) {
2161 $tweaks->wpquery();
2162 }
2163
2164 if ($this->cf()->is_dctrue('WOOTWEAKS')) {
2165 $tweaks->woocommerce_misc();
2166 }
2167
2168 if ($this->cf()->is_dctrue('WOOADMINOFF')) {
2169 $tweaks->woocommerce_admin_disabled();
2170 }
2171
2172 if ($this->cf()->is_dctrue('WOOWPDASHBOARDOFF')) {
2173 $tweaks->woocommerce_dashboard_status_remove();
2174 }
2175
2176 if ($this->cf()->is_dctrue('WOOWIDGETOFF')) {
2177 $tweaks->woocommerce_widget_remove();
2178 }
2179
2180 if ($this->cf()->is_dctrue('WOOCARTFRAGSOFF')) {
2181 $tweaks->woocommerce_cart_fragments_remove();
2182 }
2183
2184 if ($this->cf()->is_dctrue('WOOADDTOCHARTCRAWLING')) {
2185 $tweaks->woocommerce_crawling_addtochart_links();
2186 }
2187
2188 if ($this->cf()->is_dctrue('WOOEXTENSIONPAGEOFF')) {
2189 $tweaks->woocommerce_extensionpage_remove();
2190 }
2191
2192 if ($this->cf()->is_dctrue('MISC_TWEAKS')) {
2193 $tweaks->misc();
2194 }
2195
2196 if ($this->cf()->is_dctrue('HEADERJUNK')) {
2197 $tweaks->headerjunk();
2198 }
2199
2200 if ($this->cf()->is_dctrue('PINGBACK')) {
2201 $tweaks->pingback();
2202 }
2203
2204 if ($this->cf()->is_dctrue('WPEMOJI')) {
2205 $tweaks->wpemoji();
2206 }
2207
2208 if ($this->cf()->is_dctrue('WPFEED')) {
2209 $tweaks->wpfeed();
2210 }
2211
2212 if ($this->cf()->is_dctrue('WPEMBED')) {
2213 $tweaks->wpembed();
2214 }
2215
2216 if ($this->cf()->is_dctrue('WPLAZYLOAD')) {
2217 $tweaks->wplazyload();
2218 }
2219
2220 if ($this->cf()->is_dctrue('WPSITEMAP')) {
2221 $tweaks->wpsitemap();
2222 }
2223
2224 if ($this->cf()->is_dctrue('WPAPPPASSWORD')) {
2225 $tweaks->wpapppassword();
2226 }
2227
2228 if ($this->cf()->is_dctrue('WPDASHBOARDNEWS')) {
2229 $tweaks->wpdashboardnews();
2230 }
2231
2232 if ($this->cf()->is_dctrue('POSTVIAEMAIL')) {
2233 $tweaks->postviaemail();
2234 }
2235
2236 if ($this->cf()->is_dctrue('WPBROWSEHAPPY')) {
2237 $tweaks->wpbrowsehappy();
2238 }
2239
2240 if ($this->cf()->is_dctrue('WPSERVEHAPPY')) {
2241 $tweaks->wpservehappy();
2242 }
2243
2244 if ($this->cf()->is_dctrue('LIMITHTTPREQUEST')) {
2245 $tweaks->limit_http_request();
2246 }
2247
2248 if (version_compare($GLOBALS['wp_version'], '5.8', '<')) {
2249 if ($this->cf()->is_dctrue('HTTPHEADERSEXPECT')) {
2250 $tweaks->http_headers_expect();
2251 }
2252 }
2253
2254 if ($this->cf()->is_dctrue('POSTMISSEDSCHEDULE')) {
2255 add_action(
2256 'shutdown',
2257 function () use ($tweaks) {
2258 if ($this->co()->lockproc('post_missed_schedule', time() + 180)) {
2259 return false;
2260 }
2261 $tweaks->post_missed_schedule();
2262 $this->co()->lockreset('post_missed_schedule');
2263 },
2264 \PHP_INT_MAX
2265 );
2266 }
2267
2268 if ($this->cf()->is_dctrue('CACHEHTTPRESPONSE')) {
2269 $tweaks->cache_http_response();
2270 }
2271 }
2272
2273 // only if dropin exists
2274 if (wp_using_ext_object_cache()) {
2275 // wp_cache: advanced cache post
2276 if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
2277 if ($this->cf()->is_dctrue('ADVCPOST') && class_exists('Nawawi\\DocketCache\\PostCache')) {
2278 ( new PostCache() )->register();
2279 }
2280 }
2281
2282 // wp_cache: translation mo file cache
2283 if ($this->cf()->is_dctrue('MOCACHE') && class_exists('Nawawi\\DocketCache\\MoCache')) {
2284 add_filter(
2285 'override_load_textdomain',
2286 function ($plugin_override, $domain, $mofile) {
2287 if (!@is_file($mofile) || !@is_readable($mofile) || !isset($GLOBALS['l10n'])) {
2288 return false;
2289 }
2290
2291 $l10n = $GLOBALS['l10n'];
2292 $upstream = empty($l10n[$domain]) ? null : $l10n[$domain];
2293 $mo = new MoCache($mofile, $domain, $upstream);
2294 $l10n[$domain] = $mo;
2295
2296 $GLOBALS['l10n'] = $l10n;
2297
2298 return true;
2299 },
2300 \PHP_INT_MAX,
2301 3
2302 );
2303 }
2304
2305 // wp_cache: menu cache
2306 if ($this->cf()->is_dctrue('MENUCACHE') && class_exists('Nawawi\\DocketCache\\MenuCache')) {
2307 ( new MenuCache() )->register();
2308 }
2309 }
2310
2311 // optimize term count
2312 if ($this->cf()->is_dctrue('OPTERMCOUNT') && class_exists('Nawawi\\DocketCache\\TermCount')) {
2313 ( new TermCount() )->register();
2314 }
2315
2316 if ($this->cf()->is_dctrue('LIMITBULKEDIT') && class_exists('Nawawi\\DocketCache\\LimitBulkedit')) {
2317 ( new LimitBulkedit() )->register();
2318 }
2319 }
2320
2321 /**
2322 * register_cronjob.
2323 */
2324 private function register_cronjob()
2325 {
2326 ( new Event($this) )->register();
2327 }
2328
2329 /**
2330 * unregister_cronjob.
2331 */
2332 private function unregister_cronjob()
2333 {
2334 ( new Event($this) )->unregister();
2335 }
2336
2337 private function register_cli()
2338 {
2339 if ($this->cf()->is_dctrue('WPCLI') && $this->cf()->is_false('DocketCache_CLI')) {
2340 \define('DocketCache_CLI', true);
2341 $cli = new Command($this);
2342
2343 \WP_CLI::add_command('cache dropin:update', [$cli, 'dropino_update']);
2344 \WP_CLI::add_command('cache dropin:enable', [$cli, 'dropino_enable']);
2345 \WP_CLI::add_command('cache dropin:disable', [$cli, 'dropino_disable']);
2346 \WP_CLI::add_command('cache run:gc', [$cli, 'run_gc']);
2347 \WP_CLI::add_command('cache run:cron', [$cli, 'run_cron']);
2348 \WP_CLI::add_command('cache run:stats', [$cli, 'run_stats']);
2349 \WP_CLI::add_command('cache run:optimizedb', [$cli, 'run_optimizedb']);
2350 \WP_CLI::add_command('cache reset:lock', [$cli, 'reset_lock']);
2351 \WP_CLI::add_command('cache reset:cron', [$cli, 'reset_cron']);
2352
2353 if (version_compare($GLOBALS['wp_version'], '6.1', '<')) {
2354 \WP_CLI::add_command('cache flush:advcpost', [$cli, 'flush_advcpost']);
2355 }
2356
2357 \WP_CLI::add_command('cache flush:precache', [$cli, 'flush_precache']);
2358 \WP_CLI::add_command('cache flush:menucache', [$cli, 'flush_menucache']);
2359 \WP_CLI::add_command('cache flush:mocache', [$cli, 'flush_mocache']);
2360 \WP_CLI::add_command('cache flush:transient', [$cli, 'flush_transient']);
2361 \WP_CLI::add_command('cache flush', [$cli, 'flush_cache']);
2362 \WP_CLI::add_command('cache runtime:install', [$cli, 'runtime_install']);
2363 \WP_CLI::add_command('cache runtime:remove', [$cli, 'runtime_remove']);
2364 \WP_CLI::add_command('cache status', [$cli, 'status']);
2365 \WP_CLI::add_command('cache type', [$cli, 'type']);
2366 nwdcx_runaction('docketcache/init/cli', $this, $cli);
2367 }
2368 }
2369
2370 /**
2371 * register.
2372 */
2373 public function register()
2374 {
2375 if (!$this->compat_notice()) {
2376 return;
2377 }
2378 $this->register_plugin_hooks();
2379 $this->register_admin_hooks();
2380 $this->register_tweaks();
2381 $this->register_cronjob();
2382 $this->register_cli();
2383
2384 nwdcx_runaction('docketcache/init', $this);
2385 }
2386 }
2387