8000 cache-serializer · symfony/symfony@9a2b820 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9a2b820

Browse files
author
Aleksey Prilipko
committed
cache-serializer
1 parent 2ae7ad9 commit 9a2b820

26 files changed

+583
-196
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Psr\Log\NullLogger;
1818
use Symfony\Component\Cache\CacheItem;
1919
use Symfony\Component\Cache\Exception\InvalidArgumentException;
20+
use Symfony\Component\Cache\Serializer\PhpSerializer;
2021
use Symfony\Component\Cache\ResettableInterface;
2122
use Symfony\Component\Cache\Traits\AbstractTrait;
2223

@@ -35,6 +36,7 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface
3536

3637
protected function __construct(string $namespace = '', int $defaultLifetime = 0)
3738
{
39+
$this->setSerializer(new PhpSerializer());
3840
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
3941
if (null !== $this->maxIdLength && strlen($namespace) > $this->maxIdLength - 24) {
4042
throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, strlen($namespace), $namespace));

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

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Psr\Cache\CacheItemInterface;
1515
use Psr\Log\LoggerAwareInterface;
1616
use Symfony\Component\Cache\CacheItem;
17+
use Symfony\Component\Cache\Serializer\NullSerializer;
18+
use Symfony\Component\Cache\Serializer\PhpSerializer;
1719
use Symfony\Component\Cache\ResettableInterface;
1820
use Symfony\Component\Cache\Traits\ArrayTrait;
1921

