8000 [Cache] remove deprecated PSR-16 implementations et al. · symfony/symfony@9eed8d6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9eed8d6

Browse files
[Cache] remove deprecated PSR-16 implementations et al.
1 parent 2a631ec commit 9eed8d6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1611
-4904
lines changed

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

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,112 @@
1111

1212
namespace Symfony\Component\Cache\Adapter;
1313

14-
use Symfony\Component\Cache\Traits\ApcuTrait;
14+
use Symfony\Component\Cache\CacheItem;
15+
use Symfony\Component\Cache\Exception\CacheException;
1516

17+
/**
18+
* @author Nicolas Grekas <p@tchwork.com>
19+
*/
1620
class ApcuAdapter extends AbstractAdapter
1721
{
18-
use ApcuTrait;
19-
2022
/**
2123
* @throws CacheException if APCu is not enabled
2224
*/
2325
public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null)
2426
{
25-
$this->init($namespace, $defaultLifetime, $version);
27+
if (!static::isSupported()) {
28+
throw new CacheException('APCu is not enabled');
29+
}
30+
if ('cli' === \PHP_SAPI) {
31+
ini_set('apc.use_request_time', 0);
32+
}
33+
parent::__construct($namespace, $defaultLifetime);
34+
35+
if (null !== $version) {
36+
CacheItem::validateKey($version);
37+
38+
if (!apcu_exists($version.'@'.$namespace)) {
39+
$this->doClear($namespace);
40+
apcu_add($version.'@'.$namespace, null);
41+
}
42+
}
43+
}
44+
45+
public static function isSupported()
46+
{
47+
return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN);
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
protected function doFetch(array $ids)
54+
{
55+
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
56+
try {
57+
$values = [];
58+
foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) {
59+
if (null !== $v || $ok) {
60+
$values[$k] = $v;
61+
}
62+
}
63+
64+
return $values;
65+
} catch (\Error $e) {
66+
throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
67+
} finally {
68+
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
69+
}
70+
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
protected function doHave($id)
76+
{
77+
return apcu_exists($id);
78+
}
79+
80+
/**
81+
* {@inheritdoc}
82+
*/
83+
protected function doClear($namespace)
84+
{
85+
return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== \PHP_SAPI || filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN))
86+
? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY))
87+
: apcu_clear_cache();
88+
}
89+
90+
/**
91+
* {@inheritdoc}
92+
*/
93+
protected function doDelete(array $ids)
94+
{
95+
foreach ($ids as $id) {
96+
apcu_delete($id);
97+
}
98+
99+
return true;
100+
}
101+
102+
/**
103+
* {@inheritdoc}
104+
*/
105+
protected function doSave(array $values, $lifetime)
106+
{
107+
try {
108+
if (false === $failures = apcu_store($values, null, $lifetime)) {
109+
$failures = $values;
110+
}
111+
112+
return array_keys($failures);
113+
} catch (\Throwable $e) {
114+
if (1 === \count($values)) {
115+
// Workaround https://github.com/krakjoe/apcu/issues/170
116+
apcu_delete(key($values));
117+
}
118+
119+
throw $e;
120+
}
26121
}
27122
}

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

Lines changed: 143 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Psr\Cache\CacheItemInterface;
1515
use Psr\Log\LoggerAwareInterface;
16+
use Psr\Log\LoggerAwareTrait;
1617
use Symfony\Component\Cache\CacheItem;
1718
use Symfony\Component\Cache\ResettableInterface;
1819
use Symfony\Component\Cache\Traits\ArrayTrait;
@@ -23,8 +24,11 @@
2324
*/
2425
class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
2526
{
26-
use ArrayTrait;
27+
use LoggerAwareTrait;
2728

29+
private $storeSerialized;
30+
private $values = [];
31+
private $expiries = [];
2832
private $createCacheItem;
2933

3034
/**
@@ -65,6 +69,27 @@ public function get(string $key, callable $callback, float $beta = null, array &
6569
return $item->get();
6670
}
6771

72+
/**
73+
* {@inheritdoc}
74+
*/
75+
public function delete(string $key): bool
76+
{
77+
return $this->deleteItem($key);
78+
}
79+
80+
/**
81+
* {@inheritdoc}
82+
*/
83+
public function hasItem($key)
84+
{
85+
if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) {
86+
return true;
87+
}
88+
CacheItem::validateKey($key);
89+
90+
return isset($this->expiries[$key]) && !$this->deleteItem($key);
91+
}
92+
6893
/**
6994
* {@inheritdoc}
7095
*/
@@ -94,6 +119,19 @@ public function getItems(array $keys = [])
94119
return $this->generateItems($keys, microtime(true), $this->createCacheItem);
95120
}
96121

