Completed
Push — master ( 4904bb...48f77b )
by Timo
11s
created

SearchResultSetService::getParentPlugin()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
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
use Apache_Solr_ParserException;
41
42
/**
43
 * The SearchResultSetService is responsible to build a SearchResultSet from a SearchRequest.
44
 * It encapsulates the logic to trigger a search in order to be able to reuse it in multiple places.
45
 *
46
 * @author Timo Schmidt <[email protected]>
47
 */
48
class SearchResultSetService implements SingletonInterface
49
{
50
    /**
51
     * Additional filters, which will be added to the query, as well as to
52
     * suggest queries.
53
     *
54
     * @var array
55
     */
56
    protected $additionalFilters = [];
57
58
    /**
59
     * Track, if the number of results per page has been changed by the current request
60
     *
61
     * @var bool
62
     */
63
    protected $resultsPerPageChanged = false;
64
65
    /**
66
     * @var \ApacheSolrForTypo3\Solr\Search
67
     */
68
    protected $search;
69
70
    /**
71
     * @var SearchResultSet
72
     */
73
    protected $lastResultSet = null;
74
75
    /**
76
     * @var AbstractPlugin
77
     */
78
    protected $parentPlugin;
79
80
    /**
81
     * @var bool
82
     */
83
    protected $useQueryAwareComponents = true;
84
85
    /**
86
     * @var bool
87
     */
88
    protected $usePluginAwareComponents = true;
89
90
    /**
91
     * @var
92
     */
93
    protected $isSolrAvailable = false;
94
95
    /**
96
     * @var TypoScriptConfiguration
97
     */
98
    protected $typoScriptConfiguration;
99
100
    /**
101
     * @param TypoScriptConfiguration $configuration
102
     * @param Search $search
103
     * @param AbstractPlugin $parentPlugin (optional parent plugin, needed for plugin aware components)
104
     */
105 37
    public function __construct(TypoScriptConfiguration $configuration, Search $search, AbstractPlugin $parentPlugin = null)
106
    {
107 37
        $this->search = $search;
108 37
        $this->typoScriptConfiguration = $configuration;
109 37
        $this->parentPlugin = $parentPlugin;
110 37
    }
111
112
    /**
113
     * @return AbstractPlugin
114
     */
115 1
    public function getParentPlugin()
116
    {
117 1
        return $this->parentPlugin;
118
    }
119
120
    /**
121
     * @param bool $useCache
122
     * @return bool
123
     */
124 25
    public function getIsSolrAvailable($useCache = true)
125
    {
126 25
        $this->isSolrAvailable = $this->search->ping($useCache);
127 25
        return $this->isSolrAvailable;
128
    }
129
130
    /**
131
     * @return bool
132
     */
133 25
    public function getHasSearched()
134
    {
135 25
        return $this->search->hasSearched();
136
    }
137
138
    /**
139
     * Retrieves the used search instance.
140
     *
141
     * @return Search
142
     */
143 25
    public function getSearch()
144
    {
145 25
        return $this->search;
146
    }
147
148
    /**
149
     * @param bool $usePluginAwareComponents
150
     */
151
    public function setUsePluginAwareComponents($usePluginAwareComponents)
152
    {
153
        $this->usePluginAwareComponents = $usePluginAwareComponents;
154
    }
155
156
    /**
157
     * @return bool
158
     */
159
    public function getUsePluginAwareComponents()
160
    {
161
        return $this->usePluginAwareComponents;
162
    }
163
164
    /**
165
     * @param bool $useQueryAwareComponents
166
     */
167
    public function setUseQueryAwareComponents($useQueryAwareComponents)
168
    {
169
        $this->useQueryAwareComponents = $useQueryAwareComponents;
170
    }
171
172
    /**
173
     * @return bool
174
     */
175
    public function getUseQueryAwareComponents()
176
    {
177
        return $this->useQueryAwareComponents;
178
    }
179
180
    /**
181
     * Initializes the Query object and SearchComponents and returns
182
     * the initialized query object, when a search should be executed.
183
     *
184
     * @param string $rawQuery
185
     * @param int $resultsPerPage
186
     * @return Query
187
     */
188 31
    protected function getPreparedQuery($rawQuery, $resultsPerPage)
189
    {
190
        /* @var $query Query */
191 31
        $query = GeneralUtility::makeInstance(Query::class, $rawQuery);
192
193 31
        $this->applyPageSectionsRootLineFilter($query);
194
195 31
        if ($this->typoScriptConfiguration->getLoggingQuerySearchWords()) {
196
            GeneralUtility::devLog('received search query', 'solr', 0, [$rawQuery]);
197
        }
198
199 31
        $query->setResultsPerPage($resultsPerPage);
200
201 31
        $this->initializeRegisteredSearchComponents($query);
202
203 31
        if ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
204
            // empty main query, but using a "return everything"
205
            // alternative query in q.alt
206 24
            $query->setAlternativeQuery('*:*');
207
        }
208
209 31
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
210 3
            $query->setAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
211
        }
