Completed
Push — master ( 4008a8...a15d6d )
by Timo
05:41
created

SearchResultSetService   F

Complexity

Total Complexity 74

Size/Duplication

Total Lines 589
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 18

Test Coverage

Coverage 83.64%

Importance

Changes 0
Metric Value
wmc 74
lcom 1
cbo 18
dl 0
loc 589
ccs 179
cts 214
cp 0.8364
rs 2.3809
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 3
A getIsSolrAvailable() 0 5 1
A getHasSearched() 0 4 1
A getSearch() 0 4 1
B getPreparedQuery() 0 35 6
A initializeRegisteredSearchComponents() 0 19 4
A processResponse() 0 4 1
A wrapResultDocumentInResultObject() 0 17 3
A getResultSetClassName() 0 5 2
A applyPageSectionsRootLineFilter() 0 13 3
C getAdditionalFilters() 0 36 7
B search() 0 61 6
B doASearch() 0 33 4
A getAutoCorrection() 0 21 4
B peformAutoCorrection() 0 29 4
B modifyQuery() 0 28 6
A getDocumentById() 0 13 2
A handleSearchHook() 0 15 4
A getLastResultSet() 0 4 1
A getLastSearchWasExecutedWithEmptyQueryString() 0 9 2
A getInitialSearchIsConfigured() 0 4 4
A getRegisteredSearchComponents() 0 4 1
A addSearchResultsToResultSet() 0 11 3
A getQueryInstance() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like SearchResultSetService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SearchResultSetService, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace ApacheSolrForTypo3\Solr\Domain\Search\ResultSet;
4
5
/***************************************************************
6
 *  Copyright notice
7
 *
8
 *  (c) 2015-2016 Timo Schmidt <[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 2 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\QueryFields;
29
use ApacheSolrForTypo3\Solr\Domain\Search\SearchRequest;
30
use ApacheSolrForTypo3\Solr\Domain\Search\SearchRequestAware;
31
use ApacheSolrForTypo3\Solr\Domain\Variants\VariantsProcessor;
32
use ApacheSolrForTypo3\Solr\Query;
33
use ApacheSolrForTypo3\Solr\Query\Modifier\Modifier;
34
use ApacheSolrForTypo3\Solr\Search;
35
use ApacheSolrForTypo3\Solr\Search\QueryAware;
36
use ApacheSolrForTypo3\Solr\Search\SearchAware;
37
use ApacheSolrForTypo3\Solr\Search\SearchComponentManager;
38
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
39
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
40
use ApacheSolrForTypo3\Solr\System\Solr\SolrCommunicationException;
41
use ApacheSolrForTypo3\Solr\System\Solr\SolrIncompleteResponseException;
42
use ApacheSolrForTypo3\Solr\System\Solr\SolrInternalServerErrorException;
43
use TYPO3\CMS\Core\Utility\GeneralUtility;
44
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
45
46
/**
47
 * The SearchResultSetService is responsible to build a SearchResultSet from a SearchRequest.
48
 * It encapsulates the logic to trigger a search in order to be able to reuse it in multiple places.
49
 *
50
 * @author Timo Schmidt <[email protected]>
51
 */
52
class SearchResultSetService
53
{
54
    /**
55
     * Additional filters, which will be added to the query, as well as to
56
     * suggest queries.
57
     *
58
     * @var array
59
     */
60
    protected $additionalFilters = [];
61
62
    /**
63
     * Track, if the number of results per page has been changed by the current request
64
     *
65
     * @var bool
66
     */
67
    protected $resultsPerPageChanged = false;
68
69
    /**
70
     * @var Search
71
     */
72
    protected $search;
73
74
    /**
75
     * @var SearchResultSet
76
     */
77
    protected $lastResultSet = null;
78
79
    /**
80
     * @var boolean
81
     */
82
    protected $isSolrAvailable = false;
83
84
    /**
85
     * @var TypoScriptConfiguration
86
     */
87
    protected $typoScriptConfiguration;
88
89
    /**
90
     * @var SolrLogManager;
91
     */
92
    protected $logger = null;
93
94
    /**
95
     * @var SearchResultBuilder
96
     */
97
    protected $searchResultBuilder;
98
99
    /**
100
     * @param TypoScriptConfiguration $configuration
101
     * @param Search $search
102
     * @param SolrLogManager $solrLogManager
103 45
     * @param SearchResultBuilder $resultBuilder
104
     */
105 45
    public function __construct(TypoScriptConfiguration $configuration, Search $search, SolrLogManager $solrLogManager = null, SearchResultBuilder $resultBuilder = null)
106 45
    {
107 45
        $this->search = $search;
108 45
        $this->typoScriptConfiguration = $configuration;
109
        $this->logger = is_null($solrLogManager) ? GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__) : $solrLogManager;
110
        $this->searchResultBuilder = is_null($resultBuilder) ? GeneralUtility::makeInstance(SearchResultBuilder::class) : $resultBuilder;
111
    }
