Skip to content

Instantly share code, notes, and snippets.

@andrerom
Last active October 5, 2017 10:22
Show Gist options
  • Save andrerom/b93332d7e27445ce7fe392d0f596db83 to your computer and use it in GitHub Desktop.
Save andrerom/b93332d7e27445ce7fe392d0f596db83 to your computer and use it in GitHub Desktop.
DEBUG SPI Persistence Cache issues on eZ Publish 5.x / eZ Platform 1.x SPI + patches
<?php
// CASE 1: Current version number becomes inconsistent
// STATUS: Not identified, but there is a proactive attempt at solving it in EZP-28008 (patches attached, so try these first!!)
// DEBUG: Look for inconsistencies between `currentVersionNo` property of the different dumped objects, take note of which one it
// was in the array as it will give a clue to what is not properly cleared somwhere.
/**
* @var Stash\Pool $pool
*/
$pool = $container->get('ezpublish.cache_pool');
// Content id, remote id and version number to investigate cache data for, UPDATE THE VALUES TO FIT YOUR PROBLEM!
$contentId = 200;
$remoteId = "afsriofgoj4tjt94jertm";
$versionNo = 6;
$translationsKey = 'ger-DE';// format: $translationsKey = empty($translations) ? 0 : implode('|', $translations);
var_dump(
$pool->getItems([
"ez_spi/content/info/{$contentId}",
"ez_spi/content/info/remoteId/{$remoteId}",
"ez_spi/content/{$contentId}/{$versionNo}/0",
"ez_spi/content/{$contentId}/{$versionNo}/{$translationsKey}"
])
);
// CASE 2: Access deined issues, earlier tought to be issues with the cached permission data
// Status: Not identified, however:
// 1. A provided stacktrace on slack gave this clue:
// eZ\\Publish\\Core\\Base\\Exceptions\\UnauthorizedException(code: 401):
// User does not have access to 'versionread' 'content' with: contentId '405751', versionNo ''
// at /var/www/sites/example.com/vendor/ezsystems/ezpublish-kernel/eZ/Publish/Core/Repository/ContentService.php:337
//
// Code in question:
// if (
// $content->getVersionInfo()->status !== APIVersionInfo::STATUS_PUBLISHED
// && !$this->repository->canUser('content', 'versionread', $content)
// ) {
// throw new UnauthorizedException('content', 'versionread', array('contentId' => $contentId, 'versionNo' => $versionNo));
// }
// 2. "versionNo ''" means the currently published version was asked for, but the backend returned a draft
// making the code check "versionread", a permissions only editors should have
// 3. Thus this issue seems to be the same as CASE 1, so try the attached patch and report back if it works, if it does not use the code
// above to debug
diff --git a/eZ/Publish/Core/Persistence/Cache/ContentHandler.php b/eZ/Publish/Core/Persistence/Cache/ContentHandler.php
index f63230c6f3..5cdbe039ca 100644
--- a/eZ/Publish/Core/Persistence/Cache/ContentHandler.php
+++ b/eZ/Publish/Core/Persistence/Cache/ContentHandler.php
@@ -146,11 +146,17 @@ public function updateMetadata($contentId, MetadataUpdateStruct $struct)
{
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'struct' => $struct));
- $this->cache
- ->getItem('content', 'info', $contentId)
- ->set($contentInfo = $this->persistenceHandler->contentHandler()->updateMetadata($contentId, $struct))->save();
+ $contentInfo = $this->persistenceHandler->contentHandler()->updateMetadata($contentId, $struct);
$this->cache->clear('content', $contentId, $contentInfo->currentVersionNo);
+ $this->cache->clear('content', 'info', $contentId);
+
+ if ($struct->remoteId) {
+ // remote id changed
+ $this->cache->clear('content', 'info', 'remoteId');
+ } else {
+ $this->cache->clear('content', 'info', 'remoteId', $contentInfo->remoteId);
+ }
return $contentInfo;
}
@@ -163,10 +169,6 @@ 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->clear('content', $contentId, $versionNo);
- $this->cache
- ->getItem('content', $contentId, $versionNo, self::ALL_TRANSLATIONS_KEY)
- ->set($content)
- ->save();
return $content;
}
diff --git a/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php b/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php
index 24ead4709e..330606eacd 100644
--- a/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php
+++ b/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php
@@ -374,25 +374,25 @@ public function testUpdateMetadata()
->expects($this->once())
->method('updateMetadata')
->with(2, $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content\\MetadataUpdateStruct'))
- ->will($this->returnValue(new ContentInfo(array('id' => 2))));
+ ->willReturn(new ContentInfo(array('id' => 2, 'currentVersionNo' => 3, 'remoteId' => 'o34')));
- $cacheItemMock = $this->getMock('Stash\Interfaces\ItemInterface');
$this->cacheMock
- ->expects($this->once())
- ->method('getItem')
- ->with('content', 'info', 2)
- ->will($this->returnValue($cacheItemMock));
+ ->expects($this->at(0))
+ ->method('clear')
+ ->with('content', 2, 3)
+ ->willReturn(null);
- $cacheItemMock
- ->expects($this->once())
- ->method('set')
- ->with($this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content\\ContentInfo'))
- ->will($this->returnValue($cacheItemMock));
+ $this->cacheMock
+ ->expects($this->at(1))
+ ->method('clear')
+ ->with('content', 'info', 2)
+ ->willReturn(null);
- $cacheItemMock
- ->expects($this->once())
- ->method('save')
- ->with();
+ $this->cacheMock
+ ->expects($this->at(2))
+ ->method('clear')
+ ->with('content', 'info', 'remoteId', 'o34')
+ ->willReturn(null);
$handler = $this->persistenceCacheHandler->contentHandler();
$handler->updateMetadata(2, new MetadataUpdateStruct());
@@ -437,24 +437,6 @@ public function testUpdateContent()
->with('content', 2, 1)
->will($this->returnValue(null));
- $cacheItemMock = $this->getMock('Stash\Interfaces\ItemInterface');
- $this->cacheMock
- ->expects($this->once())
- ->method('getItem')
- ->with('content', 2, 1, ContentHandler::ALL_TRANSLATIONS_KEY)
- ->will($this->returnValue($cacheItemMock));
-
- $cacheItemMock
- ->expects($this->once())
- ->method('set')
- ->with($this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'))
- ->will($this->returnValue($cacheItemMock));
-
- $cacheItemMock
- ->expects($this->once())
- ->method('save')
- ->with();
-
$handler = $this->persistenceCacheHandler->contentHandler();
$handler->updateContent(2, 1, new UpdateStruct());
}
diff --git a/eZ/Publish/Core/Persistence/Cache/ContentHandler.php b/eZ/Publish/Core/Persistence/Cache/ContentHandler.php
index c8e3832ea..c39c1bea5 100644
--- a/eZ/Publish/Core/Persistence/Cache/ContentHandler.php
+++ b/eZ/Publish/Core/Persistence/Cache/ContentHandler.php
@@ -150,12 +150,17 @@ public function setStatus($contentId, $status, $version)
public function updateMetadata($contentId, MetadataUpdateStruct $struct)
{
$this->logger->logCall(__METHOD__, array('content' => $contentId, 'struct' => $struct));
-
- $this->cache
- ->getItem('content', 'info', $contentId)
- ->set($contentInfo = $this->persistenceHandler->contentHandler()->updateMetadata($contentId, $struct));
+ $contentInfo = $this->persistenceHandler->contentHandler()->updateMetadata($contentId, $struct);
$this->cache->clear('content', $contentId, $contentInfo->currentVersionNo);
+ $this->cache->clear('content', 'info', $contentId);
+
+ if ($struct->remoteId) {
+ // remote id changed
+ $this->cache->clear('content', 'info', 'remoteId');
+ } else {
+ $this->cache->clear('content', 'info', 'remoteId', $contentInfo->remoteId);
+ }
return $contentInfo;
}
@@ -168,9 +173,6 @@ 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->clear('content', $contentId, $versionNo);
- $this->cache
- ->getItem('content', $contentId, $versionNo, self::ALL_TRANSLATIONS_KEY)
- ->set($this->cloneAndSerializeXMLFields($content));
return $content;
}
diff --git a/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php b/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php
index b4a27f7d2..ff8dfea1d 100644
--- a/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php
+++ b/eZ/Publish/Core/Persistence/Cache/Tests/ContentHandlerTest.php
@@ -362,19 +362,25 @@ public function testUpdateMetadata()
->expects($this->once())
->method('updateMetadata')
->with(2, $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content\\MetadataUpdateStruct'))
- ->will($this->returnValue(new ContentInfo(array('id' => 2))));
+ ->willReturn(new ContentInfo(array('id' => 2, 'currentVersionNo' => 3, 'remoteId' => 'o34')));
- $cacheItemMock = $this->getMock('Stash\Interfaces\ItemInterface');
$this->cacheMock
- ->expects($this->once())
- ->method('getItem')
+ ->expects($this->at(0))
+ ->method('clear')
+ ->with('content', 2, 3)
+ ->willReturn(null);
+
+ $this->cacheMock
+ ->expects($this->at(1))
+ ->method('clear')
->with('content', 'info', 2)
- ->will($this->returnValue($cacheItemMock));
+ ->willReturn(null);
- $cacheItemMock
- ->expects($this->once())
- ->method('set')
- ->with($this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content\\ContentInfo'));
+ $this->cacheMock
+ ->expects($this->at(2))
+ ->method('clear')
+ ->with('content', 'info', 'remoteId', 'o34')
+ ->willReturn(null);
$handler = $this->persistenceCacheHandler->contentHandler();
$handler->updateMetadata(2, new MetadataUpdateStruct());
@@ -419,18 +425,6 @@ public function testUpdateContent()
->with('content', 2, 1)
->will($this->returnValue(null));
- $cacheItemMock = $this->getMock('Stash\Interfaces\ItemInterface');
- $this->cacheMock
- ->expects($this->once())
- ->method('getItem')
- ->with('content', 2, 1, ContentHandler::ALL_TRANSLATIONS_KEY)
- ->will($this->returnValue($cacheItemMock));
-
- $cacheItemMock
- ->expects($this->once())
- ->method('set')
- ->with($this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'));
-
$handler = $this->persistenceCacheHandler->contentHandler();
$handler->updateContent(2, 1, new UpdateStruct());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment