Completed
Push — master ( 324c2f...3e3e29 )
by Timo
47s
created

SearchResultSetService::processResponse()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.0187

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 10
cts 11
cp 0.9091
rs 8.7624
c 0
b 0
f 0
cc 5
eloc 10
nc 8
nop 3
crap 5.0187
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\SearchRequest;
29
use ApacheSolrForTypo3\Solr\Plugin\PluginAware;
30
use ApacheSolrForTypo3\Solr\Query;
31
use ApacheSolrForTypo3\Solr\Response\Processor\ResponseProcessor;
32
use ApacheSolrForTypo3\Solr\Search;
33
use ApacheSolrForTypo3\Solr\Search\QueryAware;
34
use ApacheSolrForTypo3\Solr\Search\SearchComponentManager;
35
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration;
36
use TYPO3\CMS\Core\SingletonInterface;
37
use TYPO3\CMS\Core\Utility\GeneralUtility;
38
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
39
use TYPO3\CMS\Frontend\Plugin\AbstractPlugin;
40
41
/**
42
 * The SearchResultSetService is responsible to build a SearchResultSet from a SearchRequest.
43
 * It encapsulates the logic to trigger a search in order to be able to reuse it in multiple places.
44
 *
45
 * @author Timo Schmidt <[email protected]>
46
 */
47
class SearchResultSetService implements SingletonInterface
48
{
49
    /**
50
     * Additional filters, which will be added to the query, as well as to
51
     * suggest queries.
52
     *
53
     * @var array
54
     */
55
    protected $additionalFilters = array();
56
57
    /**
58
     * Track, if the number of results per page has been changed by the current request
59
     *
60
     * @var bool
61
     */
62
    protected $resultsPerPageChanged = false;
63
64
    /**
65
     * @var \ApacheSolrForTypo3\Solr\Search
66
     */
67
    protected $search;
68
69
    /**
70
     * @var SearchResultSet
71
     */
72
    protected $lastResultSet = null;
73
74
    /**
75
     * @var AbstractPlugin
76
     */
77
    protected $parentPlugin;
78
79
    /**
80
     * @var bool
81
     */
82
    protected $useQueryAwareComponents = true;
83
84
    /**
85
     * @var bool
86
     */
87
    protected $usePluginAwareComponents = true;
88
89
    /**
90
     * @var
91
     */
92
    protected $isSolrAvailable = false;
93
94
    /**
95
     * @var TypoScriptConfiguration
96
     */
97
    protected $typoScriptConfiguration;
98
99
    /**
100
     * @param TypoScriptConfiguration $configuration
101
     * @param Search $search
102
     * @param AbstractPlugin $parentPlugin (optional parent plugin, needed for plugin aware components)
103
     */
104 36
    public function __construct(TypoScriptConfiguration $configuration, Search $search, AbstractPlugin $parentPlugin = null)
105
    {
106 36
        $this->search = $search;
107 36
        $this->typoScriptConfiguration = $configuration;
108 36
        $this->parentPlugin = $parentPlugin;
109 36
    }
110
111
    /**
112
     * @return AbstractPlugin
113
     */
114 1
    public function getParentPlugin()
115
    {
116 1
        return $this->parentPlugin;
117
    }
118
119
    /**
120
     * @param bool $useCache
121
     * @return bool
122
     */
123 25
    public function getIsSolrAvailable($useCache = true)
124
    {
125 25
        $this->isSolrAvailable = $this->search->ping($useCache);
126 25
        return $this->isSolrAvailable;
127
    }
128
129
    /**
130
     * @return bool
131
     */
132 25
    public function getHasSearched()
133
    {
134 25
        return $this->search->hasSearched();
135
    }
136
137
    /**
138
     * Retrieves the used search instance.
139
     *
140
     * @return Search
141
     */
142 25
    public function getSearch()
143
    {
144 25
        return $this->search;
145
    }
146
147
    /**
148
     * @param bool $usePluginAwareComponents
149
     */
150
    public function setUsePluginAwareComponents($usePluginAwareComponents)
151
    {
152
        $this->usePluginAwareComponents = $usePluginAwareComponents;
153
    }
154
155
    /**
156
     * @return bool
157
     */
158
    public function getUsePluginAwareComponents()
159
    {
160
        return $this->usePluginAwareComponents;
161
    }
162
163
    /**
164
     * @param bool $useQueryAwareComponents
165
     */
166
    public function setUseQueryAwareComponents($useQueryAwareComponents)
167
    {
168
        $this->useQueryAwareComponents = $useQueryAwareComponents;
169
    }
170
171
    /**
172
     * @return bool
173
     */
174
    public function getUseQueryAwareComponents()
175
    {
176
        return $this->useQueryAwareComponents;
177
    }
178
179
    /**
180
     * Initializes the Query object and SearchComponents and returns
181
     * the initialized query object, when a search should be executed.
182
     *
183
     * @param string $rawQuery
184
     * @param int $resultsPerPage
185
     * @return Query
186
     */
187 30
    protected function getPreparedQuery($rawQuery, $resultsPerPage)
188
    {
189
        /* @var $query Query */
190 30
        $query = GeneralUtility::makeInstance(Query::class, $rawQuery);
191
192 30
        $this->applyPageSectionsRootLineFilter($query);
193
194 30
        if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
195
            GeneralUtility::devLog('received search query', 'solr', 0, array($rawQuery));
196
        }
197
198 30
        $query->setResultsPerPage($resultsPerPage);
199
200 30
        $this->initializeRegisteredSearchComponents($query);
201
202 30
        if ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
203
            // empty main query, but using a "return everything"
204
            // alternative query in q.alt
205 23
            $query->setAlternativeQuery('*:*');
206
        }