212
213 31
        foreach ($this->getAdditionalFilters() as $additionalFilter) {
214 2
            $query->addFilter($additionalFilter);
215
        }
216
217 31
        return $query;
218
    }
219
220
    /**
221
     * @param Query $query
222
     */
223 31
    protected function initializeRegisteredSearchComponents(Query $query)
224
    {
225 31
        $searchComponents = $this->getRegisteredSearchComponents();
226
227 31
        foreach ($searchComponents as $searchComponent) {
228
            /** @var Search\SearchComponent $searchComponent */
229 25
            $searchComponent->setSearchConfiguration($this->typoScriptConfiguration->getSearchConfiguration());
230
231 25
            if ($searchComponent instanceof QueryAware && $this->useQueryAwareComponents) {
232 25
                $searchComponent->setQuery($query);
233
            }
234
235 25
            if ($searchComponent instanceof PluginAware && $this->usePluginAwareComponents) {
236
                $searchComponent->setParentPlugin($this->parentPlugin);
237
            }
238
239 25
            $searchComponent->initializeSearchComponent();
240
        }
241 31
    }
242
243
    /**
244
     * Returns the number of results per Page.
245
     *
246
     * Also influences how many result documents are returned by the Solr
247
     * server as the return value is used in the Solr "rows" GET parameter.
248
     *
249
     * @param string $rawQuery
250
     * @param int|null $requestedPerPage
251
     * @return int number of results to show per page
252
     */
253 31
    protected function getNumberOfResultsPerPage($rawQuery, $requestedPerPage = null)
254
    {
255 31
        $perPageSwitchOptions = $this->typoScriptConfiguration->getSearchResultsPerPageSwitchOptionsAsArray();
256 31
        if (isset($requestedPerPage) && in_array($requestedPerPage, $perPageSwitchOptions)) {
257 1
            $this->setPerPageInSession($requestedPerPage);
258 1
            $this->resultsPerPageChanged = true;
259
        }
260
261 31
        $defaultResultsPerPage = $this->typoScriptConfiguration->getSearchResultsPerPage();
262 31
        $sessionResultPerPage = $this->getPerPageFromSession();
263
264 31
        $currentNumberOfResultsShown = $defaultResultsPerPage;
265 31
        if (!is_null($sessionResultPerPage) && in_array($sessionResultPerPage, $perPageSwitchOptions)) {
266
            $currentNumberOfResultsShown = (int)$sessionResultPerPage;
267
        }
268
269 31
        if ($this->shouldHideResultsFromInitialSearch($rawQuery)) {
270
            // initialize search with an empty query, which would by default return all documents
271
            // anyway, tell Solr to not return any result documents
272
            // Solr will still return facets though
273
            $currentNumberOfResultsShown = 0;
274
        }
275
276 31
        return $currentNumberOfResultsShown;
277
    }
278
279
    /**
280
     * Provides a hook for other classes to process the search's response.
281
     *
282
     * @param string $rawQuery
283
     * @param Query $query The query that has been searched for.
284
     * @param \Apache_Solr_Response $response The search's response.
285
     */
286 32
    protected function processResponse($rawQuery, Query $query, \Apache_Solr_Response &$response)
