Skip to content

Commit

Permalink
[TASK] Add API to hide PseudoSite functionality
Browse files Browse the repository at this point in the history
In order to avoid usages of using PseudoSite objects directly,
the following changes have been made:

The main entrypoint for finding sites is now encapsulated the
SiteMatcher class.

* SiteMatcher->matchByPageId($pageId)
which consistently checks for Sites and Pseudo Sites. This is now
a singleton as it factors PseudoSiteFinder directly.

* NullSite for PID=0 (which is a slim version of a PseudoSite
and will stay around for longer than the PseudoSite).

This marks the last part of the Site API functionality, as
TYPO3 is now ready to work with the Site API in all places
throughout Frontend and Backend.

Resolves: #85930
Releases: master
Change-Id: I5e75da22337e126a39b459388e21d7f9fe05e556
Reviewed-on: https://review.typo3.org/57992
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
  • Loading branch information
bmack authored and andreaskienast committed Aug 22, 2018
1 parent 6665ed6 commit cf1d0f1
Show file tree
Hide file tree
Showing 12 changed files with 275 additions and 193 deletions.
Expand Up @@ -36,16 +36,14 @@
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\ReferenceIndex;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Http\RedirectResponse;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Routing\SiteMatcher;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Site\PseudoSiteFinder;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\HttpUtility;
Expand Down Expand Up @@ -2428,12 +2426,7 @@ public function localizationRedirect(ServerRequestInterface $request = null): ?R
*/
protected function getLanguages(int $id, string $table): array
{
try {
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($id);
} catch (SiteNotFoundException $e) {
// Check for a pseudo site
$site = GeneralUtility::makeInstance(PseudoSiteFinder::class)->getSiteByPageId($id);
}
$site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($id);

// Fetch the current translations of this page, to only show the ones where there is a page translation
$allLanguages = $site->getAvailableLanguages($this->getBackendUser(), false, $id);
Expand Down
Expand Up @@ -16,9 +16,7 @@
*/

use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Site\PseudoSiteFinder;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Routing\SiteMatcher;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
Expand All @@ -39,12 +37,7 @@ class SiteResolving implements FormDataProviderInterface
public function addData(array $result): array
{
$pageIdDefaultLanguage = $result['defaultLanguagePageRow']['uid'] ?? $result['effectivePid'];
try {
$result['site'] = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageIdDefaultLanguage);
} catch (SiteNotFoundException $e) {
// Check for a pseudo site
$result['site'] = GeneralUtility::makeInstance(PseudoSiteFinder::class)->getSiteByPageId($pageIdDefaultLanguage);
}
$result['site'] = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageIdDefaultLanguage);
return $result;
}
}
28 changes: 7 additions & 21 deletions typo3/sysext/backend/Classes/Middleware/SiteResolver.php
Expand Up @@ -20,10 +20,7 @@
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Site\Entity\SiteInterface;
use TYPO3\CMS\Core\Site\PseudoSiteFinder;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Routing\SiteMatcher;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
Expand All @@ -49,25 +46,14 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
$site = null;
$pageId = (int)($request->getQueryParams()['id'] ?? $request->getParsedBody()['id'] ?? 0);

// Check if we have a _GET/_POST parameter for "id", then a site information can be resolved based.
$rootLine = null;
if ($pageId > 0) {
try {
$finder = GeneralUtility::makeInstance(SiteFinder::class);
$site = $finder->getSiteByPageId($pageId);
} catch (SiteNotFoundException $e) {
// Check for pseudo sites, based on given ID
$finder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
$rootLine = BackendUtility::BEgetRootLine($pageId);
$site = $finder->getSiteByPageId($pageId, $rootLine);
}
} else {
$finder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
$site = $finder->getSiteByPageId(0);
}
if ($site instanceof SiteInterface) {
$request = $request->withAttribute('site', $site);
$GLOBALS['TYPO3_REQUEST'] = $request;
// Check if we have a _GET/_POST parameter for "id", then a site information can be resolved based.
$rootLine = BackendUtility::BEgetRootLine($pageId);
}
$site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageId, $rootLine);
$request = $request->withAttribute('site', $site);
$GLOBALS['TYPO3_REQUEST'] = $request;
return $handler->handle($request);
}
}
11 changes: 2 additions & 9 deletions typo3/sysext/backend/Classes/View/PageLayoutView.php
Expand Up @@ -39,12 +39,10 @@
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Routing\SiteMatcher;
use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Core\Service\FlexFormService;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Site\PseudoSiteFinder;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
Expand Down Expand Up @@ -4406,12 +4404,7 @@ protected function renderLanguageFlag(SiteLanguage $language)
*/
protected function resolveSiteLanguages(int $pageId)
{
try {
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageId);
} catch (SiteNotFoundException $e) {
// Check for a pseudo site
$site = GeneralUtility::makeInstance(PseudoSiteFinder::class)->getSiteByPageId($pageId);
}
$site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageId);
$this->siteLanguages = $site->getAvailableLanguages($this->getBackendUser(), false, $pageId);
}

Expand Down
Expand Up @@ -16,8 +16,8 @@
*/