112
113
    /**
114 29
     * @param bool $useCache
115
     * @return bool
116 29
     */
117 29
    public function getIsSolrAvailable($useCache = true)
118
    {
119
        $this->isSolrAvailable = $this->search->ping($useCache);
120
        return $this->isSolrAvailable;
121
    }
122
123 29
    /**
124
     * @return bool
125 29
     */
126
    public function getHasSearched()
127
    {
128
        return $this->search->hasSearched();
129
    }
130
131
    /**
132
     * Retrieves the used search instance.
133 2
     *
134
     * @return Search
135 2
     */
136
    public function getSearch()
137
    {
138
        return $this->search;
139
    }
140
141
    /**
142
     * Initializes the Query object and SearchComponents and returns
143
     * the initialized query object, when a search should be executed.
144
     *
145
     * @param string|null $rawQuery
146
     * @param int $resultsPerPage
147
     * @return Query
148
     */
149
    protected function getPreparedQuery($rawQuery, $resultsPerPage)
150
    {
151
        /* @var $query Query */
152
        $query = $this->getQueryInstance($rawQuery);
153
154
        $this->applyPageSectionsRootLineFilter($query);
155
156
        if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
157
            $this->logger->log(
158
                SolrLogManager::INFO,
159
                'Received search query',
160
                [
161
                    $rawQuery
162 37
                ]
163
            );
164
        }
165 37
166
        $query->setResultsPerPage($resultsPerPage);
167 37
168
        if ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
169 37
            // empty main query, but using a "return everything"
170
            // alternative query in q.alt
171
            $query->setAlternativeQuery('*:*');
172
        }
173
174
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
175
            $query->setAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
176
        }
177
178
        foreach ($this->getAdditionalFilters() as $additionalFilter) {
179 37
            $query->getFilters()->add($additionalFilter);
180
        }
181 37
182
        return $query;
183
    }
184 30
185
    /**
186
     * @param Query $query
187 37
     * @param SearchRequest $searchRequest
188 3
     */
189
    protected function initializeRegisteredSearchComponents(Query $query, SearchRequest $searchRequest)
190
    {
191 37
        $searchComponents = $this->getRegisteredSearchComponents();
192 2
193
        foreach ($searchComponents as $searchComponent) {
194
            /** @var Search\SearchComponent $searchComponent */
195 37
            $searchComponent->setSearchConfiguration($this->typoScriptConfiguration->getSearchConfiguration());
196
197
            if ($searchComponent instanceof QueryAware) {
198
                $searchComponent->setQuery($query);
199
            }
200
201
            if ($searchComponent instanceof SearchRequestAware) {
202 37
                $searchComponent->setSearchRequest($searchRequest);
203
            }
204 37
205
            $searchComponent->initializeSearchComponent();
206 37
        }
207
    }
208 31
209
    /**
210 31
     * Does post processing of the response.
211 31
     *
212
     * @param \Apache_Solr_Response $response The search's response.
213
     */
214 31
    protected function processResponse(\Apache_Solr_Response $response)
215 30
    {
216
        $this->wrapResultDocumentInResultObject($response);
217
    }
218 31
219
    /**
220 37
     * Wrap all results document it a custom EXT:solr SearchResult object.
221
     *
222
     * Can be overwritten:
223
     *
224
     * $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] = ''
225
     *
226
     * to use a custom result object.
227
     *
228
     * @param \Apache_Solr_Response $response
229
     * @throws \Apache_Solr_ParserException
230
     */
231 37
    protected function wrapResultDocumentInResultObject(\Apache_Solr_Response $response)
232
    {
233 37
        $parsedData = $response->getParsedData();
234 37
235 37
        if (!is_array($parsedData->response->docs)) {
236 4
            return;
237 4
        }
238
239
        $documents = $parsedData->response->docs;
240 37
        foreach ($documents as $key => $originalDocument) {
241 37
            $result = $this->searchResultBuilder->fromApacheSolrDocument($originalDocument);
242
            $documents[$key] = $result;
243 37
        }
244 37
245 3
        $parsedData->response->docs = $documents;
246
        $response->setParsedData($parsedData);
247
    }
248 37
249
    /**
250
     * @return string
251
     */
252 2
    protected function getResultSetClassName()