207
208 30
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
209 3
            $query->setAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
210
        }
211
212 30
        foreach ($this->getAdditionalFilters() as $additionalFilter) {
213 2
            $query->addFilter($additionalFilter);
214
        }
215
216 30
        return $query;
217
    }
218
219
    /**
220
     * @param Query $query
221
     */
222 30
    protected function initializeRegisteredSearchComponents(Query $query)
223
    {
224 30
        $searchComponents = $this->getRegisteredSearchComponents();
225
226 30
        foreach ($searchComponents as $searchComponent) {
227
            /** @var Search\SearchComponent $searchComponent */
228 24
            $searchComponent->setSearchConfiguration($this->typoScriptConfiguration->getSearchConfiguration());
229
230 24
            if ($searchComponent instanceof QueryAware && $this->useQueryAwareComponents) {
231 24
                $searchComponent->setQuery($query);
232
            }
233
234 24
            if ($searchComponent instanceof PluginAware && $this->usePluginAwareComponents) {
235
                $searchComponent->setParentPlugin($this->parentPlugin);
236
            }
237
238 24
            $searchComponent->initializeSearchComponent();
239
        }
240 30
    }
241
242
    /**
243
     * Returns the number of results per Page.
244
     *
245
     * Also influences how many result documents are returned by the Solr
246
     * server as the return value is used in the Solr "rows" GET parameter.
247
     *
248
     * @param string $rawQuery
249
     * @param int|null $requestedPerPage
250
     * @return int number of results to show per page
251
     */
252 30
    protected function getNumberOfResultsPerPage($rawQuery, $requestedPerPage = null)
253
    {
254 30
        $perPageSwitchOptions = $this->typoScriptConfiguration->getSearchResultsPerPageSwitchOptionsAsArray();
255 30
        if (isset($requestedPerPage) && in_array($requestedPerPage, $perPageSwitchOptions)) {
256 1
            $this->setPerPageInSession($requestedPerPage);
257 1
            $this->resultsPerPageChanged = true;
258
        }
259
260 30
        $defaultResultsPerPage = $this->typoScriptConfiguration->getSearchResultsPerPage();
261 30
        $sessionResultPerPage = $this->getPerPageFromSession();
262
263 30
        $currentNumberOfResultsShown = $defaultResultsPerPage;
264 30
        if (!is_null($sessionResultPerPage) && in_array($sessionResultPerPage, $perPageSwitchOptions)) {
265
            $currentNumberOfResultsShown = (int)$sessionResultPerPage;
266
        }
267
268 30
        if ($this->shouldHideResultsFromInitialSearch($rawQuery)) {
269
            // initialize search with an empty query, which would by default return all documents
270
            // anyway, tell Solr to not return any result documents
271
            // Solr will still return facets though
272
            $currentNumberOfResultsShown = 0;
273
        }
274
275 30
        return $currentNumberOfResultsShown;
276
    }
277
278
    /**
279
     * Provides a hook for other classes to process the search's response.
280
     *
281
     * @param string $rawQuery
282
     * @param Query $query The query that has been searched for.
283
     * @param \Apache_Solr_Response $response The search's response.
284
     */
