From 48724ce47a2d36cfe032b0756c754d14faea8bcb Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 20 Mar 2025 07:32:19 -0500 Subject: [PATCH 1/8] "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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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 {