Passed
Push — master ( fb7724...8efec3 )
by Timo
04:27
created

addExpandedDocumentsFromVariants()   D

Complexity

Conditions 10
Paths 9

Size

Total Lines 39
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 10

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 39
ccs 14
cts 14
cp 1
rs 4.8196
cc 10
eloc 22
nc 9
nop 1
crap 10

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Session\FrontendUserSession;
41
use TYPO3\CMS\Core\Utility\GeneralUtility;
42
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
43
use Apache_Solr_ParserException;
44
45
/**
46
 * The SearchResultSetService is responsible to build a SearchResultSet from a SearchRequest.
47
 * It encapsulates the logic to trigger a search in order to be able to reuse it in multiple places.
48
 *
49
 * @author Timo Schmidt <[email protected]>
50
 */
51
class SearchResultSetService
52
{
53
    /**
54
     * Additional filters, which will be added to the query, as well as to
55
     * suggest queries.
56
     *
57
     * @var array
58
     */
59
    protected $additionalFilters = [];
60
61
    /**
62
     * Track, if the number of results per page has been changed by the current request
63
     *
64
     * @var bool
65
     */
66
    protected $resultsPerPageChanged = false;
67
68
    /**
69
     * @var Search
70
     */
71
    protected $search;
72
73
    /**
74
     * @var SearchResultSet
75
     */
76
    protected $lastResultSet = null;
77
78
    /**
79
     * @var boolean
80
     */
81
    protected $isSolrAvailable = false;
82
83
    /**
84
     * @var TypoScriptConfiguration
85
     */
86
    protected $typoScriptConfiguration;
87
88
    /**
89
     * @var SolrLogManager;
90
     */
91
    protected $logger = null;
92
93
    /**
94
     * @var FrontendUserSession
95
     */
96
    protected $session = null;
97
98
    /**
99
     * @var SearchResultBuilder
100
     */
101
    protected $searchResultBuilder;
102
103 46
    /**
104
     * @param TypoScriptConfiguration $configuration
105 46
     * @param Search $search
106 46
     * @param SolrLogManager $solrLogManager
107 46
     * @param FrontendUserSession $frontendUserSession
108 46
     * @param SearchResultBuilder $resultBuilder
109
     */
110
    public function __construct(TypoScriptConfiguration $configuration, Search $search, SolrLogManager $solrLogManager = null, FrontendUserSession $frontendUserSession = null, SearchResultBuilder $resultBuilder = null)
111
    {
112
        $this->search = $search;
113
        $this->typoScriptConfiguration = $configuration;
114 30
        $this->logger = is_null($solrLogManager) ? GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__) : $solrLogManager;
115
        $this->session = is_null($frontendUserSession) ? GeneralUtility::makeInstance(FrontendUserSession::class) : $frontendUserSession;
116 30
        $this->searchResultBuilder = is_null($resultBuilder) ? GeneralUtility::makeInstance(SearchResultBuilder::class) : $resultBuilder;
117 30
    }
118
119
    /**
120
     * @param bool $useCache
121
     * @return bool
122
     */
123 30
    public function getIsSolrAvailable($useCache = true)
124
    {
125 30
        $this->isSolrAvailable = $this->search->ping($useCache);
126
        return $this->isSolrAvailable;
127
    }
128
129
    /**
130
     * @return bool
131
     */
132
    public function getHasSearched()
133 2
    {
134
        return $this->search->hasSearched();
135 2
    }
136
137
    /**
138
     * Retrieves the used search instance.
139
     *
140
     * @return Search
141
     */
142
    public function getSearch()
143
    {
144
        return $this->search;
145
    }
146
147
    /**
148
     * Initializes the Query object and SearchComponents and returns
149
     * the initialized query object, when a search should be executed.
150
     *
151
     * @param string|null $rawQuery
152
     * @param int $resultsPerPage
153
     * @return Query
154
     */
155
    protected function getPreparedQuery($rawQuery, $resultsPerPage)
156
    {
157
        /* @var $query Query */
158
        $query = $this->getQueryInstance($rawQuery);
159
160
        $this->applyPageSectionsRootLineFilter($query);
161
162 38
        if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
163
            $this->logger->log(
164
                SolrLogManager::INFO,
165 38
                'Received search query',
166
                [
167 38
                    $rawQuery
168
                ]
169 38
            );
170
        }
171
172
        $query->setResultsPerPage($resultsPerPage);
173
174
        if ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