287
    {
288 32
        if ($this->shouldHideResultsFromInitialSearch($rawQuery)) {
289
            // explicitly set number of results to 0 as we just wanted
290
            // facets and the like according to configuration
291
            // @see getNumberOfResultsPerPage()
292
            $response->response->numFound = 0;
293
        }
294
295 32
        $this->wrapResultDocumentInResultObject($response);
296 32
        $this->addExpandedDocumentsFromVariants($response);
297
298 32
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse'])) {
299 21
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse'] as $classReference) {
300 21
                $responseProcessor = GeneralUtility::getUserObj($classReference);
301 21
                if ($responseProcessor instanceof ResponseProcessor) {
302 21
                    $responseProcessor->processResponse($query, $response);
303
                }
304
            }
305
        }
306 32
    }
307
308
    /**
309
     * This method is used to add documents to the expanded documents of the SearchResult
310
     * when collapsing is configured.
311
     *
312
     * @param \Apache_Solr_Response $response
313
     */
314 32
    protected function addExpandedDocumentsFromVariants(\Apache_Solr_Response &$response)
315
    {
316 32
        if (!is_array($response->response->docs)) {
317 5
            return;
318
        }
319
320 27
        if (!$this->typoScriptConfiguration->getSearchVariants()) {
321 24
            return;
322
        }
323
324 3
        $variantsField = $this->typoScriptConfiguration->getSearchVariantsField();
325 3
        foreach ($response->response->docs as $key => $resultDocument) {
326
            /** @var $resultDocument SearchResult */
327 2
            $variantField = $resultDocument->getField($variantsField);
328 2
            $variantId = isset($variantField['value']) ? $variantField['value'] : null;
329
330
                // when there is no value in the collapsing field, we can return
331 2
            if ($variantId === null) {
332
                continue;
333
            }
334
335 2
            $variantAccessKey = strtolower($variantId);
336 2
            if (!isset($response->{'expanded'}) || !isset($response->{'expanded'}->{$variantAccessKey})) {
337
                continue;
338
            }
339
340 2
            foreach ($response->{'expanded'}->{$variantAccessKey}->{'docs'} as $variantDocumentArray) {
341 2
                $variantDocument = new \Apache_Solr_Document();
342 2
                foreach (get_object_vars($variantDocumentArray) as $propertyName => $propertyValue) {
343 2
                    $variantDocument->{$propertyName} = $propertyValue;
344
                }
345 2
                $variantSearchResult = $this->wrapApacheSolrDocumentInResultObject($variantDocument);
346 2
                $variantSearchResult->setIsVariant(true);
347 2
                $variantSearchResult->setVariantParent($resultDocument);
348
349 2
                $resultDocument->addVariant($variantSearchResult);
350
            }
351
        }
352 3
    }
353
354
    /**
355
     * Wrap all results document it a custom EXT:solr SearchResult object.
356
     *
357
     * Can be overwritten:
358
     *
359
     * $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] = ''
360
     *
361
     * to use a custom result object.
362
     *
363
     * @param \Apache_Solr_Response $response
364
     * @throws \Apache_Solr_ParserException
365
     */
366 32
    protected function wrapResultDocumentInResultObject(\Apache_Solr_Response &$response)
367
    {
368
        try {
369 32
            $documents = $response->response->docs;
370 1
        } 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...
Bug introduced by
The class Apache_Solr_ParserException does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
371
            // when variant are enable and the index is empty, we get a parse exception, because of a
372
            // Apache Solr Bug.
373
            // see: https://github.com/TYPO3-Solr/ext-solr/issues/668
374
            // @todo this try/catch block can be removed after upgrading to Apache Solr 6.4
375 1
            if (!$this->typoScriptConfiguration->getSearchVariants()) {
376
                throw $e;
377
            }
378
379 1
            $response->response = new \stdClass();
380 1
            $response->spellcheck = [];
381 1
            $response->debug = [];
382 1
            $response->responseHeader = [];
383 1
            $response->facet_counts = [];
384
385 1
            $documents = [];
386
        }
387
388 32
        if (!is_array($documents)) {
389 5
            return;
390
        }
391
392 27
        foreach ($documents as $key => $originalDocument) {
393 24
            $result = $this->wrapApacheSolrDocumentInResultObject($originalDocument);
394 24
            $documents[$key] = $result;
395
        }
396
397 27
        $response->response->docs = $documents;
398 27
    }
399
400
    /**
401
     * This method is used to wrap the \Apache_Solr_Document instance in an instance of the configured SearchResult
402
     * class.
403
     *
404
     * @param \Apache_Solr_Document $originalDocument
405
     * @throws \InvalidArgumentException
406
     * @return SearchResult
407
     */