@@ -32,7 +34,7 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable
3234
*/
3335
public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true)
3436
{
35-
$this->storeSerialized = $storeSerialized;
37+
$this->setSerializer($storeSerialized ? new PhpSerializer() : new NullSerializer());
3638
$this->createCacheItem = \Closure::bind(
3739
function ($key, $value, $isHit) use ($defaultLifetime) {
3840
$item = new CacheItem();
@@ -57,13 +59,8 @@ public function getItem($key)
5759
try {
5860
if (!$isHit) {
5961
$this->values[$key] = $value = null;
60-
} elseif (!$this->storeSerialized) {
61-
$value = $this->values[$key];
62-
} elseif ('b:0;' === $value = $this->values[$key]) {
63-
$value = false;
64-
} elseif (false === $value = unserialize($value)) {
65-
$this->values[$key] = $value = null;
66-
$isHit = false;
62+
} else {
63+
$value = $this->unserialize($this->values[$key]);
6764
}
6865
} catch (\Exception $e) {
6966
CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e));
@@ -117,15 +114,13 @@ public function save(CacheItemInterface $item)
117114

118115
return true;
119116
}
120-
if ($this->storeSerialized) {
121-
try {
122-
$value = serialize($value);
123-
} catch (\Exception $e) {
124-
$type = is_object($value) ? get_class($value) : gettype($value);
125-
CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e));
126-
127-
return false;
128-
}
117+
try {
118+
$value = $this->serialize($value);
119+
} catch (\Exception $e) {
120+
$type = is_object($value) ? get_class($value) : gettype($value);
121+
CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e));
122+
123+
return false;
129124
}
130125
if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) {
131126
$expiry = time() + $item["\0*\0defaultLifetime"];

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

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Cache\Exception\InvalidArgumentException;
1818
use Symfony\Component\Cache\PruneableInterface;
1919
use Symfony\Component\Cache\ResettableInterface;
20+
use Symfony\Component\Cache\Serializer\PhpSerializer;
2021
use Symfony\Component\Cache\Traits\PhpArrayTrait;
2122

2223
/**
@@ -53,6 +54,7 @@ function ($key, $value, $isHit) {
5354
null,
5455
CacheItem::class
5556
);
57+
$this->setSerializer(new PhpSerializer());
5658
}
5759

5860
/**
@@ -92,24 +94,18 @@ public function getItem($key)
9294
return $this->pool->getItem($key);
9395
}
9496

95-
$value = $this->values[$key];
96-
$isHit = true;
97-
98-
if ('N;' === $value) {
97+
try {
98+
$e = null;
99+
$value = $this->unwrapValue($this->values[$key]);
100+
$isHit = true;
101+
} catch (\Error $e) {
102+
} catch (\Exception $e) {
103+
}
104+
if (null !== $e) {
99105
$value = null;
100-
} elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
101-
try {
102-
$e = null;
103-
$value = unserialize($value);
104-
} catch (\Error $e) {
105-
} catch (\Exception $e) {
106-
}
107-
if (null !== $e) {
108-
$value = null;
109-
$isHit = false;
110-
}
106+
$isHit = false;
107+
unset($this->values[$key]);
111108
}
112-
113109
$f = $this->createCacheItem;
114110

115111
return $f($key, $value, $isHit);
@@ -231,20 +227,13 @@ private function generateItems(array $keys): \Generator
231227

232228
foreach ($keys as $key) {
233229
if (isset($this->values[$key])) {
234-
$value = $this->values[$key];
235-
236-
if ('N;' === $value) {
237-
yield $key => $f($key, null, true);
238-
} elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
239-
try {
240-
yield $key => $f($key, unserialize($value), true);
241-
} catch (\Error $e) {
242-
yield $key => $f($key, null, false);
243-
} catch (\Exception $e) {
244-
yield $key => $f($key, null, false);
245-
}
246-
} else {
230+
try {
231+
$value = $this->unwrapValue($this->values[$key]);
247232
yield $key => $f($key, $value, true);
233+
} catch (\Error $e) {
234+
yield $key => $f($key, null, false);
235+
} catch (\Exception $e) {
236+
yield $key => $f($key, null, false);
248237
}
249238
} else {
250239
$fallbackKeys[] = $key;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Serializer;
13+
14+
use Symfony\Component\Cache\Exception\CacheException;
15+
use Symfony\Component\Cache\SerializerInterface;
16+
17+
class IgbinarySerializer implements SerializerInterface
18+
{
19+
public function serialize($data)
20+
{
21+
return igbinary_serialize($data);
22+
}
23+
24+
public function unserialize($serialized)
25+
{
26+
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
27+
try {
28+
$value = igbinary_unserialize($serialized);
29+
if (false === $value && igbinary_serialize(false) !== $serialized) {
30+
throw new CacheException('failed to unserialize value');
31+
}
32+
33+
return $value;
34+
} catch (\Error $e) {
35+
throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
36+
} finally {
37+
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
38+
}
39+
}
40+
41+
/**
42+
* @internal
43+
*/
44+
public static function handleUnserializeCallback($class)
45+
{
46+
throw new \DomainException('Class not found: '.$class);
47+
}
48+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Serializer;
13+
14+
use Symfony\Component\Cache\SerializerInterface;
15+
16+
class NullSerializer implements SerializerInterface
17+
{
18+
public function serialize($data)
19+
{
20+
return $data;
21+
}
22+
23+
public function unserialize($serialized)
24+
{
25+
return $serialized;
26+
}
27+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Serializer;
13+
14+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
15+
use Symfony\Component\Cache\SerializerInterface;
16+
17+
/**
18+
* Serializes values in php code.
19+
*/
20+
class PhpExportSerializer implements SerializerInterface
21+
{
22+
private static function isExportable($data)
23+
{
24+
if (is_object($data)) {
25+
return method_exists(get_class($data), '__set_state');
26+
}
27+
28+
if (is_array($data)) {
29+
$exportable = true;
30+
foreach ($data as $key => $value) {
31+
$exportable = $exportable && self::isExportable($key) && self::isExportable($value);
32+
}
33+
34+
return $exportable;
35+
}
36+
37+
return true;
38+
}
39+
40+
public function serialize($data)
41+
{
42+
if (!self::isExportable($data)) {
43+
throw new InvalidArgumentException('classes without __set_state method are not exportable');
44+
}
45+
46+
return var_export($data, true);
47+
}
48+
49+
public function unserialize($serialized)
50+
{
51+
return eval("return $serialized;");
52+
}
53+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Serializer;
13+
14+
use Symfony\Component\Cache\Exception\CacheException;
15+
use Symfony\Component\Cache\SerializerInterface;
16+
17+
class PhpSerializer implements SerializerInterface
18+
{
19+
public function serialize($data)
20+
{
21+
return serialize($data);
22+
}
23+
24+
public function unserialize($serialized)
25+
{
26+
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
27+
try {
28+
$value = unserialize($serialized);
29+
if (false === $value && serialize(false) !== $serialized) {
30+
throw new CacheException('failed to unserialize value');
31+
}
32+
33+
return $value;
34+
} catch (\Error $e) {
35+
throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
36+
} finally {
37+
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
38+
}
39+
}
40+
41+
/**
42+
* @internal
43+
*/
44+
public static function handleUnserializeCallback($class)
45+
{
46+
throw new \DomainException('Class not found: '.$class);
47+
}
48+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache;
13+
14+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Alexei Prilipko <palex.fpt@gmail.com>
18+
*/
19+
interface SerializerInterface
20+
{
21+
/**
22+
* Generates a storable representation of a value.
23+
*
24+
* @param $data mixed
25+
*
26+
* @return string|mixed serialized value
27+
*
28+
* @throws InvalidArgumentException when $data can not be serialized
29+
*/
30+
public function serialize($data);
31+
32+
/**
33+
* Creates a PHP value from a stored representation.
34+
*
35+
* @param string|mixed $serialized the serialized string
36+
*
37+
* @return mixed Original value
38+
*/
39+
public function unserialize($serialized);
40+
}

src/Symfony/Component/Cache/Simple/AbstractCache.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Psr\SimpleCache\CacheInterface;
1616
use Symfony\Component\Cache\CacheItem;
1717
use Symfony\Component\Cache\Exception\InvalidArgumentException;
18+
use Symfony\Component\Cache\Serializer\PhpSerializer;
1819
use Symfony\Component\Cache\Traits\AbstractTrait;
1920
use Symfony\Component\Cache\ResettableInterface;
2021

@@ -33,6 +34,7 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re
3334

3435
protected function __construct(string $namespace = '', int $defaultLifetime = 0)
3536
{
37+
$this->setSerializer(new PhpSerializer());
3638
$this->defaultLifetime = max(0, $defaultLifetime);
3739
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
3840
if (null !== $this->maxIdLength && strlen($namespace) > $this->maxIdLength - 24) {

0 commit comments

Comments
 (0)
0