253
    {
254
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName ']) ?
255 37
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] : SearchResultSet::class;
256
    }
257
258
    /**
259
     * Initializes additional filters configured through TypoScript and
260
     * Flexforms for use in regular queries and suggest queries.
261
     *
262
     * @param Query $query
263
     * @return void
264 39
     */
265
    protected function applyPageSectionsRootLineFilter(Query $query)
266 39
    {
267 39
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
268
        if (count($searchQueryFilters) <= 0) {
269 39
            return;
270 39
        }
271
272
        // special filter to limit search to specific page tree branches
273
        if (array_key_exists('__pageSections', $searchQueryFilters)) {
274
            $query->setRootlineFilter($searchQueryFilters['__pageSections']);
275
            $this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
276
        }
277
    }
278
279 39
    /**
280
     * Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
281 39
     *
282 1
     * @return array
283
     */
284 1
    public function getAdditionalFilters()
285 1
    {
286 1
        // when we've build the additionalFilter once, we could return them
287 1
        if (count($this->additionalFilters) > 0) {
288
            return $this->additionalFilters;
289
        }
290
291 39
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
292
        if (count($searchQueryFilters) <= 0) {
293
            return [];
294
        }
295
296
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
297
298
        // all other regular filters
299 39
        foreach ($searchQueryFilters as $filterKey => $filter) {
300
            // the __pageSections filter should not be handled as additional filter
301 39
            if ($filterKey === '__pageSections') {
302 5
                continue;
303
            }
304
305 34
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
306 31
            if ($filterIsArray) {
307
                continue;
308
            }
309 3
310 3
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
311
            if ($hasSubConfiguration) {
312 2
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
313 2
            }
314
315
            $this->additionalFilters[$filterKey] = $filter;
316 2
        }
317
318
        return $this->additionalFilters;
319
    }
320 2
321 2
    /**
322
     * Performs a search and returns a SearchResultSet.
323
     *
324
     * @param SearchRequest $searchRequest
325 2
     * @return SearchResultSet
326 2
     */
327 2
    public function search(SearchRequest $searchRequest)
328 2
    {
329
        /** @var $resultSet SearchResultSet */
330 2
        $resultSetClass = $this->getResultSetClassName();
331 2
        $resultSet = GeneralUtility::makeInstance($resultSetClass);
332 2
        $resultSet->setUsedSearchRequest($searchRequest);
333
        $this->lastResultSet = $resultSet;
334 2
335
        $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
336
337 3
        if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
338
            // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
339
            return $resultSet;
340
        }
341
342
        if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
343
            // the user entered an empty query string "" or "  " and empty querystring is not allowed
344
            return $resultSet;
345
        }
346
347
        $rawQuery = $searchRequest->getRawUserQuery();
348
        $resultsPerPage = (int)$searchRequest->getResultsPerPage();
349
        $query = $this->getPreparedQuery($rawQuery, $resultsPerPage);
350
        $this->initializeRegisteredSearchComponents($query, $searchRequest);
351 39
        $resultSet->setUsedQuery($query);
352
353
        // the offset mulitplier is page - 1 but not less then zero
354 39
        $offsetMultiplier = max(0, $searchRequest->getPage() - 1);
355 1
        $offSet = $offsetMultiplier * $resultsPerPage;
356
357
        // performing the actual search, sending the query to the Solr server
358
        $query = $this->modifyQuery($query, $searchRequest, $this->search);
359
        $response = $this->doASearch($query, $offSet);
360 1
361
        if ($resultsPerPage === 0) {
362
            // when resultPerPage was forced to 0 we also set the numFound to 0 to hide results, e.g.
363
            // when results for the initial search should not be shown.
364 1
            $response->response->numFound = 0;
0 ignored issues
show
Bug introduced by
The property response does not seem to exist. Did you mean _response?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
365 1
        }
366 1
367 1
        $this->processResponse($response);
368 1
        $this->addSearchResultsToResultSet($response, $resultSet);
369
370 1
        $resultSet->setResponse($response);
371
        $resultSet->setUsedPage((int)$searchRequest->getPage());
372
        $resultSet->setUsedResultsPerPage($resultsPerPage);
373 39
        $resultSet->setUsedAdditionalFilters($this->getAdditionalFilters());
374 5
        $resultSet->setUsedSearch($this->search);
375
376
        /** @var $variantsProcessor VariantsProcessor */
377 34
        $variantsProcessor = GeneralUtility::makeInstance(VariantsProcessor::class, $this->typoScriptConfiguration, $this->searchResultBuilder);
378 28
        $variantsProcessor->process($resultSet);
