Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
os: >-
['ubuntu-latest', 'windows-latest']
php: >-
['7.4', '8.0', '8.1']
['8.0', '8.1']
2 changes: 1 addition & 1 deletion .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
os: >-
['ubuntu-latest']
php: >-
['7.4', '8.0', '8.1']
['8.0', '8.1']
6 changes: 2 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Yii FileCache Change Log

## 2.0.0 under development

## 1.0.2 under development

- no changes in this release.

- Chg #44: Raise the minimum `psr/simple-cache` version to `^2.0|^3.0` and the minimum PHP version to `^8.0` (@dehbka)

## 1.0.1 March 23, 2021

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This package implements file-based [PSR-16](https://www.php-fig.org/psr/psr-16/)

## Requirements

- PHP 7.4 or higher.
- PHP 8.0 or higher.

## Installation

Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"source": "https://github.com/yiisoft/cache-file"
},
"require": {
"php": "^7.4|^8.0",
"psr/simple-cache": "^1.0.1"
"php": "^8.0",
"psr/simple-cache": "^2.0|^3.0"
},
"require-dev": {
"php-mock/php-mock-phpunit": "^2.6",
Expand Down
48 changes: 15 additions & 33 deletions src/FileCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@
use function fileowner;
use function fopen;
use function function_exists;
use function gettype;
use function is_dir;
use function is_file;
use function is_iterable;
use function is_string;
use function iterator_to_array;
use function opendir;
use function posix_geteuid;
Expand Down Expand Up @@ -111,7 +108,7 @@ public function __construct(string $cachePath)
$this->cachePath = $cachePath;
}

public function get($key, $default = null)
public function get(string $key, mixed $default = null): mixed
{
$this->validateKey($key);
$file = $this->getCacheFile($key);
Expand All @@ -128,7 +125,7 @@ public function get($key, $default = null)
return unserialize($value);
}

public function set($key, $value, $ttl = null): bool
public function set(string $key, mixed $value, null|int|DateInterval $ttl = null): bool
{
$this->validateKey($key);
$this->gc();
Expand Down Expand Up @@ -163,7 +160,7 @@ public function set($key, $value, $ttl = null): bool
return touch($file, $expiration);
}

public function delete($key): bool
public function delete(string $key): bool
{
$this->validateKey($key);
$file = $this->getCacheFile($key);
Expand All @@ -181,7 +178,7 @@ public function clear(): bool
return true;
}

public function getMultiple($keys, $default = null): iterable
public function getMultiple(iterable $keys, mixed $default = null): iterable
{
$keys = $this->iterableToArray($keys);
$this->validateKeys($keys);
Expand All @@ -194,7 +191,7 @@ public function getMultiple($keys, $default = null): iterable
return $results;
}

public function setMultiple($values, $ttl = null): bool
public function setMultiple(iterable $values, null|int|DateInterval $ttl = null): bool
{
$values = $this->iterableToArray($values);
$this->validateKeys(array_map('\strval', array_keys($values)));
Expand All @@ -206,7 +203,7 @@ public function setMultiple($values, $ttl = null): bool
return true;
}

public function deleteMultiple($keys): bool
public function deleteMultiple(iterable $keys): bool
{
$keys = $this->iterableToArray($keys);
$this->validateKeys($keys);
Expand All @@ -218,7 +215,7 @@ public function deleteMultiple($keys): bool
return true;
}

