Skip to content

Commit 859b2f3

Browse files
Merge pull request #68 from daniellienert/feature/make-suggestionContext-configurable
FEATURE: Make suggestion context configurable
2 parents 75473a3 + d410143 commit 859b2f3

6 files changed

Lines changed: 147 additions & 19 deletions

File tree

Classes/Controller/SuggestController.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Eel\ElasticSearchQueryBuilder;
1515
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\ElasticSearchClient;
1616
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception\QueryBuildingException;
17-
use Flowpack\SearchPlugin\EelHelper\SuggestionIndexHelper;
17+
use Flowpack\SearchPlugin\Suggestion\SuggestionContextInterface;
1818
use Flowpack\SearchPlugin\Utility\SearchTerm;
1919
use Neos\Cache\Frontend\VariableFrontend;
20+
use Neos\ContentRepository\Domain\Model\NodeInterface;
2021
use Neos\Flow\Annotations as Flow;
2122
use Neos\Flow\Mvc\Controller\ActionController;
2223
use Neos\Flow\Mvc\View\JsonView;
@@ -44,9 +45,9 @@ class SuggestController extends ActionController
4445

4546
/**
4647
* @Flow\Inject
47-
* @var SuggestionIndexHelper
48+
* @var SuggestionContextInterface
4849
*/
49-
protected $suggestionIndexHelper;
50+
protected $suggestionContext;
5051

