Completed
Push — master ( fb7724...2be180 )
by Timo
05:13
created

SearchResultSetService::getDocumentById()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 1
crap 2
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 45
    /**
104
     * @param TypoScriptConfiguration $configuration
105 45
     * @param Search $search
106 45
     * @param SolrLogManager $solrLogManager
107 45
     * @param FrontendUserSession $frontendUserSession
108 45
     * @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 29
        $this->logger = is_null($solrLogManager) ? GeneralUtility::makeInstance(SolrLogManager::class, __CLASS__) : $solrLogManager;
115
        $this->session = is_null($frontendUserSession) ? GeneralUtility::makeInstance(FrontendUserSession::class) : $frontendUserSession;
116 29
        $this->searchResultBuilder = is_null($resultBuilder) ? GeneralUtility::makeInstance(SearchResultBuilder::class) : $resultBuilder;
117 29
    }
118
119
    /**
120
     * @param bool $useCache
121
     * @return bool
122
     */
123 29
    public function getIsSolrAvailable($useCache = true)
124
    {
125 29
        $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 37
        if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
163
            $this->logger->log(
164
                SolrLogManager::INFO,
165 37
                'Received search query',
166
                [
167 37
                    $rawQuery
168
                ]
169 37
            );
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 37
180
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
181 37
            $query->setAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
182
        }
183
184 30
        foreach ($this->getAdditionalFilters() as $additionalFilter) {
185
            $query->getFilters()->add($additionalFilter);
186
        }
187 37
188 3
        return $query;
189
    }
190
191 37
    /**
192 2
     * @param Query $query
193
     * @param SearchRequest $searchRequest
194
     */
195 37
    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 37
203
            if ($searchComponent instanceof QueryAware) {
204 37
                $searchComponent->setQuery($query);
205
            }
206 37
207
            if ($searchComponent instanceof SearchRequestAware) {
208 31
                $searchComponent->setSearchRequest($searchRequest);
209
            }
210 31
211 31
            $searchComponent->initializeSearchComponent();
212
        }
213
    }
214 31
215 30
    /**
216
     * Returns the number of results per Page.
217
     *
218 31
     * 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 37
     *
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 37
        }
232
233 37
        $defaultResultsPerPage = $this->typoScriptConfiguration->getSearchResultsPerPage();
234 37
        $currentNumberOfResultsShown = $defaultResultsPerPage;
235 37
        if ($this->session->getHasPerPage()) {
236 4
            $sessionResultPerPage = $this->session->getPerPage();
237 4
            if (in_array($sessionResultPerPage, $perPageSwitchOptions)) {
238
                $currentNumberOfResultsShown = (int)$sessionResultPerPage;
239
            }
240 37
        }
241 37
242
        if ($this->shouldHideResultsFromInitialSearch($searchRequest)) {
243 37
            // initialize search with an empty query, which would by default return all documents
244 37
            // anyway, tell Solr to not return any result documents
245 3
            // Solr will still return facets though
246
            $currentNumberOfResultsShown = 0;
247
        }
248 37
249
        return $currentNumberOfResultsShown;
250
    }
251
252 2
    /**
253
     * Does post processing of the response.
254
     *
255 37
     * @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 39
     *
265
     * Can be overwritten:
266 39
     *
267 39
     * $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] = ''
268
     *
269 39
     * to use a custom result object.
270 39
     *
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 39
            // when variant are enable and the index is empty, we get a parse exception, because of a
280
            // Apache Solr Bug.
281 39
            // 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 39
            $response->facet_counts = [];
292
293
            $documents = [];
294
        }
295
296
        if (!is_array($documents)) {
297
            return;
298
        }
299 39
300
        foreach ($documents as $key => $originalDocument) {
301 39
            $result = $this->searchResultBuilder->fromApacheSolrDocument($originalDocument);
302 5
            $documents[$key] = $result;
303
        }
304
305 34
        $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 31
    }
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 39
     *
352
     * @return array
353
     */
354 39
    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 39
            }
374 5
375
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
376
            if ($filterIsArray) {
377 34
                continue;
378 28
            }
379 28
380
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
381
            if ($hasSubConfiguration) {
382 34
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
383 34
            }
384
385
            $this->additionalFilters[$filterKey] = $filter;
386
        }
387
388
        return $this->additionalFilters;
389
    }
390
391
    /**
392
     * Performs a search and returns a SearchResultSet.
393 28
     *
394
     * @param SearchRequest $searchRequest
395 28
     * @return SearchResultSet
396 28
     */
397 28
    public function search(SearchRequest $searchRequest)
398
    {
399
        /** @var $resultSet SearchResultSet */
400
        $resultSetClass = $this->getResultSetClassName();
401 28
        $resultSet = GeneralUtility::makeInstance($resultSetClass);
402
        $resultSet->setUsedSearchRequest($searchRequest);
403
        $this->lastResultSet = $resultSet;
404
405
        $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
406
407 28
        if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
408
            // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
409 28
            return $resultSet;
410 28
        }
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 39
417
        $rawQuery = $searchRequest->getRawUserQuery();
