22
33namespace Salient \Cache ;
44
5- use Salient \Contract \Cache \CacheStoreInterface ;
5+ use Salient \Contract \Cache \CacheInterface ;
66use Salient \Core \AbstractStore ;
77use DateInterval ;
88use DateTimeImmutable ;
99use DateTimeInterface ;
1010use LogicException ;
1111use SQLite3Result ;
12+ use SQLite3Stmt ;
1213
1314/**
1415 * A PSR-16 key-value store backed by a SQLite database
1516 *
1617 * @api
1718 */
18- final class CacheStore extends AbstractStore implements CacheStoreInterface
19+ final class CacheStore extends AbstractStore implements CacheInterface
1920{
21+ private ?SQLite3Stmt $ Stmt = null ;
2022 private ?int $ Now = null ;
2123
2224 /**
@@ -103,34 +105,36 @@ public function set($key, $value, $ttl = null): bool
103105 /**
104106 * @phpstan-impure
105107 */
106- public function has ($ key, ? int $ maxAge = null ): bool
108+ public function has ($ key ): bool
107109 {
108110 $ sql = <<<SQL
109111SELECT
110112 COUNT(*)
111113FROM
112114 _cache_item
113115SQL ;
114- $ result = $ this ->queryItems ($ sql , $ key, $ maxAge );
116+ $ result = $ this ->queryItems ($ sql , $ key );
115117 /** @var array{int} */
116118 $ row = $ result ->fetchArray (\SQLITE3_NUM );
119+ $ this ->closeStmt ();
117120
118121 return (bool ) $ row [0 ];
119122 }
120123
121124 /**
122125 * @phpstan-impure
123126 */
124- public function get ($ key , $ default = null , ? int $ maxAge = null )
127+ public function get ($ key , $ default = null )
125128 {
126129 $ sql = <<<SQL
127130SELECT
128131 item_value
129132FROM
130133 _cache_item
131134SQL ;
132- $ result = $ this ->queryItems ($ sql , $ key, $ maxAge );
135+ $ result = $ this ->queryItems ($ sql , $ key );
133136 $ row = $ result ->fetchArray (\SQLITE3_NUM );
137+ $ this ->closeStmt ();
134138
135139 return $ row === false
136140 ? $ default
@@ -140,14 +144,10 @@ public function get($key, $default = null, ?int $maxAge = null)
140144 /**
141145 * @phpstan-impure
142146 */
143- public function getInstanceOf ($ key , string $ class , ?object $ default = null , ? int $ maxAge = null ): ?object
147+ public function getInstanceOf ($ key , string $ class , ?object $ default = null ): ?object
144148 {
145- $ store = $ this ->maybeAsOfNow ();
146- if (!$ store ->has ($ key , $ maxAge )) {
147- return $ default ;
148- }
149- $ item = $ store ->get ($ key , $ default , $ maxAge );
150- if (!is_object ($ item ) || !is_a ($ item , $ class )) {
149+ $ item = $ this ->get ($ key );
150+ if ($ item === null || !is_object ($ item ) || !is_a ($ item , $ class )) {
151151 return $ default ;
152152 }
153153 return $ item ;
@@ -156,14 +156,10 @@ public function getInstanceOf($key, string $class, ?object $default = null, ?int
156156 /**
157157 * @phpstan-impure
158158 */
159- public function getArray ($ key , ?array $ default = null , ? int $ maxAge = null ): ?array
159+ public function getArray ($ key , ?array $ default = null ): ?array
160160 {
161- $ store = $ this ->maybeAsOfNow ();
162- if (!$ store ->has ($ key , $ maxAge )) {
163- return $ default ;
164- }
165- $ item = $ store ->get ($ key , $ default , $ maxAge );
166- if (!is_array ($ item )) {
161+ $ item = $ this ->get ($ key );
162+ if ($ item === null || !is_array ($ item )) {
167163 return $ default ;
168164 }
169165 return $ item ;
@@ -172,14 +168,10 @@ public function getArray($key, ?array $default = null, ?int $maxAge = null): ?ar
172168 /**
173169 * @phpstan-impure
174170 */
175- public function getInt ($ key , ?int $ default = null , ? int $ maxAge = null ): ?int
171+ public function getInt ($ key , ?int $ default = null ): ?int
176172 {
177- $ store = $ this ->maybeAsOfNow ();
178- if (!$ store ->has ($ key , $ maxAge )) {
179- return $ default ;
180- }
181- $ item = $ store ->get ($ key , $ default , $ maxAge );
182- if (!is_int ($ item )) {
173+ $ item = $ this ->get ($ key );
174+ if ($ item === null || !is_int ($ item )) {
183175 return $ default ;
184176 }
185177 return $ item ;
@@ -188,14 +180,10 @@ public function getInt($key, ?int $default = null, ?int $maxAge = null): ?int
188180 /**
189181 * @phpstan-impure
190182 */
191- public function getString ($ key , ?string $ default = null , ? int $ maxAge = null ): ?string
183+ public function getString ($ key , ?string $ default = null ): ?string
192184 {
193- $ store = $ this ->maybeAsOfNow ();
194- if (!$ store ->has ($ key , $ maxAge )) {
195- return $ default ;
196- }
197- $ item = $ store ->get ($ key , $ default , $ maxAge );
198- if (!is_string ($ item )) {
185+ $ item = $ this ->get ($ key );
186+ if ($ item === null || !is_string ($ item )) {
199187 return $ default ;
200188 }
201189 return $ item ;
@@ -256,10 +244,10 @@ public function clearExpired(): bool
256244 /**
257245 * @inheritDoc
258246 */
259- public function getMultiple ($ keys , $ default = null , ? int $ maxAge = null )
247+ public function getMultiple ($ keys , $ default = null )
260248 {
261249 foreach ($ keys as $ key ) {
262- $ values [$ key ] = $ this ->get ($ key , $ default, $ maxAge );
250+ $ values [$ key ] = $ this ->get ($ key , $ default );
263251 }
264252 return $ values ?? [];
265253 }
@@ -289,44 +277,46 @@ public function deleteMultiple($keys): bool
289277 /**
290278 * @phpstan-impure
291279 */
292- public function getItemCount (? int $ maxAge = null ): int
280+ public function getItemCount (): int
293281 {
294282 $ sql = <<<SQL
295283SELECT
296284 COUNT(*)
297285FROM
298286 _cache_item
299287SQL ;
300- $ result = $ this ->queryItems ($ sql, null , $ maxAge );
288+ $ result = $ this ->queryItems ($ sql );
301289 /** @var array{int} */
302290 $ row = $ result ->fetchArray (\SQLITE3_NUM );
291+ $ this ->closeStmt ();
303292
304293 return $ row [0 ];
305294 }
306295
307296 /**
308297 * @phpstan-impure
309298 */
310- public function getAllKeys (? int $ maxAge = null ): array
299+ public function getItemKeys ( ): array
311300 {
312301 $ sql = <<<SQL
313302SELECT
314303 item_key
315304FROM
316305 _cache_item
317306SQL ;
318- $ result = $ this ->queryItems ($ sql, null , $ maxAge );
307+ $ result = $ this ->queryItems ($ sql );
319308 while (($ row = $ result ->fetchArray (\SQLITE3_NUM )) !== false ) {
320309 $ keys [] = $ row [0 ];
321310 }
311+ $ this ->closeStmt ();
322312
323313 return $ keys ?? [];
324314 }
325315
326316 /**
327317 * @inheritDoc
328318 */
329- public function asOfNow (?int $ now = null ): CacheStoreInterface
319+ public function asOfNow (?int $ now = null ): CacheInterface
330320 {
331321 if ($ this ->Now !== null ) {
332322 throw new LogicException (
@@ -378,49 +368,34 @@ private function now(): int
378368 return $ this ->Now ?? time ();
379369 }
380370
381- /**
382- * @return static
383- */
384- private function maybeAsOfNow (): self
371+ private function queryItems (string $ sql , ?string $ key = null ): SQLite3Result
385372 {
386- return $ this ->Now === null
387- ? $ this ->asOfNow ()
388- : $ this ;
389- }
390-
391- private function queryItems (string $ sql , ?string $ key , ?int $ maxAge ): SQLite3Result
392- {
393- $ where = [];
394- $ bind = [];
395-
396373 if ($ key !== null ) {
397374 $ where [] = 'item_key = :item_key ' ;
398375 $ bind [] = [':item_key ' , $ key , \SQLITE3_TEXT ];
399376 }
400377
401- $ bindNow = false ;
402- if ($ maxAge === null ) {
403- $ where [] = "(expires_at IS NULL OR expires_at > DATETIME(:now, 'unixepoch')) " ;
404- $ bindNow = true ;
405- } elseif ($ maxAge ) {
406- $ where [] = "DATETIME(set_at, :max_age) > DATETIME(:now, 'unixepoch') " ;
407- $ bind [] = [':max_age ' , "+ $ maxAge seconds " , \SQLITE3_TEXT ];
408- $ bindNow = true ;
409- }
410- if ($ bindNow ) {
411- $ bind [] = [':now ' , $ this ->now (), \SQLITE3_INTEGER ];
412- }
378+ $ where [] = "(expires_at IS NULL OR expires_at > DATETIME(:now, 'unixepoch')) " ;
379+ $ bind [] = [':now ' , $ this ->now (), \SQLITE3_INTEGER ];
413380
414381 $ where = implode (' AND ' , $ where );
415- if ($ where !== '' ) {
416- $ sql .= " WHERE $ where " ;
417- }
382+ $ sql .= " WHERE $ where " ;
418383
419384 $ stmt = $ this ->prepare ($ sql );
420385 foreach ($ bind as [$ param , $ value , $ type ]) {
421386 $ stmt ->bindValue ($ param , $ value , $ type );
422387 }
423388
424- return $ this ->execute ($ stmt );
389+ $ result = $ this ->execute ($ stmt );
390+ $ this ->Stmt = $ stmt ;
391+ return $ result ;
392+ }
393+
394+ private function closeStmt (): void
395+ {
396+ if ($ this ->Stmt !== null ) {
397+ $ this ->Stmt ->close ();
398+ $ this ->Stmt = null ;
399+ }
425400 }
426401}
0 commit comments