5152
/**
5253
* @var array
@@ -77,7 +78,7 @@ public function initializeObject()
7778
* @throws QueryBuildingException
7879
* @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException
7980
*/
80-
public function indexAction(string $term = '', string $contextNodeIdentifier, string $dimensionCombination = null): void
81+
public function indexAction(string $term = '', string $contextNodeIdentifier = '', string $dimensionCombination = null): void
8182
{
8283
if ($this->elasticSearchClient === null) {
8384
throw new \RuntimeException('The SuggestController needs an ElasticSearchClient, it seems you run without the flowpack/elasticsearch-contentrepositoryadaptor package, though.', 1487189823);
@@ -110,9 +111,10 @@ public function indexAction(string $term = '', string $contextNodeIdentifier, st
110111
/**
111112
* @param string $term
112113
* @param string $contextNodeIdentifier
113-
* @param string $dimensionCombination
114+
* @param string|null $dimensionCombination
114115
* @return string
115116
* @throws QueryBuildingException
117+
* @throws \Neos\Cache\Exception
116118
* @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException
117119
*/
118120
protected function buildRequestForTerm(string $term, string $contextNodeIdentifier, string $dimensionCombination = null): string
@@ -129,6 +131,10 @@ protected function buildRequestForTerm(string $term, string $contextNodeIdentifi
129131
$contentContext = $this->createContentContext('live', $dimensionCombination ? json_decode($dimensionCombination, true) : []);
130132
$contextNode = $contentContext->getNodeByIdentifier($contextNodeIdentifier);
131133

134+
if (!$contextNode instanceof NodeInterface) {
135+
throw new \Exception(sprintf('The context node for search with identifier %s could not be found', $contextNodeIdentifier), 1634467679);
136+
}
137+
132138
$sourceFields = array_filter($this->searchAsYouTypeSettings['suggestions']['sourceFields'] ?? ['neos_path']);
133139

134140
/** @var ElasticSearchQueryBuilder $query */
@@ -160,7 +166,7 @@ protected function buildRequestForTerm(string $term, string $contextNodeIdentifi
160166
'fuzzy' => true,
161167
'size' => $this->searchAsYouTypeSettings['suggestions']['size'] ?? 10,
162168
'contexts' => [
163-
'suggestion_context' => $this->suggestionIndexHelper->buildContext($contextNode)
169+
'suggestion_context' => $this->suggestionContext->buildForSearch($contextNode)->getContextIdentifier()
164170
]
165171
]
166172
]);

Classes/EelHelper/SuggestionIndexHelper.php

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

1616
use Flowpack\SearchPlugin\Exception;
17+
use Flowpack\SearchPlugin\Suggestion\SuggestionContextInterface;
1718
use Flowpack\SearchPlugin\Utility\SearchTerm;
1819
use Neos\ContentRepository\Domain\Model\NodeInterface;
1920
use Neos\Eel\ProtectedContextAwareInterface;
2021
use Neos\Flow\Annotations as Flow;
2122

2223
/**
2324
* Helper for building suggestion configurations
24-
*
25-
* @Flow\Proxy(false)
2625
*/
2726
class SuggestionIndexHelper implements ProtectedContextAwareInterface
2827
{
@@ -33,6 +32,12 @@ class SuggestionIndexHelper implements ProtectedContextAwareInterface
3332
*/
3433
protected const SITES_OFFSET = 7;
3534

35+
/**
36+
* @Flow\Inject
37+
* @var SuggestionContextInterface
38+
*/
39+
protected $suggestionContext;
40+
3641
/**
3742
* @param string|array $input The input to store, this can be a an array of strings or just a string. This field is mandatory.
3843
* @param int $weight A positive integer or a string containing a positive integer, which defines a weight and allows you to rank your suggestions.
@@ -49,13 +54,7 @@ public function build($input, $weight = 1): array
4954

5055
public function buildContext(NodeInterface $node): string
5156
{
52-
$siteName = substr($node->getPath(), self::SITES_OFFSET, strpos($node->getPath() . '/', '/', self::SITES_OFFSET) - self::SITES_OFFSET);
53-
return sprintf(
54-
'%s-%s-%s',
55-
$siteName,
56-
$node->getWorkspace()->getName(),
57-
$node->isHidden() ? 'hidden' : 'visible'
58-
);
57+
return (string)($this->suggestionContext->buildForIndex($node));
5958
}
6059

6160
/**
@@ -72,15 +71,17 @@ protected function prepareInput($input): ?array
7271

7372
if (\is_string($input)) {
7473
return $process($input);
75-
} elseif (\is_array($input)) {
74+
}
75+
76+
if (\is_array($input)) {
7677
$data = [];
7778
foreach (array_map($process, $input) as $values) {
7879
$data = \array_merge($data, $values);
7980
}
8081
return $data;
81-
} else {
82-
throw new Exception('Only string or array are supported as input', 1512733287);
8382
}
83+
84+
throw new Exception('Only string or array are supported as input', 1512733287);
8485
}
8586

8687
/**
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Flowpack\SearchPlugin\Suggestion;
5+
6+
/*
7+
* This file is part of the Flowpack.SearchPlugin package.
8+
*
9+
* (c) Contributors of the Flowpack Team - flowpack.org
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\NodeInterface;
17+
18+
class SuggestionContext implements SuggestionContextInterface
19+
{
20+
21+
/**
22+
* Rhe length of '/sites/'
23+
* @var int
24+
*/
25+
protected const SITES_OFFSET = 7;
26+
27+
/**
28+
* @var array
29+
*/
30+
protected $contextValues = [];
31+
32+
public function buildForIndex(NodeInterface $node): self
33+
{
34+
$this->contextValues = [
35+
'siteName' => $this->getSiteName($node),
36+
'workspace' => $node->getWorkspace()->getName(),
37+
'isHidden' => $node->isHidden() ? 'hidden' : 'visible',
38+
];
39+
40+
return $this;
41+
}
42+
43+
public function buildForSearch(NodeInterface $node): self
44+
{
45+
$this->contextValues = [
46+
'siteName' => $this->getSiteName($node),
47+
'workspace' => $node->getWorkspace()->getName(),
48+
'isHidden' => 'visible',
49+
];
50+
51+
return $this;
52+
}
53+
54+
public function getContextIdentifier(): string
55+
{
56+
return implode('_', $this->contextValues);
57+
}
58+
59+
public function __toString()
60+
{
61+
return $this->getContextIdentifier();
62+
}
63+
64+
/**
65+
* @param NodeInterface $node
66+
* @return string
67+
*/
68+
protected function getSiteName(NodeInterface $node): string
69+
{
70+
return substr($node->getPath(), self::SITES_OFFSET, strpos($node->getPath() . '/', '/', self::SITES_OFFSET) - self::SITES_OFFSET);
71+
}
72+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
/*
5+
* This file is part of the Flowpack.SearchPlugin package.
6+
*
7+
* (c) Contributors of the Flowpack Team - flowpack.org
8+
*
9+
* This package is Open Source Software. For the full copyright and license
10+
* information, please view the LICENSE file which was distributed with this
11+
* source code.
12+
*/
13+
14+
namespace Flowpack\SearchPlugin\Suggestion;
15+
16+
use Neos\ContentRepository\Domain\Model\NodeInterface;
17+
18+
interface SuggestionContextInterface
19+
{
20+
21+
/**
22+
* Build the context from a given node
23+
* @param NodeInterface $node
24+
*/
25+
public function buildForIndex(NodeInterface $node): self;
26+
27+
/**
28+
* Build the context from a given node
29+
* @param NodeInterface $node
30+
*/
31+
public function buildForSearch(NodeInterface $node): self;
32+
33+
/**
34+
* Returns the calculated context identifier
35+
* @return string
36+
*/
37+
public function getContextIdentifier(): string;
38+
}

Configuration/Objects.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ Flowpack\SearchPlugin\Controller\SuggestController:
66
factoryMethodName: getCache
77
arguments:
88
1:
9-
value: FlowPackSearchPlugin_ElasticSearchQueryTemplateCache
9+
value: FlowPackSearchPlugin_ElasticSearchQueryTemplateCache
10+
11+
Neos\ContentRepository\Search\AssetExtraction\AssetExtractorInterface:
12+
className: 'Flowpack\ElasticSearch\ContentRepositoryAdaptor\AssetExtraction\IngestAttachmentAssetExtractor'
13+
14+
Flowpack\SearchPlugin\Suggestion\SuggestionContextInterface:
15+
className: 'Flowpack\SearchPlugin\Suggestion\SuggestionContext'

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ In case you need to build the URI to the suggest controller yourself, this is wh
112112

113113
{f:uri.action(action: 'index', controller: 'Suggest', package: 'Flowpack.SearchPlugin', format: 'json', absolute: 1, arguments: {contextNodeIdentifier: node.identifier, dimensionCombination: dimensionCombination})}
114114

115+
### Adjust the suggestion context
116+
117+
The suggestionContext determines, if a result should be displayed in suggetions. By default, nodes that are hidden are excluded.
118+
In many projects, the search als takes the Neos.Seo metaRobotsNoindex property into account or excludes certain nodeTypes. In order to adjust the suggestion context to your search logic, you can write your custom logic and switch the implementation of the `Flowpack\SearchPlugin\Suggestion\SuggestionContextInterface` via Objects.yaml
119+
115120
## AJAX search
116121

117122
The plugin comes with a controller that can be reached like this per default, using `GET`:

0 commit comments

Comments
 (0)