1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of the TYPO3 CMS project. |
7
|
|
|
* |
8
|
|
|
* It is free software; you can redistribute it and/or modify it under |
9
|
|
|
* the terms of the GNU General Public License, either version 2 |
10
|
|
|
* of the License, or any later version. |
11
|
|
|
* |
12
|
|
|
* For the full copyright and license information, please read the |
13
|
|
|
* LICENSE.txt file that was distributed with this source code. |
14
|
|
|
* |
15
|
|
|
* The TYPO3 project - inspiring people to share! |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
namespace ApacheSolrForTypo3\Solr\Domain\Search\ResultSet; |
19
|
|
|
|
20
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\Query\ParameterBuilder\QueryFields; |
21
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\Query\Query; |
22
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\Query\QueryBuilder; |
23
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\Query\SearchQuery; |
24
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Result\Parser\ResultParserRegistry; |
25
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Result\SearchResult; |
26
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\ResultSet\Result\SearchResultBuilder; |
27
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\SearchRequest; |
28
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Search\SearchRequestAware; |
29
|
|
|
use ApacheSolrForTypo3\Solr\Domain\Variants\VariantsProcessor; |
30
|
|
|
use ApacheSolrForTypo3\Solr\Query\Modifier\Modifier; |
31
|
|
|
use ApacheSolrForTypo3\Solr\Search; |
32
|
|
|
use ApacheSolrForTypo3\Solr\Search\QueryAware; |
33
|
|
|
use ApacheSolrForTypo3\Solr\Search\SearchAware; |
34
|
|
|
use ApacheSolrForTypo3\Solr\Search\SearchComponentManager; |
35
|
|
|
use ApacheSolrForTypo3\Solr\System\Configuration\TypoScriptConfiguration; |
36
|
|
|
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager; |
37
|
|
|
use ApacheSolrForTypo3\Solr\System\Solr\Document\Document; |
38
|
|
|
use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter; |
39
|
|
|
use ApacheSolrForTypo3\Solr\System\Solr\SolrIncompleteResponseException; |
40
|
|
|
use Exception; |
41
|
|
|
use function get_class; |
42
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
43
|
|
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; |
44
|
|
|
use UnexpectedValueException; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* The SearchResultSetService is responsible to build a SearchResultSet from a SearchRequest. |
48
|
|
|
* It encapsulates the logic to trigger a search in order to be able to reuse it in multiple places. |
49
|
|
|
* |
50
|
|
|
* @author Timo Schmidt <[email protected]> |
51
|
|
|
*/ |
52
|
|
|
class SearchResultSetService |
53
|
|
|
{ |
54
|
|
|
/** |
55
|
|
|
* Track, if the number of results per page has been changed by the current request |
56
|
|
|
* |
57
|
|
|
* @var bool |
58
|
|
|
*/ |
59
|
|
|
protected bool $resultsPerPageChanged = false; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @var Search |
63
|
|
|
*/ |
64
|
|
|
protected Search $search; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @var SearchResultSet|null |
68
|
|
|
*/ |
69
|
|
|
protected ?SearchResultSet $lastResultSet = null; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @var bool |
73
|
|
|
*/ |
74
|
|
|
protected bool $isSolrAvailable = false; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @var TypoScriptConfiguration |
78
|
|
|
*/ |
79
|
|
|
protected TypoScriptConfiguration $typoScriptConfiguration; |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* @var SolrLogManager |
83
|
|
|
*/ |
84
|
|
|
protected SolrLogManager $logger; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @var SearchResultBuilder |
88
|
|
|
*/ |
89
|
|
|
protected SearchResultBuilder $searchResultBuilder; |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @var QueryBuilder |
93
|
|
|
*/ |
94
|
|
|
protected QueryBuilder $queryBuilder; |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @var ObjectManagerInterface |
98
|
|
|
*/ |
99
|
|
|
protected ObjectManagerInterface $objectManager; |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @param TypoScriptConfiguration $configuration |
103
|
|
|
* @param Search $search |
104
|
|
|
* @param SolrLogManager|null $solrLogManager |
105
|
|
|
* @param SearchResultBuilder|null $resultBuilder |
106
|
|
|
* @param QueryBuilder|null $queryBuilder |
107
|
|
|
*/ |
108
|
51 |
|
public function __construct( |
109
|
|
|
TypoScriptConfiguration $configuration, |
110
|
|
|
Search $search, |
111
|
|
|
SolrLogManager $solrLogManager = null, |
112
|
|
|
SearchResultBuilder $resultBuilder = null, |
113
|
|
|
QueryBuilder $queryBuilder = null |
114
|
|
|
) { |
115
|
51 |
|
$this->search = $search; |
116
|
51 |
|
$this->typoScriptConfiguration = $configuration; |
117
|
51 |
|
$this->logger = $solrLogManager ?? GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__); |
118
|
51 |
|
$this->searchResultBuilder = $resultBuilder ?? GeneralUtility::makeInstance(SearchResultBuilder::class); |
119
|
51 |
|
$this->queryBuilder = $queryBuilder ?? GeneralUtility::makeInstance(QueryBuilder::class, /** @scrutinizer ignore-type */ $configuration, /** @scrutinizer ignore-type */ $solrLogManager); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @param ObjectManagerInterface $objectManager |
124
|
|
|
*/ |
125
|
50 |
|
public function injectObjectManager(ObjectManagerInterface $objectManager) |
126
|
|
|
{ |
127
|
50 |
|
$this->objectManager = $objectManager; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @param bool $useCache |
132
|
|
|
* @return bool |
133
|
|
|
* @throws Exception |
134
|
|
|
*/ |
135
|
|
|
public function getIsSolrAvailable(bool $useCache = true): bool |
136
|
|
|
{ |
137
|
|
|
$this->isSolrAvailable = $this->search->ping($useCache); |
138
|
|
|
return $this->isSolrAvailable; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Retrieves the used search instance. |
143
|
|
|
* |
144
|
|
|
* @return Search |
145
|
|
|
*/ |
146
|
1 |
|
public function getSearch(): Search |
147
|
|
|
{ |
148
|
1 |
|
return $this->search; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* @param Query $query |
153
|
|
|
* @param SearchRequest $searchRequest |
154
|
|
|
*/ |
155
|
40 |
|
protected function initializeRegisteredSearchComponents(Query $query, SearchRequest $searchRequest) |
156
|
|
|
{ |
157
|
40 |
|
$searchComponents = $this->getRegisteredSearchComponents(); |
158
|
|
|
|
159
|
40 |
|
foreach ($searchComponents as $searchComponent) { |
160
|
|
|
/** @var Search\SearchComponent $searchComponent */ |
161
|
35 |
|
$searchComponent->setSearchConfiguration($this->typoScriptConfiguration->getSearchConfiguration()); |
162
|
|
|
|
163
|
35 |
|
if ($searchComponent instanceof QueryAware) { |
164
|
35 |
|
$searchComponent->setQuery($query); |
165
|
|
|
} |
166
|
|
|
|
167
|
35 |
|
if ($searchComponent instanceof SearchRequestAware) { |
168
|
34 |
|
$searchComponent->setSearchRequest($searchRequest); |
169
|
|
|
} |
170
|
|
|
|
171
|
35 |
|
$searchComponent->initializeSearchComponent(); |
172
|
|
|
} |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* @return string |
177
|
|
|
*/ |
178
|
48 |
|
protected function getResultSetClassName(): string |
179
|
|
|
{ |
180
|
48 |
|
return $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['searchResultSetClassName '] ?? SearchResultSet::class; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Performs a search and returns a SearchResultSet. |
185
|
|
|
* |
186
|
|
|
* @param SearchRequest $searchRequest |
187
|
|
|
* @return SearchResultSet |
188
|
|
|
* @throws Facets\InvalidFacetPackageException |
189
|
|
|
* @throws Exception |
190
|
|
|
*/ |
191
|
48 |
|
public function search(SearchRequest $searchRequest): SearchResultSet |
192
|
|
|
{ |
193
|
48 |
|
$resultSet = $this->getInitializedSearchResultSet($searchRequest); |
194
|
48 |
|
$this->lastResultSet = $resultSet; |
195
|
|
|
|
196
|
48 |
|
$resultSet = $this->handleSearchHook('beforeSearch', $resultSet); |
197
|
48 |
|
if ($this->shouldReturnEmptyResultSetWithoutExecutedSearch($searchRequest)) { |
198
|
8 |
|
$resultSet->setHasSearched(false); |
199
|
8 |
|
return $resultSet; |
200
|
|
|
} |
201
|
|
|
|
202
|
40 |
|
$query = $this->queryBuilder->buildSearchQuery( |
203
|
40 |
|
$searchRequest->getRawUserQuery(), |
204
|
40 |
|
$searchRequest->getResultsPerPage(), |
205
|
40 |
|
$searchRequest->getAdditionalFilters() |
206
|
|
|
); |
207
|
40 |
|
$this->initializeRegisteredSearchComponents($query, $searchRequest); |
208
|
40 |
|
$resultSet->setUsedQuery($query); |
209
|
|
|
|
210
|
|
|
// performing the actual search, sending the query to the Solr server |
211
|
40 |
|
$query = $this->modifyQuery($query, $searchRequest, $this->search); |
212
|
40 |
|
$response = $this->doASearch($query, $searchRequest); |
213
|
|
|
|
214
|
40 |
|
if ($searchRequest->getResultsPerPage() === 0) { |
215
|
|
|
// when resultPerPage was forced to 0 we also set the numFound to 0 to hide results, e.g. |
216
|
|
|
// when results for the initial search should not be shown. |
217
|
|
|
// @extensionScannerIgnoreLine |
218
|
|
|
$response->response->numFound = 0; |
219
|
|
|
} |
220
|
|
|
|
221
|
40 |
|
$resultSet->setHasSearched(true); |
222
|
40 |
|
$resultSet->setResponse($response); |
223
|
|
|
|
224
|
40 |
|
$this->getParsedSearchResults($resultSet); |
225
|
|
|
|
226
|
40 |
|
$resultSet->setUsedAdditionalFilters($this->queryBuilder->getAdditionalFilters()); |
227
|
|
|
|
228
|
|
|
/** @var $variantsProcessor VariantsProcessor */ |
229
|
40 |
|
$variantsProcessor = GeneralUtility::makeInstance( |
230
|
|
|
VariantsProcessor::class, |
231
|
|
|
/** @scrutinizer ignore-type */ |
232
|
40 |
|
$this->typoScriptConfiguration, |
233
|
|
|
/** @scrutinizer ignore-type */ |
234
|
40 |
|
$this->searchResultBuilder |
235
|
|
|
); |
236
|
40 |
|
$variantsProcessor->process($resultSet); |
237
|
|
|
|
238
|
|
|
/** @var $searchResultReconstitutionProcessor ResultSetReconstitutionProcessor */ |
239
|
40 |
|
$searchResultReconstitutionProcessor = GeneralUtility::makeInstance(ResultSetReconstitutionProcessor::class); |
240
|
40 |
|
$searchResultReconstitutionProcessor->process($resultSet); |
241
|
|
|
|
242
|
40 |
|
$resultSet = $this->getAutoCorrection($resultSet); |
243
|
|
|
|
244
|
40 |
|
return $this->handleSearchHook('afterSearch', $resultSet); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Uses the configured parser and retrieves the parsed search results. |
249
|
|
|
* |
250
|
|
|
* @param SearchResultSet $resultSet |
251
|
|
|
*/ |
252
|
40 |
|
protected function getParsedSearchResults(SearchResultSet $resultSet) |
253
|
|
|
{ |
254
|
|
|
/** @var ResultParserRegistry $parserRegistry */ |
255
|
40 |
|
$parserRegistry = GeneralUtility::makeInstance(ResultParserRegistry::class, /** @scrutinizer ignore-type */ $this->typoScriptConfiguration); |
256
|
40 |
|
$useRawDocuments = (bool)$this->typoScriptConfiguration->getValueByPathOrDefaultValue('plugin.tx_solr.features.useRawDocuments', false); |
257
|
40 |
|
$parserRegistry->getParser($resultSet)->parse($resultSet, $useRawDocuments); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Evaluates conditions on the request and configuration and returns true if no search should be triggered and an empty |
262
|
|
|
* SearchResultSet should be returned. |
263
|
|
|
* |
264
|
|
|
* @param SearchRequest $searchRequest |
265
|
|
|
* @return bool |
266
|
|
|
*/ |
267
|
48 |
|
protected function shouldReturnEmptyResultSetWithoutExecutedSearch(SearchRequest $searchRequest): bool |
268
|
|
|
{ |
269
|
48 |
|
if ($searchRequest->getRawUserQueryIsNull() && !$this->getInitialSearchIsConfigured()) { |
270
|
|
|
// when no rawQuery was passed or no initialSearch is configured, we pass an empty result set |
271
|
6 |
|
return true; |
272
|
|
|
} |
273
|
|
|
|
274
|
42 |
|
if ($searchRequest->getRawUserQueryIsEmptyString() && !$this->typoScriptConfiguration->getSearchQueryAllowEmptyQuery()) { |
275
|
|
|
// the user entered an empty query string "" or " " and empty querystring is not allowed |
276
|
2 |
|
return true; |
277
|
|
|
} |
278
|
|
|
|
279
|
40 |
|
return false; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* Initializes the SearchResultSet from the SearchRequest |
284
|
|
|
* |
285
|
|
|
* @param SearchRequest $searchRequest |
286
|
|
|
* @return SearchResultSet |
287
|
|
|
*/ |
288
|
48 |
|
protected function getInitializedSearchResultSet(SearchRequest $searchRequest): SearchResultSet |
289
|
|
|
{ |
290
|
|
|
/** @var $resultSet SearchResultSet */ |
291
|
48 |
|
$resultSetClass = $this->getResultSetClassName(); |
292
|
48 |
|
$resultSet = $this->objectManager->get($resultSetClass); |
|
|
|
|
293
|
|
|
|
294
|
48 |
|
$resultSet->setUsedSearchRequest($searchRequest); |
295
|
48 |
|
$resultSet->setUsedPage((int)$searchRequest->getPage()); |
296
|
48 |
|
$resultSet->setUsedResultsPerPage($searchRequest->getResultsPerPage()); |
297
|
48 |
|
$resultSet->setUsedSearch($this->search); |
298
|
48 |
|
return $resultSet; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* Executes the search and builds a fake response for a current bug in Apache Solr 6.3 |
303
|
|
|
* |
304
|
|
|
* @param Query $query |
305
|
|
|
* @param SearchRequest $searchRequest |
306
|
|
|
* @return ResponseAdapter |
307
|
|
|
* @throws Exception |
308
|
|
|
*/ |
309
|
40 |
|
protected function doASearch(Query $query, SearchRequest $searchRequest): ResponseAdapter |
310
|
|
|
{ |
311
|
|
|
// the offset multiplier is page - 1 but not less than zero |
312
|
40 |
|
$offsetMultiplier = max(0, $searchRequest->getPage() - 1); |
313
|
40 |
|
$offSet = $offsetMultiplier * $searchRequest->getResultsPerPage(); |
314
|
|
|
|
315
|
40 |
|
$response = $this->search->search($query, $offSet); |
316
|
40 |
|
if ($response === null) { |
317
|
|
|
throw new SolrIncompleteResponseException('The response retrieved from solr was incomplete', 1505989678); |
318
|
|
|
} |
319
|
|
|
|
320
|
40 |
|
return $response; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* @param SearchResultSet $searchResultSet |
325
|
|
|
* @return SearchResultSet |
326
|
|
|
* @throws Facets\InvalidFacetPackageException |
327
|
|
|
*/ |
328
|
40 |
|
protected function getAutoCorrection(SearchResultSet $searchResultSet): SearchResultSet |
329
|
|
|
{ |
330
|
|
|
// no secondary search configured |
331
|
40 |
|
if (!$this->typoScriptConfiguration->getSearchSpellcheckingSearchUsingSpellCheckerSuggestion()) { |
332
|
39 |
|
return $searchResultSet; |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
// if more as zero results |
336
|
1 |
|
if ($searchResultSet->getAllResultCount() > 0) { |
337
|
1 |
|
return $searchResultSet; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
// no corrections present |
341
|
1 |
|
if (!$searchResultSet->getHasSpellCheckingSuggestions()) { |
342
|
|
|
return $searchResultSet; |
343
|
|
|
} |
344
|
|
|
|
345
|
1 |
|
return $this->performAutoCorrection($searchResultSet); |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
/** |
349
|
|
|
* @param SearchResultSet $searchResultSet |
350
|
|
|
* @return SearchResultSet |
351
|
|
|
* |
352
|
|
|
* @throws Facets\InvalidFacetPackageException |
353
|
|
|
*/ |
354
|
1 |
|
protected function performAutoCorrection(SearchResultSet $searchResultSet): SearchResultSet |
355
|
|
|
{ |
356
|
1 |
|
$searchRequest = $searchResultSet->getUsedSearchRequest(); |
357
|
1 |
|
$suggestions = $searchResultSet->getSpellCheckingSuggestions(); |
358
|
|
|
|
359
|
1 |
|
$maximumRuns = $this->typoScriptConfiguration->getSearchSpellcheckingNumberOfSuggestionsToTry(); |
360
|
1 |
|
$runs = 0; |
361
|
|
|
|
362
|
1 |
|
foreach ($suggestions as $suggestion) { |
363
|
1 |
|
$runs++; |
364
|
|
|
|
365
|
1 |
|
$correction = $suggestion->getSuggestion(); |
366
|
1 |
|
$initialQuery = $searchRequest->getRawUserQuery(); |
367
|
|
|
|
368
|
1 |
|
$searchRequest->setRawQueryString($correction); |
369
|
1 |
|
$searchResultSet = $this->search($searchRequest); |
|
|
|
|
370
|
1 |
|
if ($searchResultSet->getAllResultCount() > 0) { |
371
|
1 |
|
$searchResultSet->setIsAutoCorrected(true); |
372
|
1 |
|
$searchResultSet->setCorrectedQueryString($correction); |
373
|
1 |
|
$searchResultSet->setInitialQueryString($initialQuery); |
374
|
1 |
|
break; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
if ($runs > $maximumRuns) { |
378
|
|
|
break; |
379
|
|
|
} |
380
|
|
|
} |
381
|
1 |
|
return $searchResultSet; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* Allows to modify a query before eventually handing it over to Solr. |
386
|
|
|
* |
387
|
|
|
* @param Query $query The current query before it's being handed over to Solr. |
388
|
|
|
* @param SearchRequest $searchRequest The searchRequest, relevant in the current context |
389
|
|
|
* @param Search $search The search, relevant in the current context |
390
|
|
|
* @throws UnexpectedValueException |
391
|
|
|
* @return Query The modified query that is actually going to be given to Solr. |
392
|
|
|
*/ |
393
|
40 |
|
protected function modifyQuery(Query $query, SearchRequest $searchRequest, Search $search): Query |
394
|
|
|
{ |
395
|
|
|
// hook to modify the search query |
396
|
40 |
|
if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery'] ?? null)) { |
397
|
34 |
|
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery'] as $classReference) { |
398
|
34 |
|
$queryModifier = $this->objectManager->get($classReference); |
|
|
|
|
399
|
|
|
|
400
|
34 |
|
if ($queryModifier instanceof Modifier) { |
401
|
34 |
|
if ($queryModifier instanceof SearchAware) { |
402
|
|
|
$queryModifier->setSearch($search); |
403
|
|
|
} |
404
|
|
|
|
405
|
34 |
|
if ($queryModifier instanceof SearchRequestAware) { |
406
|
16 |
|
$queryModifier->setSearchRequest($searchRequest); |
407
|
|
|
} |
408
|
|
|
|
409
|
34 |
|
$query = $queryModifier->modifyQuery($query); |
410
|
|
|
} else { |
411
|
|
|
throw new UnexpectedValueException( |
412
|
|
|
get_class($queryModifier) . ' must implement interface ' . Modifier::class, |
413
|
|
|
1310387414 |
414
|
|
|
); |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
} |
418
|
|
|
|
419
|
40 |
|
return $query; |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* Retrieves a single document from solr by document id. |
424
|
|
|
* |
425
|
|
|
* @param string $documentId |
426
|
|
|
* @return SearchResult |
427
|
|
|
* @throws Exception |
428
|
|
|
*/ |
429
|
2 |
|
public function getDocumentById(string $documentId): SearchResult |
430
|
|
|
{ |
431
|
|
|
/* @var $query SearchQuery */ |
432
|
2 |
|
$query = $this->queryBuilder->newSearchQuery($documentId)->useQueryFields(QueryFields::fromString('id'))->getQuery(); |
433
|
2 |
|
$response = $this->search->search($query, 0, 1); |
434
|
2 |
|
$parsedData = $response->getParsedData(); |
435
|
|
|
// @extensionScannerIgnoreLine |
436
|
2 |
|
$resultDocument = $parsedData->response->docs[0] ?? null; |
437
|
|
|
|
438
|
2 |
|
if (!$resultDocument instanceof Document) { |
439
|
|
|
throw new UnexpectedValueException('Response did not contain a valid Document object'); |
440
|
|
|
} |
441
|
|
|
|
442
|
2 |
|
return $this->searchResultBuilder->fromApacheSolrDocument($resultDocument); |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
/** |
446
|
|
|
* This method is used to call the registered hooks during the search execution. |
447
|
|
|
* |
448
|
|
|
* @param string $eventName |
449
|
|
|
* @param SearchResultSet $resultSet |
450
|
|
|
* @return SearchResultSet |
451
|
|
|
*/ |
452
|
48 |
|
private function handleSearchHook(string $eventName, SearchResultSet $resultSet): SearchResultSet |
453
|
|
|
{ |
454
|
48 |
|
if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] ?? null)) { |
455
|
48 |
|
return $resultSet; |
456
|
|
|
} |
457
|
|
|
|
458
|
3 |
|
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr'][$eventName] as $classReference) { |
459
|
3 |
|
$afterSearchProcessor = $this->objectManager->get($classReference); |
|
|
|
|
460
|
3 |
|
if ($afterSearchProcessor instanceof SearchResultSetProcessor) { |
461
|
3 |
|
$afterSearchProcessor->process($resultSet); |
462
|
|
|
} |
463
|
|
|
} |
464
|
|
|
|
465
|
3 |
|
return $resultSet; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* @return SearchResultSet |
470
|
|
|
*/ |
471
|
|
|
public function getLastResultSet(): ?SearchResultSet |
472
|
|
|
{ |
473
|
|
|
return $this->lastResultSet; |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
/** |
477
|
|
|
* This method returns true when the last search was executed with an empty query |
478
|
|
|
* string or whitespaces only. When no search was triggered it will return false. |
479
|
|
|
* |
480
|
|
|
* @return bool |
481
|
|
|
*/ |
482
|
|
|
public function getLastSearchWasExecutedWithEmptyQueryString(): bool |
483
|
|
|
{ |
484
|
|
|
$wasEmptyQueryString = false; |
485
|
|
|
if ($this->lastResultSet != null) { |
486
|
|
|
$wasEmptyQueryString = $this->lastResultSet->getUsedSearchRequest()->getRawUserQueryIsEmptyString(); |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
return $wasEmptyQueryString; |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
/** |
493
|
|
|
* @return bool |
494
|
|
|
*/ |
495
|
8 |
|
protected function getInitialSearchIsConfigured(): bool |
496
|
|
|
{ |
497
|
8 |
|
return $this->typoScriptConfiguration->getSearchInitializeWithEmptyQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialEmptyQuery() || $this->typoScriptConfiguration->getSearchInitializeWithQuery() || $this->typoScriptConfiguration->getSearchShowResultsOfInitialQuery(); |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
/** |
501
|
|
|
* @return mixed |
502
|
|
|
*/ |
503
|
34 |
|
protected function getRegisteredSearchComponents() |
504
|
|
|
{ |
505
|
34 |
|
return GeneralUtility::makeInstance(SearchComponentManager::class)->getSearchComponents(); |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.