Passed
Push — upcoming-feature/Introduce_Rou... ( c2e062...738f7d )
by
unknown
35:02
created

Indexer::isRootPageIdPartOfRootLine()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
namespace ApacheSolrForTypo3\Solr\IndexQueue;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2009-2015 Ingo Renner <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 3 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
use ApacheSolrForTypo3\Solr\ConnectionManager;
28
use ApacheSolrForTypo3\Solr\Domain\Search\ApacheSolrDocument\Builder;
29
use ApacheSolrForTypo3\Solr\FieldProcessor\Service;
30
use ApacheSolrForTypo3\Solr\FrontendEnvironment;
31
use ApacheSolrForTypo3\Solr\NoSolrConnectionFoundException;
32
use ApacheSolrForTypo3\Solr\Domain\Site\Site;
33
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
34
use ApacheSolrForTypo3\Solr\System\Records\Pages\PagesRepository;
35
use ApacheSolrForTypo3\Solr\System\Solr\Document\Document;
36
use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter;
37
use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection;
38
use Exception;
39
use RuntimeException;
40
use Solarium\Exception\HttpException;
41
use TYPO3\CMS\Core\Context\LanguageAspectFactory;
42
use TYPO3\CMS\Core\Error\Http\ServiceUnavailableException;
43
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
44
use TYPO3\CMS\Core\Http\ImmediateResponseException;
45
use TYPO3\CMS\Core\Site\SiteFinder;
46
use TYPO3\CMS\Core\Utility\GeneralUtility;
47
use TYPO3\CMS\Core\Utility\RootlineUtility;
48
use TYPO3\CMS\Frontend\Page\PageRepository;
49
50
/**
51
 * A general purpose indexer to be used for indexing of any kind of regular
52
 * records like tt_news, tt_address, and so on.
53
 * Specialized indexers can extend this class to handle advanced stuff like
54
 * category resolution in tt_news or file indexing.
55
 *
56
 * @author Ingo Renner <[email protected]>
57
 */