175
            // empty main query, but using a "return everything"
176
            // alternative query in q.alt
177
            $query->setAlternativeQuery('*:*');
178
        }
179 38
180
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
181 38
            $query->setAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
182
        }
183
184 31
        foreach ($this->getAdditionalFilters() as $additionalFilter) {
185
            $query->getFilters()->add($additionalFilter);
186
        }
187 38
188 3
        return $query;
189
    }
190
191 38
    /**
192 2
     * @param Query $query
193
     * @param SearchRequest $searchRequest
194
     */
195 38
    protected function initializeRegisteredSearchComponents(Query $query, SearchRequest $searchRequest)
196
    {
197
        $searchComponents = $this->getRegisteredSearchComponents();
198
199
        foreach ($searchComponents as $searchComponent) {
200
            /** @var Search\SearchComponent $searchComponent */
201
            $searchComponent->setSearchConfiguration($this->typoScriptConfiguration->getSearchConfiguration());
202 38
203
            if ($searchComponent instanceof QueryAware) {
204 38
                $searchComponent->setQuery($query);
205
            }
206 38
207
            if ($searchComponent instanceof SearchRequestAware) {
208 32
                $searchComponent->setSearchRequest($searchRequest);
209
            }
210 32
211 32
            $searchComponent->initializeSearchComponent();
212
        }
213
    }
214 32
215 31
    /**
216
     * Returns the number of results per Page.
217
     *
218 32
     * Also influences how many result documents are returned by the Solr
219
     * server as the return value is used in the Solr "rows" GET parameter.
220 38
     *
221
     * @param SearchRequest $searchRequest
222
     * @return int number of results to show per page
223
     */
224
    protected function getNumberOfResultsPerPage(SearchRequest $searchRequest)
225
    {
226
        $requestedPerPage = $searchRequest->getResultsPerPage();
227
        $perPageSwitchOptions = $this->typoScriptConfiguration->getSearchResultsPerPageSwitchOptionsAsArray();
228
        if (isset($requestedPerPage) && in_array($requestedPerPage, $perPageSwitchOptions)) {
229
            $this->session->setPerPage($requestedPerPage);
0 ignored issues
show
Documentation introduced by
$requestedPerPage is of type array, but the function expects a integer.

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...
230
            $this->resultsPerPageChanged = true;
231 38
        }
232
233 38
        $defaultResultsPerPage = $this->typoScriptConfiguration->getSearchResultsPerPage();
234 38
        $currentNumberOfResultsShown = $defaultResultsPerPage;
235 38
        if ($this->session->getHasPerPage()) {
236 4
            $sessionResultPerPage = $this->session->getPerPage();
237 4
            if (in_array($sessionResultPerPage, $perPageSwitchOptions)) {
238
                $currentNumberOfResultsShown = (int)$sessionResultPerPage;
239
            }
240 38
        }
241 38
242
        if ($this->shouldHideResultsFromInitialSearch($searchRequest)) {
243 38
            // initialize search with an empty query, which would by default return all documents
244 38
            // anyway, tell Solr to not return any result documents
245 3
            // Solr will still return facets though
246
            $currentNumberOfResultsShown = 0;
247
        }
248 38
249
        return $currentNumberOfResultsShown;
250
    }
251
252 2
    /**
253
     * Does post processing of the response.
254
     *
255 38
     * @param \Apache_Solr_Response $response The search's response.
256
     */
257
    protected function processResponse(\Apache_Solr_Response $response)
258
    {
259
        $this->wrapResultDocumentInResultObject($response);
260
    }
261
262
    /**
263
     * Wrap all results document it a custom EXT:solr SearchResult object.
264 40
     *
265
     * Can be overwritten:
266 40
     *
267 40
     * $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] = ''
268
     *
269 40
     * to use a custom result object.
270 40
     *
271
     * @param \Apache_Solr_Response $response
272
     * @throws \Apache_Solr_ParserException
273
     */
274
    protected function wrapResultDocumentInResultObject(\Apache_Solr_Response $response)
