meilisearch/Classes/Domain/Site/SiteRepository.php
2021-04-29 18:33:05 +02:00

312 lines
10 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 Meilisearch 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
{
$typo3ManagedMeilisearchSites = [];
$typo3Sites = $this->siteFinder->getAllSites();
foreach ($typo3Sites as $typo3Site) {
try {
$rootPageId = $typo3Site->getRootPageId();
if (isset($typo3ManagedMeilisearchSites[$rootPageId])) {
//get each site only once
continue;
}
$typo3ManagedMeilisearchSite = $this->buildSite($rootPageId);
if ($typo3ManagedMeilisearchSite->isEnabled()) {
$typo3ManagedMeilisearchSites[$rootPageId] = $typo3ManagedMeilisearchSite;
}
} catch (\Exception $e) {
if ($stopOnInvalidSite) {
throw $e;
}
}
}
return $typo3ManagedMeilisearchSites;
}
/**
* 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);
return $siteHashService->getSiteHashForDomain($domain);
}
/**
* @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
{
$meilisearchConfiguration = $this->frontendEnvironment->getMeilisearchConfigurationFromPageId($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);
$pageRepository = GeneralUtility::makeInstance(PagesRepository::class);
$meilisearchConnectionConfiguration = [];
$meilisearchEnabled = SiteUtility::getConnectionProperty($typo3Site, 'enabled', true);
if ($meilisearchEnabled) {
$meilisearchConnectionConfiguration = [
'connectionKey' => $rootPageRecord['uid'] . '|',
'rootPageTitle' => $rootPageRecord['title'],
'rootPageUid' => $rootPageRecord['uid'],
'scheme' => SiteUtility::getConnectionProperty($typo3Site, 'scheme', 'http'),
'host' => SiteUtility::getConnectionProperty($typo3Site, 'host', 'localhost'),
'port' => (int)SiteUtility::getConnectionProperty($typo3Site, 'port',7700),
'apiKey' => SiteUtility::getConnectionProperty($typo3Site, 'apiKey', ''),
];
}
return GeneralUtility::makeInstance(
Typo3ManagedSite::class,
$typo3Site,
/** @scrutinizer ignore-type */
$meilisearchConfiguration,
/** @scrutinizer ignore-type */
$rootPageRecord,
/** @scrutinizer ignore-type */
$domain,
/** @scrutinizer ignore-type */
$siteHash,
/** @scrutinizer ignore-type */
$pageRepository,
/** @scrutinizer ignore-type */
$meilisearchConnectionConfiguration,
/** @scrutinizer ignore-type */
$typo3Site
);
}
}