diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php index 3e91d0fc05a..52b86afce16 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Repository/NodeFactory.php @@ -176,7 +176,7 @@ public function mapNodeRowsToNodeAggregate( $rawNodeName = ''; $rawNodeAggregateClassification = ''; $occupiedDimensionSpacePoints = []; - $nodesByOccupiedDimensionSpacePoints = []; + $nodesByOccupiedDimensionSpacePoint = []; $coveredDimensionSpacePoints = []; $nodesByCoveredDimensionSpacePoints = []; $coverageByOccupants = []; @@ -186,9 +186,9 @@ public function mapNodeRowsToNodeAggregate( foreach ($nodeRows as $nodeRow) { // A node can occupy exactly one DSP and cover multiple ones... $occupiedDimensionSpacePoint = $this->dimensionSpacePointRepository->getOriginDimensionSpacePointByHash($nodeRow['origindimensionspacepointhash']); - if (!isset($nodesByOccupiedDimensionSpacePoints[$occupiedDimensionSpacePoint->hash])) { + if (!isset($nodesByOccupiedDimensionSpacePoint[$occupiedDimensionSpacePoint->hash])) { // ... so we handle occupation exactly once ... - $nodesByOccupiedDimensionSpacePoints[$occupiedDimensionSpacePoint->hash] = $this->mapNodeRowToNode( + $nodesByOccupiedDimensionSpacePoint[$occupiedDimensionSpacePoint->hash] = $this->mapNodeRowToNode( $nodeRow, $workspaceName, $contentStreamId, @@ -211,7 +211,7 @@ public function mapNodeRowsToNodeAggregate( = $coveredDimensionSpacePoint; $occupationByCovering[$coveredDimensionSpacePoint->hash] = $occupiedDimensionSpacePoint; $nodesByCoveredDimensionSpacePoints[$coveredDimensionSpacePoint->hash] - = $nodesByOccupiedDimensionSpacePoints[$occupiedDimensionSpacePoint->hash]; + = $nodesByOccupiedDimensionSpacePoint[$occupiedDimensionSpacePoint->hash]; // ... as we do for explicit subtree tags foreach (self::extractNodeTagsFromJson($nodeRow['subtreetags'])->withoutInherited() as $explicitTag) { $dimensionSpacePointsBySubtreeTags = $dimensionSpacePointsBySubtreeTags->withSubtreeTagAndDimensionSpacePoint($explicitTag, $coveredDimensionSpacePoint); @@ -220,8 +220,9 @@ public function mapNodeRowsToNodeAggregate( ksort($occupiedDimensionSpacePoints); ksort($coveredDimensionSpacePoints); - /** @var Node $primaryNode a nodeAggregate only exists if it at least contains one node. */ - $primaryNode = current($nodesByOccupiedDimensionSpacePoints); + // a nodeAggregate only exists if it at least contains one node + assert($nodesByOccupiedDimensionSpacePoint !== []); + $primaryNode = current($nodesByOccupiedDimensionSpacePoint); return new NodeAggregate( $primaryNode->subgraphIdentity->contentStreamId, @@ -230,7 +231,7 @@ public function mapNodeRowsToNodeAggregate( NodeTypeName::fromString($rawNodeTypeName), $rawNodeName ? NodeName::fromString($rawNodeName) : null, new OriginDimensionSpacePointSet($occupiedDimensionSpacePoints), - $nodesByOccupiedDimensionSpacePoints, + $nodesByOccupiedDimensionSpacePoint, CoverageByOrigin::fromArray($coverageByOccupants), new DimensionSpacePointSet($coveredDimensionSpacePoints), $nodesByCoveredDimensionSpacePoints, diff --git a/Neos.ContentRepository.Core/Classes/DimensionSpace/InterDimensionalVariationGraph.php b/Neos.ContentRepository.Core/Classes/DimensionSpace/InterDimensionalVariationGraph.php index 52725f6ec9e..df47ebd4f0a 100644 --- a/Neos.ContentRepository.Core/Classes/DimensionSpace/InterDimensionalVariationGraph.php +++ b/Neos.ContentRepository.Core/Classes/DimensionSpace/InterDimensionalVariationGraph.php @@ -117,7 +117,10 @@ public function getWeightedDimensionSpacePointByHash(string $hash): ?WeightedDim /** * Returns the root generalizations indexed by hash * - * @return array + * Even in a zero-dimensional content repository the array will have at least one entry + * of an empty dimension space point {@see DimensionSpacePoint::createWithoutDimensions()} + * + * @return non-empty-array */ public function getRootGeneralizations(): array { @@ -127,7 +130,13 @@ public function getRootGeneralizations(): array $rootGeneralizations[$dimensionSpacePointHash] = $weightedDimensionSpacePoint->dimensionSpacePoint; } } - + if (empty($rootGeneralizations)) { + // safeguard, should not happen here: + throw new \RuntimeException( + 'The dimension space is empty, please check your configuration.', + 1710613747 + ); + } return $rootGeneralizations; } diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodeAggregate.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodeAggregate.php index d75692f9369..3cc7f298ab4 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodeAggregate.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/NodeAggregate.php @@ -47,21 +47,22 @@ * This interface is called *Readable* because it exposes read operations on the set of nodes inside * a single NodeAggregate; often used for constraint checks (in command handlers). * - * @api + * @api except its constructor. */ final readonly class NodeAggregate { /** + * @internal * @param ContentStreamId $contentStreamId ID of the content stream of this node aggregate * @param NodeAggregateId $nodeAggregateId ID of this node aggregate * @param NodeAggregateClassification $classification whether this aggregate represents a root, regular or tethered node * @param NodeTypeName $nodeTypeName name of the node type of this aggregate * @param NodeName|null $nodeName optional name of this aggregate * @param OriginDimensionSpacePointSet $occupiedDimensionSpacePoints dimension space points this aggregate occupies - * @param array $nodesByOccupiedDimensionSpacePoint + * @param non-empty-array $nodesByOccupiedDimensionSpacePoint At least one node will be occupied. * @param CoverageByOrigin $coverageByOccupant - * @param DimensionSpacePointSet $coveredDimensionSpacePoints - * @param array $nodesByCoveredDimensionSpacePoint + * @param DimensionSpacePointSet $coveredDimensionSpacePoints This node aggregate will cover at least one dimension space. + * @param non-empty-array $nodesByCoveredDimensionSpacePoint At least one node will be covered. * @param OriginByCoverage $occupationByCovered * @param DimensionSpacePointsBySubtreeTags $dimensionSpacePointsBySubtreeTags dimension space points for every subtree tag this aggregate is *explicitly* tagged with (excluding inherited tags) */ @@ -87,16 +88,6 @@ public function occupiesDimensionSpacePoint(OriginDimensionSpacePoint $originDim return $this->occupiedDimensionSpacePoints->contains($originDimensionSpacePoint); } - /** - * Returns the nodes belonging to this aggregate, i.e. the "real materialized" node rows. - * - * @return iterable - */ - public function getNodes(): iterable - { - return array_values($this->nodesByOccupiedDimensionSpacePoint); - } - public function getNodeByOccupiedDimensionSpacePoint( OriginDimensionSpacePoint $occupiedDimensionSpacePoint ): Node { @@ -164,4 +155,15 @@ public function getDimensionSpacePointsTaggedWith(SubtreeTag $subtreeTag): Dimen { return $this->dimensionSpacePointsBySubtreeTags->forSubtreeTag($subtreeTag); } + + /** + * Returns the nodes belonging to this aggregate, i.e. the "real materialized" node rows. + * + * @internal Using this method to access all occupied nodes or possibly extract a single arbitrary node is not intended for use outside the core. + * @return iterable + */ + public function getNodes(): iterable + { + return array_values($this->nodesByOccupiedDimensionSpacePoint); + } } diff --git a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php index ae5d75bb1e5..d18cc4c0aae 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php +++ b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php @@ -106,12 +106,6 @@ public function createSiteNodeIfNotExists(Site $site, string $nodeTypeName): voi } $rootDimensionSpacePoints = $this->interDimensionalVariationGraph->getRootGeneralizations(); - if (empty($rootDimensionSpacePoints)) { - throw new \InvalidArgumentException( - 'The dimension space is empty, please check your configuration.', - 1651957153 - ); - } $arbitraryRootDimensionSpacePoint = array_shift($rootDimensionSpacePoints); $siteNodeAggregateId = NodeAggregateId::create(); diff --git a/Neos.Neos/Classes/View/FusionExceptionViewInternals.php b/Neos.Neos/Classes/View/FusionExceptionViewInternals.php index afc4cbd176b..554c47b6131 100644 --- a/Neos.Neos/Classes/View/FusionExceptionViewInternals.php +++ b/Neos.Neos/Classes/View/FusionExceptionViewInternals.php @@ -31,12 +31,6 @@ public function __construct( public function getArbitraryDimensionSpacePoint(): DimensionSpacePoint { $rootDimensionSpacePoints = $this->interDimensionalVariationGraph->getRootGeneralizations(); - if (empty($rootDimensionSpacePoints)) { - throw new \InvalidArgumentException( - 'The dimension space is empty, please check your configuration.', - 1651957153 - ); - } $arbitraryRootDimensionSpacePoint = array_shift($rootDimensionSpacePoints); return $arbitraryRootDimensionSpacePoint; }