275
    {
276
        try {
277
            $documents = $response->response->docs;
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...
278
        } catch (Apache_Solr_ParserException $e) {
0 ignored issues
show
Unused Code introduced by
catch (\Apache_Solr_Pars...$documents = array(); } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
279 40
            // when variant are enable and the index is empty, we get a parse exception, because of a
280
            // Apache Solr Bug.
281 40
            // see: https://github.com/TYPO3-Solr/ext-solr/issues/668
282 1
            // @todo this try/catch block can be removed after upgrading to Apache Solr 6.4
283
            if (!$this->typoScriptConfiguration->getSearchVariants()) {
284 1
                throw $e;
285 1
            }
286 1
287 1
            $response->response = new \stdClass();
288
            $response->spellcheck = [];
289
            $response->debug = [];
290
            $response->responseHeader = [];
291 40
            $response->facet_counts = [];
292
293
            $documents = [];
294
        }
295
296
        if (!is_array($documents)) {
297
            return;
298
        }
299 40
300
        foreach ($documents as $key => $originalDocument) {
301 40
            $result = $this->searchResultBuilder->fromApacheSolrDocument($originalDocument);
302 5
            $documents[$key] = $result;
303
        }
304
305 35
        $response->response->docs = $documents;
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...
306 32
    }
307
308
    /**
309 3
     * @return string
310 3
     */
311
    protected function getResultSetClassName()
312 2
    {
313 2
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName ']) ?
314
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] : SearchResultSet::class;
315
    }
316 2
317
    /**
318
     * Checks it the results should be hidden in the response.
319
     *
320 2
     * @param SearchRequest $searchRequest
321 2
     * @return bool
322
     */
323
    protected function shouldHideResultsFromInitialSearch(SearchRequest $searchRequest)
324
    {
325 2
        return ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery()) && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery() && $searchRequest->getRawUserQueryIsNull();
326 2
    }
327 2
328 2
    /**
329
     * Initializes additional filters configured through TypoScript and
330 2
     * Flexforms for use in regular queries and suggest queries.
331 2
     *
332 2
     * @param Query $query
333
     * @return void
334 2
     */
335
    protected function applyPageSectionsRootLineFilter(Query $query)
336
    {
337 3
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
338
        if (count($searchQueryFilters) <= 0) {
339
            return;
340
        }
341
342
        // special filter to limit search to specific page tree branches
343
        if (array_key_exists('__pageSections', $searchQueryFilters)) {
344
            $query->setRootlineFilter($searchQueryFilters['__pageSections']);
345
            $this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
346
        }
347
    }
348
349
    /**
350
     * Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
351 40
     *
352
     * @return array
353
     */
354 40
    public function getAdditionalFilters()
355 1
    {
356
        // when we've build the additionalFilter once, we could return them
357
        if (count($this->additionalFilters) > 0) {
358
            return $this->additionalFilters;
359
        }
360 1
361
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
362
        if (count($searchQueryFilters) <= 0) {
363
            return [];
364 1
        }
365 1
366 1
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
367 1
368 1
        // all other regular filters
369
        foreach ($searchQueryFilters as $filterKey => $filter) {
370 1
            // the __pageSections filter should not be handled as additional filter
371
            if ($filterKey === '__pageSections') {
372
                continue;
373 40
            }
374 5
375
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
376
            if ($filterIsArray) {
377 35
                continue;
378 29
            }
379 29
380
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
381
            if ($hasSubConfiguration) {
382 35
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
383 35
            }
384
385
            $this->additionalFilters[$filterKey] = $filter;
386
        }
387
388
        return $this->additionalFilters;
389
    }
390
391
    /**
392
     * Performs a search and returns a SearchResultSet.
393 29
     *
394
     * @param SearchRequest $searchRequest
395 29
     * @return SearchResultSet
396 29
     */
397 29
    public function search(SearchRequest $searchRequest)
398
    {
399
        /** @var $resultSet SearchResultSet */
400
        $resultSetClass = $this->getResultSetClassName();
401 29
        $resultSet = GeneralUtility::makeInstance($resultSetClass);
402
        $resultSet->setUsedSearchRequest($searchRequest);
403
        $this->lastResultSet = $resultSet;
404
405
        $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
406
407 29
        if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
408
            // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
409 29
            return $resultSet;
410 29
        }
411
412
        if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
413
            // the user entered an empty query string "" or "  " and empty querystring is not allowed
414
            return $resultSet;
415
        }
416 40
417
        $rawQuery = $searchRequest->getRawUserQuery();
418 40
        $resultsPerPage = $this->getNumberOfResultsPerPage($searchRequest);
419 40
        $query = $this->getPreparedQuery($rawQuery, $resultsPerPage);
420
        $this->initializeRegisteredSearchComponents($query, $searchRequest);
421
        $resultSet->setUsedQuery($query);
422
423
        $currentPage = max(0, $searchRequest->getPage());
