PluginProbe
404 Solution / trunk
404 Solution vtrunk
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / repositories / RedirectRegexCacheStore.php

RedirectRegexCacheStore.php in 404 Solution trunk, at includes/repositories/RedirectRegexCacheStore.php

102 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Per-request state store for regex redirect lookup caching.
9 *
10 * Redirect matching and redirect mutation both need to clear or inspect this
11 * cache, so the state lives in one focused owner instead of on the broad
12 * RedirectsRepository facade.
13 */
14 class ABJ_404_Solution_RedirectRegexCacheStore {
15
16 /** Maximum number of regex redirects to cache per request. */
17 const MAX_COUNT = 50;
18
19 /** @var array<int, array<string, mixed>>|null */
20 private static $regexRedirectsCache = null;
21
22 /** @var bool */
23 private static $regexCacheDisabled = false;
24
25 /**
26 * Blog id the cache above (or the disabled flag) was populated for. This
27 * is a CLASS-STATIC cache -- shared by every RedirectsBulkReader /
28 * RedirectsRepository instance in the process, not just one object --
29 * memoizing rows read from the per-blog {wp_prefix}_abj404_redirects
30 * table. The underlying query is correctly blog-scoped ($wpdb->prefix
31 * follows switch_to_blog()), but without this guard the cache sitting in
32 * front of it is not: a multisite process that switches blogs mid-request
33 * (a WP-CLI network-wide script looping get_sites()/switch_to_blog(), or
34 * an Action Scheduler worker draining queued cross-site actions
35 * sequentially) would resolve blog A's regex redirects once, cache them
36 * process-wide, then silently keep serving blog A's rows to blog B (and
37 * every blog after it) for the rest of the process. Every real caller of
38 * getRedirectsWithRegEx() (WPCLIRedirectCommandService, RestApiReadService,
39 * ViewReadService) inherits this guard automatically since they never
40 * touch the cache fields directly.
41 *
42 * @var int|null
43 */
44 private static $regexRedirectsCacheBlogId = null;
45
46 public function clear(): void {
47 self::clearStatic();
48 }
49
50 public static function clearStatic(): void {
51 self::$regexRedirectsCache = null;
52 self::$regexCacheDisabled = false;
53 self::$regexRedirectsCacheBlogId = null;
54 }
55
56 /** @return array<int, array<string, mixed>>|null */
57 public static function getRegexRedirectsCache() {
58 self::invalidateIfBlogChanged();
59 return self::$regexRedirectsCache;
60 }
61
62 /** @param array<int, array<string, mixed>>|null $cache */
63 public static function setRegexRedirectsCache($cache): void {
64 self::$regexRedirectsCache = $cache;
65 self::$regexRedirectsCacheBlogId = self::currentBlogId();
66 }
67
68 public static function isRegexCacheDisabled(): bool {
69 self::invalidateIfBlogChanged();
70 return self::$regexCacheDisabled;
71 }
72
73 public static function setRegexCacheDisabled(bool $disabled): void {
74 self::$regexCacheDisabled = $disabled;
75 self::$regexRedirectsCacheBlogId = self::currentBlogId();
76 }
77
78 /**
79 * Drop the cache (and the disabled flag) if the active WordPress blog
80 * has changed since the cache was populated. A no-op when nothing has
81 * been cached yet, so an uninitialized cache never records a blog id.
82 *
83 * @return void
84 */
85 private static function invalidateIfBlogChanged(): void {
86 if (self::$regexRedirectsCache === null && self::$regexCacheDisabled === false) {
87 return;
88 }
89
90 if (self::$regexRedirectsCacheBlogId !== self::currentBlogId()) {
91 self::$regexRedirectsCache = null;
92 self::$regexCacheDisabled = false;
93 self::$regexRedirectsCacheBlogId = null;
94 }
95 }
96
97 /** @return int */
98 private static function currentBlogId(): int {
99 return function_exists('get_current_blog_id') ? (int)get_current_blog_id() : 0;
100 }
101 }
102