Passed
Push — master ( 791909...fe60d3 )
by Timo
52s
created

wrapResultDocumentInResultObject()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 1
crap 3
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
        }
221
222 31
        if ($this->typoScriptConfiguration->getSearchInitializeWithQuery()) {
223 3
            $query->setAlternativeQuery($this->typoScriptConfiguration->getSearchInitializeWithQuery());
224
        }
225
226 31
        foreach ($this->getAdditionalFilters() as $additionalFilter) {
227 2
            $query->addFilter($additionalFilter);
228
        }
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
            }
247
248 25
            if ($searchComponent instanceof PluginAware && $this->usePluginAwareComponents) {
249
                $searchComponent->setParentPlugin($this->parentPlugin);
250
            }
251
252 25
            $searchComponent->initializeSearchComponent();
253
        }
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
        }
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;
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
        }
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
                }
317
            }
318
        }
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)) {
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...
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) {
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...
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
                }
358 2
                $variantSearchResult = $this->wrapApacheSolrDocumentInResultObject($variantDocument);
359 2
                $variantSearchResult->setIsVariant(true);
360 2
                $variantSearchResult->setVariantParent($resultDocument);
361
362 2
                $resultDocument->addVariant($variantSearchResult);
363
            }
364
        }
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 32
        $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...
382
383 32
        if (!is_array($documents)) {
384 5
            return;
385
        }
386
387 27
        foreach ($documents as $key => $originalDocument) {
388 24
            $result = $this->wrapApacheSolrDocumentInResultObject($originalDocument);
389 24
            $documents[$key] = $result;
390
        }
391
392 27
        $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...
393 27
    }
394
395
    /**
396
     * This method is used to wrap the \Apache_Solr_Document instance in an instance of the configured SearchResult
397
     * class.
398
     *
399
     * @param \Apache_Solr_Document $originalDocument
400
     * @throws \InvalidArgumentException
401
     * @return SearchResult
402
     */
403 24
    protected function wrapApacheSolrDocumentInResultObject(\Apache_Solr_Document $originalDocument)
404
    {
405 24
        $searchResultClassName = $this->getResultClassName();
406 24
        $result = GeneralUtility::makeInstance($searchResultClassName, $originalDocument);
407 24
        if (!$result instanceof SearchResult) {
408
            throw new \InvalidArgumentException('Could not create result object with class: ' . (string)$searchResultClassName, 1470037679);
409
        }
410
411 24
        return $result;
412
    }
413
414
    /**
415
     * @return string
416
     */
417 24
    protected function getResultClassName()
418
    {
419 24
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName ']) ?
420 24
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultClassName '] : SearchResult::class;
421
    }
422
423
    /**
424
     * @return string
425
     */
426 34
    protected function getResultSetClassName()
427
    {
428 34
        return isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName ']) ?
429 34
            $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] : SearchResultSet::class;
430
    }
431
432
    /**
433
     * Checks it the results should be hidden in the response.
434
     *
435
     * @param string $rawQuery
436
     * @return bool
437
     */
438 32
    protected function shouldHideResultsFromInitialSearch($rawQuery)
439
    {
440 32
        return ($this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery()) && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() && !$this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery() && $rawQuery === null;
441
    }
442
443
    /**
444
     * Initializes additional filters configured through TypoScript and
445
     * Flexforms for use in regular queries and suggest queries.
446
     *
447
     * @param Query $query
448
     * @return void
449
     */
450 31
    protected function applyPageSectionsRootLineFilter(Query $query)
451
    {
452 31
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
453 31
        if (count($searchQueryFilters) <= 0) {
454 29
            return;
455
        }
456
457
        // special filter to limit search to specific page tree branches
458 2
        if (array_key_exists('__pageSections', $searchQueryFilters)) {
459
            $query->setRootlineFilter($searchQueryFilters['__pageSections']);
460
            $this->typoScriptConfiguration->removeSearchQueryFilterForPageSections();
461
        }
462 2
    }
463
464
    /**
465
     * Retrieves the configuration filters from the TypoScript configuration, except the __pageSections filter.
466
     *
467
     * @return array
468
     */
469 36
    public function getAdditionalFilters()
470
    {
471
        // when we've build the additionalFilter once, we could return them
472 36
        if (count($this->additionalFilters) > 0) {
473 2
            return $this->additionalFilters;
474
        }
475
476 36
        $searchQueryFilters = $this->typoScriptConfiguration->getSearchQueryFilterConfiguration();
477 36
        if (count($searchQueryFilters) <= 0) {
478 33
            return [];
479
        }
480
481 3
        $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
482
483
        // all other regular filters
484 3
        foreach ($searchQueryFilters as $filterKey => $filter) {
485
            // the __pageSections filter should not be handled as additional filter
486 3
            if ($filterKey === '__pageSections') {
487
                continue;
488
            }
489
490 3
            $filterIsArray = is_array($searchQueryFilters[$filterKey]);
491 3
            if ($filterIsArray) {
492
                continue;
493
            }
494
495 3
            $hasSubConfiguration = is_array($searchQueryFilters[$filterKey . '.']);
496 3
            if ($hasSubConfiguration) {
497
                $filter = $cObj->stdWrap($searchQueryFilters[$filterKey], $searchQueryFilters[$filterKey . '.']);
498
            }
499
500 3
            $this->additionalFilters[$filterKey] = $filter;
501
        }
502
503 3
        return $this->additionalFilters;
504
    }