424
        // if the number of results per page has been changed by the current request, reset the pagebrowser
425
        if ($this->resultsPerPageChanged) {
426
            $currentPage = 0;
427
        }
428 38
429
        $offSet = $currentPage * $resultsPerPage;
430 38
431
        // performing the actual search, sending the query to the Solr server
432
        $query = $this->modifyQuery($query, $searchRequest, $this->search);
433
        $response = $this->search->search($query, $offSet, null);
434
435
        if ($resultsPerPage === 0) {
436
            // when resultPerPage was forced to 0 we also set the numFound to 0 to hide results, e.g.
437
            // when results for the initial search should not be shown.
438
            $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...
439
        }
440 38
441
        $this->processResponse($response);
442 38
        $this->addSearchResultsToResultSet($response, $resultSet);
443 38
444 36
        $resultSet->setResponse($response);
445
        $resultSet->setUsedPage($currentPage);
446
        $resultSet->setUsedResultsPerPage($resultsPerPage);
447
        $resultSet->setUsedAdditionalFilters($this->getAdditionalFilters());
448 2
        $resultSet->setUsedSearch($this->search);
449
450
        /** @var $variantsProcessor VariantsProcessor */
451
        $variantsProcessor = GeneralUtility::makeInstance(VariantsProcessor::class, $this->typoScriptConfiguration, $this->searchResultBuilder);
452 2
        $variantsProcessor->process($resultSet);
453
454
        /** @var $searchResultReconstitutionProcessor ResultSetReconstitutionProcessor */
455
        $searchResultReconstitutionProcessor = GeneralUtility::makeInstance(ResultSetReconstitutionProcessor::class);
456
        $searchResultReconstitutionProcessor->process($resultSet);
457
458
        $resultSet = $this->getAutoCorrection($resultSet);
459 43
460
        return $this->handleSearchHook('afterSearch', $resultSet);
461
    }
462 43
463 2
    /**
464
     * @param SearchResultSet $searchResultSet
465
     * @return SearchResultSet
466 43
     */
467 43
    protected function getAutoCorrection(SearchResultSet $searchResultSet)
468 41
    {
469
        // no secondary search configured
470
        if (!$this->typoScriptConfiguration->getSearchSpellcheckingSearchUsingSpellCheckerSuggestion()) {
471 2
            return $searchResultSet;
472
        }
473
474 2
        // more then zero results
475
        if ($searchResultSet->getAllResultCount() > 0) {
476 2
            return $searchResultSet;
477
        }
478
479
        // no corrections present
480 2
        if (!$searchResultSet->getHasSpellCheckingSuggestions()) {
481 2
            return $searchResultSet;
482
        }
483
484
        $searchResultSet = $this->peformAutoCorrection($searchResultSet);
485 2
486 2
        return $searchResultSet;
487
    }
488
489
    /**
490 2
     * @param SearchResultSet $searchResultSet
491
     * @return SearchResultSet
492
     */
493 2
    protected function peformAutoCorrection(SearchResultSet $searchResultSet)
494
    {
495
        $searchRequest = $searchResultSet->getUsedSearchRequest();
496
        $suggestions = $searchResultSet->getSpellCheckingSuggestions();
497
498
        $maximumRuns = $this->typoScriptConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry(1);
499
        $runs = 0;
500
501
        foreach ($suggestions as $suggestion) {
502 40
            $runs++;
503
504
            $correction = $suggestion->getSuggestion();
505 40
            $initialQuery = $searchRequest->getRawUserQuery();
506 40
507 40
            $searchRequest->setRawQueryString($correction);
508 40
            $searchResultSet = $this->search($searchRequest);
509
            if ($searchResultSet->getAllResultCount() > 0) {
510 40
                $searchResultSet->setIsAutoCorrected(true);
511
                $searchResultSet->setCorrectedQueryString($correction);
512 40
                $searchResultSet->setInitialQueryString($initialQuery);
513
                break;
514 2
            }
515
516
            if ($runs > $maximumRuns) {
517 38
                break;
518
            }
519
        }
520
        return $searchResultSet;
521
    }
522 38
523 38
    /**
524 38
     * Allows to modify a query before eventually handing it over to Solr.
525 38
     *
526 38
     * @param Query $query The current query before it's being handed over to Solr.
527
     * @param SearchRequest $searchRequest The searchRequest, relevant in the current context
528 38
     * @param Search $search The search, relevant in the current context
529
     * @throws \UnexpectedValueException
530 38
     * @return Query The modified query that is actually going to be given to Solr.
531 4
     */