122+
/**
123+
* {@inheritdoc}
124+
*/
125+
public function deleteItem($key)
126+
{
127+
if (!\is_string($key) || !isset($this->expiries[$key])) {
128+
CacheItem::validateKey($key);
129+
}
130+
unset($this->values[$key], $this->expiries[$key]);
131+
132+
return true;
133+
}
134+
97135
/**
98136
* {@inheritdoc}
99137
*/
@@ -156,8 +194,110 @@ public function commit()
156194
/**
157195
* {@inheritdoc}
158196
*/
159-
public function delete(string $key): bool
197+
public function clear()
160198
{
161-
return $this->deleteItem($key);
199+
$this->values = $this->expiries = [];
200+
201+
return true;
202+
}
203+
204+
/**
205+
* Returns all cached values, with cache miss as null.
206+
*
207+
* @return array
208+
*/
209+
public function getValues()
210+
{
211+
if (!$this->storeSerialized) {
212+
return $this->values;
213+
}
214+
215+
$values = $this->values;
216+
foreach ($values as $k => $v) {
217+
if (null === $v || 'N;' === $v) {
218+
continue;
219+
}
220+
if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) {
221+
$values[$k] = serialize($v);
222+
}
223+
}
224+
225+
return $values;
226+
}
227+
228+
/**
229+
* {@inheritdoc}
230+
*/
231+
public function reset()
232+
{
233+
$this->clear();
234+
}
235+
236+
private function generateItems(array $keys, $now, $f)
237+
{
238+
foreach ($keys as $i => $key) {
239+
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
240+
$this->values[$key] = $value = null;
241+
} else {
242+
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
243+
}
244+
unset($keys[$i]);
245+
246+
yield $key => $f($key, $value, $isHit);
247+
}
248+
249+
foreach ($keys as $key) {
250+
yield $key => $f($key, null, false);
251+
}
252+
}
253+
254+
private function freeze($value, $key)
255+
{
256+
if (null === $value) {
257+
return 'N;';
258+
}
259+
if (\is_string($value)) {
260+
// Serialize strings if they could be confused with serialized objects or arrays
261+
if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) {
262+
return serialize($value);
263+
}
264+
} elseif (!\is_scalar($value)) {
265+
try {
266+
$serialized = serialize($value);
267+
} catch (\Exception $e) {
268+
$type = \is_object($value) ? \get_class($value) : \gettype($value);
269+
$message = sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage());
270+
CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e]);
271+
272+
return;
273+
}
274+
// Keep value serialized if it contains any objects or any internal references
275+
if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) {
276+
return $serialized;
277+
}
278+
}
279+
280+
return $value;
281+
}
282+
283+
private function unfreeze(string $key, bool &$isHit)
284+
{
285+
if ('N;' === $value = $this->values[$key]) {
286+
return null;
287+
}
288+
if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
289+
try {
290+
$value = unserialize($value);
291+
} catch (\Exception $e) {
292+
CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]);
293+
$value = false;
294+
}
295+
if (false === $value) {
296+
$this->values[$key] = $value = null;
297+
$isHit = false;
298+
}
299+
}
300+
301+
return $value;
162302
}
163303
}

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

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,94 @@
1212
namespace Symfony\Component\Cache\Adapter;
1313

1414
use Doctrine\Common\Cache\CacheProvider;
15-
use Symfony\Component\Cache\Traits\DoctrineTrait;
1615

16+
/**
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
1719
class DoctrineAdapter extends AbstractAdapter
1820
{
19-
use DoctrineTrait;
21+
private $provider;
2022

2123
public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0)
2224
{
2325
parent::__construct('', $defaultLifetime);
2426
$this->provider = $provider;
2527
$provider->setNamespace($namespace);
2628
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function reset()
34+
{
35+
parent::reset();
36+
$this->provider->setNamespace($this->provider->getNamespace());
37+
}
38+
39+
/**
40+
* {@inheritdoc}
41+
*/
42+
protected function doFetch(array $ids)
43+
{
44+
$unserializeCallbackHandler = ini_set('unserialize_callback_func', parent::class.'::handleUnserializeCallback');
45+
try {
46+
return $this->provider->fetchMultiple($ids);
47+
} catch (\Error $e) {
48+
$trace = $e->getTrace();
49+
50+
if (isset($trace[0]['function']) && !isset($trace[0]['class'])) {
51+
switch ($trace[0]['function']) {
52+
case 'unserialize':
53+
case 'apcu_fetch':
54+
case 'apc_fetch':
55+
throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
56+
}
57+
}
58+
59+
throw $e;
60+
} finally {
61+
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
62+
}
63+
}
64+
65+
/**
66+
* {@inheritdoc}
67+
*/
68+
protected function doHave($id)
69+
{
70+
return $this->provider->contains($id);
71+
}
72+
73+
/**
74+
* {@inheritdoc}
75+
*/
76+
protected function doClear($namespace)
77+
{
78+
$namespace = $this->provider->getNamespace();
79+
80+
return isset($namespace[0])
81+
? $this->provider->deleteAll()
82+
: $this->provider->flushAll();
83+
}
84+
85+
/**
86+
* {@inheritdoc}
87+
*/
88+
protected function doDelete(array $ids)
89+
{
90+
$ok = true;
91+
foreach ($ids as $id) {
92+
$ok = $this->provider->delete($id) && $ok;
93+
}
94+
95+
return $ok;
96+
}
97+
98+
/**
99+
* {@inheritdoc}
100+
*/
101+
protected function doSave(array $values, $lifetime)
102+
{
103+
return $this->provider->saveMultiple($values, $lifetime);
104+
}
27105
}

0 commit comments

Comments
 (0)
0