[TASK] Deprecate PageGenerator::renderContent
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Http / RequestHandler.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Frontend\Http;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use Psr\Http\Message\ResponseInterface;
20 use Psr\Http\Message\ServerRequestInterface;
21 use Psr\Http\Server\RequestHandlerInterface as PsrRequestHandlerInterface;
22 use TYPO3\CMS\Core\Http\NullResponse;
23 use TYPO3\CMS\Core\Http\RequestHandlerInterface;
24 use TYPO3\CMS\Core\Http\Response;
25 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
28 use TYPO3\CMS\Frontend\Page\PageGenerator;
29
30 /**
31 * This is the main entry point of the TypoScript driven standard front-end
32 *
33 * Basically put, this is the script which all requests for TYPO3 delivered pages goes to in the
34 * frontend (the website). The script instantiates a $TSFE object, includes libraries and does a little logic here
35 * and there in order to instantiate the right classes to create the webpage.
36 * Previously, this was called index_ts.php and also included the logic for the lightweight "eID" concept,
37 * which is now handled in a separate middleware (EidHandler).
38 */
39 class RequestHandler implements RequestHandlerInterface, PsrRequestHandlerInterface
40 {
41 /**
42 * Instance of the timetracker
43 * @var TimeTracker
44 */
45 protected $timeTracker;
46
47 /**
48 * Handles a frontend request
49 *
50 * @param ServerRequestInterface $request
51 * @return ResponseInterface
52 */
53 public function handleRequest(ServerRequestInterface $request): ResponseInterface
54 {
55 return $this->handle($request);
56 }
57
58 /**
59 * Handles a frontend request, after finishing running middlewares
60 *
61 * @param ServerRequestInterface $request
62 * @return ResponseInterface|null
63 */
64 public function handle(ServerRequestInterface $request): ResponseInterface
65 {
66 // Fetch the initialized time tracker object
67 $this->timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
68 /** @var TypoScriptFrontendController $controller */
69 $controller = $GLOBALS['TSFE'];
70
71 // Generate page
72 if ($controller->isGeneratePage()) {
73 $this->timeTracker->push('Page generation');
74 $controller->generatePage_preProcessing();
75 $controller->preparePageContentGeneration();
76
77 // Content generation
78 $this->timeTracker->incStackPointer();
79 $this->timeTracker->push($controller->sPre, 'PAGE');
80
81 $pageContent = $this->generatePageContent($controller);
82 // Now render the Page header (<head> tag content and wrap around <body> tag) - this is done
83 // after the "main" page Content, since some JS may be inserted at that point.
84 // if 'disableAllHeaderCode' is set, all the header-code is discarded
85 if ($controller->config['config']['disableAllHeaderCode']) {
86 $controller->content = $pageContent;
87 } else {
88 PageGenerator::renderContentWithHeader($pageContent);
89 }
90
91 $this->timeTracker->pull($this->timeTracker->LR ? $controller->content : '');
92 $this->timeTracker->decStackPointer();
93
94 $controller->setAbsRefPrefix();
95 $controller->generatePage_postProcessing();
96 $this->timeTracker->pull();
97 }
98 $controller->releaseLocks();
99
100 // Render non-cached page parts by replacing placeholders which are taken from cache or added during page generation
101 if ($controller->isINTincScript()) {
102 if (!$controller->isGeneratePage()) {
103 // When page was generated, this was already called. Avoid calling this twice.
104 $controller->preparePageContentGeneration();
105 }
106 $this->timeTracker->push('Non-cached objects');
107 $controller->INTincScript();
108 $this->timeTracker->pull();
109 }
110
111 // Create a Response object when sending content
112 $response = new Response();
113
114 // Output content
115 $isOutputting = $controller->isOutputting();
116 if ($isOutputting) {
117 $this->timeTracker->push('Print Content');
118 $controller->processOutput();
119 $this->timeTracker->pull();
120 }
121 // Store session data for fe_users
122 $controller->storeSessionData();
123
124 // @deprecated since TYPO3 v9.3, will be removed in TYPO3 v10.0.
125 $redirectResponse = $controller->redirectToExternalUrl(true);
126 if ($redirectResponse instanceof ResponseInterface) {
127 return $redirectResponse;
128 }
129
130 // Statistics
131 $GLOBALS['TYPO3_MISC']['microtime_end'] = microtime(true);
132 if ($isOutputting && ($controller->config['config']['debug'] ?? !empty($GLOBALS['TYPO3_CONF_VARS']['FE']['debug']))) {
133 $response = $response->withHeader('X-TYPO3-Parsetime', $this->timeTracker->getParseTime() . 'ms');
134 }
135
136 // Preview info
137 $controller->previewInfo();
138 // Hook for end-of-frontend
139 $controller->hook_eofe();
140 // Finish timetracking
141 $this->timeTracker->pull();
142
143 if ($isOutputting) {
144 $response->getBody()->write($controller->content);
145 }
146
147 return $isOutputting ? $response : new NullResponse();
148 }
149
150 /**
151 * Generates the main content part within <body> tags (except JS files/CSS files).
152 *
153 * @param TypoScriptFrontendController $controller
154 * @return string
155 */
156 protected function generatePageContent(TypoScriptFrontendController $controller): string
157 {
158 $pageContent = $controller->cObj->cObjGet($controller->pSetup);
159 if ($controller->pSetup['wrap']) {
160 $pageContent = $controller->cObj->wrap($pageContent, $controller->pSetup['wrap']);
161 }
162 if ($controller->pSetup['stdWrap.']) {
163 $pageContent = $controller->cObj->stdWrap($pageContent, $controller->pSetup['stdWrap.']);
164 }
165 return $pageContent;
166 }
167
168 /**
169 * This request handler can handle any frontend request.
170 *
171 * @param ServerRequestInterface $request
172 * @return bool If the request is not an eID request, TRUE otherwise FALSE
173 */
174 public function canHandleRequest(ServerRequestInterface $request): bool
175 {
176 return true;
177 }
178
179 /**
180 * Returns the priority - how eager the handler is to actually handle the
181 * request.
182 *
183 * @return int The priority of the request handler.
184 */
185 public function getPriority(): int
186 {
187 return 50;
188 }
189 }