public function has($key): bool
public function has(string $key): bool
{
$this->validateKey($key);
return $this->existsAndNotExpired($this->getCacheFile($key));
Expand Down Expand Up @@ -296,11 +293,11 @@ public function withGcProbability(int $gcProbability): self
/**
* Converts TTL to expiration.
*
* @param DateInterval|int|null $ttl
* @param DateInterval|int|string|null $ttl
*
* @return int
*/
private function ttlToExpiration($ttl): int
private function ttlToExpiration(null|int|string|DateInterval $ttl = null): int
{
$ttl = $this->normalizeTtl($ttl);

Expand All @@ -322,7 +319,7 @@ private function ttlToExpiration($ttl): int
*
* @return int|null TTL value as UNIX timestamp or null meaning infinity
*/
private function normalizeTtl($ttl): ?int
private function normalizeTtl(null|int|string|DateInterval $ttl = null): ?int
{
if ($ttl === null) {
return null;
Expand Down Expand Up @@ -365,7 +362,7 @@ private function getCacheFile(string $key): string
$base = $this->cachePath;

for ($i = 0; $i < $this->directoryLevel; ++$i) {
if (($prefix = substr($key, $i + $i, 2)) !== false) {
if (($prefix = substr($key, $i + $i, 2)) !== '') {
$base .= DIRECTORY_SEPARATOR . $prefix;
}
}
Expand Down Expand Up @@ -421,31 +418,20 @@ private function gc(): void
}
}

/**
* @param mixed $key
*/
private function validateKey($key): void
private function validateKey(string $key): void
{
if (!is_string($key) || $key === '' || strpbrk($key, '{}()/\@:')) {
if ($key === '' || strpbrk($key, '{}()/\@:')) {
throw new InvalidArgumentException('Invalid key value.');
}
}

/**
* @param array $keys
*/
private function validateKeys(array $keys): void
{
foreach ($keys as $key) {
$this->validateKey($key);
}
}

/**
* @param string $file
*
* @return bool
*/
private function existsAndNotExpired(string $file): bool
{
return is_file($file) && @filemtime($file) > time();
Expand All @@ -454,16 +440,12 @@ private function existsAndNotExpired(string $file): bool
/**
* Converts iterable to array. If provided value is not iterable it throws an InvalidArgumentException.
*
* @param mixed $iterable
* @param iterable $iterable
*
* @return array
*/
private function iterableToArray($iterable): array
private function iterableToArray(iterable $iterable): array
{
if (!is_iterable($iterable)) {
throw new InvalidArgumentException('Iterable is expected, got ' . gettype($iterable));
}

/** @psalm-suppress RedundantCast */
return $iterable instanceof Traversable ? iterator_to_array($iterable) : (array) $iterable;
}
Expand Down
40 changes: 0 additions & 40 deletions tests/FileCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use phpmock\phpunit\PHPMock;
use Psr\SimpleCache\InvalidArgumentException;
use ReflectionException;
use stdClass;
use Yiisoft\Cache\File\CacheException;
use Yiisoft\Cache\File\FileCache;
use Yiisoft\Cache\File\MockHelper;
Expand Down Expand Up @@ -522,12 +521,6 @@ public function testConstructorThrowExceptionForInvalidCacheDirectory(): void
public function invalidKeyProvider(): array
{
return [
'int' => [1],
'float' => [1.1],
'null' => [null],
'bool' => [true],
'object' => [new stdClass()],
'callable' => [fn () => 'key'],
'psr-reserved' => ['{}()/\@:'],
'empty-string' => [''],
];
Expand Down Expand Up @@ -577,28 +570,6 @@ public function testGetMultipleThrowExceptionForInvalidKeys($key): void
$this->cache->getMultiple([$key]);
}

/**
* @dataProvider invalidKeyProvider
*
* @param mixed $key
*/
public function testGetMultipleThrowExceptionForInvalidKeysNotIterable($key): void
{
$this->expectException(InvalidArgumentException::class);
$this->cache->getMultiple($key);
}

/**
* @dataProvider invalidKeyProvider
*
* @param mixed $key
*/
public function testSetMultipleThrowExceptionForInvalidKeysNotIterable($key): void
{
$this->expectException(InvalidArgumentException::class);
$this->cache->setMultiple($key);
}

/**
* @dataProvider invalidKeyProvider
*
Expand All @@ -610,17 +581,6 @@ public function testDeleteMultipleThrowExceptionForInvalidKeys($key): void
$this->cache->deleteMultiple([$key]);
}

/**
* @dataProvider invalidKeyProvider
*
* @param mixed $key
*/
public function testDeleteMultipleThrowExceptionForInvalidKeysNotIterable($key): void
{
$this->expectException(InvalidArgumentException::class);
$this->cache->deleteMultiple($key);
}

/**
* @dataProvider invalidKeyProvider
*
Expand Down
8 changes: 4 additions & 4 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
*
* @return mixed
*/
protected function invokeMethod(object $object, string $method, array $args = [], bool $revoke = true)
protected function invokeMethod(object $object, string $method, array $args = [], bool $revoke = true): mixed
{
$reflection = new ReflectionObject($object);
$method = $reflection->getMethod($method);
Expand Down Expand Up @@ -76,7 +76,7 @@ protected function setInaccessibleProperty(object $object, string $propertyName,
*
* @return mixed
*/
protected function getInaccessibleProperty(object $object, string $propertyName, bool $revoke = true)
protected function getInaccessibleProperty(object $object, string $propertyName, bool $revoke = true): mixed
{
$class = new ReflectionClass($object);

Expand Down Expand Up @@ -116,7 +116,7 @@ public function dataProvider(): array
];
}

public function getDataProviderData($keyPrefix = ''): array
public function getDataProviderData(string $keyPrefix = ''): array
{
$data = [];

Expand Down Expand Up @@ -149,7 +149,7 @@ public function prepare(CacheInterface $cache): CacheInterface
return $cache;
}

public function assertSameExceptObject($expected, $actual): void
public function assertSameExceptObject(mixed $expected, mixed $actual): void
{
// assert for all types
$this->assertEquals($expected, $actual);
Expand Down