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 / Event.php

Event.php in Docket Cache – Object Cache Accelerator 24.07.06, at includes/src/Event.php

798 lines 28.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 Event
16 {
17 private $pt;
18 private $is_optimizedb;
19 private $max_execution_time = 0;
20 private $wp_start_timestamp = 0;
21
22 public function __construct(Plugin $pt)
23 {
24 $this->pt = $pt;
25 $this->is_optimizedb = false;
26 $this->wp_start_timestamp = \defined('WP_START_TIMESTAMP') ? WP_START_TIMESTAMP : microtime(true);
27 $this->max_execution_time = $this->pt->get_max_execution_time();
28 }
29
30 /**
31 * register.
32 */
33 public function register()
34 {
35 // global
36 add_filter('docketcache/filter/garbagecollector', [$this, 'garbage_collector']);
37
38 add_filter(
39 'cron_schedules',
40 function ($schedules) {
41 $schedules['halfhour'] = [
42 'interval' => 30 * MINUTE_IN_SECONDS,
43 'display' => esc_html__('Every 30 Minutes', 'docket-cache'),
44 ];
45
46 if (empty($schedules['hourly'])) {
47 $schedules['hourly'] = [
48 'interval' => HOUR_IN_SECONDS,
49 'display' => esc_html__('Once Hourly', 'docket-cache'),
50 ];
51 }
52
53 if (empty($schedules['monthly'])) {
54 $schedules['monthly'] = [
55 'interval' => MONTH_IN_SECONDS,
56 'display' => esc_html__('Once Monthly', 'docket-cache'),
57 ];
58 }
59
60 $schedules['docketcache_gc_schedule'] = [
61 'interval' => 5 * MINUTE_IN_SECONDS,
62 'display' => esc_html__('Every 5 Minutes', 'docket-cache'),
63 ];
64
65 $schedules['docketcache_checkversion_schedule'] = [
66 'interval' => 15 * DAY_IN_SECONDS,
67 'display' => esc_html__('Every 15 Days', 'docket-cache'),
68 ];
69
70 return $schedules;
71 },
72 \PHP_INT_MAX
73 );
74
75 add_action(
76 'plugins_loaded',
77 function () {
78 // 19092020: standardize. rename hooks.
79 // 19012023: remove docketcache_watchproc.
80 foreach (['docket_cache_gc', 'docket_cache_optimizedb', 'docket_cache_monitor', 'docketcache_watchproc'] as $hx) {
81 if (false !== wp_get_scheduled_event($hx)) {
82 wp_clear_scheduled_hook($hx);
83 }
84 }
85
86 // garbage collector
87 // 27012023: added disable constant
88 if ($this->pt->cf()->is_dcfalse('GCRON_DISABLED')) {
89 add_action('docketcache_gc', [$this, 'garbage_collector']);
90 if (!wp_next_scheduled('docketcache_gc')) {
91 wp_schedule_event(time(), 'docketcache_gc_schedule', 'docketcache_gc');
92 }
93 } else {
94 if (wp_get_schedule('docketcache_gc')) {
95 wp_clear_scheduled_hook('docketcache_gc');
96 }
97 }
98
99 // optimize db
100 $cronoptmzdb = $this->pt->cf()->dcvalue('CRONOPTMZDB');
101 if (!empty($cronoptmzdb) && 'never' !== $cronoptmzdb && is_main_site()) {
102 $recurrence = '';
103 switch ($cronoptmzdb) {
104 case 'daily':
105 $recurrence = 'daily';
106 break;
107 case 'weekly':
108 $recurrence = 'weekly';
109 break;
110 case 'monthly':
111 $recurrence = 'monthly';
112 break;
113 }
114
115 if (empty($recurrence)) {
116 wp_clear_scheduled_hook('docketcache_optimizedb');
117 } else {
118 $this->is_optimizedb = true;
119 add_action('docketcache_optimizedb', [$this, 'optimizedb']);
120
121 if (!wp_next_scheduled('docketcache_optimizedb')) {
122 wp_schedule_event(time(), $recurrence, 'docketcache_optimizedb');
123 }
124 }
125 } else {
126 if (wp_get_schedule('docketcache_optimizedb')) {
127 wp_clear_scheduled_hook('docketcache_optimizedb');
128 }
129 }
130
131 // check version
132 if ($this->pt->cf()->is_dctrue('CHECKVERSION', true)) {
133 // 06102020: reset old schedule
134 $check = wp_get_scheduled_event('docketcache_checkversion');
135 if (\is_object($check) && 'docketcache_checkversion_schedule' !== $check->schedule) {
136 wp_clear_scheduled_hook('docketcache_checkversion');
137 }
138
139 if (is_main_site() && is_main_network()) {
140 add_action('docketcache_checkversion', [$this, 'checkversion']);
141 if (!wp_next_scheduled('docketcache_checkversion')) {
142 wp_schedule_event(time(), 'docketcache_checkversion_schedule', 'docketcache_checkversion');
143 }
144 }
145 } else {
146 if (wp_get_schedule('docketcache_checkversion')) {
147 wp_clear_scheduled_hook('docketcache_checkversion');
148 }
149 }
150
151 // expired transient in DB
152 if (has_action('delete_expired_transients') && wp_using_ext_object_cache()) {
153 add_action('delete_expired_transients', [$this, 'delete_expired_transients_db']);
154 }
155 }
156 );
157 }
158
159 /**
160 * unregister.
161 */
162 public function unregister()
163 {
164 foreach (['docketcache_gc', 'docketcache_optimizedb', 'docketcache_watchproc', 'docketcache_checkversion'] as $hx) {
165 wp_clear_scheduled_hook($hx);
166 }
167 }
168
169 /**
170 * reset.
171 */
172 public function reset()
173 {
174 $this->unregister();
175 $this->register();
176 }
177
178 /**
179 * garbage_collector.
180 */
181 public function garbage_collector($force = false)
182 {
183 static $is_done = false;
184
185 $maxfile_default = (int) $this->pt->get_cache_maxfile();
186 $maxfile = $maxfile_default;
187
188 if ($maxfile_default > 10000) {
189 $maxfile = $maxfile_default - 1000;
190 }
191
192 $maxfile_precache_default = (int) $this->pt->get_precache_maxfile();
193 $maxfile_precache = $maxfile_precache_default;
194
195 if ($maxfile_precache_default > 10000) {
196 $maxfile_precache = $maxfile_precache_default - 1000;
197 }
198
199 $maxttl_default = (int) $this->pt->get_cache_maxttl();
200 $maxttl = $maxttl_default;
201 if (!empty($maxttl)) {
202 $maxttl = time() - $maxttl;
203 }
204
205 $chkmaxdisk = false;
206 $maxsizedisk_default = (int) $this->pt->get_cache_maxsize_disk();
207 $maxsizedisk = $maxsizedisk_default;
208 if (!empty($maxsizedisk)) {
209 $maxsizedisk = $maxsizedisk - 1048576;
210
211 if ($maxsizedisk > 1048576) {
212 $chkmaxdisk = true;
213 }
214 }
215
216 $collect = (object) [
217 'is_locked' => false,
218 'cache_maxttl' => $maxttl_default,
219 'cache_maxfile' => $maxfile_default,
220 'cache_maxdisk' => $maxsizedisk_default,
221 'cleanup_maxfile' => 0,
222 'cleanup_precache_maxfile' => 0,
223 'cleanup_maxttl' => 0,
224 'cleanup_expire' => 0,
225 'cleanup_maxdisk' => 0,
226 'cache_file' => 0,
227 'cache_cleanup' => 0,
228 'cache_ignore' => 0,
229 'cleanup_failed' => 0,
230 'cleanup_stalecache' => 0,
231 ];
232
233 clearstatcache();
234 if (!$this->pt->is_docketcachedir($this->pt->cache_path) || @is_file(DOCKET_CACHE_CONTENT_PATH.'/.object-cache-flush.txt')) {
235 $collect->is_locked = true;
236
237 return $collect;
238 }
239
240 // try to set max execution time to 3 minutes if not 0 or lower than 180 seconds.
241 $max_execution_time = $this->pt->get_max_execution_time(180);
242
243 // lock process.
244 $lock_expiry = $max_execution_time > 0 ? $max_execution_time : 180;
245 $lock_expiry = time() + $lock_expiry;
246 if ($is_done || $this->pt->co()->lockproc('garbage_collector', $lock_expiry)) {
247 $collect->is_locked = true;
248
249 return $collect;
250 }
251
252 // Stalecache
253 $is_flush_stalecache = $this->pt->cf()->is_dctrue('FLUSH_STALECACHE', true);
254 $is_ignore_stalecache = $this->pt->cf()->is_dctrue('STALECACHE_IGNORE', true);
255
256 $wp_cache_last_changed = [];
257 $wp_cache_last_changed_match = [
258 'posts' => 'wp_query',
259 'terms' => 'get_terms',
260 'comment' => 'get_comments',
261 'sites' => 'get_sites',
262 'networks' => 'get_network_ids',
263 ];
264 foreach ($wp_cache_last_changed_match as $grp => $kk) {
265 $wp_cache_last_changed[$grp] = wp_cache_get_last_changed($grp);
266 // wp >= 6.3
267 // remove ending 's' -> posts = post-queries.
268 $grpq = strtok($grp, 's').'-queries';
269 $wp_cache_last_changed[$grpq] = $wp_cache_last_changed[$grp];
270 }
271
272 $wp_cache_last_changed['advpost'] = wp_cache_get('cache_incr', 'docketcache-post');
273 $wc_has_cache_helper = method_exists('WC_Cache_Helper', 'get_cache_prefix');
274 $wc_session_cache_group = \defined('WC_SESSION_CACHE_GROUP') ? WC_SESSION_CACHE_GROUP : 'wc_session_id';
275
276 $delay = $force ? 650 : 5000;
277 if ('cli' === \PHP_SAPI) {
278 $delay = 100;
279 }
280
281 // hold cache write
282 $this->pt->suspend_cache_write(true);
283
284 $filesize_total = 0;
285 $file_cache_count = 0;
286 $file_precache_count = 0;
287 $bytes_total = 0;
288 $slowdown = 0;
289
290 $gcisrun_lock = $this->pt->cache_path.'/.gc-is-run.txt';
291 $this->pt->touch($gcisrun_lock);
292
293 foreach ($this->pt->scanfiles($this->pt->cache_path) as $object) {
294 if ($max_execution_time > 0 && (microtime(true) - $this->wp_start_timestamp) > $max_execution_time) {
295 break;
296 }
297
298 if ($slowdown > 10) {
299 $slowdown = 0;
300 usleep($delay);
301 }
302
303 ++$slowdown;
304
305 try {
306 if (!$object->isFile()) {
307 ++$collect->cache_ignore;
308 continue;
309 }
310
311 $fx = $object->getPathName();
312 $fn = $object->getFileName();
313 $fs = $object->getSize();
314 $fm = time() + 300;
315 $ft = filemtime($fx);
316
317 $this->pt->remove_non_chunk_cache($this->pt->cache_path, $fx);
318 } catch (\Throwable $e) {
319 nwdcx_throwable(__METHOD__, $e);
320 continue;
321 }
322
323 nwdcx_cliverbose('run-gc: '.$fx."\n");
324
325 if ($fm >= $ft && (0 === $fs || 'dump_' === substr($fn, 0, 5))) {
326 $this->pt->unlink($fx, true);
327
328 if ($force && @is_file($fx)) {
329 ++$collect->cleanup_failed;
330 }
331 continue;
332 }
333
334 // 03022023: timeout 0 was set to maxtll, see WP_Object_Cache::maybe_expire
335 // cleanup first to reduce memory usage
336 if ($maxttl > 0 && $maxttl > $ft) {
337 $this->pt->unlink($fx, true);
338
339 if ($force && @is_file($fx)) {
340 ++$collect->cleanup_failed;
341 }
342
343 ++$collect->cleanup_maxttl;
344 continue;
345 }
346
347 // 032e9f2c5b60- = docketcache-precache-
348 if ($maxfile_precache > 0 && '032e9f2c5b60-' === substr($fn, 0, 13)) {
349 ++$file_precache_count;
350
351 if ($file_precache_count > $maxfile_precache) {
352 $this->pt->unlink($fx, true);
353
354 if ($force && @is_file($fx)) {
355 ++$collect->cleanup_failed;
356 }
357
358 ++$collect->cleanup_precache_maxfile;
359 continue;
360 }
361 }
362
363 if ($file_cache_count >= $maxfile) {
364 $this->pt->unlink($fx, true);
365
366 if ($force && @is_file($fx)) {
367 ++$collect->cleanup_failed;
368 }
369
370 ++$collect->cleanup_maxfile;
371 continue;
372 }
373
374 if ($chkmaxdisk && $filesize_total > $maxsizedisk) {
375 $this->pt->unlink($fx, true);
376
377 if ($force && @is_file($fx)) {
378 ++$collect->cleanup_failed;
379 }
380
381 ++$collect->cleanup_maxdisk;
382 continue;
383 }
384
385 $data = $this->pt->cache_get($fx);
386 $is_timeout = false;
387 if (false !== $data) {
388 unset($data['data']);
389
390 $is_timeout = !empty($data['timeout']) && $this->pt->valid_timestamp($data['timeout']) ? true : false;
391 if ($is_timeout) {
392 if ($fm >= (int) $data['timeout']) {
393 $this->pt->unlink($fx, true);
394
395 if ($force && @is_file($fx)) {
396 ++$collect->cleanup_failed;
397 }
398
399 unset($data);
400 ++$collect->cleanup_expire;
401 continue;
402 }
403 } else {
404 if (!empty($data['timestamp']) && $this->pt->valid_timestamp($data['timestamp']) && $maxttl > $data['timestamp']) {
405 $this->pt->unlink($fx, true);
406
407 if ($force && @is_file($fx)) {
408 ++$collect->cleanup_failed;
409 }
410
411 unset($data);
412 ++$collect->cleanup_maxttl;
413 continue;
414 }
415 }
416
417 if ($is_flush_stalecache) {
418 // wp stale cache
419 // wp >= 6.3
420 if ($is_ignore_stalecache && $this->pt->is_wp_cache_group_queries($data['group'])) {
421 if (@unlink($fx)) {
422 clearstatcache(true, $fx);
423
424 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
425
426 ++$collect->cleanup_stalecache;
427 continue;
428 }
429 }
430
431 // wp stale cache
432 // prefix:hash:timestamp timestamp
433 if (!empty($wp_cache_last_changed_match[$data['group']]) && preg_match('@^(wp_query|get_terms|get_comments|comment_feed|get_sites|get_network_ids|get_page_by_path|adjacent_post|wp_get_archives):([0-9a-f]{32}):([0-9\. ]{21})([0-9\. ]+)?$@', $data['key'], $mm)) {
434 // main type
435 switch ($mm[1]) {
436 case 'get_page_by_path':
437 case 'adjacent_post':
438 $mm[1] = 'wp_query';
439 break;
440 case 'comment_feed':
441 $mm[1] = 'get_comments';
442 break;
443 }
444
445 $km = $wp_cache_last_changed_match[$data['group']];
446
447 if (($km === $mm[1] && $wp_cache_last_changed[$data['group']] !== $mm[3]) || $is_ignore_stalecache) {
448 if (@unlink($fx)) {
449 clearstatcache(true, $fx);
450
451 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
452
453 ++$collect->cleanup_stalecache;
454 continue;
455 }
456 }
457 }
458
459 // wp stale cache
460 // get_comment_child_ids:int:hash:timestamp timestamp
461 // get_comment_child_ids:1654:5247020d1a40e3b2e9a40de1139bc5c9:0.48761900 1678553206
462 if (!empty($wp_cache_last_changed_match[$data['group']]) && preg_match('@^(get_comment_child_ids):(\d+):([0-9a-f]{32}):([0-9\. ]{21})([0-9\. ]+)?$@', $data['key'], $mm)) {
463 $mm[1] = 'get_comments';
464 $km = $wp_cache_last_changed_match[$data['group']];
465
466 if (($km === $mm[1] && $wp_cache_last_changed[$data['group']] !== $mm[4]) || $is_ignore_stalecache) {
467 if (@unlink($fx)) {
468 clearstatcache(true, $fx);
469
470 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
471
472 ++$collect->cleanup_stalecache;
473 continue;
474 }
475 }
476 }
477
478 // advpost stale cache
479 if (false !== strpos($data['group'], 'docketcache-post-') && preg_match('@^docketcache-post-(\d+)$@', $data['group'], $mm)) {
480 if ((int) $wp_cache_last_changed['advpost'] !== (int) $mm[1] || $is_ignore_stalecache) {
481 if (@unlink($fx)) {
482 clearstatcache(true, $fx);
483
484 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
485
486 ++$collect->cleanup_stalecache;
487 continue;
488 }
489 }
490 }
491
492 // wc stale cache
493 if (false !== strpos($data['key'], 'wc_cache_') && preg_match('@^(wc_cache_[0-9\. ]+_)@', $data['key'], $mm)) {
494 if (!$wc_has_cache_helper || $is_ignore_stalecache) {
495 if (@unlink($fx)) {
496 clearstatcache(true, $fx);
497
498 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
499
500 ++$collect->cleanup_stalecache;
501 }
502 continue;
503 }
504
505 $current_prefix = $mm[1];
506 static $cache_prefix_cached = [];
507
508 // wc product
509 if ('products' === $data['group'] && preg_match('@.*?_type_(\d+)$@', $data['key'], $nn)) {
510 $grp = 'product_'.$nn[1];
511
512 if (!empty($cache_prefix_cached[$grp])) {
513 $cache_prefix = $cache_prefix_cached;
514 } else {
515 $cache_prefix = \WC_Cache_Helper::get_cache_prefix($grp);
516 $cache_prefix_cached[$grp] = $cache_prefix;
517 }
518
519 if ($cache_prefix !== $current_prefix) {
520 if (@unlink($fx)) {
521 clearstatcache(true, $fx);
522
523 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
524
525 ++$collect->cleanup_stalecache;
526 continue;
527 }
528 }
529 }
530
531 if (\in_array($data['group'],
532 [
533 'products', 'coupons', 'orders', 'webhooks', 'taxes', 'shipping_zones',
534 'woocommerce-attributes', 'store_api_rate_limit', $wc_session_cache_group,
535 ])) {
536 $grp = $data['group'];
537
538 if (!empty($cache_prefix_cached[$grp])) {
539 $cache_prefix = $cache_prefix_cached;
540 } else {
541 $cache_prefix = \WC_Cache_Helper::get_cache_prefix($grp);
542 $cache_prefix_cached[$grp] = $cache_prefix;
543 }
544
545 if ($cache_prefix !== $current_prefix) {
546 if (@unlink($fx)) {
547 clearstatcache(true, $fx);
548
549 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
550
551 ++$collect->cleanup_stalecache;
552 continue;
553 }
554 }
555 }
556
557 if ('wc_rate_limit' === $data['group'] && 'rate_limit' === substr($data['key'], 0, 10)) {
558 $grp = $data['group'];
559
560 if (!empty($cache_prefix_cached[$grp])) {
561 $cache_prefix = $cache_prefix_cached;
562 } else {
563 $cache_prefix = \WC_Cache_Helper::get_cache_prefix($grp);
564 $cache_prefix_cached[$grp] = $cache_prefix;
565 }
566
567 if ($cache_prefix !== $current_prefix) {
568 if (@unlink($fx)) {
569 clearstatcache(true, $fx);
570
571 nwdcx_cliverbose('run-gc:stale-cache: '.$fx."\n");
572
573 ++$collect->cleanup_stalecache;
574 continue;
575 }
576 }
577 }
578 }
579 }
580 $bytes_total += \strlen(serialize($data));
581 } // data
582
583 // no timeout data or 0
584 // 03022023: timeout 0 was set to maxtll, see WP_Object_Cache::maybe_expire
585 /*if (false === $is_timeout && $maxttl > 0 && $maxttl > $ft) {
586 $this->pt->unlink($fx, true);
587
588 if ($force && @is_file($fx)) {
589 ++$collect->cleanup_failed;
590 }
591
592 ++$collect->cleanup_maxttl;
593 continue;
594 }*/
595
596 unset($data);
597
598 $filesize_total += $fs;
599 ++$file_cache_count;
600 } // foreach1
601
602 @unlink($gcisrun_lock);
603
604 $collect->cache_file = $file_cache_count;
605
606 $collect->cache_cleanup = $collect->cleanup_maxttl + $collect->cleanup_expire + $collect->cleanup_maxfile + $collect->cleanup_maxdisk + $collect->cleanup_precache_maxfile + $collect->cleanup_stalecache;
607
608 // release
609 $this->pt->suspend_cache_write(false);
610
611 if ($this->pt->cf()->is_dcfalse('TRANSIENTDB') && \function_exists('nwdcx_cleanuptransient')) {
612 nwdcx_cliverbose("run-gc: cleanup expired transients in DB\n");
613 nwdcx_cleanuptransient();
614 }
615
616 // reset gc
617 $count_file = $collect->cache_file;
618 $count_file = $count_file < 0 ? 0 : $count_file;
619 wp_cache_set('count_file', $count_file, 'docketcache-gc', 86400);
620
621 // reset precache
622 $count_file = $file_precache_count - $collect->cleanup_precache_maxfile;
623 $count_file = $count_file < 0 ? 0 : $count_file;
624 wp_cache_set('count_file', $count_file, 'docketcache-precache-gc', 86400);
625
626 // stats
627 $this->pt->co()->save_part([
628 'timestamp' => time(),
629 'size' => $bytes_total,
630 'filesize' => $filesize_total,
631 'files' => $collect->cache_file,
632 ], 'cachestats');
633
634 // done
635 $this->pt->co()->lockreset('garbage_collector');
636 $this->pt->cx()->delay_expire();
637 $is_done = true;
638
639 return $collect;
640 }
641
642 /**
643 * optimizedb.
644 */
645 public function optimizedb()
646 {
647 if (!nwdcx_wpdb($wpdb)) {
648 return false;
649 }
650
651 if ($this->pt->co()->lockproc('optimizedb', time() + 3600)) {
652 return false;
653 }
654
655 $suppress = $wpdb->suppress_errors(true);
656
657 @set_time_limit(300);
658 $max_execution_time = $this->pt->get_max_execution_time();
659 $this->delete_expired_transients_db();
660
661 if (is_main_site() && is_main_network()) {
662 $dbname = $wpdb->dbname;
663 $tables = $wpdb->get_results('SHOW TABLES FROM '.$dbname, ARRAY_A);
664 if (!empty($tables) && \is_array($tables)) {
665 foreach ($tables as $table) {
666 $tbl = $table['Tables_in_'.$dbname];
667 $sql = 'OPTIMIZE TABLE `'.$tbl.'`';
668 $ret = $wpdb->query($sql);
669
670 nwdcx_cliverbose(str_replace('`', '', $sql)."\n");
671 if ($max_execution_time > 0 && (microtime(true) - $this->wp_start_timestamp) > $max_execution_time) {
672 break;
673 }
674 }
675 }
676 unset($tables);
677 }
678
679 $wpdb->suppress_errors($suppress);
680
681 $this->pt->co()->lockreset('optimizedb');
682
683 return true;
684 }
685
686 /**
687 * delete_expired_transients_db.
688 */
689 public function delete_expired_transients_db()
690 {
691 if (!nwdcx_wpdb($wpdb)) {
692 return false;
693 }
694
695 if ($this->pt->cf()->is_dcfalse('TRANSIENTDB') && \function_exists('nwdcx_cleanuptransient')) {
696 nwdcx_cleanuptransient();
697 } elseif (\function_exists('delete_expired_transients')) {
698 delete_expired_transients(true);
699 }
700
701 return true;
702 }
703
704 /**
705 * checkversion.
706 */
707 public function checkversion()
708 {
709 if (!is_main_site()) {
710 return false;
711 }
712
713 $part = 'checkversion';
714
715 if ($this->pt->co()->lockproc($part, time() + 3600)) {
716 return false;
717 }
718
719 $checkdata = $this->pt->co()->get_part($part, true);
720 if (!empty($checkdata) && \is_array($checkdata) && !empty($checkdata['selfcheck'])) {
721 $selfcheck = $checkdata['selfcheck'];
722 if (0 === $this->pt->sanitize_timestamp($selfcheck)) {
723 return false;
724 }
725
726 if ($selfcheck > 0 && $selfcheck > time()) {
727 return false;
728 }
729 }
730
731 $main_site_url = $this->pt->site_url();
732 $site_url = $this->pt->site_url(true);
733 $home_url = $this->pt->site_url(true, true);
734 $stmp = time() + 120;
735 $api_endpoint = $this->pt->api_endpoint.'/'.$part.'?v='.$stmp;
736
737 $args = [
738 'blocking' => true,
739 'body' => [
740 'timestamp' => date('Y-m-d H:i:s T'),
741 'timezone' => wp_timezone_string(),
742 'site' => $site_url,
743 'token' => $this->pt->nw_encrypt($main_site_url, md5($site_url)),
744 'meta' => $this->pt->site_meta(),
745 ],
746 'headers' => [
747 'REFERER' => $home_url,
748 'Cache-Control' => 'no-cache',
749 ],
750 ];
751
752 $results = Crawler::post($api_endpoint, $args);
753
754 $output = [
755 'timestamp' => time(),
756 'endpoint' => $api_endpoint,
757 'request' => [
758 'headers' => $args['headers'],
759 'content' => $args['body'],
760 ],
761 'selfcheck' => time() + 86400,
762 ];
763
764 if (is_wp_error($results)) {
765 $output['error'] = $results->get_error_message();
766 $this->pt->co()->save_part($output, $part);
767
768 return false;
769 }
770
771 $output['response'] = wp_remote_retrieve_body($results);
772 if (!empty($output['response'])) {
773 $output['response'] = json_decode($output['response'], true);
774 if (\JSON_ERROR_NONE === json_last_error()) {
775 if (!empty($output['response']['error'])) {
776 $output['error'] = $output['response']['error'];
777 $this->pt->co()->save_part($output, $part);
778
779 return false;
780 }
781 }
782 }
783
784 $code = (int) wp_remote_retrieve_response_code($results);
785 if ($code > 400) {
786 $output['error'] = $code;
787 $this->pt->co()->save_part($output, $part);
788
789 return false;
790 }
791
792 $this->pt->co()->save_part($output, $part);
793 $this->pt->co()->lockreset($part);
794
795 return true;
796 }
797 }
798