Completed
Pull Request — master (#808)
by
unknown
26:57 queued 23:22
created

SearchResultSetService   D

Complexity

Total Complexity 93

Size/Duplication

Total Lines 630
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 83.06%

Importance

Changes 0
Metric Value
wmc 93
lcom 1
cbo 10
dl 0
loc 630
ccs 201
cts 242
cp 0.8306
rs 4.7506
c 0
b 0
f 0

31 Methods

Rating   Name   Duplication   Size   Complexity  
B getNumberOfResultsPerPage() 0 25 6
B processResponse() 0 21 5
D addExpandedDocumentsFromVariants() 0 39 10
A __construct() 0 6 1
A getParentPlugin() 0 4 1
A getHasSearched() 0 4 1
A getIsSolrAvailable() 0 5 1
A getSearch() 0 4 1
A setUsePluginAwareComponents() 0 4 1
A getUsePluginAwareComponents() 0 4 1
A setUseQueryAwareComponents() 0 4 1
A getUseQueryAwareComponents() 0 4 1
B getPreparedQuery() 0 31 6
B initializeRegisteredSearchComponents() 0 19 6
A getInitialSearchIsConfigured() 0 4 4
A wrapApacheSolrDocumentInResultObject() 0 10 2
A getResultClassName() 0 5 2
A getResultSetClassName() 0 5 2
B shouldHideResultsFromInitialSearch() 0 4 5
A getDocumentById() 0 12 2
A getLastResultSet() 0 4 1
A setPerPageInSession() 0 4 1
A getPerPageFromSession() 0 4 1
A getRegisteredSearchComponents() 0 4 1
B wrapResultDocumentInResultObject() 0 31 5
A applyPageSectionsRootLineFilter() 0 13 3
C getAdditionalFilters() 0 36 7
B search() 0 47 6
A handleSearchHook() 0 15 4
A getLastSearchWasExecutedWithEmptyQueryString() 0 9 2
A addSearchResultsToResultSet() 0 10 3

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\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 37
    public function __construct(TypoScriptConfiguration $configuration, Search $search, AbstractPlugin $parentPlugin = null)
105
    {
106 37
        $this->search = $search;
107 37
        $this->typoScriptConfiguration = $configuration;
108 37
        $this->parentPlugin = $parentPlugin;
109 37
    }
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 31
    protected function getPreparedQuery($rawQuery, $resultsPerPage)
188
    {
189
        /* @var $query Query */
190 31
        $query = GeneralUtility::makeInstance(Query::class, $rawQuery);
191
192 31
        $this->applyPageSectionsRootLineFilter($query);
193
194 31
        if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
195
            GeneralUtility::devLog('received search query', 'solr', 0, array($rawQuery));
196
        }
197
198 31
        $query->setResultsPerPage($resultsPerPage);
199
200 31
        $this->initializeRegisteredSearchComponents($query);
201
202 31
        if ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
203
            // empty main query, but using a "return everything"
204
            // alternative query in q.alt
205 24
            $query->setAlternativeQuery('*:*');
206 24
        }
207
208 31
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
209 3
            $query->setAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
210 3
        }
211
212 31
        foreach ($this->getAdditionalFilters() as $additionalFilter) {
213 2
            $query->addFilter($additionalFilter);
214 31
        }
215
216 31
        return $query;
217
    }
218
219
    /**
220
     * @param Query $query
221
     */
222 31
    protected function initializeRegisteredSearchComponents(Query $query)
223
    {
224 31
        $searchComponents = $this->getRegisteredSearchComponents();
225
226 31
        foreach ($searchComponents as $searchComponent) {
227
            /** @var Search\SearchComponent $searchComponent */
228 25
            $searchComponent->setSearchConfiguration($this->typoScriptConfiguration->getSearchConfiguration());
229
230 25
            if ($searchComponent instanceof QueryAware && $this->useQueryAwareComponents) {
231 25
                $searchComponent->setQuery($query);
232 25
            }
233
234 25
            if ($searchComponent instanceof PluginAware && $this->usePluginAwareComponents) {
235
                $searchComponent->setParentPlugin($this->parentPlugin);
236
            }
237
238 25
            $searchComponent->initializeSearchComponent();
239 31
        }
240 31
    }
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 31
    protected function getNumberOfResultsPerPage($rawQuery, $requestedPerPage = null)
