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 ( 613ade...e3d09d )
by
unknown
03:49
created

SolrSearch::getNumLoadedDocuments()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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

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