Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( e2fc25...5e3251 )
by
unknown
03:14
created

SolrSearch::getDocument()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 15
c 1
b 0
f 0
nc 6
nop 4
dl 0
loc 22
rs 9.7666
1
<?php
2
3
namespace Kitodo\Dlf\Common;
4
5
use Kitodo\Dlf\Common\SolrSearchResult\ResultDocument;
6
use Kitodo\Dlf\Common\Helper;
7
use Kitodo\Dlf\Domain\Model\Collection;
8
use Kitodo\Dlf\Domain\Repository\DocumentRepository;
9
use TYPO3\CMS\Core\Cache\CacheManager;
10
use TYPO3\CMS\Core\Utility\GeneralUtility;
11
use TYPO3\CMS\Core\Utility\MathUtility;
12
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
13
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
14
15
/**
16
 * Targeted towards being used in ``PaginateController`` (``<f:widget.paginate>``).
17
 *
18
 * Notes on implementation:
19
 * - `Countable`: `count()` returns the number of toplevel documents.
20
 * - `getNumLoadedDocuments()`: Number of toplevel documents that have been fetched from Solr.
21
 * - `ArrayAccess`/`Iterator`: Access *fetched* toplevel documents indexed in order of their ranking.
22
 */
23
class SolrSearch implements \Countable, \Iterator, \ArrayAccess, QueryResultInterface
24
{
25
    /**
26
     * @var DocumentRepository
27
     */
28
    private $documentRepository;
29
30
    /**
31
     * @var QueryResult|Collection
32
     */
33
    private $collection;
34
35
    /**
36
     * @var array
37
     */
38
    private $settings;
39
40
    /**
41
     * @var array
42
     */
43
    private $searchParams;
44
45
    /**
46
     * @var QueryResult
47
     */
48
    private $listedMetadata;
49
50
    /**
51
     * @var array
52
     */
53
    private $params;
54
55
    private $result;
56
57
    /**
58
     * @var int
59
     */
60
    protected $position = 0;
61
62
    /**
63
     *
64
     * @param DocumentRepository $documentRepository
65
     * @param QueryResult|Collection $collection
66
     * @param array $settings
67
     * @param array $searchParams
68
     * @param QueryResult $listedMetadata
69
     */
70
    public function __construct($documentRepository, $collection, $settings, $searchParams, $listedMetadata = null)
71
    {
72
        $this->documentRepository = $documentRepository;
73
        $this->collection = $collection;
74
        $this->settings = $settings;
75
        $this->searchParams = $searchParams;
76
        $this->listedMetadata = $listedMetadata;
77
    }
78
79
    public function getNumLoadedDocuments()
80
    {
81
        return count($this->result['documents']);
82
    }
83
84
    public function count(): int
85
    {
86
        if ($this->result === null) {
87
            return 0;
88
        }
89
90
        return $this->result['numberOfToplevels'];
91
    }
92
93
    public function current()
94
    {
95
        return $this[$this->position];
96
    }
97
98
    public function key()
99
    {
100
        return $this->position;
101
    }
102
103
    public function next(): void
104
    {
105
        $this->position++;
106
    }
107
108
    public function rewind(): void
109
    {
110
        $this->position = 0;
111
    }
112
113
    public function valid(): bool
114
    {
115
        return isset($this[$this->position]);
116
    }
117
118
    public function offsetExists($offset): bool
119
    {
120
        $idx = $this->result['document_keys'][$offset];
121
        return isset($this->result['documents'][$idx]);
122
    }
123
124
    public function offsetGet($offset)
125
    {
126
        $idx = $this->result['document_keys'][$offset];
127
        $document = $this->result['documents'][$idx] ?? null;
128
129
        if ($document !== null) {
130
            // It may happen that a Solr group only includes non-toplevel results,
131
            // in which case metadata of toplevel entry isn't yet filled.
132
            if (empty($document['metadata'])) {
133
                $document['metadata'] = $this->fetchToplevelMetadataFromSolr([
0 ignored issues
show
Bug introduced by
array('query' => 'uid:' ...ray('score' => 'desc')) of type array<string,array<string,string>|integer|string> is incompatible with the type integer expected by parameter $queryParams of Kitodo\Dlf\Common\SolrSe...levelMetadataFromSolr(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
                $document['metadata'] = $this->fetchToplevelMetadataFromSolr(/** @scrutinizer ignore-type */ [
Loading history...
134
                    'query' => 'uid:' . $document['uid'],
135
                    'start' => 0,
136
                    'rows' => 1,
137
                    'sort' => ['score' => 'desc'],
138
                ])[$document['uid']] ?? [];
139
            }
140
141
            // get title of parent/grandparent/... if empty
142
            if (empty($document['title']) && $document['partOf'] > 0) {
143
                $superiorTitle = Doc::getTitle($document['partOf'], true);
144
                if (!empty($superiorTitle)) {
145
                    $document['title'] = '[' . $superiorTitle . ']';
146
                }
147
            }
148
        }
149
150
        return $document;
151
    }
152
153
    public function offsetSet($offset, $value): void
154
    {
155
        throw new \Exception("SolrSearch: Modifying result list is not supported");
156
    }
157
158
    public function offsetUnset($offset): void
159
    {
160
        throw new \Exception("SolrSearch: Modifying result list is not supported");
161
    }
162
163
    public function getSolrResults()
164
    {
165
        return $this->result['solrResults'];
166
    }
167
168
    public function getByUid($uid)
169
    {
170
        return $this->result['documents'][$uid];
171
    }
172
173
    public function getQuery()
174
    {
175
        return new SolrSearchQuery($this);
176
    }
177
178
    public function getFirst()
179
    {
180
        return $this[0];
181
    }
182
183
    public function toArray()
184
    {
185
        return array_values($this->result['documents']);
186
    }
187
188
    /**
189
     * Get total number of hits.
190
     *
191
     * This can be accessed in Fluid template using `.numFound`.
192
     */
193
    public function getNumFound()
194
    {
195
        return $this->result['numFound'];
196
    }
197
198
    public function prepare()
199
    {
200
        // Prepare query parameters.
201
        $params = [];
202
        $matches = [];
203
        $fields = Solr::getFields();
204
205
        // Set search query.
206
        if (
207
            (!empty($this->searchParams['fulltext']))
208
            || preg_match('/' . $fields['fulltext'] . ':\((.*)\)/', trim($this->searchParams['query']), $matches)
209
        ) {
210
            // If the query already is a fulltext query e.g using the facets
211
            $this->searchParams['query'] = empty($matches[1]) ? $this->searchParams['query'] : $matches[1];
212
            // Search in fulltext field if applicable. Query must not be empty!
213
            if (!empty($this->searchParams['query'])) {
214
                $query = $fields['fulltext'] . ':(' . Solr::escapeQuery(trim($this->searchParams['query'])) . ')';
215
            }
216
            $params['fulltext'] = true;
217
        } else {
218
            // Retain given search field if valid.
219
            if (!empty($this->searchParams['query'])) {
220
                $query = Solr::escapeQueryKeepField(trim($this->searchParams['query']), $this->settings['storagePid']);
221
            }
222
        }
223
224
        // Add extended search query.
225
        if (
226
            !empty($this->searchParams['extQuery'])
227
            && is_array($this->searchParams['extQuery'])
228
        ) {
229
            $allowedOperators = ['AND', 'OR', 'NOT'];
230
            $numberOfExtQueries = count($this->searchParams['extQuery']);
231
            for ($i = 0; $i < $numberOfExtQueries; $i++) {
232
                if (!empty($this->searchParams['extQuery'][$i])) {
233
                    if (
234
                        in_array($this->searchParams['extOperator'][$i], $allowedOperators)
235
                    ) {
236
                        if (!empty($query)) {
237
                            $query .= ' ' . $this->searchParams['extOperator'][$i] . ' ';
238
                        }
239
                        $query .= Indexer::getIndexFieldName($this->searchParams['extField'][$i], $this->settings['storagePid']) . ':(' . Solr::escapeQuery($this->searchParams['extQuery'][$i]) . ')';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $query does not seem to be defined for all execution paths leading up to this point.
Loading history...
240
                    }
241
                }
242
            }
243
        }
244
245
        // Add filter query for date search
246
        if (!empty($this->searchParams['dateFrom']) && !empty($this->searchParams['dateTo'])) {
247
            // combine dateFrom and dateTo into range search
248
            $params['filterquery'][]['query'] = '{!join from=' . $fields['uid'] . ' to=' . $fields['uid'] . '}'. $fields['date'] . ':[' . $this->searchParams['dateFrom'] . ' TO ' . $this->searchParams['dateTo'] . ']';
249
        }
250
251
        // Add filter query for faceting.
252
        if (isset($this->searchParams['fq']) && is_array($this->searchParams['fq'])) {
253
            foreach ($this->searchParams['fq'] as $filterQuery) {
254
                $params['filterquery'][]['query'] = $filterQuery;
255
            }
256
        }
257
258
        // Add filter query for in-document searching.
259
        if (
260
            !empty($this->searchParams['documentId'])
261
            && MathUtility::canBeInterpretedAsInteger($this->searchParams['documentId'])
262
        ) {
263
            // Search in document and all subordinates (valid for up to three levels of hierarchy).
264
            $params['filterquery'][]['query'] = '_query_:"{!join from='
265
                . $fields['uid'] . ' to=' . $fields['partof'] . '}'
266
                . $fields['uid'] . ':{!join from=' . $fields['uid'] . ' to=' . $fields['partof'] . '}'
267
                . $fields['uid'] . ':' . $this->searchParams['documentId'] . '"' . ' OR {!join from='
268
                . $fields['uid'] . ' to=' . $fields['partof'] . '}'
269
                . $fields['uid'] . ':' . $this->searchParams['documentId'] . ' OR '
270
                . $fields['uid'] . ':' . $this->searchParams['documentId'];
271
        }
272
273
        // if collections are given, we prepare the collection query string
274
        if ($this->collection) {
275
            $collectionsQueryString = '';
276
            $virtualCollectionsQueryString = '';
277
            foreach ($this->collection as $collectionEntry) {
278
                // check for virtual collections query string
279
                if($collectionEntry->getIndexSearch()) {
280
                    $virtualCollectionsQueryString .= empty($virtualCollectionsQueryString) ? '(' . $collectionEntry->getIndexSearch() . ')' : ' OR ('. $collectionEntry->getIndexSearch() . ')' ;
281
                } else {
282
                    $collectionsQueryString .= empty($collectionsQueryString) ? '"' . $collectionEntry->getIndexName() . '"' : ' OR "' . $collectionEntry->getIndexName() . '"';
283
                }
284
            }
285
            
286
            // distinguish between simple collection browsing and actual searching within the collection(s)
287
            if(!empty($collectionsQueryString)) {
288
                if(empty($query)) {
289
                    $collectionsQueryString = '(collection_faceting:(' . $collectionsQueryString . ') AND toplevel:true AND partof:0)';
290
                } else {
291
                    $collectionsQueryString = '(collection_faceting:(' . $collectionsQueryString . '))';
292
                }
293
            }
294
295
            // virtual collections might query documents that are neither toplevel:true nor partof:0 and need to be searched separatly
296
            if(!empty($virtualCollectionsQueryString)) {
297
                $virtualCollectionsQueryString = '(' . $virtualCollectionsQueryString . ')';
298
            }
299
300
            // combine both querystrings into a single filterquery via OR if both are given, otherwise pass either of those
301
            $params['filterquery'][]['query'] = implode(' OR ', array_filter([$collectionsQueryString, $virtualCollectionsQueryString]));
302
        }
303
304
        // Set some query parameters.
305
        $params['query'] = !empty($query) ? $query : '*';
306
307
        // order the results as given or by title as default
308
        if (!empty($this->searchParams['orderBy'])) {
309
            $querySort = [
310
                $this->searchParams['orderBy'] => $this->searchParams['order'],
311
            ];
312
        } else {
313
            $querySort = [
314
                'score' => 'desc',
315
                'year_sorting' => 'asc',
316
                'title_sorting' => 'asc',
317
                'volume' => 'asc'
318
            ];
319
        }
320
321
        $params['sort'] = $querySort;
322
        $params['listMetadataRecords'] = [];
323
324
        // Restrict the fields to the required ones.
325
        $params['fields'] = 'uid,id,page,title,thumbnail,partof,toplevel,type';
326
327
        if ($this->listedMetadata) {
328
            foreach ($this->listedMetadata as $metadata) {
329
                if ($metadata->getIndexStored() || $metadata->getIndexIndexed()) {
330
                    $listMetadataRecord = $metadata->getIndexName() . '_' . ($metadata->getIndexTokenized() ? 't' : 'u') . ($metadata->getIndexStored() ? 's' : 'u') . ($metadata->getIndexIndexed() ? 'i' : 'u');
331
                    $params['fields'] .= ',' . $listMetadataRecord;
332
                    $params['listMetadataRecords'][$metadata->getIndexName()] = $listMetadataRecord;
333
                }
334
            }
335
        }
336
337
        $this->params = $params;
338
339
        // Send off query to get total number of search results in advance
340
        $this->submit(0, 1, false);
341
    }
342
343
    public function submit($start, $rows, $processResults = true)
344
    {
345
        $params = $this->params;
346
        $params['start'] = $start;
347
        $params['rows'] = $rows;
348
349
        // Perform search.
350
        $result = $this->searchSolr($params, true);
351
352
        // Initialize values
353
        $documents = [];
354
355
        if ($processResults && $result['numFound'] > 0) {
356
            // flat array with uids from Solr search
357
            $documentSet = array_unique(array_column($result['documents'], 'uid'));
358
359
            if (empty($documentSet)) {
360
                // return nothing found
361
                $this->result = ['solrResults' => [], 'documents' => [], 'document_keys' => [], 'numFound' => 0];
362
                return;
363
            }
364
365
            // get the Extbase document objects for all uids
366
            $allDocuments = $this->documentRepository->findAllByUids($documentSet);
367
            $childrenOf = $this->documentRepository->findChildrenOfEach($documentSet);
368
369
            foreach ($result['documents'] as $doc) {
370
                if (empty($documents[$doc['uid']]) && $allDocuments[$doc['uid']]) {
371
                    $documents[$doc['uid']] = $allDocuments[$doc['uid']];
372
                }
373
                if ($documents[$doc['uid']]) {
374
                    // translate language code if applicable
375
                    if($doc['metadata']['language']) {
376
                        foreach($doc['metadata']['language'] as $indexName => $language) {
377
                            $doc['metadata']['language'][$indexName] = Helper::getLanguageName($doc['metadata']['language'][$indexName]);
378
                        }
379
                    }
380
                    if ($doc['toplevel'] === false) {
381
                        // this maybe a chapter, article, ..., year
382
                        if ($doc['type'] === 'year') {
383
                            continue;
384
                        }
385
                        if (!empty($doc['page'])) {
386
                            // it's probably a fulltext or metadata search
387
                            $searchResult = [];
388
                            $searchResult['page'] = $doc['page'];
389
                            $searchResult['thumbnail'] = $doc['thumbnail'];
390
                            $searchResult['structure'] = $doc['type'];
391
                            $searchResult['title'] = $doc['title'];
392
                            foreach ($params['listMetadataRecords'] as $indexName => $solrField) {
393
                                if (isset($doc['metadata'][$indexName])) {
394
                                    $searchResult['metadata'][$indexName] = $doc['metadata'][$indexName];
395
                                }
396
                            }
397
                            if ($this->searchParams['fulltext'] == '1') {
398
                                $searchResult['snippet'] = $doc['snippet'];
399
                                $searchResult['highlight'] = $doc['highlight'];
400
                                $searchResult['highlight_word'] = preg_replace('/^;|;$/', '',       // remove ; at beginning or end
401
                                                                  preg_replace('/;+/', ';',         // replace any multiple of ; with a single ;
402
                                                                  preg_replace('/[{~\d*}{\s+}{^=*\d+.*\d*}`~!@#$%\^&*()_|+-=?;:\'",.<>\{\}\[\]\\\]/', ';', $this->searchParams['query']))); // replace search operators and special characters with ;
403
                            }
404
                            $documents[$doc['uid']]['searchResults'][] = $searchResult;
405
                        }
406
                    } else if ($doc['toplevel'] === true) {
407
                        foreach ($params['listMetadataRecords'] as $indexName => $solrField) {
408
                            if (isset($doc['metadata'][$indexName])) {
409
                                $documents[$doc['uid']]['metadata'][$indexName] = $doc['metadata'][$indexName];
410
                            }
411
                        }
412
                        if ($this->searchParams['fulltext'] != '1') {
413
                            $documents[$doc['uid']]['page'] = 1;
414
                            $children = $childrenOf[$doc['uid']] ?? [];
415
                            $childrenRows = !empty($this->settings['childrenRows']) ? intval($this->settings['childrenRows']) : 100;
416
                            if (!empty($children)) {
417
                                $metadataOf = $this->fetchToplevelMetadataFromSolr([
0 ignored issues
show
Bug introduced by
array('query' => 'partof...rows' => $childrenRows) of type array<string,integer|string> is incompatible with the type integer expected by parameter $queryParams of Kitodo\Dlf\Common\SolrSe...levelMetadataFromSolr(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

417
                                $metadataOf = $this->fetchToplevelMetadataFromSolr(/** @scrutinizer ignore-type */ [
Loading history...
418
                                    'query' => 'partof:' . $doc['uid'],
419
                                    'start' => 0,
420
                                    'rows' => $childrenRows,
421
                                ]);
422
                                foreach ($children as $docChild) {
423
                                    // We need only a few fields from the children, but we need them as array.
424
                                    $childDocument = [
425
                                        'thumbnail' => $docChild['thumbnail'],
426
                                        'title' => $docChild['title'],
427
                                        'structure' => $docChild['structure'],
428
                                        'metsOrderlabel' => $docChild['metsOrderlabel'],
429
                                        'uid' => $docChild['uid'],
430
                                        'metadata' => $metadataOf[$docChild['uid']],
431
                                    ];
432
                                    $documents[$doc['uid']]['children'][$docChild['uid']] = $childDocument;
433
                                }
434
                            }
435
                        }
436
                    }
437
                }
438
            }
439
        }
440
441
        $this->result = ['solrResults' => $result, 'numberOfToplevels' => $result['numberOfToplevels'], 'documents' => $documents, 'document_keys' => array_keys($documents), 'numFound' => $result['numFound']];
442
    }
443
444
    /**
445
     * Find all listed metadata using specified query params.
446
     *
447
     * @param int $queryParams
448
     * @return array
449
     */
450
    protected function fetchToplevelMetadataFromSolr($queryParams)
451
    {
452
        // Prepare query parameters.
453
        $params = $queryParams;
454
        $metadataArray = [];
455
456
        // Set some query parameters.
457
        $params['listMetadataRecords'] = [];
458
459
        // Restrict the fields to the required ones.
460
        $params['fields'] = 'uid,toplevel';
461
462
        if ($this->listedMetadata) {
463
            foreach ($this->listedMetadata as $metadata) {
464
                if ($metadata->getIndexStored() || $metadata->getIndexIndexed()) {
465
                    $listMetadataRecord = $metadata->getIndexName() . '_' . ($metadata->getIndexTokenized() ? 't' : 'u') . ($metadata->getIndexStored() ? 's' : 'u') . ($metadata->getIndexIndexed() ? 'i' : 'u');
466
                    $params['fields'] .= ',' . $listMetadataRecord;
467
                    $params['listMetadataRecords'][$metadata->getIndexName()] = $listMetadataRecord;
468
                }
469
            }
470
        }
471
        // Set filter query to just get toplevel documents.
472
        $params['filterquery'][] = ['query' => 'toplevel:true'];
473
474
        // Perform search.
475
        $result = $this->searchSolr($params, true);
476
477
        foreach ($result['documents'] as $doc) {
478
            // translate language code if applicable
479
            if($doc['metadata']['language']) {
480
                foreach($doc['metadata']['language'] as $indexName => $language) {
481
                    $doc['metadata']['language'][$indexName] = Helper::getLanguageName($doc['metadata']['language'][$indexName]);
482
                }
483
            }
484
            $metadataArray[$doc['uid']] = $doc['metadata'];
485
        }
486
487
        return $metadataArray;
488
    }
489
490
    /**
491
     * Processes a search request
492
     *
493
     * @access public
494
     *
495
     * @param array $parameters: Additional search parameters
496
     * @param boolean $enableCache: Enable caching of Solr requests
497
     *
498
     * @return array The Apache Solr Documents that were fetched
499
     */
500
    protected function searchSolr($parameters = [], $enableCache = true)
501
    {
502
        // Set query.
503
        $parameters['query'] = isset($parameters['query']) ? $parameters['query'] : '*';
504
        $parameters['filterquery'] = isset($parameters['filterquery']) ? $parameters['filterquery'] : [];
505
506
        // Perform Solr query.
507
        // Instantiate search object.
508
        $solr = Solr::getInstance($this->settings['solrcore']);
509
        if (!$solr->ready) {
510
            Helper::log('Apache Solr not available', LOG_SEVERITY_ERROR);
511
            return [
512
                'documents' => [],
513
                'numberOfToplevels' => 0,
514
                'numFound' => 0,
515
            ];
516
        }
517
518
        $cacheIdentifier = '';
519
        $cache = null;
520
        // Calculate cache identifier.
521
        if ($enableCache === true) {
522
            $cacheIdentifier = Helper::digest($solr->core . print_r($parameters, true));
0 ignored issues
show
Bug introduced by
Are you sure print_r($parameters, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

522
            $cacheIdentifier = Helper::digest($solr->core . /** @scrutinizer ignore-type */ print_r($parameters, true));
Loading history...
523
            $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('tx_dlf_solr');
524
        }
525
        $resultSet = [
526
            'documents' => [],
527
            'numberOfToplevels' => 0,
528
            'numFound' => 0,
529
        ];
530
        if ($enableCache === false || ($entry = $cache->get($cacheIdentifier)) === false) {
531
            $selectQuery = $solr->service->createSelect($parameters);
532
533
            $grouping = $selectQuery->getGrouping();
534
            $grouping->addField('uid');
535
            $grouping->setLimit(100); // Results in group (TODO: check)
536
            $grouping->setNumberOfGroups(true);
537
538
            if ($parameters['fulltext'] === true) {
539
                // get highlighting component and apply settings
540
                $selectQuery->getHighlighting();
541
            }
542
543
            $solrRequest = $solr->service->createRequest($selectQuery);
544
545
            if ($parameters['fulltext'] === true) {
546
                // If it is a fulltext search, enable highlighting.
547
                // field for which highlighting is going to be performed,
548
                // is required if you want to have OCR highlighting
549
                $solrRequest->addParam('hl.ocr.fl', 'fulltext');
550
                // return the coordinates of highlighted search as absolute coordinates
551
                $solrRequest->addParam('hl.ocr.absoluteHighlights', 'on');
552
                // max amount of snippets for a single page
553
                $solrRequest->addParam('hl.snippets', 20);
554
                // we store the fulltext on page level and can disable this option
555
                $solrRequest->addParam('hl.ocr.trackPages', 'off');
556
            }
557
558
            // Perform search for all documents with the same uid that either fit to the search or marked as toplevel.
559
            $response = $solr->service->executeRequest($solrRequest);
560
            // return empty resultSet on error-response
561
            if ($response->getStatusCode() == "400") {
562
                return $resultSet;
563
            }
564
            $result = $solr->service->createResult($selectQuery, $response);
565
566
            $uidGroup = $result->getGrouping()->getGroup('uid');
0 ignored issues
show
Bug introduced by
The method getGrouping() does not exist on Solarium\Core\Query\Result\ResultInterface. It seems like you code against a sub-type of Solarium\Core\Query\Result\ResultInterface such as Solarium\QueryType\Select\Result\Result. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

566
            $uidGroup = $result->/** @scrutinizer ignore-call */ getGrouping()->getGroup('uid');
Loading history...
567
            $resultSet['numberOfToplevels'] = $uidGroup->getNumberOfGroups();
568
            $resultSet['numFound'] = $uidGroup->getMatches();
569
            $highlighting = [];
570
            if ($parameters['fulltext'] === true) {
571
                $data = $result->getData();
572
                $highlighting = $data['ocrHighlighting'];
573
            }
574
            $fields = Solr::getFields();
575
576
            foreach ($uidGroup as $group) {
577
                foreach ($group as $record) {
578
                    $resultSet['documents'][] = $this->getDocument($record, $highlighting, $fields, $parameters);
579
                }
580
            }
581
582
            // Save value in cache.
583
            if (!empty($resultSet) && $enableCache === true) {
584
                $cache->set($cacheIdentifier, $resultSet);
585
            }
586
        } else {
587
            // Return cache hit.
588
            $resultSet = $entry;
589
        }
590
        return $resultSet;
591
    }
592
593
    private function getDocument($record, $highlighting, $fields, $parameters) {
594
        $resultDocument = new ResultDocument($record, $highlighting, $fields);
595
596
        $document = [
597
            'id' => $resultDocument->getId(),
598
            'page' => $resultDocument->getPage(),
599
            'snippet' => $resultDocument->getSnippets(),
600
            'thumbnail' => $resultDocument->getThumbnail(),
601
            'title' => $resultDocument->getTitle(),
602
            'toplevel' => $resultDocument->getToplevel(),
603
            'type' => $resultDocument->getType(),
604
            'uid' => !empty($resultDocument->getUid()) ? $resultDocument->getUid() : $parameters['uid'],
605
            'highlight' => $resultDocument->getHighlightsIds(),
606
        ];
607
        
608
        foreach ($parameters['listMetadataRecords'] as $indexName => $solrField) {
609
            if (!empty($record->$solrField)) {
610
                    $document['metadata'][$indexName] = $record->$solrField;
611
            }
612
        }
613
614
        return $document;
615
    }
616
}
617