diff --git a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/FeatureContext.php index 3df89de8c1f..73351a97354 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 a3af95d66c0..6735ed24cab 100644 --- a/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php +++ b/Neos.ContentGraph.DoctrineDbalAdapter/Tests/Behavior/Features/Bootstrap/ProjectionIntegrityViolationDetectionTrait.php @@ -313,7 +313,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 19eb183ff16..e0a28f7cdfb 100644 --- a/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php +++ b/Neos.ContentRepository.BehavioralTests/Classes/TestSuite/Behavior/CRBehavioralTestsSubjectProvider.php @@ -18,9 +18,11 @@ 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\SharedModel\ContentRepository\ContentRepositoryId; use Neos\ContentRepository\TestSuite\Behavior\Features\Bootstrap\Helpers\GherkinTableNodeBasedContentDimensionSource; -use Neos\EventStore\EventStoreInterface; /** * Subject provider for behavioral tests @@ -32,6 +34,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 @@ -126,7 +134,7 @@ public function iChangeTheNodeTypesInContentRepositoryTo( } } - protected function setUpContentRepository(ContentRepositoryId $contentRepositoryId): ContentRepository + final protected function setUpContentRepository(ContentRepositoryId $contentRepositoryId): ContentRepository { /** * Reset events and projections @@ -172,11 +180,10 @@ protected function setUpContentRepository(ContentRepositoryId $contentRepository if (!in_array($contentRepository->id, self::$alreadySetUpContentRepositories)) { $contentRepository->setUp(); self::$alreadySetUpContentRepositories[] = $contentRepository->id; + unset($this->contentRepositoryServiceFactoryDependenciesById[$contentRepositoryId->value]); } - /** @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); $contentRepository->resetProjectionStates(); @@ -185,4 +192,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 00000000000..33ac3fb523b --- /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 682bf3c0d66..9d5eb6398a8 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.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php index 366084abb7b..dc2bd3430ae 100644 --- a/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php +++ b/Neos.ContentRepository.BehavioralTests/Tests/Functional/Feature/WorkspacePublication/WorkspaceWritingDuringPublication.php @@ -231,6 +231,7 @@ protected function getObject(string $className): object } 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 e603c12fd04..5a4adcdc955 100644 --- a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php +++ b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/CrImportExportTrait.php @@ -59,6 +59,7 @@ public function setupCrImportExportTrait() public function theEventsAreExportedIExpectTheFollowingJsonl() { $eventExporter = $this->getContentRepositoryService( + $this->currentContentRepository->id, new class ($this->crImportExportTrait_filesystem) implements ContentRepositoryServiceFactoryInterface { public function __construct(private readonly Filesystem $filesystem) { @@ -90,6 +91,7 @@ public function build(ContentRepositoryServiceFactoryDependencies $serviceFactor public function iImportTheFollowingJson(?string $contentStreamId = null) { $eventImporter = $this->getContentRepositoryService( + $this->currentContentRepository->id, new class ($this->crImportExportTrait_filesystem, $contentStreamId ? ContentStreamId::fromString($contentStreamId) : null) implements ContentRepositoryServiceFactoryInterface { public function __construct( private readonly Filesystem $filesystem, diff --git a/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php b/Neos.ContentRepository.Export/Tests/Behavior/Features/Bootstrap/FeatureContext.php index 01310c7beff..8ec14ab425a 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 7ab7f5a37a2..49ba2c397da 100644 --- a/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php +++ b/Neos.ContentRepository.LegacyNodeMigration/Tests/Behavior/Bootstrap/FeatureContext.php @@ -133,7 +133,7 @@ public function build(ContentRepositoryServiceFactoryDependencies $serviceFactor }; } }; - $this->getContentRepositoryService($propertyConverterAccess); + $this->getContentRepositoryService($this->currentContentRepository->id, $propertyConverterAccess); $migration = new NodeDataToEventsProcessor( $nodeTypeManager, @@ -400,6 +400,7 @@ private function parseJsonTable(TableNode $table): array } 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 f0e71b8027e..2fe6ff6240c 100644 --- a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php +++ b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/CRTestSuiteTrait.php @@ -17,9 +17,6 @@ use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Behat\Gherkin\Node\PyStringNode; use Behat\Gherkin\Node\TableNode; -use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryDependencies; -use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceFactoryInterface; -use Neos\ContentRepository\Core\Factory\ContentRepositoryServiceInterface; use Neos\ContentRepository\Core\Feature\NodeModification\Dto\PropertyValuesToWrite; use Neos\ContentRepository\Core\NodeType\NodeTypeName; use Neos\ContentRepository\Core\Projection\CatchUpOptions; @@ -242,7 +239,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); } /** @@ -252,37 +249,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 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() + return $this->getContentRepositoryServiceFactoryDependencies($this->currentContentRepository->id) ->projectionsAndCatchUpHooks ->contentGraphProjection ->getState(); diff --git a/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/MigrationsTrait.php b/Neos.ContentRepository.TestSuite/Classes/Behavior/Features/Bootstrap/MigrationsTrait.php index b02a8e2abed..cf1d0e26f9d 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 5c7970d167e..0f4b3892231 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 9d06ce491eb..3364fd024c8 100644 --- a/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php +++ b/Neos.Neos/Tests/Behavior/Features/Bootstrap/FeatureContext.php @@ -93,6 +93,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 d1b22507e62..86d7fa2818f 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(