Skip to content

Commit

Permalink
FEATURE: Copy subtree tags during copy
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed Nov 18, 2024
1 parent cb6b523 commit 8d14bae
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 9 deletions.
52 changes: 44 additions & 8 deletions Neos.Neos/Classes/Domain/Service/NodeDuplicationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Neos\ContentRepository\Core\Feature\NodeReferencing\Dto\NodeReferencesForName;
use Neos\ContentRepository\Core\Feature\NodeReferencing\Dto\NodeReferencesToWrite;
use Neos\ContentRepository\Core\Feature\NodeReferencing\Dto\NodeReferenceToWrite;
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Command\TagSubtree;
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentSubgraphInterface;
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindReferencesFilter;
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindSubtreeFilter;
Expand All @@ -23,6 +24,7 @@
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Exception\NodeAggregateCurrentlyDoesNotExist;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Node\NodeVariantSelectionStrategy;
use Neos\ContentRepository\Core\SharedModel\Node\ReferenceName;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
Expand Down Expand Up @@ -105,7 +107,7 @@ public function copyNodesRecursively(
);

$createCopyOfNodeCommand = CreateNodeAggregateWithNode::create(
$workspaceName,
$transientNodeCopy->workspaceName,
$transientNodeCopy->aggregateId,
$subtree->node->nodeTypeName,
$targetDimensionSpacePoint,
Expand All @@ -126,6 +128,18 @@ public function copyNodesRecursively(

$commands = Commands::create($createCopyOfNodeCommand);

foreach ($subtree->node->tags->withoutInherited() as $explicitTag) {
$commands = $commands->append(
TagSubtree::create(
$transientNodeCopy->workspaceName,
$transientNodeCopy->aggregateId,
$transientNodeCopy->originDimensionSpacePoint->toDimensionSpacePoint(),
NodeVariantSelectionStrategy::STRATEGY_ALL_VARIANTS,
$explicitTag
)
);
}

foreach ($subtree->children as $childSubtree) {
if ($subtree->node->classification->isTethered() && $childSubtree->node->classification->isTethered()) {
// TODO we assume here that the child node is tethered because the grandparent specifies that.
Expand All @@ -143,14 +157,17 @@ public function copyNodesRecursively(
private function commandsForSubtreeRecursively(TransientNodeCopy $transientParentNode, Subtree $subtree, ContentSubgraphInterface $subgraph, Commands $commands): Commands
{
if ($subtree->node->classification->isTethered()) {
$transientNode = $transientParentNode->forTetheredChildNode(
/**
* Case Node is tethered
*/
$transientNodeCopy = $transientParentNode->forTetheredChildNode(
$subtree
);

if ($subtree->node->properties->count() > 0) {
$setPropertiesOfTetheredNodeCommand = SetNodeProperties::create(
$transientParentNode->workspaceName,
$transientNode->aggregateId,
$transientNodeCopy->aggregateId,
$transientParentNode->originDimensionSpacePoint,
// todo skip properties not in schema
PropertyValuesToWrite::fromArray(
Expand All @@ -165,7 +182,7 @@ private function commandsForSubtreeRecursively(TransientNodeCopy $transientParen
if ($references->count() > 0) {
$setReferencesOfTetheredNodeCommand = SetNodeReferences::create(
$transientParentNode->workspaceName,
$transientNode->aggregateId,
$transientNodeCopy->aggregateId,
$transientParentNode->originDimensionSpacePoint,
$this->serializeProjectedReferences(
$references
Expand All @@ -175,13 +192,16 @@ private function commandsForSubtreeRecursively(TransientNodeCopy $transientParen
$commands = $commands->append($setReferencesOfTetheredNodeCommand);
}
} else {
$transientNode = $transientParentNode->forRegularChildNode(
/**
* Case Node is a regular child
*/
$transientNodeCopy = $transientParentNode->forRegularChildNode(
$subtree
);

$createCopyOfNodeCommand = CreateNodeAggregateWithNode::create(
$transientParentNode->workspaceName,
$transientNode->aggregateId,
$transientNodeCopy->aggregateId,
$subtree->node->nodeTypeName,
$transientParentNode->originDimensionSpacePoint,
$transientParentNode->aggregateId,
Expand All @@ -196,14 +216,30 @@ private function commandsForSubtreeRecursively(TransientNodeCopy $transientParen
);

$createCopyOfNodeCommand = $createCopyOfNodeCommand->withTetheredDescendantNodeAggregateIds(
$transientNode->tetheredNodeAggregateIds
$transientNodeCopy->tetheredNodeAggregateIds
);

$commands = $commands->append($createCopyOfNodeCommand);
}

/**
* common logic
*/

foreach ($subtree->node->tags->withoutInherited() as $explicitTag) {
$commands = $commands->append(
TagSubtree::create(
$transientNodeCopy->workspaceName,
$transientNodeCopy->aggregateId,
$transientNodeCopy->originDimensionSpacePoint->toDimensionSpacePoint(),
NodeVariantSelectionStrategy::STRATEGY_ALL_VARIANTS,
$explicitTag
)
);
}

foreach ($subtree->children as $childSubtree) {
$commands = $this->commandsForSubtreeRecursively($transientNode, $childSubtree, $subgraph, $commands);
$commands = $this->commandsForSubtreeRecursively($transientNodeCopy, $childSubtree, $subgraph, $commands);
}

return $commands;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ Feature: Copy nodes (without dimensions)
| nodeAggregateId | parentNodeAggregateId | nodeTypeName |
| sir-david-nodenborough | lady-eleonode-rootford | Neos.ContentRepository.Testing:Document |
| nody-mc-nodeface | sir-david-nodenborough | Neos.ContentRepository.Testing:Document |
| sir-nodeward-nodington-iii | lady-eleonode-rootford | Neos.ContentRepository.Testing:Document |
| node-wan-kenodi | lady-eleonode-rootford | Neos.ContentRepository.Testing:Document |
| sir-nodeward-nodington-iii | node-wan-kenodi | Neos.ContentRepository.Testing:Document |

Scenario: Simple singular node aggregate is copied
When I am in workspace "live" and dimension space point {}
Expand Down Expand Up @@ -102,6 +103,49 @@ Feature: Copy nodes (without dimensions)
| Name | Node | Properties |
| ref | cs-identifier;sir-david-nodenborough;{} | null |

Scenario: Singular node aggregate is copied with subtree tags (and disabled state)
When I am in workspace "live" and dimension space point {}

Given the command DisableNodeAggregate is executed with payload:
| Key | Value |
| nodeAggregateId | "sir-nodeward-nodington-iii" |
| coveredDimensionSpacePoint | {} |
| nodeVariantSelectionStrategy | "allVariants" |

Given the command TagSubtree is executed with payload:
| Key | Value |
| nodeAggregateId | "sir-nodeward-nodington-iii" |
| coveredDimensionSpacePoint | {} |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "tag1" |

Given the command TagSubtree is executed with payload:
| Key | Value |
| nodeAggregateId | "node-wan-kenodi" |
| coveredDimensionSpacePoint | {} |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "parent-tag" |

And VisibilityConstraints are set to "withoutRestrictions"

# we inherit the tag here but DONT copy it!
Then I expect the node with aggregate identifier "sir-nodeward-nodington-iii" to inherit the tag "parent-tag"

When copy nodes recursively is executed with payload:
| Key | Value |
| sourceDimensionSpacePoint | {} |
| sourceNodeAggregateId | "sir-nodeward-nodington-iii" |
| targetDimensionSpacePoint | {} |
| targetParentNodeAggregateId | "nody-mc-nodeface" |
| targetSucceedingSiblingnodeAggregateId | null |
| nodeAggregateIdMapping | {"sir-nodeward-nodington-iii": "sir-nodeward-nodington-iii-copy"} |

And I expect the node aggregate "sir-nodeward-nodington-iii-copy" to exist
And I expect this node aggregate to disable dimension space points [{}]

And I expect node aggregate identifier "sir-nodeward-nodington-iii-copy" to lead to node cs-identifier;sir-nodeward-nodington-iii-copy;{}
And I expect this node to be exactly explicitly tagged "disabled,tag1"

Scenario: Node aggregate is copied children recursively
When I am in workspace "live" and dimension space point {}
When the following CreateNodeAggregateWithNode commands are executed:
Expand Down Expand Up @@ -151,3 +195,27 @@ Feature: Copy nodes (without dimensions)
And I expect this node to have the following references:
| Name | Node | Properties |
| ref | cs-identifier;sir-david-nodenborough;{} | null |

Scenario: Subtree tags are copied for child nodes
When I am in workspace "live" and dimension space point {}
When the following CreateNodeAggregateWithNode commands are executed:
| nodeAggregateId | parentNodeAggregateId | nodeTypeName |
| child-a | sir-nodeward-nodington-iii | Neos.ContentRepository.Testing:Document |

Given the command TagSubtree is executed with payload:
| Key | Value |
| nodeAggregateId | "child-a" |
| coveredDimensionSpacePoint | {} |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "tag1" |

When copy nodes recursively is executed with payload:
| Key | Value |
| sourceDimensionSpacePoint | {} |
| sourceNodeAggregateId | "sir-nodeward-nodington-iii" |
| targetDimensionSpacePoint | {} |
| targetParentNodeAggregateId | "nody-mc-nodeface" |
| nodeAggregateIdMapping | {"sir-nodeward-nodington-iii": "sir-nodeward-nodington-iii-copy", "child-a": "child-a-copy"} |

And I expect node aggregate identifier "child-a-copy" to lead to node cs-identifier;child-a-copy;{}
And I expect this node to be exactly explicitly tagged "tag1"

0 comments on commit 8d14bae

Please sign in to comment.