diff --git a/doc/specifications/cache/persistence/Readme.md b/doc/specifications/cache/persistence/Readme.md index e4c3fdd759d..59fc977f3fd 100644 --- a/doc/specifications/cache/persistence/Readme.md +++ b/doc/specifications/cache/persistence/Readme.md @@ -17,6 +17,9 @@ List of tags and their meaning: - `content-` : _Meta tag used on anything that are affected on changes to content, on content itself as well as location and so on._ +- `content--version-` + _Used for specific versions, usuefull for clearing cache of a specific draft on changes for instance._ + - `content-fields-` : _Used on content/user object itself (with fields), for use when operations affects field values but not content meta info._ diff --git a/eZ/Publish/Core/Persistence/Cache/ContentHandler.php b/eZ/Publish/Core/Persistence/Cache/ContentHandler.php index d8409ed94cd..a4127f68ad8 100644 --- a/eZ/Publish/Core/Persistence/Cache/ContentHandler.php +++ b/eZ/Publish/Core/Persistence/Cache/ContentHandler.php @@ -43,7 +43,7 @@ public function createDraftFromVersion($contentId, $srcVersion, $userId) { $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $srcVersion, 'user' => $userId)); $draft = $this->persistenceHandler->contentHandler()->createDraftFromVersion($contentId, $srcVersion, $userId); - $this->cache->invalidateTags(["content-$contentId-version-list"]); + $this->cache->invalidateTags(["content-{$contentId}-version-list"]); return $draft; } @@ -72,7 +72,7 @@ public function load($contentId, $versionNo, array $translations = null) $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo, 'translations' => $translations)); $content = $this->persistenceHandler->contentHandler()->load($contentId, $versionNo, $translations); $cacheItem->set($content); - $cacheItem->tag($this->getCacheTags($content->versionInfo->contentInfo, true)); + $cacheItem->tag($this->getCacheTagsForContent($content)); $this->cache->save($cacheItem); return $content; @@ -106,7 +106,7 @@ function (array $cacheMissIds) use ($contentLoadStructs) { return $this->persistenceHandler->contentHandler()->loadContentList($filteredStructs); }, function (Content $content) { - return $this->getCacheTags($content->versionInfo->contentInfo, true); + return $this->getCacheTagsForContent($content); }, $keySuffixes ); @@ -179,7 +179,7 @@ public function loadVersionInfo($contentId, $versionNo) $this->logger->logCall(__METHOD__, ['content' => $contentId, 'version' => $versionNo]); $versionInfo = $this->persistenceHandler->contentHandler()->loadVersionInfo($contentId, $versionNo); $cacheItem->set($versionInfo); - $cacheItem->tag($this->getCacheTags($versionInfo->contentInfo)); + $cacheItem->tag($this->getCacheTagsForVersion($versionInfo)); $this->cache->save($cacheItem); return $versionInfo; @@ -203,11 +203,10 @@ public function setStatus($contentId, $status, $versionNo) $this->logger->logCall(__METHOD__, array('content' => $contentId, 'status' => $status, 'version' => $versionNo)); $return = $this->persistenceHandler->contentHandler()->setStatus($contentId, $status, $versionNo); - $this->cache->deleteItem("ez-content-version-info-${contentId}-${versionNo}"); if ($status === VersionInfo::STATUS_PUBLISHED) { $this->cache->invalidateTags(['content-' . $contentId]); } else { - $this->cache->invalidateTags(["content-$contentId-version-list"]); + $this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]); } return $return; @@ -232,7 +231,7 @@ public function updateContent($contentId, $versionNo, UpdateStruct $struct) { $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo, 'struct' => $struct)); $content = $this->persistenceHandler->contentHandler()->updateContent($contentId, $versionNo, $struct); - $this->cache->invalidateTags(['content-' . $contentId]); + $this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]); return $content; } @@ -275,7 +274,7 @@ public function deleteVersion($contentId, $versionNo) { $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo)); $return = $this->persistenceHandler->contentHandler()->deleteVersion($contentId, $versionNo); - $this->cache->invalidateTags(['content-' . $contentId]); + $this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]); return $return; } @@ -293,8 +292,11 @@ public function listVersions($contentId, $status = null, $limit = -1) $this->logger->logCall(__METHOD__, array('content' => $contentId, 'status' => $status)); $versions = $this->persistenceHandler->contentHandler()->listVersions($contentId, $status, $limit); $cacheItem->set($versions); - $tags = ["content-$contentId", "content-$contentId-version-list"]; - $cacheItem->tag(empty($versions) ? $tags : $this->getCacheTags($versions[0]->contentInfo, false, $tags)); + $tags = ["content-{$contentId}", "content-{$contentId}-version-list"]; + foreach ($versions as $version) { + $tags = $this->getCacheTagsForVersion($version, $tags); + } + $cacheItem->tag($tags); $this->cache->save($cacheItem); return $versions; @@ -397,7 +399,7 @@ public function deleteTranslationFromDraft($contentId, $versionNo, $languageCode $versionNo, $languageCode ); - $this->cache->invalidateTags(['content-' . $contentId]); + $this->cache->invalidateTags(["content-{$contentId}-version-{$versionNo}"]); return $content; } @@ -408,20 +410,14 @@ public function deleteTranslationFromDraft($contentId, $versionNo, $languageCode * For use when generating cache, not on invalidation. * * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo $contentInfo - * @param bool $withFields Set to true if item contains fields which should be expired on relation or type updates. * @param array $tags Optional, can be used to specify other tags. * * @return array */ - private function getCacheTags(ContentInfo $contentInfo, $withFields = false, array $tags = []) + private function getCacheTags(ContentInfo $contentInfo, array $tags = []) { $tags[] = 'content-' . $contentInfo->id; - if ($withFields) { - $tags[] = 'content-fields-' . $contentInfo->id; - $tags[] = 'content-fields-type-' . $contentInfo->contentTypeId; - } - if ($contentInfo->mainLocationId) { $locations = $this->persistenceHandler->locationHandler()->loadLocationsByContent($contentInfo->id); foreach ($locations as $location) { @@ -434,4 +430,23 @@ private function getCacheTags(ContentInfo $contentInfo, $withFields = false, arr return array_unique($tags); } + + private function getCacheTagsForVersion(VersionInfo $versionInfo, array $tags = []) + { + $contentInfo = $versionInfo->contentInfo; + $tags[] = 'content-' . $contentInfo->id . '-version-' . $versionInfo->versionNo; + + return $this->getCacheTags($contentInfo, $tags); + } + + private function getCacheTagsForContent(Content $content) + { + $versionInfo = $content->versionInfo; + $tags = [ + 'content-fields-' . $versionInfo->contentInfo->id, + 'content-fields-type-' . $versionInfo->contentInfo->contentTypeId, + ]; + + return $this->getCacheTagsForVersion($versionInfo, $tags); + } } diff --git a/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php b/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php index 597f49d42ae..8c80dcfc9d3 100644 --- a/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php +++ b/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php @@ -46,12 +46,12 @@ public function providerForUnCachedMethods(): array ['createDraftFromVersion', [2, 1, 14], ['content-2-version-list']], ['copy', [2, 1]], ['loadDraftsForUser', [14]], - ['setStatus', [2, 0, 1], ['content-2-version-list'], 'ez-content-version-info-2-1'], - ['setStatus', [2, 1, 1], ['content-2'], 'ez-content-version-info-2-1'], + ['setStatus', [2, 0, 1], ['content-2-version-1']], + ['setStatus', [2, 1, 1], ['content-2']], ['updateMetadata', [2, new MetadataUpdateStruct()], ['content-2']], - ['updateContent', [2, 1, new UpdateStruct()], ['content-2']], + ['updateContent', [2, 1, new UpdateStruct()], ['content-2-version-1']], //['deleteContent', [2]], own tests for relations complexity - ['deleteVersion', [2, 1], ['content-2']], + ['deleteVersion', [2, 1], ['content-2-version-1']], ['addRelation', [new RelationCreateStruct()]], ['removeRelation', [66, APIRelation::COMMON]], ['loadRelations', [2, 1, 3]],