Passed
Push — master ( e55157...ed38f6 )
by Timo
27:41
created

Indexer::getAccessRootline()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 17
ccs 8
cts 8
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
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\NoSolrConnectionFoundException;
31
use ApacheSolrForTypo3\Solr\Site;
32
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
33
use ApacheSolrForTypo3\Solr\System\Records\Pages\PagesRepository;
34
use ApacheSolrForTypo3\Solr\System\Solr\Document\Document;
35
use ApacheSolrForTypo3\Solr\System\Solr\ResponseAdapter;
36
use ApacheSolrForTypo3\Solr\System\Solr\SolrConnection;
37
use ApacheSolrForTypo3\Solr\Util;
38
use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider;
39
use TYPO3\CMS\Core\Utility\GeneralUtility;
40
use TYPO3\CMS\Frontend\Page\PageRepository;
41
42
/**
43
 * A general purpose indexer to be used for indexing of any kind of regular
44
 * records like tt_news, tt_address, and so on.
45
 * Specialized indexers can extend this class to handle advanced stuff like
46
 * category resolution in tt_news or file indexing.
47
 *
48
 * @author Ingo Renner <[email protected]>
49
 */
50
class Indexer extends AbstractIndexer
51
{
52
53
    # TODO change to singular $document instead of plural $documents
54
55
    /**
56
     * A Solr service instance to interact with the Solr server
57
     *
58
     * @var SolrConnection
59
     */
60
    protected $solr;
61
62
    /**
63
     * @var ConnectionManager
64
     */
65
    protected $connectionManager;
66
67
    /**
68
     * Holds options for a specific indexer
69
     *
70
     * @var array
71
     */
72
    protected $options = [];
73
74
    /**
75
     * To log or not to log... #Shakespeare
76
     *
77
     * @var bool
78
     */
79
    protected $loggingEnabled = false;
80
81
    /**
82
     * @var SolrLogManager
83
     */
84
    protected $logger = null;
85
86
    /**
87
     * @var PagesRepository
88
     */
89
    protected $pagesRepository;
90
91
    /**
92
     * @var Builder
93
     */
94
    protected $documentBuilder;
95
96
    /**
97
     * Constructor
98
     *
99
     * @param array $options array of indexer options
100
     * @param PagesRepository|null $pagesRepository
101
     * @param Builder|null $documentBuilder
102
     * @param SolrLogManager|null $logger
103
     * @param ConnectionManager|null $connectionManager
104
     */
105 36
    public function __construct(array $options = [], PagesRepository $pagesRepository = null, Builder $documentBuilder = null, SolrLogManager $logger = null, ConnectionManager $connectionManager = null)
106
    {
107 36
        $this->options = $options;
108 36
        $this->pagesRepository = $pagesRepository ?? GeneralUtility::makeInstance(PagesRepository::class);
109 36
        $this->documentBuilder = $documentBuilder ?? GeneralUtility::makeInstance(Builder::class);
110 36
        $this->logger = $logger ?? GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
111 36
        $this->connectionManager = $connectionManager ?? GeneralUtility::makeInstance(ConnectionManager::class);
112 36
    }
113
114
    /**
115
     * Indexes an item from the indexing queue.
116
     *
117
     * @param Item $item An index queue item
118
     * @return bool returns true when indexed, false when not
119
     */
120 20
    public function index(Item $item)
121
    {
122 20
        $indexed = true;
123
124 20
        $this->type = $item->getType();
125 20
        $this->setLogging($item);
126
127 20
        $solrConnections = $this->getSolrConnectionsByItem($item);
128 20
        foreach ($solrConnections as $systemLanguageUid => $solrConnection) {
129 20
            $this->solr = $solrConnection;
130
131 20
            if (!$this->indexItem($item, $systemLanguageUid)) {
132
                /*
133
                 * A single language voting for "not indexed" should make the whole
134
                 * item count as being not indexed, even if all other languages are
135
                 * indexed.
136
                 * If there is no translation for a single language, this item counts
137
                 * as TRUE since it's not an error which that should make the item
138
                 * being reindexed during another index run.
139
                 */
140 20
                $indexed = false;
141
            }
142
        }
143
144 20
        return $indexed;
145
    }
146
147
    /**
148
     * Creates a single Solr Document for an item in a specific language.
149
     *
150
     * @param Item $item An index queue item to index.
151
     * @param int $language The language to use.
152
     * @return bool TRUE if item was indexed successfully, FALSE on failure
153
     */
154 20
    protected function indexItem(Item $item, $language = 0)
155
    {
156 20
        $itemIndexed = false;
157 20
        $documents = [];
158
159 20
        $itemDocument = $this->itemToDocument($item, $language);
160 20
        if (is_null($itemDocument)) {
161
            /*
162
             * If there is no itemDocument, this means there was no translation
163
             * for this record. This should not stop the current item to count as
164
             * being valid because not-indexing not-translated items is perfectly
165
             * fine.
166
             */
167 1
            return true;
168
        }
169
170 20
        $documents[] = $itemDocument;
171 20
        $documents = array_merge($documents, $this->getAdditionalDocuments($item, $language, $itemDocument));
172 20
        $documents = $this->processDocuments($item, $documents);
173 20
        $documents = $this->preAddModifyDocuments($item, $language, $documents);
174
175 20
        $response = $this->solr->getWriteService()->addDocuments($documents);
176 20
        if ($response->getHttpStatus() == 200) {
177 20
            $itemIndexed = true;
178
        }
179
180 20
        $this->log($item, $documents, $response);
181
182 20
        return $itemIndexed;
183
    }
184
185
    /**
186
     * Gets the full item record.
187
     *
188
     * This general record indexer simply gets the record from the item. Other
189
     * more specialized indexers may provide more data for their specific item
190
     * types.
191
     *
192
     * @param Item $item The item to be indexed
193
     * @param int $language Language Id (sys_language.uid)
194
     * @return array|NULL The full record with fields of data to be used for indexing or NULL to prevent an item from being indexed
195
     */
196 20
    protected function getFullItemRecord(Item $item, $language = 0)
197
    {
198 20
        Util::initializeTsfe($item->getRootPageUid(), $language);
199
200 20
        $systemLanguageContentOverlay = $GLOBALS['TSFE']->sys_language_contentOL;
201 20
        $itemRecord = $this->getItemRecordOverlayed($item, $language, $systemLanguageContentOverlay);
202
203
        /*
204
         * Skip disabled records. This happens if the default language record
205
         * is hidden but a certain translation isn't. Then the default language
206
         * document appears here but must not be indexed.
207
         */
208 20
        if (!empty($GLOBALS['TCA'][$item->getType()]['ctrl']['enablecolumns']['disabled'])
209 20
            && $itemRecord[$GLOBALS['TCA'][$item->getType()]['ctrl']['enablecolumns']['disabled']]
210
        ) {
211
            $itemRecord = null;
212
        }
213
214
        /*
215
         * Skip translation mismatching records. Sometimes the requested language
216
         * doesn't fit the returned language. This might happen with content fallback
217
         * and is perfectly fine in general.
218
         * But if the requested language doesn't match the returned language and
219
         * the given record has no translation parent, the indexqueue_item most
220
         * probably pointed to a non-translated language record that is dedicated
221
         * to a very specific language. Now we have to avoid indexing this record
222
         * into all language cores.
223
         */
224 20
        $translationOriginalPointerField = 'l10n_parent';
225 20
        if (!empty($GLOBALS['TCA'][$item->getType()]['ctrl']['transOrigPointerField'])) {
226 19
            $translationOriginalPointerField = $GLOBALS['TCA'][$item->getType()]['ctrl']['transOrigPointerField'];
227
        }
228
229 20
        $languageField = $GLOBALS['TCA'][$item->getType()]['ctrl']['languageField'];
230 20
        if ($itemRecord[$translationOriginalPointerField] == 0
231 20
            && $systemLanguageContentOverlay != 1
232 20
            && !empty($languageField)
233 20
            && $itemRecord[$languageField] != $language
234 20
            && $itemRecord[$languageField] != '-1'
235
        ) {
236 1
            $itemRecord = null;
237
        }
238
239 20
        if (!is_null($itemRecord)) {
240 20
            $itemRecord['__solr_index_language'] = $language;
241
        }
242
243 20
        return $itemRecord;
244
    }
245
246
    /**
247
     * Returns the overlayed item record.
248
     *
249
     * @param Item $item
250
     * @param int $language
251
     * @param string|null $systemLanguageContentOverlay
252
     * @return array|mixed|null
253
     */
254 20
    protected function getItemRecordOverlayed(Item $item, $language, $systemLanguageContentOverlay)
255
    {
256 20
        $itemRecord = $item->getRecord();
257
258 20
        if ($language > 0) {
259 6
            $page = GeneralUtility::makeInstance(PageRepository::class);
260 6
            $page->init(false);
261 6
            $itemRecord = $page->getRecordOverlay($item->getType(), $itemRecord, $language, $systemLanguageContentOverlay);
262
        }
263
264 20
        if (!$itemRecord) {
265
            $itemRecord = null;
266
        }
267
268 20
        return $itemRecord;
269
    }
270
271
    /**
272
     * Gets the configuration how to process an item's fields for indexing.
273
     *
274
     * @param Item $item An index queue item
275
     * @param int $language Language ID
276
     * @throws \RuntimeException
277
     * @return array Configuration array from TypoScript
278
     */
279 20
    protected function getItemTypeConfiguration(Item $item, $language = 0)
280
    {
281 20
        $indexConfigurationName = $item->getIndexingConfigurationName();
282 20
        $fields = $this->getFieldConfigurationFromItemRecordPage($item, $language, $indexConfigurationName);
283 20
        if (count($fields) === 0) {
284 1
            $fields = $this->getFieldConfigurationFromItemRootPage($item, $language, $indexConfigurationName);
285 1
            if (count($fields) === 0) {
286
                throw new \RuntimeException('The item indexing configuration "' . $item->getIndexingConfigurationName() .
287
                    '" on root page uid ' . $item->getRootPageUid() . ' could not be found!', 1455530112);
288
            }
289
        }
290
291 20
        return $fields;
292
    }
293
294
    /**
295
     * The method retrieves the field configuration of the items record page id (pid).
296
     *
297
     * @param Item $item
298
     * @param integer $language
299
     * @param string $indexConfigurationName
300
     * @return array
301
     */
302 20
    protected function getFieldConfigurationFromItemRecordPage(Item $item, $language, $indexConfigurationName)
303
    {
304
        try {
305 20
            $solrConfiguration = Util::getSolrConfigurationFromPageId($item->getRecordPageId(), true, $language);
306 19
            return $solrConfiguration->getIndexQueueFieldsConfigurationByConfigurationName($indexConfigurationName, []);
307 1
        } catch (\Exception $e) {
308 1
            return [];
309
        }
310
    }
311
312
    /**
313
     * The method returns the field configuration of the items root page id (uid of the related root page).
314
     *
315
     * @param Item $item
316
     * @param integer $language
317
     * @param string $indexConfigurationName
318
     * @return array
319
     */
320 1
    protected function getFieldConfigurationFromItemRootPage(Item $item, $language, $indexConfigurationName)
321
    {
322 1
        $solrConfiguration = Util::getSolrConfigurationFromPageId($item->getRootPageUid(), true, $language);
323 1
        if (empty($solrConfiguration->getIndexQueueAdditionalPageIdsByConfigurationName($indexConfigurationName))) {
324
            return [];
325
        }
326
327 1
        return $solrConfiguration->getIndexQueueFieldsConfigurationByConfigurationName($indexConfigurationName, []);
328
    }
329
330
    /**
331
     * Converts an item array (record) to a Solr document by mapping the
332
     * record's fields onto Solr document fields as configured in TypoScript.
333
     *
334
     * @param Item $item An index queue item
335
     * @param int $language Language Id
336
     * @return Document The Solr document converted from the record
337
     */
338 20
    protected function itemToDocument(Item $item, $language = 0)
339
    {
340 20
        $document = null;
341
342 20
        $itemRecord = $this->getFullItemRecord($item, $language);
343 20
        if (!is_null($itemRecord)) {
344 20
            $itemIndexingConfiguration = $this->getItemTypeConfiguration($item, $language);
345 20
            $document = $this->getBaseDocument($item, $itemRecord);
346 20
            $document = $this->addDocumentFieldsFromTyposcript($document, $itemIndexingConfiguration, $itemRecord);
347
        }
348
349 20
        return $document;
350
    }
351
352
    /**
353
     * Creates a Solr document with the basic / core fields set already.
354
     *
355
     * @param Item $item The item to index
356
     * @param array $itemRecord The record to use to build the base document
357
     * @return Document A basic Solr document
358
     */
359 20
    protected function getBaseDocument(Item $item, array $itemRecord)
360
    {
361 20
        $type = $item->getType();
362 20
        $rootPageUid = $item->getRootPageUid();
363 20
        $accessRootLine = $this->getAccessRootline($item);
364 20
        return $this->documentBuilder->fromRecord($itemRecord, $type, $rootPageUid, $accessRootLine);
365
    }
366
367
    /**
368
     * Generates an Access Rootline for an item.
369
     *
370
     * @param Item $item Index Queue item to index.
371
     * @return string The Access Rootline for the item
372
     */
373 20
    protected function getAccessRootline(Item $item)
374
    {
375 20
        $accessRestriction = '0';
376 20
        $itemRecord = $item->getRecord();
377
378
        // TODO support access restrictions set on storage page
379
380 20
        if (isset($GLOBALS['TCA'][$item->getType()]['ctrl']['enablecolumns']['fe_group'])) {
381 1
            $accessRestriction = $itemRecord[$GLOBALS['TCA'][$item->getType()]['ctrl']['enablecolumns']['fe_group']];
382
383 1
            if (empty($accessRestriction)) {
384
                // public
385 1
                $accessRestriction = '0';
386
            }
387
        }
388
389 20
        return 'r:' . $accessRestriction;
390
    }
391
392
    /**
393
     * Sends the documents to the field processing service which takes care of
394
     * manipulating fields as defined in the field's configuration.
395
     *
396
     * @param Item $item An index queue item
397
     * @param array $documents An array of Apache_Solr_Document objects to manipulate.
398
     * @return Document[] array Array of manipulated Document objects.
399
     */
400 20
    protected function processDocuments(Item $item, array $documents)
401
    {
402
        // needs to respect the TS settings for the page the item is on, conditions may apply
403 20
        $solrConfiguration = Util::getSolrConfigurationFromPageId($item->getRootPageUid());
404 20
        $fieldProcessingInstructions = $solrConfiguration->getIndexFieldProcessingInstructionsConfiguration();
405
406
        // same as in the FE indexer
407 20
        if (is_array($fieldProcessingInstructions)) {
0 ignored issues
show
introduced by
The condition is_array($fieldProcessingInstructions) is always true.
Loading history...
408 20
            $service = GeneralUtility::makeInstance(Service::class);
409 20
            $service->processDocuments($documents, $fieldProcessingInstructions);
410
        }
411
412 20
        return $documents;
413
    }
414
415
    /**
416
     * Allows third party extensions to provide additional documents which
417
     * should be indexed for the current item.
418
     *
419
     * @param Item $item The item currently being indexed.
420
     * @param int $language The language uid currently being indexed.
421
     * @param Document $itemDocument The document representing the item for the given language.
422
     * @return Document[] array An array of additional Document objects to index.
423
     */
424 24
    protected function getAdditionalDocuments(Item $item, $language, Document $itemDocument)
425
    {
426 24
        $documents = [];
427
428 24
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['indexItemAddDocuments'])) {
429 4
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['indexItemAddDocuments'] as $classReference) {
430 4
                if (!class_exists($classReference)) {
431 2
                    throw new \InvalidArgumentException('Class does not exits' . $classReference, 1490363487);
432
                }
433 2
                $additionalIndexer = GeneralUtility::makeInstance($classReference);
434 2
                if ($additionalIndexer instanceof AdditionalIndexQueueItemIndexer) {
435 1
                    $additionalDocuments = $additionalIndexer->getAdditionalItemDocuments($item, $language, $itemDocument);
436
437 1
                    if (is_array($additionalDocuments)) {
438 1
                        $documents = array_merge($documents,
439 1
                            $additionalDocuments);
440
                    }
441
                } else {
442 1
                    throw new \UnexpectedValueException(
443 1
                        get_class($additionalIndexer) . ' must implement interface ' . AdditionalIndexQueueItemIndexer::class,
444 2
                        1326284551
445
                    );
446
                }
447
            }
