Skip to content

Commit ce4f262

Browse files
Merge pull request #414 from dlubitz/neos-9
!!! FEATURE: Neos 9.0 compatibility
2 parents 6ce6aa9 + 2f9c6de commit ce4f262

37 files changed

+586
-873
lines changed

Classes/Command/NodeIndexCommandController.php

Lines changed: 118 additions & 150 deletions
Large diffs are not rendered by default.

Classes/Command/NodeIndexMappingCommandController.php

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,12 @@
1616
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Driver\NodeTypeMappingBuilderInterface;
1717
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception;
1818
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Indexer\NodeIndexer;
19-
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\DimensionsService;
2019
use Flowpack\ElasticSearch\Domain\Model\Mapping;
21-
use Neos\ContentRepository\Domain\Service\ContentDimensionCombinator;
20+
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
21+
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
2222
use Neos\Flow\Annotations as Flow;
2323
use Neos\Flow\Cli\CommandController;
2424
use Symfony\Component\Yaml\Yaml;
25-
use function json_encode;
2625

2726
/**
2827
* Provides CLI features for checking mapping informations
@@ -37,40 +36,34 @@ class NodeIndexMappingCommandController extends CommandController
3736
*/
3837
protected $nodeIndexer;
3938

40-
/**
41-
* @Flow\Inject
42-
* @var DimensionsService
43-
*/
44-
protected $dimensionsService;
45-
46-
/**
47-
* @var ContentDimensionCombinator
48-
* @Flow\Inject
49-
*/
50-
protected $contentDimensionCombinator;
51-
5239
/**
5340
* @Flow\Inject
5441
* @var NodeTypeMappingBuilderInterface
5542
*/
5643
protected $nodeTypeMappingBuilder;
5744

