-
-
Notifications
You must be signed in to change notification settings - Fork 223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FEATURE: Node copying Version 3 (as a Neos service) #5371
Conversation
…m the cr core soon
the idea was that command hooks must be able to set a unique uri path segment, but as were using now a high level service we dont need to intercept that.
The command `CopyNodesRecursively` still needs to preserved as `RebasableToOtherWorkspaceInterface` "internal" command so publishing from user workspaces continues to work.
…e Neos ui to fetch the newly create node
…desRecursively` as node names are deprecated. Instead we should rather expose the to be run `Commands` and then one can change the node name
* @Flow\Scope("singleton") | ||
* @api | ||
*/ | ||
final class NodeDuplicationService |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to support usecases like Flowpack/Flowpack.NodeTemplates#60 were we need to return a list of commands and not handle them ourselves, it would be practical to expose a way to get the commands we would be handle but dont handle them.
Like:
public function calculateCopyNodesRecursively(
ContentRepositoryId $contentRepositoryId,
WorkspaceName $workspaceName,
DimensionSpacePoint $sourceDimensionSpacePoint,
NodeAggregateId $sourceNodeAggregateId,
OriginDimensionSpacePoint $targetDimensionSpacePoint,
NodeAggregateId $targetParentNodeAggregateId,
?NodeAggregateId $targetSucceedingSiblingNodeAggregateId,
?NodeAggregateIdMapping $nodeAggregateIdMapping = null
): Commands;
i would declare this as experimental api but it would be helpful to have that. As otherwise node copying would not be possible there without duplicating this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable to me
In case a leaf node that is tethered is copied, we un-tether it. A migration `flow migrateevents:migratecopytetherednode` fixes this for previous cases.
The
|
@@ -304,7 +305,7 @@ public function findSubtree(NodeAggregateId $entryNodeAggregateId, FindSubtreeFi | |||
$this->dimensionSpacePoint, | |||
$this->visibilityConstraints | |||
); | |||
$subtree = new Subtree((int)$nodeData['level'], $node, array_key_exists($nodeAggregateId, $subtreesByParentNodeId) ? array_reverse($subtreesByParentNodeId[$nodeAggregateId]) : []); | |||
$subtree = Subtree::create((int)$nodeData['level'], $node, Subtrees::fromArray(array_key_exists($nodeAggregateId, $subtreesByParentNodeId) ? array_reverse($subtreesByParentNodeId[$nodeAggregateId]) : [])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
took me a moment here, I think I might prefer a Subtrees::empty() and then array_key_exists($nodeAggregateId, $subtreesByParentNodeId) ? Subtrees::fromArray(array_reverse($subtreesByParentNodeId[$nodeAggregateId])) : Subtrees:empty()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Provisional +1, looks already pretty good, no major complaints atm.
to support usecases like Flowpack/Flowpack.NodeTemplates#60 were we need to return a list of commands and cant handle them ourselves, it would be practical to expose a way to get the commands that would be handled
In a followup we could improve things and address the optional todos
In Flowpack.NodeTemplates i already build a graceful mechanism by carefully checking all constraints beforehand. This is of-course tedious but might be worth in in a later point: https://github.com/Flowpack/Flowpack.NodeTemplates/releases/tag/2.0.0 And also add tests like this:
|
Hmm i just noticed that copying behaved differently in Neos 8.3 :O As per neos-development-collection/Neos.ContentRepository/Classes/Domain/Model/NodeType.php Line 283 in b03cca1
Meaning that when copying a document only its content children are copied but not nested documents? That could be implemented now with a But it makes me wonder if we really should remove the |
Because ROOT paths are only a concept of `AbsoluteNodePath` and not by a singular `NodePath` itself.
This is a lie though, I see no such check in Node::createRecursiveCopy and am not aware of one... 😜 |
Jup tested it in 8.3 it doesnt do that :D But we actually used it as neos-development-collection/Neos.ContentRepository/Classes/Domain/Model/Node.php Line 812 in 6936b7b
see neos-development-collection/Neos.ContentRepository/Classes/Domain/Model/Node.php Lines 1670 to 1681 in 6936b7b
so not interestring for our case as copying for dimensions is kinda broken still :D -> #5054 |
Resolves: #5359 (because it will be obsolete)
Resolves: #5350
Resolves: #5351
Upgrade instructions
Instead of using
CopyNodesRecursively::createFromSubgraphAndStartNode
and handling that in the CR, please use:In case a leaf node that is tethered is copied, we un-tether it.
A migration
flow migrateevents:migratecopytetherednode
fixes this for previous cases.Usages of the legacy copy node must be published before migrating to the final Neos version, to detect those see:
./flow migrateevents:copynodesstatus
Review instructions
Neos UI part: neos/neos-ui#3887
The with dd6408e introduced
CopyNodesRecursively
content repository command is not stable, see its problems outline in #5351.For one not all features were implemented (or only recently) like reference copying and subtree tag copying. Also there was little to no test coverage (2 tests)
Further by emitting events directly we would have to be super careful - which we were not. It was possible to copy tethered nodes and they kept their classification: #5350.
And lastly the event to command relation ship (needed for rebasing) is a problem. We cannot determine the copy command from the original event (which prevents us from removing the
commandClass
mapping).And more importantly for rebasing the copy the WHOLE subtree snapshot is stored in the one events metadata field which can grow way to large (and is hard to maintain and write migrations for - everything is serialised in there). We argued which changes have to be done to keep copy nodes as a content repository command and found that there were almost no constraint checks for reapplying the copy (like the references of copied nodes could be deleted already), if we would check the constraints correctly, that would mean that the whole copy command could fail then which would not be desired. Instead, also to resolve the event to command relation ship we were thinking that a better low level copy implementation would generate the events with the command classes as if they were created by hand. Guessing the command payload (especially with the complexity of tethered nodes) would be utterly complex and errors would only be spottet during rebase. So we decided to actually issue REAL commands in a batch. As this is architecturally not possible from an actual cr command (would require full recursion) and that is okay, we discussed that we want a node copy service.
The disadvantages are that copying can fail now but thats also its positive side for rebasing. As a followup we need to find solutions to be graceful while copying and reapplying the copy. (Maybe by using
NodeAggregateCommandHandler::withoutAncestorNodeTypeConstraintChecks
)And lastly, the copy command and its signature are not ideal as they dont allow multi dimension copying and also expose way to much internals: #5359 This is no problem anymore by using this service.
Checklist
Added Test-cases