448
        }
449 21
        return $documents;
450
    }
451
452
    /**
453
     * Provides a hook to manipulate documents right before they get added to
454
     * the Solr index.
455
     *
456
     * @param Item $item The item currently being indexed.
457
     * @param int $language The language uid of the documents
458
     * @param array $documents An array of documents to be indexed
459
     * @return array An array of modified documents
460
     */
461 20
    protected function preAddModifyDocuments(Item $item, $language, array $documents)
462
    {
463 20
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['preAddModifyDocuments'])) {
464
            foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['IndexQueueIndexer']['preAddModifyDocuments'] as $classReference) {
465
                $documentsModifier = GeneralUtility::makeInstance($classReference);
466
467
                if ($documentsModifier instanceof PageIndexerDocumentsModifier) {
468
                    $documents = $documentsModifier->modifyDocuments($item, $language, $documents);
469
                } else {
470
                    throw new \RuntimeException(
471
                        'The class "' . get_class($documentsModifier)
472
                        . '" registered as document modifier in hook
473
							preAddModifyDocuments must implement interface
474
							ApacheSolrForTypo3\Solr\IndexQueue\PageIndexerDocumentsModifier',
475
                        1309522677
476
                    );
477
                }
478
            }
479
        }
480
481 20
        return $documents;
