From 5bba6e813f74e3f0278a6ddae55108dbca8d7627 Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Sat, 3 Feb 2024 18:17:40 +0100 Subject: [PATCH] TASK: Introduce `NeosFusionContextSerializer` to replace node property converters --- .../Classes/Core/Cache/ContentCache.php | 4 +- .../Core/Cache/FusionContextSerializer.php | 10 ++ .../Core/Cache/RuntimeContentCache.php | 6 +- .../Cache/NeosFusionContextSerializer.php | 128 ++++++++++++++++++ .../JsonStringToNodeConverter.php | 96 ------------- .../NodeToJsonStringSerializer.php | 87 ------------ Neos.Neos/Configuration/Objects.yaml | 5 + 7 files changed, 148 insertions(+), 188 deletions(-) create mode 100644 Neos.Neos/Classes/Fusion/Cache/NeosFusionContextSerializer.php delete mode 100644 Neos.Neos/Classes/TypeConverter/JsonStringToNodeConverter.php delete mode 100644 Neos.Neos/Classes/TypeConverter/NodeToJsonStringSerializer.php diff --git a/Neos.Fusion/Classes/Core/Cache/ContentCache.php b/Neos.Fusion/Classes/Core/Cache/ContentCache.php index 1558ea2a4b4..687bb041658 100644 --- a/Neos.Fusion/Classes/Core/Cache/ContentCache.php +++ b/Neos.Fusion/Classes/Core/Cache/ContentCache.php @@ -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/body/parts/breadcrumbMenu" - * @param array $serializedContext Serialized Fusion context variables which are needed to correctly render the specified Fusion object + * @param array $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) @@ -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/body/parts/breadcrumbMenu" - * @param array $serializedContext Serialized Fusion context variables which are needed to correctly render the specified Fusion object + * @param array $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. diff --git a/Neos.Fusion/Classes/Core/Cache/FusionContextSerializer.php b/Neos.Fusion/Classes/Core/Cache/FusionContextSerializer.php index f3897166fea..ab22006fb87 100644 --- a/Neos.Fusion/Classes/Core/Cache/FusionContextSerializer.php +++ b/Neos.Fusion/Classes/Core/Cache/FusionContextSerializer.php @@ -26,11 +26,18 @@ public function __construct( ) { } + /** + * @param array $context + */ public function denormalize(mixed $data, string $type, string $format = null, array $context = []) { return $this->propertyMapper->convert($data, $type); } + /** + * @param array $context + * @return array + */ public function normalize(mixed $object, string $format = null, array $context = []) { return $this->propertyMapper->convert($object, 'string'); @@ -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 + */ public function getSupportedTypes(?string $format): array { throw new \BadMethodCallException(sprintf('Method %s is not supported.', __METHOD__), 1706978914); diff --git a/Neos.Fusion/Classes/Core/Cache/RuntimeContentCache.php b/Neos.Fusion/Classes/Core/Cache/RuntimeContentCache.php index 123d172081a..447f8609d9f 100644 --- a/Neos.Fusion/Classes/Core/Cache/RuntimeContentCache.php +++ b/Neos.Fusion/Classes/Core/Cache/RuntimeContentCache.php @@ -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; } @@ -375,7 +375,7 @@ protected function buildCacheTags(array $configuration, $fusionPath, $fusionObje * {@see self::unserializeContext()} * * @param array $contextVariables - * @return array + * @return array */ protected function serializeContext(array $contextVariables): array { @@ -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 $contextArray + * @param array $contextArray * @return array */ protected function unserializeContext(array $contextArray): array diff --git a/Neos.Neos/Classes/Fusion/Cache/NeosFusionContextSerializer.php b/Neos.Neos/Classes/Fusion/Cache/NeosFusionContextSerializer.php new file mode 100644 index 00000000000..b3f79121830 --- /dev/null +++ b/Neos.Neos/Classes/Fusion/Cache/NeosFusionContextSerializer.php @@ -0,0 +1,128 @@ + $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 $context + * @return array + */ + 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 $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 + */ + 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 + */ + public function getSupportedTypes(?string $format): array + { + throw new \BadMethodCallException(sprintf('Method %s is not supported.', __METHOD__), 1706978914); + } +} diff --git a/Neos.Neos/Classes/TypeConverter/JsonStringToNodeConverter.php b/Neos.Neos/Classes/TypeConverter/JsonStringToNodeConverter.php deleted file mode 100644 index e652bf64808..00000000000 --- a/Neos.Neos/Classes/TypeConverter/JsonStringToNodeConverter.php +++ /dev/null @@ -1,96 +0,0 @@ - - */ - protected $sourceTypes = ['string']; - - /** - * @var string - */ - protected $targetType = Node::class; - - /** - * @var integer - */ - protected $priority = 2; - - #[Flow\Inject] - protected ContentRepositoryRegistry $contentRepositoryRegistry; - - /** - * @param string $source - * @param string $targetType - * @param array $subProperties - * @return Node|null|\Neos\Error\Messages\Error - */ - public function convertFrom( - $source, - $targetType = null, - array $subProperties = [], - PropertyMappingConfigurationInterface $configuration = null - ) { - assert(is_string($source)); - - try { - $serializedNode = json_decode($source, true, 512, JSON_THROW_ON_ERROR); - } catch (\JsonException $e) { - return new \Neos\Error\Messages\Error(sprintf('Cannot convert assumed json string %s to node. %s', $source, $e->getMessage())); - } - - $contentRepositoryId = ContentRepositoryId::fromString($serializedNode['contentRepositoryId']); - - $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId); - - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($serializedNode['workspaceName'])); - if (!$workspace) { - return new \Neos\Error\Messages\Error('Could not find workspace while trying to convert node from json string %s.', 1699782153, [$source]); - } - - $subgraph = $contentRepository->getContentGraph()->getSubgraph( - $workspace->currentContentStreamId, - DimensionSpacePoint::fromArray($serializedNode['dimensionSpacePoint']), - $workspace->isPublicWorkspace() - ? VisibilityConstraints::frontend() - : VisibilityConstraints::withoutRestrictions() - ); - - return $subgraph->findNodeById(NodeAggregateId::fromString($serializedNode['nodeAggregateId'])); - } -} diff --git a/Neos.Neos/Classes/TypeConverter/NodeToJsonStringSerializer.php b/Neos.Neos/Classes/TypeConverter/NodeToJsonStringSerializer.php deleted file mode 100644 index 56dbb147f70..00000000000 --- a/Neos.Neos/Classes/TypeConverter/NodeToJsonStringSerializer.php +++ /dev/null @@ -1,87 +0,0 @@ - - */ - protected $sourceTypes = [Node::class]; - - /** - * @var string - */ - protected $targetType = 'string'; - - /** - * @var integer - */ - protected $priority = 1; - - /** - * @param Node $source - * @param string $targetType - * @param array $subProperties - * @return mixed|\Neos\Error\Messages\Error|string|null - */ - public function convertFrom( - $source, - $targetType = null, - array $subProperties = [], - PropertyMappingConfigurationInterface $configuration = null - ) { - assert($source instanceof Node); - - $contentRepository = $this->contentRepositoryRegistry->get( - $source->subgraphIdentity->contentRepositoryId - ); - - $workspace = $contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId($source->subgraphIdentity->contentStreamId); - - if (!$workspace) { - return new \Neos\Error\Messages\Error('Could not fetch workspace for node (%s) in content stream (%s).', 1699780153, [$source->nodeAggregateId->value, $source->subgraphIdentity->contentStreamId->value]); - } - - return json_encode([ - 'contentRepositoryId' => $source->subgraphIdentity->contentRepositoryId->value, - 'workspaceName' => $workspace->workspaceName->value, - 'dimensionSpacePoint' => $source->subgraphIdentity->dimensionSpacePoint->jsonSerialize(), - 'nodeAggregateId' => $source->nodeAggregateId->value - ], JSON_THROW_ON_ERROR); - } -} diff --git a/Neos.Neos/Configuration/Objects.yaml b/Neos.Neos/Configuration/Objects.yaml index fdc548b70fe..00f86de383c 100644 --- a/Neos.Neos/Configuration/Objects.yaml +++ b/Neos.Neos/Configuration/Objects.yaml @@ -20,6 +20,11 @@ Neos\Neos\Domain\Service\FusionConfigurationCache: 2: setting: "Neos.Neos.fusion.enableObjectTreeCache" +Neos\Fusion\Core\Cache\RuntimeContentCache: + properties: + serializer: + object: Neos\Fusion\Core\Cache\FusionContextSerializer + Neos\Neos\FrontendRouting\FrontendNodeRoutePartHandlerInterface: className: Neos\Neos\FrontendRouting\EventSourcedFrontendNodeRoutePartHandler