253
    {
254 31
        $perPageSwitchOptions = $this->typoScriptConfiguration->getSearchResultsPerPageSwitchOptionsAsArray();
255 31
        if (isset($requestedPerPage) && in_array($requestedPerPage, $perPageSwitchOptions)) {
256 1
            $this->setPerPageInSession($requestedPerPage);
257 1
            $this->resultsPerPageChanged = true;
258 1
        }
259
260 31
        $defaultResultsPerPage = $this->typoScriptConfiguration->getSearchResultsPerPage();
261 31
        $sessionResultPerPage = $this->getPerPageFromSession();
262
263 31
        $currentNumberOfResultsShown = $defaultResultsPerPage;
264 31
        if (!is_null($sessionResultPerPage) && in_array($sessionResultPerPage, $perPageSwitchOptions)) {
265
            $currentNumberOfResultsShown = (int)$sessionResultPerPage;
266
        }
267
268 31
        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 31
        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 32
    protected function processResponse($rawQuery, Query $query, \Apache_Solr_Response &$response)
286
    {
287 32
        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 32
        $this->wrapResultDocumentInResultObject($response);
295 32
        $this->addExpandedDocumentsFromVariants($response);
296
297 32
        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 21
                }
303 21
            }
304 21
        }
305 32
    }
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 32
    protected function addExpandedDocumentsFromVariants(\Apache_Solr_Response &$response)
314
    {
315 32
        if (!is_array($response->response->docs)) {
316 5
            return;
317
        }
318
319 27
        if (!$this->typoScriptConfiguration->getSearchVariants()) {
320 24
            return;
321
        }
322
323 3
        $variantsField = $this->typoScriptConfiguration->getSearchVariantsField();
324 3
        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 2
                }
344 2
                $variantSearchResult = $this->wrapApacheSolrDocumentInResultObject($variantDocument);
345 2
                $variantSearchResult->setIsVariant(true);
346 2
                $variantSearchResult->setVariantParent($resultDocument);
347
348 2
                $resultDocument->addVariant($variantSearchResult);
349 2
            }
350 3
        }
351 3
    }
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 \Apache_Solr_ParserException
364
     */
365 32
    protected function wrapResultDocumentInResultObject(\Apache_Solr_Response &$response)
366
    {
367
        try {
368 32
            $documents = $response->response->docs;
369 32
        } catch (\Apache_Solr_ParserException $e) {
370
            // when variant are enable and the index is empty, we get a parse exception, because of a
371
            // Apache Solr Bug.
372
            // see: https://github.com/TYPO3-Solr/ext-solr/issues/668
373
            // @todo this try/catch block can be removed after upgrading to Apache Solr 6.4
374 1
            if (!$this->typoScriptConfiguration->getSearchVariants()) {
375
                throw $e;
376
            }
377
378 1
            $response->response = new \stdClass();
379 1
            $response->spellcheck = [];
380 1
            $response->debug = [];
381 1
            $response->responseHeader = [];
382 1
            $documents = [];
383
        }
384
385 32
        if (!is_array($documents)) {
386 5
            return;
387
        }
388
389 27
        foreach ($documents as $key => $originalDocument) {
390 24
            $result = $this->wrapApacheSolrDocumentInResultObject($originalDocument);
391 24
            $documents[$key] = $result;
392 27
        }
393
394 27
        $response->response->docs = $documents;
395 27
    }
396
397
    /**
398
     * This method is used to wrap the \Apache_Solr_Document instance in an instance of the configured SearchResult
399
     * class.
400
     *
401
     * @param \Apache_Solr_Document $originalDocument
402
     * @throws \InvalidArgumentException
403
     * @return SearchResult
404
     */
405 24
    protected function wrapApacheSolrDocumentInResultObject(\Apache_Solr_Document $originalDocument)