482
    }
483
484
    // Initialization
485
486
    /**
487
     * Gets the Solr connections applicable for an item.
488
     *
489
     * The connections include the default connection and connections to be used
490
     * for translations of an item.
491
     *
492
     * @param Item $item An index queue item
493
     * @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
494
     */
495 22
    protected function getSolrConnectionsByItem(Item $item)
496
    {
497 22
        $solrConnections = [];
498
499 22
        $pageId = $item->getRootPageUid();
500 22
        if ($item->getType() === 'pages') {
501 2
            $pageId = $item->getRecordUid();
502
        }
503
504
        // Solr configurations possible for this item
505 22
        $site = $item->getSite();
506
507 22
        $solrConfigurationsBySite = $this->connectionManager->getConfigurationsBySite($site);
508 22
        $siteLanguages = [];
509 22
        foreach ($solrConfigurationsBySite as $solrConfiguration) {
510 22
            $siteLanguages[] = $solrConfiguration['language'];
511
        }
512
513 22
        $defaultLanguageUid = $this->getDefaultLanguageUid($item, $site->getRootPage(), $siteLanguages);
514 22
        $translationOverlays = $this->getTranslationOverlaysWithConfiguredSite($pageId, $site, $defaultLanguageUid, $siteLanguages);
515
516 22
        $defaultConnection = $this->connectionManager->getConnectionByPageId($pageId, 0, $item->getMountPointIdentifier());
517 22
        $translationConnections = $this->getConnectionsForIndexableLanguages($translationOverlays);
518
519 22
        if ($defaultLanguageUid == 0) {
520 21
            $solrConnections[0] = $defaultConnection;
521
        }
522
523 22
        foreach ($translationConnections as $systemLanguageUid => $solrConnection) {
524 7
            $solrConnections[$systemLanguageUid] = $solrConnection;
525
        }
526 22
        return $solrConnections;
527
    }
