TYPO3 CMS  TYPO3_7-6
RequestHandler.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
30 
41 {
46  protected $bootstrap;
47 
52  protected $timeTracker;
53 
58  protected $controller;
59 
64  protected $request;
65 
71  public function __construct(Bootstrap $bootstrap)
72  {
73  $this->bootstrap = $bootstrap;
74  }
75 
82  public function handleRequest(\Psr\Http\Message\ServerRequestInterface $request)
83  {
84  $response = null;
85  $this->request = $request;
86  $this->initializeTimeTracker();
87 
88  // Hook to preprocess the current request:
89  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'])) {
90  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preprocessRequest'] as $hookFunction) {
91  $hookParameters = [];
92  GeneralUtility::callUserFunction($hookFunction, $hookParameters, $hookParameters);
93  }
94  unset($hookFunction);
95  unset($hookParameters);
96  }
97 
98  $this->initializeController();
99 
100  if ($GLOBALS['TYPO3_CONF_VARS']['FE']['pageUnavailable_force']
102  GeneralUtility::getIndpEnv('REMOTE_ADDR'),
103  $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'])
104  ) {
105  $this->controller->pageUnavailableAndExit('This page is temporarily unavailable.');
106  }
107 
108  $this->controller->connectToDB();
109  $this->controller->sendRedirect();
110 
111  // Output compression
112  // Remove any output produced until now
113  $this->bootstrap->endOutputBufferingAndCleanPreviousOutput();
115 
116  // Initializing the Frontend User
117  $this->timeTracker->push('Front End user initialized', '');
118  $this->controller->initFEuser();
119  $this->timeTracker->pull();
120 
121  // Initializing a possible logged-in Backend User
123  $GLOBALS['BE_USER'] = $this->controller->initializeBackendUser();
124 
125  // Process the ID, type and other parameters.
126  // After this point we have an array, $page in TSFE, which is the page-record
127  // of the current page, $id.
128  $this->timeTracker->push('Process ID', '');
129  // Initialize admin panel since simulation settings are required here:
130  if ($this->controller->isBackendUserLoggedIn()) {
131  $GLOBALS['BE_USER']->initializeAdminPanel();
132  $this->bootstrap
133  ->initializeBackendRouter()
134  ->loadExtensionTables(true);
135  } else {
136  $this->bootstrap->loadCachedTca();
137  }
138  $this->controller->checkAlternativeIdMethods();
139  $this->controller->clear_preview();
140  $this->controller->determineId();
141 
142  // Now, if there is a backend user logged in and he has NO access to this page,
143  // then re-evaluate the id shown! _GP('ADMCMD_noBeUser') is placed here because
144  // \TYPO3\CMS\Version\Hook\PreviewHook might need to know if a backend user is logged in.
145  if (
146  $this->controller->isBackendUserLoggedIn()
147  && (!$GLOBALS['BE_USER']->extPageReadAccess($this->controller->page) || GeneralUtility::_GP('ADMCMD_noBeUser'))
148  ) {
149  // Remove user
150  unset($GLOBALS['BE_USER']);
151  $this->controller->beUserLogin = false;
152  // Re-evaluate the page-id.
153  $this->controller->checkAlternativeIdMethods();
154  $this->controller->clear_preview();
155  $this->controller->determineId();
156  }
157 
158  $this->controller->makeCacheHash();
159  $this->timeTracker->pull();
160 
161  // Admin Panel & Frontend editing
162  if ($this->controller->isBackendUserLoggedIn()) {
163  $GLOBALS['BE_USER']->initializeFrontendEdit();
164  if ($GLOBALS['BE_USER']->adminPanel instanceof AdminPanelView) {
165  $this->bootstrap
166  ->initializeLanguageObject()
167  ->initializeSpriteManager();
168  }
169  if ($GLOBALS['BE_USER']->frontendEdit instanceof FrontendEditingController) {
170  $GLOBALS['BE_USER']->frontendEdit->initConfigOptions();
171  }
172  }
173 
174  // Starts the template
175  $this->timeTracker->push('Start Template', '');
176  $this->controller->initTemplate();
177  $this->timeTracker->pull();
178  // Get from cache
179  $this->timeTracker->push('Get Page from cache', '');
180  $this->controller->getFromCache();
181  $this->timeTracker->pull();
182  // Get config if not already gotten
183  // After this, we should have a valid config-array ready
184  $this->controller->getConfigArray();
185  // Setting language and locale
186  $this->timeTracker->push('Setting language and locale', '');
187  $this->controller->settingLanguage();
188  $this->controller->settingLocale();
189  $this->timeTracker->pull();
190 
191  // Convert POST data to internal "renderCharset" if different from the metaCharset
192  $this->controller->convPOSTCharset();
193 
194  $this->controller->initializeRedirectUrlHandlers();
195 
196  $this->controller->handleDataSubmission();
197 
198  // Check for shortcut page and redirect
199  $this->controller->checkPageForShortcutRedirect();
200  $this->controller->checkPageForMountpointRedirect();
201 
202  // Generate page
203  $this->controller->setUrlIdToken();
204  $this->timeTracker->push('Page generation', '');
205  if ($this->controller->isGeneratePage()) {
206  $this->controller->generatePage_preProcessing();
207  $temp_theScript = $this->controller->generatePage_whichScript();
208  if ($temp_theScript) {
209  include $temp_theScript;
210  } else {
211  PageGenerator::pagegenInit();
212  // Global content object
213  $this->controller->newCObj();
214  // Content generation
215  if (!$this->controller->isINTincScript()) {
216  PageGenerator::renderContent();
217  $this->controller->setAbsRefPrefix();
218  }
219  }
220  $this->controller->generatePage_postProcessing();
221  } elseif ($this->controller->isINTincScript()) {
222  PageGenerator::pagegenInit();
223  // Global content object
224  $this->controller->newCObj();
225  }
226  $this->controller->releaseLocks();
227  $this->timeTracker->pull();
228 
229  // Render non-cached parts
230  if ($this->controller->isINTincScript()) {
231  $this->timeTracker->push('Non-cached objects', '');
232  $this->controller->INTincScript();
233  $this->timeTracker->pull();
234  }
235 
236  // Output content
237  $sendTSFEContent = false;
238  if ($this->controller->isOutputting()) {
239  $this->timeTracker->push('Print Content', '');
240  $this->controller->processOutput();
241  $sendTSFEContent = true;
242  $this->timeTracker->pull();
243  }
244  // Store session data for fe_users
245  $this->controller->storeSessionData();
246  // Statistics
247  $GLOBALS['TYPO3_MISC']['microtime_end'] = microtime(true);
248  $this->controller->setParseTime();
249  if (isset($this->controller->config['config']['debug'])) {
250  $debugParseTime = (bool)$this->controller->config['config']['debug'];
251  } else {
252  $debugParseTime = !empty($this->controller->TYPO3_CONF_VARS['FE']['debug']);
253  }
254  if ($this->controller->isOutputting() && $debugParseTime) {
255  $this->controller->content .= LF . '<!-- Parsetime: ' . $this->controller->scriptParseTime . 'ms -->';
256  }
257  $this->controller->redirectToExternalUrl();
258  // Preview info
259  $this->controller->previewInfo();
260  // Hook for end-of-frontend
261  $this->controller->hook_eofe();
262  // Finish timetracking
263  $this->timeTracker->pull();
264  // Check memory usage
265  MonitorUtility::peakMemoryUsage();
266  // beLoginLinkIPList
267  echo $this->controller->beLoginLinkIPList();
268 
269  // Admin panel
270  if ($this->controller->isBackendUserLoggedIn() && $GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication) {
271  if ($GLOBALS['BE_USER']->isAdminPanelVisible()) {
272  $this->controller->content = str_ireplace('</body>', $GLOBALS['BE_USER']->displayAdminPanel() . '</body>', $this->controller->content);
273  }
274  }
275 
276  if ($sendTSFEContent) {
278  $response = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\Response::class);
279  $response->getBody()->write($this->controller->content);
280  }
281  // Debugging Output
282  if (isset($GLOBALS['error']) && is_object($GLOBALS['error']) && @is_callable([$GLOBALS['error'], 'debugOutput'])) {
283  $GLOBALS['error']->debugOutput();
284  }
285  if (TYPO3_DLOG) {
286  GeneralUtility::devLog('END of FRONTEND session', 'cms', 0, ['_FLUSH' => true]);
287  }
288  // if any code set a response code that is not 200 clear the cache's content
289  // if we fail to do so we would deliver cache content with a wrong header, which causes big mess.
290  if (http_response_code() !== 200) {
291  $this->controller->clearPageCacheContent();
292  }
293  return $response;
294  }
295 
302  public function canHandleRequest(\Psr\Http\Message\ServerRequestInterface $request)
303  {
304  return $request->getQueryParams()['eID'] || $request->getParsedBody()['eID'] ? false : true;
305  }
306 
313  public function getPriority()
314  {
315  return 50;
316  }
317 
322  protected function initializeOutputCompression()
323  {
324  if ($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'] && extension_loaded('zlib')) {
325  if (MathUtility::canBeInterpretedAsInteger($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'])) {
326  @ini_set('zlib.output_compression_level', $GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']);
327  }
328  ob_start([GeneralUtility::makeInstance(CompressionUtility::class), 'compressionOutputHandler']);
329  }
330  }
331 
337  protected function initializeTimeTracker()
338  {
339  $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
340  if (empty($configuredCookieName)) {
341  $configuredCookieName = 'be_typo_user';
342  }
343  if ($this->request->getCookieParams()[$configuredCookieName]) {
344  $this->timeTracker = new TimeTracker();
345  } else {
346  $this->timeTracker = new NullTimeTracker();
347  }
348 
349  // We have to define this as reference here, because there is code around
350  // which exchanges the TT object in the global variable. The reference ensures
351  // that the $timeTracker member always works on the same object as the global variable.
352  // This is a dirty workaround and bypasses the protected access modifier of the $timeTracker member.
353  $GLOBALS['TT'] = &$this->timeTracker;
354  $this->timeTracker->start();
355  }
356 
362  protected function initializeController()
363  {
364  $this->controller = GeneralUtility::makeInstance(
365  TypoScriptFrontendController::class,
366  $GLOBALS['TYPO3_CONF_VARS'],
367  GeneralUtility::_GP('id'),
368  GeneralUtility::_GP('type'),
369  GeneralUtility::_GP('no_cache'),
370  GeneralUtility::_GP('cHash'),
371  GeneralUtility::_GP('jumpurl'),
372  GeneralUtility::_GP('MP'),
373  GeneralUtility::_GP('RDCT')
374  );
375  // setting the global variable for the controller
376  // We have to define this as reference here, because there is code around
377  // which exchanges the TSFE object in the global variable. The reference ensures
378  // that the $controller member always works on the same object as the global variable.
379  // This is a dirty workaround and bypasses the protected access modifier of the controller member.
380  $GLOBALS['TSFE'] = &$this->controller;
381  }
382 }
static devLog($msg, $extKey, $severity=0, $dataVar=false)
handleRequest(\Psr\Http\Message\ServerRequestInterface $request)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
canHandleRequest(\Psr\Http\Message\ServerRequestInterface $request)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']