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: References on creation and Copy #5148

Merged
merged 34 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1612659
FEATURE: References on creation and Copy
kitsunet Jun 17, 2024
c20c17b
Fix merge errors and syntax problems
kitsunet Aug 26, 2024
c50fcb7
More syntax fixes
kitsunet Aug 26, 2024
8c40cbb
Remove forgotten debug statement
kitsunet Aug 26, 2024
b600c70
Fix new unit Tests
kitsunet Aug 26, 2024
72d5f61
Fix another new unit test
kitsunet Aug 26, 2024
7519353
Adjust new behat test with References
kitsunet Aug 26, 2024
1bc6e38
Fix broken export test
kitsunet Aug 26, 2024
a9ae648
Merge branch '9.0' into feature/node-reference-copy
kitsunet Sep 3, 2024
a4cc38c
Merge remote-tracking branch 'origin/9.0' into feature/node-reference…
kitsunet Oct 21, 2024
80b719e
Cleaner References write DTOs
kitsunet Oct 22, 2024
be16480
Empty properties in refs without special treatment
kitsunet Oct 22, 2024
5505b5e
Merge branch '9.0' into feature/node-reference-copy
kitsunet Oct 22, 2024
a74c9b3
Cleanup
kitsunet Oct 22, 2024
98dead5
Add event migration for references
kitsunet Oct 23, 2024
8ccb9f0
Merge remote-tracking branch 'origin/9.0' into feature/node-reference…
kitsunet Oct 24, 2024
da531d1
Merge remote-tracking branch 'origin/9.0' into feature/node-reference…
kitsunet Oct 28, 2024
1ffad19
Code cleanup
kitsunet Oct 30, 2024
f0bb466
Code cleanup
kitsunet Oct 30, 2024
27e9550
TASK: Fix migrateReferencesToMultiFormat
mhsdesign Oct 30, 2024
a6ff4a1
TASK: Simplify code by using automatic `jsonSerialize` like in other …
mhsdesign Oct 30, 2024
0c18918
TASK: Use variadics to verify array list shape
mhsdesign Oct 30, 2024
9694c97
TASK: Introduce `fromNameAndTargets` utility and accept flat list in …
mhsdesign Oct 30, 2024
826b47d
TASK: Remove obsolet serialisation logic from vo's that are not persi…
mhsdesign Oct 30, 2024
a28c27d
TASK: Introduce `NodeReferencesToWrite::withReference` and make merge…
mhsdesign Oct 30, 2024
48efbea
TASK: Validate `NodeReferencesForName` to not contain duplicate node …
mhsdesign Oct 31, 2024
a8cfb25
TASK: Simplify `SerializedNodeReferences` capabilities
mhsdesign Oct 31, 2024
d254397
TASK: inline `fromReadReferences` so its @internal
mhsdesign Oct 31, 2024
b800c66
Merge remote-tracking branch 'origin/9.0' into feature/node-reference…
mhsdesign Oct 31, 2024
7cadf90
TASK: Adjust documentation and namings
mhsdesign Oct 31, 2024
3310d74
TASK: Adjust namings to remove obsolete `fromNameAnd` part
mhsdesign Oct 31, 2024
4eee438
TASK: Ensure that `SerializedNodeReferencesForName` are serialized as…
mhsdesign Oct 31, 2024
bc2427c
TASK: Make atomic delete instead of deleting old references one by one
mhsdesign Oct 31, 2024
4041870
TASK: Optimise reference writing by splitting by scope
mhsdesign Oct 31, 2024
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 @@ -51,8 +51,7 @@ Feature: Run integrity violation detection regarding reference relations
| Key | Value |
| sourceOriginDimensionSpacePoint | {"language":"de"} |
| sourceNodeAggregateId | "source-nodandaise" |
| referenceName | "referenceProperty" |
| references | [{"target": "anthony-destinode"}] |
| references | [{"referenceName": "referenceProperty", "references": [{"target": "anthony-destinode"}]}] |
And I detach the following reference relation from its source:
| Key | Value |
| contentStreamId | "cs-identifier" |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Neos\ContentGraph\DoctrineDbalAdapter;

use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception as DBALException;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\ContentStream;
Expand Down Expand Up @@ -36,7 +37,7 @@
use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues;
use Neos\ContentRepository\Core\Feature\NodeModification\Event\NodePropertiesWereSet;
use Neos\ContentRepository\Core\Feature\NodeMove\Event\NodeAggregateWasMoved;
use Neos\ContentRepository\Core\Feature\NodeReferencing\Dto\SerializedNodeReference;
use Neos\ContentRepository\Core\Feature\NodeReferencing\Dto\SerializedNodeReferences;
use Neos\ContentRepository\Core\Feature\NodeReferencing\Event\NodeReferencesWereSet;
use Neos\ContentRepository\Core\Feature\NodeRemoval\Event\NodeAggregateWasRemoved;
use Neos\ContentRepository\Core\Feature\NodeRenaming\Event\NodeAggregateNameWasChanged;
Expand Down Expand Up @@ -71,6 +72,7 @@
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\Node\ReferenceName;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\EventStore\Model\Event\SequenceNumber;
use Neos\EventStore\Model\EventEnvelope;
Expand Down Expand Up @@ -142,6 +144,7 @@ public function status(): ProjectionStatus
if ($requiredSqlStatements !== []) {
return ProjectionStatus::setupRequired(sprintf('The following SQL statement%s required: %s', count($requiredSqlStatements) !== 1 ? 's are' : ' is', implode(chr(10), $requiredSqlStatements)));
}

