Skip to content

Commit

Permalink
FEATURE: Subtree Tags
Browse files Browse the repository at this point in the history
Resolves: #4550
Related: #3732
  • Loading branch information
bwaidelich committed Oct 30, 2023
1 parent 8f9ae0f commit 57f2000
Show file tree
Hide file tree
Showing 60 changed files with 740 additions and 335 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ Feature: Run integrity violation detection regarding restriction relations
| parentNodeAggregateId | "sir-david-nodenborough" |
| nodeName | "child-document" |
| nodeAggregateClassification | "regular" |
And the event NodeAggregateWasDisabled was published with payload:
And the event SubtreeTagWasAdded was published with payload:
| Key | Value |
| contentStreamId | "cs-identifier" |
| nodeAggregateId | "sir-david-nodenborough" |
| affectedDimensionSpacePoints | [{"language":"de"},{"language":"gsw"},{"language":"fr"}] |
| tag | "disabled" |
And the graph projection is fully up to date

Scenario: Detach a restriction relation from its origin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ Feature: Run integrity violation detection regarding restriction relations
| parentNodeAggregateId | "sir-nodeward-nodington-iii" |
| nodeName | "child-document" |
| nodeAggregateClassification | "regular" |
And the event NodeAggregateWasDisabled was published with payload:
And the event SubtreeTagWasAdded was published with payload:
| Key | Value |
| contentStreamId | "cs-identifier" |
| nodeAggregateId | "sir-david-nodenborough" |
| affectedDimensionSpacePoints | [{"language":"de"},{"language":"gsw"},{"language":"fr"}] |
| tag | "disabled" |
And the graph projection is fully up to date
And I remove the following restriction relation:
| Key | Value |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Types\Types;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeDisabling;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\Tagging;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeMove;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeRemoval;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeVariation;
Expand All @@ -28,8 +28,6 @@
use Neos\ContentRepository\Core\Feature\DimensionSpaceAdjustment\Event\DimensionShineThroughWasAdded;
use Neos\ContentRepository\Core\Feature\DimensionSpaceAdjustment\Event\DimensionSpacePointWasMoved;
use Neos\ContentRepository\Core\Feature\NodeCreation\Event\NodeAggregateWithNodeWasCreated;
use Neos\ContentRepository\Core\Feature\NodeDisabling\Event\NodeAggregateWasDisabled;
use Neos\ContentRepository\Core\Feature\NodeDisabling\Event\NodeAggregateWasEnabled;
use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues;
use Neos\ContentRepository\Core\Feature\NodeModification\Event\NodePropertiesWereSet;
use Neos\ContentRepository\Core\Feature\NodeMove\Event\NodeAggregateWasMoved;
Expand All @@ -43,6 +41,8 @@
use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodeSpecializationVariantWasCreated;
use Neos\ContentRepository\Core\Feature\RootNodeCreation\Event\RootNodeAggregateDimensionsWereUpdated;
use Neos\ContentRepository\Core\Feature\RootNodeCreation\Event\RootNodeAggregateWithNodeWasCreated;
use Neos\ContentRepository\Core\Feature\Tagging\Event\SubtreeTagWasAdded;
use Neos\ContentRepository\Core\Feature\Tagging\Event\SubtreeTagWasRemoved;
use Neos\ContentRepository\Core\Infrastructure\DbalClientInterface;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
Expand All @@ -67,7 +67,7 @@
final class DoctrineDbalContentGraphProjection implements ProjectionInterface, WithMarkStaleInterface
{
use NodeVariation;
use NodeDisabling;
use Tagging;
use RestrictionRelations;
use NodeRemoval;
use NodeMove;
Expand Down Expand Up @@ -163,7 +163,6 @@ public function canHandle(EventInterface $event): bool
ContentStreamWasRemoved::class,
NodePropertiesWereSet::class,
NodeReferencesWereSet::class,
NodeAggregateWasEnabled::class,
NodeAggregateTypeWasChanged::class,
DimensionSpacePointWasMoved::class,
DimensionShineThroughWasAdded::class,
Expand All @@ -172,7 +171,8 @@ public function canHandle(EventInterface $event): bool
NodeSpecializationVariantWasCreated::class,
NodeGeneralizationVariantWasCreated::class,
NodePeerVariantWasCreated::class,
NodeAggregateWasDisabled::class
SubtreeTagWasAdded::class,
SubtreeTagWasRemoved::class,
]);
}

