PluginProbe
seQura / trunk
seQura vtrunk
4.3.4 4.3.3 4.3.2 4.3.1 trunk 2.0.0 2.0.10 2.0.11 2.0.12 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 3.0.0 3.0.2 3.0.5 3.0.6 3.0.7 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 4.0.0 All 30 releases
sequra / src / Repositories / class-cache-repository.php

class-cache-repository.php in seQura trunk, at src/Repositories/class-cache-repository.php

135 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cache repository implementation.
4 *
5 * @package SeQura/WC
6 * @subpackage SeQura/WC/Repositories
7 */
8
9 namespace SeQura\WC\Repositories;
10
11 /**
12 * Two-level cache: static in-memory array (per-request fast path)
13 * + WordPress object cache (persistent when a backend is configured).
14 *
15 * The static array is checked first to avoid repeated wp_cache_get() calls
16 * (each of which may involve a network round-trip to Redis/Memcached).
17 * On a cache hit from the WordPress object cache, the value is promoted to
18 * the static array for the remainder of the request.
19 */
20 class Cache_Repository implements Interface_Cache_Repository {
21
22 /**
23 * Per-request in-memory cache, keyed by group then by key.
24 *
25 * Public to allow test suites to reset the static state between tests
26 * without requiring Reflection.
27 *
28 * @var array<string, array<string, mixed>>
29 */
30 public static $static_cache = array();
31
32 /**
33 * Get a value from the cache.
34 *
35 * @param string $key Cache key.
36 * @param string $group Cache group.
37 * @param bool $found Whether the key was found in the cache. Passed by reference.
38 *
39 * @return mixed Cached value, or false on miss.
40 */
41 public function get( $key, $group, &$found = false ) {
42 // Level 1: static array — no serialization, no network.
43 if ( \array_key_exists( $group, self::$static_cache )
44 && \array_key_exists( $key, self::$static_cache[ $group ] ) ) {
45 $found = true;
46 return self::$static_cache[ $group ][ $key ];
47 }
48
49 // Level 2: WordPress object cache (persistent if Redis/Memcached configured).
50 $wp_found = false;
51 $value = \wp_cache_get( $key, $group, false, $wp_found );
52 if ( $wp_found ) {
53 // Promote to static cache for the remainder of the request.
54 self::$static_cache[ $group ][ $key ] = $value;
55 $found = true;
56 return $value;
57 }
58
59 $found = false;
60 return false;
61 }
62
63 /**
64 * Set a value in the cache.
65 *
66 * @param string $key Cache key.
67 * @param mixed $value Value to store. Must be serializable.
68 * @param string $group Cache group.
69 * @param int $ttl Time to live in seconds. 0 means no expiration.
70 */
71 public function set( $key, $value, $group, $ttl = 0 ): bool {
72 self::$static_cache[ $group ][ $key ] = $value;
73 //phpcs:ignore WordPressVIPMinimum.Performance.LowExpiryCacheTime.CacheTimeUndetermined
74 return \wp_cache_set( $key, $value, $group, $ttl );
75 }
76
77 /**
78 * Delete a value from the cache.
79 *
80 * @param string $key Cache key.
81 * @param string $group Cache group.
82 */
83 public function delete( $key, $group ): bool {
84 unset( self::$static_cache[ $group ][ $key ] );
85 return \wp_cache_delete( $key, $group );
86 }
87
88 /**
89 * Atomically increment a numeric value in the cache.
90 *
91 * @param string $key Cache key.
92 * @param string $group Cache group.
93 * @param int $ttl TTL used only when the key is first created.
94 *
95 * @return int New value after increment.
96 */
97 public function increment( $key, $group, $ttl = 0 ): int {
98 // wp_cache_incr() is atomic on Redis/Memcached; it returns false if the key does not exist.
99 $new_value = \wp_cache_incr( $key, 1, $group );
100 if ( false === $new_value ) {
101 // Key did not exist; use add() (a no-op if another request created it concurrently)
102 // then retry the atomic incr() to avoid two requests both writing 1.
103 //phpcs:ignore WordPressVIPMinimum.Performance.LowExpiryCacheTime.CacheTimeUndetermined
104 \wp_cache_add( $key, 0, $group, $ttl );
105 $new_value = \wp_cache_incr( $key, 1, $group );
106 if ( false === $new_value ) {
107 // Fallback for backends where incr after add still fails (e.g. default WP array cache without the key).
108 //phpcs:ignore WordPressVIPMinimum.Performance.LowExpiryCacheTime.CacheTimeUndetermined
109 \wp_cache_set( $key, 1, $group, $ttl );
110 $new_value = 1;
111 }
112 }
113 // Keep static cache in sync so subsequent get() calls in this request see the new value.
114 self::$static_cache[ $group ][ $key ] = $new_value;
115 return (int) $new_value;
116 }
117
118 /**
119 * Flush all cached data from both the static in-memory array and the WordPress object cache.
120 *
121 * Uses wp_cache_flush_group() per seQura group when available (WP 6.1+) to avoid flushing
122 * the entire object cache — which would evict entries for other sites in a multisite network.
123 * Falls back to wp_cache_flush() on older WordPress versions.
124 */
125 public function flush(): void {
126 self::$static_cache = array();
127 if ( \function_exists( 'wp_cache_flush_group' ) ) {
128 \wp_cache_flush_group( Repository::TABLE_EXISTS_CACHE_GROUP );
129 \wp_cache_flush_group( Repository::DATA_CACHE_GROUP );
130 } else {
131 \wp_cache_flush();
132 }
133 }
134 }
135