58
class Indexer extends AbstractIndexer
59
{
60
61
    # TODO change to singular $document instead of plural $documents
62
63
    /**
64
     * A Solr service instance to interact with the Solr server
65
     *
66
     * @var SolrConnection
67
     */
68
    protected $solr;
69
70
    /**
71
     * @var ConnectionManager
72
     */
73
    protected $connectionManager;
74
75
    /**
76
     * Holds options for a specific indexer
77
     *
78
     * @var array
79
     */
80
    protected $options = [];
81
82
    /**
83
     * To log or not to log... #Shakespeare
84
     *
85
     * @var bool
86
     */
87
    protected $loggingEnabled = false;
88
89
    /**
90
     * @var SolrLogManager
91
     */
92
    protected $logger = null;
93
94
    /**
95
     * @var PagesRepository
96
     */
97
    protected $pagesRepository;
98
99
    /**
100
     * @var Builder
101
     */
102
    protected $documentBuilder;
103
104
    /**
105
     * @var FrontendEnvironment
106
     */
107
    protected $frontendEnvironment = null;
108
109
    /**
110
     * Constructor
111
     *
112
     * @param array $options array of indexer options
113
     * @param PagesRepository|null $pagesRepository
114
     * @param Builder|null $documentBuilder
115
     * @param SolrLogManager|null $logger
116
     * @param ConnectionManager|null $connectionManager
117
     * @param FrontendEnvironment|null $frontendEnvironment
118
     */
119 38
    public function __construct(
120
        array $options = [],
121
        PagesRepository $pagesRepository = null,
122
        Builder $documentBuilder = null,
123
        SolrLogManager $logger = null,
124
        ConnectionManager $connectionManager = null,
125
        FrontendEnvironment $frontendEnvironment = null
126
    )
127
    {
128 38
        $this->options = $options;
129 38
        $this->pagesRepository = $pagesRepository ?? GeneralUtility::makeInstance(PagesRepository::class);
130 38
        $this->documentBuilder = $documentBuilder ?? GeneralUtility::makeInstance(Builder::class);
131 38
        $this->logger = $logger ?? GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
132 38
        $this->connectionManager = $connectionManager ?? GeneralUtility::makeInstance(ConnectionManager::class);
133 38
        $this->frontendEnvironment = $frontendEnvironment ?? GeneralUtility::makeInstance(FrontendEnvironment::class);
134 38
    }
135
136
    /**
137
     * Indexes an item from the indexing queue.
138
     *
139
     * @param Item $item An index queue item
140
     * @return bool returns true when indexed, false when not
141
     */
142 19
    public function index(Item $item)
143
    {
144 19
        $indexed = true;
145
146 19
        $this->type = $item->getType();
147 19
        $this->setLogging($item);
148
149 19
        $solrConnections = $this->getSolrConnectionsByItem($item);
150 19
        foreach ($solrConnections as $systemLanguageUid => $solrConnection) {
151 19
            $this->solr = $solrConnection;
152
153 19
            if (!$this->indexItem($item, $systemLanguageUid)) {
154
                /*
155
                 * A single language voting for "not indexed" should make the whole
156
                 * item count as being not indexed, even if all other languages are
157
                 * indexed.
158
                 * If there is no translation for a single language, this item counts
159
                 * as TRUE since it's not an error which that should make the item
160
                 * being reindexed during another index run.
161
                 */
162
                $indexed = false;
163
            }
164
        }
165
166 19
        return $indexed;
167
    }
168
169
    /**
170
     * Creates a single Solr Document for an item in a specific language.
171
     *
172
     * @param Item $item An index queue item to index.
173
     * @param int $language The language to use.
174
     * @return bool TRUE if item was indexed successfully, FALSE on failure
175
     */
176 19
    protected function indexItem(Item $item, $language = 0)
177
    {
178 19
        $itemIndexed = false;
179 19
        $documents = [];
180
181 19
        $itemDocument = $this->itemToDocument($item, $language);
182 19
        if (is_null($itemDocument)) {
183
            /*
184
             * If there is no itemDocument, this means there was no translation
185
             * for this record. This should not stop the current item to count as
186
             * being valid because not-indexing not-translated items is perfectly
187
             * fine.
188
             */
189
            return true;
190
        }
191
192 19
        $documents[] = $itemDocument;
193 19
        $documents = array_merge($documents, $this->getAdditionalDocuments($item, $language, $itemDocument));
194 19
        $documents = $this->processDocuments($item, $documents);
195 19
        $documents = $this->preAddModifyDocuments($item, $language, $documents);
196
197
        try {
198 19
            $response = $this->solr->getWriteService()->addDocuments($documents);
199 19
            if ($response->getHttpStatus() == 200) {
200 19
                $itemIndexed = true;
201
            }
202
        } catch (HttpException $e) {
203
            $response = new ResponseAdapter($e->getBody(), $httpStatus = 500, $e->getStatusMessage());
204
        }
205
206 19
        $this->log($item, $documents, $response);
207
208 19
        return $itemIndexed;
209
    }
210
211
    /**
212
     * Gets the full item record.
213
     *
214
     * This general record indexer simply gets the record from the item. Other
215
     * more specialized indexers may provide more data for their specific item
216
     * types.
217
     *
218
     * @param Item $item The item to be indexed
219
     * @param int $language Language Id (sys_language.uid)
220
     * @return array|NULL The full record with fields of data to be used for indexing or NULL to prevent an item from being indexed
221
     */
222 19
    protected function getFullItemRecord(Item $item, $language = 0)
223
    {
224 19
        $itemRecord = $this->getItemRecordOverlayed($item, $language);
225
226 19
        if (!is_null($itemRecord)) {
227 19
            $itemRecord['__solr_index_language'] = $language;
228
        }
229
230 19
        return $itemRecord;
231
    }
232
233
    /**
234
     * Returns the overlayed item record.
235
     *
236
     * @param Item $item
237
     * @param int $language
238
     * @return array|mixed|null
239
     */
240 19
    protected function getItemRecordOverlayed(Item $item, int $language): ?array
241
    {
242 19
        $itemRecord = $item->getRecord();
243
244 19
        if ($language > 0) {
245 17
            $page = GeneralUtility::makeInstance(PageRepository::class);
246 17
            $itemRecord = $page->getLanguageOverlay($item->getType(), $itemRecord);
247
        }
248
249 19
        if (!$itemRecord) {
250
            $itemRecord = null;
251
        }
252
253 19
        return $itemRecord;
254
    }
255
256
    /**
257
     * Gets the configuration how to process an item's fields for indexing.
258
     *
259
     * @param Item $item An index queue item
260
     * @param int $language Language ID
261
     * @throws RuntimeException
262
     * @return array Configuration array from TypoScript
263
     */
264 19
    protected function getItemTypeConfiguration(Item $item, int $language = 0): array
265
    {
266 19
        $indexConfigurationName = $item->getIndexingConfigurationName();
267 19
        $fields = $this->getFieldConfigurationFromItemRecordPage($item, $language, $indexConfigurationName);
268 19
        if (!$this->isRootPageIdPartOfRootLine($item) || count($fields) === 0) {
269 2
            $fields = $this->getFieldConfigurationFromItemRootPage($item, $language, $indexConfigurationName);
270 2
            if (count($fields) === 0) {
271
                throw new RuntimeException('The item indexing configuration "' . $item->getIndexingConfigurationName() .
272
                    '" on root page uid ' . $item->getRootPageUid() . ' could not be found!', 1455530112);
273
            }
274
        }
275
276 19
        return $fields;
277
    }
278
279
    /**
280
     * The method retrieves the field configuration of the items record page id (pid).
281
     *
282
     * @param Item $item
283
     * @param integer $language
284
     * @param string $indexConfigurationName
285
     * @return array
286
     */
287 19
    protected function getFieldConfigurationFromItemRecordPage(Item $item, $language, $indexConfigurationName): array
288
    {
289
        try {
290 19
            $pageId = $this->getPageIdOfItem($item);
291 19
            $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($pageId, $language);
292 19
            return $solrConfiguration->getIndexQueueFieldsConfigurationByConfigurationName($indexConfigurationName, []);
293
        } catch (Exception $e) {
294
            return [];
295
        }
296
    }
297
298
    /**
299
     * @param Item $item
300
     * @return int
301
     */
302 19
    protected function getPageIdOfItem(Item $item): int
303
    {
304 19
        if ($item->getType() === 'pages') {
305 2
            return (int)$item->getRecordUid();
306
        }
307 17
        return (int)$item->getRecordPageId();
308
    }
309
310
    /**
311
     * The method returns the field configuration of the items root page id (uid of the related root page).
312
     *
313
     * @param Item $item
314
     * @param integer $language
315
     * @param string $indexConfigurationName
316
     * @return array
317
     */
318 2
    protected function getFieldConfigurationFromItemRootPage(Item $item, $language, $indexConfigurationName)
319
    {
320 2
        $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($item->getRootPageUid(), $language);
321
322 2
        return $solrConfiguration->getIndexQueueFieldsConfigurationByConfigurationName($indexConfigurationName, []);
323
    }
324
325
    /**
326
     * In case of additionalStoragePid config recordPageId can be outside of siteroot.
327
     * In that case we should not read TS config of foreign siteroot.
328
     *
329
     * @param Item $item
330
     * @return bool
331
     */
332 19
    protected function isRootPageIdPartOfRootLine(Item $item): bool
333
    {
334 19
        $rootPageId = (int)$item->getRootPageUid();
335 19
        $buildRootlineWithPid = $this->getPageIdOfItem($item);
336 19
        $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $buildRootlineWithPid);
337 19
        $rootline = $rootlineUtility->get();
338
339
        $pageInRootline = array_filter($rootline, function($page) use ($rootPageId) {
340 19
            return (int)$page['uid'] === $rootPageId;
341 19
        });
342 19
        return !empty($pageInRootline);
343
    }