406
    {
407 24
        $searchResultClassName = $this->getResultClassName();
408 24
        $result = GeneralUtility::makeInstance($searchResultClassName, $originalDocument);
409 24
        if (!$result instanceof SearchResult) {
410
            throw new \InvalidArgumentException('Could not create result object with class: ' . (string)$searchResultClassName, 1470037679);
411
        }
412
413 24
        return $result;
414
    }
415
416
    /**
417
     * @return string
418
     */
419 24
    protected function getResultClassName()
420
    {
421 24
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName ']) ?
422 24
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] : SearchResult::class;
423
    }
424
425
    /**
426
     * @return string
427
     */
428 34
    protected function getResultSetClassName()
429
    {
430 34
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName ']) ?
431 34
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] : SearchResultSet::class;
432
    }
433
434
    /**
435
     * Checks it the results should be hidden in the response.
436
     *
437
     * @param string $rawQuery
438
     * @return bool
439
     */
440 32
    protected function shouldHideResultsFromInitialSearch($rawQuery)
441
    {
442 32
        return ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery()) && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery() && empty($rawQuery);
443
    }
444
445
    /**
446
     * Initializes additional filters configured through TypoScript and
447
     * Flexforms for use in regular queries and suggest queries.
448
     *
449
     * @param Query $query
450
     * @return void
451
     */
452 31
    protected function applyPageSectionsRootLineFilter(Query $query)
453
    {
454 31
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
455 31
        if (count($searchQueryFilters) <= 0) {
456 29
            return;
457
        }
458
459
        // special filter to limit search to specific page tree branches
460 2
        if (array_key_exists('__pageSections', $searchQueryFilters)) {
461
            $query->setRootlineFilter($searchQueryFilters['__pageSections']);
462
            $this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
463
        }
464 2
    }
465
466
    /**
467
     * Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
468
     *
469
     * @return array
470
     */
471 36
    public function getAdditionalFilters()
472
    {
473
        // when we've build the additionalFilter once, we could return them
474 36
        if (count($this->additionalFilters) > 0) {
475 2
            return $this->additionalFilters;
476
        }
477
478 36
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
479 36
        if (count($searchQueryFilters) <= 0) {
480 33
            return array();
481
        }
482
483 3
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
484
485
        // all other regular filters
486 3
        foreach ($searchQueryFilters as $filterKey => $filter) {
487
            // the __pageSections filter should not be handled as additional filter
488 3
            if ($filterKey === '__pageSections') {
489
                continue;
490
            }
491
492 3
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
493 3
            if ($filterIsArray) {
494
                continue;
495
            }
496
497 3
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
498 3
            if ($hasSubConfiguration) {
499
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
500
            }
501
502 3
            $this->additionalFilters[$filterKey] = $filter;
503 3
        }
504
505 3
        return $this->additionalFilters;
506
    }
507
508
    /**
509
     * Performs a search and returns a SearchResultSet.
510
     *
511
     * @param SearchRequest $searchRequest
512
     * @return SearchResultSet
513
     */
514 34
    public function search(SearchRequest $searchRequest)
515
    {
516
        /** @var $resultSet SearchResultSet */
517 34
        $resultSetClass = $this->getResultSetClassName();
518 34
        $resultSet = GeneralUtility::makeInstance($resultSetClass);
519 34
        $resultSet->setUsedSearchRequest($searchRequest);
520 34
        $this->lastResultSet = $resultSet;
521
522 34
        $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
523
524 34
        if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
525
            // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
526 1
            return $resultSet;
527
        }
528
529 33
        if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
530
            // the user entered an empty query string "" or "  " and empty querystring is not allowed
531 2
            return $resultSet;
532
        }
533
534 31
        $rawQuery = $searchRequest->getRawUserQuery();
535 31
        $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...
536 31
        $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...
537
538 31
        $resultSet->setUsedQuery($query);
539
540 31
        $currentPage = max(0, $searchRequest->getPage());
541
        // if the number of results per page has been changed by the current request, reset the pagebrowser
542 31
        if ($this->resultsPerPageChanged) {
543 1
            $currentPage = 0;
544 1
        }
545
546 31
        $offSet = $currentPage * $resultsPerPage;
