Passed
Push — master ( 8c1190...8a69bb )
by Timo
04:59
created

Classes/Domain/Site/SiteRepository.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace ApacheSolrForTypo3\Solr\Domain\Site;
4
5
/***************************************************************
6
 *  Copyright notice
7
 *
8
 *  (c) 2017 - Thomas Hohn <[email protected]>
9
 *  All rights reserved
10
 *
11
 *  This script is part of the TYPO3 project. The TYPO3 project is
12
 *  free software; you can redistribute it and/or modify
13
 *  it under the terms of the GNU General Public License as published by
14
 *  the Free Software Foundation; either version 3 of the License, or
15
 *  (at your option) any later version.
16
 *
17
 *  The GNU General Public License can be found at
18
 *  http://www.gnu.org/copyleft/gpl.html.
19
 *
20
 *  This script is distributed in the hope that it will be useful,
21
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 *  GNU General Public License for more details.
24
 *
25
 *  This copyright notice MUST APPEAR in all copies of the script!
26
 ***************************************************************/
27
28
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\RecordMonitor\Helper\RootPageResolver;
29
use ApacheSolrForTypo3\Solr\System\Cache\TwoLevelCache;
30
use ApacheSolrForTypo3\Solr\System\Configuration\ExtensionConfiguration;
31
use ApacheSolrForTypo3\Solr\System\Records\Pages\PagesRepository;
32
use ApacheSolrForTypo3\Solr\System\Records\SystemLanguage\SystemLanguageRepository;
33
use ApacheSolrForTypo3\Solr\System\Service\SiteService;
34
use ApacheSolrForTypo3\Solr\System\Util\SiteUtility;
35
use ApacheSolrForTypo3\Solr\Util;
36
use TYPO3\CMS\Backend\Utility\BackendUtility;
37
use TYPO3\CMS\Core\Registry;
38
use TYPO3\CMS\Core\Site\SiteFinder;
39
use TYPO3\CMS\Core\Utility\GeneralUtility;
40
use TYPO3\CMS\Core\Utility\RootlineUtility;
41
use TYPO3\CMS\Frontend\Compatibility\LegacyDomainResolver;
42
43
/**
44
 * SiteRepository
45
 *
46
 * Responsible to retrieve instances of Site objects
47
 *
48
 * @author Thomas Hohn <[email protected]>
49
 */
50
class SiteRepository
51
{
52
    /**
53
     * Rootpage resolver
54
     *
55
     * @var RootPageResolver
56
     */
57
    protected $rootPageResolver;
58
59
    /**
60
     * @var TwoLevelCache
61
     */
62
    protected $runtimeCache;
63
64
    /**
65
     * @var Registry
66
     */
67
    protected $registry;
68
69
    /**
70
     * @var SiteFinder
71
     */
72
    protected $siteFinder;
73
74
    /**
75
     * @var ExtensionConfiguration
76
     */
77
    protected $extensionConfiguration;
78
79
    /**
80
     * SiteRepository constructor.
81
     *
82
     * @param RootPageResolver|null $rootPageResolver
83
     * @param TwoLevelCache|null $twoLevelCache
84
     * @param Registry|null $registry
85
     * @param SiteFinder|null $siteFinder
86
     * @param ExtensionConfiguration| null
87
     */
88 187
    public function __construct(RootPageResolver $rootPageResolver = null, TwoLevelCache $twoLevelCache = null, Registry $registry = null, SiteFinder $siteFinder = null, ExtensionConfiguration $extensionConfiguration = null)
89
    {
90 187
        $this->rootPageResolver = $rootPageResolver ?? GeneralUtility::makeInstance(RootPageResolver::class);
91 187
        $this->runtimeCache = $twoLevelCache ?? GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */'cache_runtime');
92 187
        $this->registry = $registry ?? GeneralUtility::makeInstance(Registry::class);
93 187
        $this->siteFinder = $siteFinder ?? GeneralUtility::makeInstance(SiteFinder::class);
94 187
        $this->extensionConfiguration = $extensionConfiguration ?? GeneralUtility::makeInstance(ExtensionConfiguration::class);
95 187
    }
96
97
    /**
98
     * Gets the Site for a specific page Id.
99
     *
100
     * @param int $pageId The page Id to get a Site object for.
101
     * @param string $mountPointIdentifier
102
     * @return SiteInterface Site for the given page Id.
103
     */
104 111
    public function getSiteByPageId($pageId, $mountPointIdentifier = '')
105
    {
106 111
        $rootPageId = $this->rootPageResolver->getRootPageId($pageId, false, $mountPointIdentifier);
107 111
        return $this->getSiteByRootPageId($rootPageId);
108
    }