344
345
    /**
346
     * Converts an item array (record) to a Solr document by mapping the
347
     * record's fields onto Solr document fields as configured in TypoScript.
348
     *
349
     * @param Item $item An index queue item
350
     * @param int $language Language Id
351
     * @return Document|null The Solr document converted from the record
352
     * @throws SiteNotFoundException
353
     * @throws ServiceUnavailableException
354
     * @throws ImmediateResponseException
355
     */
356 20
    protected function itemToDocument(Item $item, $language = 0): ?Document
357
    {
358 20
        $document = null;
359 20
        if ($item->getType() === 'pages') {
360 3
            $this->frontendEnvironment->initializeTsfe($item->getRecordUid(), $language);
361
        } else {
362 17
            $this->frontendEnvironment->initializeTsfe($item->getRootPageUid(), $language);
363
        }
364
365 20
        $itemRecord = $this->getFullItemRecord($item, $language);
366 20
        if (!is_null($itemRecord)) {
367 19
            $itemIndexingConfiguration = $this->getItemTypeConfiguration($item, $language);
368 19
            $document = $this->getBaseDocument($item, $itemRecord);
369 19
            $document = $this->addDocumentFieldsFromTyposcript($document, $itemIndexingConfiguration, $itemRecord);
370
        }
371
372 20
        return $document;
373
    }