408 24
    protected function wrapApacheSolrDocumentInResultObject(\Apache_Solr_Document $originalDocument)
409
    {
410 24
        $searchResultClassName = $this->getResultClassName();
411 24
        $result = GeneralUtility::makeInstance($searchResultClassName, $originalDocument);
412 24
        if (!$result instanceof SearchResult) {
413
            throw new \InvalidArgumentException('Could not create result object with class: ' . (string)$searchResultClassName, 1470037679);
414
        }
415
416 24
        return $result;
417
    }
418
419
    /**
420
     * @return string
421
     */
422 24
    protected function getResultClassName()
423
    {
424 24
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName ']) ?
425 24
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] : SearchResult::class;
426
    }
427
428
    /**
429
     * @return string
430
     */
431 34
    protected function getResultSetClassName()
432
    {
433 34
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName ']) ?
434 34
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] : SearchResultSet::class;
435
    }
436
437
    /**
438
     * Checks it the results should be hidden in the response.
439
     *
440
     * @param string $rawQuery
441
     * @return bool
442
     */
443 32
    protected function shouldHideResultsFromInitialSearch($rawQuery)
444
    {
445 32
        return ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery()) && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery() && $rawQuery === null;
446
    }
447
448
    /**
449
     * Initializes additional filters configured through TypoScript and
450
     * Flexforms for use in regular queries and suggest queries.
451
     *
452
     * @param Query $query
453
     * @return void
454
     */
455 31
    protected function applyPageSectionsRootLineFilter(Query $query)
456
    {
457 31
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
458 31
        if (count($searchQueryFilters) <= 0) {
459 29
            return;
460
        }
461
462
        // special filter to limit search to specific page tree branches
463 2
        if (array_key_exists('__pageSections', $searchQueryFilters)) {
464
            $query->setRootlineFilter($searchQueryFilters['__pageSections']);
465
            $this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
466
        }
467 2
    }
468
469
    /**
470
     * Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
471
     *
472
     * @return array
473
     */
474 36
    public function getAdditionalFilters()
475
    {
476
        // when we've build the additionalFilter once, we could return them
477 36
        if (count($this->additionalFilters) > 0) {
478 2
            return $this->additionalFilters;
479
        }
480
481 36
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
482 36
        if (count($searchQueryFilters) <= 0) {
483 33
            return [];
484
        }
485
486 3
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
487
488
        // all other regular filters
489 3
        foreach ($searchQueryFilters as $filterKey => $filter) {
490
            // the __pageSections filter should not be handled as additional filter
491 3
            if ($filterKey === '__pageSections') {
492
                continue;
493
            }
494
495 3
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
496 3
            if ($filterIsArray) {
497
                continue;
498
            }
499
500 3
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
501 3
            if ($hasSubConfiguration) {
502
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
503
            }
504
505 3
            $this->additionalFilters[$filterKey] = $filter;
506
        }
507
508 3
        return $this->additionalFilters;
509
    }
510
511
    /**
512
     * Performs a search and returns a SearchResultSet.
513
     *
514
     * @param SearchRequest $searchRequest
515
     * @return SearchResultSet
516
     */
517 34
    public function search(SearchRequest $searchRequest)
518
    {
519
        /** @var $resultSet SearchResultSet */
520 34
        $resultSetClass = $this->getResultSetClassName();
521 34
        $resultSet = GeneralUtility::makeInstance($resultSetClass);
522 34
        $resultSet->setUsedSearchRequest($searchRequest);
523 34
        $this->lastResultSet = $resultSet;
524
525 34
        $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
526
527 34
        if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
528
            // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
529 1
            return $resultSet;
530
        }
531
532 33
        if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
533
            // the user entered an empty query string "" or "  " and empty querystring is not allowed
534 2
            return $resultSet;
535
        }
536
537 31
        $rawQuery = $searchRequest->getRawUserQuery();
538 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...
539 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...
540
541 31
        $resultSet->setUsedQuery($query);
542
543 31
        $currentPage = max(0, $searchRequest->getPage());
544
        // if the number of results per page has been changed by the current request, reset the pagebrowser