528
529
    /**
530
     * Retrieves only translation overlays where a solr site is configured.
531
     *
532
     * @param int $pageId
533
     * @param Site $site
534
     * @param int $defaultLanguageUid
535
     * @param $siteLanguages
536
     * @return array
537
     */
538 22
    protected function getTranslationOverlaysWithConfiguredSite($pageId, Site $site, $defaultLanguageUid, $siteLanguages)
539
    {
540 22
        $translationOverlays = $this->getTranslationOverlaysForPage($pageId, $site->getSysLanguageMode($defaultLanguageUid));
541
542 22
        foreach ($translationOverlays as $key => $translationOverlay) {
543 7
            if (!in_array($translationOverlay['sys_language_uid'], $siteLanguages)) {
544 7
                unset($translationOverlays[$key]);
545
            }
546
        }
547
548 22
        return $translationOverlays;
549
    }
550
551
    /**
552
     * @param Item $item An index queue item
553
     * @param array $rootPage
554
     * @param array $siteLanguages
555
     *
556
     * @return int
557
     * @throws \RuntimeException
558
     */
559 22
    private function getDefaultLanguageUid(Item $item, array $rootPage, array $siteLanguages)
560
    {
561 22
        $defaultLanguageUid = 0;
562 22
        if (($rootPage['l18n_cfg'] & 1) == 1 && count($siteLanguages) > 1) {
563 1
            unset($siteLanguages[array_search('0', $siteLanguages)]);
564 1
            $defaultLanguageUid = $siteLanguages[min(array_keys($siteLanguages))];
565 21
        } elseif (($rootPage['l18n_cfg'] & 1) == 1 && count($siteLanguages) == 1) {
566
            $message = 'Root page ' . (int)$item->getRootPageUid() . ' is set to hide default translation, but no other language is configured!';
567
            throw new \RuntimeException($message);
568
        }
569
570 22
        return $defaultLanguageUid;
571
    }