285 31
    protected function processResponse($rawQuery, Query $query, \Apache_Solr_Response &$response)
286
    {
287 31
        if ($this->shouldHideResultsFromInitialSearch($rawQuery)) {
288
            // explicitly set number of results to 0 as we just wanted
289
            // facets and the like according to configuration
290
            // @see getNumberOfResultsPerPage()
291
            $response->response->numFound = 0;
292
        }
293
294 31
        $this->wrapResultDocumentInResultObject($response);
295 31
        $this->addExpandedDocumentsFromVariants($response);
296
297 31
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse'])) {
298 21
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse'] as $classReference) {
299 21
                $responseProcessor = GeneralUtility::getUserObj($classReference);
300 21
                if ($responseProcessor instanceof ResponseProcessor) {
301 21
                    $responseProcessor->processResponse($query, $response);
302
                }
303
            }
304
        }
305 31
    }
306
307
    /**
308
     * This method is used to add documents to the expanded documents of the SearchResult
309
     * when collapsing is configured.
310
     *
311
     * @param \Apache_Solr_Response $response
312
     */
313 31
    protected function addExpandedDocumentsFromVariants(\Apache_Solr_Response &$response)
314
    {
315 31
        if (!is_array($response->response->docs)) {
316 5
            return;
317
        }
318
319 26
        if (!$this->typoScriptConfiguration->getSearchVariants()) {
320 24
            return;
321
        }
322
323 2
        $variantsField = $this->typoScriptConfiguration->getSearchVariantsField();
324 2
        foreach ($response->response->docs as $key => $resultDocument) {
325
            /** @var $resultDocument SearchResult */
326 2
            $variantField = $resultDocument->getField($variantsField);
327 2
            $variantId = isset($variantField['value']) ? $variantField['value'] : null;
328
329
                // when there is no value in the collapsing field, we can return
330 2
            if ($variantId === null) {
331
                continue;
332
            }
333
334 2
            $variantAccessKey = strtolower($variantId);
335 2
            if (!isset($response->{'expanded'}) || !isset($response->{'expanded'}->{$variantAccessKey})) {
336
                continue;
337
            }
338
339 2
            foreach ($response->{'expanded'}->{$variantAccessKey}->{'docs'} as $variantDocumentArray) {
340 2
                $variantDocument = new \Apache_Solr_Document();
341 2
                foreach (get_object_vars($variantDocumentArray) as $propertyName => $propertyValue) {
342 2
                    $variantDocument->{$propertyName} = $propertyValue;
343
                }
344 2
                $variantSearchResult = $this->wrapApacheSolrDocumentInResultObject($variantDocument);
345 2
                $variantSearchResult->setIsVariant(true);
346 2
                $variantSearchResult->setVariantParent($resultDocument);
347
348 2
                $resultDocument->addVariant($variantSearchResult);
349
            }
350
        }
351 2
    }
352
353
    /**
354
     * Wrap all results document it a custom EXT:solr SearchResult object.
355
     *
356
     * Can be overwritten:
357
     *
358
     * $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] = ''
359
     *
360
     * to use a custom result object.
361
     *
362
     * @param \Apache_Solr_Response $response
363
     * @throws \InvalidArgumentException
364
     */
365 31
    protected function wrapResultDocumentInResultObject(\Apache_Solr_Response &$response)
366
    {
367 31
        if (!is_array($response->response->docs)) {
368 5
            return;
369
        }
370
371 26
        foreach ($response->response->docs as $key => $originalDocument) {
372 24
            $result = $this->wrapApacheSolrDocumentInResultObject($originalDocument);
373 24
            $response->response->docs[$key] = $result;
374
        }
375 26
    }
376
377
    /**
378
     * This method is used to wrap the \Apache_Solr_Document instance in an instance of the configured SearchResult
379
     * class.
380
     *
381
     * @param \Apache_Solr_Document $originalDocument
382
     * @throws \InvalidArgumentException
383
     * @return SearchResult
384
     */
385 24
    protected function wrapApacheSolrDocumentInResultObject(\Apache_Solr_Document $originalDocument)
386
    {
387 24
        $searchResultClassName = $this->getResultClassName();
388 24
        $result = GeneralUtility::makeInstance($searchResultClassName, $originalDocument);
389 24
        if (!$result instanceof SearchResult) {
390
            throw new \InvalidArgumentException('Could not create result object with class: ' . (string)$searchResultClassName, 1470037679);
391
        }
392
393 24
        return $result;
394
    }
