diff --git a/Neos.Neos/Classes/Fusion/ConvertUrisImplementation.php b/Neos.Neos/Classes/Fusion/ConvertUrisImplementation.php index cd86cf22933..1fdee9b7e1a 100644 --- a/Neos.Neos/Classes/Fusion/ConvertUrisImplementation.php +++ b/Neos.Neos/Classes/Fusion/ConvertUrisImplementation.php @@ -13,6 +13,7 @@ use Neos\Flow\Annotations as Flow; use Neos\Neos\Domain\Exception; +use Neos\Neos\Fusion\Helper\CachingHelper; use Neos\Neos\Service\LinkingService; use Neos\ContentRepository\Domain\Model\NodeInterface; use Neos\Fusion\FusionObjects\AbstractFusionObject; @@ -56,6 +57,12 @@ class ConvertUrisImplementation extends AbstractFusionObject */ protected $linkingService; + /** + * @Flow\Inject + * @var CachingHelper + */ + protected $cachingHelper; + /** * Convert URIs matching a supported scheme with generated URIs * @@ -97,11 +104,13 @@ public function evaluate() switch ($matches[1]) { case 'node': $resolvedUri = $linkingService->resolveNodeUri($matches[0], $node, $controllerContext, $absolute); - $this->runtime->addCacheTag('node', $matches[2]); + $cacheTagIdentifier = sprintf('%s_%s', $this->cachingHelper->renderWorkspaceTagForContextNode($node->getContext()->getWorkspaceName()), $matches[2]); + $this->runtime->addCacheTag('node', $cacheTagIdentifier); break; case 'asset': $resolvedUri = $linkingService->resolveAssetUri($matches[0]); - $this->runtime->addCacheTag('asset', $matches[2]); + $cacheTagIdentifier = sprintf('%s_%s', $this->cachingHelper->renderWorkspaceTagForContextNode($node->getContext()->getWorkspaceName()), $matches[2]); + $this->runtime->addCacheTag('asset', $cacheTagIdentifier); break; default: $resolvedUri = null; diff --git a/Neos.Neos/Tests/Unit/Fusion/ConvertUrisImplementationTest.php b/Neos.Neos/Tests/Unit/Fusion/ConvertUrisImplementationTest.php index d7f9e075e81..b496ab47b84 100644 --- a/Neos.Neos/Tests/Unit/Fusion/ConvertUrisImplementationTest.php +++ b/Neos.Neos/Tests/Unit/Fusion/ConvertUrisImplementationTest.php @@ -18,6 +18,7 @@ use Neos\Flow\Mvc\Routing\UriBuilder; use Neos\Flow\Tests\UnitTestCase; use Neos\Neos\Domain\Exception; +use Neos\Neos\Fusion\Helper\CachingHelper; use Neos\Neos\Service\LinkingService; use Neos\Neos\Fusion\ConvertUrisImplementation; use Neos\ContentRepository\Domain\Model\NodeInterface; @@ -77,6 +78,11 @@ class ConvertUrisImplementationTest extends UnitTestCase */ protected $mockUriBuilder; + /** + * @var CachingHelper + */ + protected $mockCachingHelper; + public function setUp(): void { $this->convertUrisImplementation = $this->getAccessibleMock(ConvertUrisImplementation::class, ['fusionValue'], [], '', false); @@ -85,6 +91,9 @@ public function setUp(): void $this->mockContext = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock(); $this->mockContext->expects(self::any())->method('getWorkspace')->will(self::returnValue($this->mockWorkspace)); + $this->mockContext->expects(self::any())->method('getWorkspaceName')->willReturnCallback(function () { + return $this->mockWorkspace->getName(); + }); $this->mockNode = $this->getMockBuilder(NodeInterface::class)->getMock(); $this->mockNode->expects(self::any())->method('getContext')->will(self::returnValue($this->mockContext)); @@ -104,6 +113,9 @@ public function setUp(): void $this->mockLinkingService = $this->createMock(LinkingService::class); $this->convertUrisImplementation->_set('linkingService', $this->mockLinkingService); + $this->mockCachingHelper = $this->createMock(CachingHelper::class); + $this->convertUrisImplementation->_set('cachingHelper', $this->mockCachingHelper); + $this->mockRuntime = $this->getMockBuilder(Runtime::class)->disableOriginalConstructor()->getMock(); $this->mockRuntime->expects(self::any())->method('getControllerContext')->will(self::returnValue($this->mockControllerContext)); $this->convertUrisImplementation->_set('runtime', $this->mockRuntime); @@ -347,4 +359,27 @@ public function evaluateReplaceResourceLinkTargetsInsideTag() $actualResult = $this->convertUrisImplementation->evaluate(); $this->assertSame($expectedResult, $actualResult); } + + /** + * @test + */ + public function evaluateDoesAddCacheTags() + { + $workspaceName = 'live'; + $workspaceNameHash = 'hashedworkspacename'; + $nodeIdentifier = 'aeabe76a-551a-495f-a324-ad9a86b2aff7'; + $nodeCacheIdentifier = 'hashedworkspacename_aeabe76a-551a-495f-a324-ad9a86b2aff7'; + $assetIdentifier = 'cb2d0e4a-7d2f-4601-981a-f9a01530f53f'; + $assetCacheIdentifier = 'hashedworkspacename_cb2d0e4a-7d2f-4601-981a-f9a01530f53f'; + + $value = 'This string contains a node URI: node://' . $nodeIdentifier . ' and asset link.'; + $this->addValueExpectation($value, null, true); + + $this->mockWorkspace->expects(self::any())->method('getName')->willReturn($workspaceName); + $this->mockCachingHelper->expects(self::any())->method('renderWorkspaceTagForContextNode')->with($workspaceName)->willReturn($workspaceNameHash); + + $this->mockRuntime->expects(self::exactly(2))->method('addCacheTag')->withConsecutive(['node', $nodeCacheIdentifier], ['asset', $assetCacheIdentifier]); + + $this->convertUrisImplementation->evaluate(); + } }