Skip to content

Commit

Permalink
Merge pull request #5148 from kitsunet/feature/node-reference-copy
Browse files Browse the repository at this point in the history
!!! FEATURE: References on creation and Copy
  • Loading branch information
kitsunet authored Nov 1, 2024
2 parents e9fe343 + 4041870 commit 4d00a25
Show file tree
Hide file tree
Showing 56 changed files with 953 additions and 593 deletions.
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++;
}
}
} else {
throw EventCouldNotBeAppliedToContentGraph::becauseTheSourceNodeIsMissing(get_class($event));
Expand Down
Loading

0 comments on commit 4d00a25

Please sign in to comment.