Skip to content
Open
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 @@ -23,6 +23,7 @@
use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphReadModelInterface;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist;
use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceIsDeactivated;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStream;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\SharedModel\Workspace\Workspace;
Expand Down Expand Up @@ -66,6 +67,9 @@ public function getContentGraph(WorkspaceName $workspaceName): ContentGraph
if ($row === false) {
throw WorkspaceDoesNotExist::butWasSupposedTo($workspaceName);
}
if ($row['currentContentStreamId'] === null) {
throw WorkspaceIsDeactivated::butWasSupposedToBeActivated($workspaceName);
}
$currentContentStreamId = ContentStreamId::fromString($row['currentContentStreamId']);
return new ContentGraph($this->dbal, $this->nodeFactory, $this->contentRepositoryId, $this->nodeTypeManager, $this->tableNames, $workspaceName, $currentContentStreamId);
}
Expand Down Expand Up @@ -144,7 +148,7 @@ private function getBasicWorkspaceQuery(): QueryBuilder
return $queryBuilder
->select('ws.name, ws.baseWorkspaceName, ws.currentContentStreamId, cs.hasChanges, cs.sourceContentStreamVersion = scs.version as upToDateWithBase')
->from($this->tableNames->workspace(), 'ws')
->join('ws', $this->tableNames->contentStream(), 'cs', 'cs.id = ws.currentcontentstreamid')
->leftJoin('ws', $this->tableNames->contentStream(), 'cs', 'cs.id = ws.currentcontentstreamid')
->leftJoin('cs', $this->tableNames->contentStream(), 'scs', 'scs.id = cs.sourceContentStreamId');
}

