diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php index 6fa805c907..41e2321f8a 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -57,6 +57,7 @@ public function resetContentRepositoryComponents(BeforeScenarioScope $scope): vo } protected function getContentRepositoryService( + ContentRepositoryId $contentRepositoryId, ContentRepositoryServiceFactoryInterface $factory ): ContentRepositoryServiceInterface { return $this->contentRepositoryRegistry->buildService( diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php index 1ccdb4a01a..38cff2e4b1 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php @@ -338,7 +338,10 @@ private function transformPayloadTableToDataset(TableNode $payloadTable): array */ public function iRunIntegrityViolationDetection(): void { - $projectionIntegrityViolationDetectionRunner = $this->getContentRepositoryService(new DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory($this->dbal)); + $projectionIntegrityViolationDetectionRunner = $this->getContentRepositoryService( + $this->currentContentRepository->id, + new DoctrineDbalProjectionIntegrityViolationDetectionRunnerFactory($this->dbal) + ); $this->lastIntegrityViolationDetectionResult = $projectionIntegrityViolationDetectionRunner->run(); } diff --git a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php index 2fb4fe8ac9..6089bf8547 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php @@ -18,13 +18,15 @@ use Behat\Gherkin\Node\TableNode; use Doctrine\DBAL\Connection; use Neos\ContentRepository\Core\ContentRepository; +use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies; +use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface; +use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Service\ContentRepositoryMaintainerFactory; use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\Core\Subscription\Engine\SubscriptionEngine; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\GherkinTableNodeBasedContentDimensionSource; use Neos\ContentRepository\TestSuite\Fakes\FakeContentDimensionSourceFactory; use Neos\ContentRepository\TestSuite\Fakes\FakeNodeTypeManagerFactory; -use Neos\EventStore\EventStoreInterface; use PHPUnit\Framework\Assert; use Symfony\Component\Yaml\Yaml; @@ -38,6 +40,12 @@ trait CRBehavioralTestsSubjectProvider */ protected array $contentRepositories = []; + /** + * @internal {@see getContentRepositoryServiceFactoryDependencies} + * @var array + */ + protected array $contentRepositoryServiceFactoryDependenciesById = []; + /** * A runtime cache of all content repositories already set up, represented by their ID * @var array @@ -138,7 +146,7 @@ public function iChangeTheNodeTypesInContentRepositoryTo( } } - protected function setUpContentRepository(ContentRepositoryId $contentRepositoryId): ContentRepository + final protected function setUpContentRepository(ContentRepositoryId $contentRepositoryId): ContentRepository { /** * Reset events and projections @@ -186,12 +194,10 @@ protected function setUpContentRepository(ContentRepositoryId $contentRepository $result = $contentRepositoryMaintainer->setUp(); Assert::assertNull($result); self::$alreadySetUpContentRepositories[] = $contentRepository->id; + unset($this->contentRepositoryServiceFactoryDependenciesById[$contentRepositoryId->value]); } // todo we TRUNCATE here and do not want to use $contentRepositoryMaintainer->prune(); here as it would not reset the autoincrement sequence number making some assertions impossible - /** @var EventStoreInterface $eventStore */ - $eventStore = (new \ReflectionClass($contentRepository))->getProperty('eventStore')->getValue($contentRepository); - /** @var Connection $databaseConnection */ - $databaseConnection = (new \ReflectionClass($eventStore))->getProperty('connection')->getValue($eventStore); + $databaseConnection = $this->getObject(Connection::class); $eventTableName = sprintf('cr_%s_events', $contentRepositoryId->value); $databaseConnection->executeStatement('TRUNCATE ' . $eventTableName); @@ -206,4 +212,26 @@ protected function setUpContentRepository(ContentRepositoryId $contentRepository } abstract protected function createContentRepository(ContentRepositoryId $contentRepositoryId): ContentRepository; + + /** + * Access content repository services. + * + * @template T of ContentRepositoryServiceInterface + * @param ContentRepositoryServiceFactoryInterface $contentRepositoryServiceFactory + * @return T + */ + abstract protected function getContentRepositoryService( + ContentRepositoryId $contentRepositoryId, + ContentRepositoryServiceFactoryInterface $factory + ): ContentRepositoryServiceInterface; + + final protected function getContentRepositoryServiceFactoryDependencies(ContentRepositoryId $contentRepositoryId): ContentRepositoryServiceFactoryDependencies + { + if (!isset($this->contentRepositoryServiceFactoryDependenciesById[$contentRepositoryId->value])) { + $accessor = new ContentRepositoryInternalsAccessor(); + $this->getContentRepositoryService($contentRepositoryId, $accessor); + $this->contentRepositoryServiceFactoryDependenciesById[$contentRepositoryId->value] = $accessor->spiedInternals; + } + return $this->contentRepositoryServiceFactoryDependenciesById[$contentRepositoryId->value]; + } } diff --git a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/ContentRepositoryInternalsAccessor.php b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/ContentRepositoryInternalsAccessor.php new file mode 100644 index 0000000000..33ac3fb523 --- /dev/null +++ b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/ContentRepositoryInternalsAccessor.php @@ -0,0 +1,21 @@ +spiedInternals = $serviceFactoryDependencies; + return new class implements ContentRepositoryServiceInterface + { + }; + } +}; diff --git a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php index 9646198d20..dd5a236dfd 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.BehavioralTests/Tests/Behavior/Bootstrap/FeatureContext.php @@ -111,6 +111,7 @@ public function resetContentRepositoryComponents(BeforeScenarioScope $scope): vo } protected function getContentRepositoryService( + ContentRepositoryId $contentRepositoryId, ContentRepositoryServiceFactoryInterface $factory ): ContentRepositoryServiceInterface { return $this->contentRepositoryRegistry->buildService( diff --git a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php index 996c451bde..e085b848f0 100644 --- a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php +++ b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php @@ -93,7 +93,8 @@ private function runCrImportExportProcessors(ProcessorInterface ...$processors): */ public function theEventsAreExported(): void { - $eventExporter = $this->getContentRepositoryService(new EventExportProcessorFactory($this->currentContentRepository->findWorkspaceByName(WorkspaceName::forLive())->currentContentStreamId)); + $eventExporter = $this->getContentRepositoryService($this->currentContentRepository->id, + new EventExportProcessorFactory($this->currentContentRepository->findWorkspaceByName(WorkspaceName::forLive())->currentContentStreamId)); assert($eventExporter instanceof EventExportProcessor); $this->runCrImportExportProcessors($eventExporter); } diff --git a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php index 15543eef06..c7863fc039 100644 --- a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -57,6 +57,7 @@ public function resetContentRepositoryComponents(BeforeScenarioScope $scope): vo } protected function getContentRepositoryService( + ContentRepositoryId $contentRepositoryId, ContentRepositoryServiceFactoryInterface $factory ): ContentRepositoryServiceInterface { return $this->contentRepositoryRegistry->buildService( diff --git a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php index fa8c3b68f4..6a8de5f0ff 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php @@ -115,7 +115,7 @@ public function build(ContentRepositoryServiceFactoryDependencies $serviceFactor }; } }; - $this->getContentRepositoryService($crInternalsAccess); + $this->getContentRepositoryService($this->currentContentRepository->id, $crInternalsAccess); $eventExportProcessor = new EventExportProcessor( $nodeTypeManager, @@ -255,6 +255,7 @@ public function iRunTheSiteMigration(): void /** ---------------------------------- */ protected function getContentRepositoryService( + ContentRepositoryId $contentRepositoryId, ContentRepositoryServiceFactoryInterface $factory ): ContentRepositoryServiceInterface { return $this->contentRepositoryRegistry->buildService( diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php index 0bde052fc7..f89dbf002a 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php @@ -217,7 +217,7 @@ protected function getRootNodeAggregateId(): ?NodeAggregateId */ public function iPruneRemovedContentStreamsFromTheEventStream(): void { - $this->getContentRepositoryService(new ContentStreamPrunerFactory())->pruneRemovedFromEventStream(fn () => null); + $this->getContentRepositoryService($this->currentContentRepository->id, new ContentStreamPrunerFactory())->pruneRemovedFromEventStream(fn () => null); } /** @@ -227,20 +227,15 @@ public function iExpectTheContentStreamStatus(PyStringNode $pyStringNode): void { // todo a little dirty to compare the cli output here :D $lines = []; - $this->getContentRepositoryService(new ContentStreamPrunerFactory())->outputStatus(function ($line = '') use (&$lines) { + $this->getContentRepositoryService($this->currentContentRepository->id, new ContentStreamPrunerFactory())->outputStatus(function ($line = '') use (&$lines) { $lines[] = $line; }); Assert::assertSame($pyStringNode->getRaw(), join("\n", $lines)); } - - abstract protected function getContentRepositoryService( - ContentRepositoryServiceFactoryInterface $factory - ): ContentRepositoryServiceInterface; - final protected function getContentGraphReadModel(): ContentGraphReadModelInterface { - return $this->getContentRepositoryService(new class implements ContentRepositoryServiceFactoryInterface { + return $this->getContentRepositoryService($this->currentContentRepository->id, new class implements ContentRepositoryServiceFactoryInterface { public function build(ContentRepositoryServiceFactoryDependencies $serviceFactoryDependencies): ContentRepositoryServiceInterface { $contentGraphReadModel = $serviceFactoryDependencies->contentGraphReadModel; diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/MigrationsTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/MigrationsTrait.php index b02a8e2abe..cf1d0e26f9 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/MigrationsTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/MigrationsTrait.php @@ -44,8 +44,7 @@ public function iRunTheFollowingNodeMigrationWithTargetWorkspace(string $sourceW ContentStreamId::fromString($contentStreamId) ); - /** @var NodeMigrationService $nodeMigrationService */ - $nodeMigrationService = $this->getContentRepositoryService(new NodeMigrationServiceFactory()); + $nodeMigrationService = $this->getContentRepositoryService($this->currentContentRepository->id, new NodeMigrationServiceFactory()); $nodeMigrationService->executeMigration($command); } diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/StructureAdjustmentsTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/StructureAdjustmentsTrait.php index 5c7970d167..0f4b389223 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/StructureAdjustmentsTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/StructureAdjustmentsTrait.php @@ -35,8 +35,7 @@ trait StructureAdjustmentsTrait */ public function iAdjustTheNodeStructureForNodeType(string $nodeTypeName): void { - /** @var StructureAdjustmentService $structureAdjustmentService */ - $structureAdjustmentService = $this->getContentRepositoryService(new StructureAdjustmentServiceFactory()); + $structureAdjustmentService = $this->getContentRepositoryService($this->currentContentRepository->id, new StructureAdjustmentServiceFactory()); $errors = $structureAdjustmentService->findAdjustmentsForNodeType(NodeTypeName::fromString($nodeTypeName)); foreach ($errors as $error) { $structureAdjustmentService->fixError($error); @@ -49,8 +48,7 @@ public function iAdjustTheNodeStructureForNodeType(string $nodeTypeName): void */ public function iExpectNoStructureAdjustmentsForType(string $nodeTypeName): void { - /** @var StructureAdjustmentService $structureAdjustmentService */ - $structureAdjustmentService = $this->getContentRepositoryService(new StructureAdjustmentServiceFactory()); + $structureAdjustmentService = $this->getContentRepositoryService($this->currentContentRepository->id, new StructureAdjustmentServiceFactory()); $errors = $structureAdjustmentService->findAdjustmentsForNodeType(NodeTypeName::fromString($nodeTypeName)); $errors = iterator_to_array($errors); Assert::assertEmpty($errors, implode(', ', array_map(fn (StructureAdjustment $adjustment) => $adjustment->render(), $errors))); @@ -62,8 +60,7 @@ public function iExpectNoStructureAdjustmentsForType(string $nodeTypeName): void */ public function iExpectTheFollowingStructureAdjustmentsForType(string $nodeTypeName, TableNode $expectedAdjustments): void { - /** @var StructureAdjustmentService $structureAdjustmentService */ - $structureAdjustmentService = $this->getContentRepositoryService(new StructureAdjustmentServiceFactory()); + $structureAdjustmentService = $this->getContentRepositoryService($this->currentContentRepository->id, new StructureAdjustmentServiceFactory()); $actualAdjustments = $structureAdjustmentService->findAdjustmentsForNodeType(NodeTypeName::fromString($nodeTypeName)); $actualAdjustments = iterator_to_array($actualAdjustments); diff --git a/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php index 77d5fba610..735abcfc53 100644 --- a/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -98,6 +98,7 @@ public function resetPersistenceManagerAndFeedbackCollection() } protected function getContentRepositoryService( + ContentRepositoryId $contentRepositoryId, ContentRepositoryServiceFactoryInterface $factory ): ContentRepositoryServiceInterface { return $this->contentRepositoryRegistry->buildService( diff --git a/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php b/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php index 2656730cb9..f8e421f755 100644 --- a/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.TimeableNodeVisibility/Tests/Behavior/Bootstrap/FeatureContext.php @@ -78,6 +78,7 @@ public function iExpectThisNodeToBeDisabled(): void } protected function getContentRepositoryService( + ContentRepositoryId $contentRepositoryId, ContentRepositoryServiceFactoryInterface $factory ): ContentRepositoryServiceInterface { return $this->contentRepositoryRegistry->buildService(