588 lines
21 KiB
PHP
588 lines
21 KiB
PHP
<?php
|
|
namespace WapplerSystems\Meilisearch\Domain\Search\Query;
|
|
|
|
/***************************************************************
|
|
* Copyright notice
|
|
*
|
|
* (c) 2017 <timo.hund@dkd.de>
|
|
* All rights reserved
|
|
*
|
|
* This script is part of the TYPO3 project. The TYPO3 project is
|
|
* free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* The GNU General Public License can be found at
|
|
* http://www.gnu.org/copyleft/gpl.html.
|
|
*
|
|
* This script is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* This copyright notice MUST APPEAR in all copies of the script!
|
|
***************************************************************/
|
|
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\BigramPhraseFields;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Elevation;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Faceting;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\FieldCollapsing;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Filters;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Grouping;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Highlighting;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\PhraseFields;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\QueryFields;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\ReturnFields;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Slops;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Sorting;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Sortings;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\Spellchecking;
|
|
use WapplerSystems\Meilisearch\Domain\Search\Query\ParameterBuilder\TrigramPhraseFields;
|
|
use WapplerSystems\Meilisearch\Domain\Site\SiteHashService;
|
|
use WapplerSystems\Meilisearch\Domain\Site\SiteRepository;
|
|
use WapplerSystems\Meilisearch\FieldProcessor\PageUidToHierarchy;
|
|
use WapplerSystems\Meilisearch\System\Configuration\TypoScriptConfiguration;
|
|
use WapplerSystems\Meilisearch\System\Logging\MeilisearchLogManager;
|
|
use WapplerSystems\Meilisearch\Util;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
|
|
|
/**
|
|
* The concrete QueryBuilder contains all TYPO3 specific initialization logic of meilisearch queries, for TYPO3.
|
|
*/
|
|
class QueryBuilder extends AbstractQueryBuilder {
|
|
|
|
/**
|
|
* Additional filters, which will be added to the query, as well as to
|
|
* suggest queries.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $additionalFilters = [];
|
|
|
|
/**
|
|
* @var TypoScriptConfiguration
|
|
*/
|
|
protected $typoScriptConfiguration = null;
|
|
|
|
/**
|
|
* @var MeilisearchLogManager;
|
|
*/
|
|
protected $logger = null;
|
|
|
|
/**
|
|
* @var SiteHashService
|
|
*/
|
|
protected $siteHashService = null;
|
|
|
|
/**
|
|
* QueryBuilder constructor.
|
|
* @param TypoScriptConfiguration|null $configuration
|
|
* @param MeilisearchLogManager|null $meilisearchLogManager
|
|
* @param SiteHashService|null $siteHashService
|
|
*/
|
|
public function __construct(TypoScriptConfiguration $configuration = null, MeilisearchLogManager $meilisearchLogManager = null, SiteHashService $siteHashService = null)
|
|
{
|
|
$this->typoScriptConfiguration = $configuration ?? Util::getMeilisearchConfiguration();
|
|
$this->logger = $meilisearchLogManager ?? GeneralUtility::makeInstance(MeilisearchLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
|
|
$this->siteHashService = $siteHashService ?? GeneralUtility::makeInstance(SiteHashService::class);
|
|
}
|
|
|
|
/**
|
|
* @param string $queryString
|
|
* @return QueryBuilder
|
|
*/
|
|
public function newSearchQuery($queryString): QueryBuilder
|
|
{
|
|
$this->queryToBuild = $this->getSearchQueryInstance((string)$queryString);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string $queryString
|
|
* @return QueryBuilder
|
|
*/
|
|
public function newSuggestQuery($queryString): QueryBuilder
|
|
{
|
|
$this->queryToBuild = $this->getSuggestQueryInstance($queryString);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Initializes the Query object and SearchComponents and returns
|
|
* the initialized query object, when a search should be executed.
|
|
*
|
|
* @param string|null $rawQuery
|
|
* @param int $resultsPerPage
|
|
* @param array $additionalFiltersFromRequest
|
|
* @return SearchQuery
|
|
*/
|
|
public function buildSearchQuery($rawQuery, $resultsPerPage = 10, array $additionalFiltersFromRequest = []) : SearchQuery
|
|
{
|
|
if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
|
|
$this->logger->log(MeilisearchLogManager::INFO, 'Received search query', [$rawQuery]);
|
|
}
|
|
|
|
/* @var $query SearchQuery */
|
|
return $this->newSearchQuery($rawQuery)
|
|
->useResultsPerPage($resultsPerPage)
|
|
->useReturnFieldsFromTypoScript()
|
|
->useQueryFieldsFromTypoScript()
|
|
->useInitialQueryFromTypoScript()
|
|
->useFiltersFromTypoScript()
|
|
->useFilterArray($additionalFiltersFromRequest)
|
|
->useFacetingFromTypoScript()
|
|
->useVariantsFromTypoScript()
|
|
->useGroupingFromTypoScript()
|
|
->useHighlightingFromTypoScript()
|
|
->usePhraseFieldsFromTypoScript()
|
|
->useBigramPhraseFieldsFromTypoScript()
|
|
->useTrigramPhraseFieldsFromTypoScript()
|
|
->useOmitHeader(false)
|
|
->getQuery();
|
|
}
|
|
|
|
/**
|
|
* Builds a SuggestQuery with all applied filters.
|
|
*
|
|
* @param string $queryString
|
|
* @param array $additionalFilters
|
|
* @param integer $requestedPageId
|
|
* @param string $groupList
|
|
* @return SuggestQuery
|
|
*/
|
|
public function buildSuggestQuery(string $queryString, array $additionalFilters, int $requestedPageId, string $groupList) : SuggestQuery
|
|
{
|
|
$this->newSuggestQuery($queryString)
|
|
->useFiltersFromTypoScript()
|
|
->useSiteHashFromTypoScript($requestedPageId)
|
|
->useUserAccessGroups(explode(',', $groupList))
|
|
->useOmitHeader();
|
|
|
|
|
|
if (!empty($additionalFilters)) {
|
|
$this->useFilterArray($additionalFilters);
|
|
}
|
|
|
|
return $this->queryToBuild;
|
|
}
|
|
|
|
/**
|
|
* Returns Query for Search which finds document for given page.
|
|
* Note: The Connection is per language as recommended in ext-meilisearch docs.
|
|
*
|
|
* @return Query
|
|
*/
|
|
public function buildPageQuery($pageId)
|
|
{
|
|
$siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
|
|
$site = $siteRepository->getSiteByPageId($pageId);
|
|
|
|
return $this->newSearchQuery('')
|
|
->useQueryString('*:*')
|
|
->useFilter('(type:pages AND uid:' . $pageId . ') OR (*:* AND pid:' . $pageId . ' NOT type:pages)', 'type')
|
|
->useFilter('siteHash:' . $site->getSiteHash(), 'siteHash')
|
|
->useReturnFields(ReturnFields::fromString('*'))
|
|
->useSortings(Sortings::fromString('type asc, title asc'))
|
|
->useQueryType('standard')
|
|
->getQuery();
|
|
}
|
|
|
|
/**
|
|
* Returns a query for single record
|
|
*
|
|
* @return Query
|
|
*/
|
|
public function buildRecordQuery($type, $uid, $pageId): Query
|
|
{
|
|
$siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
|
|
$site = $siteRepository->getSiteByPageId($pageId);
|
|
|
|
return $this->newSearchQuery('')
|
|
->useQueryString('*:*')
|
|
->useFilter('type:' . $type . ' AND uid:' . $uid, 'type')
|
|
->useFilter('siteHash:' . $site->getSiteHash(), 'siteHash')
|
|
->useReturnFields(ReturnFields::fromString('*'))
|
|
->useSortings(Sortings::fromString('type asc, title asc'))
|
|
->useQueryType('standard')
|
|
->getQuery();
|
|
}
|
|
|
|
/**
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useSlopsFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useSlops(Slops::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Uses the configured boost queries from typoscript
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useBoostQueriesFromTypoScript(): QueryBuilder
|
|
{
|
|
$searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
|
|
|
|
if (!empty($searchConfiguration['query.']['boostQuery'])) {
|
|
return $this->useBoostQueries($searchConfiguration['query.']['boostQuery']);
|
|
}
|
|
|
|
if (!empty($searchConfiguration['query.']['boostQuery.'])) {
|
|
$boostQueries = $searchConfiguration['query.']['boostQuery.'];
|
|
return $this->useBoostQueries(array_values($boostQueries));
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Uses the configured boostFunction from the typoscript configuration.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useBoostFunctionFromTypoScript(): QueryBuilder
|
|
{
|
|
$searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
|
|
if (!empty($searchConfiguration['query.']['boostFunction'])) {
|
|
return $this->useBoostFunction($searchConfiguration['query.']['boostFunction']);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Uses the configured minimumMatch from the typoscript configuration.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useMinimumMatchFromTypoScript(): QueryBuilder
|
|
{
|
|
$searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
|
|
if (!empty($searchConfiguration['query.']['minimumMatch'])) {
|
|
return $this->useMinimumMatch($searchConfiguration['query.']['minimumMatch']);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useTieParameterFromTypoScript(): QueryBuilder
|
|
{
|
|
$searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
|
|
if (empty($searchConfiguration['query.']['tieParameter'])) {
|
|
return $this;
|
|
}
|
|
|
|
return $this->useTieParameter($searchConfiguration['query.']['tieParameter']);
|
|
}
|
|
|
|
/**
|
|
* Applies the configured query fields from the typoscript configuration.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useQueryFieldsFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useQueryFields(QueryFields::fromString($this->typoScriptConfiguration->getSearchQueryQueryFields()));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured return fields from the typoscript configuration.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useReturnFieldsFromTypoScript(): QueryBuilder
|
|
{
|
|
$returnFieldsArray = (array)$this->typoScriptConfiguration->getSearchQueryReturnFieldsAsArray(['*', 'score']);
|
|
return $this->useReturnFields(ReturnFields::fromArray($returnFieldsArray));
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Can be used to apply the allowed sites from plugin.tx_meilisearch.search.query.allowedSites to the query.
|
|
*
|
|
* @param int $requestedPageId
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useSiteHashFromTypoScript(int $requestedPageId): QueryBuilder
|
|
{
|
|
$queryConfiguration = $this->typoScriptConfiguration->getObjectByPathOrDefault('plugin.tx_meilisearch.search.query.', []);
|
|
$allowedSites = $this->siteHashService->getAllowedSitesForPageIdAndAllowedSitesConfiguration($requestedPageId, $queryConfiguration['allowedSites']);
|
|
return $this->useSiteHashFromAllowedSites($allowedSites);
|
|
}
|
|
|
|
/**
|
|
* Can be used to apply a list of allowed sites to the query.
|
|
*
|
|
* @param string $allowedSites
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useSiteHashFromAllowedSites($allowedSites): QueryBuilder
|
|
{
|
|
$isAnySiteAllowed = trim($allowedSites) === '*';
|
|
if ($isAnySiteAllowed) {
|
|
// no filter required
|
|
return $this;
|
|
}
|
|
|
|
$allowedSites = GeneralUtility::trimExplode(',', $allowedSites);
|
|
$filters = [];
|
|
foreach ($allowedSites as $site) {
|
|
$siteHash = $this->siteHashService->getSiteHashForDomain($site);
|
|
$filters[] = 'siteHash:"' . $siteHash . '"';
|
|
}
|
|
|
|
$siteHashFilterString = implode(' OR ', $filters);
|
|
return $this->useFilter($siteHashFilterString, 'siteHash');
|
|
}
|
|
|
|
/**
|
|
* Can be used to filter the result on an applied list of user groups.
|
|
*
|
|
* @param array $groups
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useUserAccessGroups(array $groups): QueryBuilder
|
|
{
|
|
$groups = array_map('intval', $groups);
|
|
$groups[] = 0; // always grant access to public documents
|
|
$groups = array_unique($groups);
|
|
sort($groups, SORT_NUMERIC);
|
|
|
|
$accessFilter = '{!typo3access}' . implode(',', $groups);
|
|
$this->queryToBuild->removeFilterQuery('access');
|
|
return $this->useFilter($accessFilter, 'access');
|
|
}
|
|
|
|
/**
|
|
* Applies the configured initial query settings to set the alternative query for meilisearch as required.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useInitialQueryFromTypoScript(): QueryBuilder
|
|
{
|
|
if ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
|
|
// empty main query, but using a "return everything"
|
|
// alternative query in q.alt
|
|
$this->useAlternativeQuery('*:*');
|
|
}
|
|
|
|
if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
|
|
$this->useAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Applies the configured facets from the typoscript configuration on the query.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useFacetingFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useFaceting(Faceting::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured variants from the typoscript configuration on the query.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useVariantsFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useFieldCollapsing(FieldCollapsing::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured groupings from the typoscript configuration to the query.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useGroupingFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useGrouping(Grouping::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured highlighting from the typoscript configuration to the query.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useHighlightingFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useHighlighting(Highlighting::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured filters (page section and other from typoscript).
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useFiltersFromTypoScript(): QueryBuilder
|
|
{
|
|
$filters = Filters::fromTypoScriptConfiguration($this->typoScriptConfiguration);
|
|
$this->queryToBuild->setFilterQueries($filters->getValues());
|
|
|
|
$this->useFilterArray($this->getAdditionalFilters());
|
|
|
|
$searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
|
|
|
|
if (!is_array($searchQueryFilters) || count($searchQueryFilters) <= 0) {
|
|
return $this;
|
|
}
|
|
|
|
// special filter to limit search to specific page tree branches
|
|
if (array_key_exists('__pageSections', $searchQueryFilters)) {
|
|
$pageIds = GeneralUtility::trimExplode(',', $searchQueryFilters['__pageSections']);
|
|
$this->usePageSectionsFromPageIds($pageIds);
|
|
$this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Applies the configured elevation from the typoscript configuration.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useElevationFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useElevation(Elevation::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured spellchecking from the typoscript configuration.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useSpellcheckingFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useSpellchecking(Spellchecking::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the passed pageIds as __pageSection filter.
|
|
*
|
|
* @param array $pageIds
|
|
* @return QueryBuilder
|
|
*/
|
|
public function usePageSectionsFromPageIds(array $pageIds = []): QueryBuilder
|
|
{
|
|
$filters = [];
|
|
|
|
/** @var $processor PageUidToHierarchy */
|
|
$processor = GeneralUtility::makeInstance(PageUidToHierarchy::class);
|
|
$hierarchies = $processor->process($pageIds);
|
|
|
|
foreach ($hierarchies as $hierarchy) {
|
|
$lastLevel = array_pop($hierarchy);
|
|
$filters[] = 'rootline:"' . $lastLevel . '"';
|
|
}
|
|
|
|
$pageSectionsFilterString = implode(' OR ', $filters);
|
|
return $this->useFilter($pageSectionsFilterString, 'pageSections');
|
|
}
|
|
|
|
/**
|
|
* Applies the configured phrase fields from the typoscript configuration to the query.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function usePhraseFieldsFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->usePhraseFields(PhraseFields::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured bigram phrase fields from the typoscript configuration to the query.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useBigramPhraseFieldsFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useBigramPhraseFields(BigramPhraseFields::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Applies the configured trigram phrase fields from the typoscript configuration to the query.
|
|
*
|
|
* @return QueryBuilder
|
|
*/
|
|
public function useTrigramPhraseFieldsFromTypoScript(): QueryBuilder
|
|
{
|
|
return $this->useTrigramPhraseFields(TrigramPhraseFields::fromTypoScriptConfiguration($this->typoScriptConfiguration));
|
|
}
|
|
|
|
/**
|
|
* Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getAdditionalFilters() : array
|
|
{
|
|
// when we've build the additionalFilter once, we could return them
|
|
if (count($this->additionalFilters) > 0) {
|
|
return $this->additionalFilters;
|
|
}
|
|
|
|
$searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
|
|
if (!is_array($searchQueryFilters) || count($searchQueryFilters) <= 0) {
|
|
return [];
|
|
}
|
|
|
|
$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
|
|
|
|
// all other regular filters
|
|
foreach ($searchQueryFilters as $filterKey => $filter) {
|
|
// the __pageSections filter should not be handled as additional filter
|
|
if ($filterKey === '__pageSections') {
|
|
continue;
|
|
}
|
|
|
|
$filterIsArray = is_array($searchQueryFilters[$filterKey]);
|
|
if ($filterIsArray) {
|
|
continue;
|
|
}
|
|
|
|
$hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
|
|
if ($hasSubConfiguration) {
|
|
$filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
|
|
}
|
|
|
|
$this->additionalFilters[$filterKey] = $filter;
|
|
}
|
|
|
|
return $this->additionalFilters;
|
|
}
|
|
|
|
/**
|
|
* @param string $rawQuery
|
|
* @return SearchQuery
|
|
*/
|
|
protected function getSearchQueryInstance(string $rawQuery): SearchQuery
|
|
{
|
|
$query = GeneralUtility::makeInstance(SearchQuery::class);
|
|
$query->setQuery($rawQuery);
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* @param string $rawQuery
|
|
* @return SuggestQuery
|
|
*/
|
|
protected function getSuggestQueryInstance($rawQuery): SuggestQuery
|
|
{
|
|
$query = GeneralUtility::makeInstance(SuggestQuery::class, /** @scrutinizer ignore-type */ $rawQuery, /** @scrutinizer ignore-type */ $this->typoScriptConfiguration);
|
|
|
|
return $query;
|
|
}
|
|
}
|