From da354660e0c9a0f46f1aaa0fc1ab176c2025b4f2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 9 Dec 2016 18:34:32 +0100 Subject: [PATCH] [Cache] Add CacheItem::getPreviousTags() --- .../Cache/Adapter/TagAwareAdapter.php | 39 ++++++++++++++----- src/Symfony/Component/Cache/CHANGELOG.md | 1 + src/Symfony/Component/Cache/CacheItem.php | 15 ++++++- .../Tests/Adapter/TagAwareAdapterTest.php | 11 ++++++ 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index b8c4a08021b70..1d9dc7ce57241 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -25,6 +25,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface private $itemsAdapter; private $deferred = array(); private $createCacheItem; + private $setCacheItemTags; private $getTagsByKey; private $invalidateTags; private $tagsAdapter; @@ -38,7 +39,6 @@ function ($key, $value, CacheItem $protoItem) { $item = new CacheItem(); $item->key = $key; $item->value = $value; - $item->isHit = false; $item->defaultLifetime = $protoItem->defaultLifetime; $item->expiry = $protoItem->expiry; $item->innerItem = $protoItem->innerItem; @@ -49,6 +49,26 @@ function ($key, $value, CacheItem $protoItem) { null, CacheItem::class ); + $this->setCacheItemTags = \Closure::bind( + function (CacheItem $item, $key, array &$itemTags) { + if (!$item->isHit) { + return $item; + } + if (isset($itemTags[$key])) { + foreach ($itemTags[$key] as $tag => $version) { + $item->prevTags[$tag] = $tag; + } + unset($itemTags[$key]); + } else { + $item->value = null; + $item->isHit = false; + } + + return $item; + }, + null, + CacheItem::class + ); $this->getTagsByKey = \Closure::bind( function ($deferred) { $tagsByKey = array(); @@ -256,12 +276,12 @@ public function __destruct() private function generateItems($items, array $tagKeys) { - $bufferedItems = $itemTags = $invalidKeys = array(); - $f = $this->createCacheItem; + $bufferedItems = $itemTags = array(); + $f = $this->setCacheItemTags; foreach ($items as $key => $item) { if (!$tagKeys) { - yield $key => isset($invalidKeys[self::TAGS_PREFIX.$key]) ? $f($key, null, $item) : $item; + yield $key => $f($item, self::TAGS_PREFIX.$key, $itemTags); continue; } if (!isset($tagKeys[$key])) { @@ -270,24 +290,23 @@ private function generateItems($items, array $tagKeys) } unset($tagKeys[$key]); - if ($tags = $item->get()) { - $itemTags[$key] = $tags; - } + $itemTags[$key] = $item->get() ?: array(); + if (!$tagKeys) { $tagVersions = $this->getTagVersions($itemTags); foreach ($itemTags as $key => $tags) { foreach ($tags as $tag => $version) { if ($tagVersions[$tag] !== $version) { - $invalidKeys[$key] = true; + unset($itemTags[$key]); continue 2; } } } - $itemTags = $tagVersions = $tagKeys = null; + $tagVersions = $tagKeys = null; foreach ($bufferedItems as $key => $item) { - yield $key => isset($invalidKeys[self::TAGS_PREFIX.$key]) ? $f($key, null, $item) : $item; + yield $key => $f($item, self::TAGS_PREFIX.$key, $itemTags); } $bufferedItems = null; } diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index 57a0780ae207b..9a4a31dd83531 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.3.0 ----- + * [EXPERIMENTAL] added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any * added PSR-16 "Simple Cache" implementations for all existing PSR-6 adapters * added Psr6Cache and SimpleCacheAdapter for bidirectional interoperability between PSR-6 and PSR-16 * added MemcachedAdapter (PSR-6) and MemcachedCache (PSR-16) diff --git a/src/Symfony/Component/Cache/CacheItem.php b/src/Symfony/Component/Cache/CacheItem.php index 941d0bc6cd5e9..55e25de9a9513 100644 --- a/src/Symfony/Component/Cache/CacheItem.php +++ b/src/Symfony/Component/Cache/CacheItem.php @@ -22,10 +22,11 @@ final class CacheItem implements CacheItemInterface { protected $key; protected $value; - protected $isHit; + protected $isHit = false; protected $expiry; protected $defaultLifetime; protected $tags = array(); + protected $prevTags = array(); protected $innerItem; protected $poolHash; @@ -130,6 +131,18 @@ public function tag($tags) return $this; } + /** + * Returns the list of tags bound to the value coming from the pool storage if any. + * + * @return array + * + * @experimental in version 3.3 + */ + public function getPreviousTags() + { + return $this->prevTags; + } + /** * Validates a cache key according to PSR-6. * diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php index 24586c0ca9aae..deca227c47dd0 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php @@ -114,4 +114,15 @@ public function testTagItemExpiry() $this->assertFalse($pool->getItem('foo')->isHit()); } + + public function testGetPreviousTags() + { + $pool = $this->createCachePool(); + + $i = $pool->getItem('k'); + $pool->save($i->tag('foo')); + + $i = $pool->getItem('k'); + $this->assertSame(array('foo' => 'foo'), $i->getPreviousTags()); + } }