‪TYPO3CMS  ‪main
PageRenderer.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
16 namespace ‪TYPO3\CMS\Core\Page;
17 
18 use Psr\Http\Message\ResponseFactoryInterface;
19 use Psr\Http\Message\ResponseInterface;
20 use Psr\Http\Message\ServerRequestInterface;
21 use Psr\Http\Message\StreamFactoryInterface;
38 
46 {
47  // Constants for the part to be rendered
48  protected const ‪PART_COMPLETE = 0;
49  protected const ‪PART_HEADER = 1;
50  protected const ‪PART_FOOTER = 2;
51 
55  protected ‪$compressJavascript = false;
56 
60  protected ‪$compressCss = false;
61 
65  protected ‪$concatenateJavascript = false;
66 
70  protected ‪$concatenateCss = false;
71 
75  protected ‪$moveJsFromHeaderToFooter = false;
76 
80  protected ‪Locale ‪$locale;
81 
82  // Arrays containing associative array for the included files
86  protected $jsFiles = [];
87 
91  protected $jsFooterFiles = [];
92 
96  protected $jsLibs = [];
97 
101  protected $jsFooterLibs = [];
102 
106  protected $cssFiles = [];
107 
111  protected $cssLibs = [];
112 
118  protected $title;
119 
123  protected $favIcon;
124 
125  // Static header blocks
129  protected $xmlPrologAndDocType = '';
130 
134  protected $inlineComments = [];
135 
139  protected $headerData = [];
140 
144  protected $footerData = [];
145 
149  protected $titleTag = '<title>|</title>';
150 
154  protected $htmlTag = '<html>';
155 
159  protected $headTag = '<head>';
160 
164  protected $iconMimeType = '';
165 
169  protected $shortcutTag = '<link rel="icon" href="%1$s"%2$s />';
170 
171  // Static inline code blocks
175  protected $jsInline = [];
176 
180  protected $jsFooterInline = [];
181 
185  protected $cssInline = [];
186 
190  protected $bodyContent;
191 
195  protected $templateFile;
196 
200  protected $inlineLanguageLabels = [];
201 
205  protected $inlineLanguageLabelFiles = [];
206 
210  protected $inlineSettings = [];
211 
217  protected string $endingSlash = '';
218 
219  protected JavaScriptRenderer $javaScriptRenderer;
220  protected ?‪ConsumableNonce $nonce = null;
221  protected ‪DocType $docType = DocType::html5;
222  protected bool $applyNonceHint = false;
223 
224  public function __construct(
225  protected readonly ‪FrontendInterface $assetsCache,
226  protected readonly ‪MarkerBasedTemplateService $templateService,
227  protected readonly ‪MetaTagManagerRegistry $metaTagRegistry,
228  protected readonly ‪AssetRenderer $assetRenderer,
229  protected readonly ‪ResourceCompressor $resourceCompressor,
230  protected readonly ‪RelativeCssPathFixer $relativeCssPathFixer,
231  protected readonly ‪LanguageServiceFactory $languageServiceFactory,
232  protected readonly ResponseFactoryInterface $responseFactory,
233  protected readonly StreamFactoryInterface $streamFactory,
234  ) {
235  $this->‪reset();
236 
237  $this->‪setMetaTag('name', 'generator', 'TYPO3 CMS');
238  }
239 
243  public function ‪updateState(array $state): void
244  {
245  foreach ($state as $var => $value) {
246  switch ($var) {
247  case 'assetsCache':
248  case 'assetRenderer':
249  case 'templateService':
250  case 'resourceCompressor':
251  case 'relativeCssPathFixer':
252  case 'languageServiceFactory':
253  case 'responseFactory':
254  case 'streamFactory':
255  break;
256  case 'nonce':
257  $this->‪setNonce(new ‪ConsumableNonce($value));
258  break;
259  case 'metaTagRegistry':
260  $this->metaTagRegistry->updateState($value);
261  break;
262  case 'javaScriptRenderer':
263  $this->javaScriptRenderer->updateState($value);
264  break;
265  default:
266  $this->{$var} = $value;
267  break;
268  }
269  }
270  }
271 
275  public function ‪getState(): array
276  {
277  $state = [];
278  foreach (get_object_vars($this) as $var => $value) {
279  switch ($var) {
280  case 'assetsCache':
281  case 'assetRenderer':
282  case 'templateService':
283  case 'resourceCompressor':
284  case 'relativeCssPathFixer':
285  case 'languageServiceFactory':
286  case 'responseFactory':
287  case 'streamFactory':
288  break;
289  case 'nonce':
290  if ($value instanceof ‪ConsumableNonce) {
291  $state[$var] = $value->value;
292  }
293  break;
294  case 'metaTagRegistry':
295  $state[$var] = $this->metaTagRegistry->getState();
296  break;
297  case 'javaScriptRenderer':
298  $state[$var] = $this->javaScriptRenderer->getState();
299  break;
300  default:
301  $state[$var] = $value;
302  break;
303  }
304  }
305  return $state;
306  }
307 
308  public function ‪getJavaScriptRenderer(): JavaScriptRenderer
309  {
310  return $this->javaScriptRenderer;
311  }
312 
316  protected function ‪reset(): void
317  {
318  $this->locale = new ‪Locale();
319  $this->‪setDocType(DocType::html5);
320  $this->templateFile = 'EXT:core/Resources/Private/Templates/PageRenderer.html';
321  $this->jsFiles = [];
322  $this->jsFooterFiles = [];
323  $this->jsInline = [];
324  $this->jsFooterInline = [];
325  $this->jsLibs = [];
326  $this->cssFiles = [];
327  $this->cssInline = [];
328  $this->inlineComments = [];
329  $this->headerData = [];
330  $this->footerData = [];
331  $this->javaScriptRenderer = JavaScriptRenderer::create(
332  $this->‪getStreamlinedFileName('EXT:core/Resources/Public/JavaScript/java-script-item-handler.js', true)
333  );
334  }
335 
336  /*****************************************************/
337  /* */
338  /* Public Setters */
339  /* */
340  /* */
341  /*****************************************************/
347  public function ‪setTitle($title)
348  {
349  $this->title = $title;
350  }
351 
357  public function ‪setXmlPrologAndDocType($xmlPrologAndDocType)
358  {
359  $this->xmlPrologAndDocType = $xmlPrologAndDocType;
360  }
361 
365  public function ‪setLanguage(Locale ‪$locale): void
366  {
367  $this->locale = ‪$locale;
368  $this->‪setDefaultHtmlTag();
369  }
370 
375  protected function ‪setDefaultHtmlTag(): void
376  {
377  if ($this->docType === DocType::html5) {
378  $attributes = [
379  'lang' => $this->locale->getName(),
380  ];
381  if ($this->locale->isRightToLeftLanguageDirection()) {
382  $attributes['dir'] = 'rtl';
383  }
384  $this->‪setHtmlTag('<html ' . GeneralUtility::implodeAttributes($attributes, true) . '>');
385  }
386  }
387 
393  public function ‪setHtmlTag($htmlTag)
394  {
395  $this->htmlTag = $htmlTag;
396  }
397 
403  public function ‪setHeadTag($headTag)
404  {
405  $this->headTag = $headTag;
406  }
407 
413  public function ‪setFavIcon($favIcon)
414  {
415  $this->favIcon = $favIcon;
416  }
417 
423  public function ‪setIconMimeType($iconMimeType)
424  {
425  $this->iconMimeType = $iconMimeType;
426  }
427 
433  public function ‪setTemplateFile($file)
434  {
435  $this->templateFile = $file;
436  }
437 
443  public function ‪setBodyContent($content)
444  {
445  $this->bodyContent = $content;
446  }
447 
448  public function ‪setApplyNonceHint(bool $applyNonceHint): void
449  {
450  $this->applyNonceHint = $applyNonceHint;
451  }
452 
453  /*****************************************************/
454  /* */
455  /* Public Enablers / Disablers */
456  /* */
457  /* */
458  /*****************************************************/
462  public function ‪enableMoveJsFromHeaderToFooter()
463  {
464  $this->moveJsFromHeaderToFooter = true;
465  }
466 
470  public function ‪disableMoveJsFromHeaderToFooter()
471  {
472  $this->moveJsFromHeaderToFooter = false;
473  }
474 
478  public function ‪enableCompressJavascript()
479  {
480  $this->compressJavascript = true;
481  }
482 
486  public function ‪disableCompressJavascript()
487  {
488  $this->compressJavascript = false;
489  }
490 
494  public function ‪enableCompressCss()
495  {
496  $this->compressCss = true;
497  }
498 
502  public function ‪disableCompressCss()
503  {
504  $this->compressCss = false;
505  }
506 
510  public function ‪enableConcatenateJavascript()
511  {
512  $this->concatenateJavascript = true;
513  }
514 
518  public function ‪disableConcatenateJavascript()
519  {
520  $this->concatenateJavascript = false;
521  }
522 
526  public function ‪enableConcatenateCss()
527  {
528  $this->concatenateCss = true;
529  }
530 
534  public function ‪disableConcatenateCss()
535  {
536  $this->concatenateCss = false;
537  }
538 
539  /*****************************************************/
540  /* */
541  /* Public Getters */
542  /* */
543  /* */
544  /*****************************************************/
550  public function ‪getTitle()
551  {
552  return $this->title;
553  }
554 
558  public function ‪getLanguage(): string
559  {
560  return (string)‪$this->locale;
561  }
562 
563  public function ‪setNonce(?ConsumableNonce $nonce): void
564  {
565  $this->nonce = $nonce;
566  }
567 
568  public function ‪setDocType(‪DocType $docType): void
569  {
570  $this->docType = $docType;
571  $this->xmlPrologAndDocType = $docType->getDoctypeDeclaration();
572  $this->‪setDefaultHtmlTag();
573  }
574 
575  public function ‪getDocType(): ‪DocType
576  {
577  return $this->docType;
578  }
579 
585  public function ‪getHtmlTag()
586  {
587  return $this->htmlTag;
588  }
589 
595  public function ‪getHeadTag()
596  {
597  return $this->headTag;
598  }
599 
605  public function ‪getFavIcon()
606  {
607  return $this->favIcon;
608  }
609 
615  public function ‪getIconMimeType()
616  {
617  return $this->iconMimeType;
618  }
619 
625  public function ‪getTemplateFile()
626  {
627  return $this->templateFile;
628  }
629 
636  {
638  }
639 
645  public function ‪getCompressJavascript()
646  {
648  }
649 
655  public function ‪getCompressCss()
656  {
657  return ‪$this->compressCss;
658  }
659 
665  public function ‪getConcatenateJavascript()
666  {
668  }
669 
675  public function ‪getConcatenateCss()
676  {
678  }
679 
685  public function ‪getBodyContent()
686  {
687  return $this->bodyContent;
688  }
689 
695  public function ‪getInlineLanguageLabels()
696  {
697  return $this->inlineLanguageLabels;
698  }
699 
705  public function ‪getInlineLanguageLabelFiles()
706  {
707  return $this->inlineLanguageLabelFiles;
708  }
709 
710  /*****************************************************/
711  /* */
712  /* Public Functions to add Data */
713  /* */
714  /* */
715  /*****************************************************/
716 
727  public function ‪setMetaTag(string $type, string $name, string $content, array $subProperties = [], $replace = true)
728  {
729  // Lowercase all the things
730  $type = strtolower($type);
731  $name = strtolower($name);
732  if (!in_array($type, ['property', 'name', 'http-equiv'], true)) {
733  throw new \InvalidArgumentException(
734  'When setting a meta tag the only types allowed are property, name or http-equiv. "' . $type . '" given.',
735  1496402460
736  );
737  }
738  $manager = $this->metaTagRegistry->getManagerForProperty($name);
739  $manager->addProperty($name, $content, $subProperties, $replace, $type);
740  }
741 
745  public function ‪getMetaTag(string $type, string $name): array
746  {
747  // Lowercase all the things
748  $type = strtolower($type);
749  $name = strtolower($name);
750 
751  $manager = $this->metaTagRegistry->getManagerForProperty($name);
752  $propertyContent = $manager->getProperty($name, $type);
753 
754  if (!empty($propertyContent[0])) {
755  return [
756  'type' => $type,
757  'name' => $name,
758  'content' => $propertyContent[0]['content'],
759  ];
760  }
761  return [];
762  }
763 
767  public function ‪removeMetaTag(string $type, string $name)
768  {
769  // Lowercase all the things
770  $type = strtolower($type);
771  $name = strtolower($name);
772 
773  $manager = $this->metaTagRegistry->getManagerForProperty($name);
774  $manager->removeProperty($name, $type);
775  }
776 
782  public function ‪addInlineComment($comment)
783  {
784  if (!in_array($comment, $this->inlineComments)) {
785  $this->inlineComments[] = $comment;
786  }
787  }
788 
794  public function ‪addHeaderData($data)
795  {
796  if (!in_array($data, $this->headerData)) {
797  $this->headerData[] = $data;
798  }
799  }
800 
806  public function ‪addFooterData($data)
807  {
808  if (!in_array($data, $this->footerData)) {
809  $this->footerData[] = $data;
810  }
811  }
812 
831  public function ‪addJsLibrary($name, $file, $type = '', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '', $nomodule = false, array $tagAttributes = [])
832  {
833  if ($type === null) {
834  $type = $this->docType === DocType::html5 ? '' : 'text/javascript';
835  }
836  if (!isset($this->jsLibs[strtolower($name)])) {
837  $this->jsLibs[strtolower($name)] = [
838  'file' => $file,
839  'type' => $type,
840  'section' => ‪self::PART_HEADER,
841  'compress' => $compress,
842  'forceOnTop' => $forceOnTop,
843  'allWrap' => $allWrap,
844  'excludeFromConcatenation' => $excludeFromConcatenation,
845  'splitChar' => $splitChar,
846  'async' => $async,
847  'integrity' => $integrity,
848  'defer' => $defer,
849  'crossorigin' => $crossorigin,
850  'nomodule' => $nomodule,
851  'tagAttributes' => $tagAttributes,
852  ];
853  }
854  }
855 
874  public function ‪addJsFooterLibrary($name, $file, $type = '', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '', $nomodule = false, array $tagAttributes = [])
875  {
876  if ($type === null) {
877  $type = $this->docType === DocType::html5 ? '' : 'text/javascript';
878  }
879  $name .= '_jsFooterLibrary';
880  if (!isset($this->jsLibs[strtolower($name)])) {
881  $this->jsLibs[strtolower($name)] = [
882  'file' => $file,
883  'type' => $type,
884  'section' => ‪self::PART_FOOTER,
885  'compress' => $compress,
886  'forceOnTop' => $forceOnTop,
887  'allWrap' => $allWrap,
888  'excludeFromConcatenation' => $excludeFromConcatenation,
889  'splitChar' => $splitChar,
890  'async' => $async,
891  'integrity' => $integrity,
892  'defer' => $defer,
893  'crossorigin' => $crossorigin,
894  'nomodule' => $nomodule,
895  'tagAttributes' => $tagAttributes,
896  ];
897  }
898  }
899 
917  public function ‪addJsFile($file, $type = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '', $nomodule = false, array $tagAttributes = [])
918  {
919  if ($type === null) {
920  $type = $this->docType === DocType::html5 ? '' : 'text/javascript';
921  }
922  if (!isset($this->jsFiles[$file])) {
923  $this->jsFiles[$file] = [
924  'file' => $file,
925  'type' => $type,
926  'section' => ‪self::PART_HEADER,
927  'compress' => $compress,
928  'forceOnTop' => $forceOnTop,
929  'allWrap' => $allWrap,
930  'excludeFromConcatenation' => $excludeFromConcatenation,
931  'splitChar' => $splitChar,
932  'async' => $async,
933  'integrity' => $integrity,
934  'defer' => $defer,
935  'crossorigin' => $crossorigin,
936  'nomodule' => $nomodule,
937  'tagAttributes' => $tagAttributes,
938  ];
939  }
940  }
941 
959  public function ‪addJsFooterFile($file, $type = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '', $defer = false, $crossorigin = '', $nomodule = false, array $tagAttributes = [])
960  {
961  if ($type === null) {
962  $type = $this->docType === DocType::html5 ? '' : 'text/javascript';
963  }
964  if (!isset($this->jsFiles[$file])) {
965  $this->jsFiles[$file] = [
966  'file' => $file,
967  'type' => $type,
968  'section' => ‪self::PART_FOOTER,
969  'compress' => $compress,
970  'forceOnTop' => $forceOnTop,
971  'allWrap' => $allWrap,
972  'excludeFromConcatenation' => $excludeFromConcatenation,
973  'splitChar' => $splitChar,
974  'async' => $async,
975  'integrity' => $integrity,
976  'defer' => $defer,
977  'crossorigin' => $crossorigin,
978  'nomodule' => $nomodule,
979  'tagAttributes' => $tagAttributes,
980  ];
981  }
982  }
983 
992  public function ‪addJsInlineCode($name, $block, $compress = true, $forceOnTop = false, bool $useNonce = false)
993  {
994  if (!isset($this->jsInline[$name]) && !empty($block)) {
995  $this->jsInline[$name] = [
996  'code' => $block . LF,
997  'section' => ‪self::PART_HEADER,
998  'compress' => $compress,
999  'forceOnTop' => $forceOnTop,
1000  'useNonce' => $useNonce,
1001  ];
1002  }
1003  }
1004 
1013  public function ‪addJsFooterInlineCode($name, $block, $compress = true, $forceOnTop = false, bool $useNonce = false)
1014  {
1015  if (!isset($this->jsInline[$name]) && !empty($block)) {
1016  $this->jsInline[$name] = [
1017  'code' => $block . LF,
1018  'section' => ‪self::PART_FOOTER,
1019  'compress' => $compress,
1020  'forceOnTop' => $forceOnTop,
1021  'useNonce' => $useNonce,
1022  ];
1023  }
1024  }
1025 
1041  public function ‪addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $inline = false, array $tagAttributes = [])
1042  {
1043  if (!isset($this->cssFiles[$file])) {
1044  $this->cssFiles[$file] = [
1045  'file' => $file,
1046  'rel' => $rel,
1047  'media' => $media,
1048  'title' => $title,
1049  'compress' => $compress,
1050  'forceOnTop' => $forceOnTop,
1051  'allWrap' => $allWrap,
1052  'excludeFromConcatenation' => $excludeFromConcatenation,
1053  'splitChar' => $splitChar,
1054  'inline' => $inline,
1055  'tagAttributes' => $tagAttributes,
1056  ];
1057  }
1058  }
1059 
1075  public function ‪addCssLibrary($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $inline = false, array $tagAttributes = [])
1076  {
1077  if (!isset($this->cssLibs[$file])) {
1078  $this->cssLibs[$file] = [
1079  'file' => $file,
1080  'rel' => $rel,
1081  'media' => $media,
1082  'title' => $title,
1083  'compress' => $compress,
1084  'forceOnTop' => $forceOnTop,
1085  'allWrap' => $allWrap,
1086  'excludeFromConcatenation' => $excludeFromConcatenation,
1087  'splitChar' => $splitChar,
1088  'inline' => $inline,
1089  'tagAttributes' => $tagAttributes,
1090  ];
1091  }
1092  }
1093 
1102  public function ‪addCssInlineBlock($name, $block, $compress = false, $forceOnTop = false, bool $useNonce = false)
1103  {
1104  if (!isset($this->cssInline[$name]) && !empty($block)) {
1105  $this->cssInline[$name] = [
1106  'code' => $block,
1107  'compress' => $compress,
1108  'forceOnTop' => $forceOnTop,
1109  'useNonce' => $useNonce,
1110  ];
1111  }
1112  }
1113 
1120  public function ‪loadJavaScriptModule(string $specifier)
1121  {
1122  $this->javaScriptRenderer->addJavaScriptModuleInstruction(
1124  );
1125  }
1134  public function ‪addInlineLanguageLabel($key, $value)
1135  {
1136  $this->inlineLanguageLabels[$key] = $value;
1137  }
1138 
1144  public function ‪addInlineLanguageLabelArray(array $array)
1145  {
1146  $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
1147  }
1148 
1156  public function ‪addInlineLanguageLabelFile($fileRef, $selectionPrefix = '', $stripFromSelectionName = '')
1157  {
1158  $index = md5($fileRef . $selectionPrefix . $stripFromSelectionName);
1159  if ($fileRef && !isset($this->inlineLanguageLabelFiles[$index])) {
1160  $this->inlineLanguageLabelFiles[$index] = [
1161  'fileRef' => $fileRef,
1162  'selectionPrefix' => $selectionPrefix,
1163  'stripFromSelectionName' => $stripFromSelectionName,
1164  ];
1165  }
1166  }
1167 
1176  public function ‪addInlineSetting($namespace, $key, $value)
1177  {
1178  if ($namespace) {
1179  if (strpos($namespace, '.')) {
1180  $parts = explode('.', $namespace);
1181  $a = &$this->inlineSettings;
1182  foreach ($parts as $part) {
1183  $a = &$a[$part];
1184  }
1185  $a[$key] = $value;
1186  } else {
1187  $this->inlineSettings[$namespace][$key] = $value;
1188  }
1189  } else {
1190  $this->inlineSettings[$key] = $value;
1191  }
1192  }
1193 
1201  public function ‪addInlineSettingArray($namespace, array $array)
1202  {
1203  if ($namespace) {
1204  if (strpos($namespace, '.')) {
1205  $parts = explode('.', $namespace);
1206  $a = &$this->inlineSettings;
1207  foreach ($parts as $part) {
1208  $a = &$a[$part];
1209  }
1210  $a = array_merge((array)$a, $array);
1211  } else {
1212  $this->inlineSettings[$namespace] = array_merge((array)($this->inlineSettings[$namespace] ?? []), $array);
1213  }
1214  } else {
1215  $this->inlineSettings = array_merge($this->inlineSettings, $array);
1216  }
1217  }
1218 
1224  public function ‪addBodyContent($content)
1225  {
1226  $this->bodyContent .= $content;
1227  }
1228 
1229  /*****************************************************/
1230  /* */
1231  /* Render Functions */
1232  /* */
1233  /*****************************************************/
1239  public function ‪render()
1240  {
1241  $this->‪prepareRendering();
1242  [$jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs] = $this->‪renderJavaScriptAndCss();
1243  $metaTags = implode(LF, $this->‪renderMetaTagsFromAPI());
1244  $markerArray = $this->‪getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags);
1245  $template = $this->‪getTemplate();
1246 
1247  // The page renderer needs a full reset when the page was rendered
1248  $this->‪reset();
1249  return trim($this->templateService->substituteMarkerArray($template, $markerArray, '###|###'));
1250  }
1251 
1252  public function ‪renderResponse(
1253  int $code = 200,
1254  string $reasonPhrase = '',
1255  ): ResponseInterface {
1256  $stream = $this->streamFactory->createStream($this->‪render());
1257  return $this->responseFactory->createResponse($code, $reasonPhrase)
1258  ->withHeader('Content-Type', 'text/html; charset=utf-8')
1259  ->withBody($stream);
1260  }
1261 
1267  protected function ‪renderMetaTagsFromAPI()
1268  {
1269  $metaTags = [];
1270  $metaTagManagers = $this->metaTagRegistry->getAllManagers();
1271 
1272  foreach ($metaTagManagers as $manager => $managerObject) {
1273  $properties = $managerObject->renderAllProperties();
1274  if (!empty($properties)) {
1275  $metaTags[] = $properties;
1276  }
1277  }
1278  return $metaTags;
1279  }
1280 
1288  public function ‪renderPageWithUncachedObjects($substituteHash)
1289  {
1290  $this->‪prepareRendering();
1291  $markerArray = $this->‪getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash);
1292  $template = $this->‪getTemplate();
1293  return trim($this->templateService->substituteMarkerArray($template, $markerArray, '###|###'));
1294  }
1295 
1305  public function ‪renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash)
1306  {
1308  [$jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs] = $this->‪renderJavaScriptAndCss();
1309  $title = $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '';
1310  $markerArray = [
1311  '<!-- ###TITLE' . $substituteHash . '### -->' => $title,
1312  '<!-- ###CSS_LIBS' . $substituteHash . '### -->' => $cssLibs,
1313  '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->' => $cssFiles,
1314  '<!-- ###CSS_INLINE' . $substituteHash . '### -->' => $cssInline,
1315  '<!-- ###JS_INLINE' . $substituteHash . '### -->' => $jsInline,
1316  '<!-- ###JS_INCLUDE' . $substituteHash . '### -->' => $jsFiles,
1317  '<!-- ###JS_LIBS' . $substituteHash . '### -->' => $jsLibs,
1318  '<!-- ###META' . $substituteHash . '### -->' => implode(LF, $this->‪renderMetaTagsFromAPI()),
1319  '<!-- ###HEADERDATA' . $substituteHash . '### -->' => implode(LF, $this->headerData),
1320  '<!-- ###FOOTERDATA' . $substituteHash . '### -->' => implode(LF, $this->footerData),
1321  '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->' => $jsFooterLibs,
1322  '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->' => $jsFooterFiles,
1323  '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->' => $jsFooterInline,
1324  ];
1325  foreach ($markerArray as $placeHolder => $content) {
1326  $cachedPageContent = str_replace($placeHolder, $content, $cachedPageContent);
1327  }
1328  $this->‪reset();
1329  return $cachedPageContent;
1330  }
1331 
1337  protected function ‪prepareRendering()
1338  {
1339  if ($this->docType->isXmlCompliant()) {
1340  $this->endingSlash = ' /';
1341  } else {
1342  $this->shortcutTag = str_replace(' />', '>', $this->shortcutTag);
1343  $this->endingSlash = '';
1344  }
1345  }
1346 
1352  protected function ‪renderJavaScriptAndCss()
1353  {
1354  $this->‪executePreRenderHook();
1355  $mainJsLibs = $this->‪renderMainJavaScriptLibraries();
1356  if ($this->concatenateJavascript || $this->concatenateCss) {
1357  // Do the file concatenation
1358  $this->‪doConcatenate();
1359  }
1360  if ($this->compressCss || $this->compressJavascript) {
1361  // Do the file compression
1362  $this->‪doCompress();
1363  }
1365  $cssLibs = $this->‪renderCssLibraries();
1366  $cssFiles = $this->‪renderCssFiles();
1367  $cssInline = $this->‪renderCssInline();
1368  [$jsLibs, $jsFooterLibs] = $this->‪renderAdditionalJavaScriptLibraries();
1369  [$jsFiles, $jsFooterFiles] = $this->‪renderJavaScriptFiles();
1370  [$jsInline, $jsFooterInline] = $this->‪renderInlineJavaScript();
1371  $jsLibs = $mainJsLibs . $jsLibs;
1372  if ($this->moveJsFromHeaderToFooter) {
1373  $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
1374  $jsLibs = '';
1375  $jsFooterFiles = $jsFiles . LF . $jsFooterFiles;
1376  $jsFiles = '';
1377  $jsFooterInline = $jsInline . LF . $jsFooterInline;
1378  $jsInline = '';
1379  }
1380  // Use AssetRenderer to inject all JavaScripts and CSS files
1381  $jsInline .= $this->assetRenderer->renderInlineJavaScript(true, $this->nonce);
1382  $jsFooterInline .= $this->assetRenderer->renderInlineJavaScript(false, $this->nonce);
1383  $jsFiles .= $this->assetRenderer->renderJavaScript(true, $this->nonce);
1384  $jsFooterFiles .= $this->assetRenderer->renderJavaScript(false, $this->nonce);
1385  $cssInline .= $this->assetRenderer->renderInlineStyleSheets(true, $this->nonce);
1386  // append inline CSS to footer (as there is no cssFooterInline)
1387  $jsFooterFiles .= $this->assetRenderer->renderInlineStyleSheets(false, $this->nonce);
1388  $cssLibs .= $this->assetRenderer->renderStyleSheets(true, $this->endingSlash, $this->nonce);
1389  $cssFiles .= $this->assetRenderer->renderStyleSheets(false, $this->endingSlash, $this->nonce);
1390 
1391  $this->‪executePostRenderHook($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs);
1392  return [$jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs];
1393  }
1394 
1410  protected function ‪getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags)
1411  {
1412  $markerArray = [
1413  'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
1414  'HTMLTAG' => $this->htmlTag,
1415  'HEADTAG' => $this->headTag,
1416  'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
1417  'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
1418  'CSS_LIBS' => $cssLibs,
1419  'CSS_INCLUDE' => $cssFiles,
1420  'CSS_INLINE' => $cssInline,
1421  'JS_INLINE' => $jsInline,
1422  'JS_INCLUDE' => $jsFiles,
1423  'JS_LIBS' => $jsLibs,
1424  'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
1425  'META' => $metaTags,
1426  'HEADERDATA' => $this->headerData ? implode(LF, $this->headerData) : '',
1427  'FOOTERDATA' => $this->footerData ? implode(LF, $this->footerData) : '',
1428  'JS_LIBS_FOOTER' => $jsFooterLibs,
1429  'JS_INCLUDE_FOOTER' => $jsFooterFiles,
1430  'JS_INLINE_FOOTER' => $jsFooterInline,
1431  'BODY' => $this->bodyContent,
1432  // @internal
1433  'TRAILING_SLASH_FOR_SELF_CLOSING_TAG' => $this->endingSlash ? ' ' . $this->endingSlash : '',
1434  ];
1435  $markerArray = array_map(static fn($item) => (trim((string)$item)), $markerArray);
1436  return $markerArray;
1437  }
1438 
1445  protected function ‪getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash)
1446  {
1447  $markerArray = [
1448  'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
1449  'HTMLTAG' => $this->htmlTag,
1450  'HEADTAG' => $this->headTag,
1451  'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
1452  'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
1453  'META' => '<!-- ###META' . $substituteHash . '### -->',
1454  'BODY' => $this->bodyContent,
1455  'TITLE' => '<!-- ###TITLE' . $substituteHash . '### -->',
1456  'CSS_LIBS' => '<!-- ###CSS_LIBS' . $substituteHash . '### -->',
1457  'CSS_INCLUDE' => '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->',
1458  'CSS_INLINE' => '<!-- ###CSS_INLINE' . $substituteHash . '### -->',
1459  'JS_INLINE' => '<!-- ###JS_INLINE' . $substituteHash . '### -->',
1460  'JS_INCLUDE' => '<!-- ###JS_INCLUDE' . $substituteHash . '### -->',
1461  'JS_LIBS' => '<!-- ###JS_LIBS' . $substituteHash . '### -->',
1462  'HEADERDATA' => '<!-- ###HEADERDATA' . $substituteHash . '### -->',
1463  'FOOTERDATA' => '<!-- ###FOOTERDATA' . $substituteHash . '### -->',
1464  'JS_LIBS_FOOTER' => '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->',
1465  'JS_INCLUDE_FOOTER' => '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->',
1466  'JS_INLINE_FOOTER' => '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->',
1467  // @internal
1468  'TRAILING_SLASH_FOR_SELF_CLOSING_TAG' => $this->endingSlash ? ' ' . $this->endingSlash : '',
1469  ];
1470  $markerArray = array_map(static fn($item) => (trim((string)$item)), $markerArray);
1471  return $markerArray;
1472  }
1473 
1477  protected function ‪getTemplate(): string
1478  {
1479  $templateFile = GeneralUtility::getFileAbsFileName($this->templateFile);
1480  if (is_file($templateFile)) {
1481  $template = (string)file_get_contents($templateFile);
1482  } else {
1483  $template = '';
1484  }
1485  return $template;
1486  }
1487 
1493  protected function ‪renderMainJavaScriptLibraries()
1494  {
1495  $out = '';
1496 
1497  // adds a nonce hint/work-around for lit-elements (which is only applied automatically in ShadowDOM)
1498  // see https://lit.dev/docs/api/ReactiveElement/#ReactiveElement.styles)
1499  if ($this->applyNonceHint && $this->nonce !== null) {
1500  $out .= GeneralUtility::wrapJS(
1501  sprintf('window.litNonce = %s;', GeneralUtility::quoteJSvalue($this->nonce->consume())),
1502  ['nonce' => $this->nonce->consume()]
1503  );
1504  }
1505 
1506  $out .= $this->javaScriptRenderer->renderImportMap(
1507  // @todo hookup with PSR-7 request/response and
1508  GeneralUtility::getIndpEnv('TYPO3_SITE_PATH'),
1509  $this->nonce
1510  );
1511 
1513  if ($this->‪getApplicationType() === 'BE') {
1514  $noBackendUserLoggedIn = empty(‪$GLOBALS['BE_USER']->user['uid']);
1515  $this->‪addAjaxUrlsToInlineSettings($noBackendUserLoggedIn);
1517  }
1518  $assignments = array_filter([
1519  'settings' => $this->inlineSettings,
1520  'lang' => $this->‪parseLanguageLabelsForJavaScript(),
1521  ]);
1522  if ($assignments !== []) {
1523  if ($this->‪getApplicationType() === 'BE') {
1524  $this->javaScriptRenderer->addGlobalAssignment(['TYPO3' => $assignments]);
1525  } else {
1526  $out .= $this->‪wrapInlineScript(
1527  sprintf(
1528  "var TYPO3 = Object.assign(TYPO3 || {}, %s);\r\n",
1529  // filter potential prototype pollution
1530  sprintf(
1531  'Object.fromEntries(Object.entries(%s).filter((entry) => '
1532  . "!['__proto__', 'prototype', 'constructor'].includes(entry[0])))",
1533  json_encode($assignments)
1534  )
1535  ),
1536  $this->nonce !== null ? ['nonce' => $this->nonce->consume()] : []
1537  );
1538  }
1539  }
1540  $out .= $this->javaScriptRenderer->render($this->nonce);
1541  return $out;
1542  }
1543 
1547  protected function ‪parseLanguageLabelsForJavaScript(): array
1548  {
1549  if (empty($this->inlineLanguageLabels)) {
1550  return [];
1551  }
1552 
1553  $labels = [];
1554  foreach ($this->inlineLanguageLabels as $key => $translationUnit) {
1555  if (is_array($translationUnit)) {
1556  $translationUnit = current($translationUnit);
1557  $labels[$key] = $translationUnit['target'] ?? $translationUnit['source'];
1558  } else {
1559  $labels[$key] = $translationUnit;
1560  }
1561  }
1562 
1563  return $labels;
1564  }
1565 
1569  protected function ‪loadJavaScriptLanguageStrings()
1570  {
1571  foreach ($this->inlineLanguageLabelFiles as $languageLabelFile) {
1572  $this->‪includeLanguageFileForInline($languageLabelFile['fileRef'], $languageLabelFile['selectionPrefix'], $languageLabelFile['stripFromSelectionName']);
1573  }
1574  $this->inlineLanguageLabelFiles = [];
1575  }
1576 
1580  protected function ‪addAjaxUrlsToInlineSettings(bool $publicRoutesOnly = false)
1581  {
1582  $ajaxUrls = [];
1583  // Add the ajax-based routes
1584  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
1585  $router = GeneralUtility::makeInstance(Router::class);
1586  foreach ($router->getRoutes() as $routeIdentifier => $route) {
1587  if ($publicRoutesOnly && $route->getOption('access') !== 'public') {
1588  continue;
1589  }
1590  if ($route->getOption('ajax')) {
1591  $uri = (string)$uriBuilder->buildUriFromRoute($routeIdentifier);
1592  // use the shortened value in order to use this in JavaScript
1593  $routeIdentifier = str_replace('ajax_', '', $routeIdentifier);
1594  $ajaxUrls[$routeIdentifier] = $uri;
1595  }
1596  }
1597 
1598  $this->inlineSettings['ajaxUrls'] = $ajaxUrls;
1599  }
1600 
1601  protected function ‪addGlobalCSSUrlsToInlineSettings()
1602  {
1603  $this->inlineSettings['cssUrls'] = [
1604  'backend' => $this->‪getStreamlinedFileName('EXT:backend/Resources/Public/Css/backend.css'),
1605  ];
1606  }
1607 
1613  protected function ‪renderCssLibraries()
1614  {
1615  $cssFiles = '';
1616  if (!empty($this->cssLibs)) {
1617  foreach ($this->cssLibs as $file => $properties) {
1618  $tag = $this->‪createCssTag($properties, $file);
1619  if ($properties['forceOnTop'] ?? false) {
1620  $cssFiles = $tag . $cssFiles;
1621  } else {
1622  $cssFiles .= $tag;
1623  }
1624  }
1625  }
1626  return $cssFiles;
1627  }
1628 
1634  protected function ‪renderCssFiles()
1635  {
1636  $cssFiles = '';
1637  if (!empty($this->cssFiles)) {
1638  foreach ($this->cssFiles as $file => $properties) {
1639  $tag = $this->‪createCssTag($properties, $file);
1640  if ($properties['forceOnTop'] ?? false) {
1641  $cssFiles = $tag . $cssFiles;
1642  } else {
1643  $cssFiles .= $tag;
1644  }
1645  }
1646  }
1647  return $cssFiles;
1648  }
1649 
1653  private function ‪createCssTag(array $properties, string $file): string
1654  {
1655  $includeInline = $properties['inline'] ?? false;
1656  $file = $this->‪getStreamlinedFileName($file, !$includeInline);
1657  if ($includeInline && @is_file($file)) {
1658  $tag = $this->‪createInlineCssTagFromFile($file, $properties);
1659  } else {
1660  $tagAttributes = [];
1661  if ($properties['rel'] ?? false) {
1662  $tagAttributes['rel'] = $properties['rel'];
1663  }
1664  $tagAttributes['href'] = $file;
1665  if ($properties['media'] ?? false) {
1666  $tagAttributes['media'] = $properties['media'];
1667  }
1668  if ($properties['title'] ?? false) {
1669  $tagAttributes['title'] = $properties['title'];
1670  }
1671  // use nonce if given
1672  if ($this->nonce !== null) {
1673  $tagAttributes['nonce'] = $this->nonce->consume();
1674  }
1675  $tagAttributes = array_merge($tagAttributes, $properties['tagAttributes'] ?? []);
1676  $tag = '<link ' . GeneralUtility::implodeAttributes($tagAttributes, true, true) . $this->endingSlash . '>';
1677  }
1678  if ($properties['allWrap'] ?? false) {
1679  $wrapArr = explode(($properties['splitChar'] ?? false) ?: '|', $properties['allWrap'], 2);
1680  $tag = $wrapArr[0] . $tag . $wrapArr[1];
1681  }
1682  $tag .= LF;
1683 
1684  return $tag;
1685  }
1686 
1692  protected function ‪renderCssInline()
1693  {
1694  if (empty($this->cssInline)) {
1695  return '';
1696  }
1697  $cssItems = [0 => [], 1 => []];
1698  foreach ($this->cssInline as $name => $properties) {
1699  $nonceKey = (int)(!empty($properties['useNonce']));
1700  $cssCode = '/*' . htmlspecialchars($name) . '*/' . LF . ($properties['code'] ?? '') . LF;
1701  if ($properties['forceOnTop'] ?? false) {
1702  array_unshift($cssItems[$nonceKey], $cssCode);
1703  } else {
1704  $cssItems[$nonceKey][] = $cssCode;
1705  }
1706  }
1707  $cssItems = array_filter($cssItems);
1708  foreach ($cssItems as $useNonce => $items) {
1709  $attributes = $useNonce && $this->nonce !== null ? ['nonce' => $this->nonce->consume()] : [];
1710  $cssItems[$useNonce] = $this->‪wrapInlineStyle(implode('', $items), $attributes);
1711  }
1712  return implode(LF, $cssItems);
1713  }
1714 
1720  protected function ‪renderAdditionalJavaScriptLibraries()
1721  {
1722  $jsLibs = '';
1723  $jsFooterLibs = '';
1724  if (!empty($this->jsLibs)) {
1725  foreach ($this->jsLibs as $properties) {
1726  $tagAttributes = [];
1727  $tagAttributes['src'] = $this->‪getStreamlinedFileName($properties['file'] ?? '');
1728  if ($properties['type'] ?? false) {
1729  $tagAttributes['type'] = $properties['type'];
1730  }
1731  if ($properties['async'] ?? false) {
1732  $tagAttributes['async'] = 'async';
1733  }
1734  if ($properties['defer'] ?? false) {
1735  $tagAttributes['defer'] = 'defer';
1736  }
1737  if ($properties['nomodule'] ?? false) {
1738  $tagAttributes['nomodule'] = 'nomodule';
1739  }
1740  if ($properties['integrity'] ?? false) {
1741  $tagAttributes['integrity'] = $properties['integrity'];
1742  }
1743  if ($properties['crossorigin'] ?? false) {
1744  $tagAttributes['crossorigin'] = $properties['crossorigin'];
1745  }
1746  // use nonce if given
1747  if ($this->nonce !== null) {
1748  $tagAttributes['nonce'] = $this->nonce->consume();
1749  }
1750  $tagAttributes = array_merge($tagAttributes, $properties['tagAttributes'] ?? []);
1751  $tag = '<script ' . GeneralUtility::implodeAttributes($tagAttributes, true, true) . '></script>';
1752  if ($properties['allWrap'] ?? false) {
1753  $wrapArr = explode(($properties['splitChar'] ?? false) ?: '|', $properties['allWrap'], 2);
1754  $tag = $wrapArr[0] . $tag . $wrapArr[1];
1755  }
1756  $tag .= LF;
1757  if ($properties['forceOnTop'] ?? false) {
1758  if (($properties['section'] ?? 0) === self::PART_HEADER) {
1759  $jsLibs = $tag . $jsLibs;
1760  } else {
1761  $jsFooterLibs = $tag . $jsFooterLibs;
1762  }
1763  } elseif (($properties['section'] ?? 0) === self::PART_HEADER) {
1764  $jsLibs .= $tag;
1765  } else {
1766  $jsFooterLibs .= $tag;
1767  }
1768  }
1769  }
1770  if ($this->moveJsFromHeaderToFooter) {
1771  $jsFooterLibs = $jsLibs . LF . $jsFooterLibs;
1772  $jsLibs = '';
1773  }
1774  return [$jsLibs, $jsFooterLibs];
1775  }
1776 
1782  protected function ‪renderJavaScriptFiles()
1783  {
1784  $jsFiles = '';
1785  $jsFooterFiles = '';
1786  if (!empty($this->jsFiles)) {
1787  foreach ($this->jsFiles as $file => $properties) {
1788  $tagAttributes = [];
1789  $tagAttributes['src'] = $this->‪getStreamlinedFileName($file);
1790  if ($properties['type'] ?? false) {
1791  $tagAttributes['type'] = $properties['type'];
1792  }
1793  if ($properties['async'] ?? false) {
1794  $tagAttributes['async'] = 'async';
1795  }
1796  if ($properties['defer'] ?? false) {
1797  $tagAttributes['defer'] = 'defer';
1798  }
1799  if ($properties['nomodule'] ?? false) {
1800  $tagAttributes['nomodule'] = 'nomodule';
1801  }
1802  if ($properties['integrity'] ?? false) {
1803  $tagAttributes['integrity'] = $properties['integrity'];
1804  }
1805  if ($properties['crossorigin'] ?? false) {
1806  $tagAttributes['crossorigin'] = $properties['crossorigin'];
1807  }
1808  // use nonce if given
1809  if ($this->nonce !== null) {
1810  $tagAttributes['nonce'] = $this->nonce->consume();
1811  }
1812  $tagAttributes = array_merge($tagAttributes, $properties['tagAttributes'] ?? []);
1813  $tag = '<script ' . GeneralUtility::implodeAttributes($tagAttributes, true, true) . '></script>';
1814  if ($properties['allWrap'] ?? false) {
1815  $wrapArr = explode(($properties['splitChar'] ?? false) ?: '|', $properties['allWrap'], 2);
1816  $tag = $wrapArr[0] . $tag . $wrapArr[1];
1817  }
1818  $tag .= LF;
1819  if ($properties['forceOnTop'] ?? false) {
1820  if (($properties['section'] ?? 0) === self::PART_HEADER) {
1821  $jsFiles = $tag . $jsFiles;
1822  } else {
1823  $jsFooterFiles = $tag . $jsFooterFiles;
1824  }
1825  } elseif (($properties['section'] ?? 0) === self::PART_HEADER) {
1826  $jsFiles .= $tag;
1827  } else {
1828  $jsFooterFiles .= $tag;
1829  }
1830  }
1831  }
1832  if ($this->moveJsFromHeaderToFooter) {
1833  $jsFooterFiles = $jsFiles . $jsFooterFiles;
1834  $jsFiles = '';
1835  }
1836  return [$jsFiles, $jsFooterFiles];
1837  }
1838 
1844  protected function ‪renderInlineJavaScript()
1845  {
1846  if (empty($this->jsInline)) {
1847  return ['', ''];
1848  }
1849  $regularItems = [0 => [], 1 => []];
1850  $footerItems = [0 => [], 1 => []];
1851  foreach ($this->jsInline as $name => $properties) {
1852  $nonceKey = (int)(!empty($properties['useNonce'])); // 0 or 1
1853  $jsCode = '/*' . htmlspecialchars($name) . '*/' . LF . ($properties['code'] ?? '') . LF;
1854  if ($properties['forceOnTop'] ?? false) {
1855  if (($properties['section'] ?? 0) === ‪self::PART_HEADER) {
1856  array_unshift($regularItems[$nonceKey], $jsCode);
1857  } else {
1858  array_unshift($footerItems[$nonceKey], $jsCode);
1859  }
1860  } elseif (($properties['section'] ?? 0) === self::PART_HEADER) {
1861  $regularItems[$nonceKey][] = $jsCode;
1862  } else {
1863  $footerItems[$nonceKey][] = $jsCode;
1864  }
1865  }
1866  $regularItems = array_filter($regularItems);
1867  $footerItems = array_filter($footerItems);
1868  foreach ($regularItems as $useNonce => $items) {
1869  $attributes = $useNonce && $this->nonce !== null ? ['nonce' => $this->nonce->consume()] : [];
1870  $regularItems[$useNonce] = $this->‪wrapInlineScript(implode('', $items), $attributes);
1871  }
1872  foreach ($footerItems as $useNonce => $items) {
1873  $attributes = $useNonce && $this->nonce !== null ? ['nonce' => $this->nonce->consume()] : [];
1874  $footerItems[$useNonce] = $this->‪wrapInlineScript(implode('', $items), $attributes);
1875  }
1876  $regularCode = implode(LF, $regularItems);
1877  $footerCode = implode(LF, $footerItems);
1878  if ($this->moveJsFromHeaderToFooter) {
1879  $footerCode = $regularCode . $footerCode;
1880  $regularCode = '';
1881  }
1882  return [$regularCode, $footerCode];
1883  }
1884 
1892  protected function ‪includeLanguageFileForInline($fileRef, $selectionPrefix = '', $stripFromSelectionName = '')
1893  {
1894  $labelsFromFile = [];
1895  $allLabels = $this->‪readLLfile($fileRef);
1896 
1897  // Iterate through all labels from the language file
1898  foreach ($allLabels as $label => $value) {
1899  // If $selectionPrefix is set, only respect labels that start with $selectionPrefix
1900  if ($selectionPrefix === '' || str_starts_with($label, $selectionPrefix)) {
1901  // Remove substring $stripFromSelectionName from label
1902  $label = str_replace($stripFromSelectionName, '', $label);
1903  $labelsFromFile[$label] = $value;
1904  }
1905  }
1906  $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $labelsFromFile);
1907  }
1908 
1915  protected function ‪readLLfile(string $fileRef): array
1916  {
1917  $languageService = $this->languageServiceFactory->create($this->locale);
1918  return $languageService->getLabelsFromResource($fileRef);
1919  }
1920 
1921  /*****************************************************/
1922  /* */
1923  /* Tools */
1924  /* */
1925  /*****************************************************/
1930  protected function ‪doConcatenate()
1931  {
1932  $this->‪doConcatenateCss();
1933  $this->‪doConcatenateJavaScript();
1934  }
1935 
1939  protected function ‪doConcatenateJavaScript()
1940  {
1941  if ($this->‪getApplicationType() !== 'FE') {
1942  return;
1943  }
1944  if (!$this->concatenateJavascript) {
1945  return;
1946  }
1947  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['jsConcatenateHandler'])) {
1948  // use external concatenation routine
1949  $params = [
1950  'jsLibs' => &$this->jsLibs,
1951  'jsFiles' => &$this->jsFiles,
1952  'jsFooterFiles' => &$this->jsFooterFiles,
1953  'headerData' => &$this->headerData,
1954  'footerData' => &$this->footerData,
1955  ];
1956  GeneralUtility::callUserFunction(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['jsConcatenateHandler'], $params, $this);
1957  } else {
1958  $this->jsLibs = $this->resourceCompressor->concatenateJsFiles($this->jsLibs);
1959  $this->jsFiles = $this->resourceCompressor->concatenateJsFiles($this->jsFiles);
1960  $this->jsFooterFiles = $this->resourceCompressor->concatenateJsFiles($this->jsFooterFiles);
1961  }
1962  }
1967  protected function ‪doConcatenateCss()
1968  {
1969  if ($this->‪getApplicationType() !== 'FE') {
1970  return;
1971  }
1972  if (!$this->concatenateCss) {
1973  return;
1974  }
1975  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['cssConcatenateHandler'])) {
1976  // use external concatenation routine
1977  $params = [
1978  'cssFiles' => &$this->cssFiles,
1979  'cssLibs' => &$this->cssLibs,
1980  'headerData' => &$this->headerData,
1981  'footerData' => &$this->footerData,
1982  ];
1983  GeneralUtility::callUserFunction(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['cssConcatenateHandler'], $params, $this);
1984  } else {
1985  $this->cssLibs = $this->resourceCompressor->concatenateCssFiles($this->cssLibs);
1986  $this->cssFiles = $this->resourceCompressor->concatenateCssFiles($this->cssFiles);
1987  }
1988  }
1989 
1993  protected function ‪doCompress()
1994  {
1995  $this->‪doCompressJavaScript();
1996  $this->‪doCompressCss();
1997  }
1998 
2002  protected function ‪doCompressCss()
2003  {
2004  if ($this->‪getApplicationType() !== 'FE') {
2005  return;
2006  }
2007  if (!$this->compressCss) {
2008  return;
2009  }
2010  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['cssCompressHandler'])) {
2011  // Use external compression routine
2012  $params = [
2013  'cssInline' => &$this->cssInline,
2014  'cssFiles' => &$this->cssFiles,
2015  'cssLibs' => &$this->cssLibs,
2016  'headerData' => &$this->headerData,
2017  'footerData' => &$this->footerData,
2018  ];
2019  GeneralUtility::callUserFunction(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['cssCompressHandler'], $params, $this);
2020  } else {
2021  $this->cssLibs = $this->resourceCompressor->compressCssFiles($this->cssLibs);
2022  $this->cssFiles = $this->resourceCompressor->compressCssFiles($this->cssFiles);
2023  }
2024  }
2025 
2029  protected function ‪doCompressJavaScript()
2030  {
2031  if ($this->‪getApplicationType() !== 'FE') {
2032  return;
2033  }
2034  if (!$this->compressJavascript) {
2035  return;
2036  }
2037  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['jsCompressHandler'])) {
2038  // Use external compression routine
2039  $params = [
2040  'jsInline' => &$this->jsInline,
2041  'jsFooterInline' => &$this->jsFooterInline,
2042  'jsLibs' => &$this->jsLibs,
2043  'jsFiles' => &$this->jsFiles,
2044  'jsFooterFiles' => &$this->jsFooterFiles,
2045  'headerData' => &$this->headerData,
2046  'footerData' => &$this->footerData,
2047  ];
2048  GeneralUtility::callUserFunction(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['jsCompressHandler'], $params, $this);
2049  } else {
2050  // Traverse the arrays, compress files
2051  foreach ($this->jsInline ?? [] as $name => $properties) {
2052  if ($properties['compress'] ?? false) {
2053  $this->jsInline[$name]['code'] = $this->resourceCompressor->compressJavaScriptSource($properties['code'] ?? '');
2054  }
2055  }
2056  $this->jsLibs = $this->resourceCompressor->compressJsFiles($this->jsLibs);
2057  $this->jsFiles = $this->resourceCompressor->compressJsFiles($this->jsFiles);
2058  $this->jsFooterFiles = $this->resourceCompressor->compressJsFiles($this->jsFooterFiles);
2059  }
2060  }
2061 
2070  protected function ‪processJsFile($filename)
2071  {
2072  $filename = $this->‪getStreamlinedFileName($filename, false);
2073  if ($this->‪getApplicationType() === 'FE') {
2074  if ($this->compressJavascript) {
2075  $filename = $this->resourceCompressor->compressJsFile($filename);
2076  } else {
2077  $filename = GeneralUtility::createVersionNumberedFilename($filename);
2078  }
2079  }
2080  return $this->‪getAbsoluteWebPath($filename);
2081  }
2082 
2095  protected function ‪getStreamlinedFileName($file, $prepareForOutput = true)
2096  {
2097  if (‪PathUtility::isExtensionPath($file)) {
2099  // as the path is now absolute, make it "relative" to the current script to stay compatible
2100  $file = ‪PathUtility::getRelativePathTo($file) ?? '';
2101  $file = rtrim($file, '/');
2102  } else {
2103  $file = GeneralUtility::resolveBackPath($file);
2104  }
2105  if ($prepareForOutput) {
2106  $file = GeneralUtility::createVersionNumberedFilename($file);
2107  $file = $this->‪getAbsoluteWebPath($file);
2108  }
2109  return $file;
2110  }
2111 
2119  protected function ‪getAbsoluteWebPath(string $file): string
2120  {
2121  if ($this->‪getApplicationType() === 'FE') {
2122  return $file;
2123  }
2124  return ‪PathUtility::getAbsoluteWebPath($file);
2125  }
2126 
2127  /*****************************************************/
2128  /* */
2129  /* Hooks */
2130  /* */
2131  /*****************************************************/
2135  protected function ‪executePreRenderHook()
2136  {
2137  $hooks = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'] ?? false;
2138  if (!$hooks) {
2139  return;
2140  }
2141  $params = [
2142  'jsLibs' => &$this->jsLibs,
2143  'jsFooterLibs' => &$this->jsFooterLibs,
2144  'jsFiles' => &$this->jsFiles,
2145  'jsFooterFiles' => &$this->jsFooterFiles,
2146  'cssLibs' => &$this->cssLibs,
2147  'cssFiles' => &$this->cssFiles,
2148  'headerData' => &$this->headerData,
2149  'footerData' => &$this->footerData,
2150  'jsInline' => &$this->jsInline,
2151  'jsFooterInline' => &$this->jsFooterInline,
2152  'cssInline' => &$this->cssInline,
2153  ];
2154  foreach ($hooks as $hook) {
2155  GeneralUtility::callUserFunction($hook, $params, $this);
2156  }
2157  }
2158 
2162  protected function ‪executeRenderPostTransformHook()
2163  {
2164  $hooks = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'] ?? false;
2165  if (!$hooks) {
2166  return;
2167  }
2168  $params = [
2169  'jsLibs' => &$this->jsLibs,
2170  'jsFooterLibs' => &$this->jsFooterLibs,
2171  'jsFiles' => &$this->jsFiles,
2172  'jsFooterFiles' => &$this->jsFooterFiles,
2173  'cssLibs' => &$this->cssLibs,
2174  'cssFiles' => &$this->cssFiles,
2175  'headerData' => &$this->headerData,
2176  'footerData' => &$this->footerData,
2177  'jsInline' => &$this->jsInline,
2178  'jsFooterInline' => &$this->jsFooterInline,
2179  'cssInline' => &$this->cssInline,
2180  ];
2181  foreach ($hooks as $hook) {
2182  GeneralUtility::callUserFunction($hook, $params, $this);
2183  }
2184  }
2185 
2199  protected function ‪executePostRenderHook(&$jsLibs, &$jsFiles, &$jsFooterFiles, &$cssLibs, &$cssFiles, &$jsInline, &$cssInline, &$jsFooterInline, &$jsFooterLibs)
2200  {
2201  $hooks = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'] ?? false;
2202  if (!$hooks) {
2203  return;
2204  }
2205  $params = [
2206  'jsLibs' => &$jsLibs,
2207  'jsFiles' => &$jsFiles,
2208  'jsFooterFiles' => &$jsFooterFiles,
2209  'cssLibs' => &$cssLibs,
2210  'cssFiles' => &$cssFiles,
2211  'headerData' => &$this->headerData,
2212  'footerData' => &$this->footerData,
2213  'jsInline' => &$jsInline,
2214  'cssInline' => &$cssInline,
2215  'xmlPrologAndDocType' => &$this->xmlPrologAndDocType,
2216  'htmlTag' => &$this->htmlTag,
2217  'headTag' => &$this->headTag,
2218  'shortcutTag' => &$this->shortcutTag,
2219  'inlineComments' => &$this->inlineComments,
2220  'favIcon' => &$this->favIcon,
2221  'iconMimeType' => &$this->iconMimeType,
2222  'titleTag' => &$this->titleTag,
2223  'title' => &$this->title,
2224  'jsFooterInline' => &$jsFooterInline,
2225  'jsFooterLibs' => &$jsFooterLibs,
2226  'bodyContent' => &$this->bodyContent,
2227  ];
2228  foreach ($hooks as $hook) {
2229  GeneralUtility::callUserFunction($hook, $params, $this);
2230  }
2231  }
2232 
2238  protected function ‪createInlineCssTagFromFile(string $file, array $properties): string
2239  {
2240  $cssInline = file_get_contents($file);
2241  if ($cssInline === false) {
2242  return '';
2243  }
2244  $cssInlineFix = $this->relativeCssPathFixer->fixRelativeUrlPaths($cssInline, '/' . ‪PathUtility::dirname($file) . '/');
2245  $tagAttributes = [];
2246  if ($properties['media'] ?? false) {
2247  $tagAttributes['media'] = $properties['media'];
2248  }
2249  if ($properties['title'] ?? false) {
2250  $tagAttributes['title'] = $properties['title'];
2251  }
2252  // use nonce if given - special case, since content is created from a static file
2253  if ($this->nonce !== null) {
2254  $tagAttributes['nonce'] = $this->nonce->consume();
2255  }
2256  $tagAttributes = array_merge($tagAttributes, $properties['tagAttributes'] ?? []);
2257  return '<style ' . GeneralUtility::implodeAttributes($tagAttributes, true, true) . '>' . LF
2258  . '/*<![CDATA[*/' . LF . '<!-- ' . LF
2259  . $cssInlineFix
2260  . '-->' . LF . '/*]]>*/' . LF . '</style>' . LF;
2261  }
2262 
2263  protected function ‪wrapInlineStyle(string $content, array $attributes = []): string
2264  {
2265  $attributesList = GeneralUtility::implodeAttributes($attributes, true);
2266  return sprintf(
2267  "<style%s>\n/*<![CDATA[*/\n<!-- \n%s-->\n/*]]>*/\n</style>\n",
2268  $attributesList !== '' ? ' ' . $attributesList : '',
2269  $content
2270  );
2271  }
2272 
2273  protected function ‪wrapInlineScript(string $content, array $attributes = []): string
2274  {
2275  // * Whenever HTML5 is used, remove the "text/javascript" type from the wrap
2276  // since this is not needed and may lead to validation errors in the future.
2277  // * Whenever XHTML gets disabled, remove the "text/javascript" type from the wrap
2278  // since this is not needed and may lead to validation errors in the future.
2279  if ($this->docType !== DocType::html5 || $this->docType->isXmlCompliant()) {
2280  $attributes['type'] = 'text/javascript';
2281  }
2282 
2283  $attributesList = GeneralUtility::implodeAttributes($attributes, true);
2284  return sprintf(
2285  "<script%s>\n/*<![CDATA[*/\n%s/*]]>*/\n</script>\n",
2286  $attributesList !== '' ? ' ' . $attributesList : '',
2287  $content
2288  );
2289  }
2290 
2296  public function ‪getApplicationType(): string
2297  {
2298  if (
2299  (‪$GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface &&
2300  ‪ApplicationType::fromRequest(‪$GLOBALS['TYPO3_REQUEST'])->isFrontend()
2301  ) {
2302  return 'FE';
2303  }
2304 
2305  return 'BE';
2306  }
2307 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Core\Page\PageRenderer\addJsLibrary
‪addJsLibrary($name, $file, $type='', $compress=false, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $async=false, $integrity='', $defer=false, $crossorigin='', $nomodule=false, array $tagAttributes=[])
Definition: PageRenderer.php:801
‪TYPO3\CMS\Core\Page\PageRenderer\disableCompressJavascript
‪disableCompressJavascript()
Definition: PageRenderer.php:456
‪TYPO3\CMS\Core\Page\PageRenderer\addInlineLanguageLabelFile
‪addInlineLanguageLabelFile($fileRef, $selectionPrefix='', $stripFromSelectionName='')
Definition: PageRenderer.php:1126
‪TYPO3\CMS\Core\Page\PageRenderer\renderCssInline
‪string renderCssInline()
Definition: PageRenderer.php:1662
‪TYPO3\CMS\Core\Page\PageRenderer\readLLfile
‪array readLLfile(string $fileRef)
Definition: PageRenderer.php:1885
‪TYPO3\CMS\Core\Page\PageRenderer\enableConcatenateJavascript
‪enableConcatenateJavascript()
Definition: PageRenderer.php:480
‪TYPO3\CMS\Core\Page\PageRenderer\renderJavaScriptAndCssForProcessingOfUncachedContentObjects
‪string renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash)
Definition: PageRenderer.php:1275
‪TYPO3\CMS\Core\Page\PageRenderer\setDefaultHtmlTag
‪setDefaultHtmlTag()
Definition: PageRenderer.php:345
‪TYPO3\CMS\Core\Utility\PathUtility\isExtensionPath
‪static isExtensionPath(string $path)
Definition: PathUtility.php:117
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Core\Page\PageRenderer\setFavIcon
‪setFavIcon($favIcon)
Definition: PageRenderer.php:383
‪TYPO3\CMS\Core\Page\PageRenderer\loadJavaScriptLanguageStrings
‪loadJavaScriptLanguageStrings()
Definition: PageRenderer.php:1539
‪TYPO3\CMS\Core\Page\PageRenderer\renderJavaScriptFiles
‪array string[] renderJavaScriptFiles()
Definition: PageRenderer.php:1752
‪TYPO3\CMS\Core\Page\PageRenderer\addGlobalCSSUrlsToInlineSettings
‪addGlobalCSSUrlsToInlineSettings()
Definition: PageRenderer.php:1571
‪TYPO3\CMS\Core\Page\PageRenderer\addJsFooterInlineCode
‪addJsFooterInlineCode($name, $block, $compress=true, $forceOnTop=false, bool $useNonce=false)
Definition: PageRenderer.php:983
‪TYPO3\CMS\Core\Page\PageRenderer\renderAdditionalJavaScriptLibraries
‪array string[] renderAdditionalJavaScriptLibraries()
Definition: PageRenderer.php:1690
‪TYPO3\CMS\Core\Page\PageRenderer\enableCompressJavascript
‪enableCompressJavascript()
Definition: PageRenderer.php:448
‪TYPO3\CMS\Core\Page\PageRenderer\doCompressCss
‪doCompressCss()
Definition: PageRenderer.php:1972
‪TYPO3\CMS\Core\Page\PageRenderer\getConcatenateCss
‪bool getConcatenateCss()
Definition: PageRenderer.php:645
‪TYPO3\CMS\Core\Page\PageRenderer\getIconMimeType
‪string getIconMimeType()
Definition: PageRenderer.php:585
‪TYPO3\CMS\Core\Page\PageRenderer\renderMainJavaScriptLibraries
‪string renderMainJavaScriptLibraries()
Definition: PageRenderer.php:1463
‪TYPO3\CMS\Core\Page\PageRenderer\getTemplateFile
‪string getTemplateFile()
Definition: PageRenderer.php:595
‪TYPO3\CMS\Core\Page\PageRenderer\renderCssFiles
‪string renderCssFiles()
Definition: PageRenderer.php:1604
‪TYPO3\CMS\Core\Page\PageRenderer\renderJavaScriptAndCss
‪array string[] renderJavaScriptAndCss()
Definition: PageRenderer.php:1322
‪TYPO3\CMS\Core\Page\PageRenderer\enableConcatenateCss
‪enableConcatenateCss()
Definition: PageRenderer.php:496
‪TYPO3\CMS\Core\Page\PageRenderer\$concatenateCss
‪bool $concatenateCss
Definition: PageRenderer.php:66
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Core\Page\PageRenderer\getJavaScriptRenderer
‪getJavaScriptRenderer()
Definition: PageRenderer.php:278
‪TYPO3\CMS\Core\Utility\PathUtility\getRelativePathTo
‪static getRelativePathTo(string $absolutePath)
Definition: PathUtility.php:33
‪TYPO3\CMS\Core\Page\PageRenderer\getFavIcon
‪string getFavIcon()
Definition: PageRenderer.php:575
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction\create
‪static create(string $name, string $exportName=null)
Definition: JavaScriptModuleInstruction.php:47
‪TYPO3\CMS\Core\Page\PageRenderer\addJsInlineCode
‪addJsInlineCode($name, $block, $compress=true, $forceOnTop=false, bool $useNonce=false)
Definition: PageRenderer.php:962
‪TYPO3\CMS\Core\Page\PageRenderer\getState
‪getState()
Definition: PageRenderer.php:245
‪TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce
Definition: ConsumableNonce.php:24
‪TYPO3\CMS\Core\Page\PageRenderer\addCssInlineBlock
‪addCssInlineBlock($name, $block, $compress=false, $forceOnTop=false, bool $useNonce=false)
Definition: PageRenderer.php:1072
‪TYPO3\CMS\Core\Page\PageRenderer\PART_COMPLETE
‪const PART_COMPLETE
Definition: PageRenderer.php:48
‪TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry
Definition: MetaTagManagerRegistry.php:28
‪TYPO3\CMS\Core\Resource\ResourceCompressor
Definition: ResourceCompressor.php:31
‪TYPO3\CMS\Core\Page\PageRenderer\setHeadTag
‪setHeadTag($headTag)
Definition: PageRenderer.php:373
‪TYPO3\CMS\Core\Page
Definition: AssetCollector.php:18
‪TYPO3\CMS\Core\Page\PageRenderer\doConcatenate
‪doConcatenate()
Definition: PageRenderer.php:1900
‪TYPO3\CMS\Core\Page\PageRenderer\getInlineLanguageLabelFiles
‪array getInlineLanguageLabelFiles()
Definition: PageRenderer.php:675
‪TYPO3\CMS\Core\Page\PageRenderer\getTemplate
‪getTemplate()
Definition: PageRenderer.php:1447
‪TYPO3\CMS\Core\Page\PageRenderer\setApplyNonceHint
‪setApplyNonceHint(bool $applyNonceHint)
Definition: PageRenderer.php:418
‪TYPO3\CMS\Core\Page\PageRenderer\getBodyContent
‪string getBodyContent()
Definition: PageRenderer.php:655
‪TYPO3\CMS\Core\Page\PageRenderer\disableConcatenateJavascript
‪disableConcatenateJavascript()
Definition: PageRenderer.php:488
‪TYPO3\CMS\Core\Page\PageRenderer\getAbsoluteWebPath
‪getAbsoluteWebPath(string $file)
Definition: PageRenderer.php:2089
‪TYPO3\CMS\Core\Page\PageRenderer\doCompress
‪doCompress()
Definition: PageRenderer.php:1963
‪TYPO3\CMS\Core\Page\PageRenderer\getHtmlTag
‪string getHtmlTag()
Definition: PageRenderer.php:555
‪TYPO3\CMS\Core\Page\PageRenderer\$compressJavascript
‪bool $compressJavascript
Definition: PageRenderer.php:54
‪TYPO3\CMS\Core\Page\PageRenderer\getPreparedMarkerArrayForPageWithUncachedObjects
‪array getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash)
Definition: PageRenderer.php:1415
‪TYPO3\CMS\Core\Page\PageRenderer\renderPageWithUncachedObjects
‪string renderPageWithUncachedObjects($substituteHash)
Definition: PageRenderer.php:1258
‪TYPO3\CMS\Core\Page\PageRenderer\setXmlPrologAndDocType
‪setXmlPrologAndDocType($xmlPrologAndDocType)
Definition: PageRenderer.php:327
‪TYPO3\CMS\Core\Page\PageRenderer\disableMoveJsFromHeaderToFooter
‪disableMoveJsFromHeaderToFooter()
Definition: PageRenderer.php:440
‪TYPO3\CMS\Core\Page\PageRenderer\addInlineSettingArray
‪addInlineSettingArray($namespace, array $array)
Definition: PageRenderer.php:1171
‪TYPO3\CMS\Core\Page\PageRenderer\renderCssLibraries
‪string renderCssLibraries()
Definition: PageRenderer.php:1583
‪TYPO3\CMS\Core\Page\PageRenderer\addInlineLanguageLabel
‪addInlineLanguageLabel($key, $value)
Definition: PageRenderer.php:1104
‪TYPO3\CMS\Core\Utility\PathUtility\getAbsoluteWebPath
‪static string getAbsoluteWebPath(string $targetPath, bool $prefixWithSitePath=true)
Definition: PathUtility.php:52
‪TYPO3\CMS\Core\Page\PageRenderer\setHtmlTag
‪setHtmlTag($htmlTag)
Definition: PageRenderer.php:363
‪TYPO3\CMS\Core\Page\PageRenderer\renderResponse
‪renderResponse(int $code=200, string $reasonPhrase='',)
Definition: PageRenderer.php:1222
‪TYPO3\CMS\Core\Page\PageRenderer\executePreRenderHook
‪executePreRenderHook()
Definition: PageRenderer.php:2105
‪TYPO3\CMS\Core\Page\PageRenderer\setBodyContent
‪setBodyContent($content)
Definition: PageRenderer.php:413
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:46
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static dirname(string $path)
Definition: PathUtility.php:243
‪TYPO3\CMS\Core\Page\PageRenderer\getCompressCss
‪bool getCompressCss()
Definition: PageRenderer.php:625
‪TYPO3\CMS\Core\Page\PageRenderer\getApplicationType
‪getApplicationType()
Definition: PageRenderer.php:2266
‪TYPO3\CMS\Core\Page\PageRenderer\doCompressJavaScript
‪doCompressJavaScript()
Definition: PageRenderer.php:1999
‪TYPO3\CMS\Core\Page\PageRenderer\addJsFooterLibrary
‪addJsFooterLibrary($name, $file, $type='', $compress=false, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $async=false, $integrity='', $defer=false, $crossorigin='', $nomodule=false, array $tagAttributes=[])
Definition: PageRenderer.php:844
‪TYPO3\CMS\Core\Utility\PathUtility\getPublicResourceWebPath
‪static getPublicResourceWebPath(string $resourcePath, bool $prefixWithSitePath=true)
Definition: PathUtility.php:97
‪TYPO3\CMS\Core\Page\PageRenderer\$concatenateJavascript
‪bool $concatenateJavascript
Definition: PageRenderer.php:62
‪TYPO3\CMS\Core\Page\PageRenderer\getTitle
‪string getTitle()
Definition: PageRenderer.php:520
‪TYPO3\CMS\Core\Page\PageRenderer\setNonce
‪setNonce(?ConsumableNonce $nonce)
Definition: PageRenderer.php:533
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Core\Page\PageRenderer\setLanguage
‪setLanguage(Locale $locale)
Definition: PageRenderer.php:335
‪TYPO3\CMS\Core\Page\PageRenderer\updateState
‪array< string, $jsFiles=array();protected array $jsFooterFiles=array();protected array $jsLibs=array();protected array $jsFooterLibs=array();protected array< string, $cssFiles=array();protected array< string, $cssLibs=array();protected string $title;protected string $favIcon;protected string $xmlPrologAndDocType='';protected array $inlineComments=array();protected array $headerData=array();protected array $footerData=array();protected string $titleTag='< title >|</title >';protected string $htmlTag='< html >';protected string $headTag='< head >';protected string $iconMimeType='';protected string $shortcutTag='< link rel="icon" href="%1$s"%2 $s/>';protected array< string, $jsInline=array();protected array $jsFooterInline=array();protected array< string, $cssInline=array();protected string $bodyContent;protected string $templateFile;protected array $inlineLanguageLabels=array();protected array $inlineLanguageLabelFiles=array();protected array $inlineSettings=array();protected string $endingSlash='';protected JavaScriptRenderer $javaScriptRenderer;protected ?ConsumableNonce $nonce=null;protected DocType $docType=DocType::html5;protected bool $applyNonceHint=false;public __construct(protected readonly FrontendInterface $assetsCache, protected readonly MarkerBasedTemplateService $templateService, protected readonly MetaTagManagerRegistry $metaTagRegistry, protected readonly AssetRenderer $assetRenderer, protected readonly ResourceCompressor $resourceCompressor, protected readonly RelativeCssPathFixer $relativeCssPathFixer, protected readonly LanguageServiceFactory $languageServiceFactory, protected readonly ResponseFactoryInterface $responseFactory, protected readonly StreamFactoryInterface $streamFactory,) { $this->reset();$this->setMetaTag( 'name', 'generator', 'TYPO3 CMS');} public function updateState(array $state):void { foreach( $state as $var=> $value) { switch( $var) { case 'assetsCache':case 'assetRenderer':case 'templateService':case 'resourceCompressor':case 'relativeCssPathFixer':case 'languageServiceFactory':case 'responseFactory':case 'streamFactory':break;case 'nonce':$this->setNonce(new ConsumableNonce( $value));break;case 'metaTagRegistry':$this->metaTagRegistry-> updateState($value)
‪TYPO3\CMS\Core\Page\PageRenderer\PART_FOOTER
‪const PART_FOOTER
Definition: PageRenderer.php:50
‪TYPO3\CMS\Core\Page\PageRenderer\addInlineLanguageLabelArray
‪addInlineLanguageLabelArray(array $array)
Definition: PageRenderer.php:1114
‪TYPO3\CMS\Core\Page\PageRenderer\setTitle
‪setTitle($title)
Definition: PageRenderer.php:317
‪TYPO3\CMS\Core\Page\PageRenderer\getInlineLanguageLabels
‪array getInlineLanguageLabels()
Definition: PageRenderer.php:665
‪TYPO3\CMS\Core\Page\PageRenderer\$compressCss
‪bool $compressCss
Definition: PageRenderer.php:58
‪TYPO3\CMS\Core\Page\PageRenderer\getStreamlinedFileName
‪string getStreamlinedFileName($file, $prepareForOutput=true)
Definition: PageRenderer.php:2065
‪TYPO3\CMS\Core\Page\PageRenderer\addCssFile
‪addCssFile($file, $rel='stylesheet', $media='all', $title='', $compress=true, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $inline=false, array $tagAttributes=[])
Definition: PageRenderer.php:1011
‪TYPO3\CMS\Core\Page\PageRenderer\createInlineCssTagFromFile
‪createInlineCssTagFromFile(string $file, array $properties)
Definition: PageRenderer.php:2208
‪TYPO3\CMS\Core\Page\PageRenderer\addInlineComment
‪addInlineComment($comment)
Definition: PageRenderer.php:752
‪TYPO3\CMS\Core\Page\PageRenderer\loadJavaScriptModule
‪loadJavaScriptModule(string $specifier)
Definition: PageRenderer.php:1090
‪TYPO3\CMS\Core\Page\PageRenderer\doConcatenateJavaScript
‪doConcatenateJavaScript()
Definition: PageRenderer.php:1909
‪TYPO3\CMS\Core\Page\PageRenderer\render
‪string render()
Definition: PageRenderer.php:1209
‪TYPO3\CMS\Core\Page\PageRenderer\executePostRenderHook
‪executePostRenderHook(&$jsLibs, &$jsFiles, &$jsFooterFiles, &$cssLibs, &$cssFiles, &$jsInline, &$cssInline, &$jsFooterInline, &$jsFooterLibs)
Definition: PageRenderer.php:2169
‪TYPO3\CMS\Core\Page\PageRenderer\enableMoveJsFromHeaderToFooter
‪enableMoveJsFromHeaderToFooter()
Definition: PageRenderer.php:432
‪TYPO3\CMS\Core\Page\PageRenderer\processJsFile
‪string processJsFile($filename)
Definition: PageRenderer.php:2040
‪TYPO3\CMS\Core\Page\PageRenderer\getPreparedMarkerArray
‪array getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags)
Definition: PageRenderer.php:1380
‪TYPO3\CMS\Core\Page\PageRenderer\setIconMimeType
‪setIconMimeType($iconMimeType)
Definition: PageRenderer.php:393
‪TYPO3\CMS\Core\Page\PageRenderer\wrapInlineStyle
‪wrapInlineStyle(string $content, array $attributes=[])
Definition: PageRenderer.php:2233
‪TYPO3\CMS\Core\Page\PageRenderer\addJsFile
‪addJsFile($file, $type='', $compress=true, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $async=false, $integrity='', $defer=false, $crossorigin='', $nomodule=false, array $tagAttributes=[])
Definition: PageRenderer.php:887
‪TYPO3\CMS\Core\Page\PageRenderer\addHeaderData
‪addHeaderData($data)
Definition: PageRenderer.php:764
‪TYPO3\CMS\Core\Page\PageRenderer\createCssTag
‪createCssTag(array $properties, string $file)
Definition: PageRenderer.php:1623
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Page\PageRenderer\renderMetaTagsFromAPI
‪array renderMetaTagsFromAPI()
Definition: PageRenderer.php:1237
‪TYPO3\CMS\Core\Page\PageRenderer\addJsFooterFile
‪addJsFooterFile($file, $type='', $compress=true, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $async=false, $integrity='', $defer=false, $crossorigin='', $nomodule=false, array $tagAttributes=[])
Definition: PageRenderer.php:929
‪TYPO3\CMS\Core\Page\PageRenderer\includeLanguageFileForInline
‪includeLanguageFileForInline($fileRef, $selectionPrefix='', $stripFromSelectionName='')
Definition: PageRenderer.php:1862
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Page\PageRenderer\getHeadTag
‪string getHeadTag()
Definition: PageRenderer.php:565
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Page\PageRenderer\setDocType
‪setDocType(DocType $docType)
Definition: PageRenderer.php:538
‪TYPO3\CMS\Core\Page\PageRenderer\enableCompressCss
‪enableCompressCss()
Definition: PageRenderer.php:464
‪TYPO3\CMS\Core\Page\PageRenderer\doConcatenateCss
‪doConcatenateCss()
Definition: PageRenderer.php:1937
‪TYPO3\CMS\Core\Localization\Locale
Definition: Locale.php:30
‪TYPO3\CMS\Core\Page\PageRenderer\addFooterData
‪addFooterData($data)
Definition: PageRenderer.php:776
‪TYPO3\CMS\Core\Page\PageRenderer\addInlineSetting
‪addInlineSetting($namespace, $key, $value)
Definition: PageRenderer.php:1146
‪TYPO3\CMS\Core\Page\PageRenderer\removeMetaTag
‪removeMetaTag(string $type, string $name)
Definition: PageRenderer.php:737
‪TYPO3\CMS\Core\Page\PageRenderer\executeRenderPostTransformHook
‪executeRenderPostTransformHook()
Definition: PageRenderer.php:2132
‪TYPO3\CMS\Core\Page\AssetRenderer
Definition: AssetRenderer.php:31
‪TYPO3\CMS\Core\Page\PageRenderer\prepareRendering
‪prepareRendering()
Definition: PageRenderer.php:1307
‪TYPO3\CMS\Core\Page\PageRenderer\getDocType
‪getDocType()
Definition: PageRenderer.php:545
‪TYPO3\CMS\Core\Type\DocType
‪DocType
Definition: DocType.php:27
‪TYPO3\CMS\Core\Http\fromRequest
‪@ fromRequest
Definition: ApplicationType.php:67
‪TYPO3\CMS\Core\Page\PageRenderer\disableCompressCss
‪disableCompressCss()
Definition: PageRenderer.php:472
‪TYPO3\CMS\Core\Page\PageRenderer\setTemplateFile
‪setTemplateFile($file)
Definition: PageRenderer.php:403
‪TYPO3\CMS\Core\Page\PageRenderer\addBodyContent
‪addBodyContent($content)
Definition: PageRenderer.php:1194
‪TYPO3\CMS\Core\Service\MarkerBasedTemplateService
Definition: MarkerBasedTemplateService.php:27
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Page\PageRenderer\getCompressJavascript
‪bool getCompressJavascript()
Definition: PageRenderer.php:615
‪TYPO3\CMS\Core\Page\PageRenderer\setMetaTag
‪setMetaTag(string $type, string $name, string $content, array $subProperties=[], $replace=true)
Definition: PageRenderer.php:697
‪TYPO3\CMS\Core\Page\PageRenderer\disableConcatenateCss
‪disableConcatenateCss()
Definition: PageRenderer.php:504
‪TYPO3\CMS\Backend\Routing\Router
Definition: Router.php:39
‪TYPO3\CMS\Core\Page\PageRenderer\addAjaxUrlsToInlineSettings
‪addAjaxUrlsToInlineSettings(bool $publicRoutesOnly=false)
Definition: PageRenderer.php:1550
‪TYPO3\CMS\Core\Page\PageRenderer\renderInlineJavaScript
‪array string[] renderInlineJavaScript()
Definition: PageRenderer.php:1814
‪TYPO3\CMS\Core\Page\PageRenderer\PART_HEADER
‪const PART_HEADER
Definition: PageRenderer.php:49
‪TYPO3\CMS\Core\Page\PageRenderer\getMetaTag
‪getMetaTag(string $type, string $name)
Definition: PageRenderer.php:715
‪TYPO3\CMS\Core\Page\PageRenderer\reset
‪reset()
Definition: PageRenderer.php:286
‪TYPO3\CMS\Core\Page\PageRenderer\addCssLibrary
‪addCssLibrary($file, $rel='stylesheet', $media='all', $title='', $compress=true, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $inline=false, array $tagAttributes=[])
Definition: PageRenderer.php:1045
‪TYPO3\CMS\Core\Page\PageRenderer\parseLanguageLabelsForJavaScript
‪parseLanguageLabelsForJavaScript()
Definition: PageRenderer.php:1517
‪TYPO3\CMS\Core\Page\PageRenderer\getMoveJsFromHeaderToFooter
‪bool getMoveJsFromHeaderToFooter()
Definition: PageRenderer.php:605
‪TYPO3\CMS\Core\Page\PageRenderer\getConcatenateJavascript
‪bool getConcatenateJavascript()
Definition: PageRenderer.php:635
‪TYPO3\CMS\Core\Page\PageRenderer\$locale
‪Locale $locale
Definition: PageRenderer.php:75
‪TYPO3\CMS\Core\Http\ApplicationType
‪ApplicationType
Definition: ApplicationType.php:56
‪TYPO3\CMS\Core\Resource\RelativeCssPathFixer
Definition: RelativeCssPathFixer.php:29
‪TYPO3\CMS\Core\Page\PageRenderer\getLanguage
‪getLanguage()
Definition: PageRenderer.php:528
‪TYPO3\CMS\Core\Page\PageRenderer\wrapInlineScript
‪wrapInlineScript(string $content, array $attributes=[])
Definition: PageRenderer.php:2243
‪TYPO3\CMS\Core\Page\PageRenderer\$moveJsFromHeaderToFooter
‪bool $moveJsFromHeaderToFooter
Definition: PageRenderer.php:70