379 28
380
        /** @var $searchResultReconstitutionProcessor ResultSetReconstitutionProcessor */
381
        $searchResultReconstitutionProcessor = GeneralUtility::makeInstance(ResultSetReconstitutionProcessor::class);
382 34
        $searchResultReconstitutionProcessor->process($resultSet);
383 34
384
        $resultSet = $this->getAutoCorrection($resultSet);
385
386
        return $this->handleSearchHook('afterSearch', $resultSet);
387
    }
388
389
    /**
390
     * Executes the search and builds a fake response for a current bug in Apache Solr 6.3
391
     *
392
     * @param Query $query
393 28
     * @param int $offSet
394
     * @throws SolrCommunicationException
395 28
     * @return \Apache_Solr_Response
396 28
     */
397 28
    protected function doASearch($query, $offSet)
398
    {
399
        try {
400
            $response = $this->search->search($query, $offSet, null);
401 28
        } catch (SolrInternalServerErrorException $e) {
402
            // when variants are enable and the index is empty, we get a parse exception, because of a
403
            // Apache Solr Bug.
404
            // see: https://github.com/TYPO3-Solr/ext-solr/issues/668
405
            // @todo this try/catch block can be removed after upgrading to Apache Solr 6.4
406
            if (!$this->typoScriptConfiguration->getSearchVariants()) {
407 28
                throw $e;
408
            }
409 28
410 28
            $response = $e->getSolrResponse();
411
412
            $parsedData = new \stdClass();
413
            $parsedData->response = new \stdClass();
414
            $parsedData->response->docs = [];
415
            $parsedData->spellcheck = [];
416 39
            $parsedData->debug = [];
417
            $parsedData->responseHeader = [];
418 39
            $parsedData->facet_counts = [];
419 39
            $parsedData->facets = [];
420
            $response->setParsedData($parsedData);
421
422
        }
423
424
        if($response === null) {
425
            throw new SolrIncompleteResponseException('The response retrieved from solr was incomplete', 1505989678);
426
        }
427
428 37
        return $response;
429
    }
430 37
431
    /**
432
     * @param SearchResultSet $searchResultSet
433
     * @return SearchResultSet
434
     */
435
    protected function getAutoCorrection(SearchResultSet $searchResultSet)
436
    {
437
        // no secondary search configured
438
        if (!$this->typoScriptConfiguration->getSearchSpellcheckingSearchUsingSpellCheckerSuggestion()) {
439
            return $searchResultSet;
440 37
        }
441
442 37
        // more then zero results
443 37
        if ($searchResultSet->getAllResultCount() > 0) {
444 35
            return $searchResultSet;
445
        }
446
447
        // no corrections present
448 2
        if (!$searchResultSet->getHasSpellCheckingSuggestions()) {
449
            return $searchResultSet;
450
        }
451
452 2
        $searchResultSet = $this->peformAutoCorrection($searchResultSet);
453
454
        return $searchResultSet;
455
    }
456
457
    /**
458
     * @param SearchResultSet $searchResultSet
459 42
     * @return SearchResultSet
460
     */
461
    protected function peformAutoCorrection(SearchResultSet $searchResultSet)
462 42
    {
463 2
        $searchRequest = $searchResultSet->getUsedSearchRequest();
464
        $suggestions = $searchResultSet->getSpellCheckingSuggestions();
465
466 42
        $maximumRuns = $this->typoScriptConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry(1);
467 42
        $runs = 0;
468 40
469
        foreach ($suggestions as $suggestion) {
470
            $runs++;
471 2
472
            $correction = $suggestion->getSuggestion();
473
            $initialQuery = $searchRequest->getRawUserQuery();
474 2
475
            $searchRequest->setRawQueryString($correction);
476 2
            $searchResultSet = $this->search($searchRequest);
477
            if ($searchResultSet->getAllResultCount() > 0) {
478
                $searchResultSet->setIsAutoCorrected(true);
479
                $searchResultSet->setCorrectedQueryString($correction);
480 2
                $searchResultSet->setInitialQueryString($initialQuery);
481 2
                break;
482
            }
483
484
            if ($runs > $maximumRuns) {
485 2
                break;
486 2
            }
487
        }
488
        return $searchResultSet;
489
    }
490 2
491
    /**
492
     * Allows to modify a query before eventually handing it over to Solr.
493 2
     *
494
     * @param Query $query The current query before it's being handed over to Solr.
495
     * @param SearchRequest $searchRequest The searchRequest, relevant in the current context
496
     * @param Search $search The search, relevant in the current context
497
     * @throws \UnexpectedValueException
498
     * @return Query The modified query that is actually going to be given to Solr.
499
     */
