diff --git a/Classes/AbstractIndexingJob.php b/Classes/AbstractIndexingJob.php index 33a6cc1..bdf903a 100644 --- a/Classes/AbstractIndexingJob.php +++ b/Classes/AbstractIndexingJob.php @@ -42,18 +42,6 @@ abstract class AbstractIndexingJob implements JobInterface */ protected $nodeDataRepository; - /** - * @var NodeFactory - * @Flow\Inject - */ - protected $nodeFactory; - - /** - * @var ContextFactoryInterface - * @Flow\Inject - */ - protected $contextFactory; - /** * @var FakeNodeDataFactory * @Flow\Inject diff --git a/Classes/Command/NodeIndexQueueCommandController.php b/Classes/Command/NodeIndexQueueCommandController.php index c45155b..c504e54 100644 --- a/Classes/Command/NodeIndexQueueCommandController.php +++ b/Classes/Command/NodeIndexQueueCommandController.php @@ -81,12 +81,6 @@ class NodeIndexQueueCommandController extends CommandController */ protected $nodeDataRepository; - /** - * @var WorkspaceRepository - * @Flow\Inject - */ - protected $workspaceRepository; - /** * @var NodeIndexer * @Flow\Inject @@ -99,11 +93,8 @@ class NodeIndexQueueCommandController extends CommandController */ protected $batchSize; - /** - * @Flow\Inject - * @var \Neos\ContentRepository\Domain\Service\ContentDimensionCombinator - */ - protected $contentDimensionCombinator; + #[\Neos\Flow\Annotations\Inject] + protected \Neos\ContentRepositoryRegistry\ContentRepositoryRegistry $contentRepositoryRegistry; /** * Index all nodes by creating a new index and when everything was completed, switch the index alias. @@ -139,8 +130,12 @@ public function buildCommand(string $workspace = null): void $this->outputLine(); $this->indexWorkspace($workspace, $indexPostfix); } + $contentRepository = $this->contentRepositoryRegistry->get(\Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId::fromString('default')); + $dimensionSpacePoints = $contentRepository->getVariationGraph()->getDimensionSpacePoints(); + // TODO 9.0 migration: try to directly work with $dimensionSpacePoints, instead of converting them to the legacy dimension format - $combinations = new ArrayCollection($this->contentDimensionCombinator->getAllAllowedCombinations()); + + $combinations = new ArrayCollection(array_map(fn(\Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint $dimensionSpacePoint) => $dimensionSpacePoint->toLegacyDimensionArray(), iterator_to_array($dimensionSpacePoints))); $combinations->map(function (array $dimensionValues) use ($indexPostfix) { $updateAliasJob = new UpdateAliasJob($indexPostfix, $dimensionValues); $this->jobManager->queue(self::BATCH_QUEUE_NAME, $updateAliasJob); @@ -319,7 +314,11 @@ protected function indexWorkspace(string $workspaceName, string $indexPostfix): */ protected function updateMapping(string $indexPostfix): void { - $combinations = new ArrayCollection($this->contentDimensionCombinator->getAllAllowedCombinations()); + $contentRepository = $this->contentRepositoryRegistry->get(\Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId::fromString('default')); + $dimensionSpacePoints = $contentRepository->getVariationGraph()->getDimensionSpacePoints(); + // TODO 9.0 migration: try to directly work with $dimensionSpacePoints, instead of converting them to the legacy dimension format + + $combinations = new ArrayCollection(array_map(fn(\Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint $dimensionSpacePoint) => $dimensionSpacePoint->toLegacyDimensionArray(), iterator_to_array($dimensionSpacePoints))); $combinations->map(function (array $dimensionValues) use ($indexPostfix) { $this->nodeIndexer->setDimensions($dimensionValues); $this->nodeIndexer->setIndexNamePostfix($indexPostfix); diff --git a/Classes/Domain/Service/FakeNodeDataFactory.php b/Classes/Domain/Service/FakeNodeDataFactory.php index 2155213..36787a3 100644 --- a/Classes/Domain/Service/FakeNodeDataFactory.php +++ b/Classes/Domain/Service/FakeNodeDataFactory.php @@ -26,23 +26,13 @@ */ class FakeNodeDataFactory { - /** - * @var WorkspaceRepository - * @Flow\Inject - */ - protected $workspaceRepository; - - /** - * @var NodeTypeManager - * @Flow\Inject - */ - protected $nodeTypeManager; - /** * @var PersistenceManager * @Flow\Inject */ protected $persistenceManager; + #[\Neos\Flow\Annotations\Inject] + protected \Neos\ContentRepositoryRegistry\ContentRepositoryRegistry $contentRepositoryRegistry; /** * This creates a "fake" removed NodeData instance from the given payload @@ -73,13 +63,17 @@ public function createFromPayload(array $payload): NodeData $nodeData = new NodeData($payload['path'], $workspace, $payload['identifier'], isset($payload['dimensions']) ? $payload['dimensions'] : null); try { - $nodeData->setNodeType($this->nodeTypeManager->getNodeType($payload['nodeType'])); + // TODO 9.0 migration: Make this code aware of multiple Content Repositories. + $contentRepository = $this->contentRepositoryRegistry->get(\Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId::fromString('default')); + $nodeData->setNodeType($contentRepository->getNodeTypeManager()->getNodeType($payload['nodeType'])); } catch (NodeTypeNotFoundException $e) { throw new Exception('Unable to create fake node data, node type not found', 1509362172); } $nodeData->setProperty('title', 'Fake node'); $nodeData->setProperty('uriPathSegment', 'fake-node'); + // TODO 9.0 migration: !! NodeData::setRemoved is removed in Neos 9.0 - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here. + $nodeData->setRemoved(true); diff --git a/Classes/Indexer/NodeIndexer.php b/Classes/Indexer/NodeIndexer.php index 2434cd2..9210345 100644 --- a/Classes/Indexer/NodeIndexer.php +++ b/Classes/Indexer/NodeIndexer.php @@ -46,14 +46,18 @@ class NodeIndexer extends ContentRepositoryAdaptor\Indexer\NodeIndexer * @Flow\InjectConfiguration(path="enableLiveAsyncIndexing") */ protected $enableLiveAsyncIndexing; + #[\Neos\Flow\Annotations\Inject] + protected \Neos\ContentRepositoryRegistry\ContentRepositoryRegistry $contentRepositoryRegistry; /** - * @param NodeInterface $node + * @param \Neos\ContentRepository\Core\Projection\ContentGraph\Node $node * @param string|null $targetWorkspaceName In case indexing is triggered during publishing, a target workspace name will be passed in * @throws ContentRepositoryAdaptor\Exception */ - public function indexNode(NodeInterface $node, $targetWorkspaceName = null): void + public function indexNode(\Neos\ContentRepository\Core\Projection\ContentGraph\Node $node, $targetWorkspaceName = null): void { + // TODO 9.0 migration: !! Node::isRemoved() - the new CR *never* returns removed nodes; so you can simplify your code and just assume removed == FALSE in all scenarios. + if( $node->isRemoved() ){ $this->removeNode($node, $targetWorkspaceName); return; @@ -69,7 +73,7 @@ public function indexNode(NodeInterface $node, $targetWorkspaceName = null): voi return; } - if ($targetWorkspaceName === null && $node->getContext()->getWorkspaceName() !== 'live') { + if ($targetWorkspaceName === null && $node->workspaceName !== 'live') { return; } } @@ -79,14 +83,14 @@ public function indexNode(NodeInterface $node, $targetWorkspaceName = null): voi } /** - * @param NodeInterface $node + * @param \Neos\ContentRepository\Core\Projection\ContentGraph\Node $node * @param string|null $targetWorkspaceName In case indexing is triggered during publishing, a target workspace name will be passed in * @throws ContentRepositoryAdaptor\Exception * @throws \Flowpack\ElasticSearch\Exception * @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException * @throws \Neos\Utility\Exception\FilesException */ - public function removeNode(NodeInterface $node, string $targetWorkspaceName = null): void + public function removeNode(\Neos\ContentRepository\Core\Projection\ContentGraph\Node $node, string $targetWorkspaceName = null): void { if ($this->enableLiveAsyncIndexing !== true) { parent::removeNode($node, $targetWorkspaceName); @@ -99,12 +103,14 @@ public function removeNode(NodeInterface $node, string $targetWorkspaceName = nu return; } - if ($targetWorkspaceName === null && $node->getContext()->getWorkspaceName() !== 'live') { + if ($targetWorkspaceName === null && $node->workspaceName !== 'live') { return; } } $dimensionCombinations = $this->dimensionService->getDimensionCombinationsForIndexing($node); + // TODO 9.0 migration: !! Node::getWorkspace() does not make sense anymore concept-wise. In Neos < 9, it pointed to the workspace where the node was *at home at*. Now, the closest we have here is the node identity. + $targetWorkspaceName = $targetWorkspaceName ?? $node->getWorkspace()->getName(); if (array_filter($dimensionCombinations) === []) { @@ -113,17 +119,29 @@ public function removeNode(NodeInterface $node, string $targetWorkspaceName = nu } else { foreach ($dimensionCombinations as $combination) { - $nodeFromContext = $this->createContentContext($targetWorkspaceName, $combination)->getNodeByIdentifier($node->getIdentifier()); - if ($nodeFromContext instanceof NodeInterface && !$nodeFromContext->isRemoved()) { + // TODO 9.0 migration: Check if you could change your code to work with the NodeAggregateId value object instead. + + $nodeFromContext = $this->createContentContext($targetWorkspaceName, $combination)->getNodeByIdentifier($node->aggregateId->value); + // TODO 9.0 migration: !! Node::isRemoved() - the new CR *never* returns removed nodes; so you can simplify your code and just assume removed == FALSE in all scenarios. + + if ($nodeFromContext instanceof \Neos\ContentRepository\Core\Projection\ContentGraph\Node && !$nodeFromContext->isRemoved()) { continue; } + // TODO 9.0 migration: !! Node::getWorkspace() does not make sense anymore concept-wise. In Neos < 9, it pointed to the workspace where the node was *at home at*. Now, the closest we have here is the node identity. + + // TODO 9.0 migration: !! Node::getWorkspace() does not make sense anymore concept-wise. In Neos < 9, it pointed to the workspace where the node was *at home at*. Now, the closest we have here is the node identity. + $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); + // TODO 9.0 migration: Try to remove the (string) cast and make your code more type-safe. + + // TODO 9.0 migration: Try to remove the (string) cast and make your code more type-safe. + $fakeNodeArray = [ 'persistenceObjectIdentifier' => 'fake', 'workspace' => $node->getWorkspace()->getName(), - 'path' => $node->getPath(), - 'identifier' => $node->getIdentifier(), - 'nodeType' => $node->getNodeType()->getName(), + 'path' => (string) $subgraph->findNodePath($node->aggregateId), + 'identifier' => $node->aggregateId->value, + 'nodeType' => $node->nodeTypeName->value, 'dimensions' => $combination ]; @@ -136,19 +154,29 @@ public function removeNode(NodeInterface $node, string $targetWorkspaceName = nu /** * Returns an array of data from the node for use as job payload. * - * @param NodeInterface $node + * @param \Neos\ContentRepository\Core\Projection\ContentGraph\Node $node * @return array */ - protected function nodeAsArray(NodeInterface $node): array + protected function nodeAsArray(\Neos\ContentRepository\Core\Projection\ContentGraph\Node $node): array { + // TODO 9.0 migration: !! Node::getNodeData() - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here. + + // TODO 9.0 migration: !! Node::getNodeData() - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here. + + // TODO 9.0 migration: !! Node::getNodeData() - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here. + + // TODO 9.0 migration: !! Node::getNodeData() - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here. + $subgraph = $this->contentRepositoryRegistry->subgraphForNode($node); + // TODO 9.0 migration: Try to remove the (string) cast and make your code more type-safe. + return [ [ 'persistenceObjectIdentifier' => $this->persistenceManager->getIdentifierByObject($node->getNodeData()), - 'identifier' => $node->getIdentifier(), + 'identifier' => $node->aggregateId->value, 'dimensions' => $node->getContext()->getDimensions(), 'workspace' => $node->getWorkspace()->getName(), - 'nodeType' => $node->getNodeType()->getName(), - 'path' => $node->getPath() + 'nodeType' => $node->nodeTypeName->value, + 'path' => (string) $subgraph->findNodePath($node->aggregateId) ] ]; } diff --git a/Classes/IndexingJob.php b/Classes/IndexingJob.php index de02032..9510cdc 100644 --- a/Classes/IndexingJob.php +++ b/Classes/IndexingJob.php @@ -47,8 +47,10 @@ public function execute(QueueInterface $queue, Message $message): bool $this->logger->notice(sprintf('Node data of node %s could not be loaded. Node might be deleted."', $node['identifier']), LogEnvironment::fromMethodName(__METHOD__)); continue; } + // TODO 9.0 migration: !! NodeData::getWorkspace is removed in Neos 9.0 - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here. - $context = $this->contextFactory->create([ + + $context = new \Neos\Rector\ContentRepository90\Legacy\LegacyContextStub([ 'workspaceName' => $this->targetWorkspaceName ?: $nodeData->getWorkspace()->getName(), 'invisibleContentShown' => true, 'inaccessibleContentShown' => false, @@ -57,7 +59,7 @@ public function execute(QueueInterface $queue, Message $message): bool $currentNode = $this->nodeFactory->createFromNodeData($nodeData, $context); // Skip this iteration if the node can not be fetched from the current context - if (!$currentNode instanceof NodeInterface) { + if (!$currentNode instanceof \Neos\ContentRepository\Core\Projection\ContentGraph\Node) { $this->logger->warning(sprintf('Node %s could not be created from node data"', $node['identifier']), LogEnvironment::fromMethodName(__METHOD__)); continue; } diff --git a/Classes/RemovalJob.php b/Classes/RemovalJob.php index 6e60010..fedb8d6 100644 --- a/Classes/RemovalJob.php +++ b/Classes/RemovalJob.php @@ -61,8 +61,10 @@ public function execute(QueueInterface $queue, Message $message): bool continue; } } + // TODO 9.0 migration: !! NodeData::getWorkspace is removed in Neos 9.0 - the new CR is not based around the concept of NodeData anymore. You need to rewrite your code here. - $context = $this->contextFactory->create([ + + $context = new \Neos\Rector\ContentRepository90\Legacy\LegacyContextStub([ 'workspaceName' => $this->targetWorkspaceName ?: $nodeData->getWorkspace()->getName(), 'invisibleContentShown' => true, 'removedContentShown' => true, @@ -72,13 +74,15 @@ public function execute(QueueInterface $queue, Message $message): bool $currentNode = $this->nodeFactory->createFromNodeData($nodeData, $context); // Skip this iteration if the node can not be fetched from the current context - if (!$currentNode instanceof NodeInterface) { + if (!$currentNode instanceof \Neos\ContentRepository\Core\Projection\ContentGraph\Node) { $this->logger->info(sprintf('Node %s could not be processed', $node['identifier']), LogEnvironment::fromMethodName(__METHOD__)); continue; } $this->nodeIndexer->setIndexNamePostfix($this->indexPostfix); - $this->logger->info(sprintf('Removed node %s', $currentNode->getIdentifier()), LogEnvironment::fromMethodName(__METHOD__)); + // TODO 9.0 migration: Check if you could change your code to work with the NodeAggregateId value object instead. + + $this->logger->info(sprintf('Removed node %s', $currentNode->aggregateId->value), LogEnvironment::fromMethodName(__METHOD__)); $this->nodeIndexer->removeNode($currentNode, $this->targetWorkspaceName); } diff --git a/composer.json b/composer.json index 4e6f414..5e548e6 100644 --- a/composer.json +++ b/composer.json @@ -4,9 +4,9 @@ "description": "Neos CMS Elasticsearch indexer based on a job queue", "license": "MIT", "require": { - "neos/flow": "^5.1 || ^6.0 || ^7.0 || ^8.0", + "neos/flow": "^5.1 || ^6.0 || ^7.0 || ^8.0 || ^9.0", "flowpack/jobqueue-common": "^3.0 || dev-master", - "flowpack/elasticsearch-contentrepositoryadaptor": "^7.0 || ^8.0 || dev-master" + "flowpack/elasticsearch-contentrepositoryadaptor": "^7.0 || ^8.0 || ^9.0 || dev-master" }, "autoload": { "psr-4": {