505
506
    /**
507
     * Performs a search and returns a SearchResultSet.
508
     *
509
     * @param SearchRequest $searchRequest
510
     * @return SearchResultSet
511
     */
512 34
    public function search(SearchRequest $searchRequest)
513
    {
514
        /** @var $resultSet SearchResultSet */
515 34
        $resultSetClass = $this->getResultSetClassName();
516 34
        $resultSet = GeneralUtility::makeInstance($resultSetClass);
517 34
        $resultSet->setUsedSearchRequest($searchRequest);
518 34
        $this->lastResultSet = $resultSet;
519
520 34
        $resultSet = $this->handleSearchHook('beforeSearch', $resultSet);
521
522 34
        if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) {
523
            // when no rawQuery was passed or no initialSearch is configured, we pass an empty result set
524 1
            return $resultSet;
525
        }
526
527 33
        if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) {
528
            // the user entered an empty query string "" or "  " and empty querystring is not allowed
529 2
            return $resultSet;
530
        }
531
532 31
        $rawQuery = $searchRequest->getRawUserQuery();
533 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...
534 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...
535
536 31
        $resultSet->setUsedQuery($query);
537
538 31
        $currentPage = max(0, $searchRequest->getPage());
539
        // if the number of results per page has been changed by the current request, reset the pagebrowser
540 31
        if ($this->resultsPerPageChanged) {
541 1
            $currentPage = 0;
542
        }
543
544 31
        $offSet = $currentPage * $resultsPerPage;
545
        // performing the actual search, sending the query to the Solr server
546 31
        $response = $this->search->search($query, $offSet, null);
547
548 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...
549 31
        $this->addSearchResultsToResultSet($response, $resultSet);
550
551 31
        $resultSet->setResponse($response);
552 31
        $resultSet->setUsedPage($currentPage);
553 31
        $resultSet->setUsedResultsPerPage($resultsPerPage);
554 31
        $resultSet->setUsedAdditionalFilters($this->getAdditionalFilters());
555 31
        $resultSet->setUsedSearch($this->search);
556
557 31
        return $this->handleSearchHook('afterSearch', $resultSet);
558
    }
559
560
    /**
561
     * Retrieves a single document from solr by document id.
562
     *
563
     * @param string $documentId
564
     * @return SearchResult
565
     */
566 1
    public function getDocumentById($documentId)
567
    {
568
        /* @var $query Query */
569 1
        $query = GeneralUtility::makeInstance(Query::class, $documentId);
570 1
        $query->setQueryFieldsFromString('id');
571
572 1
        $response = $this->search->search($query, 0, 1);
573 1
        $this->processResponse($documentId, $query, $response);
574
575 1
        $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...
576 1
        return $resultDocument;
577
    }
578
579
    /**
580
     * This method is used to call the registered hooks during the search execution.
581
     *
582
     * @param string $eventName
583
     * @param SearchResultSet $resultSet
584
     * @return SearchResultSet
585
     */
586 34
    private function handleSearchHook($eventName, SearchResultSet $resultSet)
587
    {
588 34
        if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName])) {
589 34
            return $resultSet;
590
        }
591
592
        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) {
593
            $afterSearchProcessor = GeneralUtility::getUserObj($classReference);
594
            if ($afterSearchProcessor instanceof SearchResultSetProcessor) {
595
                $afterSearchProcessor->process($resultSet);
596
            }
597
        }
598
599
        return $resultSet;
600
    }
601
602
    /**
603
     * @return SearchResultSet
604
     */
605 19
    public function getLastResultSet()
606
    {
607 19
        return $this->lastResultSet;
608
    }
609
610
    /**
611
     * This method returns true when the last search was executed with an empty query
612
     * string or whitespaces only. When no search was triggered it will return false.
613
     *
614
     * @return bool
615
     */
616 25
    public function getLastSearchWasExecutedWithEmptyQueryString()
617
    {
618 25
        $wasEmptyQueryString = false;
619 25
        if ($this->lastResultSet != null) {
620 23
            $wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString();
621
        }
622
623 25
        return $wasEmptyQueryString;
624
    }
625
626
    /**
627
     * @param int $requestedPerPage
628
     */
629
    protected function setPerPageInSession($requestedPerPage)
630
    {
631
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'tx_solr_resultsPerPage', intval($requestedPerPage));
632
    }
633
634
    /**
635
     * @return mixed
636
     */
637 24
    protected function getPerPageFromSession()
638
    {
639 24
        return $GLOBALS['TSFE']->fe_user->getKey('ses', 'tx_solr_resultsPerPage');
640
    }
641
642
    /**
643
     * @return bool
644
     */
645 2
    protected function getInitialSearchIsConfigured()
646
    {
647 2
        return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery();
648
    }
649
650
    /**
651
     * @return mixed
652
     */
653 24
    protected function getRegisteredSearchComponents()
654
    {
655 24
        return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents();
656
    }
657
658
    /**
659
     * This method is used to reference the SearchResult object from the response in the SearchResultSet object.
660
     *
661
     * @param \Apache_Solr_Response $response
662
     * @param SearchResultSet $resultSet
663
     */
664 31
    protected function addSearchResultsToResultSet($response, $resultSet)
665
    {
666 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...
667 5
            return;
668
        }
669
670 26
        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...
671 23
            $resultSet->addSearchResult($searchResult);
672
        }
673 26
    }
674
}
675