8000 [Cache] Fix regressions in Psr16Adapter, Psr16Cache · symfony/symfony@48176f6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 48176f6

Browse files
committed
[Cache] Fix regressions in Psr16Adapter, Psr16Cache
1 parent ca1bc5e commit 48176f6

File tree

4 files changed

+160
-3
lines changed

4 files changed

+160
-3
lines changed

src/Symfony/Component/Cache/Adapter/Psr16Adapter.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Cache\Adapter;
1313

1414
use Psr\SimpleCache\CacheInterface;
15+
use Symfony\Component\Cache\CacheItem;
1516
use Symfony\Component\Cache\PruneableInterface;
1617
use Symfony\Component\Cache\ResettableInterface;
1718
use Symfony\Component\Cache\Traits\ProxyTrait;
@@ -40,6 +41,20 @@ public function __construct(CacheInterface $pool, string $namespace = '', int $d
4041
$this->miss = new \stdClass();
4142
}
4243

44+
public function getItem(mixed $key): CacheItem
45+
{
46+
CacheItem::validateKey($key);
47+
48+
return parent::getItem($key);
49+
}
50+
51+
public function getItems(array $keys = []): iterable
52+
{
53+
CacheItem::validateKeys($keys);
54+
55+
return parent::getItems($keys);
56+
}
57+
4358
protected function doFetch(array $ids): iterable
4459
{
4560
foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) {
@@ -64,6 +79,13 @@ protected function doDelete(array $ids): bool
6479
return $this->pool->deleteMultiple($ids);
6580
}
6681

82+
public function deleteItems(array $keys): bool
83+
{
84+
CacheItem::validateKeys($keys);
85+
86+
return parent::deleteItems($keys);
87+
}
88+
6789
protected function doSave(array $values, int $lifetime): array|bool
6890
{
6991
return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime);

src/Symfony/Component/Cache/CacheItem.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,16 @@ public static function validateKey($key, string $reservedChars = self::RESERVED_
143143
return $key;
144144
}
145145

