Skip to content
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: 5054 - Add custom destination support for CreateNodeVariant #5403

Draft
wants to merge 1 commit into
base: 9.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,24 @@ Feature: Create node variant
tethered:
type: 'Neos.ContentRepository.Testing:Tethered'
'Neos.ContentRepository.Testing:Tethered': []
'Neos.ContentRepository.Testing:RestrictiveDocument':
constraints:
nodeTypes:
'Neos.ContentRepository.Testing:Document': false
childNodes:
tethered:
type: 'Neos.ContentRepository.Testing:Tethered'
constraints:
nodeTypes:
'Neos.ContentRepository.Testing:Document': false
"""
And using identifier "default", I define a content repository
And I am in content repository "default"
And I am user identified by "initiating-user-identifier"
And the command CreateRootWorkspace is executed with payload:
| Key | Value |
| workspaceName | "live" |
| newContentStreamId | "cs-identifier" |
| Key | Value |
| workspaceName | "live" |
| newContentStreamId | "cs-identifier" |
And I am in workspace "live" and dimension space point {"market":"DE", "language":"gsw"}
And the command CreateRootNodeAggregateWithNode is executed with payload:
| Key | Value |
Expand All @@ -36,6 +46,15 @@ Feature: Create node variant
# We have to add yet another node since we need test cases with a partially covering parent node
# Node /document/child
| nody-mc-nodeface | child | sir-david-nodenborough | Neos.ContentRepository.Testing:Document | {} |
And I am in workspace "live" and dimension space point {"market":"DE", "language":"de"}
# We have to add yet another node that could be varied but not to a different parent
And the following CreateNodeAggregateWithNode commands are executed:
| nodeAggregateId | nodeName | parentNodeAggregateId | nodeTypeName |
| polyglot-mc-nodeface | polyglot-child | lady-eleonode-rootford | Neos.ContentRepository.Testing:Document |
# ...and we have to add yet another node for node type constraint checks
And the following CreateNodeAggregateWithNode commands are executed:
| nodeAggregateId | nodeName | parentNodeAggregateId | nodeTypeName | tetheredDescendantNodeAggregateIds |
| the-governode | governode | lady-eleonode-rootford | Neos.ContentRepository.Testing:RestrictiveDocument | {"tethered": "nodimer-tetherton"} |

Scenario: Try to create a variant in a workspace that does not exist
When the command CreateNodeVariant is executed with payload and exceptions are caught:
Expand Down Expand Up @@ -120,3 +139,82 @@ Feature: Create node variant
| sourceOrigin | {"market":"DE", "language":"gsw"} |
| targetOrigin | {"market":"DE", "language":"de"} |
Then the last command should have thrown an exception of type "NodeAggregateDoesCurrentlyNotCoverDimensionSpacePoint"

Scenario: Try to create a variant as a child of a different parent aggregate that does not exist
When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"DE", "language":"gsw"} |
| parentNodeAggregateId | "i-do-not-exist" |
Then the last command should have thrown an exception of type "NodeAggregateCurrentlyDoesNotExist"

Scenario: Try to create a variant as a sibling of a non-existing succeeding sibling
When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"DE", "language":"gsw"} |
| parentNodeAggregateId | "nody-mc-nodeface" |
| succeedingSiblingNodeAggregateId | "i-do-not-exist" |
Then the last command should have thrown an exception of type "NodeAggregateCurrentlyDoesNotExist"

Scenario: Try to create a variant before a sibling which is not a child of the new parent
When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"DE", "language":"gsw"} |
| parentNodeAggregateId | "nody-mc-nodeface" |
| succeedingSiblingNodeAggregateId | "sir-david-nodenborough" |
Then the last command should have thrown an exception of type "NodeAggregateIsNoChild"

Scenario: Try to create a variant before a sibling which is none (no new parent case)
When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"DE", "language":"gsw"} |
| succeedingSiblingNodeAggregateId | "nody-mc-nodeface" |
Then the last command should have thrown an exception of type "NodeAggregateIsNoSibling"

Scenario: Try to create a variant as a child of a different parent aggregate that does not cover the requested DSP
When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"CH", "language":"de"} |
| parentNodeAggregateId | "sir-david-nodenborough" |
Then the last command should have thrown an exception of type "NodeAggregateDoesCurrentlyNotCoverDimensionSpacePoint"

Scenario: Try to create a variant of a node having a name that is already taken by one of the variant's siblings
Given I am in workspace "live" and dimension space point {"market":"DE", "language":"gsw"}
And the following CreateNodeAggregateWithNode commands are executed:
| nodeAggregateId | nodeName | parentNodeAggregateId | nodeTypeName |
| evil-occupant | polyglot-child | nody-mc-nodeface | Neos.ContentRepository.Testing:Document |

When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"DE", "language":"gsw"} |
| parentNodeAggregateId | "nody-mc-nodeface" |
Then the last command should have thrown an exception of type "NodeNameIsAlreadyCovered"

Scenario: Try to vary a node as a child of another parent whose node type does not allow child nodes of the variant's type
When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"DE", "language":"gsw"} |
| parentNodeAggregateId | "the-governode" |
Then the last command should have thrown an exception of type "NodeConstraintException"

Scenario: Try to vary a node as a child of another parent whose parent's node type does not allow grand child nodes of the variant's type
When the command CreateNodeVariant is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "polyglot-mc-nodeface" |
| sourceOrigin | {"market":"DE", "language":"de"} |
| targetOrigin | {"market":"DE", "language":"gsw"} |
| parentNodeAggregateId | "nodimer-tetherton" |
Then the last command should have thrown an exception of type "NodeConstraintException"
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@
* @param NodeAggregateId $nodeAggregateId The identifier of the affected node aggregate
* @param OriginDimensionSpacePoint $sourceOrigin Dimension Space Point from which the node is to be copied from
* @param OriginDimensionSpacePoint $targetOrigin Dimension Space Point to which the node is to be copied to
* @param ?NodeAggregateId $parentNodeAggregateId The optional id of the node aggregate to be used as the variant's parent
* @param ?NodeAggregateId $succeedingSiblingNodeAggregateId The optional id of the node aggregate to be used as the variant's succeeding sibling
*/
private function __construct(
public WorkspaceName $workspaceName,
public NodeAggregateId $nodeAggregateId,
public OriginDimensionSpacePoint $sourceOrigin,
public OriginDimensionSpacePoint $targetOrigin,
public ?NodeAggregateId $parentNodeAggregateId,
public ?NodeAggregateId $succeedingSiblingNodeAggregateId,
) {
}

Expand All @@ -51,10 +55,12 @@ private function __construct(
* @param NodeAggregateId $nodeAggregateId The identifier of the affected node aggregate
* @param OriginDimensionSpacePoint $sourceOrigin Dimension Space Point from which the node is to be copied from
* @param OriginDimensionSpacePoint $targetOrigin Dimension Space Point to which the node is to be copied to
* @param ?NodeAggregateId $parentNodeAggregateId The id of the node aggregate to be used as the variant's parent
* @param ?NodeAggregateId $succeedingSiblingNodeAggregateId The optional id of the node aggregate to be used as the variant's succeeding sibling
*/
public static function create(WorkspaceName $workspaceName, NodeAggregateId $nodeAggregateId, OriginDimensionSpacePoint $sourceOrigin, OriginDimensionSpacePoint $targetOrigin): self
public static function create(WorkspaceName $workspaceName, NodeAggregateId $nodeAggregateId, OriginDimensionSpacePoint $sourceOrigin, OriginDimensionSpacePoint $targetOrigin, ?NodeAggregateId $parentNodeAggregateId = null, ?NodeAggregateId $succeedingSiblingNodeAggregateId = null): self
{
return new self($workspaceName, $nodeAggregateId, $sourceOrigin, $targetOrigin);
return new self($workspaceName, $nodeAggregateId, $sourceOrigin, $targetOrigin, $parentNodeAggregateId, $succeedingSiblingNodeAggregateId);
}

public static function fromArray(array $array): self
Expand All @@ -64,6 +70,12 @@ public static function fromArray(array $array): self
NodeAggregateId::fromString($array['nodeAggregateId']),
OriginDimensionSpacePoint::fromArray($array['sourceOrigin']),
OriginDimensionSpacePoint::fromArray($array['targetOrigin']),
array_key_exists('parentNodeAggregateId', $array)
? NodeAggregateId::fromString($array['parentNodeAggregateId'])
: null,
array_key_exists('succeedingSiblingNodeAggregateId', $array)
? NodeAggregateId::fromString($array['succeedingSiblingNodeAggregateId'])
: null,
);
}

Expand All @@ -83,6 +95,8 @@ public function createCopyForWorkspace(
$this->nodeAggregateId,
$this->sourceOrigin,
$this->targetOrigin,
$this->parentNodeAggregateId,
$this->succeedingSiblingNodeAggregateId,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,45 @@ private function handleCreateNodeVariant(
$this->requireNodeAggregateToBeUntethered($nodeAggregate);
$this->requireNodeAggregateToOccupyDimensionSpacePoint($nodeAggregate, $command->sourceOrigin);
$this->requireNodeAggregateToNotOccupyDimensionSpacePoint($nodeAggregate, $command->targetOrigin);
$parentNodeAggregate = $this->requireProjectedParentNodeAggregate(
$contentGraph,
$command->nodeAggregateId,
$command->sourceOrigin
);

if ($command->succeedingSiblingNodeAggregateId) {
$this->requireProjectedNodeAggregate($contentGraph, $command->succeedingSiblingNodeAggregateId);
}
if ($command->parentNodeAggregateId) {
$parentNodeAggregate = $this->requireProjectedNodeAggregate($contentGraph, $command->parentNodeAggregateId);
if ($command->succeedingSiblingNodeAggregateId) {
$this->requireNodeAggregateToBeChild(
$contentGraph,
$command->succeedingSiblingNodeAggregateId,
$command->parentNodeAggregateId,
$command->targetOrigin->toDimensionSpacePoint(),
);
}
if ($nodeAggregate->nodeName) {
$this->requireNodeNameToBeUncovered($contentGraph, $nodeAggregate->nodeName, $command->parentNodeAggregateId);
$this->requireNodeTypeNotToDeclareTetheredChildNodeName($parentNodeAggregate->nodeTypeName, $nodeAggregate->nodeName);
}
$this->requireConstraintsImposedByAncestorsAreMet(
$contentGraph,
$this->requireNodeType($nodeAggregate->nodeTypeName),
[$command->parentNodeAggregateId],
);
} else {
$parentNodeAggregate = $this->requireProjectedParentNodeAggregate(
$contentGraph,
$command->nodeAggregateId,
$command->sourceOrigin
);
if ($command->succeedingSiblingNodeAggregateId) {
$this->requireNodeAggregateToBeSibling(
$contentGraph,
$command->nodeAggregateId,
$command->succeedingSiblingNodeAggregateId,
$command->targetOrigin->toDimensionSpacePoint(),
);
}
}

$this->requireNodeAggregateToCoverDimensionSpacePoint(
$parentNodeAggregate,
$command->targetOrigin->toDimensionSpacePoint()
Expand Down
Loading