PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.3
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.3
1.3.3 1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 All 29 releases
← All changes | includes/class-redis-client.php +47 -1 1.0.51.3.3 View file →
@@ -89,9 +89,23 @@
89 89 }
90 90
91 91 // --- Commands -----------------------------------------------------------
92 92
93 - public function auth( string $password ) {
93 + /**
94 + * Authenticate. With a username (Redis 6+ ACL) emit the two-argument
95 + * `AUTH <user> <pass>`; without one fall back to the legacy
96 + * single-argument `AUTH <pass>` (which authenticates as the built-in
97 + * `default` user). Managed hosts that provision a dedicated ACL user
98 + * and disable `default` reject the one-arg form with WRONGPASS, so the
99 + * username must be threaded through here. (FBS-83118)
100 + *
101 + * @param string $password Redis password.
102 + * @param string $username Optional ACL username; '' = legacy default user.
103 + */
104 + public function auth( string $password, string $username = '' ) {
105 + if ( '' !== $username ) {
106 + return $this->command( array( 'AUTH', $username, $password ) );
107 + }
94 108 return $this->command( array( 'AUTH', $password ) );
95 109 }
96 110
97 111 public function select( int $db ) {
@@ -155,8 +169,40 @@
155 169
156 170 public function flushDB(): bool {
157 171 $r = $this->command( array( 'FLUSHDB' ) );
158 172 return '+OK' === $r || 'OK' === $r;
173 + }
174 +
175 + /**
176 + * Delete every key matching a glob-style pattern, using a non-blocking
177 + * SCAN cursor (never KEYS, which blocks the whole server on large
178 + * datasets). Returns the number of keys deleted. Used for prefix-scoped
179 + * flushes so we only ever touch this site's namespace, never the whole
180 + * Redis DB. (FBS-83119)
181 + *
182 + * @param string $pattern e.g. "salt:*" or "salt:*:options:*".
183 + * @param int $count SCAN COUNT hint (batch size per round trip).
184 + */
185 + public function delete_by_pattern( string $pattern, int $count = 500 ): int {
186 + $deleted = 0;
187 + $cursor = '0';
188 + do {
189 + $reply = $this->command( array( 'SCAN', $cursor, 'MATCH', $pattern, 'COUNT', (string) $count ) );
190 + // Expected: [ next_cursor, [ key, key, ... ] ]. Anything else
191 + // (false on socket error, malformed) ends the loop safely.
192 + if ( ! is_array( $reply ) || count( $reply ) < 2 || ! is_array( $reply[1] ) ) {
193 + break;
194 + }
195 + $cursor = (string) $reply[0];
196 + $keys = $reply[1];
197 + if ( ! empty( $keys ) ) {
198 + // DEL accepts variadic keys — one round trip per batch.
199 + $args = array_merge( array( 'DEL' ), array_map( 'strval', $keys ) );
200 + $n = $this->command( $args );
201 + $deleted += is_int( $n ) ? $n : 0;
202 + }
203 + } while ( '0' !== $cursor );
204 + return $deleted;
159 205 }
160 206
161 207 public function close(): void {
162 208 if ( is_resource( $this->sock ) && ! $this->persistent ) {