545 31
        if ($this->resultsPerPageChanged) {
546 1
            $currentPage = 0;
547
        }
548
549 31
        $offSet = $currentPage * $resultsPerPage;
550
        // performing the actual search, sending the query to the Solr server
551 31
        $response = $this->search->search($query, $offSet, null);
552
553 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...
554 31
        $this->addSearchResultsToResultSet($response, $resultSet);
555
556 31
        $resultSet->setResponse($response);
557 31
        $resultSet->setUsedPage($currentPage);
558 31
        $resultSet->setUsedResultsPerPage($resultsPerPage);
559 31
        $resultSet->setUsedAdditionalFilters($this->getAdditionalFilters());
560 31
        $resultSet->setUsedSearch($this->search);
561
562 31
        return $this->handleSearchHook('afterSearch', $resultSet);
563
    }
564
565
    /**
566
     * Retrieves a single document from solr by document id.
567
     *
568
     * @param string $documentId
569
     * @return SearchResult
570
     */
571 1
    public function getDocumentById($documentId)
572
    {
573
        /* @var $query Query */
574 1
        $query = GeneralUtility::makeInstance(Query::class, $documentId);
575 1
        $query->setQueryFieldsFromString('id');
576
577 1
        $response = $this->search->search($query, 0, 1);
578 1
        $this->processResponse($documentId, $query, $response);
579
580 1
        $resultDocument = isset($response->response->docs[0]) ? $response->response->docs[0] : null;
581 1
        return $resultDocument;
582
    }
583
584
    /**
585
     * This method is used to call the registered hooks during the search execution.
586
     *
587
     * @param string $eventName
588
     * @param SearchResultSet $resultSet
589
     * @return SearchResultSet
590
     */
591 34
    private function handleSearchHook($eventName, SearchResultSet $resultSet)
592
    {
593 34
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName])) {
594 34
            return $resultSet;
595
        }
596
597
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) {
598
            $afterSearchProcessor = GeneralUtility::getUserObj($classReference);
599
            if ($afterSearchProcessor instanceof SearchResultSetProcessor) {
600
                $afterSearchProcessor->process($resultSet);
601
            }
602
        }
603
604
        return $resultSet;
605
    }
606
607
    /**
608
     * @return SearchResultSet
609
     */
610 19
    public function getLastResultSet()
611
    {
612 19
        return $this->lastResultSet;
613
    }
614
615
    /**
616
     * This method returns true when the last search was executed with an empty query
617
     * string or whitespaces only. When no search was triggered it will return false.
618
     *
619
     * @return bool
620
     */
621 25
    public function getLastSearchWasExecutedWithEmptyQueryString()
622
    {
623 25
        $wasEmptyQueryString = false;
624 25
        if ($this->lastResultSet != null) {
625 23
            $wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString();
626
        }
627
628 25
        return $wasEmptyQueryString;
629
    }
630
631
    /**
632
     * @param int $requestedPerPage
633
     */
634
    protected function setPerPageInSession($requestedPerPage)
635
    {
636
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'tx_solr_resultsPerPage', intval($requestedPerPage));
637
    }
638
639
    /**
640
     * @return mixed
641
     */
642 24
    protected function getPerPageFromSession()
643
    {
644 24
        return $GLOBALS['TSFE']->fe_user->getKey('ses', 'tx_solr_resultsPerPage');
645
    }
646
647
    /**
648
     * @return bool
649
     */
650 2
    protected function getInitialSearchIsConfigured()
651
    {
652 2
        return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery();
653
    }
654
655
    /**
656
     * @return mixed
657
     */
658 24
    protected function getRegisteredSearchComponents()
659
    {
660 24
        return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents();
661
    }
662
663
    /**
664
     * This method is used to reference the SearchResult object from the response in the SearchResultSet object.
665
     *
666
     * @param \Apache_Solr_Response $response
667
     * @param SearchResultSet $resultSet
668
     */
669 31
    protected function addSearchResultsToResultSet($response, $resultSet)
670
    {
671 31
        if (!is_array($response->response->docs)) {
672 5
            return;
673
        }
674
675 26
        foreach ($response->response->docs as $searchResult) {
676 23
            $resultSet->addSearchResult($searchResult);
677
        }
678 26
    }
679
}
680