use TYPO3\CMS\Backend\Form\FormDataProvider\SiteResolving;
use TYPO3\CMS\Core\Routing\SiteMatcher;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;

Expand All @@ -26,16 +26,18 @@
*/
class SiteResolvingTest extends UnitTestCase
{
protected $resetSingletonInstances = true;

/**
* @test
*/
public function addDataAddsSiteObjectOfDefaultLanguageRow()
{
$siteFinderProphecy = $this->prophesize(SiteFinder::class);
GeneralUtility::addInstance(SiteFinder::class, $siteFinderProphecy->reveal());
$siteMatcherProphecy = $this->prophesize(SiteMatcher::class);
GeneralUtility::setSingletonInstance(SiteMatcher::class, $siteMatcherProphecy->reveal());
$siteProphecy = $this->prophesize(Site::class);
$siteProphecyRevelation = $siteProphecy->reveal();
$siteFinderProphecy->getSiteByPageId(23)->willReturn($siteProphecyRevelation);
$siteMatcherProphecy->matchByPageId(23)->willReturn($siteProphecyRevelation);
$input = [
'defaultLanguagePageRow' => [
'uid' => 23,
Expand All @@ -53,11 +55,11 @@ public function addDataAddsSiteObjectOfDefaultLanguageRow()
*/
public function addDataAddsSiteObjectOfEffectivePid()
{
$siteFinderProphecy = $this->prophesize(SiteFinder::class);
GeneralUtility::addInstance(SiteFinder::class, $siteFinderProphecy->reveal());
$siteMatcherProphecy = $this->prophesize(SiteMatcher::class);
GeneralUtility::setSingletonInstance(SiteMatcher::class, $siteMatcherProphecy->reveal());
$siteProphecy = $this->prophesize(Site::class);
$siteProphecyRevelation = $siteProphecy->reveal();
$siteFinderProphecy->getSiteByPageId(42)->willReturn($siteProphecyRevelation);
$siteMatcherProphecy->matchByPageId(42)->willReturn($siteProphecyRevelation);
$input = [
'effectivePid' => 42,
'site' => $siteProphecyRevelation,
Expand Down
39 changes: 36 additions & 3 deletions typo3/sysext/core/Classes/Routing/SiteMatcher.php
Expand Up @@ -24,6 +24,9 @@
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Site\Entity\PseudoSite;
use TYPO3\CMS\Core\Site\Entity\SiteInterface;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Site\PseudoSiteFinder;
use TYPO3\CMS\Core\Site\SiteFinder;
Expand All @@ -36,21 +39,31 @@
*
* The main usage is the ->matchRequest() functionality, which receives a request object and boots up
* Symfony Routing to find the proper route with its defaults / attributes.
*
* On top, this is also commonly used throughout TYPO3 to fetch a site by a given pageId.
* ->matchPageId()
*/
class SiteMatcher
class SiteMatcher implements SingletonInterface
{
/**
* @var SiteFinder
*/
protected $finder;

/**
* Injects necessary objects
* @var PseudoSiteFinder
*/
protected $pseudoSiteFinder;

/**
* Injects necessary objects. PseudoSiteFinder is not injectable as this will be become obsolete in the future.
*
* @param SiteFinder|null $finder
*/
public function __construct(SiteFinder $finder = null)
{
$this->finder = $finder ?? GeneralUtility::makeInstance(SiteFinder::class);
$this->pseudoSiteFinder = GeneralUtility::makeInstance(PseudoSiteFinder::class);
}

/**
Expand Down Expand Up @@ -141,6 +154,23 @@ public function matchRequest(ServerRequestInterface $request): array
return ['site' => $site, 'language' => $language];
}

/**
* If a given page ID is handed in, a Site/PseudoSite/NullSite is returned.
*
* @param int $pageId the page ID (must be a page in the default language)
* @param array|null $rootLine an alternative root line, if already at and.
* @return SiteInterface
*/
public function matchByPageId(int $pageId, array $rootLine = null): SiteInterface
{
try {
return $this->finder->getSiteByPageId($pageId, $rootLine);
} catch (SiteNotFoundException $e) {
// Check for a pseudo / null site
return $this->pseudoSiteFinder->getSiteByPageId($pageId, $rootLine);
}
}

/**
* Returns a Symfony RouteCollection containing all routes to all sites.
*
Expand Down Expand Up @@ -178,9 +208,12 @@ protected function getRouteCollectionForAllSites(): RouteCollection
*/
protected function getRouteCollectionForVisibleSysDomains(): RouteCollection
{
$sites = GeneralUtility::makeInstance(PseudoSiteFinder::class)->findAll();
$sites = $this->pseudoSiteFinder->findAll();
$groupedRoutes = [];
foreach ($sites as $site) {
if (!$site instanceof PseudoSite) {
continue;
}
foreach ($site->getEntryPoints() as $domainName) {
// Site has no sys_domain record, it is not valid for a routing entrypoint, but only available
// via "id" GET parameter which is handled before
Expand Down

0 comments on commit cf1d0f1

Please sign in to comment.