c7755dab753adcbefc73ede03f487e4d5758e672
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Http / RequestHandler.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Frontend\Http;
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\RequestHandlerInterface as PsrRequestHandlerInterface;
21 use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
22 use TYPO3\CMS\Core\FrontendEditing\FrontendEditingController;
23 use TYPO3\CMS\Core\Http\NullResponse;
24 use TYPO3\CMS\Core\Http\RequestHandlerInterface;
25 use TYPO3\CMS\Core\Http\Response;
26 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
27 use TYPO3\CMS\Core\Utility\GeneralUtility;
28 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
29 use TYPO3\CMS\Frontend\Page\PageGenerator;
30
31 /**
32 * This is the main entry point of the TypoScript driven standard front-end
33 *
34 * Basically put, this is the script which all requests for TYPO3 delivered pages goes to in the
35 * frontend (the website). The script instantiates a $TSFE object, includes libraries and does a little logic here
36 * and there in order to instantiate the right classes to create the webpage.
37 * Previously, this was called index_ts.php and also included the logic for the lightweight "eID" concept,
38 * which is now handled in a separate middleware (EidHandler).
39 */
40 class RequestHandler implements RequestHandlerInterface, PsrRequestHandlerInterface
41 {
42 /**
43 * Instance of the timetracker
44 * @var TimeTracker
45 */
46 protected $timeTracker;
47
48 /**
49 * Handles a frontend request
50 *
51 * @param ServerRequestInterface $request
52 * @return ResponseInterface
53 */
54 public function handleRequest(ServerRequestInterface $request): ResponseInterface
55 {
56 return $this->handle($request);
57 }
58
59 /**
60 * Handles a frontend request, after finishing running middlewares
61 *
62 * @param ServerRequestInterface $request
63 * @return ResponseInterface|null
64 */
65 public function handle(ServerRequestInterface $request): ResponseInterface
66 {
67 // Fetch the initialized time tracker object
68 $this->timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
69 /** @var TypoScriptFrontendController $controller */
70 $controller = $GLOBALS['TSFE'];
71
72 // Admin Panel & Frontend editing
73 if ($controller->isBackendUserLoggedIn()) {
74 $GLOBALS['BE_USER']->initializeFrontendEdit();
75 if ($GLOBALS['BE_USER']->frontendEdit instanceof FrontendEditingController) {
76 $GLOBALS['BE_USER']->frontendEdit->initConfigOptions();
77 }
78 }
79
80 // Starts the template
81 $this->timeTracker->push('Start Template', '');
82 $controller->initTemplate();
83 $this->timeTracker->pull();
84 // Get from cache
85 $this->timeTracker->push('Get Page from cache', '');
86 $controller->getFromCache();
87 $this->timeTracker->pull();
88 // Get config if not already gotten
89 // After this, we should have a valid config-array ready
90 $controller->getConfigArray();
91 // Setting language and locale
92 $this->timeTracker->push('Setting language and locale', '');
93 $controller->settingLanguage();
94 $controller->settingLocale();
95 $this->timeTracker->pull();
96
97 // Convert POST data to utf-8 for internal processing if metaCharset is different
98 $controller->convPOSTCharset();
99
100 $controller->initializeRedirectUrlHandlers();
101
102 $controller->handleDataSubmission();
103
104 // Check for shortcut page and redirect
105 $controller->checkPageForShortcutRedirect();
106 $controller->checkPageForMountpointRedirect();
107
108 // Generate page
109 $controller->setUrlIdToken();
110 $this->timeTracker->push('Page generation', '');
111 if ($controller->isGeneratePage()) {
112 $controller->generatePage_preProcessing();
113 $controller->preparePageContentGeneration();
114 // Content generation
115 if (!$controller->isINTincScript()) {
116 PageGenerator::renderContent();
117 $controller->setAbsRefPrefix();
118 }
119 $controller->generatePage_postProcessing();
120 } elseif ($controller->isINTincScript()) {
121 $controller->preparePageContentGeneration();
122 }
123 $controller->releaseLocks();
124 $this->timeTracker->pull();
125
126 // Render non-cached parts
127 if ($controller->isINTincScript()) {
128 $this->timeTracker->push('Non-cached objects', '');
129 $controller->INTincScript();
130 $this->timeTracker->pull();
131 }
132
133 // Create a Response object when sending content
134 $response = new Response();
135
136 // Output content
137 $isOutputting = $controller->isOutputting();
138 if ($isOutputting) {
139 $this->timeTracker->push('Print Content', '');
140 $controller->processOutput();
141 $this->timeTracker->pull();
142 }
143 // Store session data for fe_users
144 $controller->storeSessionData();
145
146 $redirectResponse = $controller->redirectToExternalUrl();
147 if ($redirectResponse instanceof ResponseInterface) {
148 return $redirectResponse;
149 }
150
151 // Statistics
152 $GLOBALS['TYPO3_MISC']['microtime_end'] = microtime(true);
153 if ($isOutputting && ($controller->config['config']['debug'] ?? !empty($GLOBALS['TYPO3_CONF_VARS']['FE']['debug']))) {
154 $response = $response->withHeader('X-TYPO3-Parsetime', $this->timeTracker->getParseTime() . 'ms');
155 }
156
157 // Preview info
158 $controller->previewInfo();
159 // Hook for end-of-frontend
160 $controller->hook_eofe();
161 // Finish timetracking
162 $this->timeTracker->pull();
163
164 // Admin panel
165 if ($controller->isBackendUserLoggedIn() && $GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication && $GLOBALS['BE_USER']->isAdminPanelVisible()) {
166 $controller->content = str_ireplace('</body>', $GLOBALS['BE_USER']->displayAdminPanel() . '</body>', $controller->content);
167 }
168
169 if ($isOutputting) {
170 $response->getBody()->write($controller->content);
171 }
172
173 return $isOutputting ? $response : new NullResponse();
174 }
175
176 /**
177 * This request handler can handle any frontend request.
178 *
179 * @param ServerRequestInterface $request
180 * @return bool If the request is not an eID request, TRUE otherwise FALSE
181 */
182 public function canHandleRequest(ServerRequestInterface $request): bool
183 {
184 return true;
185 }
186
187 /**
188 * Returns the priority - how eager the handler is to actually handle the
189 * request.
190 *
191 * @return int The priority of the request handler.
192 */
193 public function getPriority(): int
194 {
195 return 50;
196 }
197 }