‪TYPO3CMS  9.5
PageResolver.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
20 use Psr\Http\Server\MiddlewareInterface;
21 use Psr\Http\Server\RequestHandlerInterface;
41 
49 class ‪PageResolver implements MiddlewareInterface
50 {
54  protected ‪$controller;
55 
57  {
58  $this->controller = ‪$controller ?? ‪$GLOBALS['TSFE'];
59  }
60 
68  public function ‪process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
69  {
70  // First, resolve the root page of the site, the Page ID of the current domain
71  if (($site = $request->getAttribute('site', null)) instanceof ‪SiteInterface) {
72  $this->controller->domainStartPage = $site->getRootPageId();
73  }
74  $language = $request->getAttribute('language', null);
75 
76  $hasSiteConfiguration = $language instanceof SiteLanguage && $site instanceof Site;
77 
78  // Resolve the page ID based on TYPO3's native routing functionality
79  if ($hasSiteConfiguration) {
81  $previousResult = $request->getAttribute('routing', null);
82  if (!$previousResult) {
83  return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
84  $request,
85  'The requested page does not exist',
87  );
88  }
89 
90  $requestId = (string)($request->getQueryParams()['id'] ?? '');
91  if (!empty($requestId)) {
92  $page = $this->‪resolvePageId($requestId);
93  if ($page === null) {
94  return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
95  $request,
96  'The requested page does not exist',
98  );
99  }
100  // Legacy URIs (?id=12345) takes precedence, not matter if a route is given
101  $pageArguments = new PageArguments(
102  (int)($page['l10n_parent'] ?: $page['uid']),
103  (string)($request->getQueryParams()['type'] ?? '0'),
104  [],
105  [],
106  $request->getQueryParams()
107  );
108  } else {
109  // Check for the route
110  try {
111  $pageArguments = $site->getRouter()->matchRequest($request, $previousResult);
112  } catch (RouteNotFoundException $e) {
113  return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
114  $request,
115  'The requested page does not exist',
117  );
118  }
119  }
120  if (!$pageArguments->getPageId()) {
121  return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
122  $request,
123  'The requested page does not exist',
125  );
126  }
127 
128  $this->controller->id = $pageArguments->getPageId();
129  $this->controller->type = $pageArguments->getPageType() ?? $this->controller->type;
130  $this->controller->MP = $pageArguments->getArguments()['MP'] ?? $this->controller->MP;
131  $request = $request->withAttribute('routing', $pageArguments);
132  // stop in case arguments are dirty (=defined twice in route and GET query parameters)
133  if ($pageArguments->areDirty()) {
134  return GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
135  $request,
136  'The requested URL is not distinct',
138  );
139  }
140 
141  // merge the PageArguments with the request query parameters
142  $queryParams = array_replace_recursive($request->getQueryParams(), $pageArguments->getArguments());
143  $request = $request->withQueryParams($queryParams);
144  $this->controller->setPageArguments($pageArguments);
145 
146  // At this point, we later get further route modifiers
147  // for bw-compat we update $GLOBALS[TYPO3_REQUEST] to be used later in TSFE.
148  ‪$GLOBALS['TYPO3_REQUEST'] = $request;
149  } else {
150  // old-school page resolving for realurl, cooluri etc.
151  $this->controller->siteScript = $request->getAttribute('normalizedParams')->getSiteScript();
152  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkAlternativeIdMethods-PostProc'])) {
153  trigger_error('The "checkAlternativeIdMethods-PostProc" hook will be removed in TYPO3 v10.0 in favor of PSR-15. Use a middleware instead.', E_USER_DEPRECATED);
154  $this->‪checkAlternativeIdMethods($this->controller);
155  }
156  }
157 
158  $this->controller->determineId();
159 
160  // No access? Then remove user & Re-evaluate the page-id
161  if ($this->controller->isBackendUserLoggedIn() && !‪$GLOBALS['BE_USER']->doesUserHaveAccess($this->controller->page, ‪Permission::PAGE_SHOW)) {
162  unset(‪$GLOBALS['BE_USER']);
163  // Register an empty backend user as aspect
164  $this->‪setBackendUserAspect(GeneralUtility::makeInstance(Context::class), null);
165  if (!$hasSiteConfiguration) {
166  $this->‪checkAlternativeIdMethods($this->controller);
167  }
168  $this->controller->determineId();
169  }
170 
171  return $handler->handle($request);
172  }
173 
183  protected function ‪checkAlternativeIdMethods(TypoScriptFrontendController $tsfe)
184  {
185  // Call post processing function for custom URL methods.
186  $_params = ['pObj' => &$tsfe];
187  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['checkAlternativeIdMethods-PostProc'] ?? [] as $_funcRef) {
188  GeneralUtility::callUserFunction($_funcRef, $_params, $tsfe);
189  }
190  }
191 
196  protected function ‪resolvePageId(string $pageId): ?array
197  {
198  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
199  ->getQueryBuilderForTable('pages');
200  $queryBuilder
201  ->getRestrictions()
202  ->removeAll()
203  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
204  ->add(GeneralUtility::makeInstance(FrontendWorkspaceRestriction::class));
205 
207  $constraint = $queryBuilder->expr()->eq(
208  'uid',
209  $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
210  );
211  } else {
212  $constraint = $queryBuilder->expr()->eq(
213  'alias',
214  $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_STR)
215  );
216  }
217 
218  $statement = $queryBuilder
219  ->select('uid', 'l10n_parent', 'pid')
220  ->from('pages')
221  ->where($constraint)
222  ->execute();
223 
224  $page = $statement->fetch();
225  if (empty($page)) {
226  return null;
227  }
228  return $page;
229  }
230 
237  protected function ‪setBackendUserAspect(Context $context, BackendUserAuthentication $user = null)
238  {
239  $context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
240  $context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user ? $user->workspace : 0));
241  }
242 }
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:25
‪TYPO3\CMS\Core\Routing\PageArguments
Definition: PageArguments.php:25
‪TYPO3\CMS\Frontend\Middleware\PageResolver\setBackendUserAspect
‪setBackendUserAspect(Context $context, BackendUserAuthentication $user=null)
Definition: PageResolver.php:236
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:29
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Frontend\Middleware\PageResolver\$controller
‪TypoScriptFrontendController $controller
Definition: PageResolver.php:53
‪TYPO3\CMS\Core\Site\Entity\Site\getAttribute
‪mixed getAttribute(string $attributeName)
Definition: Site.php:322
‪TYPO3\CMS\Core\Database\Query\Restriction\FrontendWorkspaceRestriction
Definition: FrontendWorkspaceRestriction.php:28
‪TYPO3\CMS\Core\Routing\RouteNotFoundException
Definition: RouteNotFoundException.php:23
‪TYPO3\CMS\Frontend\Middleware\PageResolver
Definition: PageResolver.php:50
‪TYPO3\CMS\Frontend\Controller\ErrorController
Definition: ErrorController.php:35
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:23
‪TYPO3\CMS\Core\Context\Context\setAspect
‪setAspect(string $name, AspectInterface $aspect)
Definition: Context.php:141
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:39
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:25
‪TYPO3\CMS\Frontend\Middleware
Definition: BackendUserAuthenticator.php:4
‪TYPO3\CMS\Core\Routing\SiteRouteResult
Definition: SiteRouteResult.php:29
‪TYPO3\CMS\Frontend\Middleware\PageResolver\__construct
‪__construct(TypoScriptFrontendController $controller=null)
Definition: PageResolver.php:55
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons\PAGE_NOT_FOUND
‪const PAGE_NOT_FOUND
Definition: PageAccessFailureReasons.php:26
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:32
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:97
‪TYPO3\CMS\Frontend\Middleware\PageResolver\resolvePageId
‪array null resolvePageId(string $pageId)
Definition: PageResolver.php:195
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Frontend\Middleware\PageResolver\process
‪ResponseInterface process(ServerRequestInterface $request, RequestHandlerInterface $handler)
Definition: PageResolver.php:67
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Frontend\Page\PageAccessFailureReasons
Definition: PageAccessFailureReasons.php:23
‪TYPO3\CMS\Core\Context\UserAspect
Definition: UserAspect.php:36
‪TYPO3\CMS\Frontend\Middleware\PageResolver\checkAlternativeIdMethods
‪checkAlternativeIdMethods(TypoScriptFrontendController $tsfe)
Definition: PageResolver.php:182