45+
#[Flow\Inject()]
46+
protected ContentRepositoryRegistry $contentRepositoryRegistry;
47+
5848
/**
5949
* Shows the mapping between dimensions presets and index name
6050
*
6151
* @throws Exception
6252
*/
63-
public function indicesCommand(): void
53+
public function indicesCommand(string $contentRepository = 'default'): void
6454
{
6555
$indexName = $this->nodeIndexer->getIndexName();
6656

6757
$headers = ['Dimension Preset', 'Index Name'];
6858
$rows = [];
6959

70-
foreach ($this->contentDimensionCombinator->getAllAllowedCombinations() as $dimensionValues) {
60+
$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
61+
$variationGraph = $this->contentRepositoryRegistry->get($contentRepositoryId)->getVariationGraph();
62+
63+
foreach ($variationGraph->getDimensionSpacePoints() as $dimensionSpacePoint) {
7164
$rows[] = [
72-
json_encode($dimensionValues),
73-
sprintf('%s-%s', $indexName, $this->dimensionsService->hash($dimensionValues))
65+
$dimensionSpacePoint->toJson(),
66+
sprintf('%s-%s', $indexName, $dimensionSpacePoint->hash)
7467
];
7568
}
7669

@@ -83,10 +76,11 @@ public function indicesCommand(): void
8376
* @return void
8477
* @throws \Flowpack\ElasticSearch\Exception
8578
*/
86-
public function mappingCommand(): void
79+
public function mappingCommand(string $contentRepository = 'default'): void
8780
{
81+
$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
8882
try {
89-
$nodeTypeMappingCollection = $this->nodeTypeMappingBuilder->buildMappingInformation($this->nodeIndexer->getIndex());
83+
$nodeTypeMappingCollection = $this->nodeTypeMappingBuilder->buildMappingInformation($contentRepositoryId, $this->nodeIndexer->getIndex());
9084
} catch (Exception $e) {
9185
$this->outputLine('Unable to get the current index');
9286
$this->sendAndExit(1);

Classes/Command/NodeTypeCommandController.php

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
*/
1515

1616
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Service\NodeTypeIndexingConfiguration;
17-
use Neos\ContentRepository\Domain\Model\NodeType;
18-
use Neos\ContentRepository\Domain\Service\NodeTypeManager;
19-
use Neos\ContentRepository\Exception\NodeTypeNotFoundException;
17+
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
18+
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
19+
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
2020
use Neos\Flow\Annotations as Flow;
2121
use Neos\Flow\Cli\CommandController;
2222
use Symfony\Component\Yaml\Yaml;
@@ -30,35 +30,33 @@
3030
*/
3131
class NodeTypeCommandController extends CommandController
3232
{
33-
/**
34-
* @Flow\Inject
35-
* @var NodeTypeManager
36-
*/
37-
protected $nodeTypeManager;
38-
3933
/**
4034
* @Flow\Inject
4135
* @var NodeTypeIndexingConfiguration
4236
*/
4337
protected $nodeTypeIndexingConfiguration;
4438

39+
#[Flow\Inject]
40+
protected ContentRepositoryRegistry $contentRepositoryRegistry;
41+
4542
/**
4643
* Show node type configuration after applying all supertypes etc
4744
*
4845
* @param string $nodeType the node type to optionally filter for
4946
* @return void
50-
* @throws NodeTypeNotFoundException
5147
*/
52-
public function showCommand(string $nodeType = null): void
48+
public function showCommand(string $contentRepository = 'default', ?string $nodeType = null): void
5349
{
50+
$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
51+
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);
52+
$nodeTypeManager = $contentRepository->getNodeTypeManager();
53+
5454
if ($nodeType !== null) {
55-
/** @var NodeType $nodeType */
56-
$nodeType = $this->nodeTypeManager->getNodeType($nodeType);
55+
$nodeType = $nodeTypeManager->getNodeType(NodeTypeName::fromString($nodeType));
5756
$configuration = $nodeType->getFullConfiguration();
5857
} else {
59-
$nodeTypes = $this->nodeTypeManager->getNodeTypes();
58+
$nodeTypes = $nodeTypeManager->getNodeTypes();
6059
$configuration = [];
61-
/** @var NodeType $nodeType */
6260
foreach ($nodeTypes as $nodeTypeName => $nodeType) {
6361
$configuration[$nodeTypeName] = $nodeType->getFullConfiguration();
6462
}
@@ -71,9 +69,11 @@ public function showCommand(string $nodeType = null): void
7169
*
7270
* @throws \Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception
7371
*/
74-
public function showIndexableConfigurationCommand(): void
72+
public function showIndexableConfigurationCommand(string $contentRepository = 'default'): void
7573
{
76-
$indexableConfiguration = $this->nodeTypeIndexingConfiguration->getIndexableConfiguration();
74+
$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
75+
76+
$indexableConfiguration = $this->nodeTypeIndexingConfiguration->getIndexableConfiguration($contentRepositoryId);
7777
$indexTable = [];
7878
foreach ($indexableConfiguration as $nodeTypeName => $value) {
7979
$indexTable[] = [$nodeTypeName, $value ? '<success>true</success>' : '<error>false</error>'];

Classes/Command/SearchCommandController.php

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,48 +19,69 @@
1919
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\ElasticSearchClient;
2020
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception;
2121
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception\QueryBuildingException;
22-
use Neos\ContentRepository\Domain\Model\NodeInterface;
23-
use Neos\ContentRepository\Domain\Service\Context;
24-
use Neos\ContentRepository\Domain\Service\ContextFactoryInterface;
22+
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
23+
use Neos\ContentRepository\Core\Projection\ContentGraph\Node;
24+
use Neos\ContentRepository\Core\Projection\ContentGraph\VisibilityConstraints;
25+
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
26+
use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId;
27+
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
28+
use Neos\ContentRepositoryRegistry\ContentRepositoryRegistry;
2529
use Neos\Flow\Annotations as Flow;
2630
use Neos\Flow\Cli\CommandController;
2731
use Neos\Flow\Persistence\Exception\IllegalObjectTypeException;
2832
use Neos\Media\Domain\Model\ResourceBasedInterface;
33+
use Neos\Neos\Domain\NodeLabel\NodeLabelGeneratorInterface;
34+
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
2935
use Neos\Utility\Arrays;
3036

3137
/**
3238
* @Flow\Scope("singleton")
3339
*/
3440
class SearchCommandController extends CommandController
3541
{
36-
/**
37-
* @var ContextFactoryInterface
38-
* @Flow\Inject
39-
*/
40-
protected $contextFactory;
41-
4242
/**
4343
* @Flow\Inject
4444
* @var ElasticSearchClient
4545
*/
4646
protected $elasticSearchClient;
4747

48+
#[Flow\Inject]
49+
protected ContentRepositoryRegistry $contentRepositoryRegistry;
50+
51+
#[Flow\Inject]
52+
protected NodeLabelGeneratorInterface $nodeLabelGenerator;
53+
4854
/**
4955
* This commnd can be used to test and debug
5056
* full-text searches
5157
*
5258
* @param string $searchWord The search word to seartch for.
59+
* @param string $contentRepository
5360
* @param string $path Path to the root node. Defaults to '/'
5461
* @param string|null $dimensions The dimesnions to be taken into account.
5562
* @throws Exception
5663
* @throws QueryBuildingException
5764
* @throws IllegalObjectTypeException
5865
* @throws Exception\ConfigurationException
5966
*/
60-
public function fulltextCommand(string $searchWord, string $path = '/', ?string $dimensions = null): void
67+
public function fulltextCommand(string $searchWord, $contentRepository = 'default', ?string $nodeAggregateId = null, ?string $dimensions = null): void
6168
{
62-
$context = $this->createContext($dimensions);
63-
$contextNode = $context->getNode($path);
69+
if ($dimensions !== null && is_array(json_decode($dimensions, true)) === false) {
70+
$this->outputLine('<error>Error: </error>The Dimensions must be given as a JSON array like \'{"language":["de"]}\'');
71+
$this->sendAndExit(1);
72+
}
73+
74+
$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
75+
$dimensionSpacePoint = $dimensions ? DimensionSpacePoint::fromJsonString($dimensions) : DimensionSpacePoint::createWithoutDimensions();
76+
77+
$contentGraph = $this->contentRepositoryRegistry->get($contentRepositoryId)->getContentGraph(WorkspaceName::forLive());
78+
$subgraph = $contentGraph->getSubgraph($dimensionSpacePoint, VisibilityConstraints::withoutRestrictions());
79+
80+
if ($nodeAggregateId !== null) {
81+
$contextNode = $subgraph->findNodeById(NodeAggregateId::fromString($nodeAggregateId));
82+
} else {
83+
$contextNode = $subgraph->findRootNodeByType(NodeTypeNameFactory::forSites());
84+
}
6485

6586
if ($contextNode === null) {
6687
$this->outputLine('Context node not found');
@@ -94,25 +115,37 @@ public function fulltextCommand(string $searchWord, string $path = '/', ?string
94115
* Prints the index content of the given node identifier.
95116
*
96117
* @param string $identifier The node identifier
97-
* @param string|null $dimensions Dimensions, specified in JSON format, like '{"language":["de"]}'
118+
* @param string $contentRepository
119+
* @param string|null $dimensions Dimensions, specified in JSON format, like '{"language":"en"}'
98120
* @param string $field Name or path to a source field to display. Eg. "__fulltext.h1"
99121
* @throws Exception
100122
* @throws IllegalObjectTypeException
101123
* @throws QueryBuildingException
102124
* @throws \Flowpack\ElasticSearch\Exception
103125
* @throws \Neos\Flow\Http\Exception
104126
*/
105-
public function viewNodeCommand(string $identifier, ?string $dimensions = null, string $field = ''): void
127+
public function viewNodeCommand(string $identifier, string $contentRepository = 'default', ?string $dimensions = null, string $field = ''): void
106128
{
107-
if ($dimensions !== null && is_array(json_decode($dimensions, true, 512, JSON_THROW_ON_ERROR)) === false) {
129+
if ($dimensions !== null && is_array(json_decode($dimensions, true)) === false) {
108130
$this->outputLine('<error>Error: </error>The Dimensions must be given as a JSON array like \'{"language":["de"]}\'');
109131
$this->sendAndExit(1);
110132
}
111133

112-
$context = $this->createContext($dimensions);
134+
$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);
135+
$dimensionSpacePoint = $dimensions ? DimensionSpacePoint::fromJsonString($dimensions) : DimensionSpacePoint::createWithoutDimensions();
136+
137+
$contentGraph = $this->contentRepositoryRegistry->get($contentRepositoryId)->getContentGraph(WorkspaceName::forLive());
138+
$subgraph = $contentGraph->getSubgraph($dimensionSpacePoint, VisibilityConstraints::withoutRestrictions());
139+
140+
$rootNode = $subgraph->findRootNodeByType(NodeTypeNameFactory::forSites());
141+
142+
if ($rootNode === null) {
143+
$this->outputLine('<error>Error: </error>No root node found for the given dimensions');
144+
return;
145+
}
113146

114147
$queryBuilder = new ElasticSearchQueryBuilder();
115-
$queryBuilder->query($context->getRootNode());
148+
$queryBuilder->query($rootNode);
116149
$queryBuilder->exactMatch('neos_node_identifier', $identifier);
117150

118151
$queryBuilder->getRequest()->setValueByPath('_source', []);
@@ -122,7 +155,7 @@ public function viewNodeCommand(string $identifier, ?string $dimensions = null,
122155
$this->outputLine('<info>Results</info>');
123156

124157
foreach ($queryBuilder->execute() as $node) {
125-
$this->outputLine('<b>%s</b>', [(string)$node]);
158+
$this->outputLine('<b>%s</b>', [(string)$node->aggregateId->value]);
126159
$data = $queryBuilder->getFullElasticSearchHitForNode($node);
127160

128161
if ($field !== '') {
@@ -143,48 +176,31 @@ public function viewNodeCommand(string $identifier, ?string $dimensions = null,
143176
*/
144177
private function outputResults(ElasticSearchQueryResult $result): void
145178
{
146-
$results = array_map(static function (NodeInterface $node) {
179+
$results = array_map(function (Node $node) {
147180
$properties = [];
148181

149-
foreach ($node->getProperties() as $propertyName => $propertyValue) {
182+
foreach ($node->properties as $propertyName => $propertyValue) {
150183
if ($propertyValue instanceof ResourceBasedInterface) {
151184
$properties[$propertyName] = '<b>' . $propertyName . '</b>: ' . (string)$propertyValue->getResource()->getFilename();
152-
} elseif ($propertyValue instanceof \DateTime) {
185+
} elseif ($propertyValue instanceof \DateTimeInterface) {
153186
$properties[$propertyName] = '<b>' . $propertyName . '</b>: ' . $propertyValue->format('Y-m-d H:i');
154187
} elseif (is_array($propertyValue)) {
155188
$properties[$propertyName] = '<b>' . $propertyName . '</b>: ' . 'array';
156-
} elseif ($propertyValue instanceof NodeInterface) {
157-
$properties[$propertyName] = '<b>' . $propertyName . '</b>: ' . $propertyValue->getIdentifier();
189+
} elseif ($propertyValue instanceof Node) {
190+
$properties[$propertyName] = '<b>' . $propertyName . '</b>: ' . $propertyValue->aggregateId->value;
158191
} else {
159192
$properties[$propertyName] = '<b>' . $propertyName . '</b>: ' . (string)$propertyValue;
160193
}
161194
}
162195

163196
return [
164-
'identifier' => $node->getIdentifier(),
165-
'label' => $node->getLabel(),
166-
'nodeType' => $node->getNodeType()->getName(),
197+
'identifier' => $node->aggregateId->value,
198+
'label' => $this->nodeLabelGenerator->getLabel($node),
199+
'nodeType' => $node->nodeTypeName->value,
167200
'properties' => implode(PHP_EOL, $properties),
168201
];
169202
}, $result->toArray());
170203

171204
$this->output->outputTable($results, ['Identifier', 'Label', 'Node Type', 'Properties']);
172205
}
173-
174-
/**
175-
* @param string|null $dimensions
176-
* @return Context
177-
*/
178-
private function createContext(string $dimensions = null): Context
179-
{
180-
$contextConfiguration = [
181-
'workspaceName' => 'live',
182-
];
183-
184-
if ($dimensions !== null) {
185-
$contextConfiguration['dimensions'] = json_decode($dimensions, true);
186-
}
187-
188-
return $this->contextFactory->create($contextConfiguration);
189-
}
190206
}

0 commit comments

Comments
 (0)