Passed
Pull Request — release-11.2.x (#3594)
by Markus
14:43 queued 10:47
created

QueryBuilder::useGroupingFromTypoScript()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 1
cts 1
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace ApacheSolrForTypo3\Solr\Domain\Search\Query;
4
5
/***************************************************************
6
 *  Copyright notice
7
 *
8
 *  (c) 2017 <[email protected]>
9
 *  All rights reserved
10
 *
11
 *  This script is part of the TYPO3 project. The TYPO3 project is
12
 *  free software; you can redistribute it and/or modify
13
 *  it under the terms of the GNU General Public License as published by
14
 *  the Free Software Foundation; either version 3 of the License, or
15
 *  (at your option) any later version.
16
 *
17
 *  The GNU General Public License can be found at
18
 *  http://www.gnu.org/copyleft/gpl.html.
19
 *
20
 *  This script is distributed in the hope that it will be useful,
21
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 *  GNU General Public License for more details.
24
 *
25
 *  This copyright notice MUST APPEAR in all copies of the script!
26
 ***************************************************************/
27
28
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\BigramPhraseFields;
29
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Elevation;
30
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Faceting;
31
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\FieldCollapsing;
32
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Filters;
33
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Grouping;
34
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Highlighting;
35
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\PhraseFields;
36
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\QueryFields;
37
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\ReturnFields;
38
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Slops;
39
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Sortings;
40
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\Spellchecking;
41
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\TrigramPhraseFields;
42
use ApacheSolrForTypo3\Solr\Domain\Site\SiteHashService;
43
use ApacheSolrForTypo3\Solr\Domain\Site\SiteRepository;
44
use ApacheSolrForTypo3\Solr\FieldProcessor\PageUidToHierarchy;
45
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
46
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
47
use ApacheSolrForTypo3\Solr\Util;
48
use TYPO3\CMS\Core\Utility\GeneralUtility;
49
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
50
51
/**
52
 * The concrete QueryBuilder contains all TYPO3 specific initialization logic of solr queries, for TYPO3.
53
 */
54
class QueryBuilder extends AbstractQueryBuilder
55
{
56
57
    /**
58
     * Additional filters, which will be added to the query, as well as to
59
     * suggest queries.
60
     *
61
     * @var array
62
     */
63
    protected $additionalFilters = [];
64
65
    /**
66
     * @var TypoScriptConfiguration
67
     */
68
    protected $typoScriptConfiguration;
69
70
    /**
71
     * @var SolrLogManager;
72
     */
73
    protected $logger;
74
75
    /**
76
     * @var SiteHashService
77
     */
78
    protected $siteHashService;
79
80
    /**
81
     * QueryBuilder constructor.
82
     * @param TypoScriptConfiguration|null $configuration
83
     * @param SolrLogManager|null $solrLogManager
84
     * @param SiteHashService|null $siteHashService
85 147
     */
86
    public function __construct(TypoScriptConfiguration $configuration = null, SolrLogManager $solrLogManager = null, SiteHashService $siteHashService = null)
87 147
    {
88 147
        $this->typoScriptConfiguration = $configuration ?? Util::getSolrConfiguration();
89 147
        $this->logger = $solrLogManager ?? GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
90 147
        $this->siteHashService = $siteHashService ?? GeneralUtility::makeInstance(SiteHashService::class);
91
    }
92
93
    /**
94
     * @param string $queryString
95
     * @return QueryBuilder
96 119
     */
97
    public function newSearchQuery($queryString): QueryBuilder
98 119
    {
99 119
        $this->queryToBuild = $this->getSearchQueryInstance((string)$queryString);
100
        return $this;
101
    }
102
103
    /**
104
     * @param string $queryString
105
     * @return QueryBuilder
106 3
     */
107
    public function newSuggestQuery($queryString): QueryBuilder
108 3
    {
109 3
        $this->queryToBuild = $this->getSuggestQueryInstance($queryString);
110
        return $this;
111
    }
112
113
    /**
114
     * Initializes the Query object and SearchComponents and returns
115
     * the initialized query object, when a search should be executed.
116
     *
117
     * @param string|null $rawQuery
118
     * @param int $resultsPerPage
119
     * @param array $additionalFiltersFromRequest
120
     * @return SearchQuery
121 109
     */
122
    public function buildSearchQuery($rawQuery, $resultsPerPage = 10, array $additionalFiltersFromRequest = []): SearchQuery
123 109
    {
124
        if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
125
            $this->logger->log(SolrLogManager::INFO, 'Received search query', [$rawQuery]);
126
        }
127
128 109
        /* @var $query SearchQuery */
129 109
        return $this->newSearchQuery($rawQuery)
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->newSearchQ...ader(false)->getQuery() returns the type ApacheSolrForTypo3\Solr\Domain\Search\Query\Query which includes types incompatible with the type-hinted return ApacheSolrForTypo3\Solr\...earch\Query\SearchQuery.
Loading history...
130 109
                ->useResultsPerPage($resultsPerPage)
131 109
                ->useReturnFieldsFromTypoScript()
132 109
                ->useQueryFieldsFromTypoScript()
133 109
                ->useInitialQueryFromTypoScript()
134 109
                ->useFiltersFromTypoScript()
135 109
                ->useFilterArray($additionalFiltersFromRequest)
136 109
                ->useFacetingFromTypoScript()
137 109
                ->useVariantsFromTypoScript()
138 109
                ->useGroupingFromTypoScript()
139 109
                ->useHighlightingFromTypoScript()
140 109
                ->usePhraseFieldsFromTypoScript()
141 109
                ->useBigramPhraseFieldsFromTypoScript()
142 109
                ->useTrigramPhraseFieldsFromTypoScript()
143 109
                ->useOmitHeader(false)
144
                ->getQuery();
145
    }
146
147
    /**
148
     * Builds a SuggestQuery with all applied filters.
149
     *
150
     * @param string $queryString
151
     * @param array $additionalFilters
152
     * @param int $requestedPageId
153
     * @param string $groupList
154
     * @return SuggestQuery
155 2
     */
156
    public function buildSuggestQuery(string $queryString, array $additionalFilters, int $requestedPageId, string $groupList): SuggestQuery
157 2
    {
158 2
        $this->newSuggestQuery($queryString)
159 2
            ->useFiltersFromTypoScript()
160 2
            ->useSiteHashFromTypoScript($requestedPageId)
161 2
            ->useUserAccessGroups(explode(',', $groupList))
162
            ->useOmitHeader();
163
164 2
        if (!empty($additionalFilters)) {
165
            $this->useFilterArray($additionalFilters);
166
        }
167
168 2
        return $this->queryToBuild;
169
    }
170
171
    /**
172
     * Returns Query for Search which finds document for given page.
173
     * Note: The Connection is per language as recommended in ext-solr docs.
174
     *
175
     * @return Query
176
     */
177 1
    public function buildPageQuery($pageId)
178
    {
179 1
        $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
180 1
        $site = $siteRepository->getSiteByPageId($pageId);
181
182 1
        return $this->newSearchQuery('')
183 1
            ->useQueryString('*:*')
184 1
            ->useFilter('(type:pages AND uid:' . $pageId . ') OR (*:* AND pid:' . $pageId . ' NOT type:pages)', 'type')
185 1
            ->useFilter('siteHash:' . $site->getSiteHash(), 'siteHash')
186 1
            ->useReturnFields(ReturnFields::fromString('*'))
187 1
            ->useSortings(Sortings::fromString('type asc, title asc'))
188 1
            ->useQueryType('standard')
189 1
            ->getQuery();
190
    }
191
192
    /**
193
     * Returns a query for single record
194
     *
195
     * @return Query
196
     */
197
    public function buildRecordQuery($type, $uid, $pageId): Query
198
    {
199
        $siteRepository = GeneralUtility::makeInstance(SiteRepository::class);
200
        $site = $siteRepository->getSiteByPageId($pageId);
201
202
        return $this->newSearchQuery('')
203
            ->useQueryString('*:*')
204
            ->useFilter('type:' . $type . ' AND uid:' . $uid, 'type')
205
            ->useFilter('siteHash:' . $site->getSiteHash(), 'siteHash')
206
            ->useReturnFields(ReturnFields::fromString('*'))
207
            ->useSortings(Sortings::fromString('type asc, title asc'))
208
            ->useQueryType('standard')
209
            ->getQuery();
210
    }
211
212
    /**
213
     * @return QueryBuilder
214
     */
215 18
    public function useSlopsFromTypoScript(): QueryBuilder
216
    {
217 18
        return $this->useSlops(Slops::fromTypoScriptConfiguration($this->typoScriptConfiguration));
218
    }
219
220
    /**
221
     * Uses the configured boost queries from typoscript
222
     *
223
     * @return QueryBuilder
224
     */
225 18
    public function useBoostQueriesFromTypoScript(): QueryBuilder
226
    {
227 18
        $searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
228
229 18
        if (!empty($searchConfiguration['query.']['boostQuery'])) {
230 1
            return $this->useBoostQueries($searchConfiguration['query.']['boostQuery']);
231
        }
232
233 17
        if (!empty($searchConfiguration['query.']['boostQuery.'])) {
234 1
            $boostQueries = $searchConfiguration['query.']['boostQuery.'];
235 1
            return $this->useBoostQueries(array_values($boostQueries));
236
        }
237
238 16
        return $this;
239
    }
240
241
    /**
242
     * Uses the configured boostFunction from the typoscript configuration.
243
     *
244
     * @return QueryBuilder
245
     */
246 18
    public function useBoostFunctionFromTypoScript(): QueryBuilder
247
    {
248 18
        $searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
249 18
        if (!empty($searchConfiguration['query.']['boostFunction'])) {
250 1
            return $this->useBoostFunction($searchConfiguration['query.']['boostFunction']);
251
        }
252
253 17
        return $this;
254
    }
255
256
    /**
257
     * Uses the configured minimumMatch from the typoscript configuration.
258
     *
259
     * @return QueryBuilder
260
     */
261 18
    public function useMinimumMatchFromTypoScript(): QueryBuilder
262
    {
263 18
        $searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
264 18
        if (!empty($searchConfiguration['query.']['minimumMatch'])) {
265 1
            return $this->useMinimumMatch($searchConfiguration['query.']['minimumMatch']);
266
        }
267
268 17
        return $this;
269
    }
270
271
    /**
272
     * @return QueryBuilder
273
     */
274 18
    public function useTieParameterFromTypoScript(): QueryBuilder
275
    {
276 18
        $searchConfiguration = $this->typoScriptConfiguration->getSearchConfiguration();
277 18
        if (empty($searchConfiguration['query.']['tieParameter'])) {
278 17
            return $this;
279
        }
280
281 1
        return $this->useTieParameter($searchConfiguration['query.']['tieParameter']);
282
    }
283
284
    /**
285
     * Applies the configured query fields from the typoscript configuration.
286
     *
287
     * @return QueryBuilder
288
     */
289 109
    public function useQueryFieldsFromTypoScript(): QueryBuilder
290
    {
291 109
        return $this->useQueryFields(QueryFields::fromString($this->typoScriptConfiguration->getSearchQueryQueryFields()));
292
    }
293
294
    /**
295
     * Applies the configured return fields from the typoscript configuration.
296
     *
297
     * @return QueryBuilder
298
     */
299 109
    public function useReturnFieldsFromTypoScript(): QueryBuilder
300
    {
301 109
        $returnFieldsArray = (array)$this->typoScriptConfiguration->getSearchQueryReturnFieldsAsArray(['*', 'score']);
302 109
        return $this->useReturnFields(ReturnFields::fromArray($returnFieldsArray));
303
    }
304
305
    /**
306
     * Can be used to apply the allowed sites from plugin.tx_solr.search.query.allowedSites to the query.
307
     *
308
     * @param int $requestedPageId
309
     * @return QueryBuilder
310
     */
311
    public function useSiteHashFromTypoScript(int $requestedPageId): QueryBuilder
312
    {
313 7
        $queryConfiguration = $this->typoScriptConfiguration->getObjectByPathOrDefault('plugin.tx_solr.search.query.', []);
314
        $allowedSites = $this->siteHashService->getAllowedSitesForPageIdAndAllowedSitesConfiguration($requestedPageId, $queryConfiguration['allowedSites']);
315 7
        return $this->useSiteHashFromAllowedSites($allowedSites);
316 7
    }
317 7
318
    /**
319
     * Can be used to apply a list of allowed sites to the query.
320
     *
321
     * @param string $allowedSites
322
     * @return QueryBuilder
323
     */
324
    public function useSiteHashFromAllowedSites($allowedSites): QueryBuilder
325
    {
326 7
        $isAnySiteAllowed = trim($allowedSites) === '*';
327
        if ($isAnySiteAllowed) {
328 7
            // no filter required
329 7
            return $this;
330
        }
331 1
332
        $allowedSites = GeneralUtility::trimExplode(',', $allowedSites);
333
        $filters = [];
334 6
        foreach ($allowedSites as $site) {
335 6
            $siteHash = $this->siteHashService->getSiteHashForDomain($site);
336 6
            $filters[] = 'siteHash:"' . $siteHash . '"';
337 6
        }
338 6
339
        $siteHashFilterString = implode(' OR ', $filters);
340
        return $this->useFilter($siteHashFilterString, 'siteHash');
341 6
    }
342 6
343
    /**
344
     * Can be used to filter the result on an applied list of user groups.
345
     *
346
     * @param array $groups
347
     * @return QueryBuilder
348
     */
349
    public function useUserAccessGroups(array $groups): QueryBuilder
350
    {
351 11
        $groups = array_map('intval', $groups);
352
        $groups[] = 0; // always grant access to public documents
353 11
        $groups = array_unique($groups);
354 11
        sort($groups, SORT_NUMERIC);
355 11
356 11
        $accessFilter = '{!typo3access}' . implode(',', $groups);
357
        $this->queryToBuild->removeFilterQuery('access');
358 11
        return $this->useFilter($accessFilter, 'access');
359 11
    }
360 11
361
    /**
362
     * Applies the configured initial query settings to set the alternative query for solr as required.
363
     *
364
     * @return QueryBuilder
365
     */
366
    public function useInitialQueryFromTypoScript(): QueryBuilder
367
    {
368 109
        if ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
369
            // empty main query, but using a "return everything"
370 109
            // alternative query in q.alt
371
            $this->useAlternativeQuery('*:*');
372
        }
373 7
374
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
375
            $this->useAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
376 109
        }
