Skip to content

Commit

Permalink
Merge pull request #68 from daniellienert/feature/make-suggestionCont…
Browse files Browse the repository at this point in the history
…ext-configurable

FEATURE: Make suggestion context configurable
  • Loading branch information
daniellienert authored Oct 29, 2021
2 parents 75473a3 + d410143 commit 859b2f3
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 19 deletions.
18 changes: 12 additions & 6 deletions Classes/Controller/SuggestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Eel\ElasticSearchQueryBuilder;
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\ElasticSearchClient;
use Flowpack\ElasticSearch\ContentRepositoryAdaptor\Exception\QueryBuildingException;
use Flowpack\SearchPlugin\EelHelper\SuggestionIndexHelper;
use Flowpack\SearchPlugin\Suggestion\SuggestionContextInterface;
use Flowpack\SearchPlugin\Utility\SearchTerm;
use Neos\Cache\Frontend\VariableFrontend;
use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;
use Neos\Flow\Mvc\View\JsonView;
Expand Down Expand Up @@ -44,9 +45,9 @@ class SuggestController extends ActionController

/**
* @Flow\Inject
* @var SuggestionIndexHelper
* @var SuggestionContextInterface
*/
protected $suggestionIndexHelper;
protected $suggestionContext;

/**
* @var array
Expand Down Expand Up @@ -77,7 +78,7 @@ public function initializeObject()
* @throws QueryBuildingException
* @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException
*/
public function indexAction(string $term = '', string $contextNodeIdentifier, string $dimensionCombination = null): void
public function indexAction(string $term = '', string $contextNodeIdentifier = '', string $dimensionCombination = null): void
{
if ($this->elasticSearchClient === null) {
throw new \RuntimeException('The SuggestController needs an ElasticSearchClient, it seems you run without the flowpack/elasticsearch-contentrepositoryadaptor package, though.', 1487189823);
Expand Down Expand Up @@ -110,9 +111,10 @@ public function indexAction(string $term = '', string $contextNodeIdentifier, st
/**
* @param string $term
* @param string $contextNodeIdentifier
* @param string $dimensionCombination
* @param string|null $dimensionCombination
* @return string
* @throws QueryBuildingException
* @throws \Neos\Cache\Exception
* @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException
*/
protected function buildRequestForTerm(string $term, string $contextNodeIdentifier, string $dimensionCombination = null): string
Expand All @@ -129,6 +131,10 @@ protected function buildRequestForTerm(string $term, string $contextNodeIdentifi
$contentContext = $this->createContentContext('live', $dimensionCombination ? json_decode($dimensionCombination, true) : []);
$contextNode = $contentContext->getNodeByIdentifier($contextNodeIdentifier);

if (!$contextNode instanceof NodeInterface) {
throw new \Exception(sprintf('The context node for search with identifier %s could not be found', $contextNodeIdentifier), 1634467679);
}

$sourceFields = array_filter($this->searchAsYouTypeSettings['suggestions']['sourceFields'] ?? ['neos_path']);

/** @var ElasticSearchQueryBuilder $query */
Expand Down Expand Up @@ -160,7 +166,7 @@ protected function buildRequestForTerm(string $term, string $contextNodeIdentifi
'fuzzy' => true,
'size' => $this->searchAsYouTypeSettings['suggestions']['size'] ?? 10,
'contexts' => [
'suggestion_context' => $this->suggestionIndexHelper->buildContext($contextNode)
'suggestion_context' => $this->suggestionContext->buildForSearch($contextNode)->getContextIdentifier()
]
]
]);
Expand Down
25 changes: 13 additions & 12 deletions Classes/EelHelper/SuggestionIndexHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
*/

use Flowpack\SearchPlugin\Exception;
use Flowpack\SearchPlugin\Suggestion\SuggestionContextInterface;
use Flowpack\SearchPlugin\Utility\SearchTerm;
use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Eel\ProtectedContextAwareInterface;
use Neos\Flow\Annotations as Flow;

/**
* Helper for building suggestion configurations
*
* @Flow\Proxy(false)
*/
class SuggestionIndexHelper implements ProtectedContextAwareInterface
{
Expand All @@ -33,6 +32,12 @@ class SuggestionIndexHelper implements ProtectedContextAwareInterface
*/
protected const SITES_OFFSET = 7;

/**
* @Flow\Inject
* @var SuggestionContextInterface
*/
protected $suggestionContext;

/**
* @param string|array $input The input to store, this can be a an array of strings or just a string. This field is mandatory.
* @param int $weight A positive integer or a string containing a positive integer, which defines a weight and allows you to rank your suggestions.
Expand All @@ -49,13 +54,7 @@ public function build($input, $weight = 1): array

public function buildContext(NodeInterface $node): string
{
$siteName = substr($node->getPath(), self::SITES_OFFSET, strpos($node->getPath() . '/', '/', self::SITES_OFFSET) - self::SITES_OFFSET);
return sprintf(
'%s-%s-%s',
$siteName,
$node->getWorkspace()->getName(),
$node->isHidden() ? 'hidden' : 'visible'
);
return (string)($this->suggestionContext->buildForIndex($node));
}

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

if (\is_string($input)) {
return $process($input);
} elseif (\is_array($input)) {
}

if (\is_array($input)) {
$data = [];
foreach (array_map($process, $input) as $values) {
$data = \array_merge($data, $values);
}
return $data;
} else {
throw new Exception('Only string or array are supported as input', 1512733287);
}

throw new Exception('Only string or array are supported as input', 1512733287);
}

/**
Expand Down
72 changes: 72 additions & 0 deletions Classes/Suggestion/SuggestionContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);

namespace Flowpack\SearchPlugin\Suggestion;

/*
* This file is part of the Flowpack.SearchPlugin package.
*
* (c) Contributors of the Flowpack Team - flowpack.org
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\ContentRepository\Domain\Model\NodeInterface;

class SuggestionContext implements SuggestionContextInterface
{

/**
* Rhe length of '/sites/'
* @var int
*/
protected const SITES_OFFSET = 7;

/**
* @var array
*/
protected $contextValues = [];

public function buildForIndex(NodeInterface $node): self
{
$this->contextValues = [
'siteName' => $this->getSiteName($node),
'workspace' => $node->getWorkspace()->getName(),
'isHidden' => $node->isHidden() ? 'hidden' : 'visible',
];

return $this;
}

public function buildForSearch(NodeInterface $node): self
{
$this->contextValues = [
'siteName' => $this->getSiteName($node),
'workspace' => $node->getWorkspace()->getName(),
'isHidden' => 'visible',
];

return $this;
}

public function getContextIdentifier(): string
{
return implode('_', $this->contextValues);
}

public function __toString()
{
return $this->getContextIdentifier();
}

/**
* @param NodeInterface $node
* @return string
*/
protected function getSiteName(NodeInterface $node): string
{
return substr($node->getPath(), self::SITES_OFFSET, strpos($node->getPath() . '/', '/', self::SITES_OFFSET) - self::SITES_OFFSET);
}
}
38 changes: 38 additions & 0 deletions Classes/Suggestion/SuggestionContextInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);

/*
* This file is part of the Flowpack.SearchPlugin package.
*
* (c) Contributors of the Flowpack Team - flowpack.org
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

namespace Flowpack\SearchPlugin\Suggestion;

use Neos\ContentRepository\Domain\Model\NodeInterface;

interface SuggestionContextInterface
{

/**
* Build the context from a given node
* @param NodeInterface $node
*/
public function buildForIndex(NodeInterface $node): self;

/**
* Build the context from a given node
* @param NodeInterface $node
*/
public function buildForSearch(NodeInterface $node): self;

/**
* Returns the calculated context identifier
* @return string
*/
public function getContextIdentifier(): string;
}
8 changes: 7 additions & 1 deletion Configuration/Objects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ Flowpack\SearchPlugin\Controller\SuggestController:
factoryMethodName: getCache
arguments:
1:
value: FlowPackSearchPlugin_ElasticSearchQueryTemplateCache
value: FlowPackSearchPlugin_ElasticSearchQueryTemplateCache

Neos\ContentRepository\Search\AssetExtraction\AssetExtractorInterface:
className: 'Flowpack\ElasticSearch\ContentRepositoryAdaptor\AssetExtraction\IngestAttachmentAssetExtractor'

Flowpack\SearchPlugin\Suggestion\SuggestionContextInterface:
className: 'Flowpack\SearchPlugin\Suggestion\SuggestionContext'
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ In case you need to build the URI to the suggest controller yourself, this is wh

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

### Adjust the suggestion context

The suggestionContext determines, if a result should be displayed in suggetions. By default, nodes that are hidden are excluded.
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

## AJAX search

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

0 comments on commit 859b2f3

Please sign in to comment.