342 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			342 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace WapplerSystems\Meilisearch\Domain\Site;
 | 
						|
 | 
						|
/***************************************************************
 | 
						|
 *  Copyright notice
 | 
						|
 *
 | 
						|
 *  (c) 2017 - Thomas Hohn <tho@systime.dk>
 | 
						|
 *  All rights reserved
 | 
						|
 *
 | 
						|
 *  This script is part of the TYPO3 project. The TYPO3 project is
 | 
						|
 *  free software; you can redistribute it and/or modify
 | 
						|
 *  it under the terms of the GNU General Public License as published by
 | 
						|
 *  the Free Software Foundation; either version 3 of the License, or
 | 
						|
 *  (at your option) any later version.
 | 
						|
 *
 | 
						|
 *  The GNU General Public License can be found at
 | 
						|
 *  http://www.gnu.org/copyleft/gpl.html.
 | 
						|
 *
 | 
						|
 *  This script is distributed in the hope that it will be useful,
 | 
						|
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 *  GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 *  This copyright notice MUST APPEAR in all copies of the script!
 | 
						|
 ***************************************************************/
 | 
						|
 | 
						|
use WapplerSystems\Meilisearch\Domain\Index\Queue\RecordMonitor\Helper\RootPageResolver;
 | 
						|
use WapplerSystems\Meilisearch\FrontendEnvironment;
 | 
						|
use WapplerSystems\Meilisearch\System\Cache\TwoLevelCache;
 | 
						|
use WapplerSystems\Meilisearch\System\Configuration\ExtensionConfiguration;
 | 
						|
use WapplerSystems\Meilisearch\System\Records\Pages\PagesRepository;
 | 
						|
use WapplerSystems\Meilisearch\System\Util\SiteUtility;
 | 
						|
use TYPO3\CMS\Backend\Utility\BackendUtility;
 | 
						|
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
 | 
						|
use TYPO3\CMS\Core\Registry;
 | 
						|
use TYPO3\CMS\Core\Site\SiteFinder;
 | 
						|
use TYPO3\CMS\Core\Utility\GeneralUtility;
 | 
						|
 | 
						|
/**
 | 
						|
 * SiteRepository
 | 
						|
 *
 | 
						|
 * Responsible to retrieve instances of Site objects
 | 
						|
 *
 | 
						|
 * @author Thomas Hohn <tho@systime.dk>
 | 
						|
 */
 | 
						|
