From 48724ce47a2d36cfe032b0756c754d14faea8bcb Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 07:32:19 -0500 Subject: [PATCH 01/11] "Add #[Override] annotation and update compatibility and docs Include #[Override] attributes in methods for better code clarity and compliance, and update PHPUnit configurations and tests for PHP 8.4 support. Enhance documentation, streamline compatibility with newer versions of dependencies, and improve general code maintainability." --- .github/workflows/phpunit.yml | 3 +- README.md | 115 +++++++++++++--------------- composer.json | 6 +- docs/atomic-operations.md | 4 +- docs/class-redis-cache-engine.md | 6 +- docs/class-tmpfs-cache-engine.md | 6 +- docs/garbage-collection.md | 6 +- phpunit.xml.dist | 17 ++-- src/Factory.php | 2 +- src/Psr16/ArrayCacheEngine.php | 8 ++ src/Psr16/BaseCacheEngine.php | 8 +- src/Psr16/FileSystemCacheEngine.php | 11 +++ src/Psr16/MemcachedEngine.php | 9 +++ src/Psr16/NoCacheEngine.php | 6 ++ src/Psr16/RedisCacheEngine.php | 26 +++---- src/Psr16/SessionCacheEngine.php | 6 ++ src/Psr16/ShmopCacheEngine.php | 6 ++ src/Psr6/CacheItem.php | 6 ++ src/Psr6/CachePool.php | 9 +++ tests/BaseCacheTest.php | 3 +- tests/BasicContainer.php | 2 + 21 files changed, 166 insertions(+), 99 deletions(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 82e2934..b55e670 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -16,6 +16,7 @@ jobs: strategy: matrix: php-version: + - "8.4" - "8.3" - "8.2" - "8.1" @@ -39,8 +40,8 @@ jobs: steps: - uses: actions/checkout@v4 - run: composer install - - run: ./vendor/bin/phpunit --stderr - run: ./vendor/bin/psalm + - run: ./vendor/bin/phpunit Documentation: if: github.ref == 'refs/heads/master' diff --git a/README.md b/README.md index 6610c1a..c334c5f 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,78 @@ -# Cache Engine - [![Build Status](https://github.com/byjg/php-cache-engine/actions/workflows/phpunit.yml/badge.svg?branch=master)](https://github.com/byjg/php-cache-engine/actions/workflows/phpunit.yml) [![Opensource ByJG](https://img.shields.io/badge/opensource-byjg-success.svg)](http://opensource.byjg.com) [![GitHub source](https://img.shields.io/badge/Github-source-informational?logo=github)](https://github.com/byjg/php-cache-engine/) [![GitHub license](https://img.shields.io/github/license/byjg/php-cache-engine.svg)](https://opensource.byjg.com/opensource/licensing.html) [![GitHub release](https://img.shields.io/github/release/byjg/php-cache-engine.svg)](https://github.com/byjg/php-cache-engine/releases/) +# PHP Cache Engine -A multipurpose cache engine PSR-6 and PSR-16 implementation with several drivers. - -## PSR-16 - -PSR-16 defines a Simple Cache interface with less verbosity than PSR-6. Below a list -of engines available in this library that is PSR-16 compliant: - -PSR-16 Getting Started: [here](docs/basic-usage-psr16-simplecache.md) - -## PSR-6 - -The PSR-6 implementation use the engines defined above. PSR-6 is more verbosity and -have an extra layer do get and set the cache values. - -You can use one of the factory methods to create a instance of the CachePool implementation: - -PSR-6 Getting Started: [here](docs/basic-usage-psr6-cachepool.md) - -## List of Cache Engines - -| Class | Description | -|:-------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------| -| [\ByJG\Cache\Psr16\NoCacheEngine](docs/class-no-cache-engine.md) | Do nothing. Use it for disable the cache without change your code | -| [\ByJG\Cache\Psr16\ArrayCacheEngine](docs/class-array-cache-engine.md) | Local cache only using array. It does not persists between requests | -| [\ByJG\AnyDataset\NoSql\Cache\KeyValueCacheEngine](https://github.com/byjg/php-anydataset-nosql) | Use S3-Like or ClouflareKV as a store for the cache (other repository) | -| [\ByJG\Cache\Psr16\FileSystemCacheEngine](docs/class-filesystem-cache-engine.md) | Save the cache result in the local file system | -| [\ByJG\Cache\Psr16\MemcachedEngine](docs/class-memcached-engine.md) | Uses the Memcached as the cache engine | -| [\ByJG\Cache\Psr16\TmpfsCacheEngine](docs/class-tmpfs-cache-engine.md) | Uses the Tmpfs as the cache engine | -| [\ByJG\Cache\Psr16\RedisCachedEngine](docs/class-redis-cache-engine.md) | uses the Redis as cache | -| [\ByJG\Cache\Psr16\SessionCachedEngine](docs/class-session-cache-engine.md) | uses the PHP session as cache | -| [\ByJG\Cache\Psr16\ShmopCacheEngine](docs/class-shmop-cache-engine.md) (deprecated) | uses the shared memory area for cache. Use TmpfsCacheEngine. | - - -## Logging cache commands - -You can add a PSR Log compatible to the constructor in order to get Log of the operations - -See log examples [here](docs/setup-log-handler.md) +A powerful, versatile cache implementation providing both PSR-6 and PSR-16 interfaces with support for multiple storage drivers. -## Use a PSR-11 container to retrieve the cache keys +## Key Features -You can use a PSR-11 compatible to retrieve the cache keys. +- **PSR-16 Simple Cache interface** - Simple, straightforward caching API +- **PSR-6 Cache Pool interface** - More verbose caching with fine-grained control +- **Multiple storage backends** - Choose from memory, file system, Redis, Memcached and more +- **Atomic operations** - Support for increment, decrement and add operations in compatible engines +- **Garbage collection** - Automatic cleanup of expired items +- **PSR-11 container support** - Retrieve cache keys via dependency container +- **Logging capabilities** - PSR-3 compatible logging of cache operations -See more [here](docs/psr11-usage.md) +## Quick Start -## Beyond the PSR protocol - -The PSR protocol is a good way to standardize the cache access, -but sometimes you need to go beyond the protocol. +```bash +composer require "byjg/cache-engine" +``` -Some cache engines have additional features that are not covered by the PSR protocol. +```php +// PSR-16 Simple Cache +$cache = new \ByJG\Cache\Psr16\FileSystemCacheEngine(); +$cache->set('key', 'value', 3600); // Cache for 1 hour +$value = $cache->get('key'); + +// PSR-6 Cache Pool +$pool = \ByJG\Cache\Factory::createFilesystemPool(); +$item = $pool->getItem('key'); +if (!$item->isHit()) { + $item->set('value'); + $item->expiresAfter(3600); + $pool->save($item); +} +$value = $item->get(); +``` -Some examples are: +## Documentation + +### Getting Started +- [PSR-16 Simple Cache Usage](docs/basic-usage-psr16-simplecache.md) +- [PSR-6 Cache Pool Usage](docs/basic-usage-psr6-cachepool.md) + +### Available Cache Engines +| Engine | Description | +|:--------------------------------------------------------------------|:--------------------------------------------------------| +| [NoCacheEngine](docs/class-no-cache-engine.md) | No-op engine for disabling cache without code changes | +| [ArrayCacheEngine](docs/class-array-cache-engine.md) | In-memory array cache (non-persistent between requests) | +| [FileSystemCacheEngine](docs/class-filesystem-cache-engine.md) | File system based caching | +| [MemcachedEngine](docs/class-memcached-engine.md) | Memcached distributed caching | +| [RedisCacheEngine](docs/class-redis-cache-engine.md) | Redis-based caching | +| [SessionCacheEngine](docs/class-session-cache-engine.md) | PHP session-based caching | +| [TmpfsCacheEngine](docs/class-tmpfs-cache-engine.md) | Tmpfs-based caching | +| [ShmopCacheEngine](docs/class-shmop-cache-engine.md) | Shared memory caching (deprecated) | +| [KeyValueCacheEngine](https://github.com/byjg/php-anydataset-nosql) | S3-Like or CloudflareKV storage (separate package) | + +### Advanced Features - [Atomic Operations](docs/atomic-operations.md) - [Garbage Collection](docs/garbage-collection.md) +- [Logging](docs/setup-log-handler.md) +- [PSR-11 Container Usage](docs/psr11-usage.md) -## Install - -Just type: - -``` -composer require "byjg/cache-engine" -``` - - -## Running Unit Testes +## Running Unit Tests ``` vendor/bin/phpunit --stderr ``` -**Note:** the parameter `--stderr` after `phpunit` is to permit run the tests on SessionCacheEngine. +**Note:** The `--stderr` parameter is required for SessionCacheEngine tests to run properly. ## Dependencies @@ -89,5 +83,6 @@ flowchart TD byjg/cache-engine --> psr/simple-cache byjg/cache-engine --> psr/container ``` + ---- [Open source ByJG](http://opensource.byjg.com) diff --git a/composer.json b/composer.json index 0053294..5e7677e 100644 --- a/composer.json +++ b/composer.json @@ -12,15 +12,15 @@ } }, "require": { - "php": ">=8.1 <8.4", + "php": ">=8.1 <8.5", "psr/cache": "^1.0|^2.0|^3.0", "psr/log": "^1.0|^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0", "psr/container": "^1.0|^1.1|^2.0" }, "require-dev": { - "phpunit/phpunit": "^9.6", - "vimeo/psalm": "^5.9" + "phpunit/phpunit": "^10.5|^11.5", + "vimeo/psalm": "^5.9|^6.2" }, "suggest": { "ext-memcached": "*", diff --git a/docs/atomic-operations.md b/docs/atomic-operations.md index 88aa954..3974673 100644 --- a/docs/atomic-operations.md +++ b/docs/atomic-operations.md @@ -15,10 +15,10 @@ The atomic operations are: The engines that support atomic operations have to implement the `AtomicOperationInterface`. Some engines that support atomic operations are: -- RedisCachedEngine +- RedisCacheEngine - MemcachedEngine -- TmpfsCacheEngine - FileSystemCacheEngine +- TmpfsCacheEngine (inherits from FileSystemCacheEngine) ## Increment diff --git a/docs/class-redis-cache-engine.md b/docs/class-redis-cache-engine.md index 43b4598..9b500b7 100644 --- a/docs/class-redis-cache-engine.md +++ b/docs/class-redis-cache-engine.md @@ -13,19 +13,19 @@ $server = 'localhost:5678' ## PSR-16 Constructor ```php -$cache = new \ByJG\Cache\Psr16\RedisCacheEngine($server, $password) +$cache = new \ByJG\Cache\Psr16\RedisCacheEngine($server, $password, $logger) ``` ## PSR-6 Constructor ```php -$cachePool = \ByJG\Cache\Factory::createRedisCacheEngine($server, $password) +$cachePool = \ByJG\Cache\Factory::createRedisPool($server, $password, $bufferSize, $logger) ``` or ```php -$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\RedisCacheEngine($server, $password)); +$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\RedisCacheEngine($server, $password, $logger)); ``` diff --git a/docs/class-tmpfs-cache-engine.md b/docs/class-tmpfs-cache-engine.md index 157bbce..ce2c4c3 100644 --- a/docs/class-tmpfs-cache-engine.md +++ b/docs/class-tmpfs-cache-engine.md @@ -10,19 +10,19 @@ The TmpfsCacheEngine allows to store the cache files in the `/dev/shm` tmpfs. ## PSR-16 Constructor ```php -$cache = new \ByJG\Cache\Psr16\TmpfsCacheEngine($path, $prefix) +$cache = new \ByJG\Cache\Psr16\TmpfsCacheEngine($prefix, $logger) ``` ## PSR-6 Constructor ```php -$cachePool = \ByJG\Cache\Factory::createTmpfsCachePool($path, $prefix, $bufferSize = 10) +$cachePool = \ByJG\Cache\Factory::createTmpfsCachePool($prefix, $logger) ``` or ```php -$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\createTmpfsCachePool($path, $prefix)); +$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\TmpfsCacheEngine($prefix, $logger)); ``` diff --git a/docs/garbage-collection.md b/docs/garbage-collection.md index 6b32428..3203e5c 100644 --- a/docs/garbage-collection.md +++ b/docs/garbage-collection.md @@ -10,18 +10,18 @@ is based on the Best Effort. It means an expired key is removed only when you tr If the cache engine has a low hit rate, it is recommended to run a garbage collection process to avoid the cache to grow indefinitely. -The classes that implement the `GarbageCollectionInterface` have the method `collectGarbage()`. +The classes that implement the `GarbageCollectorInterface` have the method `collectGarbage()`. Some engines that support garbage collection are: - FileSystemCacheEngine - ArrayCacheEngine -- TmpfsCacheEngine +- TmpfsCacheEngine (inherits from FileSystemCacheEngine) ## Example ```php collectGarbage(); ``` diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 13600e9..365de7f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -9,12 +9,13 @@ and open the template in the editor. bootstrap="./vendor/autoload.php" colors="true" testdox="true" - convertErrorsToExceptions="true" - convertNoticesToExceptions="true" - convertWarningsToExceptions="true" - convertDeprecationsToExceptions="true" + displayDetailsOnTestsThatTriggerDeprecations="true" + displayDetailsOnTestsThatTriggerErrors="true" + displayDetailsOnTestsThatTriggerNotices="true" + displayDetailsOnTestsThatTriggerWarnings="true" + displayDetailsOnPhpunitDeprecations="true" stopOnFailure="false" - xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"> + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"> @@ -22,11 +23,11 @@ and open the template in the editor. - + - ./src + ./src/ - + diff --git a/src/Factory.php b/src/Factory.php index 61c6148..117c821 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -62,7 +62,7 @@ public static function createMemcachedPool(?array $servers = null, int $bufferSi ); } - public static function createRedisCacheEngine(?string $servers = null, ?string $password = null, int $bufferSize = 10, ?LoggerInterface $logger = null): CachePool + public static function createRedisPool(?string $servers = null, ?string $password = null, int $bufferSize = 10, ?LoggerInterface $logger = null): CachePool { return new CachePool( new RedisCacheEngine($servers, $password, $logger), diff --git a/src/Psr16/ArrayCacheEngine.php b/src/Psr16/ArrayCacheEngine.php index 4c40698..f5404b1 100644 --- a/src/Psr16/ArrayCacheEngine.php +++ b/src/Psr16/ArrayCacheEngine.php @@ -40,6 +40,7 @@ public function __construct(LoggerInterface|null $logger = null) * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ + #[\Override] public function has(string $key): bool { $key = $this->getKeyFromContainer($key); @@ -63,6 +64,7 @@ public function has(string $key): bool * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function get(string $key, mixed $default = null): mixed { if ($this->has($key)) { @@ -88,6 +90,7 @@ public function get(string $key, mixed $default = null): mixed * * MUST be thrown if the $key string is not a legal value. */ + #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $key = $this->getKeyFromContainer($key); @@ -102,6 +105,7 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null return true; } + #[\Override] public function clear(): bool { $this->cache = []; @@ -114,6 +118,7 @@ public function clear(): bool * @param string $key * @return bool */ + #[\Override] public function delete(string $key): bool { $key = $this->getKeyFromContainer($key); @@ -123,11 +128,13 @@ public function delete(string $key): bool return true; } + #[\Override] public function isAvailable(): bool { return true; } + #[\Override] public function collectGarbage() { foreach ($this->cache["ttl"] as $key => $ttl) { @@ -138,6 +145,7 @@ public function collectGarbage() } } + #[\Override] public function getTtl(string $key): ?int { $key = $this->getKeyFromContainer($key); diff --git a/src/Psr16/BaseCacheEngine.php b/src/Psr16/BaseCacheEngine.php index 0c10629..ec1c656 100644 --- a/src/Psr16/BaseCacheEngine.php +++ b/src/Psr16/BaseCacheEngine.php @@ -6,6 +6,7 @@ use ByJG\Cache\Exception\InvalidArgumentException; use DateInterval; use DateTime; +use Override; use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; @@ -21,6 +22,7 @@ abstract class BaseCacheEngine implements CacheInterface, CacheAvailabilityInter * @return iterable * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[Override] public function getMultiple(string|iterable $keys, mixed $default = null): iterable { if (is_string($keys)) { @@ -40,6 +42,7 @@ public function getMultiple(string|iterable $keys, mixed $default = null): itera * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[Override] public function setMultiple(iterable $values, DateInterval|int|null $ttl = null): bool { foreach ($values as $key => $value) { @@ -53,6 +56,7 @@ public function setMultiple(iterable $values, DateInterval|int|null $ttl = null) * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[Override] public function deleteMultiple(iterable $keys): bool { foreach ($keys as $key) { @@ -61,12 +65,14 @@ public function deleteMultiple(iterable $keys): bool return true; } + #[Override] abstract public function isAvailable(): bool; protected function addToNow(DateInterval|int|null $ttl): int|null { if (is_numeric($ttl)) { - return strtotime("+$ttl second"); + $timestamp = strtotime("+$ttl second"); + return $timestamp !== false ? $timestamp : null; } if ($ttl instanceof DateInterval) { diff --git a/src/Psr16/FileSystemCacheEngine.php b/src/Psr16/FileSystemCacheEngine.php index c0c58f9..ccb7e70 100644 --- a/src/Psr16/FileSystemCacheEngine.php +++ b/src/Psr16/FileSystemCacheEngine.php @@ -42,6 +42,7 @@ public function __construct(string $prefix = 'cache', ?string $path = null, ?Log * @throws NotFoundExceptionInterface * @throws \ByJG\Cache\Exception\InvalidArgumentException */ + #[\Override] public function get(string $key, mixed $default = null): mixed { // Check if file is Locked @@ -70,6 +71,7 @@ public function get(string $key, mixed $default = null): mixed * * MUST be thrown if the $key string is not a legal value. */ + #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $fileKey = $this->fixKey($key); @@ -94,6 +96,7 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null * @param string $key * @return bool */ + #[\Override] public function delete(string $key): bool { $this->set($key, null); @@ -105,6 +108,7 @@ public function delete(string $key): bool * @throws NotFoundExceptionInterface * @throws \ByJG\Cache\Exception\InvalidArgumentException */ + #[\Override] public function isAvailable(): bool { return is_writable(dirname($this->fixKey('test'))); @@ -133,6 +137,7 @@ protected function fixKey(string $key): string * @throws NotFoundExceptionInterface * @throws \ByJG\Cache\Exception\InvalidArgumentException */ + #[\Override] public function clear(): bool { $patternKey = $this->fixKey('*'); @@ -158,6 +163,7 @@ public function clear(): bool * @throws NotFoundExceptionInterface * @throws \ByJG\Cache\Exception\InvalidArgumentException */ + #[\Override] public function has(string $key): bool { $fileKey = $this->fixKey($key); @@ -239,6 +245,7 @@ protected function putContents(string $fileKey, mixed $value, ?int $ttl, ?Closur return $returnValue; } + #[\Override] public function collectGarbage() { $patternKey = $this->fixKey('*'); @@ -257,6 +264,7 @@ public function collectGarbage() } + #[\Override] public function getTtl(string $key): ?int { $fileKey = $this->fixKey($key); @@ -266,6 +274,7 @@ public function getTtl(string $key): ?int return null; } + #[\Override] public function increment(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { return $this->putContents($this->fixKey($key), $value, $ttl, function ($currentValue, $value) { @@ -273,6 +282,7 @@ public function increment(string $key, int $value = 1, DateInterval|int|null $tt }); } + #[\Override] public function decrement(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { return $this->putContents($this->fixKey($key), $value, $ttl, function ($currentValue, $value) { @@ -280,6 +290,7 @@ public function decrement(string $key, int $value = 1, DateInterval|int|null $tt }); } + #[\Override] public function add(string $key, $value, DateInterval|int|null $ttl = null): array { return $this->putContents($this->fixKey($key), $value, $ttl, function ($currentValue, $value) { diff --git a/src/Psr16/MemcachedEngine.php b/src/Psr16/MemcachedEngine.php index 117cc38..5e7e0f2 100644 --- a/src/Psr16/MemcachedEngine.php +++ b/src/Psr16/MemcachedEngine.php @@ -79,6 +79,7 @@ protected function lazyLoadMemCachedServers(): void * @throws NotFoundExceptionInterface * @throws StorageErrorException */ + #[\Override] public function get(string $key, mixed $default = null): mixed { $this->lazyLoadMemCachedServers(); @@ -102,6 +103,7 @@ public function get(string $key, mixed $default = null): mixed * @throws NotFoundExceptionInterface * @throws StorageErrorException */ + #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $this->lazyLoadMemCachedServers(); @@ -125,6 +127,7 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null * @throws NotFoundExceptionInterface * @throws StorageErrorException */ + #[\Override] public function delete(string $key): bool { $this->lazyLoadMemCachedServers(); @@ -133,6 +136,7 @@ public function delete(string $key): bool return true; } + #[\Override] public function isAvailable(): bool { if (!class_exists('\Memcached')) { @@ -151,6 +155,7 @@ public function isAvailable(): bool * @return bool * @throws StorageErrorException */ + #[\Override] public function clear(): bool { $this->lazyLoadMemCachedServers(); @@ -166,6 +171,7 @@ public function clear(): bool * @throws NotFoundExceptionInterface * @throws StorageErrorException */ + #[\Override] public function has(string $key): bool { $this->lazyLoadMemCachedServers(); @@ -174,6 +180,7 @@ public function has(string $key): bool return ($this->memCached->getResultCode() === Memcached::RES_SUCCESS); } + #[\Override] public function increment(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { $this->lazyLoadMemCachedServers(); @@ -193,6 +200,7 @@ public function increment(string $key, int $value = 1, DateInterval|int|null $tt return $result; } + #[\Override] public function decrement(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { $this->lazyLoadMemCachedServers(); @@ -212,6 +220,7 @@ public function decrement(string $key, int $value = 1, DateInterval|int|null $tt return $result; } + #[\Override] public function add(string $key, $value, DateInterval|int|null $ttl = null): array { $this->lazyLoadMemCachedServers(); diff --git a/src/Psr16/NoCacheEngine.php b/src/Psr16/NoCacheEngine.php index 19f3d8b..8ffdb05 100644 --- a/src/Psr16/NoCacheEngine.php +++ b/src/Psr16/NoCacheEngine.php @@ -17,6 +17,7 @@ class NoCacheEngine extends BaseCacheEngine * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function get(string $key, mixed $default = null): mixed { $key = $this->getKeyFromContainer($key); @@ -32,6 +33,7 @@ public function get(string $key, mixed $default = null): mixed * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $key = $this->getKeyFromContainer($key); @@ -45,6 +47,7 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function delete(string $key): bool { $key = $this->getKeyFromContainer($key); @@ -69,6 +72,7 @@ public function unlock(string $key): void return; } + #[\Override] public function isAvailable(): bool { return true; @@ -79,6 +83,7 @@ public function isAvailable(): bool * * @return bool True on success and false on failure. */ + #[\Override] public function clear(): bool { return true; @@ -97,6 +102,7 @@ public function clear(): bool * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function has(string $key): bool { $key = $this->getKeyFromContainer($key); diff --git a/src/Psr16/RedisCacheEngine.php b/src/Psr16/RedisCacheEngine.php index d2dde57..e5d78b6 100644 --- a/src/Psr16/RedisCacheEngine.php +++ b/src/Psr16/RedisCacheEngine.php @@ -81,6 +81,7 @@ protected function fixKey(string $key): string * @throws NotFoundExceptionInterface * @throws RedisException */ + #[\Override] public function get(string $key, mixed $default = null): mixed { $this->lazyLoadRedisServer(); @@ -120,6 +121,7 @@ public function get(string $key, mixed $default = null): mixed * @throws NotFoundExceptionInterface * @throws RedisException */ + #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $this->lazyLoadRedisServer(); @@ -138,6 +140,7 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null * @throws RedisException * @throws ContainerExceptionInterface */ + #[\Override] public function delete(string $key): bool { $this->lazyLoadRedisServer(); @@ -153,10 +156,11 @@ public function delete(string $key): bool * @throws RedisException * @throws ContainerExceptionInterface */ + #[\Override] public function clear(): bool { $keys = $this->redis->keys('cache:*'); - foreach ((array)$keys as $key) { + foreach ($keys as $key) { if (preg_match('/^cache:(?.*)/', $key, $matches)) { $this->delete($matches['key']); } @@ -170,21 +174,14 @@ public function clear(): bool * @throws RedisException * @throws ContainerExceptionInterface */ + #[\Override] public function has(string $key): bool { $result = $this->redis->exists($this->fixKey($key)); - - if (is_numeric($result)) { - return $result !== 0; - } - - if ($result instanceof Redis) { - return true; - } - - return $result; + return (bool)$result; } + #[\Override] public function isAvailable(): bool { if (!class_exists('\Redis')) { @@ -199,6 +196,7 @@ public function isAvailable(): bool } } + #[\Override] public function increment(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { $this->lazyLoadRedisServer(); @@ -209,9 +207,10 @@ public function increment(string $key, int $value = 1, DateInterval|int|null $tt $this->redis->expire($this->fixKey($key), $this->convertToSeconds($ttl)); } - return is_int($result) ? $result : -1; + return $result; } + #[\Override] public function decrement(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { $this->lazyLoadRedisServer(); @@ -222,9 +221,10 @@ public function decrement(string $key, int $value = 1, DateInterval|int|null $tt $this->redis->expire($this->fixKey($key), $this->convertToSeconds($ttl)); } - return is_int($result) ? $result : -1; + return $result; } + #[\Override] public function add(string $key, $value, DateInterval|int|null $ttl = null): array { $this->lazyLoadRedisServer(); diff --git a/src/Psr16/SessionCacheEngine.php b/src/Psr16/SessionCacheEngine.php index 6b69cc1..af87326 100644 --- a/src/Psr16/SessionCacheEngine.php +++ b/src/Psr16/SessionCacheEngine.php @@ -47,6 +47,7 @@ protected function keyName($key): string * @throws ContainerExceptionInterface * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function get(string $key, mixed $default = null): mixed { $this->checkSession(); @@ -65,6 +66,7 @@ public function get(string $key, mixed $default = null): mixed * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function delete(string $key): bool { $this->checkSession(); @@ -81,6 +83,7 @@ public function delete(string $key): bool return true; } + #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $this->checkSession(); @@ -94,12 +97,14 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null return true; } + #[\Override] public function clear(): bool { session_destroy(); return true; } + #[\Override] public function has(string $key): bool { $keyName = $this->keyName($key); @@ -116,6 +121,7 @@ public function has(string $key): bool return false; } + #[\Override] public function isAvailable(): bool { try { diff --git a/src/Psr16/ShmopCacheEngine.php b/src/Psr16/ShmopCacheEngine.php index 1f0ab58..4e84470 100644 --- a/src/Psr16/ShmopCacheEngine.php +++ b/src/Psr16/ShmopCacheEngine.php @@ -86,6 +86,7 @@ protected function getFTok(string $file): int * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function get(string $key, mixed $default = null): mixed { if ($default === false) { @@ -144,6 +145,7 @@ protected function isValidAge(string $file): bool * @throws NotFoundExceptionInterface * @throws StorageErrorException */ + #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $this->logger->info("[Shmop Cache] set '$key'"); @@ -191,6 +193,7 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function delete(string $key): bool { $this->logger->info("[Shmop Cache] release '$key'"); @@ -226,6 +229,7 @@ private function deleteFromFilenameToken(string $file): void } } + #[\Override] public function clear(): bool { $patternKey = sys_get_temp_dir() . '/shmop-*.cache'; @@ -241,6 +245,7 @@ public function clear(): bool * @throws InvalidArgumentException * @throws NotFoundExceptionInterface */ + #[\Override] public function has(string $key): bool { $file = $this->getFilenameToken($key); @@ -260,6 +265,7 @@ public function has(string $key): bool } + #[\Override] public function isAvailable(): bool { return function_exists('shmop_open'); diff --git a/src/Psr6/CacheItem.php b/src/Psr6/CacheItem.php index fa809d6..ff193e4 100644 --- a/src/Psr6/CacheItem.php +++ b/src/Psr6/CacheItem.php @@ -46,6 +46,7 @@ public function __construct(string $key, mixed $value, bool $hit = true) /** * {@inheritdoc} */ + #[\Override] public function getKey(): string { return $this->key; @@ -54,6 +55,7 @@ public function getKey(): string /** * {@inheritdoc} */ + #[\Override] public function get(): mixed { return $this->isHit() ? $this->value : null; @@ -61,6 +63,7 @@ public function get(): mixed /** * {@inheritdoc} */ + #[\Override] public function set(mixed $value = null): static { $this->value = $value; @@ -70,6 +73,7 @@ public function set(mixed $value = null): static /** * {@inheritdoc} */ + #[\Override] public function isHit(): bool { return $this->hit; @@ -77,6 +81,7 @@ public function isHit(): bool /** * {@inheritdoc} */ + #[\Override] public function expiresAt(?DateTimeInterface $expiration): static { if (empty($expiration)) { @@ -90,6 +95,7 @@ public function expiresAt(?DateTimeInterface $expiration): static /** * {@inheritdoc} */ + #[\Override] public function expiresAfter(int|\DateInterval|null $time): static { $this->expiration = new DateTime('now +1 year'); diff --git a/src/Psr6/CachePool.php b/src/Psr6/CachePool.php index e3141ce..949baf4 100644 --- a/src/Psr6/CachePool.php +++ b/src/Psr6/CachePool.php @@ -114,6 +114,7 @@ protected function removeElementFromBuffer(string $key): void * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function getItem(string $key): CacheItemInterface { // Get the element from the buffer if still remains valid! @@ -140,6 +141,7 @@ public function getItem(string $key): CacheItemInterface * @return array * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function getItems(array $keys = array()): iterable { $result = []; @@ -157,6 +159,7 @@ public function getItems(array $keys = array()): iterable * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function hasItem(string $key): bool { return $this->getItem($key)->isHit(); @@ -165,6 +168,7 @@ public function hasItem(string $key): bool /** * Psr implementation of clear() */ + #[\Override] public function clear(): bool { $this->_cacheEngine->clear(); @@ -180,6 +184,7 @@ public function clear(): bool * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function deleteItem(string $key): bool { return $this->deleteItems([$key]); @@ -193,6 +198,7 @@ public function deleteItem(string $key): bool * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function deleteItems(array $keys): bool { foreach ($keys as $key) { @@ -208,6 +214,7 @@ public function deleteItems(array $keys): bool * @return bool * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function save(CacheItemInterface $item): bool { if (!($item instanceof CacheItem)) { @@ -235,6 +242,7 @@ public function save(CacheItemInterface $item): bool * @param CacheItemInterface $item * @return bool */ + #[\Override] public function saveDeferred(CacheItemInterface $item): bool { $this->deferredItem[] = $item; @@ -246,6 +254,7 @@ public function saveDeferred(CacheItemInterface $item): bool * * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[\Override] public function commit(): bool { foreach ($this->deferredItem as $item) { diff --git a/tests/BaseCacheTest.php b/tests/BaseCacheTest.php index af7e54a..ad9213f 100644 --- a/tests/BaseCacheTest.php +++ b/tests/BaseCacheTest.php @@ -11,6 +11,7 @@ abstract class BaseCacheTest extends TestCase */ protected $cacheEngine = null; + #[\Override] protected function tearDown(): void { if (empty($this->cacheEngine)) { @@ -20,7 +21,7 @@ protected function tearDown(): void $this->cacheEngine = null; } - public function CachePoolProvider() + public static function CachePoolProvider() { $memcachedServer = ['127.0.0.1:11211']; $redisCacheServer = '127.0.0.1:6379'; diff --git a/tests/BasicContainer.php b/tests/BasicContainer.php index 149852b..5d215c0 100644 --- a/tests/BasicContainer.php +++ b/tests/BasicContainer.php @@ -11,6 +11,7 @@ class BasicContainer implements ContainerInterface /** * @inheritDoc */ + #[\Override] public function get(string $id) { if ($id == "test-key") { @@ -23,6 +24,7 @@ public function get(string $id) /** * @inheritDoc */ + #[\Override] public function has(string $id): bool { if ($id == "test-key") { From 3cc1caaa8d31a6d18a473b673998a471289dc576 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 07:46:38 -0500 Subject: [PATCH 02/11] Add Gitpod configuration and migrate PHPUnit data providers Add a `.gitpod.yml` setup for development environments and a VS Code debug configuration for PHP projects. Migrated PHPUnit annotations for data providers to PHP 8 attributes for improved code clarity and compliance with modern PHP versions. --- .gitpod.yml | 28 ++++++++++++++++++++++++++++ .vscode/launch.json | 35 +++++++++++++++++++++++++++++++++++ tests/CachePSR16Test.php | 37 +++++++++++++++++++++++++------------ tests/CachePSR6Test.php | 26 ++++++++++++++------------ 4 files changed, 102 insertions(+), 24 deletions(-) create mode 100644 .gitpod.yml create mode 100644 .vscode/launch.json diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..335de09 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,28 @@ +tasks: + - name: Run Composer + command: | + composer install + +image: byjg/gitpod-image:latest + +jetbrains: + phpstorm: + vmoptions: '-Xmx4g' + plugins: + - com.github.copilot + - com.intellij.kubernetes + - com.intellij.mermaid + - ru.adelf.idea.dotenv + - org.toml.lang + +vscode: + extensions: + - ikappas.composer + - hbenl.test-adapter-converter + - hbenl.vscode-test-explorer + - felixfbecker.php-debug + - neilbrayfield.php-docblocker + - bmewburn.vscode-intelephense-client + - getpsalm.psalm-vscode-plugin + - SonarSource.sonarlint-vscode + - recca0120.vscode-phpunit \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..a8c1b2a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug current Script in Console", + "type": "php", + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "port": 9003, + "runtimeArgs": [ + "-dxdebug.start_with_request=yes" + ], + "env": { + "XDEBUG_MODE": "debug,develop", + "XDEBUG_CONFIG": "client_port=${port}" + } + }, + { + "name": "PHPUnit Debug", + "type": "php", + "request": "launch", + "program": "${workspaceFolder}/vendor/bin/phpunit", + "cwd": "${workspaceFolder}", + "port": 9003, + "runtimeArgs": [ + "-dxdebug.start_with_request=yes" + ], + "env": { + "XDEBUG_MODE": "debug,develop", + "XDEBUG_CONFIG": "client_port=${port}" + } + } + ] +} \ No newline at end of file diff --git a/tests/CachePSR16Test.php b/tests/CachePSR16Test.php index cd64da0..76d29af 100644 --- a/tests/CachePSR16Test.php +++ b/tests/CachePSR16Test.php @@ -7,14 +7,15 @@ use ByJG\Cache\GarbageCollectorInterface; use ByJG\Cache\Psr16\BaseCacheEngine; use ByJG\Cache\Psr16\NoCacheEngine; +use PHPUnit\Framework\Attributes\DataProvider; class CachePSR16Test extends BaseCacheTest { /** - * @dataProvider CachePoolProvider * @param BaseCacheEngine $cacheEngine * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testGetOneItem(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -47,10 +48,10 @@ public function testGetOneItem(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider * @param BaseCacheEngine $cacheEngine * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testGetMultipleItems(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -88,10 +89,10 @@ public function testGetMultipleItems(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider * @param BaseCacheEngine $cacheEngine * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testTtl(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -125,10 +126,10 @@ public function testTtl(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider * @param BaseCacheEngine $cacheEngine * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testCacheObject(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -158,10 +159,10 @@ public function testCacheObject(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider * @param BaseCacheEngine $cacheEngine * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testCacheArray(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -196,10 +197,10 @@ public function testCacheArray(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider * @param BaseCacheEngine $cacheEngine * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testClear(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -238,8 +239,10 @@ public function testClear(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider + * @param BaseCacheEngine $cacheEngine + * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testCacheContainerKeyNonExistent(BaseCacheEngine $cacheEngine) { if ($cacheEngine->isAvailable()) { @@ -254,8 +257,10 @@ public function testCacheContainerKeyNonExistent(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider + * @param BaseCacheEngine $cacheEngine + * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testCacheContainerKey(BaseCacheEngine $cacheEngine) { if ($cacheEngine->isAvailable() && !($cacheEngine instanceof NoCacheEngine)) { @@ -279,8 +284,10 @@ public function testCacheContainerKey(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider + * @param BaseCacheEngine $cacheEngine + * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testGarbageCollector(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -310,8 +317,10 @@ public function testGarbageCollector(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider + * @param BaseCacheEngine $cacheEngine + * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testAtomicIncrement(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -330,8 +339,10 @@ public function testAtomicIncrement(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider + * @param BaseCacheEngine $cacheEngine + * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testAtomicDecrement(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -350,8 +361,10 @@ public function testAtomicDecrement(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider + * @param BaseCacheEngine $cacheEngine + * @throws \Psr\SimpleCache\InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testAtomicAdd(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; diff --git a/tests/CachePSR6Test.php b/tests/CachePSR6Test.php index 649be98..bb8c903 100644 --- a/tests/CachePSR6Test.php +++ b/tests/CachePSR6Test.php @@ -5,14 +5,16 @@ use ByJG\Cache\Psr16\BaseCacheEngine; use ByJG\Cache\Psr6\CachePool; use DateInterval; +use PHPUnit\Framework\Attributes\DataProvider; +use Psr\SimpleCache\InvalidArgumentException; class CachePSR6Test extends BaseCacheTest { /** - * @dataProvider CachePoolProvider - * @param \ByJG\Cache\Psr16\BaseCacheEngine $cacheEngine - * @throws \Psr\SimpleCache\InvalidArgumentException + * @param BaseCacheEngine $cacheEngine + * @throws InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testGetOneItem(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -45,10 +47,10 @@ public function testGetOneItem(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider - * @param \ByJG\Cache\Psr16\BaseCacheEngine $cacheEngine - * @throws \Psr\SimpleCache\InvalidArgumentException + * @param BaseCacheEngine $cacheEngine + * @throws InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testGetMultipleItems(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; @@ -89,10 +91,10 @@ public function testGetMultipleItems(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider - * @param \ByJG\Cache\Psr16\BaseCacheEngine $cacheEngine - * @throws \Psr\SimpleCache\InvalidArgumentException + * @param BaseCacheEngine $cacheEngine + * @throws InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testTtl(BaseCacheEngine $cacheEngine) { $timeList = [ @@ -137,10 +139,10 @@ public function testTtl(BaseCacheEngine $cacheEngine) } /** - * @dataProvider CachePoolProvider - * @param \ByJG\Cache\Psr16\BaseCacheEngine $cacheEngine - * @throws \Psr\SimpleCache\InvalidArgumentException + * @param BaseCacheEngine $cacheEngine + * @throws InvalidArgumentException */ + #[DataProvider('CachePoolProvider')] public function testCacheObject(BaseCacheEngine $cacheEngine) { $this->cacheEngine = $cacheEngine; From dda89ba4511fe460fa3694867f459209b821cf80 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 08:20:59 -0500 Subject: [PATCH 03/11] Rename test classes for clarity and consistency. Renamed `BaseCacheTest` to `TestBase` and updated corresponding test classes to align with the new naming convention. This improves readability and ensures consistent naming across the test suite. --- tests/{CachePSR16Test.php => CachePSR16TestBase.php} | 2 +- tests/{CachePSR6Test.php => CachePSR6TestBase.php} | 2 +- tests/{BaseCacheTest.php => TestBase.php} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename tests/{CachePSR16Test.php => CachePSR16TestBase.php} (99%) rename tests/{CachePSR6Test.php => CachePSR6TestBase.php} (99%) rename tests/{BaseCacheTest.php => TestBase.php} (97%) diff --git a/tests/CachePSR16Test.php b/tests/CachePSR16TestBase.php similarity index 99% rename from tests/CachePSR16Test.php rename to tests/CachePSR16TestBase.php index 76d29af..d0fbabd 100644 --- a/tests/CachePSR16Test.php +++ b/tests/CachePSR16TestBase.php @@ -9,7 +9,7 @@ use ByJG\Cache\Psr16\NoCacheEngine; use PHPUnit\Framework\Attributes\DataProvider; -class CachePSR16Test extends BaseCacheTest +class CachePSR16TestBase extends TestBase { /** * @param BaseCacheEngine $cacheEngine diff --git a/tests/CachePSR6Test.php b/tests/CachePSR6TestBase.php similarity index 99% rename from tests/CachePSR6Test.php rename to tests/CachePSR6TestBase.php index bb8c903..53ace0a 100644 --- a/tests/CachePSR6Test.php +++ b/tests/CachePSR6TestBase.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use Psr\SimpleCache\InvalidArgumentException; -class CachePSR6Test extends BaseCacheTest +class CachePSR6TestBase extends TestBase { /** * @param BaseCacheEngine $cacheEngine diff --git a/tests/BaseCacheTest.php b/tests/TestBase.php similarity index 97% rename from tests/BaseCacheTest.php rename to tests/TestBase.php index ad9213f..d6d7608 100644 --- a/tests/BaseCacheTest.php +++ b/tests/TestBase.php @@ -4,7 +4,7 @@ use PHPUnit\Framework\TestCase; -abstract class BaseCacheTest extends TestCase +abstract class TestBase extends TestCase { /** * @var \ByJG\Cache\Psr16\BaseCacheEngine From 14ef34394f647fbf66d942183163ceb36cd98cee Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 08:26:10 -0500 Subject: [PATCH 04/11] Refactor test class hierarchy and import structures. Renamed test base classes for better clarity and cohesion, consolidating them under `MainTest`. Simplified imports by using concise class references, improving readability and maintainability. These changes enhance test structure organization and prepare the codebase for potential future extensions. --- ...R16TestBase.php => CachePSR16MainTest.php} | 2 +- ...PSR6TestBase.php => CachePSR6MainTest.php} | 2 +- tests/{TestBase.php => MainTest.php} | 33 ++++++++++++------- 3 files changed, 23 insertions(+), 14 deletions(-) rename tests/{CachePSR16TestBase.php => CachePSR16MainTest.php} (99%) rename tests/{CachePSR6TestBase.php => CachePSR6MainTest.php} (99%) rename tests/{TestBase.php => MainTest.php} (51%) diff --git a/tests/CachePSR16TestBase.php b/tests/CachePSR16MainTest.php similarity index 99% rename from tests/CachePSR16TestBase.php rename to tests/CachePSR16MainTest.php index d0fbabd..0fc084c 100644 --- a/tests/CachePSR16TestBase.php +++ b/tests/CachePSR16MainTest.php @@ -9,7 +9,7 @@ use ByJG\Cache\Psr16\NoCacheEngine; use PHPUnit\Framework\Attributes\DataProvider; -class CachePSR16TestBase extends TestBase +class CachePSR16MainTest extends MainTest { /** * @param BaseCacheEngine $cacheEngine diff --git a/tests/CachePSR6TestBase.php b/tests/CachePSR6MainTest.php similarity index 99% rename from tests/CachePSR6TestBase.php rename to tests/CachePSR6MainTest.php index 53ace0a..5651576 100644 --- a/tests/CachePSR6TestBase.php +++ b/tests/CachePSR6MainTest.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use Psr\SimpleCache\InvalidArgumentException; -class CachePSR6TestBase extends TestBase +class CachePSR6MainTest extends MainTest { /** * @param BaseCacheEngine $cacheEngine diff --git a/tests/TestBase.php b/tests/MainTest.php similarity index 51% rename from tests/TestBase.php rename to tests/MainTest.php index d6d7608..934a192 100644 --- a/tests/TestBase.php +++ b/tests/MainTest.php @@ -2,14 +2,23 @@ namespace Tests; +use ByJG\Cache\Psr16\ArrayCacheEngine; +use ByJG\Cache\Psr16\BaseCacheEngine; +use ByJG\Cache\Psr16\FileSystemCacheEngine; +use ByJG\Cache\Psr16\MemcachedEngine; +use ByJG\Cache\Psr16\NoCacheEngine; +use ByJG\Cache\Psr16\RedisCacheEngine; +use ByJG\Cache\Psr16\SessionCacheEngine; +use ByJG\Cache\Psr16\ShmopCacheEngine; +use ByJG\Cache\Psr16\TmpfsCacheEngine; use PHPUnit\Framework\TestCase; -abstract class TestBase extends TestCase +class MainTest extends TestCase { /** - * @var \ByJG\Cache\Psr16\BaseCacheEngine + * @var BaseCacheEngine|null */ - protected $cacheEngine = null; + protected ?BaseCacheEngine $cacheEngine = null; #[\Override] protected function tearDown(): void @@ -29,31 +38,31 @@ public static function CachePoolProvider() return [ 'Array' => [ - new \ByJG\Cache\Psr16\ArrayCacheEngine() + new ArrayCacheEngine() ], 'FileSystem' => [ - new \ByJG\Cache\Psr16\FileSystemCacheEngine() + new FileSystemCacheEngine() ], 'Tmpfs' => [ - new \ByJG\Cache\Psr16\TmpfsCacheEngine() + new TmpfsCacheEngine() ], 'ShmopCache' => [ - new \ByJG\Cache\Psr16\ShmopCacheEngine() + new ShmopCacheEngine() ], 'SessionCache' => [ - new \ByJG\Cache\Psr16\SessionCacheEngine() + new SessionCacheEngine() ], 'NoCacheEngine' => [ - new \ByJG\Cache\Psr16\NoCacheEngine() + new NoCacheEngine() ], 'Memcached' => [ - new \ByJG\Cache\Psr16\MemcachedEngine($memcachedServer) + new MemcachedEngine($memcachedServer) ], 'Redis' => [ - new \ByJG\Cache\Psr16\RedisCacheEngine($redisCacheServer, $redisPassword) + new RedisCacheEngine($redisCacheServer, $redisPassword) ], 'Memory' => [ - new \ByJG\Cache\Psr16\TmpfsCacheEngine() + new TmpfsCacheEngine() ] ]; } From 2cd1be464a2faef7f9fdd0c91a9a73835ee9555b Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 08:37:53 -0500 Subject: [PATCH 05/11] Refactor test class hierarchy and naming. Renamed `MainTest` to `TestBase` and made it abstract to better reflect its role as a base class. Updated derived test classes (`CachePSR16MainTest` and `CachePSR6MainTest`) to extend `TestBase` and renamed them for consistency. --- tests/{CachePSR16MainTest.php => CachePSR16Test.php} | 2 +- tests/{CachePSR6MainTest.php => CachePSR6Test.php} | 2 +- tests/{MainTest.php => TestBase.php} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename tests/{CachePSR16MainTest.php => CachePSR16Test.php} (99%) rename tests/{CachePSR6MainTest.php => CachePSR6Test.php} (99%) rename tests/{MainTest.php => TestBase.php} (97%) diff --git a/tests/CachePSR16MainTest.php b/tests/CachePSR16Test.php similarity index 99% rename from tests/CachePSR16MainTest.php rename to tests/CachePSR16Test.php index 0fc084c..fa64c0a 100644 --- a/tests/CachePSR16MainTest.php +++ b/tests/CachePSR16Test.php @@ -9,7 +9,7 @@ use ByJG\Cache\Psr16\NoCacheEngine; use PHPUnit\Framework\Attributes\DataProvider; -class CachePSR16MainTest extends MainTest +class CachePSR16Test extends TestBase { /** * @param BaseCacheEngine $cacheEngine diff --git a/tests/CachePSR6MainTest.php b/tests/CachePSR6Test.php similarity index 99% rename from tests/CachePSR6MainTest.php rename to tests/CachePSR6Test.php index 5651576..cedd0d6 100644 --- a/tests/CachePSR6MainTest.php +++ b/tests/CachePSR6Test.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use Psr\SimpleCache\InvalidArgumentException; -class CachePSR6MainTest extends MainTest +class CachePSR6Test extends TestBase { /** * @param BaseCacheEngine $cacheEngine diff --git a/tests/MainTest.php b/tests/TestBase.php similarity index 97% rename from tests/MainTest.php rename to tests/TestBase.php index 934a192..e613401 100644 --- a/tests/MainTest.php +++ b/tests/TestBase.php @@ -13,7 +13,7 @@ use ByJG\Cache\Psr16\TmpfsCacheEngine; use PHPUnit\Framework\TestCase; -class MainTest extends TestCase +abstract class TestBase extends TestCase { /** * @var BaseCacheEngine|null From 15291390dc15bbcc6372bb1ccb67cac144dbb26c Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 08:48:40 -0500 Subject: [PATCH 06/11] Test memcache isAvailable in GitHub Action --- src/Psr16/MemcachedEngine.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Psr16/MemcachedEngine.php b/src/Psr16/MemcachedEngine.php index 5e7e0f2..44c4c37 100644 --- a/src/Psr16/MemcachedEngine.php +++ b/src/Psr16/MemcachedEngine.php @@ -143,12 +143,13 @@ public function isAvailable(): bool return false; } - try { +// try { $this->lazyLoadMemCachedServers(); - return true; - } catch (StorageErrorException $ex) { - return false; - } +// return true; +// } catch (StorageErrorException $ex) { +// return false; +// } + return true; } /** From e9f713743af65eb4d509b92c78d2b99e03149616 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 10:12:58 -0500 Subject: [PATCH 07/11] Try Fix unit test --- .github/workflows/phpunit.yml | 4 ++++ src/Psr16/MemcachedEngine.php | 11 +++++------ tests/TestBase.php | 18 +++++++++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index b55e670..9be254e 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -21,6 +21,10 @@ jobs: - "8.2" - "8.1" + env: + MEMCACHED_SERVER: "memcached:11211" + REDIS_SERVER: "redis:6379" + # Service containers to run services: memcached: diff --git a/src/Psr16/MemcachedEngine.php b/src/Psr16/MemcachedEngine.php index 44c4c37..5e7e0f2 100644 --- a/src/Psr16/MemcachedEngine.php +++ b/src/Psr16/MemcachedEngine.php @@ -143,13 +143,12 @@ public function isAvailable(): bool return false; } -// try { + try { $this->lazyLoadMemCachedServers(); -// return true; -// } catch (StorageErrorException $ex) { -// return false; -// } - return true; + return true; + } catch (StorageErrorException $ex) { + return false; + } } /** diff --git a/tests/TestBase.php b/tests/TestBase.php index e613401..0e8d2f9 100644 --- a/tests/TestBase.php +++ b/tests/TestBase.php @@ -32,9 +32,21 @@ protected function tearDown(): void public static function CachePoolProvider() { - $memcachedServer = ['127.0.0.1:11211']; - $redisCacheServer = '127.0.0.1:6379'; - $redisPassword = ''; + if (getenv('MEMCACHED_SERVER')) { + $memcachedServer = [getenv('MEMCACHED_SERVER')]; + } else { + $memcachedServer = ['127.0.0.1:11211']; + } + if (getenv('REDIS_SERVER')) { + $redisCacheServer = getenv('REDIS_SERVER'); + } else { + $redisCacheServer = '127.0.0.1:6379'; + } + if (getenv('REDIS_PASSWORD')) { + $redisPassword = getenv('REDIS_PASSWORD'); + } else { + $redisPassword = ''; + } return [ 'Array' => [ From 71698884441f6f4807985fff87d5951aded80e22 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Sun, 23 Mar 2025 09:50:41 -0500 Subject: [PATCH 08/11] Minor Adjustments --- src/Psr16/ArrayCacheEngine.php | 12 +++++++--- src/Psr16/BaseCacheEngine.php | 5 +++-- src/Psr16/FileSystemCacheEngine.php | 34 +++++++++++++++-------------- src/Psr16/MemcachedEngine.php | 21 ++++++++++++++++-- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/Psr16/ArrayCacheEngine.php b/src/Psr16/ArrayCacheEngine.php index f5404b1..c9eeb8f 100644 --- a/src/Psr16/ArrayCacheEngine.php +++ b/src/Psr16/ArrayCacheEngine.php @@ -80,15 +80,18 @@ public function get(string $key, mixed $default = null): mixed /** * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. * - * @param string $key The key of the item to store. - * @param mixed $value The value of the item to store, must be serializable. - * @param null|int|DateInterval $ttl Optional. The TTL value of this item. If no value is sent and + * @param string $key The key of the item to store. + * @param mixed $value The value of the item to store, must be serializable. + * @param null|int|DateInterval $ttl Optional. The TTL value of this item. If no value is sent and * the driver supports TTL then the library may set a default value * for it or let the driver take care of that. * * @return bool True on success and false on failure. * * MUST be thrown if the $key string is not a legal value. + * @throws ContainerExceptionInterface + * @throws InvalidArgumentException + * @throws NotFoundExceptionInterface */ #[\Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool @@ -117,6 +120,9 @@ public function clear(): bool * * @param string $key * @return bool + * @throws ContainerExceptionInterface + * @throws InvalidArgumentException + * @throws NotFoundExceptionInterface */ #[\Override] public function delete(string $key): bool diff --git a/src/Psr16/BaseCacheEngine.php b/src/Psr16/BaseCacheEngine.php index ec1c656..8b3ac6f 100644 --- a/src/Psr16/BaseCacheEngine.php +++ b/src/Psr16/BaseCacheEngine.php @@ -85,7 +85,8 @@ protected function addToNow(DateInterval|int|null $ttl): int|null } /** - * @throws InvalidArgumentException + * @param DateInterval|int|null $ttl + * @return DateInterval|int|null */ protected function convertToSeconds(DateInterval|int|null $ttl): DateInterval|int|null { @@ -115,7 +116,7 @@ protected function getKeyFromContainer(string $key): mixed return $this->container->get($key); } - public function withKeysFromContainer(?ContainerInterface $container) + public function withKeysFromContainer(?ContainerInterface $container): static { $this->container = $container; return $this; diff --git a/src/Psr16/FileSystemCacheEngine.php b/src/Psr16/FileSystemCacheEngine.php index ccb7e70..04c8e8b 100644 --- a/src/Psr16/FileSystemCacheEngine.php +++ b/src/Psr16/FileSystemCacheEngine.php @@ -3,10 +3,12 @@ namespace ByJG\Cache\Psr16; use ByJG\Cache\AtomicOperationInterface; +use ByJG\Cache\Exception\InvalidArgumentException; use ByJG\Cache\GarbageCollectorInterface; use Closure; use DateInterval; use Exception; +use Override; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Psr\Log\LoggerInterface; @@ -40,9 +42,9 @@ public function __construct(string $prefix = 'cache', ?string $path = null, ?Log * @return mixed Description * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface - * @throws \ByJG\Cache\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ - #[\Override] + #[Override] public function get(string $key, mixed $default = null): mixed { // Check if file is Locked @@ -71,7 +73,7 @@ public function get(string $key, mixed $default = null): mixed * * MUST be thrown if the $key string is not a legal value. */ - #[\Override] + #[Override] public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool { $fileKey = $this->fixKey($key); @@ -96,7 +98,7 @@ public function set(string $key, mixed $value, DateInterval|int|null $ttl = null * @param string $key * @return bool */ - #[\Override] + #[Override] public function delete(string $key): bool { $this->set($key, null); @@ -106,9 +108,9 @@ public function delete(string $key): bool /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface - * @throws \ByJG\Cache\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ - #[\Override] + #[Override] public function isAvailable(): bool { return is_writable(dirname($this->fixKey('test'))); @@ -117,7 +119,7 @@ public function isAvailable(): bool /** * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface - * @throws \ByJG\Cache\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ protected function fixKey(string $key): string { @@ -135,9 +137,9 @@ protected function fixKey(string $key): string * @return bool True on success and false on failure. * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface - * @throws \ByJG\Cache\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ - #[\Override] + #[Override] public function clear(): bool { $patternKey = $this->fixKey('*'); @@ -161,9 +163,9 @@ public function clear(): bool * @return bool * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface - * @throws \ByJG\Cache\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ - #[\Override] + #[Override] public function has(string $key): bool { $fileKey = $this->fixKey($key); @@ -245,7 +247,7 @@ protected function putContents(string $fileKey, mixed $value, ?int $ttl, ?Closur return $returnValue; } - #[\Override] + #[Override] public function collectGarbage() { $patternKey = $this->fixKey('*'); @@ -264,7 +266,7 @@ public function collectGarbage() } - #[\Override] + #[Override] public function getTtl(string $key): ?int { $fileKey = $this->fixKey($key); @@ -274,7 +276,7 @@ public function getTtl(string $key): ?int return null; } - #[\Override] + #[Override] public function increment(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { return $this->putContents($this->fixKey($key), $value, $ttl, function ($currentValue, $value) { @@ -282,7 +284,7 @@ public function increment(string $key, int $value = 1, DateInterval|int|null $tt }); } - #[\Override] + #[Override] public function decrement(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { return $this->putContents($this->fixKey($key), $value, $ttl, function ($currentValue, $value) { @@ -290,7 +292,7 @@ public function decrement(string $key, int $value = 1, DateInterval|int|null $tt }); } - #[\Override] + #[Override] public function add(string $key, $value, DateInterval|int|null $ttl = null): array { return $this->putContents($this->fixKey($key), $value, $ttl, function ($currentValue, $value) { diff --git a/src/Psr16/MemcachedEngine.php b/src/Psr16/MemcachedEngine.php index 5e7e0f2..37a0e51 100644 --- a/src/Psr16/MemcachedEngine.php +++ b/src/Psr16/MemcachedEngine.php @@ -159,8 +159,7 @@ public function isAvailable(): bool public function clear(): bool { $this->lazyLoadMemCachedServers(); - $result = $this->memCached->flush(); - return $result; + return $this->memCached->flush(); } /** @@ -180,6 +179,12 @@ public function has(string $key): bool return ($this->memCached->getResultCode() === Memcached::RES_SUCCESS); } + /** + * @throws NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws InvalidArgumentException + * @throws StorageErrorException + */ #[\Override] public function increment(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { @@ -200,6 +205,12 @@ public function increment(string $key, int $value = 1, DateInterval|int|null $tt return $result; } + /** + * @throws NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws InvalidArgumentException + * @throws StorageErrorException + */ #[\Override] public function decrement(string $key, int $value = 1, DateInterval|int|null $ttl = null): int { @@ -220,6 +231,12 @@ public function decrement(string $key, int $value = 1, DateInterval|int|null $tt return $result; } + /** + * @throws NotFoundExceptionInterface + * @throws InvalidArgumentException + * @throws ContainerExceptionInterface + * @throws StorageErrorException + */ #[\Override] public function add(string $key, $value, DateInterval|int|null $ttl = null): array { From 4c1271b7ccfa2502de0c5c649c76c235b4978914 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Sat, 23 Aug 2025 18:20:17 -0400 Subject: [PATCH 09/11] GitHub Actions --- src/Psr6/CacheItem.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Psr6/CacheItem.php b/src/Psr6/CacheItem.php index ff193e4..e0f7eb5 100644 --- a/src/Psr6/CacheItem.php +++ b/src/Psr6/CacheItem.php @@ -25,7 +25,7 @@ class CacheItem implements CacheItemInterface protected bool $hit; /** - * @var DateTime + * @var DateTimeInterface */ protected DateTimeInterface $expiration; @@ -85,7 +85,8 @@ public function isHit(): bool public function expiresAt(?DateTimeInterface $expiration): static { if (empty($expiration)) { - $this->expiration = new DateTime('now +1 year'); + // We need to set a especific date far from now + $this->expiration = new DateTime('now +99 year'); return $this; } @@ -98,21 +99,22 @@ public function expiresAt(?DateTimeInterface $expiration): static #[\Override] public function expiresAfter(int|\DateInterval|null $time): static { - $this->expiration = new DateTime('now +1 year'); if (is_numeric($time)) { - $this->expiration = new DateTime('now +' . $time . ' seconds'); + $this->expiresAt(new DateTime('now +' . $time . ' seconds')); } else if ($time instanceof DateInterval) { $expiration = new DateTime(); $expiration->add($time); - $this->expiration = $expiration; + $this->expiresAt($expiration); + } else { + $this->expiresAt(null); } return $this; } /** - * @return DateTime + * @return ?DateTime */ - public function getExpiresAt(): DateTime + public function getExpiresAt(): ?DateTime { return $this->expiration; } From 5bc8da7c06c1acf646c3d538ab6350929b423af3 Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Mon, 3 Nov 2025 19:09:35 -0500 Subject: [PATCH 10/11] Update Documentation --- .gitignore | 2 ++ .run/PSalm.run.xml | 5 ----- .run/psalm.run.xml | 8 +++++++ README.md | 2 +- composer.json | 4 ++++ docs/atomic-operations.md | 20 ++++++++++------- docs/basic-usage-psr16-simplecache.md | 15 +++++++------ docs/basic-usage-psr6-cachepool.md | 12 +++++++---- docs/class-array-cache-engine.md | 10 ++++++--- docs/class-filesystem-cache-engine.md | 21 ++++++++++++------ docs/class-memcached-engine.md | 8 +++++-- docs/class-no-cache-engine.md | 8 +++++-- docs/class-redis-cache-engine.md | 8 +++++-- docs/class-session-cache-engine.md | 8 +++++-- docs/class-shmop-cache-engine.md | 31 ++++++++++++++++++--------- docs/class-tmpfs-cache-engine.md | 21 +++++++++++++----- docs/garbage-collection.md | 21 +++++++++++------- docs/psr11-usage.md | 21 ++++++++++++------ docs/setup-log-handler.md | 21 +++++++++++++++--- psalm.xml | 1 + 20 files changed, 173 insertions(+), 74 deletions(-) delete mode 100644 .run/PSalm.run.xml create mode 100644 .run/psalm.run.xml diff --git a/.gitignore b/.gitignore index 49b94ef..d06da71 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ vendor config/cacheconfig.php .idea .phpunit.result.cache +/phpunit.xml.dist.bak +/.claude/settings.local.json diff --git a/.run/PSalm.run.xml b/.run/PSalm.run.xml deleted file mode 100644 index bd119ce..0000000 --- a/.run/PSalm.run.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.run/psalm.run.xml b/.run/psalm.run.xml new file mode 100644 index 0000000..d9c1b61 --- /dev/null +++ b/.run/psalm.run.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/README.md b/README.md index c334c5f..8631411 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ $cache->set('key', 'value', 3600); // Cache for 1 hour $value = $cache->get('key'); // PSR-6 Cache Pool -$pool = \ByJG\Cache\Factory::createFilesystemPool(); +$pool = \ByJG\Cache\Factory::createFilePool(); $item = $pool->getItem('key'); if (!$item->isHit()) { $item->set('value'); diff --git a/composer.json b/composer.json index 5e7677e..ac9278c 100644 --- a/composer.json +++ b/composer.json @@ -31,5 +31,9 @@ "psr/cache-implementation": "1.0", "psr/simple-cache-implementation": "1.0" }, + "scripts": { + "test": "vendor/bin/phpunit", + "psalm": "vendor/bin/psalm" + }, "license": "MIT" } diff --git a/docs/atomic-operations.md b/docs/atomic-operations.md index 3974673..542b8cf 100644 --- a/docs/atomic-operations.md +++ b/docs/atomic-operations.md @@ -1,20 +1,24 @@ +--- +sidebar_position: 11 +--- + # Atomic Operations Some cache engines allow you to do atomic operations such as incrementing or decrementing a value. -Besides this is not cache operation, it is a common operation in cache engines. +Although this is not a traditional cache operation, it is a common operation in cache engines. -The advantage of using atomic operations is that you can avoid race conditions when multiple processes +The advantage of using atomic operations is that you can avoid race conditions when multiple processes are trying to update the same value. -The atomic operations are: -- Increment: Increment a value by a given number -- Decrement: Decrement a value by a given number -- Add: Add a value to a list in the cache +**Available atomic operations:** +- **Increment**: Increment a value by a given number +- **Decrement**: Decrement a value by a given number +- **Add**: Add a value to a list in the cache -The engines that support atomic operations have to implement the `AtomicOperationInterface`. +The engines that support atomic operations implement the `AtomicOperationInterface`. -Some engines that support atomic operations are: +**Engines that support atomic operations:** - RedisCacheEngine - MemcachedEngine - FileSystemCacheEngine diff --git a/docs/basic-usage-psr16-simplecache.md b/docs/basic-usage-psr16-simplecache.md index 9311580..3850571 100644 --- a/docs/basic-usage-psr16-simplecache.md +++ b/docs/basic-usage-psr16-simplecache.md @@ -1,6 +1,10 @@ -# Basic Usage - Psr16 Simple Cache +--- +sidebar_position: 1 +--- -Psr16 is a standard for cache in PHP with less verbosity than Psr6. +# Basic Usage - PSR-16 Simple Cache + +PSR-16 is a standard for cache in PHP with less verbosity than PSR-6. You can just instantiate the cache engine and use it as you can see below. @@ -11,14 +15,13 @@ You can just instantiate the cache engine and use it as you can see below. $cacheEngine = new \ByJG\Cache\Psr16\FileSystemCacheEngine(); $result = $cacheEngine->get($key); -if (empty($result)) -{ - // Do the operations will be cached +if (empty($result)) { + // Do the operations that will be cached // .... // And set variable result $result = "..."; - // Set the cache: + // Set the cache with 60 seconds TTL: $cacheEngine->set($key, $result, 60); } return $result; diff --git a/docs/basic-usage-psr6-cachepool.md b/docs/basic-usage-psr6-cachepool.md index c5a9c69..db9359f 100644 --- a/docs/basic-usage-psr6-cachepool.md +++ b/docs/basic-usage-psr6-cachepool.md @@ -1,18 +1,22 @@ -# Basic Usage - Psr6 Cache Pool +--- +sidebar_position: 2 +--- -## Get an element from cache (using Factory...) +# Basic Usage - PSR-6 Cache Pool + +## Get an element from cache (using Factory) ```php getItem('mykey'); if (!$item->isHit()) { - // Do the operations will be cached + // Do the operations that will be cached // .... // And set variable '$value' $value = "..."; $item->set($value); - $item->expiresAfter(3600); + $item->expiresAfter(3600); // Cache for 1 hour $pool->save($item); } diff --git a/docs/class-array-cache-engine.md b/docs/class-array-cache-engine.md index 2916f38..4c90b17 100644 --- a/docs/class-array-cache-engine.md +++ b/docs/class-array-cache-engine.md @@ -1,7 +1,11 @@ -# Class ArrayCacheEngine +--- +sidebar_position: 4 +--- -This class is a simple cache engine that uses an array to store the values. -It does not persist between requests. +# ArrayCacheEngine + +This class is a simple cache engine that uses an array to store the values. +It does not persist between requests. It is ideal to use on unit tests or when you need a simple cache engine. diff --git a/docs/class-filesystem-cache-engine.md b/docs/class-filesystem-cache-engine.md index cbde656..24930a8 100644 --- a/docs/class-filesystem-cache-engine.md +++ b/docs/class-filesystem-cache-engine.md @@ -1,6 +1,10 @@ -# Class FilesystemCacheEngine +--- +sidebar_position: 5 +--- -This class uses the Filesystem as the cache engine. +# FileSystemCacheEngine + +This class uses the filesystem as the cache engine. ## Defining the Path @@ -8,23 +12,28 @@ The FileSystemCacheEngine expects a prefix and a path to store the cache files. The prefix is used to avoid collision between different applications using the same cache path. If the path is not defined, the default is the system temporary path. - ## PSR-16 Constructor ```php -$cache = new \ByJG\Cache\Psr16\FileSystemCacheEngine($path, $prefix) +$cache = new \ByJG\Cache\Psr16\FileSystemCacheEngine($prefix, $path, $logger, $createPath); ``` +**Parameters:** +- `$prefix` (string, default: 'cache'): Prefix to avoid cache key collisions +- `$path` (string|null, default: null): Directory path to store cache files (defaults to system temp directory) +- `$logger` (LoggerInterface|null, default: null): PSR-3 logger instance +- `$createPath` (bool, default: false): Whether to create the path if it doesn't exist + ## PSR-6 Constructor ```php -$cachePool = \ByJG\Cache\Factory::createFilePool($path, $prefix, $bufferSize = 10) +$cachePool = \ByJG\Cache\Factory::createFilePool($prefix, $path, $bufferSize, $logger, $createPath); ``` or ```php -$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\FileSystemCacheEngine($path, $prefix)); +$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\FileSystemCacheEngine($prefix, $path)); ``` diff --git a/docs/class-memcached-engine.md b/docs/class-memcached-engine.md index 30831cb..e59e725 100644 --- a/docs/class-memcached-engine.md +++ b/docs/class-memcached-engine.md @@ -1,6 +1,10 @@ -# Class MemcachedEngine +--- +sidebar_position: 6 +--- -This class uses the Memcached as the cache engine. +# MemcachedEngine + +This class uses Memcached as the cache engine. ## Defining the Servers diff --git a/docs/class-no-cache-engine.md b/docs/class-no-cache-engine.md index 81d1841..6356a3e 100644 --- a/docs/class-no-cache-engine.md +++ b/docs/class-no-cache-engine.md @@ -1,6 +1,10 @@ -# Class NoCacheEngine +--- +sidebar_position: 3 +--- -This class don't cache. Use it for disable the cache without change your code. +# NoCacheEngine + +This class doesn't cache. Use it to disable the cache without changing your code. ## PSR-16 Constructor diff --git a/docs/class-redis-cache-engine.md b/docs/class-redis-cache-engine.md index 9b500b7..4f1fa2e 100644 --- a/docs/class-redis-cache-engine.md +++ b/docs/class-redis-cache-engine.md @@ -1,6 +1,10 @@ -# Class RedisCacheEngine +--- +sidebar_position: 7 +--- -This class uses the Redis as the cache engine. +# RedisCacheEngine + +This class uses Redis as the cache engine. ## Defining the Servers diff --git a/docs/class-session-cache-engine.md b/docs/class-session-cache-engine.md index 0ccb8f8..374d1b0 100644 --- a/docs/class-session-cache-engine.md +++ b/docs/class-session-cache-engine.md @@ -1,6 +1,10 @@ -# Class SessionCacheEngine +--- +sidebar_position: 8 +--- -This class uses the PHP Session as the cache engine. +# SessionCacheEngine + +This class uses the PHP Session as the cache engine. This will persist the cache between requests while the user session is active. The cache is not shared between different users. diff --git a/docs/class-shmop-cache-engine.md b/docs/class-shmop-cache-engine.md index 3fad9ae..7518ed6 100644 --- a/docs/class-shmop-cache-engine.md +++ b/docs/class-shmop-cache-engine.md @@ -1,9 +1,17 @@ -# Class ShmopCacheEngine +--- +sidebar_position: 10 +--- -This class uses the PHP Shmop as the cache engine. +# ShmopCacheEngine -The Shared memory allows multiple processes to access the same data in memory. -You can use it to share data among running PHP scripts in the same server. +:::warning Deprecated +This engine is deprecated. Use [TmpfsCacheEngine](class-tmpfs-cache-engine.md) instead for better performance and reliability. +::: + +This class uses PHP Shmop (shared memory) as the cache engine. + +Shared memory allows multiple processes to access the same data in memory. +You can use it to share data among running PHP scripts on the same server. ## Configuration @@ -11,28 +19,31 @@ These are the default values for the configuration: ```php $config = [ - 'max-size' => 524288, // 512Kb - 'default-permission' = > '0700', + 'max-size' => 524288, // 512KB + 'default-permission' => '0700', ]; ``` - ## PSR-16 Constructor ```php -$cache = new \ByJG\Cache\Psr16\ShmopCacheEngine($config, $prefix) +$cache = new \ByJG\Cache\Psr16\ShmopCacheEngine($config, $logger); ``` +**Parameters:** +- `$config` (array, default: []): Configuration options for shared memory +- `$logger` (LoggerInterface|null, default: null): PSR-3 logger instance + ## PSR-6 Constructor ```php -$cachePool = \ByJG\Cache\Factory::createSessionPool($prefix, $bufferSize = 10) +$cachePool = \ByJG\Cache\Factory::createShmopPool($config, $bufferSize, $logger); ``` or ```php -$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\ShmopCacheEngine($config, $prefix)); +$cachePool = new \ByJG\Cache\Psr6\CachePool(new \ByJG\Cache\Psr16\ShmopCacheEngine($config, $logger)); ``` diff --git a/docs/class-tmpfs-cache-engine.md b/docs/class-tmpfs-cache-engine.md index ce2c4c3..fba8a27 100644 --- a/docs/class-tmpfs-cache-engine.md +++ b/docs/class-tmpfs-cache-engine.md @@ -1,22 +1,33 @@ -# Class TmpfsCacheEngine +--- +sidebar_position: 9 +--- -This class uses the Tmpfs as the cache engine. +# TmpfsCacheEngine + +This class uses tmpfs as the cache engine. ## Defining the Path -The TmpfsCacheEngine allows to store the cache files in the `/dev/shm` tmpfs. +The TmpfsCacheEngine stores cache files in the `/dev/shm` tmpfs (temporary file system in RAM). +:::info +This engine extends FileSystemCacheEngine and automatically uses `/dev/shm` as the storage path for better performance. +::: ## PSR-16 Constructor ```php -$cache = new \ByJG\Cache\Psr16\TmpfsCacheEngine($prefix, $logger) +$cache = new \ByJG\Cache\Psr16\TmpfsCacheEngine($prefix, $logger); ``` +**Parameters:** +- `$prefix` (string, default: 'cache'): Prefix to avoid cache key collisions +- `$logger` (LoggerInterface|null, default: null): PSR-3 logger instance + ## PSR-6 Constructor ```php -$cachePool = \ByJG\Cache\Factory::createTmpfsCachePool($prefix, $logger) +$cachePool = \ByJG\Cache\Factory::createTmpfsCachePool($prefix, $logger); ``` or diff --git a/docs/garbage-collection.md b/docs/garbage-collection.md index 3203e5c..ec92dfa 100644 --- a/docs/garbage-collection.md +++ b/docs/garbage-collection.md @@ -1,18 +1,22 @@ +--- +sidebar_position: 12 +--- + # Garbage Collection -Some cache engines need to have a garbage collection process to remove the expired keys. +Some cache engines need to have a garbage collection process to remove expired keys. -In some engines like `Memcached` and `Redis` the garbage collection is done automatically by the engine itself. +In some engines like `Memcached` and `Redis`, the garbage collection is done automatically by the engine itself. -In other engines like `FileSystem` and `Array` there is no such process. The current implementation -is based on the Best Effort. It means an expired key is removed only when you try to access it. +In other engines like `FileSystem` and `Array`, there is no automatic process. The current implementation +is based on best effort, meaning an expired key is removed only when you try to access it. If the cache engine has a low hit rate, it is recommended to run a garbage collection process -to avoid the cache to grow indefinitely. +to prevent the cache from growing indefinitely. The classes that implement the `GarbageCollectorInterface` have the method `collectGarbage()`. -Some engines that support garbage collection are: +**Engines that support garbage collection:** - FileSystemCacheEngine - ArrayCacheEngine - TmpfsCacheEngine (inherits from FileSystemCacheEngine) @@ -25,6 +29,7 @@ Some engines that support garbage collection are: $cache->collectGarbage(); ``` -Note: The garbage collection process is blocking. -It means the process will be slow if you have a lot of keys to remove. +:::caution Performance Warning +The garbage collection process is blocking and will be slow if you have many keys to remove. +::: diff --git a/docs/psr11-usage.md b/docs/psr11-usage.md index 304b039..0ee4681 100644 --- a/docs/psr11-usage.md +++ b/docs/psr11-usage.md @@ -1,20 +1,27 @@ -## Use a PSR-11 container to retrieve the cache keys +--- +sidebar_position: 14 +--- -You can use a PSR-11 compatible to retrieve the cache keys. Once is defined, only the keys defined -in the PSR-11 will be used to cache. +# PSR-11 Container Usage + +You can use a PSR-11 compatible container to retrieve cache keys. Once defined, only the keys defined +in the PSR-11 container will be used for caching. ```php withKeysFromContainer(new SomePsr11Implementation()); ``` -After the PSR-11 container is defined, when I run: +After the PSR-11 container is defined, when you run: ```php $value = $fileCache->get('my-key'); ``` -The key `my-key` will be retrieved from the PSR-11 container and +The key `my-key` will be retrieved from the PSR-11 container, and the value retrieved will be used as the cache key. -If it does not exist in the PSR-11 container, an exception will be thrown. + +:::warning +If the key does not exist in the PSR-11 container, an exception will be thrown. +::: diff --git a/docs/setup-log-handler.md b/docs/setup-log-handler.md index d64a24d..b505b4e 100644 --- a/docs/setup-log-handler.md +++ b/docs/setup-log-handler.md @@ -1,11 +1,26 @@ +--- +sidebar_position: 13 +--- + # Setup Log Handler -You can add a PSR Log compatible to the constructor in order to get Log of the operations. +You can add a PSR-3 compatible logger to the constructor to log cache operations. ## Example ```php pushHandler(new StreamHandler('php://stderr', Logger::DEBUG)); + +// Pass the logger to the cache engine constructor +$cache = new \ByJG\Cache\Psr16\FileSystemCacheEngine('cache', null, $logger); ``` + +:::tip +Most cache engines accept a PSR-3 logger as a constructor parameter. Check the specific engine documentation for the exact parameter position. +::: diff --git a/psalm.xml b/psalm.xml index ebabb1a..b208114 100644 --- a/psalm.xml +++ b/psalm.xml @@ -4,6 +4,7 @@ resolveFromConfigFile="true" findUnusedBaselineEntry="true" findUnusedCode="false" + cacheDirectory="/tmp/psalm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" From 9b56f531be75b9a26750dc00d8874f82982a2a0e Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Tue, 4 Nov 2025 13:47:38 -0500 Subject: [PATCH 11/11] Update Documentation --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ac9278c..d630313 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "require": { "php": ">=8.1 <8.5", "psr/cache": "^1.0|^2.0|^3.0", - "psr/log": "^1.0|^1.1|^2.0", + "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0", "psr/container": "^1.0|^1.1|^2.0" },