diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphReadModelAdapter.php b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphReadModelAdapter.php index 7e5e2051a5f..8a0f6de9359 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphReadModelAdapter.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/src/ContentGraphReadModelAdapter.php @@ -25,7 +25,6 @@ use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStream; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; -use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreams; use Neos\ContentRepository\Core\SharedModel\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepository\Core\SharedModel\Workspace\Workspaces; @@ -123,22 +122,6 @@ public function findContentStreamById(ContentStreamId $contentStreamId): ?Conten return self::contentStreamFromDatabaseRow($row); } - public function findContentStreams(): ContentStreams - { - $contentStreamsStatement = <<tableNames->contentStream()} - SQL; - try { - $rows = $this->dbal->fetchAllAssociative($contentStreamsStatement); - } catch (Exception $e) { - throw new \RuntimeException(sprintf('Failed to load content streams from database: %s', $e->getMessage()), 1716903042, $e); - } - return ContentStreams::fromArray(array_map(self::contentStreamFromDatabaseRow(...), $rows)); - } - public function countNodes(): int { $countNodesStatement = <<contentGraphReadModel->findWorkspaces(); } - public function findContentStreamById(ContentStreamId $contentStreamId): ?ContentStream - { - return $this->contentGraphReadModel->findContentStreamById($contentStreamId); - } - - public function findContentStreams(): ContentStreams - { - return $this->contentGraphReadModel->findContentStreams(); - } - public function getNodeTypeManager(): NodeTypeManager { return $this->nodeTypeManager; diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php index 5f157f8d708..58833404882 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/ContentGraphReadModelInterface.php @@ -18,7 +18,6 @@ use Neos\ContentRepository\Core\SharedModel\Exception\WorkspaceDoesNotExist; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStream; use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId; -use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreams; use Neos\ContentRepository\Core\SharedModel\Workspace\Workspace; use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName; use Neos\ContentRepository\Core\SharedModel\Workspace\Workspaces; @@ -42,10 +41,11 @@ public function findWorkspaceByName(WorkspaceName $workspaceName): ?Workspace; public function findWorkspaces(): Workspaces; + /** + * @internal only used for constraint checks and in testcases, the public API must only use workspaces {@see findWorkspaceByName}. + */ public function findContentStreamById(ContentStreamId $contentStreamId): ?ContentStream; - public function findContentStreams(): ContentStreams; - /** * Provides the total number of projected nodes regardless of workspace or content stream. * diff --git a/Neos.ContentRepository.Core/Classes/SharedModel/Workspace/ContentStream.php b/Neos.ContentRepository.Core/Classes/SharedModel/Workspace/ContentStream.php index c52109de269..3de05a5103d 100644 --- a/Neos.ContentRepository.Core/Classes/SharedModel/Workspace/ContentStream.php +++ b/Neos.ContentRepository.Core/Classes/SharedModel/Workspace/ContentStream.php @@ -19,7 +19,7 @@ /** * Content Stream Read Model * - * @api Note: The constructor is not part of the public API + * @internal the public API is limited to the {@see Workspace} read model */ final readonly class ContentStream { @@ -31,9 +31,6 @@ private function __construct( ) { } - /** - * @internal - */ public static function create( ContentStreamId $id, ?ContentStreamId $sourceContentStreamId, diff --git a/Neos.ContentRepository.Core/Classes/SharedModel/Workspace/ContentStreams.php b/Neos.ContentRepository.Core/Classes/SharedModel/Workspace/ContentStreams.php deleted file mode 100644 index 75fea156bd8..00000000000 --- a/Neos.ContentRepository.Core/Classes/SharedModel/Workspace/ContentStreams.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * @api - */ -final class ContentStreams implements \IteratorAggregate, \Countable -{ - /** - * @var array - */ - private array $contentStreams; - - /** - * @param iterable $collection - */ - private function __construct(iterable $collection) - { - $contentStreams = []; - foreach ($collection as $item) { - if (!$item instanceof ContentStream) { - throw new \InvalidArgumentException(sprintf('ContentStreams must only consist of %s objects, got: %s', ContentStream::class, get_debug_type($item)), 1716900709); - } - $contentStreams[$item->id->value] = $item; - } - - $this->contentStreams = $contentStreams; - } - - /** - * @param array $contentStreams - */ - public static function fromArray(array $contentStreams): self - { - return new self($contentStreams); - } - - public static function createEmpty(): self - { - return new self([]); - } - - public function getIterator(): \Traversable - { - yield from array_values($this->contentStreams); - } - - /** - * @param \Closure(ContentStream): bool $callback - */ - public function filter(\Closure $callback): self - { - return new self(array_filter($this->contentStreams, $callback)); - } - - /** - * @param \Closure(ContentStream): bool $callback - */ - public function find(\Closure $callback): ?ContentStream - { - foreach ($this->contentStreams as $contentStream) { - if ($callback($contentStream)) { - return $contentStream; - } - } - return null; - } - - public function count(): int - { - return count($this->contentStreams); - } - - public function isEmpty(): bool - { - return $this->contentStreams === []; - } -} diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php index e15be252379..d64808594b1 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php @@ -108,7 +108,7 @@ protected function readPayloadTable(TableNode $payloadTable): array */ public function iExpectTheContentStreamToExist(string $rawContentStreamId): void { - $contentStream = $this->currentContentRepository->findContentStreamById(ContentStreamId::fromString($rawContentStreamId)); + $contentStream = $this->getContentGraphReadModel()->findContentStreamById(ContentStreamId::fromString($rawContentStreamId)); Assert::assertNotNull($contentStream, sprintf('Content stream "%s" was expected to exist, but it does not', $rawContentStreamId)); } @@ -117,7 +117,7 @@ public function iExpectTheContentStreamToExist(string $rawContentStreamId): void */ public function iExpectTheContentStreamToNotExist(string $rawContentStreamId, string $not = ''): void { - $contentStream = $this->currentContentRepository->findContentStreamById(ContentStreamId::fromString($rawContentStreamId)); + $contentStream = $this->getContentGraphReadModel()->findContentStreamById(ContentStreamId::fromString($rawContentStreamId)); Assert::assertNull($contentStream, sprintf('Content stream "%s" was not expected to exist, but it does', $rawContentStreamId)); } @@ -142,20 +142,7 @@ public function workspaceStatusMatchesExpected(string $rawWorkspaceNames, string */ public function iExpectTheGraphProjectionToConsistOfExactlyNodes(int $expectedNumberOfNodes): void { - // HACK to access - $contentGraphReadModelAccess = new class implements ContentRepositoryServiceFactoryInterface { - public ContentGraphReadModelInterface|null $instance; - public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): ContentRepositoryServiceInterface - { - $this->instance = $serviceFactoryDependencies->projectionsAndCatchUpHooks->contentGraphProjection->getState(); - return new class implements ContentRepositoryServiceInterface - { - }; - } - }; - $this->getContentRepositoryService($contentGraphReadModelAccess); - - $actualNumberOfNodes = $contentGraphReadModelAccess->instance->countNodes(); + $actualNumberOfNodes = $this->getContentGraphReadModel()->countNodes(); Assert::assertSame($expectedNumberOfNodes, $actualNumberOfNodes, 'Content graph consists of ' . $actualNumberOfNodes . ' nodes, expected were ' . $expectedNumberOfNodes . '.'); } @@ -252,6 +239,31 @@ abstract protected function getContentRepositoryService( ContentRepositoryServiceFactoryInterface $factory ): ContentRepositoryServiceInterface; + final protected function getContentRepositoryServiceFactoryDependencies(): ContentRepositoryServiceFactoryDependencies + { + $accessorFactory = new class implements ContentRepositoryServiceFactoryInterface { + public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): ContentRepositoryServiceInterface + { + return new class ($serviceFactoryDependencies) implements ContentRepositoryServiceInterface + { + public function __construct( + public readonly ContentRepositoryServiceFactoryDependencies $dependencies + ) { + } + }; + } + }; + return $this->getContentRepositoryService($accessorFactory)->dependencies; + } + + final protected function getContentGraphReadModel(): ContentGraphReadModelInterface + { + return $this->getContentRepositoryServiceFactoryDependencies() + ->projectionsAndCatchUpHooks + ->contentGraphProjection + ->getState(); + } + /** * @When I replay the :projectionName projection */