class SiteRepository
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * Rootpage resolver
 | 
						|
     *
 | 
						|
     * @var RootPageResolver
 | 
						|
     */
 | 
						|
    protected $rootPageResolver;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var TwoLevelCache
 | 
						|
     */
 | 
						|
    protected $runtimeCache;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var Registry
 | 
						|
     */
 | 
						|
    protected $registry;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var SiteFinder
 | 
						|
     */
 | 
						|
    protected $siteFinder;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var ExtensionConfiguration
 | 
						|
     */
 | 
						|
    protected $extensionConfiguration;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var FrontendEnvironment
 | 
						|
     */
 | 
						|
    protected $frontendEnvironment = null;
 | 
						|
 | 
						|
    /**
 | 
						|
     * SiteRepository constructor.
 | 
						|
     *
 | 
						|
     * @param RootPageResolver|null $rootPageResolver
 | 
						|
     * @param TwoLevelCache|null $twoLevelCache
 | 
						|
     * @param Registry|null $registry
 | 
						|
     * @param SiteFinder|null $siteFinder
 | 
						|
     * @param ExtensionConfiguration| null
 | 
						|
     */
 | 
						|
    public function __construct(
 | 
						|
        RootPageResolver $rootPageResolver = null,
 | 
						|
        TwoLevelCache $twoLevelCache = null,
 | 
						|
        Registry $registry = null,
 | 
						|
        SiteFinder $siteFinder = null,
 | 
						|
        ExtensionConfiguration $extensionConfiguration = null,
 | 
						|
        FrontendEnvironment $frontendEnvironment = null
 | 
						|
    )
 | 
						|
    {
 | 
						|
        $this->rootPageResolver = $rootPageResolver ?? GeneralUtility::makeInstance(RootPageResolver::class);
 | 
						|
        $this->runtimeCache = $twoLevelCache ?? GeneralUtility::makeInstance(TwoLevelCache::class, /** @scrutinizer ignore-type */'cache_runtime');
 | 
						|
        $this->registry = $registry ?? GeneralUtility::makeInstance(Registry::class);
 | 
						|
        $this->siteFinder = $siteFinder ?? GeneralUtility::makeInstance(SiteFinder::class);
 | 
						|
        $this->extensionConfiguration = $extensionConfiguration ?? GeneralUtility::makeInstance(ExtensionConfiguration::class);
 | 
						|
        $this->frontendEnvironment = $frontendEnvironment ?? GeneralUtility::makeInstance(FrontendEnvironment::class);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Gets the Site for a specific page Id.
 | 
						|
     *
 | 
						|
     * @param int $pageId The page Id to get a Site object for.
 | 
						|
     * @param string $mountPointIdentifier
 | 
						|
     * @return SiteInterface Site for the given page Id.
 | 
						|
     */
 | 
						|
    public function getSiteByPageId($pageId, $mountPointIdentifier = '')
 | 
						|
    {
 | 
						|
        $rootPageId = $this->rootPageResolver->getRootPageId($pageId, false, $mountPointIdentifier);
 | 
						|
        return $this->getSiteByRootPageId($rootPageId);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Gets the Site for a specific root page Id.
 | 
						|
     *
 | 
						|
     * @param int $rootPageId Root page Id to get a Site object for.
 | 
						|
     * @return SiteInterface Site for the given page Id.
 | 
						|
     */
 | 
						|
    public function getSiteByRootPageId($rootPageId)
 | 
						|
    {
 | 
						|
        $cacheId = 'SiteRepository' . '_' . 'getSiteByPageId' . '_' . $rootPageId;
 | 
						|
 | 
						|
        $methodResult = $this->runtimeCache->get($cacheId);
 | 
						|
        if (!empty($methodResult)) {
 | 
						|
            return $methodResult;
 | 
						|
        }
 | 
						|
 | 
						|
        $methodResult = $this->buildSite($rootPageId);
 | 
						|
        $this->runtimeCache->set($cacheId, $methodResult);
 | 
						|
 | 
						|
        return $methodResult;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns the first available Site.
 | 
						|
     *
 | 
						|
     * @param bool $stopOnInvalidSite
 | 
						|
     * @throws \Exception
 | 
						|
     * @return Site
 | 
						|
     */
 | 
						|
    public function getFirstAvailableSite($stopOnInvalidSite = false)
 | 
						|
    {
 | 
						|
        $sites = $this->getAvailableSites($stopOnInvalidSite);
 | 
						|
        return array_shift($sites);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Gets all available TYPO3 sites with Solr configured.
 | 
						|
     *
 | 
						|
     * @param bool $stopOnInvalidSite
 | 
						|
     * @throws \Exception
 | 
						|
     * @return Site[] An array of availablesites
 | 
						|
     */
 | 
						|
    public function getAvailableSites($stopOnInvalidSite = false)
 | 
						|
    {
 | 
						|
        $cacheId = 'SiteRepository' . '_' . 'getAvailableSites';
 | 
						|
 | 
						|
        $sites = $this->runtimeCache->get($cacheId);
 | 
						|
        if (!empty($sites)) {
 | 
						|
            return $sites;
 | 
						|
        }
 | 
						|
 | 
						|
        $sites = $this->getAvailableTYPO3ManagedSites($stopOnInvalidSite);
 | 
						|
        $this->runtimeCache->set($cacheId, $sites);
 | 
						|
 | 
						|
        return $sites;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param bool $stopOnInvalidSite
 | 
						|
     * @return array
 | 
						|
     * @throws \Exception
 | 
						|
     */
 | 
						|
    protected function getAvailableTYPO3ManagedSites(bool $stopOnInvalidSite): array
 | 
						|
    {
 | 
						|
        $typo3ManagedSolrSites = [];
 | 
						|
        $typo3Sites = $this->siteFinder->getAllSites();
 | 
						|
        foreach ($typo3Sites as $typo3Site) {
 | 
						|
            try {
 | 
						|
                $rootPageId = $typo3Site->getRootPageId();
 | 
						|
                if (isset($typo3ManagedSolrSites[$rootPageId])) {
 | 
						|
                    //get each site only once
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
                $typo3ManagedSolrSite = $this->buildSite($rootPageId);
 | 
						|
                if ($typo3ManagedSolrSite->isEnabled()) {
 | 
						|
                    $typo3ManagedSolrSites[$rootPageId] = $typo3ManagedSolrSite;
 | 
						|
                }
 | 
						|
 | 
						|
            } catch (\Exception $e) {
 | 
						|
                if ($stopOnInvalidSite) {
 | 
						|
                    throw $e;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return $typo3ManagedSolrSites;
 | 
						|
    }
 | 
						|
 | 
						|
     /**
 | 
						|
     * Creates an instance of the Site object.
 | 
						|
     *
 | 
						|
     * @param integer $rootPageId
 | 
						|
     * @throws \InvalidArgumentException
 | 
						|
     * @return SiteInterface
 | 
						|
     */
 | 
						|
    protected function buildSite($rootPageId)
 | 
						|
    {
 | 
						|
        if (empty($rootPageId)) {
 | 
						|
            throw new \InvalidArgumentException('Root page id can not be empty');
 | 
						|
        }
 | 
						|
        $rootPageRecord = (array)BackendUtility::getRecord('pages', $rootPageId);
 | 
						|
 | 
						|
        $this->validateRootPageRecord($rootPageId, $rootPageRecord);
 | 
						|
 | 
						|
        return $this->buildTypo3ManagedSite($rootPageRecord);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $domain
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    protected function getSiteHashForDomain($domain)
 | 
						|
    {
 | 
						|
        /** @var $siteHashService SiteHashService */
 | 
						|
        $siteHashService = GeneralUtility::makeInstance(SiteHashService::class);
 | 
						|
        $siteHash = $siteHashService->getSiteHashForDomain($domain);
 | 
						|
        return $siteHash;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param int $rootPageId
 | 
						|
     * @param array $rootPageRecord
 | 
						|
     * @throws \InvalidArgumentException
 | 
						|
     */
 | 
						|
    protected function validateRootPageRecord($rootPageId, $rootPageRecord)
 | 
						|
    {
 | 
						|
        if (empty($rootPageRecord)) {
 | 
						|
            throw new \InvalidArgumentException(
 | 
						|
                '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.',
 | 
						|
                1487326416
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        if (!Site::isRootPage($rootPageRecord)) {
 | 
						|
            throw new \InvalidArgumentException(
 | 
						|
                'The rootPageRecord for the given rootPageRecord ID \'' . $rootPageId . '\' is not marked as root rootPageRecord and can therefore not be used as site root rootPageRecord.',
 | 
						|
                1309272922
 | 
						|
            );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param array $rootPageRecord
 | 
						|
     * @return Typo3ManagedSite
 | 
						|
     */
 | 
						|
    protected function buildTypo3ManagedSite(array $rootPageRecord): ?Typo3ManagedSite
 | 
						|
    {
 | 
						|
        $solrConfiguration = $this->frontendEnvironment->getSolrConfigurationFromPageId($rootPageRecord['uid']);
 | 
						|
        /** @var \TYPO3\CMS\Core\Site\Entity\Site $typo3Site */
 | 
						|
        try {
 | 
						|
            $typo3Site = $this->siteFinder->getSiteByPageId($rootPageRecord['uid']);
 | 
						|
        } catch (SiteNotFoundException $e) {
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
        $domain = $typo3Site->getBase()->getHost();
 | 
						|
 | 
						|
        $siteHash = $this->getSiteHashForDomain($domain);
 | 
						|
        $defaultLanguage = $typo3Site->getDefaultLanguage()->getLanguageId();
 | 
						|
        $pageRepository = GeneralUtility::makeInstance(PagesRepository::class);
 | 
						|
        $availableLanguageIds = array_map(function($language) {
 | 
						|
            return $language->getLanguageId();
 | 
						|
        }, $typo3Site->getLanguages());
 | 
						|
 | 
						|
        $solrConnectionConfigurations = [];
 | 
						|
 | 
						|
        foreach ($availableLanguageIds as $languageUid) {
 | 
						|
            $solrEnabled = SiteUtility::getConnectionProperty($typo3Site, 'enabled', $languageUid, 'read', true);
 | 
						|
            if ($solrEnabled) {
 | 
						|
                $solrConnectionConfigurations[$languageUid] = [
 | 
						|
                    'connectionKey' =>  $rootPageRecord['uid'] . '|' . $languageUid,
 | 
						|
                    'rootPageTitle' => $rootPageRecord['title'],
 | 
						|
                    'rootPageUid' => $rootPageRecord['uid'],
 | 
						|
                    'read' => [
 | 
						|
                        'scheme' => SiteUtility::getConnectionProperty($typo3Site, 'scheme', $languageUid, 'read', 'http'),
 | 
						|
                        'host' => SiteUtility::getConnectionProperty($typo3Site, 'host', $languageUid, 'read', 'localhost'),
 | 
						|
                        'port' => (int)SiteUtility::getConnectionProperty($typo3Site, 'port', $languageUid, 'read', 8983),
 | 
						|
                        // @todo: transform core to path
 | 
						|
                        'path' =>
 | 
						|
                            SiteUtility::getConnectionProperty($typo3Site, 'path', $languageUid, 'read', '/solr/') .
 | 
						|
                            SiteUtility::getConnectionProperty($typo3Site, 'core', $languageUid, 'read', 'core_en') . '/' ,
 | 
						|
                        'username' => SiteUtility::getConnectionProperty($typo3Site, 'username', $languageUid, 'read', ''),
 | 
						|
                        'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'read', '')
 | 
						|
                    ],
 | 
						|
                    'write' => [
 | 
						|
                        'scheme' => SiteUtility::getConnectionProperty($typo3Site, 'scheme', $languageUid, 'write', 'http'),
 | 
						|
                        'host' => SiteUtility::getConnectionProperty($typo3Site, 'host', $languageUid, 'write', 'localhost'),
 | 
						|
                        'port' => (int)SiteUtility::getConnectionProperty($typo3Site, 'port', $languageUid, 'write', 8983),
 | 
						|
                        // @todo: transform core to path
 | 
						|
                        'path' =>
 | 
						|
                            SiteUtility::getConnectionProperty($typo3Site, 'path', $languageUid, 'read', '/solr/') .
 | 
						|
                            SiteUtility::getConnectionProperty($typo3Site, 'core', $languageUid, 'read', 'core_en') . '/' ,
 | 
						|
                        'username' => SiteUtility::getConnectionProperty($typo3Site, 'username', $languageUid, 'write', ''),
 | 
						|
                        'password' => SiteUtility::getConnectionProperty($typo3Site, 'password', $languageUid, 'write', '')
 | 
						|
                    ],
 | 
						|
 | 
						|
                    'language' => $languageUid
 | 
						|
                ];
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return GeneralUtility::makeInstance(
 | 
						|
            Typo3ManagedSite::class,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $solrConfiguration,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $rootPageRecord,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $domain,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $siteHash,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $pageRepository,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $defaultLanguage,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $availableLanguageIds,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $solrConnectionConfigurations,
 | 
						|
            /** @scrutinizer ignore-type */
 | 
						|
            $typo3Site
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
}
 |