395
396
    /**
397
     * @return string
398
     */
399 24
    protected function getResultClassName()
400
    {
401 24
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName ']) ?
402 24
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] : SearchResult::class;
403
    }
404
405
    /**
406
     * @return string
407
     */
408 33
    protected function getResultSetClassName()
409
    {
410 33
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName ']) ?
411 33
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] : SearchResultSet::class;
412
    }
413
414
    /**
415
     * Checks it the results should be hidden in the response.
416
     *
417
     * @param string $rawQuery
418
     * @return bool
419
     */
420 31
    protected function shouldHideResultsFromInitialSearch($rawQuery)
421
    {
422 31
        return ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery()) && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery() && empty($rawQuery);
423
    }
424
425
    /**
426
     * Initializes additional filters configured through TypoScript and
427
     * Flexforms for use in regular queries and suggest queries.
428
     *
429
     * @param Query $query
430
     * @return void
431
     */
432 30
    protected function applyPageSectionsRootLineFilter(Query $query)
433
    {
434 30
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
435 30
        if (count($searchQueryFilters) <= 0) {
436 28
            return;
437
        }
438
439
        // special filter to limit search to specific page tree branches
440 2
        if (array_key_exists('__pageSections', $searchQueryFilters)) {
441
            $query->setRootlineFilter($searchQueryFilters['__pageSections']);
442
            $this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
443
        }
444 2
    }
445
446
    /**
447
     * Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
448
     *
449
     * @return array
450
     */
451 35
    public function getAdditionalFilters()
452
    {
453
        // when we've build the additionalFilter once, we could return them
454 35
        if (count($this->additionalFilters) > 0) {
455 2
            return $this->additionalFilters;
456
        }
457
458 35
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
459 35
        if (count($searchQueryFilters) <= 0) {
460 32
            return array();
461
        }
462
463 3
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
464
465
        // all other regular filters
466 3
        foreach ($searchQueryFilters as $filterKey => $filter) {
467
            // the __pageSections filter should not be handled as additional filter
468 3
            if ($filterKey === '__pageSections') {
469
                continue;
470
            }
471
472 3
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
473 3
            if ($filterIsArray) {
474
                continue;
475
            }
476
477 3
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
478 3
            if ($hasSubConfiguration) {
479
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
480
            }
481
482 3
            $this->additionalFilters[$filterKey] = $filter;
483
        }
484
485 3
        return $this->additionalFilters;
486
    }
487
488
    /**
489
     * Performs a search and returns a SearchResultSet.
490
     *
491
     * @param SearchRequest $searchRequest
492
     * @return SearchResultSet
493
     */
494 33
    public function search(SearchRequest $searchRequest)
495
    {
496
        /** @var $resultSet SearchResultSet */
497 33
        $resultSetClass = $this->getResultSetClassName();
498 33
        $resultSet = GeneralUtility::makeInstance($resultSetClass);
499 33
        $resultSet->setUsedSearchRequest($searchRequest);
500 33
        $this->lastResultSet = $resultSet;
501
502 33
        $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
503
504 33
        if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
505
            // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
506 1
            return $resultSet;
507
        }
508
509 32
        if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
510
            // the user entered an empty query string "" or "  " and empty querystring is not allowed
511 2
            return $resultSet;
512
        }
513
514 30
        $rawQuery = $searchRequest->getRawUserQuery();
515 30
        $resultsPerPage = $this->getNumberOfResultsPerPage($rawQuery, $searchRequest->getResultsPerPage());
0 ignored issues
show
Documentation introduced by
$rawQuery is of type array|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug introduced by
It seems like $searchRequest->getResultsPerPage() targeting ApacheSolrForTypo3\Solr\...st::getResultsPerPage() can also be of type array; however, ApacheSolrForTypo3\Solr\...umberOfResultsPerPage() does only seem to accept integer|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
516 30
        $query = $this->getPreparedQuery($rawQuery, $resultsPerPage);
0 ignored issues
show
Documentation introduced by
$rawQuery is of type array|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
517
518 30
        $resultSet->setUsedQuery($query);
519
520 30
        $currentPage = max(0, $searchRequest->getPage());
521
        // if the number of results per page has been changed by the current request, reset the pagebrowser
