Skip to content

Commit 4a068d7

Browse files
FEATURE: Add support for excluding NodeTypes from indexing
Resolves: Flowpack#45
1 parent 5b62c98 commit 4a068d7

File tree

6 files changed

+221
-0
lines changed

6 files changed

+221
-0
lines changed

Classes/Indexer/NodeIndexer.php

+20
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace Flowpack\SimpleSearch\ContentRepositoryAdaptor\Indexer;
55

6+
use Flowpack\SimpleSearch\ContentRepositoryAdaptor\Service\NodeTypeIndexingConfiguration;
67
use Flowpack\SimpleSearch\Domain\Service\IndexInterface;
78
use Neos\ContentRepository\Domain\Model\NodeInterface;
89
use Neos\ContentRepository\Domain\Repository\WorkspaceRepository;
@@ -14,8 +15,10 @@
1415
use Neos\ContentRepository\Search\Indexer\AbstractNodeIndexer;
1516
use Neos\Eel\Exception;
1617
use Neos\Flow\Annotations as Flow;
18+
use Neos\Flow\Log\Utility\LogEnvironment;
1719
use Neos\Flow\Persistence\PersistenceManagerInterface;
1820
use Neos\Flow\Security\Context;
21+
use Psr\Log\LoggerInterface;
1922
use Symfony\Component\Yaml\Yaml;
2023

2124
/**
@@ -83,6 +86,18 @@ class NodeIndexer extends AbstractNodeIndexer
8386
*/
8487
protected $indexedNodeData = [];
8588

