Skip to content

Commit

Permalink
[TASK] Move rootPage resolving into PSR-15 middleware
Browse files Browse the repository at this point in the history
The functionality to resolve the "domain start page" - the page ID
where a sys_domain record is found, is moved from TSFE/sys_page
into the SiteResolver middleware, making the domain start page value
available at an earlier point of a request.

Change of behaviours:
- TSFE->domainStartPage is now filled earlier than before
- TSFE->domainStartPage is now filled regardless of access checks of the
permissions of that page record, as the check is done later-on again anyways.

For the sake of completeness:
If a site is configured, this code is not executed anymore, as the site contains
the rootpage ID already anyways.

The method "TypoScriptFrontendController->findDomainRecord"
is removed, as it was marked as private and should have not been
used outside TYPO3 Core.

The method "PageRepository->getDomainStartPage" is marked
as deprecated as it is not called anymore.

Resolves: #84725
Releases: master
Change-Id: I5c420701eb463630d6286578ff582cb0e4e1dd35
Reviewed-on: https://review.typo3.org/56664
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Frans Saris <franssaris@gmail.com>
Tested-by: Frans Saris <franssaris@gmail.com>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Tested-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
  • Loading branch information
bmack committed Apr 15, 2018
1 parent ca1c88c commit fe1892c
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 35 deletions.
@@ -0,0 +1,46 @@
.. include:: ../../Includes.txt

================================================================
Deprecation: #84725 - sys_domain resolving moved into middleware
================================================================

See :issue:`84725`

Description
===========

The PHP method `PageRepository->getDomainStartPage()` has been marked as deprecated.

The PHP method `TypoScriptFrontendController->findDomainRecord()` which was marked
as internal, has been removed.

As both methods have been used to resolve the root page ID of the current request,
they were solely there to fill :php:`$GLOBALS['TSFE']->domainStartPage` which is now filled
at an earlier stage through the :php:`SiteResolver` middleware.


Impact
======

Calling the PageRepository method will trigger a deprecation warning.

Calling the TypoScriptFrontendController method will result in a fatal PHP error.


Affected Installations
======================

TYPO3 installations with third-party extensions calling the methods directly, usually
related to resolve a page ID or to mimic a frontend call.


Migration
=========

If the return value is needed, access :php:`$GLOBALS['TSFE']->domainStartPage` directly.

If the functionality is used in a third-party functionality and still needed,
ensure to extend from `SiteResolver` middleware to call the now-protected method equivalents
instead.

.. index:: Frontend, PHP-API, FullyScanned, ext:frontend
Expand Up @@ -1276,12 +1276,6 @@ public function fetch_the_id()
$timeTracker->pull();
// We find the first page belonging to the current domain
$timeTracker->push('fetch_the_id domain/', '');
// The page_id of the current domain
if ($this->getCurrentSiteLanguage()) {
$this->domainStartPage = $this->getCurrentSiteLanguage()->getSite()->getRootPageId();
} else {
$this->domainStartPage = $this->findDomainRecord($GLOBALS['TYPO3_CONF_VARS']['SYS']['recursiveDomainSearch']);
}
if (!$this->id) {
if ($this->domainStartPage) {
// If the id was not previously set, set it to the id of the domain.
Expand Down Expand Up @@ -1837,30 +1831,6 @@ public function setSysPageWhereClause()
$this->sys_page->where_groupAccess = $this->sys_page->getMultipleGroupsWhereClause('pages.fe_group', 'pages');
}

/**
* Looking up a domain record based on HTTP_HOST
*
* @param bool $recursive If set, it looks "recursively" meaning that a domain like "123.456.typo3.com" would find a domain record like "typo3.com" if "123.456.typo3.com" or "456.typo3.com" did not exist.
* @return int Returns the page id of the page where the domain record was found.
* @access private
*/
public function findDomainRecord($recursive = false)
{
if ($recursive) {
$pageUid = 0;
$host = explode('.', GeneralUtility::getIndpEnv('HTTP_HOST'));
while (count($host)) {
$pageUid = $this->sys_page->getDomainStartPage(implode('.', $host), GeneralUtility::getIndpEnv('SCRIPT_NAME'));
if ($pageUid) {
return $pageUid;
}
array_shift($host);
}
return $pageUid;
}
return $this->sys_page->getDomainStartPage(GeneralUtility::getIndpEnv('HTTP_HOST'), GeneralUtility::getIndpEnv('SCRIPT_NAME'));
}

/**
* Page unavailable handler for use in frontend plugins from extensions.
*
Expand Down
92 changes: 87 additions & 5 deletions typo3/sysext/frontend/Classes/Middleware/SiteResolver.php
Expand Up @@ -19,19 +19,22 @@
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Http\NormalizedParams;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* Identify the current request and resolve the site to it.
* After that middleware, TSFE should be populated with
* - language configuration
* - site configuration
* Identifies if a site is configured for the request, based on "id" and "L" GET/POST parameters, or the requested
* string.
*
* Properties like config.sys_language_uid and config.language is then set for TypoScript.
* If a site is found, the request is populated with the found language+site objects. If none is found, the main magic
* is handled by the PageResolver middleware.
*
* In addition to that, TSFE gets the $domainStartPage information resolved and added.
*/
class SiteResolver implements MiddlewareInterface
{
Expand Down Expand Up @@ -83,6 +86,85 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
// for bw-compat we update $GLOBALS[TYPO3_REQUEST] to be used later in TSFE.
$GLOBALS['TYPO3_REQUEST'] = $request;
}

// Now resolve the root page of the site, the page_id of the current domain
if ($site instanceof Site) {
$GLOBALS['TSFE']->domainStartPage = $site->getRootPageId();
} else {
$GLOBALS['TSFE']->domainStartPage = $this->findDomainRecord($request->getAttribute('normalizedParams'), (bool)$GLOBALS['TYPO3_CONF_VARS']['SYS']['recursiveDomainSearch']);
}

return $handler->handle($request);
}