522 30
        if ($this->resultsPerPageChanged) {
523 1
            $currentPage = 0;
524
        }
525
526 30
        $offSet = $currentPage * $resultsPerPage;
527
        // performing the actual search, sending the query to the Solr server
528 30
        $response = $this->search->search($query, $offSet, null);
529
530 30
        $this->processResponse($rawQuery, $query, $response);
0 ignored issues
show
Documentation introduced by
$rawQuery is of type array|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
531 30
        $this->addSearchResultsToResultSet($response, $resultSet);
532
533 30
        $resultSet->setResponse($response);
534 30
        $resultSet->setUsedPage($currentPage);
535 30
        $resultSet->setUsedResultsPerPage($resultsPerPage);
536 30
        $resultSet->setUsedAdditionalFilters($this->getAdditionalFilters());
537 30
        $resultSet->setUsedSearch($this->search);
538
539 30
        return $this->handleSearchHook('afterSearch', $resultSet);
540
    }
541
542
    /**
543
     * Retrieves a single document from solr by document id.
544
     *
545
     * @param string $documentId
546
     * @return SearchResult
547
     */
548 1
    public function getDocumentById($documentId)
549
    {
550
        /* @var $query Query */
551 1
        $query = GeneralUtility::makeInstance(Query::class, $documentId);
552 1
        $query->setQueryFieldsFromString('id');
553
554 1
        $response = $this->search->search($query, 0, 1);
555 1
        $this->processResponse($documentId, $query, $response);
556
557 1
        $resultDocument = isset($response->response->docs[0]) ? $response->response->docs[0] : null;
558 1
        return $resultDocument;
559
    }
560
561
    /**
562
     * This method is used to call the registered hooks during the search execution.
563
     *
564
     * @param string $eventName
565
     * @param SearchResultSet $resultSet
566
     * @return SearchResultSet
567
     */
568 33
    private function handleSearchHook($eventName, SearchResultSet $resultSet)
569
    {
570 33
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName])) {
571 33
            return $resultSet;
572
        }
573
574
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) {
575
            $afterSearchProcessor = GeneralUtility::getUserObj($classReference);
576
            if ($afterSearchProcessor instanceof SearchResultSetProcessor) {
577
                $afterSearchProcessor->process($resultSet);
578
            }
579
        }
580
581
        return $resultSet;
582
    }
583
584
    /**
585
     * @return SearchResultSet
586
     */
587 19
    public function getLastResultSet()
588
    {
589 19
        return $this->lastResultSet;
590
    }
591
592
    /**
593
     * This method returns true when the last search was executed with an empty query
594
     * string or whitespaces only. When no search was triggered it will return false.
595
     *
596
     * @return bool
597
     */
598 25
    public function getLastSearchWasExecutedWithEmptyQueryString()
599
    {
600 25
        $wasEmptyQueryString = false;
601 25
        if ($this->lastResultSet != null) {
602 23
            $wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString();
603
        }
604
605 25
        return $wasEmptyQueryString;
606
    }
607
608
    /**
609
     * @param int $requestedPerPage
610
     */
611
    protected function setPerPageInSession($requestedPerPage)
612
    {
613
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'tx_solr_resultsPerPage', intval($requestedPerPage));
614
    }
615
616
    /**
617
     * @return mixed
618
     */
619 23
    protected function getPerPageFromSession()
620
    {
621 23
        return $GLOBALS['TSFE']->fe_user->getKey('ses', 'tx_solr_resultsPerPage');
622
    }
623
624
    /**
625
     * @return bool
626
     */
627 2
    protected function getInitialSearchIsConfigured()
628
    {
629 2
        return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery();
630
    }
631
632
    /**
633
     * @return mixed
634
     */
635 23
    protected function getRegisteredSearchComponents()
636
    {
637 23
        return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents();
638
    }
639
640
    /**
641
     * This method is used to reference the SearchResult object from the response in the SearchResultSet object.
642
     *
643
     * @param \Apache_Solr_Response $response
644
     * @param SearchResultSet $resultSet
645
     */
646 30
    protected function addSearchResultsToResultSet($response, $resultSet)
647
    {
648 30
        if (!is_array($response->response->docs)) {
649 5
            return;
650
        }
651
652 25
        foreach ($response->response->docs as $searchResult) {
653 23
            $resultSet->addSearchResult($searchResult);
654
        }
655 25
    }
656
}
657