Expand All @@ -187,7 +187,6 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event),
NodePropertiesWereSet::class => $this->whenNodePropertiesWereSet($event, $eventEnvelope),
NodeReferencesWereSet::class => $this->whenNodeReferencesWereSet($event, $eventEnvelope),
NodeAggregateWasEnabled::class => $this->whenNodeAggregateWasEnabled($event),
NodeAggregateTypeWasChanged::class => $this->whenNodeAggregateTypeWasChanged($event, $eventEnvelope),
DimensionSpacePointWasMoved::class => $this->whenDimensionSpacePointWasMoved($event),
DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event),
Expand All @@ -196,7 +195,8 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
NodeSpecializationVariantWasCreated::class => $this->whenNodeSpecializationVariantWasCreated($event, $eventEnvelope),
NodeGeneralizationVariantWasCreated::class => $this->whenNodeGeneralizationVariantWasCreated($event, $eventEnvelope),
NodePeerVariantWasCreated::class => $this->whenNodePeerVariantWasCreated($event, $eventEnvelope),
NodeAggregateWasDisabled::class => $this->whenNodeAggregateWasDisabled($event),
SubtreeTagWasAdded::class => $this->whenSubtreeTagWasAdded($event),
SubtreeTagWasRemoved::class => $this->whenSubtreeTagWasRemoved($event),
default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))),
};
}
Expand Down Expand Up @@ -900,20 +900,6 @@ private function cascadeRestrictionRelations(
);
}

/**
* @throws \Throwable
*/
private function whenNodeAggregateWasEnabled(NodeAggregateWasEnabled $event): void
{
$this->transactional(function () use ($event) {
$this->removeOutgoingRestrictionRelationsOfNodeAggregateInDimensionSpacePoints(
$event->contentStreamId,
$event->nodeAggregateId,
$event->affectedDimensionSpacePoints
);
});
}

