Issues (202)

Classes/IndexQueue/Indexer.php (4 issues)

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

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