374
375
    /**
376
     * Creates a Solr document with the basic / core fields set already.
377
     *
378
     * @param Item $item The item to index
379
     * @param array $itemRecord The record to use to build the base document
380
     * @return Document A basic Solr document
381
     */
382 19
    protected function getBaseDocument(Item $item, array $itemRecord)
383
    {
384 19
        $type = $item->getType();
385 19
        $rootPageUid = $item->getRootPageUid();
386 19
        $accessRootLine = $this->getAccessRootline($item);
387 19
        return $this->documentBuilder->fromRecord($itemRecord, $type, $rootPageUid, $accessRootLine);
388
    }
389
390
    /**
391
     * Generates an Access Rootline for an item.
392
     *
393
     * @param Item $item Index Queue item to index.
394
     * @return string The Access Rootline for the item
395
     */
396 19
    protected function getAccessRootline(Item $item)
397
    {
398 19
        $accessRestriction = '0';
399 19
        $itemRecord = $item->getRecord();
400
401
        // TODO support access restrictions set on storage page
402
403 19
        if (isset($GLOBALS['TCA'][$item->getType()]['ctrl']['enablecolumns']['fe_group'])) {
404 2
            $accessRestriction = $itemRecord[$GLOBALS['TCA'][$item->getType()]['ctrl']['enablecolumns']['fe_group']];
405
406 2
            if (empty($accessRestriction)) {
407
                // public
408 2
                $accessRestriction = '0';
409
            }
410
        }
411
412 19
        return 'r:' . $accessRestriction;
413
    }
414
415
    /**
416
     * Sends the documents to the field processing service which takes care of
417
     * manipulating fields as defined in the field's configuration.
418
     *
419
     * @param Item $item An index queue item
420
     * @param array $documents An array of \ApacheSolrForTypo3\Solr\System\Solr\Document\Document objects to manipulate.
421
     * @return Document[] array Array of manipulated Document objects.
422
     */
423 19
    protected function processDocuments(Item $item, array $documents)
424
    {
425
        // needs to respect the TS settings for the page the item is on, conditions may apply
426 19
        $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($item->getRootPageUid());
427 19
        $fieldProcessingInstructions = $solrConfiguration->getIndexFieldProcessingInstructionsConfiguration();
428
429
        // same as in the FE indexer
430 19
        if (is_array($fieldProcessingInstructions)) {
0 ignored issues
show
introduced by
The condition is_array($fieldProcessingInstructions) is always true.
Loading history...
431 19
            $service = GeneralUtility::makeInstance(Service::class);
432 19
            $service->processDocuments($documents, $fieldProcessingInstructions);
433
        }
434
435 19
        return $documents;
436
    }
