TYPO3  7.6
frontend/Classes/Http/RequestHandler.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Frontend\Http;
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 = array();
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']->extAdmEnabled) {
272  // Style sheet is also used for frontend editing.
273  $this->controller->content = str_ireplace('</head>', $GLOBALS['BE_USER']->adminPanel->getAdminPanelHeaderData() . '</head>', $this->controller->content);
274  }
275  if ($GLOBALS['BE_USER']->isAdminPanelVisible()) {
276  $this->controller->content = str_ireplace('</body>', $GLOBALS['BE_USER']->displayAdminPanel() . '</body>', $this->controller->content);
277  }
278  }
279 
280  if ($sendTSFEContent) {
282  $response = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\Response::class);
283  $response->getBody()->write($this->controller->content);
284  }
285  // Debugging Output
286  if (isset($GLOBALS['error']) && is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debugOutput'))) {
287  $GLOBALS['error']->debugOutput();
288  }
289  if (TYPO3_DLOG) {
290  GeneralUtility::devLog('END of FRONTEND session', 'cms', 0, array('_FLUSH' => true));
291  }
292  return $response;
293  }
294 
301  public function canHandleRequest(\Psr\Http\Message\ServerRequestInterface $request)
302  {
303  return $request->getQueryParams()['eID'] || $request->getParsedBody()['eID'] ? false : true;
304  }
305 
312  public function getPriority()
313  {
314  return 50;
315  }
316 
321  protected function initializeOutputCompression()
322  {
323  if ($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'] && extension_loaded('zlib')) {
324  if (MathUtility::canBeInterpretedAsInteger($GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel'])) {
325  @ini_set('zlib.output_compression_level', $GLOBALS['TYPO3_CONF_VARS']['FE']['compressionLevel']);
326  }
327  ob_start(array(GeneralUtility::makeInstance(CompressionUtility::class), 'compressionOutputHandler'));
328  }
329  }
330 
336  protected function initializeTimeTracker()
337  {
338  $configuredCookieName = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['cookieName']);
339  if (empty($configuredCookieName)) {
340  $configuredCookieName = 'be_typo_user';
341  }
342  if ($this->request->getCookieParams()[$configuredCookieName]) {
343  $this->timeTracker = new TimeTracker();
344  } else {
345  $this->timeTracker = new NullTimeTracker();
346  }
347 
348  // We have to define this as reference here, because there is code around
349  // which exchanges the TT object in the global variable. The reference ensures
350  // that the $timeTracker member always works on the same object as the global variable.
351  // This is a dirty workaround and bypasses the protected access modifier of the $timeTracker member.
352  $GLOBALS['TT'] = &$this->timeTracker;
353  $this->timeTracker->start();
354  }
355 
361  protected function initializeController()
362  {
363  $this->controller = GeneralUtility::makeInstance(
364  TypoScriptFrontendController::class,
365  $GLOBALS['TYPO3_CONF_VARS'],
366  GeneralUtility::_GP('id'),
367  GeneralUtility::_GP('type'),
368  GeneralUtility::_GP('no_cache'),
369  GeneralUtility::_GP('cHash'),
370  GeneralUtility::_GP('jumpurl'),
371  GeneralUtility::_GP('MP'),
372  GeneralUtility::_GP('RDCT')
373  );
374  // setting the global variable for the controller
375  // We have to define this as reference here, because there is code around
376  // which exchanges the TSFE object in the global variable. The reference ensures
377  // that the $controller member always works on the same object as the global variable.
378  // This is a dirty workaround and bypasses the protected access modifier of the controller member.
379  $GLOBALS['TSFE'] = &$this->controller;
380  }
381 }