377 1
378
        return $this;
379
    }
380 109
381
    /**
382
     * Applies the configured facets from the typoscript configuration on the query.
383
     *
384
     * @return QueryBuilder
385
     */
386
    public function useFacetingFromTypoScript(): QueryBuilder
387
    {
388 109
        return $this->useFaceting(Faceting::fromTypoScriptConfiguration($this->typoScriptConfiguration));
389
    }
390 109
391
    /**
392
     * Applies the configured variants from the typoscript configuration on the query.
393
     *
394
     * @return QueryBuilder
395
     */
396
    public function useVariantsFromTypoScript(): QueryBuilder
397
    {
398 109
        return $this->useFieldCollapsing(FieldCollapsing::fromTypoScriptConfiguration($this->typoScriptConfiguration));
399
    }
400 109
401
    /**
402
     * Applies the configured groupings from the typoscript configuration to the query.
403
     *
404
     * @return QueryBuilder
405
     */
406
    public function useGroupingFromTypoScript(): QueryBuilder
407
    {
408 109
        return $this->useGrouping(Grouping::fromTypoScriptConfiguration($this->typoScriptConfiguration));
409
    }
410 109
411
    /**
412
     * Applies the configured highlighting from the typoscript configuration to the query.
413
     *
414
     * @return QueryBuilder
415
     */
