From d5495908d033ce67993bd5b7140faebcff8ed3e8 Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Thu, 16 Feb 2023 09:52:58 +0100 Subject: [PATCH 1/3] TASK: Cleanup PHP types --- .../AssetExtraction/NullAssetExtractor.php | 5 +- .../Command/NodeIndexCommandController.php | 5 -- Classes/Indexer/NodeIndexer.php | 46 +++-------------- Classes/Search/AbstractQueryBuilder.php | 50 +++---------------- Classes/Search/MysqlQueryBuilder.php | 6 +-- Classes/Search/SqLiteQueryBuilder.php | 4 -- 6 files changed, 18 insertions(+), 98 deletions(-) diff --git a/Classes/AssetExtraction/NullAssetExtractor.php b/Classes/AssetExtraction/NullAssetExtractor.php index 7a7741a..f52b00f 100644 --- a/Classes/AssetExtraction/NullAssetExtractor.php +++ b/Classes/AssetExtraction/NullAssetExtractor.php @@ -10,8 +10,11 @@ class NullAssetExtractor implements AssetExtractorInterface { + /** + * @throws NotImplementedException + */ public function extract(AssetInterface $asset): AssetContent { throw new NotImplementedException('AssetExtractor is not implemented in SimpleSearchAdaptor.'); } -} \ No newline at end of file +} diff --git a/Classes/Command/NodeIndexCommandController.php b/Classes/Command/NodeIndexCommandController.php index 60e0d91..ff00eb2 100644 --- a/Classes/Command/NodeIndexCommandController.php +++ b/Classes/Command/NodeIndexCommandController.php @@ -70,9 +70,6 @@ class NodeIndexCommandController extends CommandController * * This command (re-)indexes all nodes contained in the content repository and sets the schema beforehand. * - * - * @param string $workspace - * @return void * @throws Exception */ public function buildCommand(string $workspace = null): void @@ -89,7 +86,6 @@ public function buildCommand(string $workspace = null): void } /** - * @param string $workspaceName * @throws Exception */ protected function indexWorkspace(string $workspaceName): void @@ -116,7 +112,6 @@ protected function indexWorkspace(string $workspaceName): void } /** - * @param NodeInterface $currentNode * @throws Exception */ protected function traverseNodes(NodeInterface $currentNode): void diff --git a/Classes/Indexer/NodeIndexer.php b/Classes/Indexer/NodeIndexer.php index 192e35a..6f61fc1 100644 --- a/Classes/Indexer/NodeIndexer.php +++ b/Classes/Indexer/NodeIndexer.php @@ -12,8 +12,10 @@ use Neos\ContentRepository\Exception\NodeException; use Neos\ContentRepository\Search\Exception\IndexingException; use Neos\ContentRepository\Search\Indexer\AbstractNodeIndexer; +use Neos\ContentRepository\Search\Search\QueryBuilderInterface; use Neos\Eel\Exception; use Neos\Flow\Annotations as Flow; +use Neos\Flow\Configuration\Exception\InvalidConfigurationTypeException; use Neos\Flow\Persistence\PersistenceManagerInterface; use Neos\Flow\Security\Context; use Symfony\Component\Yaml\Yaml; @@ -33,7 +35,7 @@ class NodeIndexer extends AbstractNodeIndexer /** * @Flow\Inject - * @var \Neos\ContentRepository\Search\Search\QueryBuilderInterface + * @var QueryBuilderInterface */ protected $queryBuilder; @@ -87,9 +89,9 @@ class NodeIndexer extends AbstractNodeIndexer * Called by the Flow object framework after creating the object and resolving all dependencies. * * @param integer $cause Creation cause - * @throws \Neos\Flow\Configuration\Exception\InvalidConfigurationTypeException + * @throws InvalidConfigurationTypeException */ - public function initializeObject($cause) + public function initializeObject($cause): void { parent::initializeObject($cause); foreach ($this->nodeTypeManager->getNodeTypes() as $nodeType) { @@ -100,9 +102,6 @@ public function initializeObject($cause) } } - /** - * @return IndexInterface - */ public function getIndexClient(): IndexInterface { return $this->indexClient; @@ -111,13 +110,9 @@ public function getIndexClient(): IndexInterface /** * index this node, and add it to the current bulk request. * - * @param NodeInterface $node * @param string $targetWorkspaceName * @param boolean $indexVariants - * @return void - * @throws NodeException - * @throws IndexingException - * @throws Exception + * @throws NodeException|IndexingException|Exception */ public function indexNode(NodeInterface $node, $targetWorkspaceName = null, $indexVariants = true): void { @@ -158,27 +153,18 @@ public function indexNode(NodeInterface $node, $targetWorkspaceName = null, $ind } } - /** - * @param NodeInterface $node - * @return void - */ public function removeNode(NodeInterface $node): void { $identifier = $this->generateUniqueNodeIdentifier($node); $this->indexClient->removeData($identifier); } - /** - * @return void - */ public function flush(): void { $this->indexedNodeData = []; } /** - * @param NodeInterface $node - * @return void * @throws \Exception */ protected function indexAllNodeVariants(NodeInterface $node): void @@ -199,8 +185,6 @@ protected function indexAllNodeVariants(NodeInterface $node): void } /** - * @param string $nodeIdentifier - * @param string $workspaceName * @throws \Exception */ protected function indexNodeInWorkspace(string $nodeIdentifier, string $workspaceName): void @@ -226,10 +210,6 @@ protected function indexNodeInWorkspace(string $nodeIdentifier, string $workspac }); } - /** - * @param NodeInterface $node - * @param array $fulltext - */ protected function addFulltextToRoot(NodeInterface $node, array $fulltext): void { $fulltextRoot = $this->findFulltextRoot($node); @@ -239,10 +219,6 @@ protected function addFulltextToRoot(NodeInterface $node, array $fulltext): void } } - /** - * @param NodeInterface $node - * @return NodeInterface - */ protected function findFulltextRoot(NodeInterface $node): ?NodeInterface { if (in_array($node->getNodeType()->getName(), $this->fulltextRootNodeTypes, true)) { @@ -267,19 +243,12 @@ protected function findFulltextRoot(NodeInterface $node): ?NodeInterface /** * Generate identifier for index entry based on node identifier and context - * - * @param NodeInterface $node - * @return string */ protected function generateUniqueNodeIdentifier(NodeInterface $node): string { return $this->persistenceManager->getIdentifierByObject($node->getNodeData()); } - /** - * @param array $nodePropertiesToBeStoredInIndex - * @return array - */ protected function postProcess(array $nodePropertiesToBeStoredInIndex): array { foreach ($nodePropertiesToBeStoredInIndex as $propertyName => $propertyValue) { @@ -291,9 +260,6 @@ protected function postProcess(array $nodePropertiesToBeStoredInIndex): array return $nodePropertiesToBeStoredInIndex; } - /** - * @return array - */ public function calculateDimensionCombinations(): array { $dimensionPresets = $this->contentDimensionPresetSource->getAllPresets(); diff --git a/Classes/Search/AbstractQueryBuilder.php b/Classes/Search/AbstractQueryBuilder.php index 9651609..f4a7184 100644 --- a/Classes/Search/AbstractQueryBuilder.php +++ b/Classes/Search/AbstractQueryBuilder.php @@ -75,7 +75,6 @@ public function fulltext(string $searchWord, array $options = []): QueryBuilderI } /** - * @param NodeInterface $contextNode * @return MysqlQueryBuilder * @throws IllegalObjectTypeException */ @@ -90,11 +89,7 @@ public function query(NodeInterface $contextNode): QueryBuilderInterface return $this; } - /** - * @param string $nodeIdentifierPlaceholder - * @return string - */ - abstract public function getFindIdentifiersByNodeIdentifierQuery(string $nodeIdentifierPlaceholder); + abstract public function getFindIdentifiersByNodeIdentifierQuery(string $nodeIdentifierPlaceholder): string; /** * HIGH-LEVEL API @@ -102,9 +97,6 @@ abstract public function getFindIdentifiersByNodeIdentifierQuery(string $nodeIde /** * Filter by node type, taking inheritance into account. - * - * @param string $nodeType the node type to filter for - * @return QueryBuilderInterface */ public function nodeType(string $nodeType): QueryBuilderInterface { @@ -115,10 +107,6 @@ public function nodeType(string $nodeType): QueryBuilderInterface /** * add an exact-match query for a given property - * - * @param string $propertyName - * @param mixed $propertyValue - * @return QueryBuilderInterface */ public function exactMatch(string $propertyName, $propertyValue): QueryBuilderInterface { @@ -132,10 +120,6 @@ public function exactMatch(string $propertyName, $propertyValue): QueryBuilderIn /** * add an like query for a given property - * - * @param string $propertyName - * @param mixed $propertyValue - * @return QueryBuilderInterface */ public function like(string $propertyName, $propertyValue): QueryBuilderInterface { @@ -149,12 +133,8 @@ public function like(string $propertyName, $propertyValue): QueryBuilderInterfac /** * add a greater than query for a given property - * - * @param string $propertyName - * @param mixed $propertyValue - * @return QueryBuilderInterface */ - public function greaterThan($propertyName, $propertyValue) + public function greaterThan($propertyName, $propertyValue): QueryBuilderInterface { if ($propertyValue instanceof NodeInterface) { $propertyValue = (string) $propertyValue->getNodeAggregateIdentifier(); @@ -166,12 +146,8 @@ public function greaterThan($propertyName, $propertyValue) /** * add a greater than or equal query for a given property - * - * @param string $propertyName - * @param mixed $propertyValue - * @return QueryBuilderInterface */ - public function greaterThanOrEqual($propertyName, $propertyValue) + public function greaterThanOrEqual(string $propertyName, $propertyValue): QueryBuilderInterface { if ($propertyValue instanceof NodeInterface) { $propertyValue = (string) $propertyValue->getNodeAggregateIdentifier(); @@ -183,12 +159,8 @@ public function greaterThanOrEqual($propertyName, $propertyValue) /** * add a less than query for a given property - * - * @param string $propertyName - * @param mixed $propertyValue - * @return QueryBuilderInterface */ - public function lessThan($propertyName, $propertyValue) + public function lessThan(string $propertyName, $propertyValue): QueryBuilderInterface { if ($propertyValue instanceof NodeInterface) { $propertyValue = (string) $propertyValue->getNodeAggregateIdentifier(); @@ -200,12 +172,8 @@ public function lessThan($propertyName, $propertyValue) /** * add a less than query for a given property - * - * @param string $propertyName - * @param mixed $propertyValue - * @return QueryBuilderInterface */ - public function lessThanOrEqual($propertyName, $propertyValue) + public function lessThanOrEqual(string $propertyName, $propertyValue): QueryBuilderInterface { if ($propertyValue instanceof NodeInterface) { $propertyValue = (string) $propertyValue->getNodeAggregateIdentifier(); @@ -249,9 +217,8 @@ public function execute(): \Traversable * Log the current request for debugging after it has been executed. * * @param string $message an optional message to identify the log entry - * @return AbstractQueryBuilder */ - public function log($message = null) + public function log(string $message = null): AbstractQueryBuilder { $this->queryLogEnabled = true; $this->logMessage = $message; @@ -261,8 +228,6 @@ public function log($message = null) /** * Return the total number of hits for the query. - * - * @return integer */ public function count(): int { @@ -279,9 +244,8 @@ public function count(): int /** * @param string $methodName - * @return boolean */ - public function allowsCallOfMethod($methodName) + public function allowsCallOfMethod($methodName): bool { if ($methodName !== 'getFindIdentifiersByNodeIdentifierQuery') { // query must be called first to establish a context and starting point. diff --git a/Classes/Search/MysqlQueryBuilder.php b/Classes/Search/MysqlQueryBuilder.php index 92880e0..255c80f 100644 --- a/Classes/Search/MysqlQueryBuilder.php +++ b/Classes/Search/MysqlQueryBuilder.php @@ -23,16 +23,12 @@ protected function getSimpleSearchQueryBuilder(): QueryBuilderInterface return $this->mysqlQueryBuilder; } - /** - * @param string $nodeIdentifierPlaceholder - * @return string - */ public function getFindIdentifiersByNodeIdentifierQuery(string $nodeIdentifierPlaceholder): string { return 'SELECT "__identifier__" FROM "fulltext_objects" WHERE "__identifier" = :' . $nodeIdentifierPlaceholder; } - public function fulltextMatchResult($searchword, $resultTokens = 200, $ellipsis = '...', $beginModifier = '', $endModifier = ''): string + public function fulltextMatchResult(string $searchword, int $resultTokens = 200, string $ellipsis = '...', string $beginModifier = '', string $endModifier = ''): string { return $this->mysqlQueryBuilder->fulltextMatchResult($searchword, $resultTokens, $ellipsis, $beginModifier, $endModifier); } diff --git a/Classes/Search/SqLiteQueryBuilder.php b/Classes/Search/SqLiteQueryBuilder.php index 108f512..8df2994 100644 --- a/Classes/Search/SqLiteQueryBuilder.php +++ b/Classes/Search/SqLiteQueryBuilder.php @@ -24,10 +24,6 @@ protected function getSimpleSearchQueryBuilder(): QueryBuilderInterface return $this->sqLiteQueryBuilder; } - /** - * @param string $nodeIdentifierPlaceholder - * @return string - */ public function getFindIdentifiersByNodeIdentifierQuery(string $nodeIdentifierPlaceholder): string { return 'SELECT __identifier__ FROM objects WHERE __identifier = :' . $nodeIdentifierPlaceholder; From 80925a7b8633e6e0d09717ba9e0bc28eae983548 Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Thu, 16 Feb 2023 10:09:41 +0100 Subject: [PATCH 2/3] FEATURE: Allow indexing only the live workspace --- .../Command/NodeIndexCommandController.php | 10 ++++++++++ Classes/Indexer/NodeIndexer.php | 19 +++++++++++++++++++ Configuration/Settings.yaml | 6 ++++++ 3 files changed, 35 insertions(+) diff --git a/Classes/Command/NodeIndexCommandController.php b/Classes/Command/NodeIndexCommandController.php index ff00eb2..6859b2e 100644 --- a/Classes/Command/NodeIndexCommandController.php +++ b/Classes/Command/NodeIndexCommandController.php @@ -65,6 +65,12 @@ class NodeIndexCommandController extends CommandController */ protected $indexedNodes; + /** + * @var array + * @Flow\InjectConfiguration(package="Neos.ContentRepository.Search") + */ + protected $settings; + /** * Index all nodes. * @@ -74,6 +80,10 @@ class NodeIndexCommandController extends CommandController */ public function buildCommand(string $workspace = null): void { + if ($workspace === null && $this->settings['indexAllWorkspaces'] === false) { + $workspace = 'live'; + } + $this->indexedNodes = 0; if ($workspace === null) { foreach ($this->workspaceRepository->findAll() as $workspaceInstance) { diff --git a/Classes/Indexer/NodeIndexer.php b/Classes/Indexer/NodeIndexer.php index 6f61fc1..31f15b8 100644 --- a/Classes/Indexer/NodeIndexer.php +++ b/Classes/Indexer/NodeIndexer.php @@ -69,6 +69,12 @@ class NodeIndexer extends AbstractNodeIndexer */ protected $contextFactory; + /** + * @var array + * @Flow\InjectConfiguration(package="Neos.ContentRepository.Search") + */ + protected $settings; + /** * @Flow\Inject * @var Context @@ -116,6 +122,19 @@ public function getIndexClient(): IndexInterface */ public function indexNode(NodeInterface $node, $targetWorkspaceName = null, $indexVariants = true): void { + if ($this->settings['indexAllWorkspaces'] === false) { + // we are only supposed to index the live workspace. + // We need to check the workspace at two occasions; checking the + // $targetWorkspaceName and the workspace name of the node's context as fallback + if ($targetWorkspaceName !== null && $targetWorkspaceName !== 'live') { + return; + } + + if ($targetWorkspaceName === null && $node->getContext()->getWorkspaceName() !== 'live') { + return; + } + } + if ($indexVariants === true) { $this->indexAllNodeVariants($node); return; diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 85ca0fb..a640d8a 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -11,3 +11,9 @@ Neos: indexing: "${'#' + Array.join(Indexing.convertArrayOfNodesToArrayOfNodeIdentifiers(value), '#') + '#'}" defaultContext: Json: Neos\Eel\Helper\JsonHelper + + # API. If set to FALSE, only index the "live" workspace and not user workspaces. + # If you only index the live workspace, Search will not work for your editors in the user workspaces. + # Furthermore, if you heavily rely on Search for collecting content, this might be strange for editors to + # work with -- as unpublished changes are not indexed right away. + indexAllWorkspaces: true From 56916d6b94050f9dd6fbea2b7ff4937d84014901 Mon Sep 17 00:00:00 2001 From: Sebastian Helzle Date: Fri, 17 Feb 2023 13:40:28 +0100 Subject: [PATCH 3/3] BUGFIX: Prevent index error when properties is empty --- Classes/Indexer/NodeIndexer.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Classes/Indexer/NodeIndexer.php b/Classes/Indexer/NodeIndexer.php index 31f15b8..f7d1b9d 100644 --- a/Classes/Indexer/NodeIndexer.php +++ b/Classes/Indexer/NodeIndexer.php @@ -151,6 +151,9 @@ public function indexNode(NodeInterface $node, $targetWorkspaceName = null, $ind if (isset($this->indexedNodeData[$identifier])) { $properties = $this->indexClient->findOneByIdentifier($identifier); + if (!$properties) { + return; + } unset($properties['__identifier__']); $properties['__workspace'] .= ', #' . ($targetWorkspaceName ?? $node->getContext()->getWorkspaceName()) . '#'; if (array_key_exists('__dimensionshash', $properties)) {