Skip to content

Commit

Permalink
Upgrade to simple cache 2 & 3 (#11)
Browse files Browse the repository at this point in the history
* Updated PHP requirement to >=8.0 and replaced test versions with 8.0 & 8.1

* Updated codeception to ^5

* Updated simple-cache to ^2||^3

* Removed mindplay/simple-cache dev-dependency

* Updated FileCache::get signature

* Updated FileCache::set signature

* Updated FileCache::delete signature

* Updated FileCache::clear signature

* Updated FileCache::getMultiple signature

* Updated FileCache::setMultiple signature

* Updated FileCache::deleteMultiple signature

* Updated FileCache::has signature

* Changed expected throwables from `InvalidArgumentException` to `TypeError` where necessary

* Removed unnecessary throw statements, these errors will be caught by PHPs type checks

* Updated FileCacheIntegrationTest to resolve errors produced by the new typehints

* Removed mindplay/simple-cache dev-dependency

* Replaced Travis with Github Actions
  • Loading branch information
vortrixs committed Aug 24, 2022
1 parent ba75331 commit dcd68ed
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 33 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"require": {
"php": ">= 8.0",
"psr/simple-cache": "^1"
"psr/simple-cache": "^2||^3"
},
"require-dev": {
"codeception/codeception": "^5",
Expand Down
38 changes: 13 additions & 25 deletions src/FileCache.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
<?php

declare(strict_types=1);

namespace Kodus\Cache;

use DateInterval;
use function file_exists;
use FilesystemIterator;
use Generator;
use function gettype;
use function is_int;
use Psr\SimpleCache\CacheInterface;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Traversable;

/**
* This class implements a simple, file-based cache.
Expand Down Expand Up @@ -50,6 +48,8 @@ class FileCache implements CacheInterface
* @param int $default_ttl default time-to-live (in seconds)
* @param int $dir_mode permission mode for created dirs
* @param int $file_mode permission mode for created files
*
* @throws InvalidArgumentException
*/
public function __construct($cache_path, $default_ttl, $dir_mode = 0775, $file_mode = 0664)
{
Expand All @@ -74,7 +74,7 @@ public function __construct($cache_path, $default_ttl, $dir_mode = 0775, $file_m
$this->cache_path = $path;
}

public function get($key, $default = null)
public function get(string $key, mixed $default = null): mixed
{
$path = $this->getPath($key);

Expand Down Expand Up @@ -109,7 +109,7 @@ public function get($key, $default = null)
return $value;
}

public function set($key, $value, $ttl = null)
public function set(string $key, mixed $value, DateInterval|int|null $ttl = null): bool
{
$path = $this->getPath($key);

Expand All @@ -125,7 +125,7 @@ public function set($key, $value, $ttl = null)
if (is_int($ttl)) {
$expires_at = $this->getTime() + $ttl;
} elseif ($ttl instanceof DateInterval) {
$expires_at = date_create_from_format("U", $this->getTime())->add($ttl)->getTimestamp();
$expires_at = date_create_from_format("U", (string) $this->getTime())->add($ttl)->getTimestamp();
} elseif ($ttl === null) {
$expires_at = $this->getTime() + $this->default_ttl;
} else {
Expand All @@ -149,7 +149,7 @@ public function set($key, $value, $ttl = null)
return false;
}

public function delete($key)
public function delete(string $key): bool
{
$this->validateKey($key);

Expand All @@ -158,7 +158,7 @@ public function delete($key)
return !file_exists($path) || @unlink($path);
}

public function clear()
public function clear(): bool
{
$success = true;

Expand All @@ -173,12 +173,8 @@ public function clear()
return $success;
}

public function getMultiple($keys, $default = null)
public function getMultiple(iterable $keys, mixed $default = null): iterable
{
if (! is_array($keys) && ! $keys instanceof Traversable) {
throw new InvalidArgumentException("keys must be either of type array or Traversable");
}

$values = [];

foreach ($keys as $key) {
Expand All @@ -188,12 +184,8 @@ public function getMultiple($keys, $default = null)
return $values;
}

public function setMultiple($values, $ttl = null)
public function setMultiple(iterable $values, DateInterval|int|null $ttl = null): bool
{
if (! is_array($values) && ! $values instanceof Traversable) {
throw new InvalidArgumentException("keys must be either of type array or Traversable");
}

$ok = true;

foreach ($values as $key => $value) {
Expand All @@ -209,12 +201,8 @@ public function setMultiple($values, $ttl = null)
return $ok;
}

public function deleteMultiple($keys)
public function deleteMultiple(iterable $keys): bool
{
if (! is_array($keys) && ! $keys instanceof Traversable) {
throw new InvalidArgumentException("keys must be either of type array or Traversable");
}

$ok = true;

foreach ($keys as $key) {
Expand All @@ -226,7 +214,7 @@ public function deleteMultiple($keys)
return $ok;
}

public function has($key)
public function has(string $key): bool
{
return $this->get($key, $this) !== $this;
}
Expand Down
7 changes: 4 additions & 3 deletions tests/integration/FileCacheCest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use IntegrationTester;
use Kodus\Cache\InvalidArgumentException;
use Kodus\Cache\Test\TestableFileCache;
use TypeError;

class FileCacheCest
{
Expand Down Expand Up @@ -187,11 +188,11 @@ public function testGetAndSetMultiple(IntegrationTester $I)

$I->assertSame(["key1" => "value1", "key2" => "value2", "key3" => false], $results);

$I->expectThrowable(InvalidArgumentException::class, function () {
$I->expectThrowable(TypeError::class, function () {
$this->cache->getMultiple("Invalid type");
});

$I->expectThrowable(InvalidArgumentException::class, function () {
$I->expectThrowable(TypeError::class, function () {
$this->cache->setMultiple("Invalid type");
});

Expand All @@ -214,7 +215,7 @@ public function testDeleteMultiple(IntegrationTester $I)

$I->assertSame("value3", $this->cache->get("key3"));

$I->expectThrowable(InvalidArgumentException::class, function () {
$I->expectThrowable(TypeError::class, function () {
$this->cache->deleteMultiple("Invalid type");
});

Expand Down
170 changes: 166 additions & 4 deletions tests/integration/FileCacheIntegrationTest.php
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
<?php

declare(strict_types=1);

namespace Kodus\Cache\Test\Integration;

use function assert;
use Cache\IntegrationTests\SimpleCacheTest;
use Codeception\Util\FileSystem;
use function dirname;
use function file_exists;
use function is_writable;
use Kodus\Cache\FileCache;
use TypeError;

class FileCacheIntegrationTest extends SimpleCacheTest
{
const DEFAULT_EXPIRATION = 86400;
const DIR_MODE = 0775;
const FILE_MODE = 0664;

protected $skippedTests = [
'testGetInvalidKeys' => 'New simple-cache v3 type hints break the test. FileCacheIntegrationTest contains updated versions.',
'testGetMultipleInvalidKeys' => 'New simple-cache v3 type hints break the test. FileCacheIntegrationTest contains updated versions.',
'testSetInvalidKeys' => 'New simple-cache v3 type hints break the test. FileCacheIntegrationTest contains updated versions.',
'testHasInvalidKeys' => 'New simple-cache v3 type hints break the test. FileCacheIntegrationTest contains updated versions.',
'testDeleteInvalidKeys' => 'New simple-cache v3 type hints break the test. FileCacheIntegrationTest contains updated versions.',
];

public function createSimpleCache()
{
$path = dirname(__DIR__) . "/_output/cache";
Expand All @@ -30,4 +37,159 @@ public function createSimpleCache()

return $cache;
}

/**
* @dataProvider invalidStringKeys
*/
public function testGetInvalidStringKeys($key)
{
$this->expectException('Psr\SimpleCache\InvalidArgumentException');
$this->cache->get($key);
}

/**
* @dataProvider invalidNonStringKeys
*/
public function testGetInvalidNonStringKeys($key)
{
$this->expectException(TypeError::class);
$this->cache->get($key);
}

/**
* @dataProvider invalidStringKeys
*/
public function testGetMultipleInvalidStringKeys($key)
{
$this->expectException('Psr\SimpleCache\InvalidArgumentException');
$this->cache->getMultiple(['key1', $key, 'key2']);
}

/**
* @dataProvider invalidNonStringKeys
*/
public function testGetMultipleInvalidNonStringKeys($key)
{
$this->expectException(TypeError::class);
$this->cache->getMultiple(['key1', $key, 'key2']);
}

public function testGetMultipleNoIterable()
{
$this->expectException(TypeError::class);
$this->cache->getMultiple('key');
}

/**
* @dataProvider invalidStringKeys
*/
public function testSetInvalidStringKeys($key)
{
$this->expectException('Psr\SimpleCache\InvalidArgumentException');
$this->cache->set($key, 'foobar');
}

/**
* @dataProvider invalidNonStringKeys
*/
public function testSetInvalidNonStringKeys($key)
{
$this->expectException(TypeError::class);
$this->cache->set($key, 'foobar');
}

public function testSetMultipleNoIterable()
{
$this->expectException(TypeError::class);
$this->cache->setMultiple('key');
}

/**
* @dataProvider invalidStringKeys
*/
public function testHasInvalidStringKeys($key)
{
$this->expectException('Psr\SimpleCache\InvalidArgumentException');
$this->cache->has($key);
}
/**
* @dataProvider invalidNonStringKeys
*/
public function testHasInvalidNonStringKeys($key)
{
$this->expectException(TypeError::class);
$this->cache->has($key);
}

/**
* @dataProvider invalidStringKeys
*/
public function testDeleteInvalidStringKeys($key)
{
$this->expectException('Psr\SimpleCache\InvalidArgumentException');
$this->cache->delete($key);
}

/**
* @dataProvider invalidNonStringKeys
*/
public function testDeleteInvalidNonStringKeys($key)
{
$this->expectException(TypeError::class);
$this->cache->delete($key);
}


public function testDeleteMultipleNoIterable()
{
$this->expectException(TypeError::class);
$this->cache->deleteMultiple('key');
}

/**
* @dataProvider invalidTtl
*/
public function testSetInvalidTtl($ttl)
{
$this->expectException(TypeError::class);
$this->cache->set('key', 'value', $ttl);
}

/**
* @dataProvider invalidTtl
*/
public function testSetMultipleInvalidTtl($ttl)
{
$this->expectException(TypeError::class);
$this->cache->setMultiple(['key' => 'value'], $ttl);
}

public static function invalidNonStringKeys()
{
return [
[true],
[false],
[null],
[2.5],
[new \stdClass()],
[['array']],
];
}

public static function invalidStringKeys()
{
return [
[''],
['{str'],
['rand{'],
['rand{str'],
['rand}str'],
['rand(str'],
['rand)str'],
['rand/str'],
['rand\\str'],
['rand@str'],
['rand:str'],
];
}
}

0 comments on commit dcd68ed

Please sign in to comment.