Skip to content

Commit 153144c

Browse files
committed
Add SimpleCache
1 parent b2932ec commit 153144c

File tree

9 files changed

+355
-13
lines changed

9 files changed

+355
-13
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"require": {
1616
"php": ">=8.2",
1717
"ingenioz-it/clock": "^1.0",
18-
"psr/cache": "^3.0"
18+
"psr/cache": "^3.0",
19+
"psr/simple-cache": "^3.0"
1920
},
2021
"require-dev": {
2122
"phpunit/phpunit": "*",

src/CacheException.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
use Exception;
88
use Psr\Cache\CacheException as PsrCacheException;
9+
use Psr\SimpleCache\CacheException as PsrSimpleCacheException;
910

10-
class CacheException extends Exception implements PsrCacheException
11+
class CacheException extends Exception implements PsrCacheException, PsrSimpleCacheException
1112
{
1213
}

src/CacheItem.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,16 @@ public function __construct(
1717
private ?DateTimeInterface $expirationDate,
1818
private readonly ClockInterface $clock,
1919
) {
20+
self::validateKey($key);
21+
}
22+
23+
public static function validateKey(string $key): void
24+
{
25+
if (empty($key)) {
26+
throw new InvalidArgumentException('Key must not be empty');
27+
}
2028
if (strpbrk($key, '{}()/\\@:') !== false) {
21-
throw new InvalidArgumentException("Invalid key: {$key}");
29+
throw new InvalidArgumentException("Invalid key: $key");
2230
}
2331
}
2432

src/FileCacheItemPool.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ public function getItems(array $keys = []): iterable
5555
return $items;
5656
}
5757

58+
/**
59+
* @SuppressWarnings(PHPMD.StaticAccess)
60+
*/
5861
public function hasItem(string $key): bool
5962
{
60-
if (empty($key)) {
61-
throw new InvalidArgumentException('Key must be a string');
62-
}
63+
CacheItem::validateKey($key);
6364
return file_exists($this->getFilePath($key));
6465
}
6566

src/InvalidArgumentException.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
namespace IngeniozIT\Cache;
66

7-
use Psr\Cache\InvalidArgumentException as PsrInvalidArgumentException;
7+
use Psr\Cache\InvalidArgumentException as PsrCacheInvalidArgumentException;
8+
use Psr\SimpleCache\InvalidArgumentException as PsrSimpleCacheInvalidArgumentException;
89

9-
final class InvalidArgumentException extends CacheException implements PsrInvalidArgumentException
10+
final class InvalidArgumentException extends CacheException implements PsrCacheInvalidArgumentException, PsrSimpleCacheInvalidArgumentException
1011
{
1112
}

src/MemoryCacheItemPool.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ public function getItems(array $keys = []): iterable
4040
return $items;
4141
}
4242

43+
/**
44+
* @SuppressWarnings(PHPMD.StaticAccess)
45+
*/
4346
public function hasItem(string $key): bool
4447
{
45-
if (empty($key)) {
46-
throw new InvalidArgumentException('Key must be a string');
47-
}
48-
return isset($this->items[$key]);
48+
CacheItem::validateKey($key);
49+
return isset($this->items[$key]) && $this->items[$key]->isHit();
4950
}
5051

5152
public function clear(): bool
@@ -59,9 +60,10 @@ public function deleteItem(string $key): bool
5960
{
6061
if ($this->hasItem($key)) {
6162
unset($this->items[$key]);
63+
return true;
6264
}
6365

64-
return true;
66+
return false;
6567
}
6668

6769
/**

src/SimpleCache.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace IngeniozIT\Cache;
6+
7+
use Psr\SimpleCache\CacheInterface;
8+
use Psr\Cache\CacheItemPoolInterface;
9+
use DateInterval;
10+
11+
final readonly class SimpleCache implements CacheInterface
12+
{
13+
public function __construct(
14+
private CacheItemPoolInterface $pool,
15+
) {
16+
}
17+
18+
public function get(string $key, mixed $default = null): mixed
19+
{
20+
$item = $this->pool->getItem($key);
21+
return $item->isHit() ? $item->get() : $default;
22+
}
23+
24+
public function set(string $key, mixed $value, int|DateInterval|null $ttl = null): bool
25+
{
26+
$item = $this->pool->getItem($key);
27+
$item->set($value);
28+
$item->expiresAfter($ttl);
29+
return $this->pool->save($item);
30+
}
31+
32+
public function delete(string $key): bool
33+
{
34+
return $this->pool->deleteItem($key);
35+
}
36+
37+
public function clear(): bool
38+
{
39+
return $this->pool->clear();
40+
}
41+
42+
/**
43+
* @param iterable<string> $keys
44+
* @return array<string, mixed>
45+
*/
46+
public function getMultiple(iterable $keys, mixed $default = null): iterable
47+
{
48+
$values = [];
49+
foreach ($keys as $key) {
50+
$item = $this->pool->getItem($key);
51+
$values[$key] = $item->isHit() ? $item->get() : $default;
52+
}
53+
return $values;
54+
}
55+
56+
/**
57+
* @param iterable<string, mixed> $values
58+
*/
59+
public function setMultiple(iterable $values, int|DateInterval|null $ttl = null): bool
60+
{
61+
foreach ($values as $key => $value) {
62+
$item = $this->pool->getItem($key);
63+
$item->set($value);
64+
$item->expiresAfter($ttl);
65+
$this->pool->saveDeferred($item);
66+
}
67+
return $this->pool->commit();
68+
}
69+
70+
public function deleteMultiple(iterable $keys): bool
71+
{
72+
$success = true;
73+
foreach ($keys as $key) {
74+
if (!$this->pool->deleteItem($key)) {
75+
$success = false;
76+
}
77+
}
78+
return $success;
79+
}
80+
81+
public function has(string $key): bool
82+
{
83+
return $this->pool->hasItem($key);
84+
}
85+
}

tests/CacheItemPoolTestAbstract.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,49 @@ public function testDoesNotSaveOutdatedItems(): void
219219
self::assertFalse($saved);
220220
self::assertFalse($hasItem1);
221221
}
222+
223+
/**
224+
* @dataProvider invalidKeysScenariosProvider
225+
*/
226+
public function testCannotUseInvalidKeys(callable $scenario): void
227+
{
228+
$cache = $this->getPool();
229+
230+
$this->expectException(InvalidArgumentException::class);
231+
$scenario($cache);
232+
}
233+
234+
/**
235+
* @return array<string, array{0: callable}>
236+
*/
237+
public static function invalidKeysScenariosProvider(): array
238+
{
239+
return [
240+
'getItem' => [
241+
function (CacheItemPoolInterface $cache) {
242+
$cache->getItem('{invalidKey}');
243+
},
244+
],
245+
'getItems' => [
246+
function (CacheItemPoolInterface $cache) {
247+
$cache->getItems(['{invalidKey}']);
248+
},
249+
],
250+
'hasItem' => [
251+
function (CacheItemPoolInterface $cache) {
252+
$cache->hasItem('{invalidKey}');
253+
},
254+
],
255+
'deleteItem' => [
256+
function (CacheItemPoolInterface $cache) {
257+
$cache->deleteItem('{invalidKey}');
258+
},
259+
],
260+
'deleteItems' => [
261+
function (CacheItemPoolInterface $cache) {
262+
$cache->deleteItems(['{invalidKey}']);
263+
},
264+
],
265+
];
266+
}
222267
}

0 commit comments

Comments
 (0)