return ProjectionStatus::ok();
}

Expand Down Expand Up @@ -510,6 +513,7 @@ private function whenNodeAggregateWithNodeWasCreated(NodeAggregateWithNodeWasCre
$event->originDimensionSpacePoint,
$event->succeedingSiblingsForCoverage,
$event->initialPropertyValues,
$event->nodeReferences,
$event->nodeAggregateClassification,
$event->nodeName,
$eventEnvelope,
Expand Down Expand Up @@ -595,22 +599,40 @@ function (NodeRecord $node) use ($eventEnvelope) {
$event->contentStreamId
);


// remove old
$deleteOldReferencesSql = <<<SQL
DELETE FROM {$this->tableNames->referenceRelation()}
WHERE nodeanchorpoint = :nodeanchorpoint
AND name in (:names)
SQL;
try {
$this->dbal->delete($this->tableNames->referenceRelation(), [
'nodeanchorpoint' => $nodeAnchorPoint?->value,
'name' => $event->referenceName->value
]);
} catch (DBALException $e) {
$this->dbal->executeStatement(
$deleteOldReferencesSql,
[
'nodeanchorpoint' => $nodeAnchorPoint?->value,
'names' => array_map(fn (ReferenceName $name) => $name->value, $event->references->getReferenceNames())
],
[
'names' => ArrayParameterType::STRING
]
);
} catch (DbalException $e) {
throw new \RuntimeException(sprintf('Failed to remove reference relation: %s', $e->getMessage()), 1716486309, $e);
}

// set new
$position = 0;
/** @var SerializedNodeReference $reference */
foreach ($event->references as $reference) {
$nodeAnchorPoint && $this->writeReferencesForTargetAnchorPoint($event->references, $nodeAnchorPoint);
}
}

private function writeReferencesForTargetAnchorPoint(SerializedNodeReferences $nodeReferences, NodeRelationAnchorPoint $nodeAnchorPoint): void
{
$position = 0;
foreach ($nodeReferences as $referencesByProperty) {
foreach ($referencesByProperty->references as $reference) {
$referencePropertiesJson = null;
if ($reference->properties !== null) {
if ($reference->properties !== null && $reference->properties->count() > 0) {
try {
$referencePropertiesJson = \json_encode($reference->properties, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT);
} catch (\JsonException $e) {
Expand All @@ -619,13 +641,13 @@ function (NodeRecord $node) use ($eventEnvelope) {
}
try {
$this->dbal->insert($this->tableNames->referenceRelation(), [
'name' => $event->referenceName->value,
'name' => $referencesByProperty->referenceName->value,
'position' => $position,
'nodeanchorpoint' => $nodeAnchorPoint?->value,
'nodeanchorpoint' => $nodeAnchorPoint->value,
'destinationnodeaggregateid' => $reference->targetNodeAggregateId->value,
'properties' => $referencePropertiesJson,
]);
} catch (DBALException $e) {
} catch (DbalException $e) {
throw new \RuntimeException(sprintf('Failed to insert reference relation: %s', $e->getMessage()), 1716486309, $e);
}
$position++;
Expand Down Expand Up @@ -909,6 +931,7 @@ private function createNodeWithHierarchy(
OriginDimensionSpacePoint $originDimensionSpacePoint,
InterdimensionalSiblings $coverageSucceedingSiblings,
SerializedPropertyValues $propertyDefaultValuesAndTypes,
SerializedNodeReferences $references,
NodeAggregateClassification $nodeAggregateClassification,
?NodeName $nodeName,
EventEnvelope $eventEnvelope,
Expand Down Expand Up @@ -964,6 +987,8 @@ private function createNodeWithHierarchy(
}
}
}

$this->writeReferencesForTargetAnchorPoint($references, $node->relationAnchorPoint);
}

private function connectHierarchy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,26 @@ function (NodeRecord $node) {
}
);

// remove old
$this->getDatabaseConnection()->delete($this->tableNamePrefix . '_referencerelation', [
'sourcenodeanchor' => $anchorPoint->value,
'name' => $event->referenceName->value
]);

// set new
$position = 0;
foreach ($event->references as $reference) {
$referenceRecord = new ReferenceRelationRecord(
$anchorPoint,
$event->referenceName,
$position,
$reference->properties,
$reference->targetNodeAggregateId
);
$referenceRecord->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix);
$position++;
foreach ($event->references as $referencesForProperty) {
// TODO can't we turn this into two atomic queries?
$this->getDatabaseConnection()->delete($this->tableNamePrefix . '_referencerelation', [
'sourcenodeanchor' => $anchorPoint->value,
'name' => $referencesForProperty->referenceName->value
]);

foreach ($referencesForProperty->references as $reference) {
// set new
$referenceRecord = new ReferenceRelationRecord(
$anchorPoint,
$referencesForProperty->referenceName,
$position,
$reference->properties,
$reference->targetNodeAggregateId
);
$referenceRecord->addToDatabase($this->getDatabaseConnection(), $this->tableNamePrefix);
$position++;
}
Comment on lines +56 to +72
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, can't we turn this into two atomic queries?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for me the pg adapter is out of scope and there are no tests ... but i fixed it for doctrine

}
} else {
throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event));
Expand Down
Loading
Loading