Skip to content

Commit

Permalink
TASK: Introduce NeosFusionContextSerializer to replace node propert…
Browse files Browse the repository at this point in the history
…y converters
  • Loading branch information
mhsdesign committed Feb 3, 2024
1 parent 76a72a8 commit 6a99952
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 188 deletions.
4 changes: 2 additions & 2 deletions Neos.Fusion/Classes/Core/Cache/ContentCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public function createCacheSegment($content, $fusionPath, array $cacheIdentifier
*
* @param string $content The content rendered by the Fusion Runtime
* @param string $fusionPath The Fusion path that rendered the content, for example "page<Acme.Com:Page>/body<Acme.Demo:DefaultPageTemplate>/parts/breadcrumbMenu"
* @param array<string, array{type: string, value: string}> $serializedContext Serialized Fusion context variables which are needed to correctly render the specified Fusion object
* @param array<string, array{type: string, value: mixed}> $serializedContext Serialized Fusion context variables which are needed to correctly render the specified Fusion object
* @return string The original content, but with additional markers added
*/
public function createUncachedSegment($content, $fusionPath, array $serializedContext)
Expand All @@ -141,7 +141,7 @@ public function createUncachedSegment($content, $fusionPath, array $serializedCo
*
* @param string $content The content rendered by the Fusion Runtime
* @param string $fusionPath The Fusion path that rendered the content, for example "page<Acme.Com:Page>/body<Acme.Demo:DefaultPageTemplate>/parts/breadcrumbMenu"
* @param array<string, array{type: string, value: string}> $serializedContext Serialized Fusion context variables which are needed to correctly render the specified Fusion object
* @param array<string, array{type: string, value: mixed}> $serializedContext Serialized Fusion context variables which are needed to correctly render the specified Fusion object
* @param array $cacheIdentifierValues
* @param array $tags Tags to add to the cache entry
* @param integer $lifetime Lifetime of the cache segment in seconds. NULL for the default lifetime and 0 for unlimited lifetime.
Expand Down
10 changes: 10 additions & 0 deletions Neos.Fusion/Classes/Core/Cache/FusionContextSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,18 @@ public function __construct(
) {
}

/**
* @param array<int|string,mixed> $context
*/
public function denormalize(mixed $data, string $type, string $format = null, array $context = [])
{
return $this->propertyMapper->convert($data, $type);
}

/**
* @param array<int|string,mixed> $context
* @return array<int|string,mixed>
*/
public function normalize(mixed $object, string $format = null, array $context = [])
{
return $this->propertyMapper->convert($object, 'string');
Expand All @@ -46,6 +53,9 @@ public function supportsNormalization(mixed $data, string $format = null)
throw new \BadMethodCallException(sprintf('Method %s is not supported.', __METHOD__), 1706978913);
}

/**
* @return array<int|string,mixed>
*/
public function getSupportedTypes(?string $format): array
{
throw new \BadMethodCallException(sprintf('Method %s is not supported.', __METHOD__), 1706978914);
Expand Down
6 changes: 3 additions & 3 deletions Neos.Fusion/Classes/Core/Cache/RuntimeContentCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function __construct(Runtime $runtime)
$this->runtime = $runtime;
}

public function injectSerializer(NormalizerInterface&DenormalizerInterface $serializer)
public function injectSerializer(NormalizerInterface&DenormalizerInterface $serializer): void
{
$this->serializer = $serializer;
}
Expand Down Expand Up @@ -375,7 +375,7 @@ protected function buildCacheTags(array $configuration, $fusionPath, $fusionObje
* {@see self::unserializeContext()}
*
* @param array<string, mixed> $contextVariables
* @return array<string, array{type: string, value: string}>
* @return array<string, array{type: string, value: mixed}>
*/
protected function serializeContext(array $contextVariables): array
{
Expand All @@ -394,7 +394,7 @@ protected function serializeContext(array $contextVariables): array
* Decodes and serialized array of context variables to its original values
* {@see self::serializeContext()}
*
* @param array<string, array{type: string, value: string}> $contextArray
* @param array<string, array{type: string, value: mixed}> $contextArray
* @return array<string, mixed>
*/
protected function unserializeContext(array $contextArray): array
Expand Down
128 changes: 128 additions & 0 deletions Neos.Neos/Classes/Fusion/Cache/NeosFusionContextSerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

declare(strict_types=1);

namespace Neos\Neos\Fusion\Cache;

use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentRepository\Core\Factory\ContentRepositoryId;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
use Neos\Fusion\Core\Cache\FusionContextSerializer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

/**
* Serializer for Fusion's [at]cache.context values
*
* Uses the flow property mapper as implementation.
* It relies on a converter being available from the context value type to string and reverse.
*
* {@see FusionContextSerializer}
*
* @internal
*/
final class NeosFusionContextSerializer implements NormalizerInterface, DenormalizerInterface
{
public function __construct(
private readonly FusionContextSerializer $fusionContextSerializer,
private readonly ContentRepositoryRegistry $contentRepositoryRegistry
) {
}

/**
* @param array<int|string,mixed> $context
*/
public function denormalize(mixed $data, string $type, string $format = null, array $context = [])
{
if ($type === Node::class) {
return $this->deserializeNode($data);
}
return $this->fusionContextSerializer->denormalize($data, $type, $format, $context);
}

/**
* @param array<int|string,mixed> $context
* @return array<int|string,mixed>
*/
public function normalize(mixed $object, string $format = null, array $context = [])
{
if ($object instanceof Node) {
return $this->serializeNode($object);
}
return $this->fusionContextSerializer->normalize($object, $format, $context);
}

/**
* @param array<int|string,mixed> $serializedNode
*/
private function deserializeNode(array $serializedNode): Node
{
$contentRepositoryId = ContentRepositoryId::fromString($serializedNode['contentRepositoryId']);

$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);

$workspace = $contentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($serializedNode['workspaceName']));
if (!$workspace) {
throw new \RuntimeException(sprintf('Could not find workspace while trying to convert node from array %s.', json_encode($serializedNode)), 1699782153);
}

$subgraph = $contentRepository->getContentGraph()->getSubgraph(
$workspace->currentContentStreamId,
DimensionSpacePoint::fromArray($serializedNode['dimensionSpacePoint']),
$workspace->isPublicWorkspace()
? VisibilityConstraints::frontend()
: VisibilityConstraints::withoutRestrictions()
);

$node = $subgraph->findNodeById(NodeAggregateId::fromString($serializedNode['nodeAggregateId']));
if (!$node) {
throw new \RuntimeException(sprintf('Could not find serialized node %s.', json_encode($serializedNode)), 1699782153);
}
return $node;
}

/**
* @return array<int|string,mixed>
*/
private function serializeNode(Node $source): array
{
$contentRepository = $this->contentRepositoryRegistry->get(
$source->subgraphIdentity->contentRepositoryId
);

$workspace = $contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId($source->subgraphIdentity->contentStreamId);

if (!$workspace) {
throw new \RuntimeException(sprintf('Could not fetch workspace for node (%s) in content stream (%s).', $source->nodeAggregateId->value, $source->subgraphIdentity->contentStreamId->value), 1699780153);
}

return [
'contentRepositoryId' => $source->subgraphIdentity->contentRepositoryId->value,
'workspaceName' => $workspace->workspaceName->value,
'dimensionSpacePoint' => $source->subgraphIdentity->dimensionSpacePoint->jsonSerialize(),
'nodeAggregateId' => $source->nodeAggregateId->value
];
}

public function supportsDenormalization(mixed $data, string $type, string $format = null)
{
throw new \BadMethodCallException(sprintf('Method %s is not supported.', __METHOD__), 1706978912);
}

public function supportsNormalization(mixed $data, string $format = null)
{
throw new \BadMethodCallException(sprintf('Method %s is not supported.', __METHOD__), 1706978913);
}

/**
* @return array<int|string,mixed>
*/
public function getSupportedTypes(?string $format): array
{
throw new \BadMethodCallException(sprintf('Method %s is not supported.', __METHOD__), 1706978914);
}
}
96 changes: 0 additions & 96 deletions Neos.Neos/Classes/TypeConverter/JsonStringToNodeConverter.php

This file was deleted.

87 changes: 0 additions & 87 deletions Neos.Neos/Classes/TypeConverter/NodeToJsonStringSerializer.php

This file was deleted.

5 changes: 5 additions & 0 deletions Neos.Neos/Configuration/Objects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ Neos\Neos\Domain\Service\FusionConfigurationCache:
2:
setting: "Neos.Neos.fusion.enableObjectTreeCache"

Neos\Fusion\Core\Cache\RuntimeContentCache:
properties:
serializer:
object: Neos\Neos\Fusion\Cache\NeosFusionContextSerializer

Neos\Neos\FrontendRouting\FrontendNodeRoutePartHandlerInterface:
className: Neos\Neos\FrontendRouting\EventSourcedFrontendNodeRoutePartHandler

Expand Down

0 comments on commit 6a99952

Please sign in to comment.