416
    public function useHighlightingFromTypoScript(): QueryBuilder
417
    {
418 109
        return $this->useHighlighting(Highlighting::fromTypoScriptConfiguration($this->typoScriptConfiguration));
419
    }
420 109
421
    /**
422
     * Applies the configured filters (page section and other from typoscript).
423
     *
424
     * @return QueryBuilder
425
     */
426
    public function useFiltersFromTypoScript(): QueryBuilder
427
    {
428 111
        $filters = Filters::fromTypoScriptConfiguration($this->typoScriptConfiguration);
429
        $this->queryToBuild->setFilterQueries($filters->getValues());
430 111
431 111
        $this->useFilterArray($this->getAdditionalFilters());
432
433 111
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
434
435 111
        if (!is_array($searchQueryFilters) || count($searchQueryFilters) <= 0) {
0 ignored issues
show
introduced by
The condition is_array($searchQueryFilters) is always true.
Loading history...
436
            return $this;
437 111
        }
438 108
439
        // special filter to limit search to specific page tree branches
440
        if (array_key_exists('__pageSections', $searchQueryFilters)) {
441
            $pageIds = GeneralUtility::trimExplode(',', $searchQueryFilters['__pageSections']);
442 3
            $this->usePageSectionsFromPageIds($pageIds);
443
            $this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
444
        }
445
446
        return $this;
447
    }