89+
/**
90+
* @Flow\Inject
91+
* @var NodeTypeIndexingConfiguration
92+
*/
93+
protected $nodeTypeIndexingConfiguration;
94+
95+
/**
96+
* @Flow\Inject
97+
* @var LoggerInterface
98+
*/
99+
protected $logger;
100+
86101
/**
87102
* Called by the Flow object framework after creating the object and resolving all dependencies.
88103
*
@@ -121,6 +136,11 @@ public function getIndexClient(): IndexInterface
121136
*/
122137
public function indexNode(NodeInterface $node, $targetWorkspaceName = null, $indexVariants = true): void
123138
{
139+
if ($this->nodeTypeIndexingConfiguration->isIndexable($node->getNodeType()) === false) {
140+
$this->logger->debug(sprintf('Node "%s" (%s) skipped, Node Type is not allowed in the index.', $node->getContextPath(), $node->getNodeType()), LogEnvironment::fromMethodName(__METHOD__));
141+
return;
142+
}
143+
124144
if ($indexVariants === true) {
125145
$this->indexAllNodeVariants($node);
126146
return;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\SimpleSearch\ContentRepositoryAdaptor\Service;
5+
6+
/*
7+
* This file is part of the Flowpack.ElasticSearch.ContentRepositoryAdaptor package.
8+
*
9+
* (c) Contributors of the Neos Project - www.neos.io
10+
*
11+
* This package is Open Source Software. For the full copyright and license
12+
* information, please view the LICENSE file which was distributed with this
13+
* source code.
14+
*/
15+
16+
use Neos\ContentRepository\Domain\Model\NodeType;
17+
use Neos\ContentRepository\Domain\Service\NodeTypeManager;
18+
use Neos\Flow\Annotations as Flow;
19+
20+
/**
21+
* @Flow\Scope("singleton")
22+
*/
23+
final class NodeTypeIndexingConfiguration
24+
{
25+
/**
26+
* @var array
27+
* @Flow\InjectConfiguration(path="defaultConfigurationPerNodeType", package="Neos.ContentRepository.Search")
28+
*/
29+
protected $settings;
30+
31+
/**
32+
* @Flow\Inject
33+
* @var NodeTypeManager
34+
*/
35+
protected $nodeTypeManager;
36+
37+
/**
38+
* @param NodeType $nodeType
39+
* @return bool
40+
*/
41+
public function isIndexable(NodeType $nodeType): bool
42+
{
43+
if ($this->settings === null || !is_array($this->settings)) {
44+
return true;
45+
}
46+
47+
if (isset($this->settings[$nodeType->getName()]['indexed'])) {
48+
return (bool)$this->settings[$nodeType->getName()]['indexed'];
49+
}
50+
51+
$nodeTypeParts = explode(':', $nodeType->getName());
52+
$namespace = reset($nodeTypeParts) . ':*';
53+
if (isset($this->settings[$namespace]['indexed'])) {
54+
return (bool)$this->settings[$namespace]['indexed'];
55+
}
56+
if (isset($this->settings['*']['indexed'])) {
57+
return (bool)$this->settings['*']['indexed'];
58+
}
59+
60+
return false;
61+
}
62+
63+
/**
64+
* @return array
65+
* @throws Exception
66+
*/
67+
public function getIndexableConfiguration(): array
68+
{
69+
$nodeConfigurations = [];
70+
/** @var NodeType $nodeType */
71+
foreach ($this->nodeTypeManager->getNodeTypes(false) as $nodeType) {
72+
$nodeConfigurations[$nodeType->getName()] = $this->isIndexable($nodeType);
73+
}
74+
75+
return $nodeConfigurations;
76+
}
77+
}

Configuration/Testing/NodeTypes.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'Flowpack.SimpleSearch.ContentRepositoryAdaptor:BaseType':
2+
superTypes: { }
3+
'Flowpack.SimpleSearch.ContentRepositoryAdaptor:Type1':
4+
superTypes:
5+
'Flowpack.SimpleSearch.ContentRepositoryAdaptor:BaseType': true
6+
'Flowpack.SimpleSearch.ContentRepositoryAdaptor:Type2':
7+
superTypes: { }

Configuration/Testing/Settings.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Neos:
2+
ContentRepository:
3+
Search:
4+
realtimeIndexing:
5+
enabled: false
6+
defaultConfigurationPerNodeType:
7+
'*':
8+
indexed: true
9+
'Flowpack.SimpleSearch.ContentRepositoryAdaptor:Type1':
10+
indexed: false
11+

README.md

+27
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,30 @@ and configure the DB connection as needed:
4848
value: '%env:DATABASE_PASSWORD%'
4949

5050
The `arguments` are the index identifier (can be chosen freely) and the DSN.
51+
52+
## Exclude NodeTypes from indexing
53+
54+
By default the indexing processes all NodeTypes, but you can change this in your *Settings.yaml*:
55+
56+
```yaml
57+
Neos:
58+
ContentRepository:
59+
Search:
60+
defaultConfigurationPerNodeType:
61+
'*':
62+
indexed: true
63+
'Neos.Neos:FallbackNode':
64+
indexed: false
65+
'Neos.Neos:Shortcut':
66+
indexed: false
67+
'Neos.Neos:ContentCollection':
68+
indexed: false
69+
```
70+
71+
You need to explicitly configure the individual NodeTypes (this feature does not check the Super Type configuration).
72+
But you can use a special notation to configure a full namespace, `Acme.AcmeCom:*` will be applied for all node
73+
types in the `Acme.AcmeCom` namespace. The most specific configuration is used in this order:
74+
75+
- NodeType name (`Neos.Neos:Shortcut`)
76+
- Full namespace notation (`Neos.Neos:*`)
77+
- Catch all (`*`)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\SimpleSearch\ContentRepositoryAdaptor\Tests\Functional\Service;
5+
6+
/*
7+
* This file is part of the Flowpack.ElasticSearch.ContentRepositoryAdaptor package.
8+
*
9+
* (c) Contributors of the Neos Project - www.neos.io
10+
*
11+
* This package is Open Source Software. For the full copyright and license
12+
* information, please view the LICENSE file which was distributed with this
13+
* source code.
14+
*/
15+
16+
use Flowpack\SimpleSearch\ContentRepositoryAdaptor\Service\NodeTypeIndexingConfiguration;
17+
use Neos\ContentRepository\Domain\Service\NodeTypeManager;
18+
use Neos\Flow\Tests\FunctionalTestCase;
19+
20+
class NodeTypeIndexingConfigurationTest extends FunctionalTestCase
21+
{
22+
23+
/**
24+
* @var NodeTypeManager
25+
*/
26+
protected $nodeTypeManager;
27+
28+
/**
29+
* @var NodeTypeIndexingConfiguration
30+
*/
31+
protected $nodeTypeIndexingConfiguration;
32+
33+
public function setUp(): void
34+
{
35+
parent::setUp();
36+
$this->nodeTypeManager = $this->objectManager->get(NodeTypeManager::class);
37+
$this->nodeTypeIndexingConfiguration = $this->objectManager->get(NodeTypeIndexingConfiguration::class);
38+
}
39+
40+
public function nodeTypeDataProvider(): array
41+
{
42+
return [
43+
'notIndexable' => [
44+
'nodeTypeName' => 'Flowpack.SimpleSearch.ContentRepositoryAdaptor:Type1',
45+
'expected' => false,
46+
],
47+
'indexable' => [
48+
'nodeTypeName' => 'Flowpack.SimpleSearch.ContentRepositoryAdaptor:Type2',
49+
'expected' => true,
50+
],
51+
];
52+
}
53+
54+
/**
55+
* @test
56+
* @dataProvider nodeTypeDataProvider
57+
*
58+
* @param string $nodeTypeName
59+
* @param bool $expected
60+
* @throws \Neos\ContentRepository\Exception\NodeTypeNotFoundException
61+
*/
62+
public function isIndexable(string $nodeTypeName, bool $expected): void
63+
{
64+
self::assertEquals($expected, $this->nodeTypeIndexingConfiguration->isIndexable($this->nodeTypeManager->getNodeType($nodeTypeName)));
65+
}
66+
67+
/**
68+
* @test
69+
* @dataProvider nodeTypeDataProvider
70+
*
71+
* @param string $nodeTypeName
72+
* @param bool $expected
73+
*/
74+
public function getIndexableConfiguration(string $nodeTypeName, bool $expected): void
75+
{
76+
$indexableConfiguration = $this->nodeTypeIndexingConfiguration->getIndexableConfiguration();
77+
self::assertEquals($indexableConfiguration[$nodeTypeName], $expected);
78+
}
79+
}

0 commit comments

Comments
 (0)