/**
* @param HierarchyRelation $sourceHierarchyRelation
* @param ContentStreamId $contentStreamId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,22 @@
namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Types\Types;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\NodeRecord;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePointSet;
use Neos\ContentRepository\Core\Feature\NodeDisabling\Event\NodeAggregateWasDisabled;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\EventStore\Model\EventEnvelope;
use Neos\ContentRepository\Core\Feature\Tagging\Event\SubtreeTagWasAdded;
use Neos\ContentRepository\Core\Feature\Tagging\Event\SubtreeTagWasRemoved;

/**
* The NodeDisabling projection feature trait
* The Tagging projection feature trait
*
* @internal
*/
trait NodeDisabling
trait Tagging
{
abstract protected function getTableNamePrefix(): string;

/**
* @throws \Throwable
*/
private function whenNodeAggregateWasDisabled(NodeAggregateWasDisabled $event): void
private function whenSubtreeTagWasAdded(SubtreeTagWasAdded $event): void
{
$this->transactional(function () use ($event) {

Expand All @@ -34,7 +29,7 @@ private function whenNodeAggregateWasDisabled(NodeAggregateWasDisabled $event):
// normal "INSERT" can trigger a duplicate key constraint exception
$this->getDatabaseConnection()->executeStatement(
'
-- GraphProjector::whenNodeAggregateWasDisabled
-- GraphProjector::whenSubtreeTagWasAdded
insert ignore into ' . $this->getTableNamePrefix() . '_restrictionrelation
(contentstreamid, dimensionspacepointhash, originnodeaggregateid, affectednodeaggregateid)
Expand Down Expand Up @@ -94,6 +89,20 @@ private function whenNodeAggregateWasDisabled(NodeAggregateWasDisabled $event):
});
}

/**
* @throws \Throwable
*/
private function whenSubtreeTagWasRemoved(SubtreeTagWasRemoved $event): void
{
$this->transactional(function () use ($event) {
$this->removeOutgoingRestrictionRelationsOfNodeAggregateInDimensionSpacePoints(
$event->contentStreamId,
$event->nodeAggregateId,
$event->affectedDimensionSpacePoints
);
});
}

abstract protected function getDatabaseConnection(): Connection;

abstract protected function transactional(\Closure $operations): void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,19 @@
use Doctrine\DBAL\Connection;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\ProjectionHypergraph;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\RestrictionHyperrelationRecord;
use Neos\ContentRepository\Core\Feature\NodeDisabling\Event\NodeAggregateWasDisabled;
use Neos\ContentRepository\Core\Feature\NodeDisabling\Event\NodeAggregateWasEnabled;
use Neos\ContentRepository\Core\Feature\Tagging\Event\SubtreeTagWasAdded;

/**
* The node disabling feature set for the hypergraph projector
*
* @internal
*/
trait NodeDisabling
trait Tagging
{
/**
* @throws \Throwable
*/
private function whenNodeAggregateWasDisabled(NodeAggregateWasDisabled $event): void
private function whenSubtreeTagWasAdded(SubtreeTagWasAdded $event): void
{
$this->transactional(function () use ($event) {
$descendantNodeAggregateIdsByAffectedDimensionSpacePoint
Expand Down Expand Up @@ -58,7 +57,7 @@ private function whenNodeAggregateWasDisabled(NodeAggregateWasDisabled $event):
/**
* @throws \Throwable
*/
private function whenNodeAggregateWasEnabled(NodeAggregateWasEnabled $event): void
private function whenSubtreeTagWasRemoved(SubtreeTagWasRemoved $event): void
{
$this->transactional(function () use ($event) {
$restrictionRelations = $this->getProjectionHypergraph()->findOutgoingRestrictionRelations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Doctrine\DBAL\Schema\Comparator;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\ContentStreamForking;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeCreation;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeDisabling;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\Tagging;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeModification;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeReferencing;
use Neos\ContentGraph\PostgreSQLAdapter\Domain\Projection\Feature\NodeRemoval;
Expand All @@ -33,8 +33,6 @@
use Neos\ContentRepository\Core\EventStore\EventInterface;
use Neos\ContentRepository\Core\Feature\ContentStreamForking\Event\ContentStreamWasForked;
use Neos\ContentRepository\Core\Feature\NodeCreation\Event\NodeAggregateWithNodeWasCreated;
use Neos\ContentRepository\Core\Feature\NodeDisabling\Event\NodeAggregateWasDisabled;
use Neos\ContentRepository\Core\Feature\NodeDisabling\Event\NodeAggregateWasEnabled;
use Neos\ContentRepository\Core\Feature\NodeModification\Event\NodePropertiesWereSet;
use Neos\ContentRepository\Core\Feature\NodeReferencing\Event\NodeReferencesWereSet;
use Neos\ContentRepository\Core\Feature\NodeRemoval\Event\NodeAggregateWasRemoved;
Expand All @@ -44,6 +42,8 @@
use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodePeerVariantWasCreated;
use Neos\ContentRepository\Core\Feature\NodeVariation\Event\NodeSpecializationVariantWasCreated;
use Neos\ContentRepository\Core\Feature\RootNodeCreation\Event\RootNodeAggregateWithNodeWasCreated;
use Neos\ContentRepository\Core\Feature\Tagging\Event\SubtreeTagWasAdded;
use Neos\ContentRepository\Core\Feature\Tagging\Event\SubtreeTagWasRemoved;
use Neos\ContentRepository\Core\NodeType\NodeTypeManager;
use Neos\ContentRepository\Core\Projection\ProjectionInterface;
use Neos\EventStore\CatchUp\CheckpointStorageInterface;
Expand All @@ -62,7 +62,7 @@ final class HypergraphProjection implements ProjectionInterface
{
use ContentStreamForking;
use NodeCreation;
use NodeDisabling;
use Tagging;
use NodeModification;
use NodeReferencing;
use NodeRemoval;
Expand Down Expand Up @@ -156,9 +156,9 @@ public function canHandle(EventInterface $event): bool
// NodeCreation
RootNodeAggregateWithNodeWasCreated::class,
NodeAggregateWithNodeWasCreated::class,
// NodeDisabling
NodeAggregateWasDisabled::class,
NodeAggregateWasEnabled::class,
// Tagging
SubtreeTagWasAdded::class,
SubtreeTagWasRemoved::class,
// NodeModification
NodePropertiesWereSet::class,
// NodeReferencing
Expand Down Expand Up @@ -189,9 +189,9 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
// NodeCreation
RootNodeAggregateWithNodeWasCreated::class => $this->whenRootNodeAggregateWithNodeWasCreated($event),
NodeAggregateWithNodeWasCreated::class => $this->whenNodeAggregateWithNodeWasCreated($event),
// NodeDisabling
NodeAggregateWasDisabled::class => $this->whenNodeAggregateWasDisabled($event),
NodeAggregateWasEnabled::class => $this->whenNodeAggregateWasEnabled($event),
// Tagging
SubtreeTagWasAdded::class => $this->whenSubtreeTagWasAdded($event),
SubtreeTagWasRemoved::class => $this->whenSubtreeTagWasRemoved($event),
// NodeModification
NodePropertiesWereSet::class => $this->whenNodePropertiesWereSet($event),
// NodeReferencing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,54 +34,61 @@ Feature: Constraint checks on node aggregate disabling
| sir-david-nodenborough | Neos.ContentRepository.Testing:Document | lady-eleonode-rootford | document |

Scenario: Try to disable a node aggregate in a non-existing content stream
When the command DisableNodeAggregate is executed with payload and exceptions are caught:
When the command AddSubtreeTag is executed with payload and exceptions are caught:
| Key | Value |
| contentStreamId | "i-do-not-exist" |
| nodeAggregateId | "sir-david-nodenborough" |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "disabled" |
Then the last command should have thrown an exception of type "ContentStreamDoesNotExistYet"

Scenario: Try to disable a non-existing node aggregate
When the command DisableNodeAggregate is executed with payload and exceptions are caught:
When the command AddSubtreeTag is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "i-do-not-exist" |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "disabled" |
Then the last command should have thrown an exception of type "NodeAggregateCurrentlyDoesNotExist"

Scenario: Try to disable an already disabled node aggregate
Given the command DisableNodeAggregate is executed with payload:
Given the command AddSubtreeTag is executed with payload:
| Key | Value |
| nodeAggregateId | "sir-david-nodenborough" |
| coveredDimensionSpacePoint | {"language": "de"} |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "disabled" |
And the graph projection is fully up to date

# Note: The behavior has been changed with https://github.com/neos/neos-development-collection/pull/4284 and the test was adjusted accordingly
When the command DisableNodeAggregate is executed with payload:
When the command AddSubtreeTag is executed with payload:
| Key | Value |
| nodeAggregateId | "sir-david-nodenborough" |
| coveredDimensionSpacePoint | {"language": "de"} |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "disabled" |
Then I expect exactly 4 events to be published on stream with prefix "ContentStream:cs-identifier"
And event at index 3 is of type "NodeAggregateWasDisabled" with payload:
And event at index 3 is of type "SubtreeTagWasAdded" with payload:
| Key | Expected |
| contentStreamId | "cs-identifier" |
| nodeAggregateId | "sir-david-nodenborough" |
| affectedDimensionSpacePoints | [{"language":"de"},{"language":"gsw"}] |
| tag | "disabled" |


Scenario: Try to disable a node aggregate in a non-existing dimension space point
When the command DisableNodeAggregate is executed with payload and exceptions are caught:
When the command AddSubtreeTag is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "sir-david-nodenborough" |
| coveredDimensionSpacePoint | {"undeclared": "undefined"} |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "disabled" |
Then the last command should have thrown an exception of type "DimensionSpacePointNotFound"

Scenario: Try to disable a node aggregate in a dimension space point it does not cover
When the command DisableNodeAggregate is executed with payload and exceptions are caught:
When the command AddSubtreeTag is executed with payload and exceptions are caught:
| Key | Value |
| nodeAggregateId | "sir-david-nodenborough" |
| coveredDimensionSpacePoint | {"language": "en"} |
| nodeVariantSelectionStrategy | "allVariants" |
| tag | "disabled" |
Then the last command should have thrown an exception of type "NodeAggregateDoesCurrentlyNotCoverDimensionSpacePoint"
Loading

0 comments on commit 57f2000

Please sign in to comment.