547
        // performing the actual search, sending the query to the Solr server
548 31
        $response = $this->search->search($query, $offSet, null);
549
550 31
        $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...
551 31
        $this->addSearchResultsToResultSet($response, $resultSet);
552
553 31
        $resultSet->setResponse($response);
554 31
        $resultSet->setUsedPage($currentPage);
555 31
        $resultSet->setUsedResultsPerPage($resultsPerPage);
556 31
        $resultSet->setUsedAdditionalFilters($this->getAdditionalFilters());
557 31
        $resultSet->setUsedSearch($this->search);
558
559 31
        return $this->handleSearchHook('afterSearch', $resultSet);
560
    }
561
562
    /**
563
     * Retrieves a single document from solr by document id.
564
     *
565
     * @param string $documentId
566
     * @return SearchResult
567
     */
568 1
    public function getDocumentById($documentId)
569
    {
570
        /* @var $query Query */
571 1
        $query = GeneralUtility::makeInstance(Query::class, $documentId);
572 1
        $query->setQueryFieldsFromString('id');
573
574 1
        $response = $this->search->search($query, 0, 1);
575 1
        $this->processResponse($documentId, $query, $response);
576
577 1
        $resultDocument = isset($response->response->docs[0]) ? $response->response->docs[0] : null;
578 1
        return $resultDocument;
579
    }
580
581
    /**
582
     * This method is used to call the registered hooks during the search execution.
583
     *
584
     * @param string $eventName
585
     * @param SearchResultSet $resultSet
586
     * @return SearchResultSet
587
     */
588 34
    private function handleSearchHook($eventName, SearchResultSet $resultSet)
589
    {
590 34
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName])) {
591 34
            return $resultSet;
592
        }
593
594
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) {
595
            $afterSearchProcessor = GeneralUtility::getUserObj($classReference);
596
            if ($afterSearchProcessor instanceof SearchResultSetProcessor) {
597
                $afterSearchProcessor->process($resultSet);
598
            }
599
        }
600
601
        return $resultSet;
602
    }
603
604
    /**
605
     * @return SearchResultSet
606
     */
607 19
    public function getLastResultSet()
608
    {
609 19
        return $this->lastResultSet;
610
    }
611
612
    /**
613
     * This method returns true when the last search was executed with an empty query
614
     * string or whitespaces only. When no search was triggered it will return false.
615
     *
616
     * @return bool
617
     */
618 25
    public function getLastSearchWasExecutedWithEmptyQueryString()
619
    {
620 25
        $wasEmptyQueryString = false;
621 25
        if ($this->lastResultSet != null) {
622 23
            $wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString();
623 23
        }
624
625 25
        return $wasEmptyQueryString;
626
    }
627
628
    /**
629
     * @param int $requestedPerPage
630
     */
631
    protected function setPerPageInSession($requestedPerPage)
632
    {
633
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'tx_solr_resultsPerPage', intval($requestedPerPage));
634
    }
635
636
    /**
637
     * @return mixed
638
     */
639 24
    protected function getPerPageFromSession()
640
    {
641 24
        return $GLOBALS['TSFE']->fe_user->getKey('ses', 'tx_solr_resultsPerPage');
642
    }
643
644
    /**
645
     * @return bool
646
     */
647 2
    protected function getInitialSearchIsConfigured()
648
    {
649 2
        return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery();
650
    }
651
652
    /**
653
     * @return mixed
654
     */
655 24
    protected function getRegisteredSearchComponents()
656
    {
657 24
        return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents();
658
    }
659
660
    /**
661
     * This method is used to reference the SearchResult object from the response in the SearchResultSet object.
662
     *
663
     * @param \Apache_Solr_Response $response
664
     * @param SearchResultSet $resultSet
665
     */
666 31
    protected function addSearchResultsToResultSet($response, $resultSet)
667
    {
668 31
        if (!is_array($response->response->docs)) {
669 5
            return;
670
        }
671
672 26
        foreach ($response->response->docs as $searchResult) {
673 23
            $resultSet->addSearchResult($searchResult);
674 26
        }
675 26
    }
676
}
677