/**
* Looking up a domain record based on server parameters HTTP_HOST
*
* @param NormalizedParams $requestParams used to get sanitized information of the current request
* @param bool $recursive If set, it looks "recursively" meaning that a domain like "123.456.typo3.com" would find a domain record like "typo3.com" if "123.456.typo3.com" or "456.typo3.com" did not exist.
* @return int|null Returns the page id of the page where the domain record was found or null if no sys_domain record found.
* previously found at \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::findDomainRecord()
*/
protected function findDomainRecord(NormalizedParams $requestParams, $recursive = false): ?int
{
if ($recursive) {
$pageUid = 0;
$host = explode('.', $requestParams->getHttpHost());
while (count($host)) {
$pageUid = $this->getRootPageIdFromDomainRecord(implode('.', $host), $requestParams->getScriptName());
if ($pageUid) {
return $pageUid;
}
array_shift($host);
}
return $pageUid;
}
return $this->getRootPageIdFromDomainRecord($requestParams->getHttpHost(), $requestParams->getScriptName());
}

/**
* Will find the page ID carrying the domain record matching the input domain.
*
* @param string $domain Domain name to search for. Eg. "www.typo3.com". Typical the HTTP_HOST value.
* @param string $path Path for the current script in domain. Eg. "/somedir/subdir". Typ. supplied by \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('SCRIPT_NAME')
* @return int|null If found, returns integer with page UID where found. Otherwise null.
* previously found at PageRepository::getDomainStartPage
*/
protected function getRootPageIdFromDomainRecord(string $domain, string $path = ''): ?int
{
list($domain) = explode(':', $domain);
$domain = strtolower(preg_replace('/\\.$/', '', $domain));
// Removing extra trailing slashes
$path = trim(preg_replace('/\\/[^\\/]*$/', '', $path));
// Appending to domain string
$domain .= $path;
$domain = preg_replace('/\\/*$/', '', $domain);
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_domain');
$queryBuilder->getRestrictions()->removeAll();
$row = $queryBuilder
->select(
'pid'
)
->from('sys_domain')
->where(
$queryBuilder->expr()->eq(
'hidden',
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
),
$queryBuilder->expr()->orX(
$queryBuilder->expr()->eq(
'domainName',
$queryBuilder->createNamedParameter($domain, \PDO::PARAM_STR)
),
$queryBuilder->expr()->eq(
'domainName',
$queryBuilder->createNamedParameter($domain . '/', \PDO::PARAM_STR)
)
)
)
->setMaxResults(1)
->execute()
->fetch();
return $row ? (int)$row['pid'] : null;
}
}
3 changes: 3 additions & 0 deletions typo3/sysext/frontend/Classes/Page/PageRepository.php
Expand Up @@ -877,6 +877,7 @@ protected function checkValidShortcutOfPage(array $page, $additionalWhereClause)
}
return $page;
}

/**
* Will find the page carrying the domain record matching the input domain.
*
Expand All @@ -885,9 +886,11 @@ protected function checkValidShortcutOfPage(array $page, $additionalWhereClause)
* @param string $request_uri Request URI: Used to get parameters from if they should be appended. Typ. supplied by \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('REQUEST_URI')
* @return mixed If found, returns integer with page UID where found. Otherwise blank. Might exit if location-header is sent, see description.
* @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::findDomainRecord()
* @deprecated will be removed in TYPO3 v10.0.
*/
public function getDomainStartPage($domain, $path = '', $request_uri = '')
{
trigger_error('This method will be removed in TYPO3 v10.0. As the SiteResolver middleware resolves the domain start page.', E_USER_DEPRECATED);
$domain = explode(':', $domain);
$domain = strtolower(preg_replace('/\\.$/', '', $domain[0]));
// Removing extra trailing slashes
Expand Down
Expand Up @@ -2116,4 +2116,18 @@
'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst',
],
],
'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->findDomainRecord' => [
'numberOfMandatoryArguments' => 0,
'maximumNumberOfArguments' => 1,
'restFiles' => [
'Deprecation-84725-SysDomainResolvingMovedIntoMiddleware.rst',
],
],
'TYPO3\CMS\Frontend\Page\PageRepository->getDomainStartPage' => [
'numberOfMandatoryArguments' => 1,
'maximumNumberOfArguments' => 3,
'restFiles' => [
'Deprecation-84725-SysDomainResolvingMovedIntoMiddleware.rst',
],
],
];

0 comments on commit fe1892c

Please sign in to comment.