109
110
    /**
111
     * Gets the Site for a specific root page Id.
112
     *
113
     * @param int $rootPageId Root page Id to get a Site object for.
114
     * @return SiteInterface Site for the given page Id.
115
     */
116 128
    public function getSiteByRootPageId($rootPageId)
117
    {
118 128
        $cacheId = 'SiteRepository' . '_' . 'getSiteByPageId' . '_' . $rootPageId;
119
120 128
        $methodResult = $this->runtimeCache->get($cacheId);
121 128
        if (!empty($methodResult)) {
122 96
            return $methodResult;
123
        }
124
125 128
        $methodResult = $this->buildSite($rootPageId);
126 121
        $this->runtimeCache->set($cacheId, $methodResult);
127
128 121
        return $methodResult;
129
    }
130
131
    /**
132
     * Returns the first available Site.
133
     *
134
     * @param bool $stopOnInvalidSite
135
     * @throws \Exception
136
     * @return Site
137
     */
138 19
    public function getFirstAvailableSite($stopOnInvalidSite = false)
139
    {
140 19
        $sites = $this->getAvailableSites($stopOnInvalidSite);
141 19
        return array_shift($sites);
142
    }
143
144
    /**
145
     * Gets all available TYPO3 sites with Solr configured.
146
     *
147
     * @param bool $stopOnInvalidSite
148
     * @throws \Exception
149
     * @return Site[] An array of availablesites
150
     */
151 73
    public function getAvailableSites($stopOnInvalidSite = false)
152
    {
153 73
        $cacheId = 'SiteRepository' . '_' . 'getAvailableSites';
154
155 73
        $sites = $this->runtimeCache->get($cacheId);
156 73
        if (!empty($sites)) {
157 13
            return $sites;
158
        }
159
160 73
        if ($this->extensionConfiguration->getIsAllowLegacySiteModeEnabled()) {
161
            $sites = $this->getAvailableLegacySites($stopOnInvalidSite);
162
        } else {
163 73
            $sites = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
164
        }
165
166 73
        $this->runtimeCache->set($cacheId, $sites);
167
168 73
        return $sites;
169
    }
170
171
    /**
172
     * @deprecated deprecated since EXT:solr 10 will be removed with EXT:solr 11 please use the site handling now
173
     * @param bool $stopOnInvalidSite
174
     * @return array
175
     */
176
    protected function getAvailableLegacySites(bool $stopOnInvalidSite): array
177
    {
178
        $serversFromRegistry = $this->getSolrServersFromRegistry();
179
        if(empty($serversFromRegistry)) {
180
            return [];
181
        }
182
183
        trigger_error('solr:deprecation: Method getAvailableLegacySites is deprecated since EXT:solr 10 and will be removed in v11, please use the site handling to configure EXT:solr', E_USER_DEPRECATED);
184
        $legacySites = [];
185
        foreach ($serversFromRegistry as $server) {
186
            if (isset($legacySites[$server['rootPageUid']])) {
187
                //get each site only once
188
                continue;
189
            }
190
191
            try {
192
                $legacySites[$server['rootPageUid']] = $this->buildSite($server['rootPageUid']);
193
            } catch (\InvalidArgumentException $e) {
194
                if ($stopOnInvalidSite) {
195
                    throw $e;
196
                }
197
            }
198
        }
199
        return $legacySites;
200
    }
201
202
203
    /**
204
     * @param bool $stopOnInvalidSite
205
     * @return array
206
     * @throws \Exception
207
     */
208 73
    protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): array
209
    {
210 73
        $typo3ManagedSolrSites = [];
211 73
        $typo3Sites = $this->siteFinder->getAllSites();
212 73
        foreach ($typo3Sites as $typo3Site) {
213
            try {
214 73
                $rootPageId = $typo3Site->getRootPageId();
215 73
                if (isset($typo3ManagedSolrSites[$rootPageId])) {
216
                    //get each site only once
217
                    continue;
218
                }
219
220 73
                $typo3ManagedSolrSites[$rootPageId] = $this->buildSite($rootPageId);
221
222 62
            } catch (\Exception $e) {
223 62
                if ($stopOnInvalidSite) {
224
                    throw $e;
225
                }
226
            }
227
        }
228 73
        return $typo3ManagedSolrSites;
229
    }
230
231
    /**
232
     * Gets the system languages (IDs) for which Solr connections have been
233
     * configured.
234
     *
235
     * @param Site $site
236
     * @return array
237
     * @throws \ApacheSolrForTypo3\Solr\NoSolrConnectionFoundException
238
     * @deprecated use $site->getConnectionConfig
239
     */
