8000 [Cache] deprecate all PSR-16 adapters, provide `Psr16Cache` · symfony/symfony@f65edc3 · GitHub
[go: up one dir, main page]

Skip to content

Commit f65edc3

Browse files
[Cache] deprecate all PSR-16 adapters, provide Psr16Cache
1 parent dbf053b commit f65edc3

37 files changed

+1243
-1539
lines changed

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

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,109 @@
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

1617
class ApcuAdapter extends AbstractAdapter
1718
{
18-
use ApcuTrait;
19+
public static function isSupported()
20+
{
21+
return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN);
22+
}
1923

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

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

Lines changed: 140 additions & 1 deletion
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,9 +24,12 @@
2324
*/
2425
class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
2526
{
26-
use ArrayTrait;
27+
use LoggerAwareTrait;
2728

29+
private $storeSerialized;
2830
private $createCacheItem;
31+
private $values = array();
32+
private $expiries = array();
2933

3034
/**
3135
* @param int $defaultLifetime
@@ -64,6 +68,19 @@ public function get(string $key, callable $callback, float $beta = null)
6468
return $item->get();
6569
}
6670

71+
/**
72+
* {@inheritdoc}
73+
*/
74+
public function hasItem($key)
75+
{
76+
if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) {
77+
return true;
78+
}
79+
CacheItem::validateKey($key);
80+
81+
return isset($this->expiries[$key]) && !$this->deleteItem($key);
82+
}
83+
6784
/**
6885
* {@inheritdoc}
6986
*/
@@ -159,4 +176,126 @@ public function delete(string $key): bool
159176
{
160177
return $this->deleteItem($key);
161178
}
179+
180+
/**
181+
* {@inheritdoc}
182+
*/
183+
public function clear()
184+
{
185+
$this->values = $this->expiries = array();
186+
187+
return true;
188+
}
189+
190+
/**
191+
* {@inheritdoc}
192+
*/
193+
public function deleteItem($key)
194+
{
195+
if (!\is_string($key) || !isset($this->expiries[$key])) {
196+
CacheItem::validateKey($key);
197+
}
198+
unset($this->values[$key], $this->expiries[$key]);
199+
200+
return true;
201+
}
202+
203+
/**
204+
* {@inheritdoc}
205+
*/
206+
public function reset()
207+
{
208+
$this->clear();
209+
}
210+
211+
/**
212+
* Returns all cached values, with cache miss as null.
213+
*
214+
* @return array
215+
*/
216+
public function getValues()
217+
{
218+
if (!$this->storeSerialized) {
219+
return $this->values;
220+
}
221+
222+
$values = $this->values;
223+
foreach ($values as $k => $v) {
224+
if (null === $v || 'N;' === $v) {
225+
continue;
226+
}
227+
if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) {
228+
$values[$k] = serialize($v);
229+
}
230+
}
231+
232+
return $values;
233+
}
234+
235+
private function generateItems(array $keys, $now, $f)
236+
{
237+
foreach ($keys as $i => $key) {
238+
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
239+
$this->values[$key] = $value = null;
240+
} else {
241+
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
242+
}
243+
unset($keys[$i]);
244+
245+
yield $key => $f($key, $value, $isHit);
246+
}
247+
248+
foreach ($keys as $key) {
249+
yield $key => $f($key, null, false);
250+
}
251+
}
252+
253+
private function freeze($value)
254+
{
255+
if (null === $value) {
256+
return 'N;';
257+
}
258+
if (\is_string($value)) {
259+
// Serialize strings if they could be confused with serialized objects or arrays
260+
if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) {
261+
return serialize($value);
262+
}
263+
} elseif (!\is_scalar($value)) {
264+
try {
265+
$serialized = serialize($value);
266+
} catch (\Exception $e) {
267+
$type = \is_object($value) ? \get_class($value) : \gettype($value);
268+
CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e));
269+
270+
return;
271+
}
272+
// Keep value serialized if it contains any objects or any internal references
273+
if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) {
274+
return $serialized;
275+
}
276+
}
277+
278+
return $value;
279+
}
280+
281+
private function unfreeze(string $key, bool &$isHit)
282+
{
283+
if ('N;' === $value = $this->values[$key]) {
284+
return null;
285+
}
286+
if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
287+
try {
288+
$value = unserialize($value);
289+
} catch (\Exception $e) {
290+
CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e));
291+
$value = false;
292+
}
293+
if (false === $value) {
294+
$this->values[$key] = $value = null;
295+
$isHit = false;
296+
}
297+
}
298+
299+
return $value;
300+
}
162301
}

0 commit comments

Comments
 (0)
0