Passed
Push — master ( 6b264d...5682bc )
by Timo
25:05
created

Indexer::getFieldConfigurationFromItemRecordPage()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

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