448 3
449
    /**
450
     * Applies the configured elevation from the typoscript configuration.
451
     *
452
     * @return QueryBuilder
453
     */
454
    public function useElevationFromTypoScript(): QueryBuilder
455
    {
456 5
        return $this->useElevation(Elevation::fromTypoScriptConfiguration($this->typoScriptConfiguration));
457
    }
458 5
459
    /**
460
     * Applies the configured spellchecking from the typoscript configuration.
461
     *
462
     * @return QueryBuilder
463
     */
464
    public function useSpellcheckingFromTypoScript(): QueryBuilder
465
    {
466 1
        return $this->useSpellchecking(Spellchecking::fromTypoScriptConfiguration($this->typoScriptConfiguration));
467
    }
468 1
469
    /**
470
     * Applies the passed pageIds as __pageSection filter.
471
     *
472
     * @param array $pageIds
473
     * @return QueryBuilder
474
     */
475
    public function usePageSectionsFromPageIds(array $pageIds = []): QueryBuilder
476
    {
477
        $filters = [];
478
479
        /** @var $processor PageUidToHierarchy */
480
        $processor = GeneralUtility::makeInstance(PageUidToHierarchy::class);
481
        $hierarchies = $processor->process($pageIds);
482
483
        foreach ($hierarchies as $hierarchy) {
484
            $lastLevel = array_pop($hierarchy);
485
            $filters[] = 'rootline:"' . $lastLevel . '"';
486
        }
487
488
        $pageSectionsFilterString = implode(' OR ', $filters);
489
        return $this->useFilter($pageSectionsFilterString, 'pageSections');
490
    }