Expand All @@ -153,9 +157,13 @@ private function getBasicWorkspaceQuery(): QueryBuilder
*/
private static function workspaceFromDatabaseRow(array $row): Workspace
{
$workspaceName = WorkspaceName::fromString($row['name']);
$baseWorkspaceName = $row['baseWorkspaceName'] !== null ? WorkspaceName::fromString($row['baseWorkspaceName']) : null;

if ($baseWorkspaceName === null) {
if ($row['currentContentStreamId'] === null) {
// no currentContentStreamId, workspace is deactivated
$status = WorkspaceStatus::DEACTIVATED;
} elseif ($baseWorkspaceName === null) {
// no base workspace, a root is always up-to-date
$status = WorkspaceStatus::UP_TO_DATE;
} elseif ($row['upToDateWithBase'] === 1) {
Expand All @@ -167,9 +175,9 @@ private static function workspaceFromDatabaseRow(array $row): Workspace
}

return Workspace::create(
WorkspaceName::fromString($row['name']),
$workspaceName,
$baseWorkspaceName,
ContentStreamId::fromString($row['currentContentStreamId']),
$row['currentContentStreamId'] ? ContentStreamId::fromString($row['currentContentStreamId']) : null,
$status,
$baseWorkspaceName === null
? false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Dto\SubtreeTags;
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged;
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged;
use Neos\ContentRepository\Core\Feature\WorkspaceActivation\Event\WorkspaceWasActivated;
use Neos\ContentRepository\Core\Feature\WorkspaceActivation\Event\WorkspaceWasDeactivated;
use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Event\RootWorkspaceWasCreated;
use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Event\WorkspaceWasCreated;
use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceBaseWorkspaceWasChanged;
Expand Down Expand Up @@ -167,9 +169,11 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void
WorkspaceBaseWorkspaceWasChanged::class => $this->whenWorkspaceBaseWorkspaceWasChanged($event),
WorkspaceRebaseFailed::class => $this->whenWorkspaceRebaseFailed($event),
WorkspaceWasCreated::class => $this->whenWorkspaceWasCreated($event),
WorkspaceWasActivated::class => $this->whenWorkspaceWasActivated($event),
WorkspaceWasDiscarded::class => $this->whenWorkspaceWasDiscarded($event),
WorkspaceWasPublished::class => $this->whenWorkspaceWasPublished($event),
WorkspaceWasRebased::class => $this->whenWorkspaceWasRebased($event),
WorkspaceWasDeactivated::class => $this->whenWorkspaceWasDeactivated($event),
WorkspaceWasRemoved::class => $this->whenWorkspaceWasRemoved($event),
default => null,
};
Expand Down Expand Up @@ -683,6 +687,16 @@ private function whenWorkspaceBaseWorkspaceWasChanged(WorkspaceBaseWorkspaceWasC
$this->updateBaseWorkspace($event->workspaceName, $event->baseWorkspaceName, $event->newContentStreamId);
}

private function whenWorkspaceWasActivated(WorkspaceWasActivated $event): void
{
$this->updateWorkspaceContentStreamId($event->workspaceName, $event->newContentStreamId);
}

private function whenWorkspaceWasDeactivated(WorkspaceWasDeactivated $event): void
{
$this->updateWorkspaceContentStreamId($event->workspaceName, null);
}

private function whenWorkspaceRebaseFailed(WorkspaceRebaseFailed $event): void
{
// legacy handling:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ private function createWorkspaceTable(AbstractPlatform $platform): Table
$workspaceTable = self::createTable($this->tableNames->workspace(), [
DbalSchemaFactory::columnForWorkspaceName('name', $platform)->setNotnull(true),
DbalSchemaFactory::columnForWorkspaceName('baseWorkspaceName', $platform)->setNotnull(false),
DbalSchemaFactory::columnForContentStreamId('currentContentStreamId', $platform)->setNotNull(true),
DbalSchemaFactory::columnForContentStreamId('currentContentStreamId', $platform)->setNotNull(false),
]);

$workspaceTable->addUniqueIndex(['currentContentStreamId']);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ private function updateBaseWorkspace(WorkspaceName $workspaceName, WorkspaceName

private function updateWorkspaceContentStreamId(
WorkspaceName $workspaceName,
ContentStreamId $contentStreamId,
?ContentStreamId $contentStreamId,
): void {
$this->dbal->update($this->tableNames->workspace(), [
'currentContentStreamId' => $contentStreamId->value,
'currentContentStreamId' => $contentStreamId?->value,
], [
'name' => $workspaceName->value
]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
@contentrepository @adapters=DoctrineDBAL
Feature: Deactivate/Activate workspace constraints

Background:
Given using no content dimensions
And using the following node types:
"""yaml
'Neos.ContentRepository.Testing:Content':
properties:
text:
type: string
'Neos.ContentRepository.Testing:Document':
childNodes:
child1:
type: 'Neos.ContentRepository.Testing:Content'
child2:
type: 'Neos.ContentRepository.Testing:Content'
"""
And using identifier "default", I define a content repository
And I am in content repository "default"
And the command CreateRootWorkspace is executed with payload:
| Key | Value |
| workspaceName | "live" |
| newContentStreamId | "cs-identifier" |
And I am in workspace "live"
And the command CreateRootNodeAggregateWithNode is executed with payload:
| Key | Value |
| workspaceName | "live" |
| nodeAggregateId | "lady-eleonode-rootford" |
| nodeTypeName | "Neos.ContentRepository:Root" |

And the command CreateWorkspace is executed with payload:
| Key | Value |
| workspaceName | "user-test" |
| baseWorkspaceName | "live" |
| newContentStreamId | "user-cs-identifier" |

Scenario: Deactivating the workspace is not allowed for workspaces with other workspaces depending on it
When the command DeactivateWorkspace is executed with payload and exceptions are caught:
| Key | Value |
| workspaceName | "live" |

Then the last command should have thrown an exception of type "WorkspaceHasWorkspacesDependingOnIt"

Scenario: Activating the workspace is not allowed for active workspaces
When the command ActivateWorkspace is executed with payload and exceptions are caught:
| Key | Value |
| workspaceName | "user-test" |
| newContentStreamId | "new-user-cs-identifier" |

Then the last command should have thrown an exception of type "WorkspaceIsActivated" with code 1766069245 and message:
"""
The workspace "user-test" is activated
"""

Scenario: Deactivating the workspace is not allowed if there are pending changes
When the command CreateNodeAggregateWithNode is executed with payload:
| Key | Value |
| workspaceName | "user-test" |
| nodeAggregateId | "holy-nody" |
| nodeTypeName | "Neos.ContentRepository.Testing:Content" |
| originDimensionSpacePoint | {} |
| parentNodeAggregateId | "lady-eleonode-rootford" |
| initialPropertyValues | {"text": "New node in shared"} |

Given I am in workspace "user-test" and dimension space point {}
Then I expect node aggregate identifier "holy-nody" to lead to node user-cs-identifier;holy-nody;{}

When the command DeactivateWorkspace is executed with payload and exceptions are caught:
| Key | Value |
| workspaceName | "user-test" |

Then the last command should have thrown an exception of type "WorkspaceContainsPublishableChanges"
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@contentrepository @adapters=DoctrineDBAL
Feature: Deactivate and Activate a Workspace

Background:
Given using no content dimensions
And using the following node types:
"""yaml
'Neos.ContentRepository.Testing:Content':
properties:
text:
type: string
'Neos.ContentRepository.Testing:Document':
childNodes:
child1:
type: 'Neos.ContentRepository.Testing:Content'
child2:
type: 'Neos.ContentRepository.Testing:Content'
"""
And using identifier "default", I define a content repository
And I am in content repository "default"
And the command CreateRootWorkspace is executed with payload:
| Key | Value |
| workspaceName | "live" |
| newContentStreamId | "cs-identifier" |
And I am in workspace "live"
And the command CreateRootNodeAggregateWithNode is executed with payload:
| Key | Value |
| workspaceName | "live" |
| nodeAggregateId | "lady-eleonode-rootford" |
| nodeTypeName | "Neos.ContentRepository:Root" |
When the command CreateNodeAggregateWithNode is executed with payload:
| Key | Value |
| workspaceName | "live" |
| nodeAggregateId | "nody-mc-nodeface" |
| nodeTypeName | "Neos.ContentRepository.Testing:Content" |
| originDimensionSpacePoint | {} |
| parentNodeAggregateId | "lady-eleonode-rootford" |
| initialPropertyValues | {"text": "Original text"} |

And the command CreateWorkspace is executed with payload:
| Key | Value |
| workspaceName | "user-test" |
| baseWorkspaceName | "live" |
| newContentStreamId | "user-cs-identifier" |

Scenario: Deactivating a workspace with no pending changes
When the command DeactivateWorkspace is executed with payload:
| Key | Value |
| workspaceName | "user-test" |
Then workspace user-test has status DEACTIVATED

Scenario: Deactivating an already deactivated Workspace fails
And the command DeactivateWorkspace is executed with payload and exceptions are caught:
| Key | Value |
| workspaceName | "user-test" |
When the command DeactivateWorkspace is executed with payload and exceptions are caught:
| Key | Value |
| workspaceName | "user-test" |
Then the last command should have thrown an exception of type "WorkspaceIsDeactivated" with code 1765977861 and message:
"""
The workspace "user-test" is deactivated
"""

Scenario: Activating a deactivated workspace
When the command DeactivateWorkspace is executed with payload:
| Key | Value |
| workspaceName | "user-test" |
And the command ActivateWorkspace is executed with payload:
| Key | Value |
| workspaceName | "user-test" |
| newContentStreamId | "user-new-cs-identifier" |
Then workspace user-test has status UP_TO_DATE

Given I am in workspace "user-test" and dimension space point {}
Then I expect node aggregate identifier "nody-mc-nodeface" to lead to node user-new-cs-identifier;nody-mc-nodeface;{}

Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
use Neos\ContentRepository\Core\Feature\RootNodeCreation\Event\RootNodeAggregateWithNodeWasCreated;
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasTagged;
use Neos\ContentRepository\Core\Feature\SubtreeTagging\Event\SubtreeWasUntagged;
use Neos\ContentRepository\Core\Feature\WorkspaceActivation\Event\WorkspaceWasActivated;
use Neos\ContentRepository\Core\Feature\WorkspaceActivation\Event\WorkspaceWasDeactivated;
use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Event\RootWorkspaceWasCreated;
use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Event\WorkspaceWasCreated;
use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceBaseWorkspaceWasChanged;
Expand Down Expand Up @@ -107,6 +109,8 @@ public static function create(): self
WorkspaceWasRemoved::class,
WorkspaceOwnerWasChanged::class,
WorkspaceBaseWorkspaceWasChanged::class,
WorkspaceWasActivated::class,
WorkspaceWasDeactivated::class,
];

$fullClassNameToShortEventType = [];
Expand Down
Loading