From c5990903351ed1048bf414866024549b9aa60ece Mon Sep 17 00:00:00 2001 From: Bastian Waidelich Date: Sat, 25 May 2024 19:13:03 +0200 Subject: [PATCH] !!! TASK: Replace dedicated Workspace and ContentStream projections wip --- .../src/ContentGraphTableNames.php | 5 + .../DoctrineDbalContentGraphProjection.php | 80 ++++++++++- .../DoctrineDbalContentGraphSchemaBuilder.php | 13 ++ .../Projection/Feature/ContentStream.php | 54 ++++++++ .../Classes/CommandHandlingDependencies.php | 27 +++- .../Classes/ContentRepository.php | 23 ++-- .../Feature/Common/ConstraintChecks.php | 7 +- .../Feature/ContentStreamCommandHandler.php | 22 ++-- .../Feature/ContentStreamEventStreamName.php | 15 ++- .../Feature/WorkspaceCommandHandler.php | 124 ++++-------------- .../Command/ChangeWorkspaceOwner.php | 36 ----- .../Command/RenameWorkspace.php | 40 ------ .../Event/WorkspaceOwnerWasChanged.php | 3 +- .../Event/WorkspaceWasRenamed.php | 3 +- .../ContentStream/ContentStreamProjection.php | 16 +-- .../Projection/Workspace/Workspaces.php | 26 ++++ .../Service/ContentRepositoryBootstrapper.php | 4 +- .../Service/WorkspaceMaintenanceService.php | 23 ++-- .../Bootstrap/CrImportExportTrait.php | 3 +- .../src/ExportService.php | 8 +- .../src/ExportServiceFactory.php | 7 +- .../src/Processors/AssetExportProcessor.php | 11 +- .../src/Processors/EventExportProcessor.php | 11 +- .../src/NodeMigrationService.php | 2 +- .../Bootstrap/CRTestSuiteRuntimeVariables.php | 2 +- .../Features/Bootstrap/CRTestSuiteTrait.php | 15 +-- .../Features/Bootstrap/ProjectedNodeTrait.php | 1 + .../Command/ContentCommandController.php | 4 +- .../Classes/Controller/UsageController.php | 7 +- .../Service/AssetUsageSyncService.php | 5 +- .../Classes/Command/CrCommandController.php | 11 +- .../Command/WorkspaceCommandController.php | 46 +++---- .../Module/Administration/SitesController.php | 4 +- .../Management/WorkspacesController.php | 65 ++++----- .../Domain/Service/SiteServiceInternals.php | 2 +- .../Classes/Domain/Workspace/Workspace.php | 3 +- .../Domain/Workspace/WorkspaceProvider.php | 2 +- .../FrontendRouting/NodeAddressFactory.php | 7 +- .../Fusion/Cache/ContentCacheFlusher.php | 6 +- ...phProjectorCatchUpHookForCacheFlushing.php | 9 +- .../Classes/Fusion/Helper/CachingHelper.php | 4 +- .../Service/EditorContentStreamZookeeper.php | 4 +- Neos.Neos/Classes/Service/LinkingService.php | 4 +- 43 files changed, 406 insertions(+), 358 deletions(-) create mode 100644 Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/ContentStream.php delete mode 100644 Neos.ContentRepository.Core/Classes/Feature/WorkspaceModification/Command/ChangeWorkspaceOwner.php delete mode 100644 Neos.ContentRepository.Core/Classes/Feature/WorkspaceModification/Command/RenameWorkspace.php diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php index aa404052865..81a95787743 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphTableNames.php @@ -45,6 +45,11 @@ public function workspace(): string return $this->tableNamePrefix . '_workspace'; } + public function contentStream(): string + { + return $this->tableNamePrefix . '_contentstream'; + } + public function checkpoint(): string { return $this->tableNamePrefix . '_checkpoint'; diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php index fedf6cdd0b3..ffe7e7df552 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphProjection.php @@ -7,6 +7,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception as DbalException; use Doctrine\DBAL\Schema\AbstractSchemaManager; +use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\ContentStream; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeMove; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeRemoval; use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\Feature\NodeVariation; @@ -23,6 +24,10 @@ use Neos\ContentRepository\Core\DimensionSpace\OriginDimensionSpacePoint; use Neos\ContentRepository\Core\EventStore\EventInterface; use Neos\ContentRepository\Core\Feature\Common\InterdimensionalSiblings; +use Neos\ContentRepository\Core\Feature\ContentStreamClosing\Event\ContentStreamWasClosed; +use Neos\ContentRepository\Core\Feature\ContentStreamClosing\Event\ContentStreamWasReopened; +use Neos\ContentRepository\Core\Feature\ContentStreamCreation\Event\ContentStreamWasCreated; +use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; use Neos\ContentRepository\Core\Feature\ContentStreamForking\Event\ContentStreamWasForked; use Neos\ContentRepository\Core\Feature\ContentStreamRemoval\Event\ContentStreamWasRemoved; use Neos\ContentRepository\Core\Feature\DimensionSpaceAdjustment\Event\DimensionShineThroughWasAdded; @@ -67,6 +72,7 @@ use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Node\NodeName; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; +use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamState; use Neos\EventStore\Model\Event\SequenceNumber; use Neos\EventStore\Model\EventEnvelope; @@ -76,6 +82,7 @@ */ final class DoctrineDbalContentGraphProjection implements ProjectionInterface, WithMarkStaleInterface { + use ContentStream; use NodeMove; use NodeRemoval; use NodeVariation; @@ -105,7 +112,7 @@ public function setUp(): void { $statements = $this->determineRequiredSqlStatements(); - // MIGRATION from 2024-05-23: copy data from "cr__p_workspace" to "cr__p_graph_workspace" table + // MIGRATION from 2024-05-25: copy data from "cr__p_workspace"/"cr__p_contentstream" to "cr__p_graph_workspace"/"cr__p_graph_contentstream" tables $legacyWorkspaceTableName = str_replace('_p_graph_workspace', '_p_workspace', $this->tableNames->workspace()); if ( $this->dbal->getSchemaManager()->tablesExist([$legacyWorkspaceTableName]) @@ -113,6 +120,13 @@ public function setUp(): void ) { $statements[] = 'INSERT INTO ' . $this->tableNames->workspace() . ' (workspacename, baseworkspacename, currentcontentstreamid, status) SELECT workspacename, baseworkspacename, currentcontentstreamid, status FROM ' . $legacyWorkspaceTableName; } + $legacyContentStreamTableName = str_replace('_p_graph_contentstream', '_p_contentstream', $this->tableNames->contentStream()); + if ( + $this->dbal->getSchemaManager()->tablesExist([$legacyContentStreamTableName]) + && !$this->dbal->getSchemaManager()->tablesExist([$this->tableNames->contentStream()]) + ) { + $statements[] = 'INSERT INTO ' . $this->tableNames->contentStream() . ' (contentStreamId, version, sourceContentStreamId, state, removed) SELECT contentStreamId, version, sourceContentStreamId, state, removed FROM ' . $legacyContentStreamTableName; + } // /MIGRATION foreach ($statements as $statement) { @@ -177,8 +191,11 @@ public function getState(): ContentGraphFinder public function canHandle(EventInterface $event): bool { return in_array($event::class, [ + ContentStreamWasClosed::class, + ContentStreamWasCreated::class, ContentStreamWasForked::class, ContentStreamWasRemoved::class, + ContentStreamWasReopened::class, DimensionShineThroughWasAdded::class, DimensionSpacePointWasMoved::class, NodeAggregateNameWasChanged::class, @@ -211,8 +228,11 @@ public function canHandle(EventInterface $event): bool public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void { match ($event::class) { + ContentStreamWasClosed::class => $this->whenContentStreamWasClosed($event), + ContentStreamWasCreated::class => $this->whenContentStreamWasCreated($event), ContentStreamWasForked::class => $this->whenContentStreamWasForked($event), ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event), + ContentStreamWasReopened::class => $this->whenContentStreamWasReopened($event), DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event), DimensionSpacePointWasMoved::class => $this->whenDimensionSpacePointWasMoved($event), NodeAggregateNameWasChanged::class => $this->whenNodeAggregateNameWasChanged($event, $eventEnvelope), @@ -241,6 +261,19 @@ public function apply(EventInterface $event, EventEnvelope $eventEnvelope): void WorkspaceWasRemoved::class => $this->whenWorkspaceWasRemoved($event), default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), }; + if (ContentStreamEventStreamName::isContentStreamStreamName($eventEnvelope->streamName)) { + $this->updateContentStreamVersion(ContentStreamEventStreamName::extractContentStreamIdFromStreamName($eventEnvelope->streamName), $eventEnvelope->version); + } + } + + private function whenContentStreamWasClosed(ContentStreamWasClosed $event): void + { + $this->updateContentStreamState($event->contentStreamId, ContentStreamState::STATE_CLOSED); + } + + private function whenContentStreamWasCreated(ContentStreamWasCreated $event): void + { + $this->createContentStream($event->contentStreamId, ContentStreamState::STATE_CREATED); } private function whenContentStreamWasForked(ContentStreamWasForked $event): void @@ -278,6 +311,8 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void // NOTE: as reference edges are attached to Relation Anchor Points (and they are lazily copy-on-written), // we do not need to copy reference edges here (but we need to do it during copy on write). + + $this->createContentStream($event->newContentStreamId, ContentStreamState::STATE_FORKED); } private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event): void @@ -321,6 +356,13 @@ private function whenContentStreamWasRemoved(ContentStreamWasRemoved $event): vo } catch (DbalException $e) { throw new \RuntimeException(sprintf('Failed to delete non-referenced reference relations: %s', $e->getMessage()), 1716489328, $e); } + + $this->removeContentStream($event->contentStreamId); + } + + private function whenContentStreamWasReopened(ContentStreamWasReopened $event): void + { + $this->updateContentStreamState($event->contentStreamId, $event->previousState); } private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded $event): void @@ -675,6 +717,9 @@ private function whenRootNodeAggregateWithNodeWasCreated(RootNodeAggregateWithNo private function whenRootWorkspaceWasCreated(RootWorkspaceWasCreated $event): void { $this->createWorkspace($event->workspaceName, null, $event->newContentStreamId); + + // the content stream is in use now + $this->updateContentStreamState($event->newContentStreamId, ContentStreamState::STATE_IN_USE_BY_WORKSPACE); } private function whenSubtreeWasTagged(SubtreeWasTagged $event): void @@ -695,11 +740,15 @@ private function whenWorkspaceBaseWorkspaceWasChanged(WorkspaceBaseWorkspaceWasC private function whenWorkspaceRebaseFailed(WorkspaceRebaseFailed $event): void { $this->markWorkspaceAsOutdatedConflict($event->workspaceName); + $this->updateContentStreamState($event->candidateContentStreamId, ContentStreamState::STATE_REBASE_ERROR); } private function whenWorkspaceWasCreated(WorkspaceWasCreated $event): void { $this->createWorkspace($event->workspaceName, $event->baseWorkspaceName, $event->newContentStreamId); + + // the content stream is in use now + $this->updateContentStreamState($event->newContentStreamId, ContentStreamState::STATE_IN_USE_BY_WORKSPACE); } private function whenWorkspaceWasDiscarded(WorkspaceWasDiscarded $event): void @@ -707,12 +756,23 @@ private function whenWorkspaceWasDiscarded(WorkspaceWasDiscarded $event): void $this->updateWorkspaceContentStreamId($event->workspaceName, $event->newContentStreamId); $this->markWorkspaceAsOutdated($event->workspaceName); $this->markDependentWorkspacesAsOutdated($event->workspaceName); + + // the new content stream is in use now + $this->updateContentStreamState($event->newContentStreamId, ContentStreamState::STATE_IN_USE_BY_WORKSPACE); + // the previous content stream is no longer in use + $this->updateContentStreamState($event->previousContentStreamId, ContentStreamState::STATE_NO_LONGER_IN_USE); } private function whenWorkspaceWasPartiallyDiscarded(WorkspaceWasPartiallyDiscarded $event): void { $this->updateWorkspaceContentStreamId($event->workspaceName, $event->newContentStreamId); $this->markDependentWorkspacesAsOutdated($event->workspaceName); + + // the new content stream is in use now + $this->updateContentStreamState($event->newContentStreamId, ContentStreamState::STATE_IN_USE_BY_WORKSPACE); + + // the previous content stream is no longer in use + $this->updateContentStreamState($event->previousContentStreamId, ContentStreamState::STATE_NO_LONGER_IN_USE); } private function whenWorkspaceWasPartiallyPublished(WorkspaceWasPartiallyPublished $event): void @@ -725,6 +785,12 @@ private function whenWorkspaceWasPartiallyPublished(WorkspaceWasPartiallyPublish $this->markWorkspaceAsUpToDate($event->sourceWorkspaceName); $this->markDependentWorkspacesAsOutdated($event->sourceWorkspaceName); + + // the new content stream is in use now + $this->updateContentStreamState($event->newSourceContentStreamId, ContentStreamState::STATE_IN_USE_BY_WORKSPACE); + + // the previous content stream is no longer in use + $this->updateContentStreamState($event->previousSourceContentStreamId, ContentStreamState::STATE_NO_LONGER_IN_USE); } private function whenWorkspaceWasPublished(WorkspaceWasPublished $event): void @@ -737,6 +803,12 @@ private function whenWorkspaceWasPublished(WorkspaceWasPublished $event): void $this->markWorkspaceAsUpToDate($event->sourceWorkspaceName); $this->markDependentWorkspacesAsOutdated($event->sourceWorkspaceName); + + // the new content stream is in use now + $this->updateContentStreamState($event->newSourceContentStreamId, ContentStreamState::STATE_IN_USE_BY_WORKSPACE); + + // the previous content stream is no longer in use + $this->updateContentStreamState($event->previousSourceContentStreamId, ContentStreamState::STATE_NO_LONGER_IN_USE); } private function whenWorkspaceWasRebased(WorkspaceWasRebased $event): void @@ -746,6 +818,12 @@ private function whenWorkspaceWasRebased(WorkspaceWasRebased $event): void // When the rebase is successful, we can set the status of the workspace back to UP_TO_DATE. $this->markWorkspaceAsUpToDate($event->workspaceName); + + // the new content stream is in use now + $this->updateContentStreamState($event->newContentStreamId, ContentStreamState::STATE_IN_USE_BY_WORKSPACE); + + // the previous content stream is no longer in use + $this->updateContentStreamState($event->previousContentStreamId, ContentStreamState::STATE_NO_LONGER_IN_USE); } private function whenWorkspaceWasRemoved(WorkspaceWasRemoved $event): void diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php index ff46c7d85b6..25c30fa31df 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/DoctrineDbalContentGraphSchemaBuilder.php @@ -31,6 +31,7 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema $this->createReferenceRelationTable(), $this->createDimensionSpacePointsTable(), $this->createWorkspaceTable(), + $this->createContentStreamTable(), ]); } @@ -112,6 +113,18 @@ private function createWorkspaceTable(): Table return $workspaceTable->setPrimaryKey(['workspacename']); } + private function createContentStreamTable(): Table + { + return self::createTable($this->tableNames->contentStream(), [ + DbalSchemaFactory::columnForContentStreamId('contentStreamId')->setNotnull(true), + (new Column('version', Type::getType(Types::INTEGER)))->setNotnull(true), + DbalSchemaFactory::columnForContentStreamId('sourceContentStreamId')->setNotnull(false), + // Should become a DB ENUM (unclear how to configure with DBAL) or int (latter needs adaption to code) + (new Column('state', Type::getType(Types::BINARY)))->setLength(20)->setNotnull(true), + (new Column('removed', Type::getType(Types::BOOLEAN)))->setDefault(false)->setNotnull(false) + ]); + } + /** * @param array $columns */ diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/ContentStream.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/ContentStream.php new file mode 100644 index 00000000000..bc39979bf46 --- /dev/null +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/Domain/Projection/Feature/ContentStream.php @@ -0,0 +1,54 @@ +dbal->insert($this->tableNames->contentStream(), [ + 'contentStreamId' => $contentStreamId->value, + 'sourceContentStreamId' => $sourceContentStreamId?->value, + 'version' => 0, + 'state' => $state->value, + ]); + } + + private function updateContentStreamState(ContentStreamId $contentStreamId, ContentStreamState $state): void + { + $this->dbal->update($this->tableNames->contentStream(), [ + 'state' => $state->value, + ], [ + 'contentStreamId' => $contentStreamId->value + ]); + } + + private function removeContentStream(ContentStreamId $contentStreamId): void + { + $this->dbal->update($this->tableNames->contentStream(), [ + 'removed' => true, + ], [ + 'contentStreamId' => $contentStreamId->value + ]); + } + + private function updateContentStreamVersion(ContentStreamId $contentStreamId, Version $version): void + { + $this->dbal->update($this->tableNames->contentStream(), [ + 'version' => $version->value, + ], [ + 'contentStreamId' => $contentStreamId->value, + ]); + } +} diff --git a/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php b/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php index c0b5270cc37..3f3515e81f3 100644 --- a/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php +++ b/Neos.ContentRepository.Core/Classes/CommandHandlingDependencies.php @@ -17,11 +17,12 @@ use Neos\ContentRepository\Core\CommandHandler\CommandInterface; use Neos\ContentRepository\Core\CommandHandler\CommandResult; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; -use Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamFinder; -use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; +use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamState; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; +use Neos\EventStore\Model\Event\Version; /** * An adapter to provide aceess to read projection data and delegate (sub) commands @@ -46,14 +47,28 @@ public function handle(CommandInterface $command): CommandResult return $this->contentRepository->handle($command); } - public function getWorkspaceFinder(): WorkspaceFinder + public function getContentStreamVersion(ContentStreamId $contentStreamId): Version { - return $this->contentRepository->getWorkspaceFinder(); + // TODO implement + return Version::fromInteger(1); } - public function getContentStreamFinder(): ContentStreamFinder + public function contentStreamExists(ContentStreamId $contentStreamId): bool { - return $this->contentRepository->getContentStreamFinder(); + // TODO implement + return false; + } + + public function getContentStreamState(ContentStreamId $contentStreamId): ContentStreamState + { + // TODO implement + return ContentStreamState::STATE_FORKED; + } + + public function findWorkspaceByName(WorkspaceName $workspaceName): ?Workspace + { + // TODO implement + return null; } /** diff --git a/Neos.ContentRepository.Core/Classes/ContentRepository.php b/Neos.ContentRepository.Core/Classes/ContentRepository.php index f6fc32cbc0e..8dc7a8d7ab0 100644 --- a/Neos.ContentRepository.Core/Classes/ContentRepository.php +++ b/Neos.ContentRepository.Core/Classes/ContentRepository.php @@ -30,12 +30,12 @@ use Neos\ContentRepository\Core\Projection\CatchUp; use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\Projection\ContentGraph\ContentGraphInterface; -use Neos\ContentRepository\Core\Projection\ContentStream\ContentStreamFinder; use Neos\ContentRepository\Core\Projection\ProjectionInterface; use Neos\ContentRepository\Core\Projection\ProjectionsAndCatchUpHooks; use Neos\ContentRepository\Core\Projection\ProjectionStateInterface; use Neos\ContentRepository\Core\Projection\ProjectionStatuses; -use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; +use Neos\ContentRepository\Core\Projection\Workspace\Workspaces; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryStatus; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; @@ -239,22 +239,23 @@ public function getNodeTypeManager(): NodeTypeManager return $this->nodeTypeManager; } - /** - * @throws WorkspaceDoesNotExist if the workspace does not exist - */ - public function getContentGraph(WorkspaceName $workspaceName): ContentGraphInterface + public function findWorkspaceByName(WorkspaceName $workspaceName): ?Workspace { - return $this->projectionState(ContentGraphFinder::class)->getByWorkspaceName($workspaceName); + // TODO implement + return null; } - public function getWorkspaceFinder(): WorkspaceFinder + public function getWorkspaces(): Workspaces { - return $this->projectionState(WorkspaceFinder::class); + // TODO implement } - public function getContentStreamFinder(): ContentStreamFinder + /** + * @throws WorkspaceDoesNotExist if the workspace does not exist + */ + public function getContentGraph(WorkspaceName $workspaceName): ContentGraphInterface { - return $this->projectionState(ContentStreamFinder::class); + return $this->projectionState(ContentGraphFinder::class)->getByWorkspaceName($workspaceName); } public function getVariationGraph(): InterDimensionalVariationGraph diff --git a/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php b/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php index 94198dcf97d..8cea354ca0f 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php +++ b/Neos.ContentRepository.Core/Classes/Feature/Common/ConstraintChecks.php @@ -82,14 +82,13 @@ protected function requireContentStream( CommandHandlingDependencies $commandHandlingDependencies ): ContentStreamId { $contentStreamId = $commandHandlingDependencies->getContentGraph($workspaceName)->getContentStreamId(); - $state = $commandHandlingDependencies->getContentStreamFinder()->findStateForContentStream($contentStreamId); - if ($state === null) { + if (!$commandHandlingDependencies->contentStreamExists($contentStreamId)) { throw new ContentStreamDoesNotExistYet( 'Content stream for "' . $workspaceName->value . '" does not exist yet.', 1521386692 ); } - + $state = $commandHandlingDependencies->getContentStreamState($contentStreamId); if ($state === ContentStreamState::STATE_CLOSED) { throw new ContentStreamIsClosed( 'Content stream "' . $contentStreamId->value . '" is closed.', @@ -680,7 +679,7 @@ protected function getExpectedVersionOfContentStream( ): ExpectedVersion { return ExpectedVersion::fromVersion( - $commandHandlingDependencies->getContentStreamFinder()->findVersionForContentStream($contentStreamId)->unwrap() + $commandHandlingDependencies->getContentStreamVersion($contentStreamId) ); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php index 2c9d9160ccd..c1e33319d5f 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamCommandHandler.php @@ -137,7 +137,7 @@ private function handleForkContentStream( $this->requireContentStreamToNotBeClosed($command->sourceContentStreamId, $commandHandlingDependencies); $this->requireContentStreamToNotExistYet($command->newContentStreamId, $commandHandlingDependencies); - $sourceContentStreamVersion = $commandHandlingDependencies->getContentStreamFinder()->findVersionForContentStream($command->sourceContentStreamId); + $sourceContentStreamVersion = $commandHandlingDependencies->getContentStreamVersion($command->sourceContentStreamId); $streamName = ContentStreamEventStreamName::fromContentStreamId($command->newContentStreamId) ->getEventStreamName(); @@ -148,7 +148,7 @@ private function handleForkContentStream( new ContentStreamWasForked( $command->newContentStreamId, $command->sourceContentStreamId, - $sourceContentStreamVersion->unwrap(), + $sourceContentStreamVersion, ), ), // NO_STREAM to ensure the "fork" happens as the first event of the new content stream @@ -187,7 +187,7 @@ protected function requireContentStreamToNotExistYet( ContentStreamId $contentStreamId, CommandHandlingDependencies $commandHandlingDependencies ): void { - if ($commandHandlingDependencies->getContentStreamFinder()->hasContentStream($contentStreamId)) { + if ($commandHandlingDependencies->contentStreamExists($contentStreamId)) { throw new ContentStreamAlreadyExists( 'Content stream "' . $contentStreamId->value . '" already exists.', 1521386345 @@ -204,8 +204,7 @@ protected function requireContentStreamToExist( ContentStreamId $contentStreamId, CommandHandlingDependencies $commandHandlingDependencies ): void { - $maybeVersion = $commandHandlingDependencies->getContentStreamFinder()->findVersionForContentStream($contentStreamId); - if ($maybeVersion->isNothing()) { + if (!$commandHandlingDependencies->contentStreamExists($contentStreamId)) { throw new ContentStreamDoesNotExistYet( 'Content stream "' . $contentStreamId->value . '" does not exist yet.', 1521386692 @@ -217,8 +216,7 @@ protected function requireContentStreamToNotBeClosed( ContentStreamId $contentStreamId, CommandHandlingDependencies $commandHandlingDependencies ): void { - $contentStreamState = $commandHandlingDependencies->getContentStreamFinder()->findStateForContentStream($contentStreamId); - if ($contentStreamState === ContentStreamState::STATE_CLOSED) { + if ($commandHandlingDependencies->getContentStreamState($contentStreamId) === ContentStreamState::STATE_CLOSED) { throw new ContentStreamIsClosed( 'Content stream "' . $contentStreamId->value . '" is closed.', 1710260081 @@ -230,8 +228,7 @@ protected function requireContentStreamToBeClosed( ContentStreamId $contentStreamId, CommandHandlingDependencies $commandHandlingDependencies ): void { - $contentStreamState = $commandHandlingDependencies->getContentStreamFinder()->findStateForContentStream($contentStreamId); - if ($contentStreamState !== ContentStreamState::STATE_CLOSED) { + if ($commandHandlingDependencies->getContentStreamState($contentStreamId) !== ContentStreamState::STATE_CLOSED) { throw new ContentStreamIsNotClosed( 'Content stream "' . $contentStreamId->value . '" is not closed.', 1710405911 @@ -243,10 +240,7 @@ protected function getExpectedVersionOfContentStream( ContentStreamId $contentStreamId, CommandHandlingDependencies $commandHandlingDependencies ): ExpectedVersion { - $maybeVersion = $commandHandlingDependencies->getContentStreamFinder()->findVersionForContentStream($contentStreamId); - return ExpectedVersion::fromVersion( - $maybeVersion - ->unwrap() - ); + $version = $commandHandlingDependencies->getContentStreamVersion($contentStreamId); + return ExpectedVersion::fromVersion($version); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamEventStreamName.php b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamEventStreamName.php index b1735fc01e9..395d7861959 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/ContentStreamEventStreamName.php +++ b/Neos.ContentRepository.Core/Classes/Feature/ContentStreamEventStreamName.php @@ -24,7 +24,7 @@ */ final readonly class ContentStreamEventStreamName { - public const EVENT_STREAM_NAME_PREFIX = 'ContentStream:'; + private const EVENT_STREAM_NAME_PREFIX = 'ContentStream:'; private function __construct( public string $value @@ -36,6 +36,19 @@ public static function fromContentStreamId(ContentStreamId $contentStreamId): se return new self(self::EVENT_STREAM_NAME_PREFIX . $contentStreamId->value); } + public static function isContentStreamStreamName(StreamName $streamName): bool + { + return str_starts_with($streamName->value, self::EVENT_STREAM_NAME_PREFIX); + } + + public static function extractContentStreamIdFromStreamName(StreamName $streamName): ContentStreamId + { + if (!self::isContentStreamStreamName($streamName)) { + throw new \InvalidArgumentException(sprintf('Failed to extract content stream id from stream name "%s"', $streamName->value), 1716640692); + } + return ContentStreamId::fromString(substr($streamName->value, strlen(self::EVENT_STREAM_NAME_PREFIX))); + } + public function getEventStreamName(): StreamName { return StreamName::fromString($this->value); diff --git a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php index 1e96149f95f..bc87d067fb8 100644 --- a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php +++ b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceCommandHandler.php @@ -41,13 +41,10 @@ use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Exception\BaseWorkspaceDoesNotExist; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Exception\WorkspaceAlreadyExists; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\ChangeBaseWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\ChangeWorkspaceOwner; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\DeleteWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\RenameWorkspace; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceBaseWorkspaceWasChanged; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceOwnerWasChanged; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceWasRemoved; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Event\WorkspaceWasRenamed; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Exception\BaseWorkspaceEqualsWorkspaceException; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Exception\CircularRelationBetweenWorkspacesException; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Exception\WorkspaceIsNotEmptyException; @@ -68,7 +65,6 @@ use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Event\WorkspaceWasRebased; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\WorkspaceRebaseFailed; use Neos\ContentRepository\Core\Projection\Workspace\Workspace; -use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder; use Neos\ContentRepository\Core\SharedModel\Exception\ContentStreamAlreadyExists; use Neos\ContentRepository\Core\SharedModel\Exception\ContentStreamDoesNotExistYet; use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; @@ -103,7 +99,6 @@ public function handle(CommandInterface $command, CommandHandlingDependencies $c /** @phpstan-ignore-next-line */ return match ($command::class) { CreateWorkspace::class => $this->handleCreateWorkspace($command, $commandHandlingDependencies), - RenameWorkspace::class => $this->handleRenameWorkspace($command, $commandHandlingDependencies), CreateRootWorkspace::class => $this->handleCreateRootWorkspace($command, $commandHandlingDependencies), PublishWorkspace::class => $this->handlePublishWorkspace($command, $commandHandlingDependencies), RebaseWorkspace::class => $this->handleRebaseWorkspace($command, $commandHandlingDependencies), @@ -111,7 +106,6 @@ public function handle(CommandInterface $command, CommandHandlingDependencies $c DiscardIndividualNodesFromWorkspace::class => $this->handleDiscardIndividualNodesFromWorkspace($command, $commandHandlingDependencies), DiscardWorkspace::class => $this->handleDiscardWorkspace($command, $commandHandlingDependencies), DeleteWorkspace::class => $this->handleDeleteWorkspace($command, $commandHandlingDependencies), - ChangeWorkspaceOwner::class => $this->handleChangeWorkspaceOwner($command, $commandHandlingDependencies), ChangeBaseWorkspace::class => $this->handleChangeBaseWorkspace($command, $commandHandlingDependencies), }; } @@ -127,9 +121,7 @@ private function handleCreateWorkspace( CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { $this->requireWorkspaceToNotExist($command->workspaceName, $commandHandlingDependencies); - - $baseWorkspace = $commandHandlingDependencies->getWorkspaceFinder()->findOneByName($command->baseWorkspaceName); - if ($baseWorkspace === null) { + if ($commandHandlingDependencies->findWorkspaceByName($command->baseWorkspaceName) === null) { throw new BaseWorkspaceDoesNotExist(sprintf( 'The workspace %s (base workspace of %s) does not exist', $command->baseWorkspaceName->value, @@ -164,30 +156,6 @@ private function handleCreateWorkspace( ); } - /** - * @throws WorkspaceDoesNotExist - */ - private function handleRenameWorkspace( - RenameWorkspace $command, - CommandHandlingDependencies $commandHandlingDependencies - ): EventsToPublish { - $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); - - $events = Events::with( - new WorkspaceWasRenamed( - $command->workspaceName, - $command->workspaceTitle, - $command->workspaceDescription, - ) - ); - - return new EventsToPublish( - WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(), - $events, - ExpectedVersion::STREAM_EXISTS() - ); - } - /** * @param CreateRootWorkspace $command * @return EventsToPublish @@ -236,8 +204,8 @@ private function handlePublishWorkspace( PublishWorkspace $command, CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { - $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); - $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies->getWorkspaceFinder()); + $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies); + $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); $this->publishContentStream( $workspace->currentContentStreamId, @@ -353,14 +321,13 @@ private function handleRebaseWorkspace( RebaseWorkspace $command, CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { - $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); - $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies->getWorkspaceFinder()); + $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies); + $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); $oldWorkspaceContentStreamId = $workspace->currentContentStreamId; - $oldWorkspaceContentStreamIdState = $commandHandlingDependencies->getContentStreamFinder() - ->findStateForContentStream($oldWorkspaceContentStreamId); - if ($oldWorkspaceContentStreamIdState === null) { + if (!$commandHandlingDependencies->contentStreamExists($oldWorkspaceContentStreamId)) { throw new \DomainException('Cannot rebase a workspace with a stateless content stream', 1711718314); } + $oldWorkspaceContentStreamIdState = $commandHandlingDependencies->getContentStreamState($oldWorkspaceContentStreamId); // 0) close old content stream $commandHandlingDependencies->handle( @@ -488,13 +455,13 @@ private function handlePublishIndividualNodesFromWorkspace( CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { $contentGraph = $commandHandlingDependencies->getContentGraph($command->workspaceName); - $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); + $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies); $oldWorkspaceContentStreamId = $workspace->currentContentStreamId; - $oldWorkspaceContentStreamIdState = $commandHandlingDependencies->getContentStreamFinder()->findStateForContentStream($oldWorkspaceContentStreamId); - if ($oldWorkspaceContentStreamIdState === null) { + if (!$commandHandlingDependencies->contentStreamExists($oldWorkspaceContentStreamId)) { throw new \DomainException('Cannot publish nodes on a workspace with a stateless content stream', 1710410114); } - $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies->getWorkspaceFinder()); + $oldWorkspaceContentStreamIdState = $commandHandlingDependencies->getContentStreamState($oldWorkspaceContentStreamId); + $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); // 1) close old content stream $commandHandlingDependencies->handle( @@ -629,13 +596,13 @@ private function handleDiscardIndividualNodesFromWorkspace( CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { $contentGraph = $commandHandlingDependencies->getContentGraph($command->workspaceName); - $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); + $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies); $oldWorkspaceContentStreamId = $contentGraph->getContentStreamId(); - $oldWorkspaceContentStreamIdState = $commandHandlingDependencies->getContentStreamFinder()->findStateForContentStream($contentGraph->getContentStreamId()); - if ($oldWorkspaceContentStreamIdState === null) { + if (!$commandHandlingDependencies->contentStreamExists($contentGraph->getContentStreamId())) { throw new \DomainException('Cannot discard nodes on a workspace with a stateless content stream', 1710408112); } - $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies->getWorkspaceFinder()); + $oldWorkspaceContentStreamIdState = $commandHandlingDependencies->getContentStreamState($contentGraph->getContentStreamId()); + $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); // 1) close old content stream $commandHandlingDependencies->handle( @@ -773,8 +740,8 @@ private function handleDiscardWorkspace( DiscardWorkspace $command, CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { - $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); - $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies->getWorkspaceFinder()); + $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies); + $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); $newContentStream = $command->newContentStreamId; $commandHandlingDependencies->handle( @@ -815,12 +782,12 @@ private function handleChangeBaseWorkspace( ChangeBaseWorkspace $command, CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { - $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); + $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies); $this->requireEmptyWorkspace($workspace); - $this->requireBaseWorkspace($workspace, $commandHandlingDependencies->getWorkspaceFinder()); - $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies->getWorkspaceFinder()); + $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); + $baseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); - $this->requireNonCircularRelationBetweenWorkspaces($workspace, $baseWorkspace, $commandHandlingDependencies->getWorkspaceFinder()); + $this->requireNonCircularRelationBetweenWorkspaces($workspace, $baseWorkspace, $commandHandlingDependencies); $commandHandlingDependencies->handle( ForkContentStream::create( @@ -852,7 +819,7 @@ private function handleDeleteWorkspace( DeleteWorkspace $command, CommandHandlingDependencies $commandHandlingDependencies, ): EventsToPublish { - $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); + $workspace = $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies); $commandHandlingDependencies->handle( RemoveContentStream::create( @@ -874,30 +841,6 @@ private function handleDeleteWorkspace( ); } - /** - * @throws WorkspaceDoesNotExist - */ - private function handleChangeWorkspaceOwner( - ChangeWorkspaceOwner $command, - CommandHandlingDependencies $commandHandlingDependencies - ): EventsToPublish { - $this->requireWorkspace($command->workspaceName, $commandHandlingDependencies->getWorkspaceFinder()); - - $events = Events::with( - new WorkspaceOwnerWasChanged( - $command->workspaceName, - $command->newWorkspaceOwner - ) - ); - - $streamName = WorkspaceEventStreamName::fromWorkspaceName($command->workspaceName)->getEventStreamName(); - return new EventsToPublish( - $streamName, - $events, - ExpectedVersion::STREAM_EXISTS() - ); - } - private function requireWorkspaceToNotExist(WorkspaceName $workspaceName, CommandHandlingDependencies $commandHandlingDependencies): void { try { @@ -916,9 +859,9 @@ private function requireWorkspaceToNotExist(WorkspaceName $workspaceName, Comman /** * @throws WorkspaceDoesNotExist */ - private function requireWorkspace(WorkspaceName $workspaceName, WorkspaceFinder $workspaceFinder): Workspace + private function requireWorkspace(WorkspaceName $workspaceName, CommandHandlingDependencies $commandHandlingDependencies): Workspace { - $workspace = $workspaceFinder->findOneByName($workspaceName); + $workspace = $commandHandlingDependencies->findWorkspaceByName($workspaceName); if (is_null($workspace)) { throw WorkspaceDoesNotExist::butWasSupposedTo($workspaceName); } @@ -930,24 +873,15 @@ private function requireWorkspace(WorkspaceName $workspaceName, WorkspaceFinder * @throws WorkspaceHasNoBaseWorkspaceName * @throws BaseWorkspaceDoesNotExist */ - private function requireBaseWorkspace( - Workspace $workspace, - WorkspaceFinder $workspaceFinder - ): Workspace { + private function requireBaseWorkspace(Workspace $workspace, CommandHandlingDependencies $commandHandlingDependencies): Workspace + { if (is_null($workspace->baseWorkspaceName)) { throw WorkspaceHasNoBaseWorkspaceName::butWasSupposedTo($workspace->workspaceName); } - - try { - $baseWorkspace = $workspaceFinder->findOneByName($workspace->baseWorkspaceName); - } catch (WorkspaceDoesNotExist $_) { - $baseWorkspace = null; - } - + $baseWorkspace = $commandHandlingDependencies->findWorkspaceByName($workspace->baseWorkspaceName); if (is_null($baseWorkspace)) { throw BaseWorkspaceDoesNotExist::butWasSupposedTo($workspace->workspaceName); } - return $baseWorkspace; } @@ -955,7 +889,7 @@ private function requireBaseWorkspace( * @throws BaseWorkspaceEqualsWorkspaceException * @throws CircularRelationBetweenWorkspacesException */ - private function requireNonCircularRelationBetweenWorkspaces(Workspace $workspace, Workspace $baseWorkspace, WorkspaceFinder $workspaceFinder): void + private function requireNonCircularRelationBetweenWorkspaces(Workspace $workspace, Workspace $baseWorkspace, CommandHandlingDependencies $commandHandlingDependencies): void { if ($workspace->workspaceName->equals($baseWorkspace->workspaceName)) { throw new BaseWorkspaceEqualsWorkspaceException(sprintf('The base workspace of the target must be different from the given workspace "%s".', $workspace->workspaceName->value)); @@ -966,7 +900,7 @@ private function requireNonCircularRelationBetweenWorkspaces(Workspace $workspac if ($workspace->workspaceName->equals($nextBaseWorkspace->baseWorkspaceName)) { throw new CircularRelationBetweenWorkspacesException(sprintf('The workspace "%s" is already on the path of the target workspace "%s".', $workspace->workspaceName->value, $baseWorkspace->workspaceName->value)); } - $nextBaseWorkspace = $this->requireBaseWorkspace($workspace, $workspaceFinder); + $nextBaseWorkspace = $this->requireBaseWorkspace($workspace, $commandHandlingDependencies); } } diff --git a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceModification/Command/ChangeWorkspaceOwner.php b/Neos.ContentRepository.Core/Classes/Feature/WorkspaceModification/Command/ChangeWorkspaceOwner.php deleted file mode 100644 index e5b36e4eae2..00000000000 --- a/Neos.ContentRepository.Core/Classes/Feature/WorkspaceModification/Command/ChangeWorkspaceOwner.php +++ /dev/null @@ -1,36 +0,0 @@ - $this->whenContentStreamWasClosed($event, $eventEnvelope), ContentStreamWasCreated::class => $this->whenContentStreamWasCreated($event, $eventEnvelope), + ContentStreamWasForked::class => $this->whenContentStreamWasForked($event, $eventEnvelope), + ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event, $eventEnvelope), + ContentStreamWasReopened::class => $this->whenContentStreamWasReopened($event, $eventEnvelope), + DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event, $eventEnvelope), RootWorkspaceWasCreated::class => $this->whenRootWorkspaceWasCreated($event), + WorkspaceRebaseFailed::class => $this->whenWorkspaceRebaseFailed($event), WorkspaceWasCreated::class => $this->whenWorkspaceWasCreated($event), - ContentStreamWasForked::class => $this->whenContentStreamWasForked($event, $eventEnvelope), WorkspaceWasDiscarded::class => $this->whenWorkspaceWasDiscarded($event), WorkspaceWasPartiallyDiscarded::class => $this->whenWorkspaceWasPartiallyDiscarded($event), WorkspaceWasPartiallyPublished::class => $this->whenWorkspaceWasPartiallyPublished($event), WorkspaceWasPublished::class => $this->whenWorkspaceWasPublished($event), WorkspaceWasRebased::class => $this->whenWorkspaceWasRebased($event), - WorkspaceRebaseFailed::class => $this->whenWorkspaceRebaseFailed($event), - ContentStreamWasClosed::class => $this->whenContentStreamWasClosed($event, $eventEnvelope), - ContentStreamWasReopened::class => $this->whenContentStreamWasReopened($event, $eventEnvelope), - ContentStreamWasRemoved::class => $this->whenContentStreamWasRemoved($event, $eventEnvelope), - DimensionShineThroughWasAdded::class => $this->whenDimensionShineThroughWasAdded($event, $eventEnvelope), default => throw new \InvalidArgumentException(sprintf('Unsupported event %s', get_debug_type($event))), }; } @@ -399,13 +399,13 @@ private static function extractVersion(EventEnvelope $eventEnvelope): int if ( !str_starts_with( $eventEnvelope->streamName->value, - ContentStreamEventStreamName::EVENT_STREAM_NAME_PREFIX + 'ContentStream:' ) ) { throw new \RuntimeException( 'Cannot extract version number, as it was projected on wrong stream "' . $eventEnvelope->streamName->value . '", but needs to start with ' - . ContentStreamEventStreamName::EVENT_STREAM_NAME_PREFIX + . 'ContentStream:' ); } return $eventEnvelope->version->value; diff --git a/Neos.ContentRepository.Core/Classes/Projection/Workspace/Workspaces.php b/Neos.ContentRepository.Core/Classes/Projection/Workspace/Workspaces.php index f8fea6db6db..82a9399355c 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/Workspace/Workspaces.php +++ b/Neos.ContentRepository.Core/Classes/Projection/Workspace/Workspaces.php @@ -100,8 +100,34 @@ public function getIterator(): \Traversable yield from array_values($this->workspaces); } + /** + * @param \Closure(Workspace): bool $callback + */ + public function filter(\Closure $callback): self + { + return new self(array_Filter($this->workspaces, $callback)); + } + + /** + * @param \Closure(Workspace): bool $callback + */ + public function find(\Closure $callback): ?Workspace + { + foreach ($this->workspaces as $workspace) { + if ($callback($workspace)) { + return $workspace; + } + } + return null; + } + public function count(): int { return count($this->workspaces); } + + public function isEmpty(): bool + { + return $this->workspaces === []; + } } diff --git a/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php b/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php index b5b92e1858a..3c459eec4c8 100644 --- a/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php +++ b/Neos.ContentRepository.Core/Classes/Service/ContentRepositoryBootstrapper.php @@ -40,7 +40,7 @@ public static function create(ContentRepository $contentRepository): self public function getOrCreateLiveWorkspace(): Workspace { $liveWorkspaceName = WorkspaceName::forLive(); - $liveWorkspace = $this->contentRepository->getWorkspaceFinder()->findOneByName($liveWorkspaceName); + $liveWorkspace = $this->contentRepository->findWorkspaceByName($liveWorkspaceName); if ($liveWorkspace instanceof Workspace) { return $liveWorkspace; } @@ -53,7 +53,7 @@ public function getOrCreateLiveWorkspace(): Workspace ContentStreamId::create() ) ); - $liveWorkspace = $this->contentRepository->getWorkspaceFinder()->findOneByName($liveWorkspaceName); + $liveWorkspace = $this->contentRepository->findWorkspaceByName($liveWorkspaceName); if (!$liveWorkspace) { throw new \Exception('Live workspace creation failed', 1699002435); } diff --git a/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php b/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php index 053d0dc3565..521af3a1a40 100644 --- a/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php +++ b/Neos.ContentRepository.Core/Classes/Service/WorkspaceMaintenanceService.php @@ -10,6 +10,8 @@ use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Command\RebaseWorkspace; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Dto\RebaseErrorHandlingStrategy; use Neos\ContentRepository\Core\Projection\Workspace\Workspace; +use Neos\ContentRepository\Core\Projection\Workspace\Workspaces; +use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceStatus; use Neos\EventStore\EventStoreInterface; /** @@ -24,17 +26,18 @@ public function __construct( } /** - * @return array the workspaces of the removed content streams - * @throws \Doctrine\DBAL\Driver\Exception - * @throws \Doctrine\DBAL\Exception - * @throws \Neos\ContentRepository\Core\Feature\WorkspaceCreation\Exception\BaseWorkspaceDoesNotExist - * @throws \Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist + * @return Workspaces the workspaces of the removed content streams */ - public function rebaseOutdatedWorkspaces(?RebaseErrorHandlingStrategy $strategy = null): array + public function rebaseOutdatedWorkspaces(?RebaseErrorHandlingStrategy $strategy = null): Workspaces { - $outdatedWorkspaces = $this->contentRepository->getWorkspaceFinder()->findOutdated(); - + $outdatedWorkspaces = $this->contentRepository->getWorkspaces()->filter( + fn (Workspace $workspace) => $workspace->status === WorkspaceStatus::OUTDATED + ); + /** @var Workspace $workspace */ foreach ($outdatedWorkspaces as $workspace) { + if ($workspace->status !== WorkspaceStatus::OUTDATED) { + continue; + } $rebaseCommand = RebaseWorkspace::create( $workspace->workspaceName, ); @@ -49,9 +52,7 @@ public function rebaseOutdatedWorkspaces(?RebaseErrorHandlingStrategy $strategy public function pruneAll(): void { - $workspaces = $this->contentRepository->getWorkspaceFinder()->findAll(); - - foreach ($workspaces as $workspace) { + foreach ($this->contentRepository->getWorkspaces() as $workspace) { $streamName = WorkspaceEventStreamName::fromWorkspaceName($workspace->workspaceName)->getEventStreamName(); $this->eventStore->deleteStream($streamName); } diff --git a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php index 2b1ce7fd096..16b8155fe8f 100644 --- a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php +++ b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php @@ -21,6 +21,7 @@ use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; +use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepository\Export\Event\ValueObject\ExportedEvents; use Neos\ContentRepository\Export\ProcessorResult; use Neos\ContentRepository\Export\Processors\EventExportProcessor; @@ -64,7 +65,7 @@ public function __construct(private readonly Filesystem $filesystem) public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): EventExportProcessor { return new EventExportProcessor( $this->filesystem, - $serviceFactoryDependencies->contentRepository->getWorkspaceFinder(), + $serviceFactoryDependencies->contentRepository->findWorkspaceByName(WorkspaceName::forLive())->currentContentStreamId, $serviceFactoryDependencies->eventStore ); } diff --git a/Neos.ContentRepository.Export/src/ExportService.php b/Neos.ContentRepository.Export/src/ExportService.php index 00a45bcbb16..51707a57a93 100644 --- a/Neos.ContentRepository.Export/src/ExportService.php +++ b/Neos.ContentRepository.Export/src/ExportService.php @@ -5,7 +5,7 @@ use League\Flysystem\Filesystem; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; -use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder; +use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Export\Processors\AssetExportProcessor; use Neos\ContentRepository\Export\Processors\EventExportProcessor; use Neos\EventStore\EventStoreInterface; @@ -20,7 +20,7 @@ class ExportService implements ContentRepositoryServiceInterface public function __construct( private readonly Filesystem $filesystem, - private readonly WorkspaceFinder $workspaceFinder, + private readonly ContentStreamId $targetContentStreamId, private readonly AssetRepository $assetRepository, private readonly AssetUsageFinder $assetUsageFinder, private readonly EventStoreInterface $eventStore, @@ -33,13 +33,13 @@ public function runAllProcessors(\Closure $outputLineFn, bool $verbose = false): $processors = [ 'Exporting events' => new EventExportProcessor( $this->filesystem, - $this->workspaceFinder, + $this->targetContentStreamId, $this->eventStore ), 'Exporting assets' => new AssetExportProcessor( $this->filesystem, $this->assetRepository, - $this->workspaceFinder, + $this->targetContentStreamId, $this->assetUsageFinder ) ]; diff --git a/Neos.ContentRepository.Export/src/ExportServiceFactory.php b/Neos.ContentRepository.Export/src/ExportServiceFactory.php index baa013bca98..4e2dadd59a5 100644 --- a/Neos.ContentRepository.Export/src/ExportServiceFactory.php +++ b/Neos.ContentRepository.Export/src/ExportServiceFactory.php @@ -6,7 +6,8 @@ use League\Flysystem\Filesystem; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface; -use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; +use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\Media\Domain\Repository\AssetRepository; use Neos\Neos\AssetUsage\Projection\AssetUsageFinder; @@ -19,7 +20,7 @@ class ExportServiceFactory implements ContentRepositoryServiceFactoryInterface public function __construct( private readonly Filesystem $filesystem, - private readonly WorkspaceFinder $workspaceFinder, + private readonly ContentStreamId $targetContentStreamId, private readonly AssetRepository $assetRepository, private readonly AssetUsageFinder $assetUsageFinder, ) { @@ -29,7 +30,7 @@ public function build(ContentRepositoryServiceFactoryDependencies $serviceFactor { return new ExportService( $this->filesystem, - $this->workspaceFinder, + $this->targetContentStreamId, $this->assetRepository, $this->assetUsageFinder, $serviceFactoryDependencies->eventStore, diff --git a/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php b/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php index db7679a18b9..8373616c6d7 100644 --- a/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php +++ b/Neos.ContentRepository.Export/src/Processors/AssetExportProcessor.php @@ -3,8 +3,7 @@ namespace Neos\ContentRepository\Export\Processors; use League\Flysystem\Filesystem; -use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder; -use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; +use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Export\Asset\ValueObject\SerializedAsset; use Neos\ContentRepository\Export\Asset\ValueObject\SerializedImageVariant; use Neos\ContentRepository\Export\ProcessorInterface; @@ -31,7 +30,7 @@ final class AssetExportProcessor implements ProcessorInterface public function __construct( private readonly Filesystem $files, private readonly AssetRepository $assetRepository, - private readonly WorkspaceFinder $workspaceFinder, + private readonly ContentStreamId $targetContentStreamId, private readonly AssetUsageFinder $assetUsageFinder, ) {} @@ -43,11 +42,7 @@ public function onMessage(\Closure $callback): void public function run(): ProcessorResult { - $liveWorkspace = $this->workspaceFinder->findOneByName(WorkspaceName::forLive()); - if ($liveWorkspace === null) { - return ProcessorResult::error('Failed to find live workspace'); - } - $assetFilter = AssetUsageFilter::create()->withContentStream($liveWorkspace->currentContentStreamId)->groupByAsset(); + $assetFilter = AssetUsageFilter::create()->withContentStream($this->targetContentStreamId)->groupByAsset(); $numberOfExportedAssets = 0; $numberOfExportedImageVariants = 0; diff --git a/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php b/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php index 5bd6b142dec..d12fc5a1d08 100644 --- a/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php +++ b/Neos.ContentRepository.Export/src/Processors/EventExportProcessor.php @@ -6,8 +6,7 @@ use League\Flysystem\FilesystemException; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Feature\ContentStreamEventStreamName; -use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceFinder; -use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; +use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Export\Event\ValueObject\ExportedEvent; use Neos\ContentRepository\Export\ProcessorInterface; use Neos\ContentRepository\Export\ProcessorResult; @@ -24,7 +23,7 @@ final class EventExportProcessor implements ProcessorInterface, ContentRepositor public function __construct( private readonly Filesystem $files, - private readonly WorkspaceFinder $workspaceFinder, + private readonly ContentStreamId $targetContentStreamId, private readonly EventStoreInterface $eventStore, ) { } @@ -36,11 +35,7 @@ public function onMessage(\Closure $callback): void public function run(): ProcessorResult { - $liveWorkspace = $this->workspaceFinder->findOneByName(WorkspaceName::forLive()); - if ($liveWorkspace === null) { - return ProcessorResult::error('Failed to find live workspace'); - } - $streamName = ContentStreamEventStreamName::fromContentStreamId($liveWorkspace->currentContentStreamId)->getEventStreamName(); + $streamName = ContentStreamEventStreamName::fromContentStreamId($this->targetContentStreamId)->getEventStreamName(); $eventStream = $this->eventStore->load($streamName); $eventFileResource = fopen('php://temp/maxmemory:5242880', 'rb+'); diff --git a/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php b/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php index 4184b8b4569..eb8d1cbe775 100644 --- a/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php +++ b/Neos.ContentRepository.NodeMigration/src/NodeMigrationService.php @@ -59,7 +59,7 @@ public function __construct( public function executeMigration(ExecuteMigration $command): void { - $workspace = $this->contentRepository->getWorkspaceFinder()->findOneByName($command->getWorkspaceName()); + $workspace = $this->contentRepository->findWorkspaceByName($command->getWorkspaceName()); if ($workspace === null) { throw new WorkspaceDoesNotExist(sprintf( 'The workspace %s does not exist', diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php index 656e45666cc..8d3173d591d 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteRuntimeVariables.php @@ -100,7 +100,7 @@ public function iAmInContentStream(string $contentStreamId): void */ public function iAmInWorkspace(string $workspaceName): void { - $workspace = $this->currentContentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($workspaceName)); + $workspace = $this->currentContentRepository->findWorkspaceByName(WorkspaceName::fromString($workspaceName)); if ($workspace === null) { throw new \Exception(sprintf('Workspace "%s" does not exist, projection not yet up to date?', $workspaceName), 1548149355); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php index 057edaa23b6..8c19546aae6 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php @@ -136,9 +136,9 @@ protected function readPayloadTable(TableNode $payloadTable): array */ public function workspacesPointToDifferentContentStreams(string $rawWorkspaceNameA, string $rawWorkspaceNameB): void { - $workspaceA = $this->currentContentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($rawWorkspaceNameA)); + $workspaceA = $this->currentContentRepository->findWorkspaceByName(WorkspaceName::fromString($rawWorkspaceNameA)); Assert::assertInstanceOf(Workspace::class, $workspaceA, 'Workspace "' . $rawWorkspaceNameA . '" does not exist.'); - $workspaceB = $this->currentContentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($rawWorkspaceNameB)); + $workspaceB = $this->currentContentRepository->findWorkspaceByName(WorkspaceName::fromString($rawWorkspaceNameB)); Assert::assertInstanceOf(Workspace::class, $workspaceB, 'Workspace "' . $rawWorkspaceNameB . '" does not exist.'); if ($workspaceA && $workspaceB) { Assert::assertNotEquals( @@ -154,9 +154,9 @@ public function workspacesPointToDifferentContentStreams(string $rawWorkspaceNam */ public function workspaceDoesNotPointToContentStream(string $rawWorkspaceName, string $rawContentStreamId): void { - $workspace = $this->currentContentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($rawWorkspaceName)); + $workspace = $this->currentContentRepository->findWorkspaceByName(WorkspaceName::fromString($rawWorkspaceName)); - Assert::assertNotEquals($rawContentStreamId, $workspace->currentContentStreamId->value); + Assert::assertNotEquals($rawContentStreamId, $workspace?->currentContentStreamId->value); } /** @@ -164,9 +164,9 @@ public function workspaceDoesNotPointToContentStream(string $rawWorkspaceName, s */ public function workspaceHasStatus(string $rawWorkspaceName, string $status): void { - $workspace = $this->currentContentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($rawWorkspaceName)); + $workspace = $this->currentContentRepository->findWorkspaceByName(WorkspaceName::fromString($rawWorkspaceName)); - Assert::assertSame($status, $workspace->status->value); + Assert::assertSame($status, $workspace?->status->value); } /** @@ -269,8 +269,7 @@ public function theCurrentContentStreamHasState(string $expectedState): void { $this->theContentStreamHasState( $this->currentContentRepository - ->getWorkspaceFinder() - ->findOneByName($this->currentWorkspaceName) + ->findWorkspaceByName($this->currentWorkspaceName) ->currentContentStreamId->value, $expectedState ); diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php index ad96bdacce4..41d9832d1b7 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/ProjectedNodeTrait.php @@ -83,6 +83,7 @@ public function iExpectANodeIdentifiedByXToExistInTheContentGraph(string $serial $nodeDiscriminator = NodeDiscriminator::fromShorthand($serializedNodeDiscriminator); $contentGraphFinder = $this->currentContentRepository->projectionState(ContentGraphFinder::class); $contentGraphFinder->forgetInstances(); + // TODO Fix $workspaceName = $this->currentContentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId( $nodeDiscriminator->contentStreamId )->workspaceName; diff --git a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php index 9262230ceca..707b012e0a8 100644 --- a/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php +++ b/Neos.ContentRepositoryRegistry/Classes/Command/ContentCommandController.php @@ -52,7 +52,7 @@ public function refreshRootNodeDimensionsCommand(string $contentRepository = 'de $contentRepositoryId = ContentRepositoryId::fromString($contentRepository); $contentRepositoryInstance = $this->contentRepositoryRegistry->get($contentRepositoryId); - $workspaceInstance = $contentRepositoryInstance->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($workspace)); + $workspaceInstance = $contentRepositoryInstance->findWorkspaceByName(WorkspaceName::fromString($workspace)); if ($workspaceInstance === null) { $this->outputLine('Workspace "%s" does not exist', [$workspace]); $this->quit(1); @@ -102,7 +102,7 @@ public function moveDimensionSpacePointCommand(string $source, string $target, s $targetDimensionSpacePoint = DimensionSpacePoint::fromJsonString($target); $contentRepositoryInstance = $this->contentRepositoryRegistry->get($contentRepositoryId); - $workspaceInstance = $contentRepositoryInstance->getWorkspaceFinder()->findOneByName(WorkspaceName::fromString($workspace)); + $workspaceInstance = $contentRepositoryInstance->findWorkspaceByName(WorkspaceName::fromString($workspace)); if ($workspaceInstance === null) { $this->outputLine('Workspace "%s" does not exist', [$workspace]); $this->quit(1); diff --git a/Neos.Media.Browser/Classes/Controller/UsageController.php b/Neos.Media.Browser/Classes/Controller/UsageController.php index bde620635cb..7bf73d78a7e 100644 --- a/Neos.Media.Browser/Classes/Controller/UsageController.php +++ b/Neos.Media.Browser/Classes/Controller/UsageController.php @@ -14,6 +14,7 @@ use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\FindClosestNodeFilter; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\Exception\NodeTypeNotFound; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry; @@ -77,7 +78,7 @@ public function relatedNodesAction(AssetInterface $asset) $currentContentRepositoryId = SiteDetectionResult::fromRequest($this->request->getHttpRequest())->contentRepositoryId; $currentContentRepository = $this->contentRepositoryRegistry->get($currentContentRepositoryId); $userWorkspaceName = WorkspaceName::fromString($this->userService->getPersonalWorkspaceName()); - $userWorkspace = $currentContentRepository->getWorkspaceFinder()->findOneByName($userWorkspaceName); + $userWorkspace = $currentContentRepository->findWorkspaceByName($userWorkspaceName); $usageReferences = $this->assetService->getUsageReferences($asset); $relatedNodes = []; @@ -98,7 +99,9 @@ public function relatedNodesAction(AssetInterface $asset) $contentRepository = $this->contentRepositoryRegistry->get($usage->getContentRepositoryId()); - $workspace = $contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId($usage->getContentStreamId()); + $workspace = $contentRepository->getWorkspaces()->find( + fn (Workspace $potentialWorkspace) => $potentialWorkspace->currentContentStreamId->equals($usage->getContentStreamId()) + ); // FIXME: AssetUsageReference->workspaceName ? $nodeAggregate = $contentRepository->getContentGraph($workspace->workspaceName)->findNodeAggregateById( diff --git a/Neos.Neos/Classes/AssetUsage/Service/AssetUsageSyncService.php b/Neos.Neos/Classes/AssetUsage/Service/AssetUsageSyncService.php index f73bf9865d5..cb4c17337ef 100644 --- a/Neos.Neos/Classes/AssetUsage/Service/AssetUsageSyncService.php +++ b/Neos.Neos/Classes/AssetUsage/Service/AssetUsageSyncService.php @@ -7,6 +7,7 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; use Neos\Media\Domain\Model\AssetInterface; use Neos\Media\Domain\Repository\AssetRepository; use Neos\Neos\AssetUsage\Dto\AssetUsage; @@ -56,7 +57,9 @@ public function isAssetUsageStillValid(AssetUsage $usage): bool $dimensionSpacePoint = $usage->originDimensionSpacePoint->toDimensionSpacePoint(); // FIXME: AssetUsage->workspaceName ? - $workspace = $this->contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId($usage->contentStreamId); + $workspace = $this->contentRepository->getWorkspaces()->find( + fn (Workspace $potentialWorkspace) => $potentialWorkspace->currentContentStreamId->equals($usage->contentStreamId) + ); if (is_null($workspace)) { return false; } diff --git a/Neos.Neos/Classes/Command/CrCommandController.php b/Neos.Neos/Classes/Command/CrCommandController.php index af2719e83e4..af42afec9af 100644 --- a/Neos.Neos/Classes/Command/CrCommandController.php +++ b/Neos.Neos/Classes/Command/CrCommandController.php @@ -9,6 +9,7 @@ use Neos\ContentRepository\Core\Projection\CatchUpOptions; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; +use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepository\Export\ExportService; use Neos\ContentRepository\Export\ExportServiceFactory; use Neos\ContentRepository\Export\ImportService; @@ -54,18 +55,22 @@ public function __construct( public function exportCommand(string $path, string $contentRepository = 'default', bool $verbose = false): void { $contentRepositoryId = ContentRepositoryId::fromString($contentRepository); - $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId); + $contentRepositoryInstance = $this->contentRepositoryRegistry->get($contentRepositoryId); Files::createDirectoryRecursively($path); $filesystem = new Filesystem(new LocalFilesystemAdapter($path)); + $liveWorkspace = $contentRepositoryInstance->findWorkspaceByName(WorkspaceName::forLive()); + if ($liveWorkspace === null) { + throw new \RuntimeException('Failed to find live workspace', 1716652280); + } $exportService = $this->contentRepositoryRegistry->buildService( $contentRepositoryId, new ExportServiceFactory( $filesystem, - $contentRepository->getWorkspaceFinder(), + $liveWorkspace->currentContentStreamId, $this->assetRepository, - $contentRepository->projectionState(AssetUsageFinder::class), + $contentRepositoryInstance->projectionState(AssetUsageFinder::class), ) ); assert($exportService instanceof ExportService); diff --git a/Neos.Neos/Classes/Command/WorkspaceCommandController.php b/Neos.Neos/Classes/Command/WorkspaceCommandController.php index 64d86078143..2d5ccc2119f 100644 --- a/Neos.Neos/Classes/Command/WorkspaceCommandController.php +++ b/Neos.Neos/Classes/Command/WorkspaceCommandController.php @@ -22,6 +22,7 @@ use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Dto\RebaseErrorHandlingStrategy; use Neos\ContentRepository\Core\Feature\WorkspaceRebase\Exception\WorkspaceRebaseFailed; use Neos\ContentRepository\Core\Projection\Workspace\Workspace; +use Neos\ContentRepository\Core\Projection\Workspace\Workspaces; use Neos\ContentRepository\Core\Projection\Workspace\WorkspaceStatus; use Neos\ContentRepository\Core\Service\WorkspaceMaintenanceServiceFactory; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; @@ -242,13 +243,13 @@ public function deleteCommand(string $workspace, bool $force = false, string $co $this->quit(2); } - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName($workspaceName); - if (!$workspace instanceof Workspace) { + $workspaceInstance = $contentRepository->findWorkspaceByName($workspaceName); + if (!$workspaceInstance instanceof Workspace) { $this->outputLine('Workspace "%s" does not exist', [$workspaceName->value]); $this->quit(1); } - if ($workspace->isPersonalWorkspace()) { + if ($workspaceInstance->isPersonalWorkspace()) { $this->outputLine( 'Did not delete workspace "%s" because it is a personal workspace.' . ' Personal workspaces cannot be deleted manually.', @@ -257,21 +258,21 @@ public function deleteCommand(string $workspace, bool $force = false, string $co $this->quit(2); } - $dependentWorkspaces = $contentRepository->getWorkspaceFinder()->findByBaseWorkspace($workspaceName); - if (count($dependentWorkspaces) > 0) { + $dependentWorkspaces = $contentRepository->getWorkspaces()->filter( + static fn (Workspace $potentiallyDependentWorkspace) => $potentiallyDependentWorkspace->baseWorkspaceName?->equals($workspaceName) ?? false + ); + if (!$dependentWorkspaces->isEmpty()) { $this->outputLine( 'Workspace "%s" cannot be deleted because the following workspaces are based on it:', [$workspaceName->value] ); $this->outputLine(); $tableRows = []; - $headerRow = ['Name', 'Title', 'Description']; + $headerRow = ['Name']; foreach ($dependentWorkspaces as $dependentWorkspace) { $tableRows[] = [ $dependentWorkspace->workspaceName->value, - $dependentWorkspace->workspaceTitle->value, - $dependentWorkspace->workspaceDescription->value ]; } $this->output->outputTable($tableRows, $headerRow); @@ -281,10 +282,10 @@ public function deleteCommand(string $workspace, bool $force = false, string $co try { $nodesCount = $contentRepository->projectionState(ChangeFinder::class) ->countByContentStreamId( - $workspace->currentContentStreamId + $workspaceInstance->currentContentStreamId ); } catch (\Exception $exception) { - $this->outputLine('Could not fetch unpublished nodes for workspace %s, nothing was deleted. %s', [$workspace->workspaceName->value, $exception->getMessage()]); + $this->outputLine('Could not fetch unpublished nodes for workspace %s, nothing was deleted. %s', [$workspaceInstance->workspaceName->value, $exception->getMessage()]); $this->quit(4); } @@ -298,11 +299,11 @@ public function deleteCommand(string $workspace, bool $force = false, string $co $this->quit(5); } // @todo bypass access control? - $workspace = $this->workspaceProvider->provideForWorkspaceName( + $workspaceService = $this->workspaceProvider->provideForWorkspaceName( $contentRepositoryId, $workspaceName ); - $workspace->discardAllChanges(); + $workspaceService->discardAllChanges(); } $contentRepository->handle( @@ -327,12 +328,12 @@ public function rebaseOutdatedCommand(string $contentRepositoryIdentifier = 'def $force ? RebaseErrorHandlingStrategy::STRATEGY_FORCE : RebaseErrorHandlingStrategy::STRATEGY_FAIL ); - if (!count($outdatedWorkspaces)) { + if ($outdatedWorkspaces->isEmpty()) { $this->outputLine('There are no outdated workspaces.'); - } else { - foreach ($outdatedWorkspaces as $outdatedWorkspace) { - $this->outputFormatted('Rebased workspace %s', [$outdatedWorkspace->workspaceName->value]); - } + return; + } + foreach ($outdatedWorkspaces as $outdatedWorkspace) { + $this->outputFormatted('Rebased workspace %s', [$outdatedWorkspace->workspaceName->value]); } } @@ -344,26 +345,21 @@ public function rebaseOutdatedCommand(string $contentRepositoryIdentifier = 'def public function listCommand(string $contentRepositoryIdentifier = 'default'): void { $contentRepositoryId = ContentRepositoryId::fromString($contentRepositoryIdentifier); - $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId); - - $workspaces = $contentRepository->getWorkspaceFinder()->findAll(); + $workspaces = $this->contentRepositoryRegistry->get($contentRepositoryId)->getWorkspaces(); - if (count($workspaces) === 0) { + if ($workspaces->isEmpty()) { $this->outputLine('No workspaces found.'); $this->quit(0); } $tableRows = []; - $headerRow = ['Name', 'Base Workspace', 'Title', 'Owner', 'Description', 'Status', 'Content Stream']; + $headerRow = ['Name', 'Base Workspace', 'Status', 'Content Stream']; foreach ($workspaces as $workspace) { /* @var Workspace $workspace */ $tableRows[] = [ $workspace->workspaceName->value, $workspace->baseWorkspaceName?->value ?: '', - $workspace->workspaceTitle->value, - $workspace->workspaceOwner ?: '', - $workspace->workspaceDescription->value, $workspace->status->value, $workspace->currentContentStreamId->value, ]; diff --git a/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php b/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php index 7ee46bbe473..9e56752f609 100755 --- a/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php +++ b/Neos.Neos/Classes/Controller/Module/Administration/SitesController.php @@ -176,7 +176,7 @@ public function updateSiteAction(Site $site, $newSiteNodeName) if ($site->getNodeName()->value !== $newSiteNodeName) { $contentRepository = $this->contentRepositoryRegistry->get($site->getConfiguration()->contentRepositoryId); - $liveWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::forLive()); + $liveWorkspace = $contentRepository->findWorkspaceByName(WorkspaceName::forLive()); if (!$liveWorkspace instanceof Workspace) { throw new \InvalidArgumentException( 'Cannot update a site without the live workspace being present.', @@ -203,7 +203,7 @@ public function updateSiteAction(Site $site, $newSiteNodeName) ); } - foreach ($contentRepository->getWorkspaceFinder()->findAll() as $workspace) { + foreach ($contentRepository->getWorkspaces() as $workspace) { $siteNodeAggregate = $contentRepository->getContentGraph($workspace->workspaceName)->findChildNodeAggregateByName( $sitesNode->nodeAggregateId, $site->getNodeName()->toNodeName() diff --git a/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php b/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php index 92f7fded383..d4b59f8a98c 100644 --- a/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php +++ b/Neos.Neos/Classes/Controller/Module/Management/WorkspacesController.php @@ -18,9 +18,7 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Command\CreateWorkspace; use Neos\ContentRepository\Core\Feature\WorkspaceCreation\Exception\WorkspaceAlreadyExists; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\ChangeWorkspaceOwner; use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\DeleteWorkspace; -use Neos\ContentRepository\Core\Feature\WorkspaceModification\Command\RenameWorkspace; use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\DiscardIndividualNodesFromWorkspace; use Neos\ContentRepository\Core\Feature\WorkspacePublication\Command\PublishIndividualNodesFromWorkspace; use Neos\ContentRepository\Core\Feature\WorkspacePublication\Dto\NodeIdsToPublishOrDiscard; @@ -115,7 +113,7 @@ public function indexAction() if ($currentAccount === null) { throw new \RuntimeException('No account is authenticated', 1710068839); } - $userWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName( + $userWorkspace = $contentRepository->findWorkspaceByName( WorkspaceNameBuilder::fromAccountIdentifier($currentAccount->getAccountIdentifier()) ); if (is_null($userWorkspace)) { @@ -133,11 +131,14 @@ public function indexAction() ] ]; - foreach ($contentRepository->getWorkspaceFinder()->findAll() as $workspace) { + foreach ($contentRepository->getWorkspaces() as $workspace) { /** @var \Neos\ContentRepository\Core\Projection\Workspace\Workspace $workspace */ // FIXME: This check should be implemented through a specialized Workspace Privilege or something similar if (!$workspace->isPersonalWorkspace() && ($workspace->isInternalWorkspace() || $this->domainUserService->currentUserCanManageWorkspace($workspace))) { $workspaceName = $workspace->workspaceName->value; + $dependentWorkspaces = $contentRepository->getWorkspaces()->filter( + static fn (Workspace $potentiallyDependentWorkspace) => $potentiallyDependentWorkspace->baseWorkspaceName?->equals($workspace->workspaceName) ?? false + ); $workspacesAndCounts[$workspaceName]['workspace'] = $workspace; $workspacesAndCounts[$workspaceName]['changesCounts'] = $this->computeChangesCount($workspace, $contentRepository); @@ -145,9 +146,7 @@ public function indexAction() = $this->domainUserService->currentUserCanPublishToWorkspace($workspace); $workspacesAndCounts[$workspaceName]['canManage'] = $this->domainUserService->currentUserCanManageWorkspace($workspace); - $workspacesAndCounts[$workspaceName]['dependentWorkspacesCount'] = count( - $contentRepository->getWorkspaceFinder()->findByBaseWorkspace($workspace->workspaceName) - ); + $workspacesAndCounts[$workspaceName]['dependentWorkspacesCount'] = $dependentWorkspaces->count(); $workspacesAndCounts[$workspaceName]['workspaceOwnerHumanReadable'] = $workspace->workspaceOwner ? $this->domainUserService->findByUserIdentifier(UserId::fromString($workspace->workspaceOwner))?->getLabel() : null; } } @@ -167,7 +166,7 @@ public function showAction(WorkspaceName $workspace): void new WorkspacesControllerInternalsFactory() ); - $workspaceObj = $contentRepository->getWorkspaceFinder()->findOneByName($workspace); + $workspaceObj = $contentRepository->findWorkspaceByName($workspace); if (is_null($workspaceObj)) { /** @todo add flash message */ $this->redirect('index'); @@ -218,7 +217,7 @@ public function createAction( WorkspaceName::transliterateFromString($title->value)->value . '-' . substr(base_convert(microtime(false), 10, 36), -5, 5) ); - while ($contentRepository->getWorkspaceFinder()->findOneByName($workspaceName) instanceof Workspace) { + while ($contentRepository->findWorkspaceByName($workspaceName) instanceof Workspace) { $workspaceName = WorkspaceName::fromString( WorkspaceName::transliterateFromString($title->value)->value . '-' . substr(base_convert(microtime(false), 10, 36), -5, 5) @@ -262,7 +261,7 @@ public function editAction(WorkspaceName $workspaceName): void ->contentRepositoryId; $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId); - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName($workspaceName); + $workspace = $contentRepository->findWorkspaceByName($workspaceName); if (is_null($workspace)) { // @todo add flash message $this->redirect('index'); @@ -302,7 +301,7 @@ public function updateAction( $title = WorkspaceTitle::fromString($workspaceName->value); } - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName($workspaceName); + $workspace = $contentRepository->findWorkspaceByName($workspaceName); if ($workspace === null) { $this->addFlashMessage( $this->getModuleLabel('workspaces.workspaceDoesNotExist'), @@ -312,25 +311,6 @@ public function updateAction( $this->redirect('index'); } - if (!$workspace->workspaceTitle->equals($title) || !$workspace->workspaceDescription->equals($description)) { - $contentRepository->handle( - RenameWorkspace::create( - $workspaceName, - $title, - $description - ) - ); - } - - if ($workspace->workspaceOwner !== $workspaceOwner) { - $contentRepository->handle( - ChangeWorkspaceOwner::create( - $workspaceName, - $workspaceOwner ?: null, - ) - ); - } - $this->addFlashMessage($this->translator->translateById( 'workspaces.workspaceHasBeenUpdated', [$title->value], @@ -357,7 +337,7 @@ public function deleteAction(WorkspaceName $workspaceName): void ->contentRepositoryId; $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId); - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName($workspaceName); + $workspace = $contentRepository->findWorkspaceByName($workspaceName); if ($workspace === null) { $this->addFlashMessage( $this->getModuleLabel('workspaces.workspaceDoesNotExist'), @@ -371,18 +351,19 @@ public function deleteAction(WorkspaceName $workspaceName): void $this->redirect('index'); } - $dependentWorkspaces = $contentRepository->getWorkspaceFinder() - ->findByBaseWorkspace($workspace->workspaceName); - if (count($dependentWorkspaces) > 0) { - $dependentWorkspaceTitles = []; + $dependentWorkspaces = $contentRepository->getWorkspaces()->filter( + static fn (Workspace $potentiallyDependentWorkspace) => $potentiallyDependentWorkspace->baseWorkspaceName?->equals($workspaceName) ?? false + ); + if (!$dependentWorkspaces->isEmpty()) { + $dependentWorkspaceNames = []; /** @var Workspace $dependentWorkspace */ foreach ($dependentWorkspaces as $dependentWorkspace) { - $dependentWorkspaceTitles[] = $dependentWorkspace->workspaceTitle->value; + $dependentWorkspaceNames[] = $dependentWorkspace->workspaceName->value; } $message = $this->translator->translateById( 'workspaces.workspaceCannotBeDeletedBecauseOfDependencies', - [$workspace->workspaceTitle->value, implode(', ', $dependentWorkspaceTitles)], + [$workspace->workspaceName->value, implode(', ', $dependentWorkspaceNames)], null, null, 'Modules', @@ -458,7 +439,7 @@ public function rebaseAndRedirectAction(Node $targetNode, Workspace $targetWorks } $personalWorkspaceName = WorkspaceNameBuilder::fromAccountIdentifier($currentAccount->getAccountIdentifier()); /** @var Workspace $personalWorkspace */ - $personalWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName($personalWorkspaceName); + $personalWorkspace = $contentRepository->findWorkspaceByName($personalWorkspaceName); /** @todo do something else * if ($personalWorkspace !== $targetWorkspace) { @@ -891,8 +872,8 @@ protected function renderContentChanges( ContentStreamId $contentStreamIdOfOriginalNode, ContentRepository $contentRepository, ): array { - $currentWorkspace = $contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId( - $contentStreamIdOfOriginalNode + $currentWorkspace = $contentRepository->getWorkspaces()->find( + fn (Workspace $potentialWorkspace) => $potentialWorkspace->currentContentStreamId->equals($contentStreamIdOfOriginalNode) ); $originalNode = null; if ($currentWorkspace !== null) { @@ -1074,7 +1055,7 @@ protected function prepareBaseWorkspaceOptions( Workspace $excludedWorkspace = null, ): array { $baseWorkspaceOptions = []; - $workspaces = $contentRepository->getWorkspaceFinder()->findAll(); + $workspaces = $contentRepository->getWorkspaces(); foreach ($workspaces as $workspace) { /** @var Workspace $workspace */ @@ -1116,7 +1097,7 @@ private function getBaseWorkspaceWhenSureItExists( /** @var WorkspaceName $baseWorkspaceName We expect this to exist */ $baseWorkspaceName = $workspace->baseWorkspaceName; /** @var Workspace $baseWorkspace We expect this to exist */ - $baseWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName($baseWorkspaceName); + $baseWorkspace = $contentRepository->findWorkspaceByName($baseWorkspaceName); return $baseWorkspace; } diff --git a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php index 7412d45e57a..80333ce656f 100644 --- a/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php +++ b/Neos.Neos/Classes/Domain/Service/SiteServiceInternals.php @@ -55,7 +55,7 @@ public function removeSiteNode(SiteNodeName $siteNodeName): void ); } - foreach ($this->contentRepository->getWorkspaceFinder()->findAll() as $workspace) { + foreach ($this->contentRepository->getWorkspaces() as $workspace) { $contentGraph = $this->contentRepository->getContentGraph($workspace->workspaceName); $sitesNodeAggregate = $contentGraph->findRootNodeAggregateByType( NodeTypeNameFactory::forSites() diff --git a/Neos.Neos/Classes/Domain/Workspace/Workspace.php b/Neos.Neos/Classes/Domain/Workspace/Workspace.php index 9d3bd125be8..7eef91d0ebd 100644 --- a/Neos.Neos/Classes/Domain/Workspace/Workspace.php +++ b/Neos.Neos/Classes/Domain/Workspace/Workspace.php @@ -444,8 +444,7 @@ private function isChangeWithSelfReferencingRemovalAttachmentPoint(Change $chang private function updateCurrentState(): void { /** The workspace projection should have been marked stale via @see WithMarkStaleInterface in the meantime */ - $contentRepositoryWorkspace = $this->contentRepository->getWorkspaceFinder() - ->findOneByName($this->name); + $contentRepositoryWorkspace = $this->contentRepository->findWorkspaceByName($this->name); if (!$contentRepositoryWorkspace) { throw new WorkspaceDoesNotExist('Cannot update state of non-existent workspace ' . $this->name->value, 1711704397); } diff --git a/Neos.Neos/Classes/Domain/Workspace/WorkspaceProvider.php b/Neos.Neos/Classes/Domain/Workspace/WorkspaceProvider.php index 257a1233410..5d62d9338ff 100644 --- a/Neos.Neos/Classes/Domain/Workspace/WorkspaceProvider.php +++ b/Neos.Neos/Classes/Domain/Workspace/WorkspaceProvider.php @@ -65,7 +65,7 @@ private function requireContentRepositoryWorkspace( ContentRepository $contentRepository, WorkspaceName $workspaceName ): ContentRepositoryWorkspace { - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName($workspaceName); + $workspace = $contentRepository->findWorkspaceByName($workspaceName); if (!$workspace instanceof ContentRepositoryWorkspace) { throw WorkspaceDoesNotExist::butWasSupposedTo($workspaceName); } diff --git a/Neos.Neos/Classes/FrontendRouting/NodeAddressFactory.php b/Neos.Neos/Classes/FrontendRouting/NodeAddressFactory.php index 7d187251677..37e35511605 100644 --- a/Neos.Neos/Classes/FrontendRouting/NodeAddressFactory.php +++ b/Neos.Neos/Classes/FrontendRouting/NodeAddressFactory.php @@ -17,6 +17,7 @@ use Neos\ContentRepository\Core\ContentRepository; use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; @@ -41,8 +42,8 @@ public function createFromContentStreamIdAndDimensionSpacePointAndNodeAggregateI DimensionSpacePoint $dimensionSpacePoint, NodeAggregateId $nodeAggregateId ): NodeAddress { - $workspace = $this->contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId( - $contentStreamId + $workspace = $this->contentRepository->getWorkspaces()->find( + fn (Workspace $potentialWorkspace) => $potentialWorkspace->currentContentStreamId->equals($contentStreamId) ); if ($workspace === null) { throw new \RuntimeException( @@ -79,7 +80,7 @@ public function createFromUriString(string $serializedNodeAddress): NodeAddress $dimensionSpacePoint = DimensionSpacePoint::fromUriRepresentation($dimensionSpacePointSerialized); $nodeAggregateId = NodeAggregateId::fromString($nodeAggregateIdSerialized); - $contentStreamId = $this->contentRepository->getWorkspaceFinder()->findOneByName($workspaceName) + $contentStreamId = $this->contentRepository->findWorkspaceByName($workspaceName) ?->currentContentStreamId; if (is_null($contentStreamId)) { throw new \InvalidArgumentException( diff --git a/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php b/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php index daea26cfeec..db036c145e1 100644 --- a/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php +++ b/Neos.Neos/Classes/Fusion/Cache/ContentCacheFlusher.php @@ -18,6 +18,7 @@ use Neos\ContentRepository\Core\NodeType\NodeType; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\SharedModel\Exception\NodeTypeNotFound; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; @@ -291,7 +292,10 @@ public function registerAssetChange(AssetInterface $asset): void $workspaceName = $workspaceNamesByContentStreamId[$contentRepositoryId][$usage->contentStreamId->value] ?? null; if ($workspaceName === null) { $contentRepository = $this->contentRepositoryRegistry->get(ContentRepositoryId::fromString($contentRepositoryId)); - $workspace = $contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId($usage->contentStreamId); + // TODO fix + $workspace = $contentRepository->getWorkspaces()->find( + fn (Workspace $potentialWorkspace) => $potentialWorkspace->currentContentStreamId->equals($usage->contentStreamId) + ); if ($workspace === null) { continue; } diff --git a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php index c71a2965ca2..f9abb3f6e83 100644 --- a/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php +++ b/Neos.Neos/Classes/Fusion/Cache/GraphProjectorCatchUpHookForCacheFlushing.php @@ -19,6 +19,7 @@ use Neos\ContentRepository\Core\Feature\NodeRemoval\Event\NodeAggregateWasRemoved; use Neos\ContentRepository\Core\Projection\CatchUpHookInterface; use Neos\ContentRepository\Core\Projection\ContentGraph\NodeAggregate; +use Neos\ContentRepository\Core\Projection\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\EventStore\Model\EventEnvelope; @@ -140,7 +141,9 @@ public function onBeforeEvent(EventInterface $eventInstance, EventEnvelope $even // cleared, leading to presumably duplicate nodes in the UI. || $eventInstance instanceof NodeAggregateWasMoved ) { - $workspace = $this->contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId($eventInstance->getContentStreamId()); + $workspace = $this->contentRepository->getWorkspaces()->find( + fn (Workspace $potentialWorkspace) => $potentialWorkspace->currentContentStreamId->equals($eventInstance->getContentStreamId()) + ); if ($workspace === null) { return; } @@ -177,7 +180,9 @@ public function onAfterEvent(EventInterface $eventInstance, EventEnvelope $event !($eventInstance instanceof NodeAggregateWasRemoved) && $eventInstance instanceof EmbedsContentStreamAndNodeAggregateId ) { - $workspace = $this->contentRepository->getWorkspaceFinder()->findOneByCurrentContentStreamId($eventInstance->getContentStreamId()); + $workspace = $this->contentRepository->getWorkspaces()->find( + fn (Workspace $potentialWorkspace) => $potentialWorkspace->currentContentStreamId->equals($eventInstance->getContentStreamId()) + ); if ($workspace === null) { return; } diff --git a/Neos.Neos/Classes/Fusion/Helper/CachingHelper.php b/Neos.Neos/Classes/Fusion/Helper/CachingHelper.php index 5901939576b..9e64658e997 100644 --- a/Neos.Neos/Classes/Fusion/Helper/CachingHelper.php +++ b/Neos.Neos/Classes/Fusion/Helper/CachingHelper.php @@ -137,7 +137,7 @@ public function getWorkspaceChain(?Node $node): array $node->contentRepositoryId ); - $currentWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName( + $currentWorkspace = $contentRepository->findWorkspaceByName( $node->workspaceName ); $workspaceChain = []; @@ -145,7 +145,7 @@ public function getWorkspaceChain(?Node $node): array while ($currentWorkspace !== null) { $workspaceChain[$currentWorkspace->workspaceName->value] = $currentWorkspace; $currentWorkspace = $currentWorkspace->baseWorkspaceName - ? $contentRepository->getWorkspaceFinder()->findOneByName($currentWorkspace->baseWorkspaceName) + ? $contentRepository->findWorkspaceByName($currentWorkspace->baseWorkspaceName) : null; } diff --git a/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php b/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php index f4e18d0a96d..e01ada06c8a 100644 --- a/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php +++ b/Neos.Neos/Classes/Service/EditorContentStreamZookeeper.php @@ -117,12 +117,12 @@ public function relayEditorAuthentication(Authentication\TokenInterface $token): $workspaceName = WorkspaceNameBuilder::fromAccountIdentifier( $token->getAccount()->getAccountIdentifier() ); - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName($workspaceName); + $workspace = $contentRepository->findWorkspaceByName($workspaceName); if ($workspace !== null) { return; } - $baseWorkspace = $contentRepository->getWorkspaceFinder()->findOneByName(WorkspaceName::forLive()); + $baseWorkspace = $contentRepository->findWorkspaceByName(WorkspaceName::forLive()); if (!$baseWorkspace) { return; } diff --git a/Neos.Neos/Classes/Service/LinkingService.php b/Neos.Neos/Classes/Service/LinkingService.php index cd9348a5365..2243fb5baed 100644 --- a/Neos.Neos/Classes/Service/LinkingService.php +++ b/Neos.Neos/Classes/Service/LinkingService.php @@ -307,7 +307,7 @@ public function createNodeUri( )->contentRepositoryId; $contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId); $nodeAddress = NodeAddressFactory::create($contentRepository)->createFromUriString($node); - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName($nodeAddress->workspaceName); + $workspace = $contentRepository->findWorkspaceByName($nodeAddress->workspaceName); $subgraph = $contentRepository->getContentGraph($nodeAddress->workspaceName)->getSubgraph( $nodeAddress->dimensionSpacePoint, $workspace && !$workspace->isPublicWorkspace() @@ -346,7 +346,7 @@ public function createNodeUri( $contentRepository = $this->contentRepositoryRegistry->get( $node->contentRepositoryId ); - $workspace = $contentRepository->getWorkspaceFinder()->findOneByName( + $workspace = $contentRepository->findWorkspaceByName( $node->workspaceName ); $mainRequest = $controllerContext->getRequest()->getMainRequest();