Skip to content

Commit 4202759

Browse files
skurfuerstPingu501
authored andcommitted
FEATURE: support for different output formats, with differing documentRenderers and custom enumerators
# Conflicts: # Classes/NodeEnumeration/Domain/Dto/EnumeratedNode.php # Classes/NodeEnumeration/NodeEnumerator.php # Classes/NodeRendering/NodeRenderer.php
1 parent 70162b8 commit 4202759

11 files changed

Lines changed: 288 additions & 43 deletions

File tree

Classes/NodeEnumeration/Domain/Dto/EnumeratedNode.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,24 @@ final class EnumeratedNode implements \JsonSerializable
4141
*/
4242
protected $nodeTypeName;
4343

44-
private function __construct(string $contextPath, string $nodeIdentifier, string $nodeTypeName, array $arguments)
44+
/**
45+
* The renderer implementation to use for this EnumeratedNode;
46+
* a key from Settings at Flowpack.DecoupledContentStore.extensions.documentRenderers.[key]
47+
*/
48+
public readonly string $rendererId;
49+
50+
private function __construct(string $contextPath, string $nodeIdentifier, string $nodeTypeName, array $arguments, string $rendererId = '')
4551
{
4652
$this->contextPath = $contextPath;
4753
$this->nodeIdentifier = $nodeIdentifier;
4854
$this->nodeTypeName = $nodeTypeName;
4955
$this->arguments = $arguments;
56+
$this->rendererId = $rendererId;
5057
}
5158

5259
static public function fromNode(NodeInterface $node, array $arguments = []): self
5360
{
54-
return new self($node->getContextPath(), $node->getIdentifier(), $node->getNodeType()->getName(), $arguments);
61+
return new self($node->getContextPath(), $node->getIdentifier(), $node->getNodeType()->getName(), $arguments, '');
5562
}
5663

5764
static public function fromJsonString(string $enumeratedNodeString): self
@@ -60,7 +67,7 @@ static public function fromJsonString(string $enumeratedNodeString): self
6067
if (!is_array($tmp)) {
6168
throw new \Exception('EnumeratedNode cannot be constructed from: ' . $enumeratedNodeString);
6269
}
63-
return new self($tmp['contextPath'], $tmp['nodeIdentifier'], $tmp['nodeTypeName'] ?? '', $tmp['arguments']);
70+
return new self($tmp['contextPath'], $tmp['nodeIdentifier'], $tmp['nodeTypeName'] ?? '', $tmp['arguments'], $tmp['rendererId']);
6471
}
6572

6673
public function jsonSerialize(): array
@@ -70,6 +77,7 @@ public function jsonSerialize(): array
7077
'nodeIdentifier' => $this->nodeIdentifier,
7178
'nodeTypeName' => $this->nodeTypeName,
7279
'arguments' => $this->arguments,
80+
'rendererId' => $this->rendererId,
7381
];
7482
}
7583

@@ -111,6 +119,11 @@ public function getArguments(): array
111119

112120
public function debugString(): string
113121
{
114-
return sprintf('%s %s %s(%s)', $this->nodeTypeName, $this->nodeIdentifier, $this->arguments ? http_build_query($this->arguments) . ' ' : '', $this->contextPath);
122+
return sprintf('%s %s %s(%s) - %s', $this->nodeTypeName, $this->nodeIdentifier, $this->arguments ? http_build_query($this->arguments) . ' ' : '', $this->contextPath, $this->rendererId);
123+
}
124+
125+
public function withRendererId(string $rendererId): self
126+
{
127+
return new self($this->contextPath, $this->nodeIdentifier, $this->nodeTypeName, $this->arguments, $rendererId);
115128
}
116129
}

Classes/NodeEnumeration/NodeEnumerator.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Repository\RedisEnumerationRepository;
1212
use Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Service\NodeContextCombinator;
1313
use Flowpack\DecoupledContentStore\NodeRendering\Dto\NodeRenderingCompletionStatus;
14+
use Flowpack\DecoupledContentStore\NodeRendering\Extensibility\NodeRenderingExtensionManager;
1415
use Flowpack\DecoupledContentStore\PrepareContentRelease\Infrastructure\RedisContentReleaseService;
1516
use Flowpack\DecoupledContentStore\Utility\GeneratorUtility;
1617
use Neos\ContentRepository\Domain\Model\NodeInterface;
@@ -40,6 +41,12 @@ class NodeEnumerator
4041
*/
4142
protected $concurrentBuildLockService;
4243