418 39
        $resultsPerPage = $this->getNumberOfResultsPerPage($searchRequest);
419 39
        $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 37
429
        $offSet = $currentPage * $resultsPerPage;
430 37
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 37
441
        $this->processResponse($response);
442 37
        $this->addSearchResultsToResultSet($response, $resultSet);
443 37
444 35
        $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 42
460
        return $this->handleSearchHook('afterSearch', $resultSet);
461
    }
462 42
463 2
    /**
464
     * @param SearchResultSet $searchResultSet
465
     * @return SearchResultSet
466 42
     */
467 42
    protected function getAutoCorrection(SearchResultSet $searchResultSet)
468 40
    {
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 39
            $runs++;
503
504
            $correction = $suggestion->getSuggestion();
505 39
            $initialQuery = $searchRequest->getRawUserQuery();
506 39
507 39
            $searchRequest->setRawQueryString($correction);
508 39
            $searchResultSet = $this->search($searchRequest);
509
            if ($searchResultSet->getAllResultCount() > 0) {
510 39
                $searchResultSet->setIsAutoCorrected(true);
511
                $searchResultSet->setCorrectedQueryString($correction);
512 39
                $searchResultSet->setInitialQueryString($initialQuery);
513
                break;
514 2
            }
515
516
            if ($runs > $maximumRuns) {
517 37
                break;
518
            }
519
        }
520
        return $searchResultSet;
521
    }
522 37
523 37
    /**
524 37
     * Allows to modify a query before eventually handing it over to Solr.
525 37
     *
526 37
     * @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 37
     * @param Search $search The search, relevant in the current context
529
     * @throws \UnexpectedValueException
530 37
     * @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 37
        // 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 37
                $queryModifier = GeneralUtility::getUserObj($classReference);
538 37
539 37
                if ($queryModifier instanceof Modifier) {
540
                    if ($queryModifier instanceof SearchAware) {
541 37
                        $queryModifier->setSearch($search);
542
                    }
543
544 2
                    if ($queryModifier instanceof SearchRequestAware) {
545
                        $queryModifier->setSearchRequest($searchRequest);
546
                    }
547 37
548
                    $query = $queryModifier->modifyQuery($query);
549 37
                } else {
550
                    throw new \UnexpectedValueException(
551 37
                        get_class($queryModifier) . ' must implement interface ' . Modifier::class,
552 37
                        1310387414
553 37
                    );
554 37
                }
555 37
            }
556
        }
557
558 37
        return $query;
559 37
    }
560
561 37
    /**
562
     * Retrieves a single document from solr by document id.
563
     *
564
     * @param string $documentId
565
     * @return SearchResult
566
     */
567
    public function getDocumentById($documentId)
568
    {
569
        /* @var $query Query */
570
        $query = GeneralUtility::makeInstance(Query::class, $documentId);
571
        $query->setQueryFields(QueryFields::fromString('id'));
572
573 37
        $response = $this->search->search($query, 0, 1);
574
        $this->processResponse($response);
575
576 37
        $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 30
        return $resultDocument;
578 30
    }
579
580 30
    /**
581 30
     * This method is used to call the registered hooks during the search execution.
582
     *
583
     * @param string $eventName
584
     * @param SearchResultSet $resultSet
585 30
     * @return SearchResultSet
586 30
     */
587
    private function handleSearchHook($eventName, SearchResultSet $resultSet)
588
    {
589 30
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName])) {
590
            return $resultSet;
591
        }
592
593 30
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) {
594
            $afterSearchProcessor = GeneralUtility::getUserObj($classReference);
595
            if ($afterSearchProcessor instanceof SearchResultSetProcessor) {
596
                $afterSearchProcessor->process($resultSet);
597
            }
598
        }
599 37
600
        return $resultSet;
601
    }
602
603
    /**
604
     * @return SearchResultSet
605
     */
606
    public function getLastResultSet()
607
    {
608
        return $this->lastResultSet;
609
    }
610
611
    /**
612
     * This method returns true when the last search was executed with an empty query
613 37
     * string or whitespaces only. When no search was triggered it will return false.
614
     *
615
     * @return bool
616 37
     */
617
    public function getLastSearchWasExecutedWithEmptyQueryString()
618
    {
619
        $wasEmptyQueryString = false;
620
        if ($this->lastResultSet != null) {
621
            $wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString();
622
        }
623
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
    /**
636
     * @return mixed
637
     */
638
    protected function getRegisteredSearchComponents()
639
    {
640
        return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents();
641
    }
642 37
643
    /**
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
     * @param SearchResultSet $resultSet
648
     */
649
    protected function addSearchResultsToResultSet($response, $resultSet)
650 2
    {
651
        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 2
        }
654 2
655
        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 2
            $resultSet->addSearchResult($searchResult);
657 2
        }
658
    }
659 2
660 2
    /**
661
     * @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