Passed
Pull Request — master (#1249)
by
unknown
19:13
created

wrapResultDocumentInResultObject()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 33
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 5.0035

Importance

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