146+
/**
147+
* @param mixed[] $keys The keys to validate
148+
*/
149+
public static function validateKeys(array $keys): void
150+
{
151+
foreach ($keys as $key) {
152+
self::validateKey($key);
153+
}
154+
}
155+
146156
/**
147157
* Internal logging helper.
148158
*

src/Symfony/Component/Cache/Psr16Cache.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) {
4747
if ($allowInt && \is_int($key)) {
4848
$item->key = (string) $key;
4949
} else {
50-
\assert('' !== CacheItem::validateKey($key));
50+
CacheItem::validateKey($key);
5151
$item->key = $key;
5252
}
5353
$item->value = $value;
@@ -79,6 +79,7 @@ static function (CacheItem $item) {
7979

8080
public function get($key, $default = null): mixed
8181
{
82+
CacheItem::validateKey($key);
8283
try {
8384
$item = $this->pool->getItem($key);
8485
} catch (SimpleCacheException $e) {
@@ -96,6 +97,7 @@ public function get($key, $default = null): mixed
9697

9798
public function set($key, $value, $ttl = null): bool
9899
{
100+
CacheItem::validateKey($key);
99101
try {
100102
if (null !== $f = $this->createCacheItem) {
101103
$item = $f($key, $value);
@@ -117,6 +119,8 @@ public function set($key, $value, $ttl = null): bool
117119
public function delete($key): bool
118120
{
119121
try {
122+
CacheItem::validateKey($key);
123+
120124
return $this->pool->deleteItem($key);
121125
} catch (SimpleCacheException $e) {
122126
throw $e;
@@ -139,6 +143,7 @@ public function getMultiple($keys, $default = null): iterable
139143
}
140144

141145
try {
146+
CacheItem::validateKeys($keys);
142147
$items = $this->pool->getItems($keys);
143148
} catch (SimpleCacheException $e) {
144149
throw $e;
@@ -179,14 +184,17 @@ public function setMultiple($values, $ttl = null): bool
179184
} elseif ($valuesIsArray) {
180185
$items = [];
181186
foreach ($values as $key => $value) {
182-
$items[] = (string) $key;
187+
$key = (string) $key;
188+
CacheItem::validateKey($key);
189+
$items[] = $key;
183190
}
184191
$items = $this->pool->getItems($items);
185192
} else {
186193
foreach ($values as $key => $value) {
187194
if (\is_int($key)) {
188195
$key = (string) $key;
189196
}
197+
CacheItem::validateKey($key);
190198
$items[$key] = $this->pool->getItem($key)->set($value);
191199
}
192200
}
@@ -198,6 +206,7 @@ public function setMultiple($values, $ttl = null): bool
198206
$ok = true;
199207

200208
foreach ($items as $key => $item) {
209+
CacheItem::validateKey((string) $key);
201210
if ($valuesIsArray) {
202211
$item->set($values[$key]);
203212
}
@@ -219,6 +228,8 @@ public function deleteMultiple($keys): bool
219228
}
220229

221230
try {
231+
CacheItem::validateKeys($keys);
232+
222233
return $this->pool->deleteItems($keys);
223234
} catch (SimpleCacheException $e) {
224235
throw $e;
@@ -230,6 +241,8 @@ public function deleteMultiple($keys): bool
230241
public function has($key): bool
231242
{
232243
try {
244+
CacheItem::validateKey($key);
245+
233246
return $this->pool->hasItem($key);
234247
} catch (SimpleCacheException $e) {
235248
throw $e;

src/Symfony/Component/Cache/Tests/Adapter/Psr16AdapterTest.php

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
namespace Symfony\Component\Cache\Tests\Adapter;
1313

1414
use Psr\Cache\CacheItemPoolInterface;
15+
use Psr\Log\AbstractLogger;
1516
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1617
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
1718
use Symfony\Component\Cache\Adapter\Psr16Adapter;
19+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
1820
use Symfony\Component\Cache\Psr16Cache;
1921

2022
/**
@@ -29,9 +31,105 @@ class Psr16AdapterTest extends AdapterTestCase
2931
'testClearPrefix' => 'SimpleCache cannot clear by prefix',
3032
];
3133

34+
private TestLogger $testLogger;
35+
3236
public function createCachePool(int $defaultLifetime = 0): CacheItemPoolInterface
3337
{
34-
return new Psr16Adapter(new Psr16Cache(new FilesystemAdapter()), '', $defaultLifetime);
38+
$this->testLogger = new TestLogger();
39+
$psr16Adapter = new Psr16Adapter(new Psr16Cache(new FilesystemAdapter()), '', $defaultLifetime);
40+
$psr16Adapter->setLogger($this->testLogger);
41+
42+
return $psr16Adapter;
43+
}
44+
45+
/**
46+
* @dataProvider invalidKeys
47+
*/
48+
public function testGetItemInvalidKeys($key)
49+
{
50+
if (isset($this->skippedTests[__FUNCTION__])) {
51+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
52+
}
53+
54+
try {
55+
$this->cache->getItem($key);
56+
} catch (\Exception $exception) {
57+
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
58+
59+
return;
60+
}
61+
62+
$this->assertNotEmpty($this->testLogger->records);
63+
$record = $this->testLogger->records[0];
64+
65+
$this->assertSame('warning', $record['level']);
66+
$this->assertSame(sprintf('Failed to fetch key "{key}": Cache key "%s" contains reserved characters "{}()/\\@:".', $key), $record['message']);
67+
$this->assertSame('Symfony\\Component\\Cache\\Adapter\\Psr16Adapter', $record['context']['cache-adapter']);
68+
$this->assertSame($key, $record['context']['key']);
69+
70+
$exception = $record['context']['exception'];
71+
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
72+
$this->assertSame(sprintf('Cache key "%s" contains reserved characters "{}()/\\@:".', $key), $exception->getMessage());
73+
}
74+
75+
/**
76+
* @dataProvider invalidKeys
77+
*/
78+
public function testHasItemInvalidKeys($key)
79+
{
80+
if (isset($this->skippedTests[__FUNCTION__])) {
81+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
82+
}
83+
84+
try {
85+
$this->cache->hasItem($key);
86+
} catch (\Exception $exception) {
87+
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
88+
89+
return;
90+
}
91+
92+
$this->assertNotEmpty($this->testLogger->records);
93+
$record = $this->testLogger->records[0];
94+
95+
$this->assertSame('warning', $record['level']);
96+
$this->assertSame(sprintf('Failed to check if key "{key}" is cached: Cache key "%s" contains reserved characters "{}()/\@:".', $key), $record['message']);
97+
$this->assertSame('Symfony\\Component\\Cache\\Adapter\\Psr16Adapter', $record['context']['cache-adapter']);
98+
$this->assertSame($key, $record['context']['key']);
99+
100+
$exception = $record['context']['exception'];
101+
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
102+
$this->assertSame(sprintf('Cache key "%s" contains reserved characters "{}()/\\@:".', $key), $exception->getMessage());
103+
}
104+
105+
/**
106+
* @dataProvider invalidKeys
107+
*/
108+
public function testDeleteItemInvalidKeys($key)
109+
{
110+
if (isset($this->skippedTests[__FUNCTION__])) {
111+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
112+
}
113+
114+
try {
115+
$this->cache->deleteItem($key);
116+
} catch (\Exception $exception) {
117+
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
118+
119+
return;
120+
}
121+
122+
$this->assertNotEmpty($this->testLogger->records);
123+
$record = $this->testLogger->records[0];
124+
125+
$this->assertSame('warning', $record['level']);
126+
$this->assertSame(sprintf('Failed to delete key "{key}": Cache key "%s" contains reserved characters "{}()/\@:".', $key), $record['message']);
127+
$this->assertSame('Symfony\\Component\\Cache\\Adapter\\Psr16Adapter', $record['context']['cache-adapter']);
128+
$this->assertSame($key, $record['context']['key']);
129+
130+
$exception = $record['context']['exception'];
131+
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
132+
$this->assertSame( A8ED sprintf('Cache key "%s" contains reserved characters "{}()/\\@:".', $key), $exception->getMessage());
35133
}
36134

37135
public function testValidCacheKeyWithNamespace()
@@ -44,3 +142,17 @@ public function testValidCacheKeyWithNamespace()
44142
$this->assertTrue($cache->getItem('my_key')->isHit(), 'Stored item is successfully retrieved.');
45143
}
46144
}
145+
146+
final class TestLogger extends AbstractLogger
147+
{
148+
public array $records = [];
149+
150+
public function log($level, $message, array $context = []): void
151+
{
152+
$this->records[] = [
153+
'level' => $level,
154+
'message' => $message,
155+
'context' => $context,
156+
];
157+
}
158+
}

0 commit comments

Comments
 (0)
0