44+
/**
45+
* @Flow\Inject
46+
* @var NodeRenderingExtensionManager
47+
*/
48+
protected $nodeRenderingExtensionManager;
49+
4350
/**
4451
* @Flow\InjectConfiguration("nodeRendering.nodeTypeWhitelist")
4552
* @var string
@@ -74,9 +81,10 @@ public function enumerateAndStoreInRedis(
7481
) {
7582
$this->concurrentBuildLockService->assertNoOtherContentReleaseWasStarted($releaseIdentifier);
7683
// $enumeration is an array of EnumeratedNode, with at most 100 elements in it.
77-
// TODO: EXTENSION POINT HERE, TO ADD ADDITIONAL ENUMERATIONS (.metadata.json f.e.)
78-
// TODO: not yet fully sure how to handle Enumeration
84+
7985
$this->redisEnumerationRepository->addDocumentNodesToEnumeration($releaseIdentifier, ...$enumeration);
86+
87+
// DEPRECATED: use extensions.documentRenderers.[...].enumeratorClassName instead
8088
foreach ($enumeration as $enumeratedNode) {
8189
$this->emitNodeEnumerated($enumeratedNode, $releaseIdentifier, $contentReleaseLogger);
8290
}
@@ -116,6 +124,7 @@ private function enumerateAll(
116124
'name' => $site->getName(),
117125
'domain' => $site->getFirstActiveDomain()
118126
]);
127+
119128
foreach ($combinator->siteNodeInContexts($site, $workspaceName) as $siteNode) {
120129
$startTime = microtime(true);
121130
$dimensionValues = $siteNode->getContext()->getDimensions();
@@ -178,6 +187,8 @@ private function enumerateAll(
178187
*
179188
* This signal can be used to add additional EnumeratedNode entries (e.g. with added arguments for pagination or filters) based on the given node.
180189
*
190+
* DEPRECATED: use extensions.documentRenderers.[...].enumeratorClassName instead
191+
*
181192
* @param EnumeratedNode $enumeratedNode
182193
* @param ContentReleaseIdentifier $releaseIdentifier
183194
* @param ContentReleaseLogger $contentReleaseLogger
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\DecoupledContentStore\NodeRendering\Extensibility;
5+
6+
use Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Dto\EnumeratedNode;
7+
use Neos\ContentRepository\Domain\Model\NodeInterface;
8+
9+
/**
10+
* Adjust document enumeration.
11+
*
12+
* The Document Enumeration decides for every Document Node what variants should appear
13+
* in the resulting Content Release.
14+
*
15+
* It should return an array of {@see EnumeratedNode} objects.
16+
*
17+
* This can be used to:
18+
* - render document nodes in different variants, e.g. formats
19+
* - use different renderers (configured via Flowpack.DecoupledContentStore.extensions.documentRenderers.[...])
20+
* - decide at runtime which (document) nodes should be part of a content release and which not.
21+
*/
22+
interface DocumentEnumeratorInterface
23+
{
24+
public function __construct(array $options = []);
25+
26+
/**
27+
* @return iterable<EnumeratedNode>
28+
*/
29+
public function enumerateDocumentNode(NodeInterface $documentNode): iterable;
30+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Flowpack\DecoupledContentStore\NodeRendering\Extensibility\DocumentEnumerators;
4+
5+
use Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Dto\EnumeratedNode;
6+
use Flowpack\DecoupledContentStore\NodeRendering\Extensibility\DocumentEnumeratorInterface;
7+
use Neos\ContentRepository\Domain\Model\NodeInterface;
8+
9+
class DefaultEnumerator implements DocumentEnumeratorInterface
10+
{
11+
public function __construct(array $options = [])
12+
{
13+
}
14+
15+
public function enumerateDocumentNode(NodeInterface $documentNode): iterable
16+
{
17+
return [
18+
EnumeratedNode::fromNode($documentNode),
19+
];
20+
}
21+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Flowpack\DecoupledContentStore\NodeRendering\Extensibility\DocumentEnumerators;
4+
5+
use Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Dto\EnumeratedNode;
6+
use Flowpack\DecoupledContentStore\NodeRendering\Extensibility\DocumentEnumeratorInterface;
7+
use Neos\ContentRepository\Domain\Model\NodeInterface;
8+
9+
/**
10+
* An enumerator which only renders the first N pages. very useful for interactive testing.
11+
* NOT useful for production.
12+
*/
13+
class LimitEnumerator implements DocumentEnumeratorInterface
14+
{
15+
protected int $i = 0;
16+
private int $limit;
17+
18+
public function __construct(
19+
array $options = []
20+
) {
21+
$this->limit = $options['limit'] ?? throw new \InvalidArgumentException('Missing limit option');
22+
}
23+
public function enumerateDocumentNode(NodeInterface $documentNode): iterable
24+
{
25+
if ($this->i++ >= $this->limit) {
26+
return [];
27+
}
28+
29+
return [
30+
EnumeratedNode::fromNode($documentNode),
31+
];
32+
}
33+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\DecoupledContentStore\NodeRendering\Extensibility;
5+
6+
use Flowpack\DecoupledContentStore\Core\Infrastructure\ContentReleaseLogger;
7+
use Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Dto\EnumeratedNode;
8+
use Flowpack\DecoupledContentStore\NodeRendering\Dto\RenderedDocumentFromContentCache;
9+
use Flowpack\DecoupledContentStore\NodeRendering\NodeRenderer;
10+
use Flowpack\DecoupledContentStore\NodeRendering\NodeRenderOrchestrator;
11+
use Neos\ContentRepository\Domain\Model\NodeInterface;
12+
13+
/**
14+
* Decide how to render a document node. Used throughout {@see NodeRenderOrchestrator} and {@see NodeRenderer}
15+
* for the specific rendering logic.
16+
*
17+
* If you want to create additional output formats (e.g. JSON), or you want rendering without
18+
* Fusion, you'll need to create a custom DocumentRenderer.
19+
*/
20+
interface DocumentRendererInterface
21+
{
22+
public function tryToExtractRenderingForEnumeratedNodeFromContentCache(EnumeratedNode $enumeratedNode): RenderedDocumentFromContentCache;
23+
24+
public function renderDocumentNodeVariant(NodeInterface $node, EnumeratedNode $enumeratedNode, ContentReleaseLogger $contentReleaseLogger);
25+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Flowpack\DecoupledContentStore\NodeRendering\Extensibility\DocumentRenderers;
4+
5+
use Neos\Flow\Annotations as Flow;
6+
use Flowpack\DecoupledContentStore\Core\Infrastructure\ContentReleaseLogger;
7+
use Flowpack\DecoupledContentStore\NodeEnumeration\Domain\Dto\EnumeratedNode;
8+
use Flowpack\DecoupledContentStore\NodeRendering\Dto\DocumentNodeCacheKey;
9+
use Flowpack\DecoupledContentStore\NodeRendering\Dto\RenderedDocumentFromContentCache;
10+
use Flowpack\DecoupledContentStore\NodeRendering\Extensibility\DocumentRendererInterface;
11+
use Flowpack\DecoupledContentStore\NodeRendering\Infrastructure\RedisContentCacheReader;
12+
use Flowpack\DecoupledContentStore\NodeRendering\Render\DocumentRenderer;
13+
use Neos\ContentRepository\Domain\Model\NodeInterface;
14+
15+
class FusionHtmlRenderer implements DocumentRendererInterface
16+
{
17+
18+
/**
19+
* @Flow\Inject
20+
* @var RedisContentCacheReader
21+
*/
22+
protected $redisContentCacheReader;
23+
24+
/**
25+
* @Flow\Inject
26+
* @var DocumentRenderer
27+
*/
28+
protected $documentRenderer;
29+
30+
31+
public function tryToExtractRenderingForEnumeratedNodeFromContentCache(EnumeratedNode $enumeratedNode): RenderedDocumentFromContentCache
32+
{
33+
return $this->redisContentCacheReader->tryToExtractRenderingForEnumeratedNodeFromContentCache(DocumentNodeCacheKey::fromEnumeratedNode($enumeratedNode));
34+
}
35+
36+
public function renderDocumentNodeVariant(NodeInterface $node, EnumeratedNode $enumeratedNode, ContentReleaseLogger $contentReleaseLogger)
37+
{
38+
return $this->documentRenderer->renderDocumentNodeVariant($node, $enumeratedNode->getArguments(), $contentReleaseLogger);
39+
}
40+
}

0 commit comments

Comments
 (0)