From 50d6e204db743a32381ac8f2510beec6c317c84f Mon Sep 17 00:00:00 2001 From: mhsdesign <85400359+mhsdesign@users.noreply.github.com> Date: Thu, 16 Nov 2023 21:06:17 +0100 Subject: [PATCH] TASK: Adjust to split up references and properties --- Classes/Domain/Model/Changes/Property.php | 42 ++++----- .../Service/NodePropertyConversionService.php | 13 +-- .../Service/NodePropertyConverterService.php | 86 +++++++++---------- Classes/Fusion/Helper/NodeInfoHelper.php | 1 + ...reationDialogPropertiesCreationHandler.php | 2 +- 5 files changed, 64 insertions(+), 80 deletions(-) diff --git a/Classes/Domain/Model/Changes/Property.php b/Classes/Domain/Model/Changes/Property.php index 448a15a260..6f9d542606 100644 --- a/Classes/Domain/Model/Changes/Property.php +++ b/Classes/Domain/Model/Changes/Property.php @@ -134,9 +134,8 @@ public function canApply(): bool } $nodeType = $this->subject->nodeType; $propertyName = $this->getPropertyName(); - $nodeTypeProperties = $nodeType->getProperties(); - return isset($nodeTypeProperties[$propertyName]); + return $nodeType->hasProperty($propertyName) || $nodeType->hasReference($propertyName); } /** @@ -153,26 +152,16 @@ public function apply(): void if ($this->canApply() && !is_null($subject) && !is_null($propertyName)) { $contentRepository = $this->contentRepositoryRegistry->get($subject->subgraphIdentity->contentRepositoryId); - $propertyType = $this->getNodeType($subject)->getPropertyType($propertyName); - - // Use extra commands for reference handling - if ($propertyType === 'reference' || $propertyType === 'references') { + if ($this->getNodeType($subject)->hasReference($propertyName)) { + // Use extra commands for reference handling $value = $this->getValue(); + $destinationNodeAggregateIds = []; - if ($propertyType === 'reference') { - if (is_string($value) && !empty($value)) { - $destinationNodeAggregateIds[] = $value; - } - } - if ($propertyType === 'references') { - /** @var array $values */ - $values = $value; - if (is_array($values)) { - foreach ($values as $singleNodeAggregateId) { - $destinationNodeAggregateIds[] = $singleNodeAggregateId; - } - } + if (is_string($value) && !empty($value)) { + $destinationNodeAggregateIds = [$value]; + } elseif (is_array($value)) { + $destinationNodeAggregateIds = $value; } $commandResult = $contentRepository->handle( @@ -278,8 +267,12 @@ public function apply(): void $updateNodeInfo->setNode($node); $this->feedbackCollection->add($updateNodeInfo); - $reloadIfChangedConfigurationPath = sprintf('properties.%s.ui.reloadIfChanged', $propertyName); - if (!$this->getIsInline() && $this->getNodeType($node)->getConfiguration($reloadIfChangedConfigurationPath)) { + if (!$this->getIsInline() + && ( + $this->getNodeType($node)->hasConfiguration(sprintf('properties.%s.ui.reloadIfChanged', $propertyName)) + || $this->getNodeType($node)->hasConfiguration(sprintf('references.%s.ui.reloadIfChanged', $propertyName)) + ) + ) { if ($this->getNodeDomAddress() && $this->getNodeDomAddress()->getFusionPath() && $parentNode && $this->getNodeType($parentNode)->isOfType('Neos.Neos:ContentCollection')) { @@ -292,9 +285,12 @@ public function apply(): void } } - $reloadPageIfChangedConfigurationPath = sprintf('properties.%s.ui.reloadPageIfChanged', $propertyName); if (!$this->getIsInline() - && $this->getNodeType($node)->getConfiguration($reloadPageIfChangedConfigurationPath)) { + && ( + $this->getNodeType($node)->hasConfiguration(sprintf('properties.%s.ui.reloadPageIfChanged', $propertyName)) + || $this->getNodeType($node)->hasConfiguration(sprintf('references.%s.ui.reloadPageIfChanged', $propertyName)) + ) + ) { $this->reloadDocument($node); } } diff --git a/Classes/Domain/Service/NodePropertyConversionService.php b/Classes/Domain/Service/NodePropertyConversionService.php index 2e5af9169e..fe27ee9ee8 100644 --- a/Classes/Domain/Service/NodePropertyConversionService.php +++ b/Classes/Domain/Service/NodePropertyConversionService.php @@ -44,9 +44,10 @@ class NodePropertyConversionService */ public function convert(NodeType $nodeType, string $propertyName, string|array|null $rawValue): mixed { - // WORKAROUND: $nodeType->getPropertyType() is missing the "initialize" call, - // so we need to trigger another method beforehand. - $nodeType->getFullConfiguration(); + if ($nodeType->hasReference($propertyName)) { + throw new \Exception("not implemented here, must be handled outside."); + } + $propertyType = $nodeType->getPropertyType($propertyName); if (is_null($rawValue)) { @@ -57,12 +58,6 @@ public function convert(NodeType $nodeType, string $propertyName, string|array|n case 'string': return $rawValue; - case 'reference': - throw new \Exception("not implemented here, must be handled outside."); - - case 'references': - throw new \Exception("not implemented here, must be handled outside."); - case 'DateTime': return $this->convertDateTime($rawValue); diff --git a/Classes/Domain/Service/NodePropertyConverterService.php b/Classes/Domain/Service/NodePropertyConverterService.php index ad098a8ad0..e152db8e3a 100644 --- a/Classes/Domain/Service/NodePropertyConverterService.php +++ b/Classes/Domain/Service/NodePropertyConverterService.php @@ -17,7 +17,6 @@ use Neos\ContentRepository\Core\NodeType\NodeType; use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindReferencesFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; -use Neos\ContentRepository\Core\Projection\ContentGraph\References; use Neos\ContentRepository\Core\Projection\NodeHiddenState\NodeHiddenStateFinder; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; use Neos\Flow\Annotations as Flow; @@ -40,6 +39,7 @@ * THIS IS DIRTY CODE. In the longer run, the neos UI should work DIRECTLY with serialized properties * instead of the objects. * + * @internal * @Flow\Scope("singleton") */ class NodePropertyConverterService @@ -99,14 +99,40 @@ public function injectThrowableStorage(ThrowableStorageInterface $throwableStora $this->throwableStorage = $throwableStorage; } + /** + * @return list|string|null + */ + private function getReference(Node $node, string $referenceName): array|string|null + { + $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); + $references = $subgraph->findReferences( + $node->nodeAggregateId, + FindReferencesFilter::create(referenceName: $referenceName) + ); + + $referenceIdentifiers = []; + foreach ($references as $reference) { + $referenceIdentifiers[] = $reference->node->nodeAggregateId->value; + } + + $maxItems = $this->getNodeType($node)->getReferences()[$referenceName]['constraints']['maxItems'] ?? null; + + if ($maxItems === 1) { + // special handling to simulate old single reference behaviour. + // todo should be adjusted in the ui + if (count($referenceIdentifiers) === 0) { + return null; + } else { + return reset($referenceIdentifiers); + } + } + return $referenceIdentifiers; + } + /** * Get a single property reduced to a simple type (no objects) representation - * - * @param Node $node - * @param string $propertyName - * @return mixed */ - public function getProperty(Node $node, $propertyName) + private function getProperty(Node $node, string $propertyName): mixed { if ($propertyName === '_hidden') { $contentRepository = $this->contentRepositoryRegistry->get($node->subgraphIdentity->contentRepositoryId); @@ -118,38 +144,14 @@ public function getProperty(Node $node, $propertyName) $node->nodeAggregateId )->isHidden; } - $propertyType = $this->getNodeType($node)->getPropertyType($propertyName); - - // We handle "reference" and "references" differently than other properties; - // because we need to use another API for querying these references. - if ($propertyType === 'reference') { - $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); - $referenceIdentifiers = $this->toNodeIdentifierStrings( - $subgraph->findReferences( - $node->nodeAggregateId, - FindReferencesFilter::create(referenceName: $propertyName) - ) - ); - if (count($referenceIdentifiers) === 0) { - return null; - } else { - return reset($referenceIdentifiers); - } - } elseif ($propertyType === 'references') { - $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); - $references = $subgraph->findReferences( - $node->nodeAggregateId, - FindReferencesFilter::create(referenceName: $propertyName) - ); - return $this->toNodeIdentifierStrings($references); - // Here, the normal property access logic starts. - } elseif ($propertyName[0] === '_' && $propertyName !== '_hiddenInIndex') { + if ($propertyName[0] === '_' && $propertyName !== '_hiddenInIndex') { $propertyValue = ObjectAccess::getProperty($node, ltrim($propertyName, '_')); } else { $propertyValue = $node->getProperty($propertyName); } + $propertyType = $this->getNodeType($node)->getPropertyType($propertyName); try { $convertedValue = $this->convertValue($propertyValue, $propertyType); } catch (PropertyException $exception) { @@ -175,19 +177,7 @@ public function getProperty(Node $node, $propertyName) } /** - * @return array - */ - private function toNodeIdentifierStrings(References $references): array - { - $identifiers = []; - foreach ($references as $reference) { - $identifiers[] = $reference->node->nodeAggregateId->value; - } - return $identifiers; - } - - /** - * Get all properties reduced to simple type (no objects) representations in an array + * Get all properties and references stuff reduced to simple type (no objects) representations in an array * * @param Node $node * @return array @@ -195,7 +185,7 @@ private function toNodeIdentifierStrings(References $references): array public function getPropertiesArray(Node $node) { $properties = []; - foreach ($this->getNodeType($node)->getProperties() as $propertyName => $propertyConfiguration) { + foreach ($this->getNodeType($node)->getProperties() as $propertyName => $_) { if ($propertyName[0] === '_' && $propertyName[1] === '_') { // skip fully-private properties continue; @@ -203,7 +193,9 @@ public function getPropertiesArray(Node $node) $properties[$propertyName] = $this->getProperty($node, $propertyName); } - + foreach ($this->getNodeType($node)->getReferences() as $referenceName => $_) { + $properties[$referenceName] = $this->getReference($node, $referenceName); + } return $properties; } diff --git a/Classes/Fusion/Helper/NodeInfoHelper.php b/Classes/Fusion/Helper/NodeInfoHelper.php index 5ebbca8ef1..3e03a9e4b9 100644 --- a/Classes/Fusion/Helper/NodeInfoHelper.php +++ b/Classes/Fusion/Helper/NodeInfoHelper.php @@ -30,6 +30,7 @@ use Neos\Neos\Utility\NodeTypeWithFallbackProvider; /** + * @internal * @Flow\Scope("singleton") */ class NodeInfoHelper implements ProtectedContextAwareInterface diff --git a/Classes/NodeCreationHandler/CreationDialogPropertiesCreationHandler.php b/Classes/NodeCreationHandler/CreationDialogPropertiesCreationHandler.php index 6d3233db63..3e75ee391c 100644 --- a/Classes/NodeCreationHandler/CreationDialogPropertiesCreationHandler.php +++ b/Classes/NodeCreationHandler/CreationDialogPropertiesCreationHandler.php @@ -55,7 +55,7 @@ public function handle(CreateNodeAggregateWithNode $command, array $data, Conten continue; } $propertyValue = $data[$propertyName]; - if ($propertyType !== 'references' && $propertyType !== 'reference' && $propertyType !== TypeHandling::getTypeForValue($propertyValue)) { + if (!$nodeType->hasReference($propertyName) && $propertyType !== TypeHandling::getTypeForValue($propertyValue)) { $propertyValue = $this->propertyMapper->convert($propertyValue, $propertyType, $propertyMappingConfiguration); }