240
    public function getAllLanguages(Site $site)
241
    {
242
        trigger_error('solr:deprecation: Method getAllLanguages is deprecated since EXT:solr 10 and will be removed in v11, use  $site->getConnectionConfig instead', E_USER_DEPRECATED);
243
244
        $siteLanguages = [];
245
        foreach ($site->getAllSolrConnectionConfigurations() as $solrConnectionConfiguration) {
246
            $siteLanguages[] = $solrConnectionConfiguration['language'];
247
        }
248
249
        return $siteLanguages;
250
    }
251
252
    /**
253
     * Creates an instance of the Site object.
254
     *
255
     * @param integer $rootPageId
256
     * @throws \InvalidArgumentException
257
     * @return SiteInterface
258
     */
259 162
    protected function buildSite($rootPageId)
260
    {
261 162
        if (empty($rootPageId)) {
262
            throw new \InvalidArgumentException('Root page id can not be empty');
263
        }
264 162
        $rootPageRecord = (array)BackendUtility::getRecord('pages', $rootPageId);
265
266 162
        $this->validateRootPageRecord($rootPageId, $rootPageRecord);
267
268
        //@todo The handling of the legacy site can be removed in EXT:solr 11
269 151
        if (!SiteUtility::getIsSiteManagedSite($rootPageId) && $this->extensionConfiguration->getIsAllowLegacySiteModeEnabled()) {
270
            return $this->buildLegacySite($rootPageRecord);
271
        }
272
273 151
        return $this->buildTypo3ManagedSite($rootPageRecord);
274
    }
275
276
    /**
277
     * Retrieves the default language by the rootPageId of a site.
278
     *
279
     * @param int $rootPageId
280
     * @return int|mixed
281
     * @deprecated Use Site directly
282
     */
283
    protected function getDefaultLanguage($rootPageId)
284
    {
285
        trigger_error('solr:deprecation: Method getDefaultLanguage is deprecated since EXT:solr 10 and will be removed in v11, use  the site directly instead', E_USER_DEPRECATED);
286
287
        $siteDefaultLanguage = 0;
288
289
        $configuration = Util::getConfigurationFromPageId($rootPageId, 'config');
290
291
        $siteDefaultLanguage = $configuration->getValueByPathOrDefaultValue('sys_language_uid', $siteDefaultLanguage);
292
        // default language is set through default L GET parameter -> overruling config.sys_language_uid
293
        $siteDefaultLanguage = $configuration->getValueByPathOrDefaultValue('defaultGetVars.L', $siteDefaultLanguage);
294
295
        return $siteDefaultLanguage;
296
    }
297
298
    /**
299
     * Retrieves the configured solr servers from the registry.
300
     *
301
     * @deprecated This method is only required for old solr based sites.
302
     * @return array
303
     */
304
    protected function getSolrServersFromRegistry()
305
    {
306
        trigger_error('solr:deprecation: Method getSolrServersFromRegistry is deprecated since EXT:solr 10 and will be removed in v11, use sitehanlding instead', E_USER_DEPRECATED);
307
308
        $servers = (array)$this->registry->get('tx_solr', 'servers', []);
309
        return $servers;
310
    }
311
312
    /**
313
     * @param $rootPageId
314
     * @deprecated This method is only required for old solr based sites.
315
     * @return NULL|string
316
     */
317
    protected function getDomainFromConfigurationOrFallbackToDomainRecord($rootPageId)
318
    {
319
        trigger_error('solr:deprecation: Method getDomainFromConfigurationOrFallbackToDomainRecord is deprecated since EXT:solr 10 and will be removed in v11, use sitehanlding instead', E_USER_DEPRECATED);
320
321
        /** @var $siteService SiteService */
322
        $siteService = GeneralUtility::makeInstance(SiteService::class);
323
        $domain = $siteService->getFirstDomainForRootPage($rootPageId);
324
        if ($domain === '') {
325
            $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $rootPageId);
326
            try {
327
                $rootLine = $rootlineUtility->get();
328
            } catch (\RuntimeException $e) {
329
                $rootLine = [];
330
            }
331
            $domain = $this->firstDomainRecordFromLegacyDomainResolver($rootLine);
332
            return (string)$domain;
333
        }
334
335
        return $domain;
336
    }
337
338
    /**
339
     * @param $rootLine
340
     * @return null|string
341
     */
342
    private function firstDomainRecordFromLegacyDomainResolver($rootLine)
