Skip to content

TASK: Neos 9 Compatibility #60

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions Classes/AbstractIndexingJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 12 additions & 13 deletions Classes/Command/NodeIndexQueueCommandController.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@ class NodeIndexQueueCommandController extends CommandController
*/
protected $nodeDataRepository;

/**
* @var WorkspaceRepository
* @Flow\Inject
*/
protected $workspaceRepository;

/**
* @var NodeIndexer
* @Flow\Inject
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 7 additions & 13 deletions Classes/Domain/Service/FakeNodeDataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down
60 changes: 44 additions & 16 deletions Classes/Indexer/NodeIndexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
}
Expand All @@ -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);
Expand All @@ -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) === []) {
Expand All @@ -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
];

Expand All @@ -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)
]
];
}
Expand Down
6 changes: 4 additions & 2 deletions Classes/IndexingJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}
Expand Down
10 changes: 7 additions & 3 deletions Classes/RemovalJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down