572
573
    /**
574
     * Finds the alternative page language overlay records for a page based on
575
     * the sys_language_mode.
576
     *
577
     * Possible Language Modes:
578
     * 1) content_fallback --> all languages
579
     * 2) strict --> available languages with page overlay
580
     * 3) ignore --> available languages with page overlay
581
     * 4) unknown mode or blank --> all languages
582
     *
583
     * @param int $pageId Page ID.
584
     * @param string $languageMode
585
     * @return array An array of translation overlays (or fake overlays) found for the given page.
586
     */
587 22
    protected function getTranslationOverlaysForPage($pageId, $languageMode)
588
    {
589 22
        $translationOverlays = [];
590 22
        $pageId = intval($pageId);
591
592 22
        $languageModes = ['content_fallback', 'strict', 'ignore'];
593 22
        $hasOverlayMode = in_array($languageMode, $languageModes,
594 22
            true);
595 22
        $isContentFallbackMode = ($languageMode === 'content_fallback');
596
597 22
        if ($hasOverlayMode && !$isContentFallbackMode) {
598 6
            $translationOverlays = $this->pagesRepository->findTranslationOverlaysByPageId($pageId);
599
        } else {
600
            // ! If no sys_language_mode is configured, all languages will be indexed !
601 16
            $languages = $this->getSystemLanguages();
602 16
            foreach ($languages as $language) {
603 15
                if ($language['uid'] <= 0) {
604 15
                    continue;
605
                }
606 1
                $translationOverlays[] = [
607 1
                    'pid' => $pageId,
608 1
                    'l10n_parent' => $pageId,
609 1
                    'sys_language_uid' => $language['uid'],
610
                ];
611
            }
612
        }
613
614 22
        return $translationOverlays;
615
    }