491
492
    /**
493
     * Applies the configured phrase fields from the typoscript configuration to the query.
494
     *
495
     * @return QueryBuilder
496
     */
497
    public function usePhraseFieldsFromTypoScript(): QueryBuilder
498
    {
499 109
        return $this->usePhraseFields(PhraseFields::fromTypoScriptConfiguration($this->typoScriptConfiguration));
500
    }
501 109
502
    /**
503
     * Applies the configured bigram phrase fields from the typoscript configuration to the query.
504
     *
505
     * @return QueryBuilder
506
     */
507
    public function useBigramPhraseFieldsFromTypoScript(): QueryBuilder
508
    {
509 109
        return $this->useBigramPhraseFields(BigramPhraseFields::fromTypoScriptConfiguration($this->typoScriptConfiguration));
510
    }
511 109
512
    /**
513
     * Applies the configured trigram phrase fields from the typoscript configuration to the query.
514
     *
515
     * @return QueryBuilder
516
     */
517
    public function useTrigramPhraseFieldsFromTypoScript(): QueryBuilder
518
    {
519 109
        return $this->useTrigramPhraseFields(TrigramPhraseFields::fromTypoScriptConfiguration($this->typoScriptConfiguration));
520
    }
521 109
522
    /**
523
     * Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
524
     *
525
     * @return array
526
     */
527
    public function getAdditionalFilters(): array
528
    {
529 111
        // when we've build the additionalFilter once, we could return them
530
        if (count($this->additionalFilters) > 0) {
531
            return $this->additionalFilters;
532 111
        }
533 2
534
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
535
        if (!is_array($searchQueryFilters) || count($searchQueryFilters) <= 0) {
0 ignored issues
show
introduced by
The condition is_array($searchQueryFilters) is always true.
Loading history...
536 111
            return [];
537 111
        }
538 108
539
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
540
541 3
        // all other regular filters
542
        foreach ($searchQueryFilters as $filterKey => $filter) {
543
            // the __pageSections filter should not be handled as additional filter
544 3
            if ($filterKey === '__pageSections') {
545
                continue;
546 3
            }
547
548
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
549
            if ($filterIsArray) {
550 3
                continue;
551 3
            }
552
553
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
554
            if ($hasSubConfiguration) {
555 3
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
556 3
            }
557
558
            $this->additionalFilters[$filterKey] = $filter;
559
        }
560 3
561
        return $this->additionalFilters;
562
    }
563 3
564
    /**
565
     * @param string $rawQuery
566
     * @return SearchQuery
567
     */
568
    protected function getSearchQueryInstance(string $rawQuery): SearchQuery
569
    {
570 119
        $query = GeneralUtility::makeInstance(SearchQuery::class);
571
        $query->setQuery($rawQuery);
572 119
        return $query;
573 119
    }
574 119
575
    /**
576
     * @param string $rawQuery
577
     * @return SuggestQuery
578
     */
579
    protected function getSuggestQueryInstance($rawQuery): SuggestQuery
580
    {
581 3
        $query = GeneralUtility::makeInstance(SuggestQuery::class, /** @scrutinizer ignore-type */ $rawQuery, /** @scrutinizer ignore-type */ $this->typoScriptConfiguration);
582
583 3
        return $query;
584
    }
585
}
586