532
    protected function modifyQuery(Query $query, SearchRequest $searchRequest, Search $search)
533
    {
534 38
        // hook to modify the search query
535
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery'])) {
536
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery'] as $classReference) {
537 38
                $queryModifier = GeneralUtility::getUserObj($classReference);
538 38
539 38
                if ($queryModifier instanceof Modifier) {
540
                    if ($queryModifier instanceof SearchAware) {
541 38
                        $queryModifier->setSearch($search);
542
                    }
543
544 2
                    if ($queryModifier instanceof SearchRequestAware) {
545
                        $queryModifier->setSearchRequest($searchRequest);
546
                    }
547 38
548
                    $query = $queryModifier->modifyQuery($query);
549 38
                } else {
550
                    throw new \UnexpectedValueException(
551 38
                        get_class($queryModifier) . ' must implement interface ' . Modifier::class,
552 38
                        1310387414
553 38
                    );
554 38
                }
555 38
            }
556
        }
557
558 38
        return $query;
559 38
    }
560
561 38
    /**
562
     * Retrieves a single document from solr by document id.
563 38
     *
564
     * @param string $documentId
565
     * @return SearchResult
566
     */
567
    public function getDocumentById($documentId)
568
    {
569
        /* @var $query Query */
570 38
        $query = GeneralUtility::makeInstance(Query::class, $documentId);
571
        $query->setQueryFields(QueryFields::fromString('id'));
572
573 38
        $response = $this->search->search($query, 0, 1);
574 37
        $this->processResponse($response);
575
576
        $resultDocument = isset($response->response->docs[0]) ? $response->response->docs[0] : null;
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...
577
        return $resultDocument;
578 1
    }
579 1
580
    /**
581
     * This method is used to call the registered hooks during the search execution.
582
     *
583 1
     * @param string $eventName
584
     * @param SearchResultSet $resultSet
585
     * @return SearchResultSet
586
     */
587 1
    private function handleSearchHook($eventName, SearchResultSet $resultSet)
588
    {
589 1
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName])) {
590
            return $resultSet;
591
        }
592
593
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) {
594
            $afterSearchProcessor = GeneralUtility::getUserObj($classReference);
595
            if ($afterSearchProcessor instanceof SearchResultSetProcessor) {
596 1
                $afterSearchProcessor->process($resultSet);
597
            }
598 1
        }
599 1
600
        return $resultSet;
601 1
    }
602 1
603
    /**
604 1
     * @return SearchResultSet
605 1
     */
606
    public function getLastResultSet()
607 1
    {
608 1
        return $this->lastResultSet;
609
    }
610 1
611 1
    /**
612 1
     * This method returns true when the last search was executed with an empty query
613 1
     * string or whitespaces only. When no search was triggered it will return false.
614 1
     *
615 1
     * @return bool
616 1
     */
617
    public function getLastSearchWasExecutedWithEmptyQueryString()
618
    {
619
        $wasEmptyQueryString = false;
620
        if ($this->lastResultSet != null) {
621
            $wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString();
622
        }
623 1
624
        return $wasEmptyQueryString;
625
    }
626
627
    /**
628
     * @return bool
629
     */
630
    protected function getInitialSearchIsConfigured()
631
    {
632
        return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery();
633
    }
634
635 38
    /**
636
     * @return mixed
637
     */
638 38
    protected function getRegisteredSearchComponents()
639 31
    {
640 31
        return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents();
641
    }
642 31
643 31
    /**
644
     * This method is used to reference the SearchResult object from the response in the SearchResultSet object.
645
     *
646
     * @param \Apache_Solr_Response $response
647 31
     * @param SearchResultSet $resultSet
648 31
     */
649
    protected function addSearchResultsToResultSet($response, $resultSet)
650
    {
651 31
        if (!is_array($response->response->docs)) {
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...
652
            return;
653
        }
654
655 31
        foreach ($response->response->docs as $searchResult) {
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...
656
            $resultSet->addSearchResult($searchResult);
657
        }
658
    }
659
660
    /**
661 38
     * @param string $rawQuery
662
     * @return Query|object
663
     */
664
    protected function getQueryInstance($rawQuery)
665
    {
666
        $query = GeneralUtility::makeInstance(Query::class, $rawQuery, $this->typoScriptConfiguration);
667
        return $query;
668
    }
669
670
}
671