437
438
    /**
439
     * Allows third party extensions to provide additional documents which
440
     * should be indexed for the current item.
441
     *
442
     * @param Item $item The item currently being indexed.
443
     * @param int $language The language uid currently being indexed.
444
     * @param Document $itemDocument The document representing the item for the given language.
445
     * @return Document[] array An array of additional Document objects to index.
446
     */
447 23
    protected function getAdditionalDocuments(Item $item, $language, Document $itemDocument)
448
    {
449 23
        $documents = [];
450
451 23
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['indexItemAddDocuments'])) {
452 4
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['indexItemAddDocuments'] as $classReference) {
453 4
                if (!class_exists($classReference)) {
454 2
                    throw new \InvalidArgumentException('Class does not exits' . $classReference, 1490363487);
455
                }
456 2
                $additionalIndexer = GeneralUtility::makeInstance($classReference);
457 2
                if ($additionalIndexer instanceof AdditionalIndexQueueItemIndexer) {
458 1
                    $additionalDocuments = $additionalIndexer->getAdditionalItemDocuments($item, $language, $itemDocument);
459
460 1
                    if (is_array($additionalDocuments)) {
461 1
                        $documents = array_merge($documents,
462
                            $additionalDocuments);
463
                    }
464
                } else {
465 1
                    throw new \UnexpectedValueException(
466 1
                        get_class($additionalIndexer) . ' must implement interface ' . AdditionalIndexQueueItemIndexer::class,
467 1
                        1326284551
468
                    );
469
                }
470
            }
471
        }
472 20
        return $documents;
473
    }
474
475
    /**
476
     * Provides a hook to manipulate documents right before they get added to
477
     * the Solr index.
478
     *
479
     * @param Item $item The item currently being indexed.
480
     * @param int $language The language uid of the documents
481
     * @param array $documents An array of documents to be indexed
482
     * @return array An array of modified documents
483
     */
484 19
    protected function preAddModifyDocuments(Item $item, $language, array $documents)
485
    {
486 19
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['preAddModifyDocuments'])) {
487
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['preAddModifyDocuments'] as $classReference) {
488
                $documentsModifier = GeneralUtility::makeInstance($classReference);
489
490
                if ($documentsModifier instanceof PageIndexerDocumentsModifier) {
491
                    $documents = $documentsModifier->modifyDocuments($item, $language, $documents);
492
                } else {
493
                    throw new RuntimeException(
494
                        'The class "' . get_class($documentsModifier)
495
                        . '" registered as document modifier in hook
496
							preAddModifyDocuments must implement interface
497
							ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerDocumentsModifier',
498
                        1309522677
499
                    );
500
                }
501
            }
502
        }
503
504 19
        return $documents;
505
    }
506
507
    // Initialization
508
509
    /**
510
     * Gets the Solr connections applicable for an item.
511
     *
512
     * The connections include the default connection and connections to be used
513
     * for translations of an item.
514
     *
515
     * @param Item $item An index queue item
516
     * @return array An array of ApacheSolrForTypo3\Solr\System\Solr\SolrConnection connections, the array's keys are the sys_language_uid of the language of the connection
517
     */
518 22
    protected function getSolrConnectionsByItem(Item $item)
519
    {
520 22
        $solrConnections = [];
521
522 22
        $rootPageId = $item->getRootPageUid();
523 22
        if ($item->getType() === 'pages') {
524 4
            $pageId = $item->getRecordUid();
525
        } else {
526 18
            $pageId = $item->getRecordPageId();
527
        }
528
529
        // Solr configurations possible for this item
530 22
        $site = $item->getSite();
531 22
        $solrConfigurationsBySite = $site->getAllSolrConnectionConfigurations();
532 22
        $siteLanguages = [];
533 22
        foreach ($solrConfigurationsBySite as $solrConfiguration) {
534 22
            $siteLanguages[] = $solrConfiguration['language'];
535
        }
536
537 22
        $defaultLanguageUid = $this->getDefaultLanguageUid($item, $site->getRootPage(), $siteLanguages);
538 22
        $translationOverlays = $this->getTranslationOverlaysWithConfiguredSite((int)$pageId, $site, (array)$siteLanguages);
539
540 22
        $defaultConnection = $this->connectionManager->getConnectionByPageId($rootPageId, $defaultLanguageUid, $item->getMountPointIdentifier());
541 22
        $translationConnections = $this->getConnectionsForIndexableLanguages($translationOverlays);
542
543 22
        if ($defaultLanguageUid == 0) {
544 20
            $solrConnections[0] = $defaultConnection;
545
        }
546
547 22
        foreach ($translationConnections as $systemLanguageUid => $solrConnection) {
548 19
            $solrConnections[$systemLanguageUid] = $solrConnection;
549
        }
550 22
        return $solrConnections;
551
    }
