‪TYPO3CMS  10.4
RequestHandler.php
Go to the documentation of this file.
1 <?php
2 
3 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 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
23 use Psr\Http\Server\RequestHandlerInterface;
43 
65 class ‪RequestHandler implements RequestHandlerInterface
66 {
71  protected ‪$timeTracker;
72 
77 
78  public function ‪__construct(EventDispatcherInterface ‪$eventDispatcher)
79  {
80  $this->eventDispatcher = ‪$eventDispatcher;
81  }
82 
92  protected function ‪resetGlobalsToCurrentRequest(ServerRequestInterface $request)
93  {
94  if ($request->getQueryParams() !== $_GET) {
95  $queryParams = $request->getQueryParams();
96  $_GET = $queryParams;
97  ‪$GLOBALS['HTTP_GET_VARS'] = $_GET;
98  }
99  if ($request->getMethod() === 'POST') {
100  $parsedBody = $request->getParsedBody();
101  if (is_array($parsedBody) && $parsedBody !== $_POST) {
102  $_POST = $parsedBody;
103  ‪$GLOBALS['HTTP_POST_VARS'] = $_POST;
104  }
105  }
106  ‪$GLOBALS['TYPO3_REQUEST'] = $request;
107  }
108 
115  public function ‪handle(ServerRequestInterface $request): ResponseInterface
116  {
117  // Fetch the initialized time tracker object
118  $this->timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
120  $controller = ‪$GLOBALS['TSFE'];
121 
122  $this->‪resetGlobalsToCurrentRequest($request);
123 
124  // Generate page
125  if ($controller->isGeneratePage()) {
126  $this->timeTracker->push('Page generation');
127  $controller->generatePage_preProcessing();
128  $controller->preparePageContentGeneration($request);
129 
130  // Content generation
131  $this->timeTracker->incStackPointer();
132  $this->timeTracker->push($controller->sPre, 'PAGE');
133 
134  $controller->content = $this->‪generatePageContent($controller, $request);
135 
136  $this->timeTracker->pull($this->timeTracker->LR ? $controller->content : '');
137  $this->timeTracker->decStackPointer();
138 
139  $controller->generatePage_postProcessing();
140  $this->timeTracker->pull();
141  }
142  $controller->releaseLocks();
143 
144  // Render non-cached page parts by replacing placeholders which are taken from cache or added during page generation
145  if ($controller->isINTincScript()) {
146  if (!$controller->isGeneratePage()) {
147  // When page was generated, this was already called. Avoid calling this twice.
148  $controller->preparePageContentGeneration($request);
149  }
150  $this->timeTracker->push('Non-cached objects');
151  $controller->INTincScript();
152  $this->timeTracker->pull();
153  }
154 
155  // Create a Response object when sending content
156  $response = new Response();
157 
158  // Output content
159  // The if() condition can be removed in TYPO3 v11, which means that TYPO3 will not return a NullResponse
160  // by default anymore, which it hasn't done without any extensions anyway already.
161  $isOutputting = $controller->isOutputting(true);
162  if ($isOutputting) {
163  $this->timeTracker->push('Print Content');
164  $response = $controller->applyHttpHeadersToResponse($response);
165  $controller->processContentForOutput(true);
166  $this->timeTracker->pull();
167  }
168 
169  // Hook for "end-of-frontend"
170  $_params = ['pObj' => &$controller];
171  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'])) {
172  trigger_error('The hook $TYPO3_CONF_VARS[SC_OPTIONS][tslib/class.tslib_fe.php][hook_eofe] will be removed in TYPO3 v11.0. The same functionality can be achieved by using a PSR-15 middleware.', E_USER_DEPRECATED);
173  }
174  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe'] ?? [] as $_funcRef) {
175  GeneralUtility::callUserFunction($_funcRef, $_params, $controller);
176  }
177  $this->‪displayPreviewInfoMessage($controller);
178 
179  if ($isOutputting) {
180  $response->getBody()->write($controller->content);
181  return $response;
182  }
183  return new NullResponse();
184  }
185 
194  protected function ‪generatePageContent(TypoScriptFrontendController $controller, ServerRequestInterface $request): string
195  {
196  // Generate the main content between the <body> tags
197  // This has to be done first, as some additional TSFE-related code could have been written
198  $pageContent = $this->‪generatePageBodyContent($controller);
199  // If 'disableAllHeaderCode' is set, all the pageRenderer settings are not evaluated
200  if ($controller->config['config']['disableAllHeaderCode'] ?? false) {
201  return $pageContent;
202  }
203  // Now, populate pageRenderer with all additional data
204  $this->‪processHtmlBasedRenderingSettings($controller, $controller->getLanguage(), $request);
205  $pageRenderer = $this->‪getPageRenderer();
206  // Add previously generated page content within the <body> tag afterwards
207  $pageRenderer->addBodyContent(LF . $pageContent);
208  if ($controller->isINTincScript()) {
209  // Store the serialized pageRenderer in configuration
210  // @todo: serialize $pageRenderer->getState() in TYPO3 v11
211  $controller->config['INTincScript_ext']['pageRenderer'] = serialize($pageRenderer);
212  // Store the serialized AssetCollector in configuration
213  // @todo: serialize $assetCollector->getState() in TYPO3 v11
214  $controller->config['INTincScript_ext']['assetCollector'] = serialize(GeneralUtility::makeInstance(AssetCollector::class));
215  // Render complete page, keep placeholders for JavaScript and CSS
216  return $pageRenderer->renderPageWithUncachedObjects($controller->config['INTincScript_ext']['divKey']);
217  }
218  // Render complete page
219  return $pageRenderer->render();
220  }
221 
230  protected function ‪generatePageBodyContent(TypoScriptFrontendController $controller): string
231  {
232  $pageContent = $controller->cObj->cObjGet($controller->pSetup) ?: '';
233  if ($controller->pSetup['wrap'] ?? false) {
234  $pageContent = $controller->cObj->wrap($pageContent, $controller->pSetup['wrap']);
235  }
236  if ($controller->pSetup['stdWrap.'] ?? false) {
237  $pageContent = $controller->cObj->stdWrap($pageContent, $controller->pSetup['stdWrap.']);
238  }
239  return $pageContent;
240  }
241 
253  protected function ‪processHtmlBasedRenderingSettings(TypoScriptFrontendController $controller, SiteLanguage $siteLanguage, ServerRequestInterface $request): void
254  {
255  $pageRenderer = $this->‪getPageRenderer();
256  if ($controller->config['config']['moveJsFromHeaderToFooter'] ?? false) {
257  $pageRenderer->enableMoveJsFromHeaderToFooter();
258  }
259  if ($controller->config['config']['pageRendererTemplateFile'] ?? false) {
260  try {
261  $file = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($controller->config['config']['pageRendererTemplateFile']);
262  $pageRenderer->setTemplateFile($file);
263  } catch (Exception $e) {
264  // do nothing
265  }
266  }
267  ‪$headerComment = trim($controller->config['config']['headerComment'] ?? '');
268  if (‪$headerComment) {
269  $pageRenderer->addInlineComment("\t" . str_replace(LF, LF . "\t", ‪$headerComment) . LF);
270  }
271  // Setting charset:
272  $theCharset = $controller->metaCharset;
273  $htmlTagAttributes = [];
274  $htmlLang = $siteLanguage->getHreflang() ?: '';
275 
276  if ($siteLanguage->getDirection()) {
277  $htmlTagAttributes['dir'] = htmlspecialchars($siteLanguage->getDirection());
278  }
279  // Setting document type:
280  $docTypeParts = [];
281  $xmlDocument = true;
282  // Part 1: XML prologue
283  switch ((string)($controller->config['config']['xmlprologue'] ?? '')) {
284  case 'none':
285  $xmlDocument = false;
286  break;
287  case 'xml_10':
288  $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>';
289  break;
290  case 'xml_11':
291  $docTypeParts[] = '<?xml version="1.1" encoding="' . $theCharset . '"?>';
292  break;
293  case '':
294  if ($controller->xhtmlVersion) {
295  $docTypeParts[] = '<?xml version="1.0" encoding="' . $theCharset . '"?>';
296  } else {
297  $xmlDocument = false;
298  }
299  break;
300  default:
301  $docTypeParts[] = $controller->config['config']['xmlprologue'];
302  }
303  // Part 2: DTD
304  $doctype = $controller->config['config']['doctype'] ?? null;
305  $defaultTypeAttributeForJavaScript = 'text/javascript';
306  if ($doctype) {
307  switch ($doctype) {
308  case 'xhtml_trans':
309  $docTypeParts[] = '<!DOCTYPE html
310  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
311  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
312  break;
313  case 'xhtml_strict':
314  $docTypeParts[] = '<!DOCTYPE html
315  PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
316  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
317  break;
318  case 'xhtml_basic':
319  $docTypeParts[] = '<!DOCTYPE html
320  PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
321  "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">';
322  break;
323  case 'xhtml_11':
324  $docTypeParts[] = '<!DOCTYPE html
325  PUBLIC "-//W3C//DTD XHTML 1.1//EN"
326  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
327  break;
328  case 'xhtml+rdfa_10':
329  $docTypeParts[] = '<!DOCTYPE html
330  PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
331  "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">';
332  break;
333  case 'html5':
334  $defaultTypeAttributeForJavaScript = '';
335  $docTypeParts[] = '<!DOCTYPE html>';
336  if ($xmlDocument) {
337  $pageRenderer->setMetaCharsetTag('<meta charset="|" />');
338  } else {
339  $pageRenderer->setMetaCharsetTag('<meta charset="|">');
340  }
341  break;
342  case 'none':
343  break;
344  default:
345  $docTypeParts[] = $doctype;
346  }
347  } else {
348  $docTypeParts[] = '<!DOCTYPE html>';
349  if ($xmlDocument) {
350  $pageRenderer->setMetaCharsetTag('<meta charset="|" />');
351  } else {
352  $pageRenderer->setMetaCharsetTag('<meta charset="|">');
353  }
354  $defaultTypeAttributeForJavaScript = '';
355  }
356  if ($htmlLang) {
357  if ($controller->xhtmlVersion) {
358  $htmlTagAttributes['xml:lang'] = $htmlLang;
359  }
360  if ($controller->xhtmlVersion < 110 || $doctype === 'html5') {
361  $htmlTagAttributes['lang'] = $htmlLang;
362  }
363  }
364  if ($controller->xhtmlVersion || $doctype === 'html5' && $xmlDocument) {
365  // We add this to HTML5 to achieve a slightly better backwards compatibility
366  $htmlTagAttributes['xmlns'] = 'http://www.w3.org/1999/xhtml';
367  if (is_array($controller->config['config']['namespaces.'])) {
368  foreach ($controller->config['config']['namespaces.'] as $prefix => $uri) {
369  // $uri gets htmlspecialchared later
370  $htmlTagAttributes['xmlns:' . htmlspecialchars($prefix)] = $uri;
371  }
372  }
373  }
374  // Swap XML and doctype order around (for MSIE / Opera standards compliance)
375  if ($controller->config['config']['doctypeSwitch'] ?? false) {
376  $docTypeParts = array_reverse($docTypeParts);
377  }
378  // Adding doctype parts:
379  if (!empty($docTypeParts)) {
380  $pageRenderer->setXmlPrologAndDocType(implode(LF, $docTypeParts));
381  }
382  // Begin header section:
383  $htmlTag = $this->‪generateHtmlTag($htmlTagAttributes, $controller->config['config'] ?? [], $controller->cObj);
384  $pageRenderer->setHtmlTag($htmlTag);
385  // Head tag:
386  $headTag = $controller->pSetup['headTag'] ?? '<head>';
387  if (isset($controller->pSetup['headTag.'])) {
388  $headTag = $controller->cObj->stdWrap($headTag, $controller->pSetup['headTag.']);
389  }
390  $pageRenderer->setHeadTag($headTag);
391  // Setting charset meta tag:
392  $pageRenderer->setCharSet($theCharset);
393  $pageRenderer->addInlineComment(GeneralUtility::makeInstance(Typo3Information::class)->getInlineHeaderComment());
394  if ($controller->baseUrl) {
395  $pageRenderer->setBaseUrl($controller->baseUrl);
396  }
397  if ($controller->pSetup['shortcutIcon'] ?? false) {
398  try {
399  $favIcon = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($controller->pSetup['shortcutIcon']);
400  $iconFileInfo = GeneralUtility::makeInstance(ImageInfo::class, ‪Environment::getPublicPath() . '/' . $favIcon);
401  if ($iconFileInfo->isFile()) {
402  $iconMimeType = $iconFileInfo->getMimeType();
403  if ($iconMimeType) {
404  $iconMimeType = ' type="' . $iconMimeType . '"';
405  $pageRenderer->setIconMimeType($iconMimeType);
406  }
407  $pageRenderer->setFavIcon(‪PathUtility::getAbsoluteWebPath($controller->absRefPrefix . $favIcon));
408  }
409  } catch (Exception $e) {
410  // do nothing
411  }
412  }
413  // Including CSS files
414  if (is_array($controller->tmpl->setup['plugin.'] ?? null)) {
415  $stylesFromPlugins = '';
416  foreach ($controller->tmpl->setup['plugin.'] as $key => $iCSScode) {
417  if (is_array($iCSScode)) {
418  if ($iCSScode['_CSS_DEFAULT_STYLE'] && empty($controller->config['config']['removeDefaultCss'])) {
419  if (isset($iCSScode['_CSS_DEFAULT_STYLE.'])) {
420  $cssDefaultStyle = $controller->cObj->stdWrap($iCSScode['_CSS_DEFAULT_STYLE'], $iCSScode['_CSS_DEFAULT_STYLE.']);
421  } else {
422  $cssDefaultStyle = $iCSScode['_CSS_DEFAULT_STYLE'];
423  }
424  $stylesFromPlugins .= '/* default styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssDefaultStyle . LF;
425  }
426  if ($iCSScode['_CSS_PAGE_STYLE'] && empty($controller->config['config']['removePageCss'])) {
427  $cssPageStyle = implode(LF, $iCSScode['_CSS_PAGE_STYLE']);
428  if (isset($iCSScode['_CSS_PAGE_STYLE.'])) {
429  $cssPageStyle = $controller->cObj->stdWrap($cssPageStyle, $iCSScode['_CSS_PAGE_STYLE.']);
430  }
431  $cssPageStyle = '/* specific page styles for extension "' . substr($key, 0, -1) . '" */' . LF . $cssPageStyle;
432  $this->‪addCssToPageRenderer($controller, $cssPageStyle, true, 'InlinePageCss');
433  }
434  }
435  }
436  if (!empty($stylesFromPlugins)) {
437  $this->‪addCssToPageRenderer($controller, $stylesFromPlugins, false, 'InlineDefaultCss');
438  }
439  }
440  /**********************************************************************/
441  /* config.includeCSS / config.includeCSSLibs
442  /**********************************************************************/
443  if (is_array($controller->pSetup['includeCSS.'] ?? null)) {
444  foreach ($controller->pSetup['includeCSS.'] as $key => $CSSfile) {
445  if (!is_array($CSSfile)) {
446  $cssFileConfig = &$controller->pSetup['includeCSS.'][$key . '.'];
447  if (isset($cssFileConfig['if.']) && !$controller->cObj->checkIf($cssFileConfig['if.'])) {
448  continue;
449  }
450  if ($cssFileConfig['external']) {
451  $ss = $CSSfile;
452  } else {
453  try {
454  $ss = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($CSSfile);
455  } catch (Exception $e) {
456  $ss = null;
457  }
458  }
459  if ($ss) {
460  if ($cssFileConfig['import']) {
461  if (!$cssFileConfig['external'] && $ss[0] !== '/') {
462  // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende)
463  $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss;
464  }
465  $cssMedia = !empty($cssFileConfig['media']) ? ' ' . htmlspecialchars($cssFileConfig['media']) : '';
466  $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '")' . $cssMedia . ';', empty($cssFileConfig['disableCompression']), (bool)$cssFileConfig['forceOnTop']);
467  } else {
468  $pageRenderer->addCssFile(
469  $ss,
470  $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet',
471  $cssFileConfig['media'] ?: 'all',
472  $cssFileConfig['title'] ?: '',
473  $cssFileConfig['external'] || (bool)$cssFileConfig['inline'] ? false : empty($cssFileConfig['disableCompression']),
474  (bool)$cssFileConfig['forceOnTop'],
475  $cssFileConfig['allWrap'],
476  (bool)$cssFileConfig['excludeFromConcatenation'] || (bool)$cssFileConfig['inline'],
477  $cssFileConfig['allWrap.']['splitChar'],
478  $cssFileConfig['inline']
479  );
480  unset($cssFileConfig);
481  }
482  }
483  }
484  }
485  }
486  if (is_array($controller->pSetup['includeCSSLibs.'] ?? null)) {
487  foreach ($controller->pSetup['includeCSSLibs.'] as $key => $CSSfile) {
488  if (!is_array($CSSfile)) {
489  $cssFileConfig = &$controller->pSetup['includeCSSLibs.'][$key . '.'];
490  if (isset($cssFileConfig['if.']) && !$controller->cObj->checkIf($cssFileConfig['if.'])) {
491  continue;
492  }
493  if ($cssFileConfig['external']) {
494  $ss = $CSSfile;
495  } else {
496  try {
497  $ss = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($CSSfile);
498  } catch (Exception $e) {
499  $ss = null;
500  }
501  }
502  if ($ss) {
503  if ($cssFileConfig['import']) {
504  if (!$cssFileConfig['external'] && $ss[0] !== '/') {
505  // To fix MSIE 6 that cannot handle these as relative paths (according to Ben v Ende)
506  $ss = GeneralUtility::dirname(GeneralUtility::getIndpEnv('SCRIPT_NAME')) . '/' . $ss;
507  }
508  $cssMedia = !empty($cssFileConfig['media']) ? ' ' . htmlspecialchars($cssFileConfig['media']) : '';
509  $pageRenderer->addCssInlineBlock('import_' . $key, '@import url("' . htmlspecialchars($ss) . '")' . $cssMedia . ';', empty($cssFileConfig['disableCompression']), (bool)$cssFileConfig['forceOnTop']);
510  } else {
511  $pageRenderer->addCssLibrary(
512  $ss,
513  $cssFileConfig['alternate'] ? 'alternate stylesheet' : 'stylesheet',
514  $cssFileConfig['media'] ?: 'all',
515  $cssFileConfig['title'] ?: '',
516  $cssFileConfig['external'] || (bool)$cssFileConfig['inline'] ? false : empty($cssFileConfig['disableCompression']),
517  (bool)$cssFileConfig['forceOnTop'],
518  $cssFileConfig['allWrap'],
519  (bool)$cssFileConfig['excludeFromConcatenation'] || (bool)$cssFileConfig['inline'],
520  $cssFileConfig['allWrap.']['splitChar'],
521  $cssFileConfig['inline']
522  );
523  unset($cssFileConfig);
524  }
525  }
526  }
527  }
528  }
529 
530  // CSS_inlineStyle from TS
531  $style = trim($controller->pSetup['CSS_inlineStyle'] ?? '');
532  $style .= $controller->cObj->cObjGet($controller->pSetup['cssInline.'] ?? null, 'cssInline.');
533  if (trim($style)) {
534  $this->‪addCssToPageRenderer($controller, $style, true, 'additionalTSFEInlineStyle');
535  }
536  // JavaScript library files
537  if (is_array($controller->pSetup['includeJSLibs.'] ?? null)) {
538  foreach ($controller->pSetup['includeJSLibs.'] as $key => $JSfile) {
539  if (!is_array($JSfile)) {
540  if (isset($controller->pSetup['includeJSLibs.'][$key . '.']['if.']) && !$controller->cObj->checkIf($controller->pSetup['includeJSLibs.'][$key . '.']['if.'])) {
541  continue;
542  }
543  if ($controller->pSetup['includeJSLibs.'][$key . '.']['external']) {
544  $ss = $JSfile;
545  } else {
546  try {
547  $ss = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($JSfile);
548  } catch (Exception $e) {
549  $ss = null;
550  }
551  }
552  if ($ss) {
553  $jsFileConfig = &$controller->pSetup['includeJSLibs.'][$key . '.'];
554  $type = $jsFileConfig['type'] ?? $defaultTypeAttributeForJavaScript;
555  $crossOrigin = $jsFileConfig['crossorigin'];
556  if (!$crossOrigin && $jsFileConfig['integrity'] && $jsFileConfig['external']) {
557  $crossOrigin = 'anonymous';
558  }
559  $pageRenderer->addJsLibrary(
560  $key,
561  $ss,
562  $type,
563  $jsFileConfig['external'] ? false : empty($jsFileConfig['disableCompression']),
564  (bool)$jsFileConfig['forceOnTop'],
565  $jsFileConfig['allWrap'],
566  (bool)$jsFileConfig['excludeFromConcatenation'],
567  $jsFileConfig['allWrap.']['splitChar'],
568  (bool)$jsFileConfig['async'],
569  $jsFileConfig['integrity'],
570  (bool)$jsFileConfig['defer'],
571  $crossOrigin,
572  (bool)$jsFileConfig['nomodule']
573  );
574  unset($jsFileConfig);
575  }
576  }
577  }
578  }
579  if (is_array($controller->pSetup['includeJSFooterlibs.'] ?? null)) {
580  foreach ($controller->pSetup['includeJSFooterlibs.'] as $key => $JSfile) {
581  if (!is_array($JSfile)) {
582  if (isset($controller->pSetup['includeJSFooterlibs.'][$key . '.']['if.']) && !$controller->cObj->checkIf($controller->pSetup['includeJSFooterlibs.'][$key . '.']['if.'])) {
583  continue;
584  }
585  if ($controller->pSetup['includeJSFooterlibs.'][$key . '.']['external']) {
586  $ss = $JSfile;
587  } else {
588  try {
589  $ss = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($JSfile);
590  } catch (Exception $e) {
591  $ss = null;
592  }
593  }
594  if ($ss) {
595  $jsFileConfig = &$controller->pSetup['includeJSFooterlibs.'][$key . '.'];
596  $type = $jsFileConfig['type'] ?? $defaultTypeAttributeForJavaScript;
597  $crossorigin = $jsFileConfig['crossorigin'];
598  if (!$crossorigin && $jsFileConfig['integrity'] && $jsFileConfig['external']) {
599  $crossorigin = 'anonymous';
600  }
601  $pageRenderer->addJsFooterLibrary(
602  $key,
603  $ss,
604  $type,
605  $jsFileConfig['external'] ? false : empty($jsFileConfig['disableCompression']),
606  (bool)$jsFileConfig['forceOnTop'],
607  $jsFileConfig['allWrap'],
608  (bool)$jsFileConfig['excludeFromConcatenation'],
609  $jsFileConfig['allWrap.']['splitChar'],
610  (bool)$jsFileConfig['async'],
611  $jsFileConfig['integrity'],
612  (bool)$jsFileConfig['defer'],
613  $crossorigin,
614  (bool)$jsFileConfig['nomodule']
615  );
616  unset($jsFileConfig);
617  }
618  }
619  }
620  }
621  // JavaScript files
622  if (is_array($controller->pSetup['includeJS.'] ?? null)) {
623  foreach ($controller->pSetup['includeJS.'] as $key => $JSfile) {
624  if (!is_array($JSfile)) {
625  if (isset($controller->pSetup['includeJS.'][$key . '.']['if.']) && !$controller->cObj->checkIf($controller->pSetup['includeJS.'][$key . '.']['if.'])) {
626  continue;
627  }
628  if ($controller->pSetup['includeJS.'][$key . '.']['external']) {
629  $ss = $JSfile;
630  } else {
631  try {
632  $ss = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($JSfile);
633  } catch (Exception $e) {
634  $ss = null;
635  }
636  }
637  if ($ss) {
638  $jsConfig = &$controller->pSetup['includeJS.'][$key . '.'];
639  $type = $jsConfig['type'] ?? $defaultTypeAttributeForJavaScript;
640  $crossorigin = $jsConfig['crossorigin'];
641  if (!$crossorigin && $jsConfig['integrity'] && $jsConfig['external']) {
642  $crossorigin = 'anonymous';
643  }
644  $pageRenderer->addJsFile(
645  $ss,
646  $type,
647  $jsConfig['external'] ? false : empty($jsConfig['disableCompression']),
648  (bool)$jsConfig['forceOnTop'],
649  $jsConfig['allWrap'],
650  (bool)$jsConfig['excludeFromConcatenation'],
651  $jsConfig['allWrap.']['splitChar'],
652  (bool)$jsConfig['async'],
653  $jsConfig['integrity'],
654  (bool)$jsConfig['defer'],
655  $crossorigin,
656  (bool)$jsConfig['nomodule']
657  );
658  unset($jsConfig);
659  }
660  }
661  }
662  }
663  if (is_array($controller->pSetup['includeJSFooter.'] ?? null)) {
664  foreach ($controller->pSetup['includeJSFooter.'] as $key => $JSfile) {
665  if (!is_array($JSfile)) {
666  if (isset($controller->pSetup['includeJSFooter.'][$key . '.']['if.']) && !$controller->cObj->checkIf($controller->pSetup['includeJSFooter.'][$key . '.']['if.'])) {
667  continue;
668  }
669  if ($controller->pSetup['includeJSFooter.'][$key . '.']['external']) {
670  $ss = $JSfile;
671  } else {
672  try {
673  $ss = GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($JSfile);
674  } catch (Exception $e) {
675  $ss = null;
676  }
677  }
678  if ($ss) {
679  $jsConfig = &$controller->pSetup['includeJSFooter.'][$key . '.'];
680  $type = $jsConfig['type'] ?? $defaultTypeAttributeForJavaScript;
681  $crossorigin = $jsConfig['crossorigin'];
682  if (!$crossorigin && $jsConfig['integrity'] && $jsConfig['external']) {
683  $crossorigin = 'anonymous';
684  }
685  $pageRenderer->addJsFooterFile(
686  $ss,
687  $type,
688  $jsConfig['external'] ? false : empty($jsConfig['disableCompression']),
689  (bool)$jsConfig['forceOnTop'],
690  $jsConfig['allWrap'],
691  (bool)$jsConfig['excludeFromConcatenation'],
692  $jsConfig['allWrap.']['splitChar'],
693  (bool)$jsConfig['async'],
694  $jsConfig['integrity'],
695  (bool)$jsConfig['defer'],
696  $crossorigin,
697  (bool)$jsConfig['nomodule']
698  );
699  unset($jsConfig);
700  }
701  }
702  }
703  }
704  // Headerdata
705  if (is_array($controller->pSetup['headerData.'] ?? null)) {
706  $pageRenderer->addHeaderData($controller->cObj->cObjGet($controller->pSetup['headerData.'], 'headerData.'));
707  }
708  // Footerdata
709  if (is_array($controller->pSetup['footerData.'] ?? null)) {
710  $pageRenderer->addFooterData($controller->cObj->cObjGet($controller->pSetup['footerData.'], 'footerData.'));
711  }
712  $controller->generatePageTitle();
713 
714  // @internal hook for EXT:seo, will be gone soon, do not use it in your own extensions
715  $_params = ['page' => $controller->page];
716  $_ref = null;
717  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['TYPO3\CMS\Frontend\Page\PageGenerator']['generateMetaTags'] ?? [] as $_funcRef) {
718  GeneralUtility::callUserFunction($_funcRef, $_params, $_ref);
719  }
720 
721  $this->‪generateHrefLangTags($controller, $request);
722  $this->‪generateMetaTagHtml(
723  $controller->pSetup['meta.'] ?? [],
724  $controller->cObj
725  );
726 
727  $controller->INTincScript_loadJSCode();
728  $scriptJsCode = '';
729 
730  if ($controller->spamProtectEmailAddresses && $controller->spamProtectEmailAddresses !== 'ascii') {
731  $scriptJsCode = '
732  /* decrypt helper function */
733  function decryptCharcode(n,start,end,offset) {
734  n = n + offset;
735  if (offset > 0 && n > end) {
736  n = start + (n - end - 1);
737  } else if (offset < 0 && n < start) {
738  n = end - (start - n - 1);
739  }
740  return String.fromCharCode(n);
741  }
742  /* decrypt string */
743  function decryptString(enc,offset) {
744  var dec = "";
745  var len = enc.length;
746  for(var i=0; i < len; i++) {
747  var n = enc.charCodeAt(i);
748  if (n >= 0x2B && n <= 0x3A) {
749  dec += decryptCharcode(n,0x2B,0x3A,offset); /* 0-9 . , - + / : */
750  } else if (n >= 0x40 && n <= 0x5A) {
751  dec += decryptCharcode(n,0x40,0x5A,offset); /* A-Z @ */
752  } else if (n >= 0x61 && n <= 0x7A) {
753  dec += decryptCharcode(n,0x61,0x7A,offset); /* a-z */
754  } else {
755  dec += enc.charAt(i);
756  }
757  }
758  return dec;
759  }
760  /* decrypt spam-protected emails */
761  function linkTo_UnCryptMailto(s) {
762  location.href = decryptString(s,' . $controller->spamProtectEmailAddresses * -1 . ');
763  }
764  ';
765  }
766  // Add inline JS
767  $inlineJS = '';
768  // defined in php
769  if (is_array($controller->inlineJS)) {
770  foreach ($controller->inlineJS as $key => $val) {
771  if (!is_array($val)) {
772  $inlineJS .= LF . $val . LF;
773  }
774  }
775  }
776  // defined in TS with page.inlineJS
777  // Javascript inline code
778  $inline = $controller->cObj->cObjGet($controller->pSetup['jsInline.'] ?? null, 'jsInline.');
779  if ($inline) {
780  $inlineJS .= LF . $inline . LF;
781  }
782  // Javascript inline code for Footer
783  $inlineFooterJs = $controller->cObj->cObjGet($controller->pSetup['jsFooterInline.'] ?? null, 'jsFooterInline.');
784  // Should minify?
785  if ($controller->config['config']['compressJs'] ?? false) {
786  $pageRenderer->enableCompressJavascript();
787  $minifyErrorScript = ($minifyErrorInline = '');
788  $scriptJsCode = ‪GeneralUtility::minifyJavaScript($scriptJsCode, $minifyErrorScript);
789  if ($minifyErrorScript) {
790  $this->timeTracker->setTSlogMessage($minifyErrorScript, 3);
791  }
792  if ($inlineJS) {
793  $inlineJS = ‪GeneralUtility::minifyJavaScript($inlineJS, $minifyErrorInline);
794  if ($minifyErrorInline) {
795  $this->timeTracker->setTSlogMessage($minifyErrorInline, 3);
796  }
797  }
798  if ($inlineFooterJs) {
799  $inlineFooterJs = ‪GeneralUtility::minifyJavaScript($inlineFooterJs, $minifyErrorInline);
800  if ($minifyErrorInline) {
801  $this->timeTracker->setTSlogMessage($minifyErrorInline, 3);
802  }
803  }
804  }
805  if (!isset($controller->config['config']['removeDefaultJS']) || !$controller->config['config']['removeDefaultJS']) {
806  // include default and inlineJS
807  if ($scriptJsCode) {
808  $pageRenderer->addJsInlineCode('_scriptCode', $scriptJsCode, $controller->config['config']['compressJs']);
809  }
810  if ($inlineJS) {
811  $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $controller->config['config']['compressJs']);
812  }
813  if ($inlineFooterJs) {
814  $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $controller->config['config']['compressJs']);
815  }
816  } elseif ($controller->config['config']['removeDefaultJS'] === 'external') {
817  /*
818  * This keeps inlineJS from *_INT Objects from being moved to external files.
819  * At this point in frontend rendering *_INT Objects only have placeholders instead
820  * of actual content so moving these placeholders to external files would
821  * a) break the JS file (syntax errors due to the placeholders)
822  * b) the needed JS would never get included to the page
823  * Therefore inlineJS from *_INT Objects must not be moved to external files but
824  * kept internal.
825  */
826  $inlineJSint = '';
827  $this->‪stripIntObjectPlaceholder($inlineJS, $inlineJSint);
828  if ($inlineJSint) {
829  $pageRenderer->addJsInlineCode('TS_inlineJSint', $inlineJSint, $controller->config['config']['compressJs']);
830  }
831  if (trim($scriptJsCode . $inlineJS)) {
832  $pageRenderer->addJsFile(GeneralUtility::writeJavaScriptContentToTemporaryFile($scriptJsCode . $inlineJS), $defaultTypeAttributeForJavaScript, $controller->config['config']['compressJs']);
833  }
834  if ($inlineFooterJs) {
835  $inlineFooterJSint = '';
836  $this->‪stripIntObjectPlaceholder($inlineFooterJs, $inlineFooterJSint);
837  if ($inlineFooterJSint) {
838  $pageRenderer->addJsFooterInlineCode('TS_inlineFooterJSint', $inlineFooterJSint, $controller->config['config']['compressJs']);
839  }
840  $pageRenderer->addJsFooterFile(GeneralUtility::writeJavaScriptContentToTemporaryFile($inlineFooterJs), $defaultTypeAttributeForJavaScript, $controller->config['config']['compressJs']);
841  }
842  } else {
843  // Include only inlineJS
844  if ($inlineJS) {
845  $pageRenderer->addJsInlineCode('TS_inlineJS', $inlineJS, $controller->config['config']['compressJs']);
846  }
847  if ($inlineFooterJs) {
848  $pageRenderer->addJsFooterInlineCode('TS_inlineFooter', $inlineFooterJs, $controller->config['config']['compressJs']);
849  }
850  }
851  if (isset($controller->pSetup['inlineLanguageLabelFiles.']) && is_array($controller->pSetup['inlineLanguageLabelFiles.'])) {
852  foreach ($controller->pSetup['inlineLanguageLabelFiles.'] as $key => $languageFile) {
853  if (is_array($languageFile)) {
854  continue;
855  }
856  $languageFileConfig = &$controller->pSetup['inlineLanguageLabelFiles.'][$key . '.'];
857  if (isset($languageFileConfig['if.']) && !$controller->cObj->checkIf($languageFileConfig['if.'])) {
858  continue;
859  }
860  $pageRenderer->addInlineLanguageLabelFile(
861  $languageFile,
862  $languageFileConfig['selectionPrefix'] ?: '',
863  $languageFileConfig['stripFromSelectionName'] ?: ''
864  );
865  }
866  }
867  if (isset($controller->pSetup['inlineSettings.']) && is_array($controller->pSetup['inlineSettings.'])) {
868  $pageRenderer->addInlineSettingArray('TS', $controller->pSetup['inlineSettings.']);
869  }
870  // Compression and concatenate settings
871  if ($controller->config['config']['compressCss'] ?? false) {
872  $pageRenderer->enableCompressCss();
873  }
874  if ($controller->config['config']['compressJs'] ?? false) {
875  $pageRenderer->enableCompressJavascript();
876  }
877  if ($controller->config['config']['concatenateCss'] ?? false) {
878  $pageRenderer->enableConcatenateCss();
879  }
880  if ($controller->config['config']['concatenateJs'] ?? false) {
881  $pageRenderer->enableConcatenateJavascript();
882  }
883  // Add header data block
884  if ($controller->additionalHeaderData) {
885  $pageRenderer->addHeaderData(implode(LF, $controller->additionalHeaderData));
886  }
887  // Add footer data block
888  if ($controller->additionalFooterData) {
889  $pageRenderer->addFooterData(implode(LF, $controller->additionalFooterData));
890  }
891  // Header complete, now the body tag is added so the regular content can be applied later-on
892  if ($controller->config['config']['disableBodyTag'] ?? false) {
893  $bodyTag = '';
894  } else {
895  $defBT = (isset($controller->pSetup['bodyTagCObject']) && $controller->pSetup['bodyTagCObject'])
896  ? $controller->cObj->cObjGetSingle($controller->pSetup['bodyTagCObject'], $controller->pSetup['bodyTagCObject.'], 'bodyTagCObject')
897  : '<body>';
898  $bodyTag = (isset($controller->pSetup['bodyTag']) && $controller->pSetup['bodyTag'])
899  ? $controller->pSetup['bodyTag']
900  : $defBT;
901  ‪if (trim($controller->pSetup['bodyTagAdd'] ?? '')) {
902  $bodyTag = preg_replace('/>$/', '', trim($bodyTag)) . ' ' . trim($controller->pSetup['bodyTagAdd']) . '>';
903  }
904  }
905  $pageRenderer->addBodyContent(LF . $bodyTag);
906  }
907 
908  /*************************
909  *
910  * Helper functions
911  *
912  *************************/
913 
921  protected function ‪stripIntObjectPlaceholder(&$searchString, &$intObjects)
922  {
923  $tempArray = [];
924  preg_match_all('/\\<\\!--INT_SCRIPT.[a-z0-9]*--\\>/', $searchString, $tempArray);
925  $searchString = preg_replace('/\\<\\!--INT_SCRIPT.[a-z0-9]*--\\>/', '', $searchString);
926  $intObjects = implode('', $tempArray[0]);
927  }
928 
935  protected function ‪generateMetaTagHtml(array $metaTagTypoScript, ContentObjectRenderer $cObj)
936  {
937  $pageRenderer = $this->‪getPageRenderer();
938 
939  $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
940  $conf = $typoScriptService->convertTypoScriptArrayToPlainArray($metaTagTypoScript);
941  foreach ($conf as $key => $properties) {
942  $replace = false;
943  if (is_array($properties)) {
944  $nodeValue = $properties['_typoScriptNodeValue'] ?? '';
945  $value = trim((string)$cObj->stdWrap($nodeValue, $metaTagTypoScript[$key . '.']));
946  if ($value === '' && !empty($properties['value'])) {
947  $value = $properties['value'];
948  $replace = false;
949  }
950  } else {
951  $value = $properties;
952  }
953 
954  $attribute = 'name';
955  if ((is_array($properties) && !empty($properties['httpEquivalent'])) || strtolower($key) === 'refresh') {
956  $attribute = 'http-equiv';
957  }
958  if (is_array($properties) && !empty($properties['attribute'])) {
959  $attribute = $properties['attribute'];
960  }
961  if (is_array($properties) && !empty($properties['replace'])) {
962  $replace = true;
963  }
964 
965  if (!is_array($value)) {
966  $value = (array)$value;
967  }
968  foreach ($value as $subValue) {
969  if (trim($subValue ?? '') !== '') {
970  $pageRenderer->setMetaTag($attribute, $key, $subValue, [], $replace);
971  }
972  }
973  }
974  }
975 
979  protected function ‪getPageRenderer(): PageRenderer
980  {
981  return GeneralUtility::makeInstance(PageRenderer::class);
982  }
983 
992  protected function ‪addCssToPageRenderer(TypoScriptFrontendController $controller, string $cssStyles, bool $excludeFromConcatenation, string $inlineBlockName)
993  {
994  if (empty($controller->config['config']['inlineStyle2TempFile'] ?? false)) {
995  $this->‪getPageRenderer()->‪addCssInlineBlock($inlineBlockName, $cssStyles, !empty($controller->config['config']['compressCss'] ?? false));
996  } else {
998  GeneralUtility::writeStyleSheetContentToTemporaryFile($cssStyles),
999  'stylesheet',
1000  'all',
1001  '',
1002  (bool)($controller->config['config']['compressCss'] ?? false),
1003  false,
1004  '',
1005  $excludeFromConcatenation
1006  );
1007  }
1008  }
1009 
1029  protected function ‪generateHtmlTag(array $htmlTagAttributes, array $configuration, ContentObjectRenderer $cObj): string
1030  {
1031  if (is_array($configuration['htmlTag.']['attributes.'] ?? null)) {
1032  $attributeString = '';
1033  foreach ($configuration['htmlTag.']['attributes.'] as $attributeName => $value) {
1034  $attributeString .= ' ' . htmlspecialchars($attributeName) . ($value !== '' ? '="' . htmlspecialchars((string)$value) . '"' : '');
1035  // If e.g. "htmlTag.attributes.dir" is set, make sure it is not added again with "implodeAttributes()"
1036  if (isset($htmlTagAttributes[$attributeName])) {
1037  unset($htmlTagAttributes[$attributeName]);
1038  }
1039  }
1040  $attributeString = ltrim(GeneralUtility::implodeAttributes($htmlTagAttributes) . $attributeString);
1041  } elseif (($configuration['htmlTag_setParams'] ?? '') === 'none') {
1042  $attributeString = '';
1043  } elseif (isset($configuration['htmlTag_setParams'])) {
1044  $attributeString = $configuration['htmlTag_setParams'];
1045  } else {
1046  $attributeString = GeneralUtility::implodeAttributes($htmlTagAttributes);
1047  }
1048  $htmlTag = '<html' . ($attributeString ? ' ' . $attributeString : '') . '>';
1049  if (isset($configuration['htmlTag_stdWrap.'])) {
1050  $htmlTag = $cObj->stdWrap($htmlTag, $configuration['htmlTag_stdWrap.']);
1051  }
1052  return $htmlTag;
1053  }
1054 
1055  protected function ‪generateHrefLangTags(‪TypoScriptFrontendController $controller, ServerRequestInterface $request): void
1056  {
1057  $hrefLangs = $this->eventDispatcher->dispatch(
1058  new ‪ModifyHrefLangTagsEvent($request)
1059  )->getHrefLangs();
1060  if (count($hrefLangs) > 1) {
1061  $data = [];
1062  foreach ($hrefLangs as $hrefLang => $href) {
1063  $data[] = sprintf('<link %s/>', GeneralUtility::implodeAttributes([
1064  'rel' => 'alternate',
1065  'hreflang' => $hrefLang,
1066  'href' => $href,
1067  ], true));
1068  }
1069  $controller->additionalHeaderData[] = implode(LF, $data);
1070  }
1071  }
1072 
1079  protected function ‪displayPreviewInfoMessage(TypoScriptFrontendController $controller)
1080  {
1081  $isInPreviewMode = $controller->getContext()->hasAspect('frontend.preview')
1082  && $controller->getContext()->getPropertyFromAspect('frontend.preview', 'isPreview');
1083  if (!$isInPreviewMode || $controller->doWorkspacePreview() || ($controller->config['config']['disablePreviewNotification'] ?? false)) {
1084  return;
1085  }
1086  if ($controller->config['config']['message_preview']) {
1087  $message = $controller->config['config']['message_preview'];
1088  } else {
1089  $label = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_tsfe.xlf:preview');
1090  $styles = [];
1091  $styles[] = 'position: fixed';
1092  $styles[] = 'top: 15px';
1093  $styles[] = 'right: 15px';
1094  $styles[] = 'padding: 8px 18px';
1095  $styles[] = 'background: #fff3cd';
1096  $styles[] = 'border: 1px solid #ffeeba';
1097  $styles[] = 'font-family: sans-serif';
1098  $styles[] = 'font-size: 14px';
1099  $styles[] = 'font-weight: bold';
1100  $styles[] = 'color: #856404';
1101  $styles[] = 'z-index: 20000';
1102  $styles[] = 'user-select: none';
1103  $styles[] = 'pointer-events: none';
1104  $styles[] = 'text-align: center';
1105  $styles[] = 'border-radius: 2px';
1106  $message = '<div id="typo3-preview-info" style="' . implode(';', $styles) . '">' . htmlspecialchars($label) . '</div>';
1107  }
1108  if (!empty($message)) {
1109  $controller->content = str_ireplace('</body>', $message . '</body>', $controller->content);
1110  }
1111  }
1112 
1113  protected function ‪getLanguageService(): ‪LanguageService
1114  {
1115  return GeneralUtility::makeInstance(LanguageServiceFactory::class)->‪createFromUserPreferences(‪$GLOBALS['BE_USER'] ?? null);
1116  }
1117 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:26
‪TYPO3\CMS\Frontend\Http\RequestHandler\$timeTracker
‪TimeTracker $timeTracker
Definition: RequestHandler.php:70
‪TYPO3\CMS\Core\Page\AssetCollector
Definition: AssetCollector.php:44
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\doWorkspacePreview
‪bool doWorkspacePreview()
Definition: TypoScriptFrontendController.php:3419
‪TYPO3\CMS\Frontend\Http\RequestHandler\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: RequestHandler.php:74
‪$headerComment
‪$headerComment
Definition: header-comment.php:38
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Core\Information\Typo3Information
Definition: Typo3Information.php:26
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:180
‪TYPO3\CMS\Core\Utility\GeneralUtility\minifyJavaScript
‪static string minifyJavaScript($script, &$error='')
Definition: GeneralUtility.php:1713
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap
‪string stdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:1590
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\generatePageTitle
‪string generatePageTitle()
Definition: TypoScriptFrontendController.php:2846
‪TYPO3\CMS\Frontend\Http
Definition: Application.php:18
‪TYPO3\CMS\Frontend\Http\RequestHandler\generatePageBodyContent
‪string generatePageBodyContent(TypoScriptFrontendController $controller)
Definition: RequestHandler.php:228
‪if
‪if(PHP_SAPI !=='cli')
Definition: splitAcceptanceTests.php:33
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer
Definition: FilePathSanitizer.php:39
‪TYPO3\CMS\Core\Page\PageRenderer\addCssInlineBlock
‪addCssInlineBlock($name, $block, $compress=false, $forceOnTop=false)
Definition: PageRenderer.php:1259
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\getDirection
‪string getDirection()
Definition: SiteLanguage.php:284
‪TYPO3\CMS\Core\Http\NullResponse
Definition: NullResponse.php:26
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getContext
‪getContext()
Definition: TypoScriptFrontendController.php:3976
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Core\Localization\LanguageService\createFromUserPreferences
‪static createFromUserPreferences(?AbstractUserAuthentication $user)
Definition: LanguageService.php:435
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\getLanguage
‪getLanguage()
Definition: TypoScriptFrontendController.php:3966
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:42
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\isINTincScript
‪bool isINTincScript()
Definition: TypoScriptFrontendController.php:3127
‪TYPO3\CMS\Core\Page\PageRenderer\addCssFile
‪addCssFile($file, $rel='stylesheet', $media='all', $title='', $compress=true, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $inline=false)
Definition: PageRenderer.php:1201
‪TYPO3\CMS\Core\Http\Response
Definition: Response.php:30
‪TYPO3\CMS\Frontend\Http\RequestHandler\addCssToPageRenderer
‪addCssToPageRenderer(TypoScriptFrontendController $controller, string $cssStyles, bool $excludeFromConcatenation, string $inlineBlockName)
Definition: RequestHandler.php:990
‪TYPO3\CMS\Frontend\Http\RequestHandler\stripIntObjectPlaceholder
‪stripIntObjectPlaceholder(&$searchString, &$intObjects)
Definition: RequestHandler.php:919
‪TYPO3\CMS\Frontend\Http\RequestHandler\generateHrefLangTags
‪generateHrefLangTags(TypoScriptFrontendController $controller, ServerRequestInterface $request)
Definition: RequestHandler.php:1053
‪TYPO3\CMS\Frontend\Http\RequestHandler\displayPreviewInfoMessage
‪displayPreviewInfoMessage(TypoScriptFrontendController $controller)
Definition: RequestHandler.php:1077
‪TYPO3\CMS\Frontend\Event\ModifyHrefLangTagsEvent
Definition: ModifyHrefLangTagsEvent.php:27
‪TYPO3\CMS\Core\Type\File\ImageInfo
Definition: ImageInfo.php:27
‪TYPO3\CMS\Core\TypoScript\TypoScriptService
Definition: TypoScriptService.php:25
‪TYPO3\CMS\Frontend\Http\RequestHandler\generatePageContent
‪string generatePageContent(TypoScriptFrontendController $controller, ServerRequestInterface $request)
Definition: RequestHandler.php:192
‪TYPO3\CMS\Frontend\Http\RequestHandler
Definition: RequestHandler.php:66
‪TYPO3\CMS\Frontend\Http\RequestHandler\getLanguageService
‪getLanguageService()
Definition: RequestHandler.php:1111
‪TYPO3\CMS\Core\Resource\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\getHreflang
‪string getHreflang()
Definition: SiteLanguage.php:274
‪TYPO3\CMS\Frontend\Http\RequestHandler\processHtmlBasedRenderingSettings
‪processHtmlBasedRenderingSettings(TypoScriptFrontendController $controller, SiteLanguage $siteLanguage, ServerRequestInterface $request)
Definition: RequestHandler.php:251
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:98
‪TYPO3\CMS\Frontend\Http\RequestHandler\handle
‪ResponseInterface handle(ServerRequestInterface $request)
Definition: RequestHandler.php:113
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Frontend\Http\RequestHandler\generateHtmlTag
‪string generateHtmlTag(array $htmlTagAttributes, array $configuration, ContentObjectRenderer $cObj)
Definition: RequestHandler.php:1027
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController\INTincScript_loadJSCode
‪INTincScript_loadJSCode()
Definition: TypoScriptFrontendController.php:3070
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:97
‪TYPO3\CMS\Frontend\Http\RequestHandler\getPageRenderer
‪PageRenderer getPageRenderer()
Definition: RequestHandler.php:977
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Frontend\Http\RequestHandler\generateMetaTagHtml
‪generateMetaTagHtml(array $metaTagTypoScript, ContentObjectRenderer $cObj)
Definition: RequestHandler.php:933
‪TYPO3\CMS\Core\Utility\PathUtility\getAbsoluteWebPath
‪static string getAbsoluteWebPath($targetPath)
Definition: PathUtility.php:43
‪TYPO3\CMS\Frontend\Http\RequestHandler\__construct
‪__construct(EventDispatcherInterface $eventDispatcher)
Definition: RequestHandler.php:76
‪TYPO3\CMS\Core\TimeTracker\TimeTracker
Definition: TimeTracker.php:30
‪TYPO3\CMS\Core\Resource\Exception
Definition: AbstractFileOperationException.php:16
‪TYPO3\CMS\Frontend\Http\RequestHandler\resetGlobalsToCurrentRequest
‪resetGlobalsToCurrentRequest(ServerRequestInterface $request)
Definition: RequestHandler.php:90