343
    {
344
        trigger_error('Method firstDomainRecordFromLegacyDomainResolver is deprecated since EXT:solr 10 and will be removed in v11, use sitehandling instead.', E_USER_DEPRECATED);
345
        $domainResolver = GeneralUtility::makeInstance(LegacyDomainResolver::class);
346
        foreach ($rootLine as $row) {
347
            $domain = $domainResolver->matchRootPageId($row['uid']);
348
            if (is_array($domain)) {
349
                return rtrim($domain['domainName'], '/');
350
            }
351
        }
352
        return null;
353
    }
354
355
    /**
356
     * @param string $domain
357
     * @return string
358
     */
359 151
    protected function getSiteHashForDomain($domain)
360
    {
361
        /** @var $siteHashService SiteHashService */
362 151
        $siteHashService = GeneralUtility::makeInstance(SiteHashService::class);
363 151
        $siteHash = $siteHashService->getSiteHashForDomain($domain);
364 151
        return $siteHash;
365
    }
366
367
    /**
368
     * @param int $rootPageId
369
     * @param array $rootPageRecord
370
     * @throws \InvalidArgumentException
371
     */
372 162
    protected function validateRootPageRecord($rootPageId, $rootPageRecord)
373
    {
374 162
        if (empty($rootPageRecord)) {
375 67
            throw new \InvalidArgumentException(
376 67
                'The rootPageRecord for the given rootPageRecord ID \'' . $rootPageId . '\' could not be found in the database and can therefore not be used as site root rootPageRecord.',
377 67
                1487326416
378
            );
379
        }
380
381 152
        if (!Site::isRootPage($rootPageRecord)) {
382 3
            throw new \InvalidArgumentException(
383 3
                'The rootPageRecord for the given rootPageRecord ID \'' . $rootPageId . '\' is not marked as root rootPageRecord and can therefore not be used as site root rootPageRecord.',
384 3
                1309272922
385
            );
386
        }
387 151
    }
388
389
    /**
390
     *
391
     * @param array $rootPageRecord
392
     * @return LegacySite
393
     * @throws Exception\InvalidSiteConfigurationCombinationException
394
     * @deprecated buildLegacySite is deprecated and will be removed in EXT:solr 11. Please configure your system with the TYPO3 sitehandling
395
     */
396
    protected function buildLegacySite($rootPageRecord): LegacySite
397
    {
398
        trigger_error('solr:deprecation: You are using EXT:solr without sitehandling. This setup is deprecated and will be removed in EXT:solr 11', E_USER_DEPRECATED);
399
400
        if (!$this->extensionConfiguration->getIsAllowLegacySiteModeEnabled()) {
401
            throw new Exception\InvalidSiteConfigurationCombinationException('It was tried to boot legacy site configuration, but allowLegacySiteMode is not enabled. ' .
402
                'Please use site handling feature or enable legacy mode under "Settings":>"Extension Configuration":>"solr"', 1567770263);
403
        }
404
405
        $solrConfiguration = Util::getSolrConfigurationFromPageId($rootPageRecord['uid']);
406
        $domain = $this->getDomainFromConfigurationOrFallbackToDomainRecord($rootPageRecord['uid']);
407
        $siteHash = $this->getSiteHashForDomain($domain);
408
        $defaultLanguage = $this->getDefaultLanguage($rootPageRecord['uid']);
409
        $pageRepository = GeneralUtility::makeInstance(PagesRepository::class);
410
        $availableLanguageIds = GeneralUtility::makeInstance(SystemLanguageRepository::class)->findSystemLanguages();
411
412
        return GeneralUtility::makeInstance(
413
            LegacySite::class,
414
            /** @scrutinizer ignore-type */
415
            $solrConfiguration,
416
            /** @scrutinizer ignore-type */
417
            $rootPageRecord,
418
            /** @scrutinizer ignore-type */
419
            $domain,
420
            /** @scrutinizer ignore-type */
421
            $siteHash,
422
            /** @scrutinizer ignore-type */
423
            $pageRepository,
424
            /** @scrutinizer ignore-type */
425
            $defaultLanguage,
426
            /** @scrutinizer ignore-type */
427
            $availableLanguageIds
428
        );
429
    }
430
431
    /**
432
     * @param array $rootPageRecord
433
     * @return Typo3ManagedSite
434
     */
435 151
    protected function buildTypo3ManagedSite(array $rootPageRecord): Typo3ManagedSite
