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: WorkspaceName with reference for unused contentStream #5167

Closed
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 @@ -40,6 +40,10 @@ public function __construct(

public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraph
{
if ($workspaceName->isReferencingUnusedContentStream()) {
return $this->buildForWorkspaceAndContentStream($workspaceName, $workspaceName->getReferencingUnusedContentStreamId());
}

// FIXME: Should be part of this projection, this is forbidden
$tableName = strtolower(sprintf(
'cr_%s_p_%s',
Expand Down Expand Up @@ -71,7 +75,7 @@ public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraph
return $this->buildForWorkspaceAndContentStream($workspaceName, ContentStreamId::fromString($currentContentStreamId));
}

public function buildForWorkspaceAndContentStream(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraph
private function buildForWorkspaceAndContentStream(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraph
{
return new ContentGraph($this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNames, $workspaceName, $contentStreamId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public function __construct(

public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraphInterface
{
if ($workspaceName->isReferencingUnusedContentStream()) {
return $this->buildForWorkspaceAndContentStream($workspaceName, $workspaceName->getReferencingUnusedContentStreamId());
}

// FIXME: Should be part of this projection, this is forbidden
$tableName = strtolower(sprintf(
'cr_%s_p_%s',
Expand All @@ -55,7 +59,7 @@ public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraphInt
return $this->buildForWorkspaceAndContentStream($workspaceName, ContentStreamId::fromString($row['currentcontentstreamid']));
}

public function buildForWorkspaceAndContentStream(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraphInterface
private function buildForWorkspaceAndContentStream(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraphInterface
{
return new ContentHyperGraph($this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNamePrefix, $workspaceName, $contentStreamId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public function getContentGraph(WorkspaceName $workspaceName): ContentGraphInter
return $this->overridenContentGraphInstances[$workspaceName->value];
}

if ($workspaceName->isReferencingUnusedContentStream()) {
throw new \RuntimeException(sprintf('Expected actual workspace name. Got a workspace name referencing an unused content stream: "%s" instead.', $workspaceName->getReferencingUnusedContentStreamId()->value), 1719648458);
}

return $this->contentRepository->getContentGraph($workspaceName);
}

Expand All @@ -83,7 +87,7 @@ public function overrideContentStreamId(WorkspaceName $workspaceName, ContentStr
throw new \RuntimeException('Contentstream override for this workspace already in effect, nesting not allowed.', 1715170938);
}

$contentGraph = $this->contentRepository->projectionState(ContentGraphFinder::class)->getByWorkspaceNameAndContentStreamId($workspaceName, $contentStreamId);
$contentGraph = $this->contentRepository->getContentGraph(WorkspaceName::createReferenceForUnusedContentStream($contentStreamId));
$this->overridenContentGraphInstances[$workspaceName->value] = $contentGraph;

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface;
use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;

/**
Expand All @@ -30,6 +29,4 @@ interface ContentGraphFactoryInterface
* @throws WorkspaceDoesNotExist if the workspace does not exist
*/
public function buildForWorkspace(WorkspaceName $workspaceName): ContentGraphInterface;

public function buildForWorkspaceAndContentStream(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraphInterface;
}
12 changes: 0 additions & 12 deletions Neos.ContentRepository.Core/Classes/ContentGraphFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,4 @@ public function forgetInstances(): void
{
$this->contentGraphInstances = [];
}

/**
* For testing we allow getting an instance set by both parameters, effectively overriding the relationship at will
*
* @param WorkspaceName $workspaceName
* @param ContentStreamId $contentStreamId
* @internal Only for testing
*/
public function getByWorkspaceNameAndContentStreamId(WorkspaceName $workspaceName, ContentStreamId $contentStreamId): ContentGraphInterface
{
return $this->contentGraphFactory->buildForWorkspaceAndContentStream($workspaceName, $contentStreamId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,10 @@ private function handleChangeWorkspaceOwner(

private function requireWorkspaceToNotExist(WorkspaceName $workspaceName, CommandHandlingDependencies $commandHandlingDependencies): void
{
if ($workspaceName->isReferencingUnusedContentStream()) {
throw new \RuntimeException(sprintf('Expected actual workspace name. Got a workspace name referencing an unused content stream: "%s" instead.', $workspaceName->getReferencingUnusedContentStreamId()->value), 1719648458);
}

try {
$commandHandlingDependencies->getContentGraph($workspaceName);
} catch (WorkspaceDoesNotExist) {
Expand All @@ -918,6 +922,10 @@ private function requireWorkspaceToNotExist(WorkspaceName $workspaceName, Comman
*/
private function requireWorkspace(WorkspaceName $workspaceName, WorkspaceFinder $workspaceFinder): Workspace
{
if ($workspaceName->isReferencingUnusedContentStream()) {
throw new \RuntimeException(sprintf('Expected actual workspace name. Got a workspace name referencing an unused content stream: "%s" instead.', $workspaceName->getReferencingUnusedContentStreamId()->value), 1719648458);
}

$workspace = $workspaceFinder->findOneByName($workspaceName);
if (is_null($workspace)) {
throw WorkspaceDoesNotExist::butWasSupposedTo($workspaceName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public static function fromString(string $value): self
return self::instance($value);
}

public static function createReferenceForUnusedContentStream(ContentStreamId $contentStreamId): self
{
return self::instance('cs:' . $contentStreamId->value);
}

public static function forLive(): self
{
return self::instance(self::WORKSPACE_NAME_LIVE);
Expand Down Expand Up @@ -92,6 +97,19 @@ public function isLive(): bool
return $this->value === self::WORKSPACE_NAME_LIVE;
}

/**
* @phpstan-assert-if-true ContentStreamId $this->getReferencingUnusedContentStreamId()
*/
public function isReferencingUnusedContentStream(): bool
{
return str_starts_with($this->value, 'cs:');
}

public function getReferencingUnusedContentStreamId(): ?ContentStreamId
{
return $this->isReferencingUnusedContentStream() ? ContentStreamId::fromString(substr($this->value, 3)) : null;
}

public function jsonSerialize(): string
{
return $this->value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ trait CRTestSuiteRuntimeVariables
{
protected ?ContentRepository $currentContentRepository = null;

protected ?ContentStreamId $currentContentStreamId = null;

protected ?WorkspaceName $currentWorkspaceName = null;

protected ?DimensionSpacePoint $currentDimensionSpacePoint = null;
Expand Down Expand Up @@ -92,7 +90,7 @@ public function theCurrentDateAndTimeIs(string $timestamp): void
*/
public function iAmInContentStream(string $contentStreamId): void
{
$this->currentContentStreamId = ContentStreamId::fromString($contentStreamId);
$this->currentWorkspaceName = WorkspaceName::createReferenceForUnusedContentStream(ContentStreamId::fromString($contentStreamId));
}

/**
Expand All @@ -101,7 +99,6 @@ public function iAmInContentStream(string $contentStreamId): void
public function iAmInWorkspace(string $workspaceName): void
{
$this->currentWorkspaceName = WorkspaceName::fromString($workspaceName);
$this->currentContentStreamId = null;
}

/**
Expand Down Expand Up @@ -147,11 +144,6 @@ public function getCurrentSubgraph(): ContentSubgraphInterface
{
$contentGraphFinder = $this->currentContentRepository->projectionState(ContentGraphFinder::class);
$contentGraphFinder->forgetInstances();
if (isset($this->currentContentStreamId)) {
// This must still be supported for low level tests, e.g. for content stream forking
return $contentGraphFinder->getByWorkspaceNameAndContentStreamId($this->currentWorkspaceName, $this->currentContentStreamId)->getSubgraph($this->currentDimensionSpacePoint, $this->currentVisibilityConstraints);
}

return $contentGraphFinder->getByWorkspaceName($this->currentWorkspaceName)->getSubgraph(
$this->currentDimensionSpacePoint,
$this->currentVisibilityConstraints
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ public function beforeEventSourcedScenarioDispatcher(BeforeScenarioScope $scope)
$this->currentVisibilityConstraints = VisibilityConstraints::frontend();
$this->currentDimensionSpacePoint = null;
$this->currentRootNodeAggregateId = null;
$this->currentContentStreamId = null;
$this->currentWorkspaceName = null;
$this->currentNodeAggregate = null;
$this->currentNode = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers;

use Neos\ContentRepository\Core\ContentRepository;
use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint;
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
Expand Down Expand Up @@ -47,10 +48,12 @@ public static function fromShorthand(string $shorthand): self
);
}

public static function fromNode(Node $node): self
public static function fromNode(Node $node, ContentRepository $contentRepository): self
{
// todo call ContentGraphFinder::forgetInstances ???
$contentStreamOfNode = $contentRepository->getContentGraph($node->workspaceName)->getContentStreamId();
return new self(
$node->subgraphIdentity->contentStreamId,
$contentStreamOfNode,
$node->aggregateId,
$node->originDimensionSpacePoint
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ public static function fromArray(array $array): self
));
}

public static function fromNodes(Nodes $nodes): self
{
return new self(...array_map(
fn (Node $node): NodeDiscriminator => NodeDiscriminator::fromNode($node),
iterator_to_array($nodes)
));
}

public function equal(self $other): bool
{
return $this->discriminators == $other->discriminators;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public function iExpectNodeAggregateIdToLeadToNode(
$this->initializeCurrentNodeFromContentSubgraph(function (ContentSubgraphInterface $subgraph) use ($nodeAggregateId, $expectedDiscriminator) {
$currentNode = $subgraph->findNodeById($nodeAggregateId);
Assert::assertNotNull($currentNode, 'No node could be found by node aggregate id "' . $nodeAggregateId->value . '" in content subgraph "' . $this->currentDimensionSpacePoint->toJson() . '@' . $this->currentWorkspaceName->value . '"');
$actualDiscriminator = NodeDiscriminator::fromNode($currentNode);
$actualDiscriminator = NodeDiscriminator::fromNode($currentNode, $this->currentContentRepository);
Assert::assertTrue($expectedDiscriminator->equals($actualDiscriminator), 'Node discriminators do not match. Expected was ' . json_encode($expectedDiscriminator) . ' , given was ' . json_encode($actualDiscriminator));
return $currentNode;
});
Expand Down Expand Up @@ -147,7 +147,7 @@ public function iExpectPathToLeadToNode(string $serializedNodePath, string $seri
$this->initializeCurrentNodeFromContentSubgraph(function (ContentSubgraphInterface $subgraph) use ($nodePath, $expectedDiscriminator) {
$currentNode = $subgraph->findNodeByPath($nodePath, $this->getRootNodeAggregateId());
Assert::assertNotNull($currentNode, 'No node could be found by node path "' . $nodePath->serializeToString() . '" in content subgraph "' . $this->currentDimensionSpacePoint->toJson() . '@' . $this->currentWorkspaceName->value . '"');
$actualDiscriminator = NodeDiscriminator::fromNode($currentNode);
$actualDiscriminator = NodeDiscriminator::fromNode($currentNode, $this->currentContentRepository);
Assert::assertTrue($expectedDiscriminator->equals($actualDiscriminator), 'Node discriminators do not match. Expected was ' . json_encode($expectedDiscriminator) . ' , given was ' . json_encode($actualDiscriminator));
return $currentNode;
});
Expand Down Expand Up @@ -479,7 +479,7 @@ private function assertReferencesMatch(TableNode $expectedReferencesTable, Refer
$actualReferences[$index]->name->value
);
$expectedReferenceDiscriminator = NodeDiscriminator::fromShorthand($row['Node']);
$actualReferenceDiscriminator = NodeDiscriminator::fromNode($actualReferences[$index]->node);
$actualReferenceDiscriminator = NodeDiscriminator::fromNode($actualReferences[$index]->node, $this->currentContentRepository);
Assert::assertTrue(
$expectedReferenceDiscriminator->equals($actualReferenceDiscriminator),
'Reference discriminator does not match.'
Expand Down Expand Up @@ -553,12 +553,12 @@ public function iExpectThisNodeToBeTheChildOfNode(string $serializedParentNodeDi

$parent = $subgraph->findParentNode($currentNode->aggregateId);
Assert::assertInstanceOf(Node::class, $parent, 'Parent not found.');
$actualParentDiscriminator = NodeDiscriminator::fromNode($parent);
$actualParentDiscriminator = NodeDiscriminator::fromNode($parent, $this->currentContentRepository);
Assert::assertTrue($expectedParentDiscriminator->equals($actualParentDiscriminator), 'Parent discriminator does not match. Expected was ' . json_encode($expectedParentDiscriminator) . ', given was ' . json_encode($actualParentDiscriminator));

$expectedChildDiscriminator = NodeDiscriminator::fromNode($currentNode);
$expectedChildDiscriminator = NodeDiscriminator::fromNode($currentNode, $this->currentContentRepository);
$child = $subgraph->findNodeByPath($currentNode->name, $parent->aggregateId);
$actualChildDiscriminator = NodeDiscriminator::fromNode($child);
$actualChildDiscriminator = NodeDiscriminator::fromNode($child, $this->currentContentRepository);
Assert::assertTrue($expectedChildDiscriminator->equals($actualChildDiscriminator), 'Child discriminator does not match. Expected was ' . json_encode($expectedChildDiscriminator) . ', given was ' . json_encode($actualChildDiscriminator));
});
}
Expand Down Expand Up @@ -596,7 +596,10 @@ public function iExpectThisNodeToHaveTheFollowingChildNodes(TableNode $expectedC
Assert::assertTrue($expectedNodeName->equals($actualNodeName), 'ContentSubgraph::findChildNodes: Node name in index ' . $index . ' does not match. Expected: "' . $expectedNodeName->value . '" Actual: "' . $actualNodeName->value . '"');
if (isset($row['NodeDiscriminator'])) {
$expectedNodeDiscriminator = NodeDiscriminator::fromShorthand($row['NodeDiscriminator']);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($actualChildNodes[$index]);
$actualNodeDiscriminator = NodeDiscriminator::fromNode(
$actualChildNodes[$index],
$this->currentContentRepository
);
Assert::assertTrue($expectedNodeDiscriminator->equals($actualNodeDiscriminator), 'ContentSubgraph::findChildNodes: Node discriminator in index ' . $index . ' does not match. Expected: ' . json_encode($expectedNodeDiscriminator->jsonSerialize()) . ' Actual: ' . json_encode($actualNodeDiscriminator));
}
}
Expand Down Expand Up @@ -635,7 +638,10 @@ public function iExpectThisNodeToHaveTheFollowingPrecedingSiblings(TableNode $ex
Assert::assertCount(count($expectedPrecedingSiblingsTable->getHash()), $actualSiblings, 'ContentSubgraph::findPrecedingSiblingNodes: Sibling count does not match');
foreach ($expectedPrecedingSiblingsTable->getHash() as $index => $row) {
$expectedNodeDiscriminator = NodeDiscriminator::fromShorthand($row['NodeDiscriminator']);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($actualSiblings[$index]);
$actualNodeDiscriminator = NodeDiscriminator::fromNode(
$actualSiblings[$index],
$this->currentContentRepository
);
Assert::assertTrue($expectedNodeDiscriminator->equals($actualNodeDiscriminator), 'ContentSubgraph::findPrecedingSiblingNodes: Node discriminator in index ' . $index . ' does not match. Expected: ' . json_encode($expectedNodeDiscriminator) . ' Actual: ' . json_encode($actualNodeDiscriminator));
}
});
Expand Down Expand Up @@ -672,7 +678,10 @@ public function iExpectThisNodeToHaveTheFollowingSucceedingSiblings(TableNode $e
Assert::assertCount(count($expectedSucceedingSiblingsTable->getHash()), $actualSiblings, 'ContentSubgraph::findSucceedingSiblingNodes: Sibling count does not match');
foreach ($expectedSucceedingSiblingsTable->getHash() as $index => $row) {
$expectedNodeDiscriminator = NodeDiscriminator::fromShorthand($row['NodeDiscriminator']);
$actualNodeDiscriminator = NodeDiscriminator::fromNode($actualSiblings[$index]);
$actualNodeDiscriminator = NodeDiscriminator::fromNode(
$actualSiblings[$index],
$this->currentContentRepository
);
Assert::assertTrue($expectedNodeDiscriminator->equals($actualNodeDiscriminator), 'ContentSubgraph::findSucceedingSiblingNodes: Node discriminator in index ' . $index . ' does not match. Expected: ' . json_encode($expectedNodeDiscriminator) . ' Actual: ' . json_encode($actualNodeDiscriminator));
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ Feature: Tests for the "Neos.Neos:ConvertUris" Fusion prototype
| Key | Value |
| nodeAggregateId | "root" |
| nodeTypeName | "Neos.Neos:Sites" |
And I am in content stream "cs-identifier" and dimension space point {}
And the following CreateNodeAggregateWithNode commands are executed:
| nodeAggregateId | parentNodeAggregateId | nodeTypeName | initialPropertyValues | nodeName |
| a | root | Neos.Neos:Site | {"title": "Node a"} | a |
Expand Down
Loading
Loading