552
553
    /**
554
     * @param int $pageId
555
     * @param Site $site
556
     * @param array $siteLanguages
557
     * @return array
558
     */
559 22
    protected function getTranslationOverlaysWithConfiguredSite(int $pageId, Site $site, array $siteLanguages): array
560
    {
561 22
        $translationOverlays = $this->pagesRepository->findTranslationOverlaysByPageId($pageId);
562 22
        $translatedLanguages = [];
563 22
        foreach ($translationOverlays as $key => $translationOverlay) {
564 6
            if (!in_array($translationOverlay['sys_language_uid'], $siteLanguages)) {
565
                unset($translationOverlays[$key]);
566
            } else {
567 6
                $translatedLanguages[] = (int)$translationOverlay['sys_language_uid'];
568
            }
569
        }
570
571 22
        if (count($translationOverlays) + 1 !== count($siteLanguages)) {
572
            // not all Languages are translated
573
            // add Language Fallback
574 21
            foreach ($siteLanguages as $languageId) {
575 21
                if ($languageId !== 0 && !in_array((int)$languageId, $translatedLanguages, true)) {
576 21
                    $fallbackLanguageIds = $this->getFallbackOrder($site, (int)$languageId, (int)$pageId);
577 21
                    foreach ($fallbackLanguageIds as $fallbackLanguageId) {
578 20
                        if ($fallbackLanguageId === 0 || in_array((int)$fallbackLanguageId, $translatedLanguages, true)) {
579
                            $translationOverlay = [
580 14
                                'pid' => $pageId,
581 14
                                'sys_language_uid' => $languageId,
582 14
                                'l10n_parent' => $pageId
583
                            ];
584 14
                            $translationOverlays[] = $translationOverlay;
585 14
                            continue 2;
586
                        }
587
                    }
588
                }
589
            }
590
        }
591 22
        return $translationOverlays;
592
    }
593
594
    /**
595
     * @param Site $site
596
     * @param int $languageId
597
     * @param int $pageId
598
     * @return array
599
     */
600 21
    protected function getFallbackOrder(Site $site,  int $languageId, int $pageId): array
0 ignored issues
show
Unused Code introduced by
The parameter $pageId is not used and could be removed. ( Ignorable by Annotation )

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

600
    protected function getFallbackOrder(Site $site,  int $languageId, /** @scrutinizer ignore-unused */ int $pageId): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
601
    {
602 21
        $fallbackChain = [];
603 21
        $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
604
        try {
605 21
            $site = $siteFinder->getSiteByRootPageId($site->getRootPageId());
606 20
            $languageAspect = LanguageAspectFactory::createFromSiteLanguage($site->getLanguageById($languageId));
607 20
            $fallbackChain = $languageAspect->getFallbackChain();
608 1
        } catch (SiteNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
609
610
        }
611 21
        return $fallbackChain;
612
    }
613
614
615
    /**
616
     * @param Item $item An index queue item
617
     * @param array $rootPage
618
     * @param array $siteLanguages
619
     *
620
     * @return int
621
     * @throws RuntimeException
622
     */
623 22
    protected function getDefaultLanguageUid(Item $item, array $rootPage, array $siteLanguages)
