Skip to content

Commit

Permalink
Merge pull request #4906 from mhsdesign/task/followup-4520-nodeTypeMa…
Browse files Browse the repository at this point in the history
…nger

!!! TASK: Followup #4520 Introduce `NodeType::tetheredNodeTypeDefinitions`
  • Loading branch information
kitsunet committed May 17, 2024
2 parents f5e39eb + 95ad9f1 commit b3d32bf
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 206 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,9 @@ protected function requireRootNodeTypeToBeUnoccupied(
*/
protected function requireTetheredDescendantNodeTypesToExist(NodeType $nodeType): void
{
// this getter throws if any of the child nodeTypes doesnt exist!
$tetheredNodeTypes = $this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeType);
foreach ($tetheredNodeTypes as $tetheredNodeType) {
$this->requireTetheredDescendantNodeTypesToExist($tetheredNodeType);
foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) {
$nodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName);
$this->requireTetheredDescendantNodeTypesToExist($nodeType);
}
}

Expand All @@ -188,7 +187,8 @@ protected function requireTetheredDescendantNodeTypesToExist(NodeType $nodeType)
*/
protected function requireTetheredDescendantNodeTypesToNotBeOfTypeRoot(NodeType $nodeType): void
{
foreach ($this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeType) as $tetheredChildNodeType) {
foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) {
$tetheredChildNodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName);
if ($tetheredChildNodeType->isOfType(NodeTypeName::ROOT_NODE_TYPE_NAME)) {
throw new NodeTypeIsOfTypeRoot(
'Node type "' . $nodeType->name->value . '" for tethered descendant is of type root.',
Expand Down Expand Up @@ -222,7 +222,7 @@ protected function requireNodeTypeToDeclareReference(NodeTypeName $nodeTypeName,
protected function requireNodeTypeNotToDeclareTetheredChildNodeName(NodeTypeName $nodeTypeName, NodeName $nodeName): void
{
$nodeType = $this->requireNodeType($nodeTypeName);
if ($nodeType->hasTetheredNode($nodeName)) {
if ($nodeType->tetheredNodeTypeDefinitions->contain($nodeName)) {
throw new NodeNameIsAlreadyCovered(
'Node name "' . $nodeName->value . '" is reserved for a tethered child of parent node aggregate of type "'
. $nodeTypeName->value . '".'
Expand Down Expand Up @@ -368,8 +368,8 @@ protected function areNodeTypeConstraintsImposedByGrandparentValid(
NodeType $nodeType
): bool {
return !($parentNodeName
&& $grandParentsNodeType->hasTetheredNode($parentNodeName)
&& !$this->getNodeTypeManager()->isNodeTypeAllowedAsChildToTetheredNode($grandParentsNodeType, $parentNodeName, $nodeType));
&& $grandParentsNodeType->tetheredNodeTypeDefinitions->contain($parentNodeName)
&& !$this->getNodeTypeManager()->isNodeTypeAllowedAsChildToTetheredNode($grandParentsNodeType->name, $parentNodeName, $nodeType->name));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,13 @@
use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues;
use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodePeerVariantWasCreated;
use Neos\ContentRepository\Core\Infrastructure\Property\PropertyConverter;
use Neos\ContentRepository\Core\NodeType\NodeType;
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
use Neos\ContentRepository\Core\NodeType\TetheredNodeTypeDefinition;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateClassification;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeName;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;

/**
* @internal implementation details of command handlers
Expand Down Expand Up @@ -58,19 +56,23 @@ protected function createEventsForMissingTetheredNode(
ContentGraphInterface $contentGraph,
NodeAggregate $parentNodeAggregate,
OriginDimensionSpacePoint $originDimensionSpacePoint,
NodeName $tetheredNodeName,
?NodeAggregateId $tetheredNodeAggregateId,
NodeType $expectedTetheredNodeType
TetheredNodeTypeDefinition $tetheredNodeTypeDefinition,
?NodeAggregateId $tetheredNodeAggregateId
): Events {
$childNodeAggregate = $contentGraph->findChildNodeAggregateByName(
$parentNodeAggregate->nodeAggregateId,
$tetheredNodeName
$tetheredNodeTypeDefinition->name
);

$expectedTetheredNodeType = $this->nodeTypeManager->getNodeType($tetheredNodeTypeDefinition->nodeTypeName);
$defaultProperties = $expectedTetheredNodeType
? SerializedPropertyValues::defaultFromNodeType($expectedTetheredNodeType, $this->getPropertyConverter())
: SerializedPropertyValues::createEmpty();

if ($childNodeAggregate === null) {
// there is no tethered child node aggregate already; let's create it!
$nodeType = $this->nodeTypeManager->requireNodeType($parentNodeAggregate->nodeTypeName);
if ($nodeType->isOfType(NodeTypeName::ROOT_NODE_TYPE_NAME)) {
$nodeType = $this->nodeTypeManager->getNodeType($parentNodeAggregate->nodeTypeName);
if ($nodeType?->isOfType(NodeTypeName::ROOT_NODE_TYPE_NAME)) {
$events = [];
$tetheredNodeAggregateId = $tetheredNodeAggregateId ?: NodeAggregateId::create();
// we create in one origin DSP and vary in the others
Expand All @@ -91,14 +93,14 @@ protected function createEventsForMissingTetheredNode(
$events[] = new NodeAggregateWithNodeWasCreated(
$parentNodeAggregate->contentStreamId,
$tetheredNodeAggregateId,
$expectedTetheredNodeType->name,
$tetheredNodeTypeDefinition->nodeTypeName,
$rootGeneralizationOrigin,
InterdimensionalSiblings::fromDimensionSpacePointSetWithoutSucceedingSiblings(
$this->getInterDimensionalVariationGraph()->getSpecializationSet($rootGeneralization)
),
$parentNodeAggregate->nodeAggregateId,
$tetheredNodeName,
SerializedPropertyValues::defaultFromNodeType($expectedTetheredNodeType, $this->getPropertyConverter()),
$tetheredNodeTypeDefinition->name,
$defaultProperties,
NodeAggregateClassification::CLASSIFICATION_TETHERED,
);
$creationOriginDimensionSpacePoint = $rootGeneralizationOrigin;
Expand All @@ -110,14 +112,14 @@ protected function createEventsForMissingTetheredNode(
new NodeAggregateWithNodeWasCreated(
$parentNodeAggregate->contentStreamId,
$tetheredNodeAggregateId ?: NodeAggregateId::create(),
$expectedTetheredNodeType->name,
$tetheredNodeTypeDefinition->nodeTypeName,
$originDimensionSpacePoint,
InterdimensionalSiblings::fromDimensionSpacePointSetWithoutSucceedingSiblings(
$parentNodeAggregate->getCoverageByOccupant($originDimensionSpacePoint)
),
$parentNodeAggregate->nodeAggregateId,
$tetheredNodeName,
SerializedPropertyValues::defaultFromNodeType($expectedTetheredNodeType, $this->getPropertyConverter()),
$tetheredNodeTypeDefinition->name,
$defaultProperties,
NodeAggregateClassification::CLASSIFICATION_TETHERED,
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodePath;
use Neos\ContentRepository\Core\SharedModel\Exception\NodeTypeNotFound;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;

/**
Expand Down Expand Up @@ -128,12 +129,16 @@ private static function createNodeAggregateIdsForNodeType(
?string $pathPrefix = null
): array {
$nodeAggregateIds = [];
foreach ($nodeTypeManager->getTetheredNodesConfigurationForNodeType($nodeTypeManager->requireNodeType($nodeTypeName)) as $nodeName => $childNodeType) {
$path = $pathPrefix ? $pathPrefix . '/' . $nodeName : $nodeName;
$nodeType = $nodeTypeManager->getNodeType($nodeTypeName);
if (!$nodeType) {
throw new NodeTypeNotFound(sprintf('Cannot build NodeAggregateIdsByNodePaths because NodeType %s does not exist.', $nodeTypeName->value), 1715711379);
}
foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) {
$path = $pathPrefix ? $pathPrefix . '/' . $tetheredNodeTypeDefinition->name->value : $tetheredNodeTypeDefinition->name->value;
$nodeAggregateIds[$path] = NodeAggregateId::create();
$nodeAggregateIds = array_merge(
$nodeAggregateIds,
self::createNodeAggregateIdsForNodeType($childNodeType->name, $nodeTypeManager, $path)
self::createNodeAggregateIdsForNodeType($tetheredNodeTypeDefinition->nodeTypeName, $nodeTypeManager, $path)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,24 +264,26 @@ private function handleTetheredChildNodes(
?NodePath $nodePath
): Events {
$events = [];
foreach ($this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeType) as $rawNodeName => $childNodeType) {
assert($childNodeType instanceof NodeType);
$nodeName = NodeName::fromString($rawNodeName);
foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) {
$childNodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName);
$childNodePath = $nodePath
? $nodePath->appendPathSegment($nodeName)
: NodePath::fromString($nodeName->value);
? $nodePath->appendPathSegment($tetheredNodeTypeDefinition->name)
: NodePath::fromString($tetheredNodeTypeDefinition->name->value);
$childNodeAggregateId = $nodeAggregateIds->getNodeAggregateId($childNodePath)
?? NodeAggregateId::create();
$initialPropertyValues = SerializedPropertyValues::defaultFromNodeType($childNodeType, $this->getPropertyConverter());
$initialPropertyValues = SerializedPropertyValues::defaultFromNodeType(
$childNodeType,
$this->getPropertyConverter()
);

$events[] = new NodeAggregateWithNodeWasCreated(
$contentGraph->getContentStreamId(),
$childNodeAggregateId,
$childNodeType->name,
$tetheredNodeTypeDefinition->nodeTypeName,
$command->originDimensionSpacePoint,
InterdimensionalSiblings::fromDimensionSpacePointSetWithoutSucceedingSiblings($coveredDimensionSpacePoints),
$parentNodeAggregateId,
$nodeName,
$tetheredNodeTypeDefinition->name,
$initialPropertyValues,
NodeAggregateClassification::CLASSIFICATION_TETHERED,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Neos\ContentRepository\Core\Feature\NodeTypeChange\Event\NodeAggregateTypeWasChanged;
use Neos\ContentRepository\Core\NodeType\NodeType;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\NodeType\TetheredNodeTypeDefinition;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate;
Expand Down Expand Up @@ -88,9 +89,8 @@ abstract protected function createEventsForMissingTetheredNode(
ContentGraphInterface $contentGraph,
NodeAggregate $parentNodeAggregate,
OriginDimensionSpacePoint $originDimensionSpacePoint,
NodeName $tetheredNodeName,
NodeAggregateId $tetheredNodeAggregateId,
NodeType $expectedTetheredNodeType
TetheredNodeTypeDefinition $tetheredNodeTypeDefinition,
NodeAggregateId $tetheredNodeAggregateId
): Events;

/**
Expand Down Expand Up @@ -147,7 +147,7 @@ private function handleChangeNodeAggregateType(
* Preparation - make the command fully deterministic in case of rebase
**************/
$descendantNodeAggregateIds = $command->tetheredDescendantNodeAggregateIds->completeForNodeOfType(
$newNodeType->name,
$command->newNodeTypeName,
$this->nodeTypeManager
);
// Write the auto-created descendant node aggregate ids back to the command;
Expand Down Expand Up @@ -180,31 +180,27 @@ private function handleChangeNodeAggregateType(
}

// new tethered child nodes
$expectedTetheredNodes = $this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($newNodeType);
foreach ($nodeAggregate->getNodes() as $node) {
assert($node instanceof Node);
foreach ($expectedTetheredNodes as $serializedTetheredNodeName => $expectedTetheredNodeType) {
$tetheredNodeName = NodeName::fromString($serializedTetheredNodeName);

foreach ($newNodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) {
$tetheredNode = $contentGraph->getSubgraph(
$node->originDimensionSpacePoint->toDimensionSpacePoint(),
VisibilityConstraints::withoutRestrictions()
)->findNodeByPath(
$tetheredNodeName,
$tetheredNodeTypeDefinition->name,
$node->nodeAggregateId,
);

if ($tetheredNode === null) {
$tetheredNodeAggregateId = $command->tetheredDescendantNodeAggregateIds
->getNodeAggregateId(NodePath::fromString($tetheredNodeName->value))
->getNodeAggregateId(NodePath::fromNodeNames($tetheredNodeTypeDefinition->name))
?: NodeAggregateId::create();
array_push($events, ...iterator_to_array($this->createEventsForMissingTetheredNode(
$contentGraph,
$nodeAggregate,
$node->originDimensionSpacePoint,
$tetheredNodeName,
$tetheredNodeAggregateId,
$expectedTetheredNodeType
$tetheredNodeTypeDefinition,
$tetheredNodeAggregateId
)));
}
}
Expand Down Expand Up @@ -348,15 +344,13 @@ private function deleteObsoleteTetheredNodesWhenChangingNodeType(
NodeAggregate $nodeAggregate,
NodeType $newNodeType
): Events {
$expectedTetheredNodes = $this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($newNodeType);

$events = [];
// find disallowed tethered nodes
$tetheredNodeAggregates = $contentGraph->findTetheredChildNodeAggregates($nodeAggregate->nodeAggregateId);

foreach ($tetheredNodeAggregates as $tetheredNodeAggregate) {
/* @var $tetheredNodeAggregate NodeAggregate */
if ($tetheredNodeAggregate->nodeName !== null && !isset($expectedTetheredNodes[$tetheredNodeAggregate->nodeName->value])) {
if ($tetheredNodeAggregate->nodeName !== null && !$newNodeType->tetheredNodeTypeDefinitions->contain($tetheredNodeAggregate->nodeName)) {
// this aggregate (or parts thereof) are DISALLOWED according to constraints.
// We now need to find out which edges we need to remove,
$dimensionSpacePointsToBeRemoved = $this->findDimensionSpacePointsConnectingParentAndChildAggregate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,24 +191,23 @@ private function handleTetheredRootChildNodes(
?NodePath $nodePath
): Events {
$events = [];
foreach ($this->getNodeTypeManager()->getTetheredNodesConfigurationForNodeType($nodeType) as $rawNodeName => $childNodeType) {
assert($childNodeType instanceof NodeType);
$nodeName = NodeName::fromString($rawNodeName);
foreach ($nodeType->tetheredNodeTypeDefinitions as $tetheredNodeTypeDefinition) {
$childNodeType = $this->requireNodeType($tetheredNodeTypeDefinition->nodeTypeName);
$childNodePath = $nodePath
? $nodePath->appendPathSegment($nodeName)
: NodePath::fromString($nodeName->value);
? $nodePath->appendPathSegment($tetheredNodeTypeDefinition->name)
: NodePath::fromNodeNames($tetheredNodeTypeDefinition->name);
$childNodeAggregateId = $nodeAggregateIdsByNodePath->getNodeAggregateId($childNodePath)
?? NodeAggregateId::create();
$initialPropertyValues = SerializedPropertyValues::defaultFromNodeType($childNodeType, $this->getPropertyConverter());

$events[] = $this->createTetheredWithNodeForRoot(
$contentStreamId,
$childNodeAggregateId,
$childNodeType->name,
$tetheredNodeTypeDefinition->nodeTypeName,
$originDimensionSpacePoint,
$coveredDimensionSpacePoints,
$parentNodeAggregateId,
$nodeName,
$tetheredNodeTypeDefinition->name,
$initialPropertyValues
);

Expand Down

This file was deleted.

0 comments on commit b3d32bf

Please sign in to comment.