Skip to content

Commit

Permalink
BUGFIX: Respect entryDiscriminator when using Content Cache mode `d…
Browse files Browse the repository at this point in the history
…ynamic` (#1631)

Currently, when using the content cache mode `dynamic` the `entryDiscriminator`
is only considered when _writing_ the Cache entry.
When trying to _retrieve_ the content segment, the discriminator is omitted
from the cache entry identifier.
Thus, the `dynamic` cache mode currently acts like `uncached`.

This change fixes the behavior and adds a functional test.

Fixes: #1630
  • Loading branch information
Bastian Waidelich committed Jul 10, 2017
1 parent 65a22b7 commit 6f3b21b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 5 deletions.
6 changes: 5 additions & 1 deletion Classes/TYPO3/TypoScript/Core/Cache/ContentCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,16 @@ public function processCacheSegments($content, $storeCacheEntries = true)
* @param string $typoScriptPath TypoScript path identifying the TypoScript object to retrieve from the content cache
* @param array $cacheIdentifierValues Further values which play into the cache identifier hash, must be the same as the ones specified while the cache entry was written
* @param boolean $addCacheSegmentMarkersToPlaceholders If cache segment markers should be added – this makes sense if the cached segment is about to be included in a not-yet-cached segment
* @param string $cacheDiscriminator The evaluated cache discriminator value, if any
* @return string|boolean The segment with replaced cache placeholders, or FALSE if a segment was missing in the cache
* @throws Exception
*/
public function getCachedSegment($uncachedCommandCallback, $typoScriptPath, $cacheIdentifierValues, $addCacheSegmentMarkersToPlaceholders = false)
public function getCachedSegment($uncachedCommandCallback, $typoScriptPath, $cacheIdentifierValues, $addCacheSegmentMarkersToPlaceholders = false, $cacheDiscriminator = null)
{
$cacheIdentifier = $this->renderContentCacheEntryIdentifier($typoScriptPath, $cacheIdentifierValues);
if ($cacheDiscriminator !== null) {
$cacheIdentifier .= '_' . md5($cacheDiscriminator);
}
$content = $this->cache->get($cacheIdentifier);

if ($content === false) {
Expand Down
10 changes: 6 additions & 4 deletions Classes/TYPO3/TypoScript/Core/Cache/RuntimeContentCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,12 @@ public function enter(array $configuration, $typoScriptPath)
public function preEvaluate(array &$evaluateContext, $tsObject)
{
if ($this->enableContentCache) {
if ($evaluateContext['cacheForPathEnabled'] && $evaluateContext['cacheForPathDisabled']) {
$evaluateContext['cacheDiscriminator'] = $this->runtime->evaluate($evaluateContext['typoScriptPath'] . '/__meta/cache/entryDiscriminator');
}
if ($evaluateContext['cacheForPathEnabled']) {
$evaluateContext['cacheIdentifierValues'] = $this->buildCacheIdentifierValues($evaluateContext['configuration'], $evaluateContext['typoScriptPath'], $tsObject);
$cacheDiscriminator = isset($evaluateContext['cacheDiscriminator']) ? $evaluateContext['cacheDiscriminator'] : null;
$self = $this;
$segment = $this->contentCache->getCachedSegment(function ($command, $additionalData, $cache) use ($self, $evaluateContext, $tsObject) {
if (strpos($command, 'eval=') === 0) {
Expand Down Expand Up @@ -190,7 +194,7 @@ public function preEvaluate(array &$evaluateContext, $tsObject)
} else {
throw new Exception(sprintf('Unknown uncached command "%s"', $command), 1392837596);
}
}, $evaluateContext['typoScriptPath'], $evaluateContext['cacheIdentifierValues'], $this->addCacheSegmentMarkersToPlaceholders);
}, $evaluateContext['typoScriptPath'], $evaluateContext['cacheIdentifierValues'], $this->addCacheSegmentMarkersToPlaceholders, $cacheDiscriminator);
if ($segment !== false) {
return [true, $segment];
} else {
Expand All @@ -200,9 +204,7 @@ public function preEvaluate(array &$evaluateContext, $tsObject)
$this->cacheMetadata[] = ['lifetime' => null];
}

if ($evaluateContext['cacheForPathEnabled'] && $evaluateContext['cacheForPathDisabled']) {
$evaluateContext['cacheDiscriminator'] = $this->runtime->evaluate($evaluateContext['typoScriptPath'] . '/__meta/cache/entryDiscriminator');
}


if (isset($evaluateContext['configuration']['maximumLifetime'])) {
$maximumLifetime = $this->runtime->evaluate($evaluateContext['typoScriptPath'] . '/__meta/cache/maximumLifetime', $tsObject);
Expand Down
48 changes: 48 additions & 0 deletions Tests/Functional/TypoScriptObjects/ContentCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -597,4 +597,52 @@ public function uncachedSegmentInCachedSegmentCanOverrideContextVariables()
$secondRenderResult = $view->render();
$this->assertSame('Outer segment|object=Object value 1|Uncached segment|counter=2|End uncached|End outer', $secondRenderResult);
}

/**
* @test
*/
public function dynamicSegmentIsCachedIfDiscriminatorIsNotChanged()
{
$renderObject = new TestModel(42, 'Render object');
$discriminatorObject = new TestModel(43, 'Discriminator object');

$view = $this->buildView();
$view->setOption('enableContentCache', true);
$view->assign('renderObject', $renderObject);
$view->assign('discriminatorObject', $discriminatorObject);
$view->setTypoScriptPath('contentCache/dynamicSegment');

$firstRenderResult = $view->render();

$renderObject->setValue('Should not affect the cache');

$secondRenderResult = $view->render();

$this->assertSame('Dynamic segment|counter=1', $secondRenderResult);
$this->assertSame($firstRenderResult, $secondRenderResult);
}

/**
* @test
*/
public function dynamicSegmentCacheIsFlushedIfDiscriminatorIsChanged()
{
$renderObject = new TestModel(42, 'Render object');
$discriminatorObject = new TestModel(43, 'Discriminator object');

$view = $this->buildView();
$view->setOption('enableContentCache', true);
$view->assign('renderObject', $renderObject);
$view->assign('discriminatorObject', $discriminatorObject);
$view->setTypoScriptPath('contentCache/dynamicSegment');

$firstRenderResult = $view->render();

$discriminatorObject->setValue('This should affect the cache');

$secondRenderResult = $view->render();

$this->assertSame('Dynamic segment|counter=2', $secondRenderResult);
$this->assertNotSame($firstRenderResult, $secondRenderResult);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -525,3 +525,20 @@ contentCache.uncachedSegmentInCachedSegmentCanOverrideContextVariables = TYPO3.T
}
}
}

contentCache.dynamicSegment = TYPO3.TypoScript:Array {
5 = 'Dynamic segment|'
10 = ${'counter=' + renderObject.counter}

@cache {
mode = 'dynamic'
context {
1 = 'renderObject'
2 = 'discriminatorObject'
}
entryIdentifier {
renderObject = 'static'
}
entryDiscriminator = ${discriminatorObject.value}
}
}

0 comments on commit 6f3b21b

Please sign in to comment.