624
    {
625 22
        $defaultLanguageUid = 0;
626 22
        if (($rootPage['l18n_cfg'] & 1) == 1 && count($siteLanguages) == 1 && $siteLanguages[min(array_keys($siteLanguages))] > 0) {
627
            $defaultLanguageUid = $siteLanguages[min(array_keys($siteLanguages))];
628 22
        } elseif (($rootPage['l18n_cfg'] & 1) == 1 && count($siteLanguages) > 1) {
629 2
            unset($siteLanguages[array_search('0', $siteLanguages)]);
630 2
            $defaultLanguageUid = $siteLanguages[min(array_keys($siteLanguages))];
631 20
        } elseif (($rootPage['l18n_cfg'] & 1) == 1 && count($siteLanguages) == 1) {
632
            $message = 'Root page ' . (int)$item->getRootPageUid() . ' is set to hide default translation, but no other language is configured!';
633
            throw new RuntimeException($message);
634
        }
635
636 22
        return $defaultLanguageUid;
637
    }
638
639
    /**
640
     * Checks for which languages connections have been configured and returns
641
     * these connections.
642
     *
643
     * @param array $translationOverlays An array of translation overlays to check for configured connections.
644
     * @return array An array of ApacheSolrForTypo3\Solr\System\Solr\SolrConnection connections.
645
     */
646 22
    protected function getConnectionsForIndexableLanguages(array $translationOverlays)
647
    {
648 22
        $connections = [];
649
650 22
        foreach ($translationOverlays as $translationOverlay) {
651 20
            $pageId = $translationOverlay['l10n_parent'];
652 20
            $languageId = $translationOverlay['sys_language_uid'];
653
654
            try {
655 20
                $connection = $this->connectionManager->getConnectionByPageId($pageId, $languageId);
656 19
                $connections[$languageId] = $connection;
657 1
            } catch (NoSolrConnectionFoundException $e) {
658
                // ignore the exception as we seek only those connections
659
                // actually available
660
            }
661
        }
662
663 22
        return $connections;
664
    }
665
666
    // Utility methods
667
668
    // FIXME extract log() and setLogging() to ApacheSolrForTypo3\Solr\IndexQueue\AbstractIndexer
669
    // FIXME extract an interface Tx_Solr_IndexQueue_ItemInterface
670
671
    /**
672
     * Enables logging dependent on the configuration of the item's site
673
     *
674
     * @param Item $item An item being indexed
675
     * @return    void
676
     */
677 20
    protected function setLogging(Item $item)
678
    {
679 20
        $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($item->getRootPageUid());
680 20
        $this->loggingEnabled = $solrConfiguration->getLoggingIndexingQueueOperationsByConfigurationNameWithFallBack(
681 20
            $item->getIndexingConfigurationName()
682
        );
683 20
    }
684
685
    /**
686
     * Logs the item and what document was created from it
687
     *
688
     * @param Item $item The item that is being indexed.
689
     * @param array $itemDocuments An array of Solr documents created from the item's data
690
     * @param ResponseAdapter $response The Solr response for the particular index document
691
     */
692 19
    protected function log(Item $item, array $itemDocuments, ResponseAdapter $response)
693
    {
694 19
        if (!$this->loggingEnabled) {
695 19
            return;
696
        }
697
698
        $message = 'Index Queue indexing ' . $item->getType() . ':' . $item->getRecordUid() . ' - ';
699
700
        // preparing data
701
        $documents = [];
702
        foreach ($itemDocuments as $document) {
703
            $documents[] = (array)$document;
704
        }
705
706
        $logData = ['item' => (array)$item, 'documents' => $documents, 'response' => (array)$response];
707
708
        if ($response->getHttpStatus() == 200) {
709
            $severity = SolrLogManager::NOTICE;
710
            $message .= 'Success';
711
        } else {
712
            $severity = SolrLogManager::ERROR;
713
            $message .= 'Failure';
714
715
            $logData['status'] = $response->getHttpStatus();
716
            $logData['status message'] = $response->getHttpStatusMessage();
717
        }
718
719
        $this->logger->log($severity, $message, $logData);
720
    }
721
}
722