616
617
    /**
618
     * Returns an array of system languages.
619
     *
620
     * @return array
621
     */
622 15
    protected function getSystemLanguages()
623
    {
624 15
        return GeneralUtility::makeInstance(TranslationConfigurationProvider::class)->getSystemLanguages();
625
    }
626
627
    /**
628
     * Checks for which languages connections have been configured and returns
629
     * these connections.
630
     *
631
     * @param array $translationOverlays An array of translation overlays to check for configured connections.
632
     * @return array An array of ApacheSolrForTypo3\Solr\System\Solr\SolrConnection connections.
633
     */
634 22
    protected function getConnectionsForIndexableLanguages(array $translationOverlays)
635
    {
636 22
        $connections = [];
637
638 22
        foreach ($translationOverlays as $translationOverlay) {
639
            // @todo usage of pid can be removed when TYPO3 8 compatibility is dropped
640 7
            $pageId = (Util::getIsTYPO3VersionBelow9()) ? $translationOverlay['pid'] : $translationOverlay['l10n_parent'];
641 7
            $languageId = $translationOverlay['sys_language_uid'];
642
643
            try {
644 7
                $connection = $this->connectionManager->getConnectionByPageId($pageId, $languageId);
645 7
                $connections[$languageId] = $connection;
646 7
            } catch (NoSolrConnectionFoundException $e) {
647
                // ignore the exception as we seek only those connections
648
                // actually available
649
            }
650
        }
651
652 22
        return $connections;
653
    }