436
    {
437 151
        $solrConfiguration = Util::getSolrConfigurationFromPageId($rootPageRecord['uid']);
438
        /** @var \TYPO3\CMS\Core\Site\Entity\Site $typo3Site */
439 151
        $typo3Site = $this->siteFinder->getSiteByPageId($rootPageRecord['uid']);
440 151
        $domain = $typo3Site->getBase()->getHost();
441
442 151
        $siteHash = $this->getSiteHashForDomain($domain);
443 151
        $defaultLanguage = $typo3Site->getDefaultLanguage()->getLanguageId();
444 151
        $pageRepository = GeneralUtility::makeInstance(PagesRepository::class);
445 151
        $availableLanguageIds = array_map(function($language) {
446 151
            return $language->getLanguageId();
447 151
        }, $typo3Site->getLanguages());
448
449 151
        $solrConnectionConfigurations = [];
450
451 151
        foreach ($availableLanguageIds as $languageUid) {
452 151
            $solrEnabled = SiteUtility::getConnectionProperty($typo3Site, 'enabled', $languageUid, 'read', true);
0 ignored issues
show
true of type true is incompatible with the type null|string expected by parameter $defaultValue of ApacheSolrForTypo3\Solr\...getConnectionProperty(). ( Ignorable by Annotation )

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

452
            $solrEnabled = SiteUtility::getConnectionProperty($typo3Site, 'enabled', $languageUid, 'read', /** @scrutinizer ignore-type */ true);
Loading history...
453 151
            if ($solrEnabled) {
454 151
                $solrConnectionConfigurations[$languageUid] = [
455 151
                    'connectionKey' =>  $rootPageRecord['uid'] . '|' . $languageUid,
456 151
                    'rootPageTitle' => $rootPageRecord['title'],
457 151
                    'rootPageUid' => $rootPageRecord['uid'],
458
                    'read' => [
459 151
                        'scheme' => SiteUtility::getConnectionProperty($typo3Site, 'scheme', $languageUid, 'read', 'http'),
460 151
                        'host' => SiteUtility::getConnectionProperty($typo3Site, 'host', $languageUid, 'read', 'localhost'),
461 151
                        'port' => (int)SiteUtility::getConnectionProperty($typo3Site, 'port', $languageUid, 'read', 8983),
462
                        // @todo: transform core to path
463
                        'path' =>
464 151
                            SiteUtility::getConnectionProperty($typo3Site, 'path', $languageUid, 'read', '/solr/') .
465 151
                            SiteUtility::getConnectionProperty($typo3Site, 'core', $languageUid, 'read', 'core_en') . '/' ,
466 151
                        'username' => SiteUtility::getConnectionProperty($typo3Site, 'username', $languageUid, 'read', ''),
467 151
                        'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'read', ''),
468 151
                        'timeout' => SiteUtility::getConnectionProperty($typo3Site, 'timeout', $languageUid, 'read', 0)
469
                    ],
470
                    'write' => [
471 151
                        'scheme' => SiteUtility::getConnectionProperty($typo3Site, 'scheme', $languageUid, 'write', 'http'),
472 151
                        'host' => SiteUtility::getConnectionProperty($typo3Site, 'host', $languageUid, 'write', 'localhost'),
473 151
                        'port' => (int)SiteUtility::getConnectionProperty($typo3Site, 'port', $languageUid, 'write', 8983),
474
                        // @todo: transform core to path
475
                        'path' =>
476 151
                            SiteUtility::getConnectionProperty($typo3Site, 'path', $languageUid, 'read', '/solr/') .
477 151
                            SiteUtility::getConnectionProperty($typo3Site, 'core', $languageUid, 'read', 'core_en') . '/' ,
478 151
                        'username' => SiteUtility::getConnectionProperty($typo3Site, 'username', $languageUid, 'write', ''),
479 151
                        'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'write', ''),
480 151
                        'timeout' => SiteUtility::getConnectionProperty($typo3Site, 'timeout', $languageUid, 'write', 0)
481
                    ],
482
483 151
                    'language' => $languageUid
484
                ];
485
            }
486
        }
487
488 151
        return GeneralUtility::makeInstance(
489 151
            Typo3ManagedSite::class,
490
            /** @scrutinizer ignore-type */
491 151
            $solrConfiguration,
492
            /** @scrutinizer ignore-type */
493 151
            $rootPageRecord,
494
            /** @scrutinizer ignore-type */
495 151
            $domain,
496
            /** @scrutinizer ignore-type */
497 151
            $siteHash,
498
            /** @scrutinizer ignore-type */
499 151
            $pageRepository,
500
            /** @scrutinizer ignore-type */
501 151
            $defaultLanguage,
502
            /** @scrutinizer ignore-type */
503 151
            $availableLanguageIds,
504
            /** @scrutinizer ignore-type */
505 151
            $solrConnectionConfigurations,
506
            /** @scrutinizer ignore-type */
507 151
            $typo3Site
508
        );
509
    }
510
511
}
512