500
    protected function modifyQuery(Query $query, SearchRequest $searchRequest, Search $search)
501
    {
502 39
        // hook to modify the search query
503
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery'])) {
504
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery'] as $classReference) {
505 39
                $queryModifier = GeneralUtility::getUserObj($classReference);
506 39
507 39
                if ($queryModifier instanceof Modifier) {
508 39
                    if ($queryModifier instanceof SearchAware) {
509
                        $queryModifier->setSearch($search);
510 39
                    }
511
512 39
                    if ($queryModifier instanceof SearchRequestAware) {
513
                        $queryModifier->setSearchRequest($searchRequest);
514 2
                    }
515
516
                    $query = $queryModifier->modifyQuery($query);
517 37
                } else {
518
                    throw new \UnexpectedValueException(
519
                        get_class($queryModifier) . ' must implement interface ' . Modifier::class,
520
                        1310387414
521
                    );
522 37
                }
523 37
            }
524 37
        }
525 37
526 37
        return $query;
527
    }
528 37
529
    /**
530 37
     * Retrieves a single document from solr by document id.
531 4
     *
532
     * @param string $documentId
533
     * @return SearchResult
534 37
     */
535
    public function getDocumentById($documentId)
536
    {
537 37
        /* @var $query Query */
538 37
        $query = GeneralUtility::makeInstance(Query::class, $documentId);
539 37
        $query->setQueryFields(QueryFields::fromString('id'));
540
541 37
        $response = $this->search->search($query, 0, 1);
542
        $this->processResponse($response);
0 ignored issues
show
Bug introduced by
It seems like $response defined by $this->search->search($query, 0, 1) on line 541 can be null; however, ApacheSolrForTypo3\Solr\...vice::processResponse() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
543
544 2
        $parsedData = $response->getParsedData();
545
        $resultDocument = isset($parsedData->response->docs[0]) ? $parsedData->response->docs[0] : null;
546
        return $resultDocument;
547 37
    }
548
549 37
    /**
550
     * This method is used to call the registered hooks during the search execution.
551 37
     *
552 37
     * @param string $eventName
553 37
     * @param SearchResultSet $resultSet
554 37
     * @return SearchResultSet
555 37
     */
556
    private function handleSearchHook($eventName, SearchResultSet $resultSet)
557
    {
558 37
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName])) {
559 37
            return $resultSet;
560
        }
561 37
562
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) {
563
            $afterSearchProcessor = GeneralUtility::getUserObj($classReference);
564
            if ($afterSearchProcessor instanceof SearchResultSetProcessor) {
565
                $afterSearchProcessor->process($resultSet);
566
            }
567
        }
568
569
        return $resultSet;
570
    }
571
572
    /**
573 37
     * @return SearchResultSet
574
     */
575
    public function getLastResultSet()
576 37
    {
577 30
        return $this->lastResultSet;
578 30
    }
579
580 30
    /**
581 30
     * This method returns true when the last search was executed with an empty query
582
     * string or whitespaces only. When no search was triggered it will return false.
583
     *
584
     * @return bool
585 30
     */
586 30
    public function getLastSearchWasExecutedWithEmptyQueryString()
587
    {
588
        $wasEmptyQueryString = false;
589 30
        if ($this->lastResultSet != null) {
590
            $wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString();
591
        }
592
593 30
        return $wasEmptyQueryString;
594
    }
595
596
    /**
597
     * @return bool
598
     */
599 37
    protected function getInitialSearchIsConfigured()
600
    {
601
        return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery();
602
    }
603
604
    /**
605
     * @return mixed
606
     */
607
    protected function getRegisteredSearchComponents()
608
    {
609
        return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents();
610
    }
611
612
    /**
613 37
     * This method is used to reference the SearchResult object from the response in the SearchResultSet object.
614
     *
615
     * @param \Apache_Solr_Response $response
616 37
     * @param SearchResultSet $resultSet
617
     */
618
    protected function addSearchResultsToResultSet($response, $resultSet)
619
    {
620
        $parsedData = $response->getParsedData();
621
        if (!is_array($parsedData->response->docs)) {
622
            return;
623
        }
624
625
        foreach ($parsedData->response->docs as $searchResult) {
626
            $resultSet->addSearchResult($searchResult);
627
        }
628
    }
629
630
    /**
631
     * @param string $rawQuery
632
     * @return Query|object
633
     */
634
    protected function getQueryInstance($rawQuery)
635
    {
636
        $query = GeneralUtility::makeInstance(Query::class, $rawQuery, $this->typoScriptConfiguration);
637
        return $query;
638
    }
639
640
}
641