22
33namespace ByJG \Cache \Psr16 ;
44
5+ use ByJG \Cache \AtomicOperationInterface ;
56use ByJG \Cache \GarbageCollectorInterface ;
7+ use Closure ;
68use DateInterval ;
79use Exception ;
810use Psr \Container \ContainerExceptionInterface ;
911use Psr \Container \NotFoundExceptionInterface ;
1012use Psr \Log \LoggerInterface ;
1113use Psr \Log \NullLogger ;
1214
13- class FileSystemCacheEngine extends BaseCacheEngine implements GarbageCollectorInterface
15+ class FileSystemCacheEngine extends BaseCacheEngine implements GarbageCollectorInterface, AtomicOperationInterface
1416{
1517
1618 protected ?LoggerInterface $ logger = null ;
@@ -75,21 +77,10 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null
7577 $ this ->logger ->info ("[Filesystem cache] Set ' $ key' in FileSystem " );
7678
7779 try {
78- if (file_exists ($ fileKey )) {
79- unlink ($ fileKey );
80- }
81- if (file_exists ("$ fileKey.ttl " )) {
82- unlink ("$ fileKey.ttl " );
83- }
84-
85- if (is_null ($ value )) {
86- return false ;
87- }
88-
8980 if (is_string ($ value ) && (strlen ($ value ) === 0 )) {
9081 touch ($ fileKey );
9182 } else {
92- $ this ->putContents ($ fileKey , $ value , $ this ->addToNow ($ ttl ));
83+ return $ this ->putContents ($ fileKey , $ value , $ this ->addToNow ($ ttl ));
9384 }
9485 } catch (Exception $ ex ) {
9586 $ this ->logger ->warning ("[Filesystem cache] I could not write to cache on file ' " . basename ($ key ) . "'. Switching to nocache=true mode. " );
@@ -208,12 +199,34 @@ protected function getContents(string $fileKey, mixed $default = null): mixed
208199 return $ content ;
209200 }
210201
211- protected function putContents (string $ fileKey , mixed $ value , ?string $ ttl ): void
202+ protected function putContents (string $ fileKey , mixed $ value , ?int $ ttl, ? Closure $ operation = null ): mixed
212203 {
213- $ fo = fopen ($ fileKey , 'w ' );
204+ $ returnValue = true ;
205+
206+ if (file_exists ("$ fileKey.ttl " )) {
207+ unlink ("$ fileKey.ttl " );
208+ }
209+
210+ if (is_null ($ value )) {
211+ if (file_exists ($ fileKey )) {
212+ unlink ($ fileKey );
213+ }
214+ return false ;
215+ }
216+
217+ $ fo = fopen ($ fileKey , 'a+ ' );
214218 $ waitIfLocked = 1 ;
215219 $ lock = flock ($ fo , LOCK_EX , $ waitIfLocked );
216220 try {
221+ if (!is_null ($ operation )) {
222+ if (!file_exists ($ fileKey )) {
223+ $ currentValue = 0 ;
224+ } else {
225+ $ content = file_get_contents ($ fileKey );
226+ $ currentValue = !empty ($ content ) ? unserialize ($ content ) : $ content ;
227+ }
228+ $ value = $ returnValue = $ operation ($ currentValue , $ value );
229+ }
217230 file_put_contents ($ fileKey , serialize ($ value ));
218231 if (!is_null ($ ttl )) {
219232 file_put_contents ("$ fileKey.ttl " , serialize ($ ttl ));
@@ -222,6 +235,8 @@ protected function putContents(string $fileKey, mixed $value, ?string $ttl): voi
222235 flock ($ fo , LOCK_UN );
223236 fclose ($ fo );
224237 }
238+
239+ return $ returnValue ;
225240 }
226241
227242 public function collectGarbage ()
@@ -250,4 +265,32 @@ public function getTtl(string $key): ?int
250265 }
251266 return null ;
252267 }
268+
269+ public function increment (string $ key , int $ value = 1 , DateInterval |int |null $ ttl = null ): int
270+ {
271+ return $ this ->putContents ($ this ->fixKey ($ key ), $ value , $ ttl , function ($ currentValue , $ value ) {
272+ return intval ($ currentValue ) + $ value ;
273+ });
274+ }
275+
276+ public function decrement (string $ key , int $ value = 1 , DateInterval |int |null $ ttl = null ): int
277+ {
278+ return $ this ->putContents ($ this ->fixKey ($ key ), $ value , $ ttl , function ($ currentValue , $ value ) {
279+ return intval ($ currentValue ) - $ value ;
280+ });
281+ }
282+
283+ public function add (string $ key , $ value , DateInterval |int |null $ ttl = null ): array
284+ {
285+ return $ this ->putContents ($ this ->fixKey ($ key ), $ value , $ ttl , function ($ currentValue , $ value ) {
286+ if (empty ($ currentValue )) {
287+ return [$ value ];
288+ }
289+ if (!is_array ($ currentValue )) {
290+ return [$ currentValue , $ value ];
291+ }
292+ $ currentValue [] = $ value ;
293+ return $ currentValue ;
294+ });
295+ }
253296}
0 commit comments