654
655
    // Utility methods
656
657
    // FIXME extract log() and setLogging() to ApacheSolrForTypo3\Solr\IndexQueue\AbstractIndexer
658
    // FIXME extract an interface Tx_Solr_IndexQueue_ItemInterface
659
660
    /**
661
     * Enables logging dependent on the configuration of the item's site
662
     *
663
     * @param Item $item An item being indexed
664
     * @return    void
665
     */
666 21
    protected function setLogging(Item $item)
667
    {
668 21
        $solrConfiguration = Util::getSolrConfigurationFromPageId($item->getRootPageUid());
669 21
        $this->loggingEnabled = $solrConfiguration->getLoggingIndexingQueueOperationsByConfigurationNameWithFallBack(
670 21
            $item->getIndexingConfigurationName()
671
        );
672 21
    }
673
674
    /**
675
     * Logs the item and what document was created from it
676
     *
677
     * @param Item $item The item that is being indexed.
678
     * @param array $itemDocuments An array of Solr documents created from the item's data
679
     * @param ResponseAdapter $response The Solr response for the particular index document
680
     */
681 20
    protected function log(Item $item, array $itemDocuments, ResponseAdapter $response)
682
    {
683 20
        if (!$this->loggingEnabled) {
684 20
            return;
685
        }
686
687
        $message = 'Index Queue indexing ' . $item->getType() . ':' . $item->getRecordUid() . ' - ';
688
689
        // preparing data
690
        $documents = [];
691
        foreach ($itemDocuments as $document) {
692
            $documents[] = (array)$document;
693
        }
694
695
        $logData = ['item' => (array)$item, 'documents' => $documents, 'response' => (array)$response];
696
697
        if ($response->getHttpStatus() == 200) {
698
            $severity = SolrLogManager::NOTICE;
699
            $message .= 'Success';
700
        } else {
701
            $severity = SolrLogManager::ERROR;
702
            $message .= 'Failure';
703
704
            $logData['status'] = $response->getHttpStatus();
705
            $logData['status message'] = $response->getHttpStatusMessage();
706
        }
707
708
        $this->logger->log($severity, $message, $logData);
709
    }
710
}
711