From 1ef44ae7c69c3bb7e2efc4efd92a5d323b579ef7 Mon Sep 17 00:00:00 2001 From: Stefano Arlandini Date: Sat, 27 Mar 2021 23:53:30 +0100 Subject: [PATCH] [Cache] Support a custom serializer in the ApcuAdapter class --- .../Component/Cache/Adapter/ApcuAdapter.php | 13 +++++++-- src/Symfony/Component/Cache/CHANGELOG.md | 1 + .../Cache/Tests/Adapter/ApcuAdapterTest.php | 27 +++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php index dc6b5316c3..28ebce3e8f 100644 --- a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php @@ -13,16 +13,19 @@ namespace Symfony\Component\Cache\Adapter; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; /** * @author Nicolas Grekas */ class ApcuAdapter extends AbstractAdapter { + private $marshaller; + /** * @throws CacheException if APCu is not enabled */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null, ?MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('APCu is not enabled.'); @@ -40,6 +43,8 @@ class ApcuAdapter extends AbstractAdapter apcu_add($version.'@'.$namespace, null); } } + + $this->marshaller = $marshaller; } public static function isSupported() @@ -57,7 +62,7 @@ class ApcuAdapter extends AbstractAdapter $values = []; foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) { if (null !== $v || $ok) { - $values[$k] = $v; + $values[$k] = null !== $this->marshaller ? $this->marshaller->unmarshall($v) : $v; } } @@ -104,6 +109,10 @@ class ApcuAdapter extends AbstractAdapter */ protected function doSave(array $values, int $lifetime) { + if (null !== $this->marshaller && (!$values = $this->marshaller->marshall($values, $failed))) { + return $failed; + } + try { if (false === $failures = apcu_store($values, null, $lifetime)) { $failures = $values; diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index 5712ebf92a..89f3e884e3 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * added support for connecting to Redis Sentinel clusters when using the Redis PHP extension + * add support for a custom serializer to the `ApcuAdapter` class 5.2.0 ----- diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php index 120a4e5a17..c2973681c4 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; use Psr\Cache\CacheItemPoolInterface; use Psr\Log\NullLogger; use Symfony\Component\Cache\Adapter\ApcuAdapter; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; class ApcuAdapterTest extends AdapterTestCase { @@ -122,4 +123,30 @@ class ApcuAdapterTest extends AdapterTestCase restore_error_handler(); } } + + public function testCacheItemValueRunsThroughMarshaller() + { + $namespace = str_replace('\\', '.', static::class); + + $marshaller = $this->createMock(MarshallerInterface::class); + $marshaller->expects($this->once()) + ->method('marshall') + ->with([$namespace.':foo' => 'bar']) + ->willReturn([$namespace.':foo' => 'bar_serialized']); + + $marshaller->expects($this->once()) + ->method('unmarshall') + ->with('bar_serialized') + ->willReturn('bar'); + + $pool = new ApcuAdapter($namespace, 0, 'p1', $marshaller); + + $item = $pool->getItem('foo'); + $this->assertFalse($item->isHit()); + $this->assertTrue($pool->save($item->set('bar'))); + + $item = $pool->getItem('foo'); + $this->assertTrue($item->isHit()); + $this->assertSame('bar', $item->get()); + } }