TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
PageRenderer.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Page;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
28 
34 {
35  // Constants for the part to be rendered
36  const PART_COMPLETE = 0;
37  const PART_HEADER = 1;
38  const PART_FOOTER = 2;
39  // jQuery Core version that is shipped with TYPO3
40  const JQUERY_VERSION_LATEST = '3.1.1';
41  // jQuery namespace options
42  const JQUERY_NAMESPACE_NONE = 'none';
43  const JQUERY_NAMESPACE_DEFAULT = 'jQuery';
44  const JQUERY_NAMESPACE_DEFAULT_NOCONFLICT = 'defaultNoConflict';
45 
49  protected $compressJavascript = false;
50 
54  protected $compressCss = false;
55 
59  protected $removeLineBreaksFromTemplate = false;
60 
64  protected $concatenateFiles = false;
65 
69  protected $concatenateJavascript = false;
70 
74  protected $concatenateCss = false;
75 
79  protected $moveJsFromHeaderToFooter = false;
80 
84  protected $csConvObj;
85 
89  protected $locales;
90 
97  protected $lang;
98 
105  protected $languageDependencies = [];
106 
110  protected $compressor;
111 
112  // Arrays containing associative array for the included files
116  protected $jsFiles = [];
117 
121  protected $jsFooterFiles = [];
122 
126  protected $jsLibs = [];
127 
131  protected $jsFooterLibs = [];
132 
136  protected $cssFiles = [];
137 
141  protected $cssLibs = [];
142 
148  protected $title;
149 
155  protected $charSet;
156 
160  protected $favIcon;
161 
165  protected $baseUrl;
166 
170  protected $renderXhtml = true;
171 
172  // Static header blocks
176  protected $xmlPrologAndDocType = '';
177 
181  protected $metaTags = [];
182 
186  protected $inlineComments = [];
187 
191  protected $headerData = [];
192 
196  protected $footerData = [];
197 
201  protected $titleTag = '<title>|</title>';
202 
206  protected $metaCharsetTag = '<meta http-equiv="Content-Type" content="text/html; charset=|" />';
207 
211  protected $htmlTag = '<html>';
212 
216  protected $headTag = '<head>';
217 
221  protected $baseUrlTag = '<base href="|" />';
222 
226  protected $iconMimeType = '';
227 
231  protected $shortcutTag = '<link rel="shortcut icon" href="%1$s"%2$s />';
232 
233  // Static inline code blocks
237  protected $jsInline = [];
238 
242  protected $jsFooterInline = [];
243 
247  protected $extOnReadyCode = [];
248 
252  protected $cssInline = [];
253 
257  protected $bodyContent;
258 
262  protected $templateFile;
263 
267  protected $jsLibraryNames = ['extjs'];
268 
269  // Paths to contributed libraries
270 
275  protected $requireJsPath = 'EXT:core/Resources/Public/JavaScript/Contrib/';
276 
280  protected $extJsPath = 'EXT:core/Resources/Public/JavaScript/Contrib/extjs/';
281 
287  protected $jQueryPath = 'EXT:core/Resources/Public/JavaScript/Contrib/jquery/';
288 
289  // Internal flags for JS-libraries
307  protected $jQueryVersions = [];
308 
315  self::JQUERY_VERSION_LATEST
316  ];
317 
323  protected $jQueryCdnUrls = [
324  'google' => 'https://ajax.googleapis.com/ajax/libs/jquery/%1$s/jquery%2$s.js',
325  'msn' => 'https://ajax.aspnetcdn.com/ajax/jQuery/jquery-%1$s%2$s.js',
326  'jquery' => 'https://code.jquery.com/jquery-%1$s%2$s.js',
327  'cloudflare' => 'https://cdnjs.cloudflare.com/ajax/libs/jquery/%1$s/jquery%2$s.js'
328  ];
329 
334  protected $addRequireJs = false;
335 
340  protected $requireJsConfig = [];
341 
345  protected $addExtJS = false;
346 
350  protected $extDirectCodeAdded = false;
351 
355  protected $enableExtJsDebug = false;
356 
360  protected $enableJqueryDebug = false;
361 
365  protected $extJStheme = true;
366 
370  protected $extJScss = true;
371 
375  protected $inlineLanguageLabels = [];
376 
381 
385  protected $inlineSettings = [];
386 
390  protected $inlineJavascriptWrap = [];
391 
395  protected $inlineCssWrap = [];
396 
402  protected $compressError = '';
403 
409  protected $endingSlash = '';
410 
414  public function __construct($templateFile = '')
415  {
416  $this->reset();
417  $this->csConvObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Charset\CharsetConverter::class);
418  $this->locales = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\Locales::class);
419  if ($templateFile !== '') {
420  $this->templateFile = $templateFile;
421  }
422  $this->inlineJavascriptWrap = [
423  '<script type="text/javascript">' . LF . '/*<![CDATA[*/' . LF,
424  '/*]]>*/' . LF . '</script>' . LF
425  ];
426  $this->inlineCssWrap = [
427  '<style type="text/css">' . LF . '/*<![CDATA[*/' . LF . '<!-- ' . LF,
428  '-->' . LF . '/*]]>*/' . LF . '</style>' . LF
429  ];
430  }
431 
437  protected function reset()
438  {
439  $this->templateFile = 'EXT:core/Resources/Private/Templates/PageRenderer.html';
440  $this->jsFiles = [];
441  $this->jsFooterFiles = [];
442  $this->jsInline = [];
443  $this->jsFooterInline = [];
444  $this->jsLibs = [];
445  $this->cssFiles = [];
446  $this->cssInline = [];
447  $this->metaTags = [];
448  $this->inlineComments = [];
449  $this->headerData = [];
450  $this->footerData = [];
451  $this->extOnReadyCode = [];
452  $this->jQueryVersions = [];
453  }
454 
455  /*****************************************************/
456  /* */
457  /* Public Setters */
458  /* */
459  /* */
460  /*****************************************************/
467  public function setTitle($title)
468  {
469  $this->title = $title;
470  }
471 
478  public function setRenderXhtml($enable)
479  {
480  $this->renderXhtml = $enable;
481  }
482 
490  {
491  $this->xmlPrologAndDocType = $xmlPrologAndDocType;
492  }
493 
500  public function setCharSet($charSet)
501  {
502  $this->charSet = $charSet;
503  }
504 
511  public function setLanguage($lang)
512  {
513  $this->lang = $lang;
514  $this->languageDependencies = [];
515 
516  // Language is found. Configure it:
517  if (in_array($this->lang, $this->locales->getLocales())) {
518  $this->languageDependencies[] = $this->lang;
519  foreach ($this->locales->getLocaleDependencies($this->lang) as $language) {
520  $this->languageDependencies[] = $language;
521  }
522  }
523  }
524 
532  {
533  $this->metaCharsetTag = $metaCharsetTag;
534  }
535 
542  public function setHtmlTag($htmlTag)
543  {
544  $this->htmlTag = $htmlTag;
545  }
546 
553  public function setHeadTag($headTag)
554  {
555  $this->headTag = $headTag;
556  }
557 
564  public function setFavIcon($favIcon)
565  {
566  $this->favIcon = $favIcon;
567  }
568 
576  {
577  $this->iconMimeType = $iconMimeType;
578  }
579 
586  public function setBaseUrl($baseUrl)
587  {
588  $this->baseUrl = $baseUrl;
589  }
590 
597  public function setTemplateFile($file)
598  {
599  $this->templateFile = $file;
600  }
601 
608  public function setBodyContent($content)
609  {
610  $this->bodyContent = $content;
611  }
612 
619  public function setRequireJsPath($path)
620  {
621  $this->requireJsPath = $path;
622  }
623 
630  public function setExtJsPath($path)
631  {
632  $this->extJsPath = $path;
633  }
634 
635  /*****************************************************/
636  /* */
637  /* Public Enablers / Disablers */
638  /* */
639  /* */
640  /*****************************************************/
647  {
648  $this->moveJsFromHeaderToFooter = true;
649  }
650 
657  {
658  $this->moveJsFromHeaderToFooter = false;
659  }
660 
666  public function enableCompressJavascript()
667  {
668  $this->compressJavascript = true;
669  }
670 
676  public function disableCompressJavascript()
677  {
678  $this->compressJavascript = false;
679  }
680 
686  public function enableCompressCss()
687  {
688  $this->compressCss = true;
689  }
690 
696  public function disableCompressCss()
697  {
698  $this->compressCss = false;
699  }
700 
706  public function enableConcatenateFiles()
707  {
708  $this->concatenateFiles = true;
709  }
710 
716  public function disableConcatenateFiles()
717  {
718  $this->concatenateFiles = false;
719  }
720 
726  public function enableConcatenateJavascript()
727  {
728  $this->concatenateJavascript = true;
729  }
730 
737  {
738  $this->concatenateJavascript = false;
739  }
740 
746  public function enableConcatenateCss()
747  {
748  $this->concatenateCss = true;
749  }
750 
756  public function disableConcatenateCss()
757  {
758  $this->concatenateCss = false;
759  }
760 
767  {
768  $this->removeLineBreaksFromTemplate = true;
769  }
770 
777  {
778  $this->removeLineBreaksFromTemplate = false;
779  }
780 
787  public function enableDebugMode()
788  {
789  $this->compressJavascript = false;
790  $this->compressCss = false;
791  $this->concatenateFiles = false;
792  $this->removeLineBreaksFromTemplate = false;
793  $this->enableExtJsDebug = true;
794  $this->enableJqueryDebug = true;
795  }
796 
797  /*****************************************************/
798  /* */
799  /* Public Getters */
800  /* */
801  /* */
802  /*****************************************************/
808  public function getTitle()
809  {
810  return $this->title;
811  }
812 
818  public function getCharSet()
819  {
820  return $this->charSet;
821  }
822 
828  public function getLanguage()
829  {
830  return $this->lang;
831  }
832 
838  public function getRenderXhtml()
839  {
840  return $this->renderXhtml;
841  }
842 
848  public function getHtmlTag()
849  {
850  return $this->htmlTag;
851  }
852 
858  public function getMetaCharsetTag()
859  {
860  return $this->metaCharsetTag;
861  }
862 
868  public function getHeadTag()
869  {
870  return $this->headTag;
871  }
872 
878  public function getFavIcon()
879  {
880  return $this->favIcon;
881  }
882 
888  public function getIconMimeType()
889  {
890  return $this->iconMimeType;
891  }
892 
898  public function getBaseUrl()
899  {
900  return $this->baseUrl;
901  }
902 
908  public function getTemplateFile()
909  {
910  return $this->templateFile;
911  }
912 
918  public function getMoveJsFromHeaderToFooter()
919  {
921  }
922 
928  public function getCompressJavascript()
929  {
931  }
932 
938  public function getCompressCss()
939  {
940  return $this->compressCss;
941  }
942 
948  public function getConcatenateFiles()
949  {
951  }
952 
958  public function getConcatenateJavascript()
959  {
961  }
962 
968  public function getConcatenateCss()
969  {
970  return $this->concatenateCss;
971  }
972 
979  {
981  }
982 
988  public function getBodyContent()
989  {
990  return $this->bodyContent;
991  }
992 
998  public function getExtJsPath()
999  {
1000  return $this->extJsPath;
1001  }
1002 
1008  public function getInlineLanguageLabels()
1009  {
1011  }
1012 
1019  {
1021  }
1022 
1023  /*****************************************************/
1024  /* */
1025  /* Public Functions to add Data */
1026  /* */
1027  /* */
1028  /*****************************************************/
1035  public function addMetaTag($meta)
1036  {
1037  if (!in_array($meta, $this->metaTags)) {
1038  $this->metaTags[] = $meta;
1039  }
1040  }
1041 
1048  public function addInlineComment($comment)
1049  {
1050  if (!in_array($comment, $this->inlineComments)) {
1051  $this->inlineComments[] = $comment;
1052  }
1053  }
1054 
1061  public function addHeaderData($data)
1062  {
1063  if (!in_array($data, $this->headerData)) {
1064  $this->headerData[] = $data;
1065  }
1066  }
1067 
1074  public function addFooterData($data)
1075  {
1076  if (!in_array($data, $this->footerData)) {
1077  $this->footerData[] = $data;
1078  }
1079  }
1080 
1096  public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1097  {
1098  if (!$type) {
1099  $type = 'text/javascript';
1100  }
1101  if (!in_array(strtolower($name), $this->jsLibs)) {
1102  $this->jsLibs[strtolower($name)] = [
1103  'file' => $file,
1104  'type' => $type,
1105  'section' => self::PART_HEADER,
1106  'compress' => $compress,
1107  'forceOnTop' => $forceOnTop,
1108  'allWrap' => $allWrap,
1109  'excludeFromConcatenation' => $excludeFromConcatenation,
1110  'splitChar' => $splitChar,
1111  'async' => $async,
1112  'integrity' => $integrity,
1113  ];
1114  }
1115  }
1116 
1132  public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1133  {
1134  if (!$type) {
1135  $type = 'text/javascript';
1136  }
1137  if (!in_array(strtolower($name), $this->jsLibs)) {
1138  $this->jsLibs[strtolower($name)] = [
1139  'file' => $file,
1140  'type' => $type,
1141  'section' => self::PART_FOOTER,
1142  'compress' => $compress,
1143  'forceOnTop' => $forceOnTop,
1144  'allWrap' => $allWrap,
1145  'excludeFromConcatenation' => $excludeFromConcatenation,
1146  'splitChar' => $splitChar,
1147  'async' => $async,
1148  'integrity' => $integrity,
1149  ];
1150  }
1151  }
1152 
1167  public function addJsFile($file, $type = 'text/javascript', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1168  {
1169  if (!$type) {
1170  $type = 'text/javascript';
1171  }
1172  if (!isset($this->jsFiles[$file])) {
1173  $this->jsFiles[$file] = [
1174  'file' => $file,
1175  'type' => $type,
1176  'section' => self::PART_HEADER,
1177  'compress' => $compress,
1178  'forceOnTop' => $forceOnTop,
1179  'allWrap' => $allWrap,
1180  'excludeFromConcatenation' => $excludeFromConcatenation,
1181  'splitChar' => $splitChar,
1182  'async' => $async,
1183  'integrity' => $integrity,
1184  ];
1185  }
1186  }
1187 
1202  public function addJsFooterFile($file, $type = 'text/javascript', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1203  {
1204  if (!$type) {
1205  $type = 'text/javascript';
1206  }
1207  if (!isset($this->jsFiles[$file])) {
1208  $this->jsFiles[$file] = [
1209  'file' => $file,
1210  'type' => $type,
1211  'section' => self::PART_FOOTER,
1212  'compress' => $compress,
1213  'forceOnTop' => $forceOnTop,
1214  'allWrap' => $allWrap,
1215  'excludeFromConcatenation' => $excludeFromConcatenation,
1216  'splitChar' => $splitChar,
1217  'async' => $async,
1218  'integrity' => $integrity,
1219  ];
1220  }
1221  }
1222 
1232  public function addJsInlineCode($name, $block, $compress = true, $forceOnTop = false)
1233  {
1234  if (!isset($this->jsInline[$name]) && !empty($block)) {
1235  $this->jsInline[$name] = [
1236  'code' => $block . LF,
1237  'section' => self::PART_HEADER,
1238  'compress' => $compress,
1239  'forceOnTop' => $forceOnTop
1240  ];
1241  }
1242  }
1243 
1253  public function addJsFooterInlineCode($name, $block, $compress = true, $forceOnTop = false)
1254  {
1255  if (!isset($this->jsInline[$name]) && !empty($block)) {
1256  $this->jsInline[$name] = [
1257  'code' => $block . LF,
1258  'section' => self::PART_FOOTER,
1259  'compress' => $compress,
1260  'forceOnTop' => $forceOnTop
1261  ];
1262  }
1263  }
1264 
1272  public function addExtOnReadyCode($block, $forceOnTop = false)
1273  {
1274  if (!in_array($block, $this->extOnReadyCode)) {
1275  if ($forceOnTop) {
1276  array_unshift($this->extOnReadyCode, $block);
1277  } else {
1278  $this->extOnReadyCode[] = $block;
1279  }
1280  }
1281  }
1282 
1289  public function addExtDirectCode(array $filterNamespaces = [])
1290  {
1291  if ($this->extDirectCodeAdded) {
1292  return;
1293  }
1294  $this->extDirectCodeAdded = true;
1295  if (empty($filterNamespaces)) {
1296  $filterNamespaces = ['TYPO3'];
1297  }
1298 
1299  // Add language labels for ExtDirect
1301  'extDirect_timeoutHeader' => 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:extDirect_timeoutHeader',
1302  'extDirect_timeoutMessage' => 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:extDirect_timeoutMessage'
1303  ], true);
1304 
1305  $token = ($api = '');
1306  if (TYPO3_MODE === 'BE') {
1308  $token = $formprotection->generateToken('extDirect');
1309 
1310  // Debugger Console strings
1311  $this->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/debugger.xlf');
1312 
1313  $this->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/wizard.xlf');
1314  }
1316  $extDirect = GeneralUtility::makeInstance(\TYPO3\CMS\Core\ExtDirect\ExtDirectApi::class);
1317  $api = $extDirect->getApiPhp($filterNamespaces);
1318  if ($api) {
1319  $this->addJsInlineCode('TYPO3ExtDirectAPI', $api, false);
1320  }
1321  // Note: we need to iterate thru the object, because the addProvider method
1322  // does this only with multiple arguments
1323  $this->addExtOnReadyCode('
1324  (function() {
1325  TYPO3.ExtDirectToken = "' . $token . '";
1326  for (var api in Ext.app.ExtDirectAPI) {
1327  var provider = Ext.Direct.addProvider(Ext.app.ExtDirectAPI[api]);
1328  provider.on("beforecall", function(provider, transaction, meta) {
1329  if (transaction.data) {
1330  transaction.data[transaction.data.length] = TYPO3.ExtDirectToken;
1331  } else {
1332  transaction.data = [TYPO3.ExtDirectToken];
1333  }
1334  });
1335 
1336  provider.on("call", function(provider, transaction, meta) {
1337  if (transaction.isForm) {
1338  transaction.params.securityToken = TYPO3.ExtDirectToken;
1339  }
1340  });
1341  }
1342  })();
1343 
1344  var extDirectDebug = function(message, header, group) {
1345  var DebugConsole = null;
1346 
1347  if (top && top.TYPO3 && typeof top.TYPO3.DebugConsole === "object") {
1348  DebugConsole = top.TYPO3.DebugConsole;
1349  } else if (typeof TYPO3 === "object" && typeof TYPO3.DebugConsole === "object") {
1350  DebugConsole = TYPO3.DebugConsole;
1351  }
1352 
1353  if (DebugConsole !== null) {
1354  DebugConsole.add(message, header, group);
1355  } else if (typeof console === "object") {
1356  console.log(message);
1357  } else {
1358  document.write(message);
1359  }
1360  };
1361 
1362  Ext.Direct.on("exception", function(event) {
1363  if (event.code === Ext.Direct.exceptions.TRANSPORT && !event.where) {
1364  top.TYPO3.Notification.error(
1365  TYPO3.l10n.localize("extDirect_timeoutHeader"),
1366  TYPO3.l10n.localize("extDirect_timeoutMessage")
1367  );
1368  } else {
1369  var backtrace = "";
1370  if (event.code === "parse") {
1371  extDirectDebug(
1372  "<p>" + event.xhr.responseText + "<\\/p>",
1373  event.type,
1374  "ExtDirect - Exception"
1375  );
1376  } else if (event.code === "router") {
1377  top.TYPO3.Notification.error(
1378  event.code,
1379  event.message
1380  );
1381  } else if (event.where) {
1382  backtrace = "<p style=\\"margin-top: 20px;\\">" +
1383  "<strong>Backtrace:<\\/strong><br \\/>" +
1384  event.where.replace(/#/g, "<br \\/>#") +
1385  "<\\/p>";
1386  extDirectDebug(
1387  "<p>" + event.message + "<\\/p>" + backtrace,
1388  event.method,
1389  "ExtDirect - Exception"
1390  );
1391  }
1392 
1393 
1394  }
1395  });
1396 
1397  Ext.Direct.on("event", function(event, provider) {
1398  if (typeof event.debug !== "undefined" && event.debug !== "") {
1399  extDirectDebug(event.debug, event.method, "ExtDirect - Debug");
1400  }
1401  });
1402  ', true);
1403  }
1404 
1419  public function addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|')
1420  {
1421  if (!isset($this->cssFiles[$file])) {
1422  $this->cssFiles[$file] = [
1423  'file' => $file,
1424  'rel' => $rel,
1425  'media' => $media,
1426  'title' => $title,
1427  'compress' => $compress,
1428  'forceOnTop' => $forceOnTop,
1429  'allWrap' => $allWrap,
1430  'excludeFromConcatenation' => $excludeFromConcatenation,
1431  'splitChar' => $splitChar
1432  ];
1433  }
1434  }
1435 
1450  public function addCssLibrary($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|')
1451  {
1452  if (!isset($this->cssLibs[$file])) {
1453  $this->cssLibs[$file] = [
1454  'file' => $file,
1455  'rel' => $rel,
1456  'media' => $media,
1457  'title' => $title,
1458  'compress' => $compress,
1459  'forceOnTop' => $forceOnTop,
1460  'allWrap' => $allWrap,
1461  'excludeFromConcatenation' => $excludeFromConcatenation,
1462  'splitChar' => $splitChar
1463  ];
1464  }
1465  }
1466 
1476  public function addCssInlineBlock($name, $block, $compress = false, $forceOnTop = false)
1477  {
1478  if (!isset($this->cssInline[$name]) && !empty($block)) {
1479  $this->cssInline[$name] = [
1480  'code' => $block,
1481  'compress' => $compress,
1482  'forceOnTop' => $forceOnTop
1483  ];
1484  }
1485  }
1486 
1496  public function loadJquery($version = null, $source = null, $namespace = self::JQUERY_NAMESPACE_DEFAULT)
1497  {
1498  // Set it to the version that is shipped with the TYPO3 core
1499  if ($version === null || $version === 'latest') {
1500  $version = self::JQUERY_VERSION_LATEST;
1501  }
1502  // Check if the source is set, otherwise set it to "default"
1503  if ($source === null) {
1504  $source = 'local';
1505  }
1506  if ($source === 'local' && !in_array($version, $this->availableLocalJqueryVersions)) {
1507  throw new \UnexpectedValueException('The requested jQuery version is not available in the local filesystem.', 1341505305);
1508  }
1509  if (!preg_match('/^[a-zA-Z0-9]+$/', $namespace)) {
1510  throw new \UnexpectedValueException('The requested namespace contains non alphanumeric characters.', 1341571604);
1511  }
1512  $this->jQueryVersions[$namespace] = [
1513  'version' => $version,
1514  'source' => $source
1515  ];
1516  }
1517 
1526  public function loadRequireJs()
1527  {
1528  if (!empty($this->requireJsConfig)) {
1529  return;
1530  }
1531  $this->addRequireJs = true;
1532 
1534  $isDevelopment = GeneralUtility::getApplicationContext()->isDevelopment();
1535  $cacheIdentifier = 'requireJS_' . md5(implode(',', $loadedExtensions) . ($isDevelopment ? ':dev' : ''));
1537  $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('assets');
1538  $this->requireJsConfig = $cache->get($cacheIdentifier);
1539 
1540  // if we did not get a configuration from the cache, compute and store it in the cache
1541  if (empty($this->requireJsConfig)) {
1542  $this->requireJsConfig = $this->computeRequireJsConfig($isDevelopment, $loadedExtensions);
1543  $cache->set($cacheIdentifier, $this->requireJsConfig);
1544  }
1545  }
1546 
1555  protected function computeRequireJsConfig($isDevelopment, array $loadedExtensions)
1556  {
1557  // load all paths to map to package names / namespaces
1558  $requireJsConfig = [];
1559 
1560  // In order to avoid browser caching of JS files, adding a GET parameter to the files loaded via requireJS
1561  if ($isDevelopment) {
1562  $requireJsConfig['urlArgs'] = 'bust=' . $GLOBALS['EXEC_TIME'];
1563  } else {
1564  $requireJsConfig['urlArgs'] = 'bust=' . GeneralUtility::hmac(TYPO3_version . PATH_site);
1565  }
1566  $corePath = ExtensionManagementUtility::extPath('core', 'Resources/Public/JavaScript/Contrib/');
1567  $corePath = PathUtility::getAbsoluteWebPath($corePath);
1568  // first, load all paths for the namespaces, and configure contrib libs.
1569  $requireJsConfig['paths'] = [
1570  'jquery-ui' => $corePath . 'jquery-ui',
1571  'datatables' => $corePath . 'jquery.dataTables',
1572  'matchheight' => $corePath . 'jquery.matchHeight-min',
1573  'nprogress' => $corePath . 'nprogress',
1574  'moment' => $corePath . 'moment',
1575  'cropper' => $corePath . 'cropper.min',
1576  'imagesloaded' => $corePath . 'imagesloaded.pkgd.min',
1577  'bootstrap' => $corePath . 'bootstrap/bootstrap',
1578  'twbs/bootstrap-datetimepicker' => $corePath . 'bootstrap-datetimepicker',
1579  'autosize' => $corePath . 'autosize',
1580  'taboverride' => $corePath . 'taboverride.min',
1581  'twbs/bootstrap-slider' => $corePath . 'bootstrap-slider.min',
1582  'jquery/autocomplete' => $corePath . 'jquery.autocomplete',
1583  'd3' => $corePath . 'd3/d3'
1584  ];
1585 
1586  foreach ($loadedExtensions as $packageName) {
1587  $fullJsPath = 'EXT:' . $packageName . '/Resources/Public/JavaScript/';
1588  $fullJsPath = GeneralUtility::getFileAbsFileName($fullJsPath);
1589  $fullJsPath = PathUtility::getAbsoluteWebPath($fullJsPath);
1590  $fullJsPath = rtrim($fullJsPath, '/');
1591  if ($fullJsPath) {
1592  $requireJsConfig['paths']['TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($packageName)] = $fullJsPath;
1593  }
1594  }
1595 
1596  // check if additional AMD modules need to be loaded if a single AMD module is initialized
1597  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules'])) {
1598  $this->addInlineSettingArray(
1599  'RequireJS.PostInitializationModules',
1600  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules']
1601  );
1602  }
1603 
1604  return $requireJsConfig;
1605  }
1606 
1620  public function addRequireJsConfiguration(array $configuration)
1621  {
1622  if (TYPO3_MODE === 'BE') {
1623  // Load RequireJS in backend context at first. Doing this in FE could break the output
1624  $this->loadRequireJs();
1625  }
1626  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($this->requireJsConfig, $configuration);
1627  }
1628 
1646  public function loadRequireJsModule($mainModuleName, $callBackFunction = null)
1647  {
1648  $inlineCodeKey = $mainModuleName;
1649  // make sure requireJS is initialized
1650  $this->loadRequireJs();
1651 
1652  // execute the main module, and load a possible callback function
1653  $javaScriptCode = 'require(["' . $mainModuleName . '"]';
1654  if ($callBackFunction !== null) {
1655  $inlineCodeKey .= sha1($callBackFunction);
1656  $javaScriptCode .= ', ' . $callBackFunction;
1657  }
1658  $javaScriptCode .= ');';
1659  $this->addJsInlineCode('RequireJS-Module-' . $inlineCodeKey, $javaScriptCode);
1660  }
1661 
1669  public function loadExtJS($css = true, $theme = true)
1670  {
1671  $this->addExtJS = true;
1672  $this->extJStheme = $theme;
1673  $this->extJScss = $css;
1674  }
1675 
1681  public function enableExtJsDebug()
1682  {
1683  $this->enableExtJsDebug = true;
1684  }
1685 
1695  public function addInlineLanguageLabel($key, $value)
1696  {
1697  $this->inlineLanguageLabels[$key] = $value;
1698  }
1699 
1710  public function addInlineLanguageLabelArray(array $array, $parseWithLanguageService = false)
1711  {
1712  if ($parseWithLanguageService === true) {
1713  foreach ($array as $key => $value) {
1714  if (TYPO3_MODE === 'FE') {
1715  $array[$key] = $this->getTypoScriptFrontendController()->sL($value);
1716  } else {
1717  $array[$key] = $this->getLanguageService()->sL($value);
1718  }
1719  }
1720  }
1721 
1722  $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
1723  }
1724 
1734  public function addInlineLanguageLabelFile($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0)
1735  {
1736  $index = md5($fileRef . $selectionPrefix . $stripFromSelectionName);
1737  if ($fileRef && !isset($this->inlineLanguageLabelFiles[$index])) {
1738  $this->inlineLanguageLabelFiles[$index] = [
1739  'fileRef' => $fileRef,
1740  'selectionPrefix' => $selectionPrefix,
1741  'stripFromSelectionName' => $stripFromSelectionName,
1742  'errorMode' => $errorMode
1743  ];
1744  }
1745  }
1746 
1757  public function addInlineSetting($namespace, $key, $value)
1758  {
1759  if ($namespace) {
1760  if (strpos($namespace, '.')) {
1761  $parts = explode('.', $namespace);
1762  $a = &$this->inlineSettings;
1763  foreach ($parts as $part) {
1764  $a = &$a[$part];
1765  }
1766  $a[$key] = $value;
1767  } else {
1768  $this->inlineSettings[$namespace][$key] = $value;
1769  }
1770  } else {
1771  $this->inlineSettings[$key] = $value;
1772  }
1773  }
1774 
1785  public function addInlineSettingArray($namespace, array $array)
1786  {
1787  if ($namespace) {
1788  if (strpos($namespace, '.')) {
1789  $parts = explode('.', $namespace);
1790  $a = &$this->inlineSettings;
1791  foreach ($parts as $part) {
1792  $a = &$a[$part];
1793  }
1794  $a = array_merge((array)$a, $array);
1795  } else {
1796  $this->inlineSettings[$namespace] = array_merge((array)$this->inlineSettings[$namespace], $array);
1797  }
1798  } else {
1799  $this->inlineSettings = array_merge($this->inlineSettings, $array);
1800  }
1801  }
1802 
1809  public function addBodyContent($content)
1810  {
1811  $this->bodyContent .= $content;
1812  }
1813 
1814  /*****************************************************/
1815  /* */
1816  /* Render Functions */
1817  /* */
1818  /*****************************************************/
1825  public function render($part = self::PART_COMPLETE)
1826  {
1827  $this->prepareRendering();
1829  $metaTags = implode(LF, $this->metaTags);
1831  $template = $this->getTemplateForPart($part);
1832 
1833  // The page renderer needs a full reset, even when only rendering one part of the page
1834  // This means that you can only register footer files *after* the header has been already rendered.
1835  // In case you render the footer part first, header files can only be added *after* the footer has been rendered
1836  $this->reset();
1837  $templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
1838  return trim($templateService->substituteMarkerArray($template, $markerArray, '###|###'));
1839  }
1840 
1848  public function renderPageWithUncachedObjects($substituteHash)
1849  {
1850  $this->prepareRendering();
1851  $markerArray = $this->getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash);
1852  $template = $this->getTemplateForPart(self::PART_COMPLETE);
1853  $templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
1854  return trim($templateService->substituteMarkerArray($template, $markerArray, '###|###'));
1855  }
1856 
1866  public function renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash)
1867  {
1868  $this->prepareRendering();
1870  $title = $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '';
1871  $markerArray = [
1872  '<!-- ###TITLE' . $substituteHash . '### -->' => $title,
1873  '<!-- ###CSS_LIBS' . $substituteHash . '### -->' => $cssLibs,
1874  '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->' => $cssFiles,
1875  '<!-- ###CSS_INLINE' . $substituteHash . '### -->' => $cssInline,
1876  '<!-- ###JS_INLINE' . $substituteHash . '### -->' => $jsInline,
1877  '<!-- ###JS_INCLUDE' . $substituteHash . '### -->' => $jsFiles,
1878  '<!-- ###JS_LIBS' . $substituteHash . '### -->' => $jsLibs,
1879  '<!-- ###HEADERDATA' . $substituteHash . '### -->' => implode(LF, $this->headerData),
1880  '<!-- ###FOOTERDATA' . $substituteHash . '### -->' => implode(LF, $this->footerData),
1881  '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->' => $jsFooterLibs,
1882  '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->' => $jsFooterFiles,
1883  '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->' => $jsFooterInline
1884  ];
1885  foreach ($markerArray as $placeHolder => $content) {
1886  $cachedPageContent = str_replace($placeHolder, $content, $cachedPageContent);
1887  }
1888  $this->reset();
1889  return $cachedPageContent;
1890  }
1891 
1899  protected function prepareRendering()
1900  {
1901  if ($this->getRenderXhtml()) {
1902  $this->endingSlash = ' /';
1903  } else {
1904  $this->metaCharsetTag = str_replace(' />', '>', $this->metaCharsetTag);
1905  $this->baseUrlTag = str_replace(' />', '>', $this->baseUrlTag);
1906  $this->shortcutTag = str_replace(' />', '>', $this->shortcutTag);
1907  $this->endingSlash = '';
1908  }
1909  }
1910 
1916  protected function renderJavaScriptAndCss()
1917  {
1918  $this->executePreRenderHook();
1919  $mainJsLibs = $this->renderMainJavaScriptLibraries();
1920  if ($this->concatenateFiles || $this->concatenateJavascript || $this->concatenateCss) {
1921  // Do the file concatenation
1922  $this->doConcatenate();
1923  }
1924  if ($this->compressCss || $this->compressJavascript) {
1925  // Do the file compression
1926  $this->doCompress();
1927  }
1929  $cssLibs = $this->renderCssLibraries();
1930  $cssFiles = $this->renderCssFiles();
1931  $cssInline = $this->renderCssInline();
1933  list($jsFiles, $jsFooterFiles) = $this->renderJavaScriptFiles();
1935  $jsLibs = $mainJsLibs . $jsLibs;
1936  if ($this->moveJsFromHeaderToFooter) {
1938  $jsLibs = '';
1940  $jsFiles = '';
1942  $jsInline = '';
1943  }
1946  }
1947 
1964  {
1965  $markerArray = [
1966  'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
1967  'HTMLTAG' => $this->htmlTag,
1968  'HEADTAG' => $this->headTag,
1969  'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
1970  'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
1971  'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
1972  'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
1973  'CSS_LIBS' => $cssLibs,
1974  'CSS_INCLUDE' => $cssFiles,
1975  'CSS_INLINE' => $cssInline,
1976  'JS_INLINE' => $jsInline,
1977  'JS_INCLUDE' => $jsFiles,
1978  'JS_LIBS' => $jsLibs,
1979  'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
1980  'META' => $metaTags,
1981  'HEADERDATA' => $this->headerData ? implode(LF, $this->headerData) : '',
1982  'FOOTERDATA' => $this->footerData ? implode(LF, $this->footerData) : '',
1983  'JS_LIBS_FOOTER' => $jsFooterLibs,
1984  'JS_INCLUDE_FOOTER' => $jsFooterFiles,
1985  'JS_INLINE_FOOTER' => $jsFooterInline,
1986  'BODY' => $this->bodyContent
1987  ];
1988  $markerArray = array_map('trim', $markerArray);
1989  return $markerArray;
1990  }
1991 
1998  protected function getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash)
1999  {
2000  $markerArray = [
2001  'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
2002  'HTMLTAG' => $this->htmlTag,
2003  'HEADTAG' => $this->headTag,
2004  'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2005  'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2006  'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2007  'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2008  'META' => implode(LF, $this->metaTags),
2009  'BODY' => $this->bodyContent,
2010  'TITLE' => '<!-- ###TITLE' . $substituteHash . '### -->',
2011  'CSS_LIBS' => '<!-- ###CSS_LIBS' . $substituteHash . '### -->',
2012  'CSS_INCLUDE' => '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->',
2013  'CSS_INLINE' => '<!-- ###CSS_INLINE' . $substituteHash . '### -->',
2014  'JS_INLINE' => '<!-- ###JS_INLINE' . $substituteHash . '### -->',
2015  'JS_INCLUDE' => '<!-- ###JS_INCLUDE' . $substituteHash . '### -->',
2016  'JS_LIBS' => '<!-- ###JS_LIBS' . $substituteHash . '### -->',
2017  'HEADERDATA' => '<!-- ###HEADERDATA' . $substituteHash . '### -->',
2018  'FOOTERDATA' => '<!-- ###FOOTERDATA' . $substituteHash . '### -->',
2019  'JS_LIBS_FOOTER' => '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->',
2020  'JS_INCLUDE_FOOTER' => '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->',
2021  'JS_INLINE_FOOTER' => '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->'
2022  ];
2023  $markerArray = array_map('trim', $markerArray);
2024  return $markerArray;
2025  }
2026 
2033  protected function getTemplateForPart($part)
2034  {
2035  $templateFile = GeneralUtility::getFileAbsFileName($this->templateFile);
2036  if (is_file($templateFile)) {
2037  $template = file_get_contents($templateFile);
2038  if ($this->removeLineBreaksFromTemplate) {
2039  $template = strtr($template, [LF => '', CR => '']);
2040  }
2041  if ($part !== self::PART_COMPLETE) {
2042  $templatePart = explode('###BODY###', $template);
2043  $template = $templatePart[$part - 1];
2044  }
2045  } else {
2046  $template = '';
2047  }
2048  return $template;
2049  }
2050 
2057  protected function renderMainJavaScriptLibraries()
2058  {
2059  $out = '';
2060 
2061  // Include RequireJS
2062  if ($this->addRequireJs) {
2063  // load the paths of the requireJS configuration
2064  $out .= GeneralUtility::wrapJS('var require = ' . json_encode($this->requireJsConfig)) . LF;
2065  // directly after that, include the require.js file
2066  $out .= '<script src="' . $this->processJsFile($this->requireJsPath . 'require.js') . '" type="text/javascript"></script>' . LF;
2067  }
2068 
2069  // Include jQuery Core for each namespace, depending on the version and source
2070  if (!empty($this->jQueryVersions)) {
2071  foreach ($this->jQueryVersions as $namespace => $jQueryVersion) {
2072  $out .= $this->renderJqueryScriptTag($jQueryVersion['version'], $jQueryVersion['source'], $namespace);
2073  }
2074  }
2075 
2076  // Include extJS
2077  if ($this->addExtJS) {
2078  // Use the base adapter all the time
2079  $out .= '<script src="' . $this->processJsFile($this->extJsPath . 'adapter/ext-base' . ($this->enableExtJsDebug ? '-debug' : '') . '.js') . '" type="text/javascript"></script>' . LF;
2080  $out .= '<script src="' . $this->processJsFile($this->extJsPath . 'ext-all' . ($this->enableExtJsDebug ? '-debug' : '') . '.js') . '" type="text/javascript"></script>' . LF;
2081  // Add extJS localization
2082  // Load standard ISO mapping and modify for use with ExtJS
2083  $localeMap = $this->locales->getIsoMapping();
2084  $localeMap[''] = 'en';
2085  $localeMap['default'] = 'en';
2086  // Greek
2087  $localeMap['gr'] = 'el_GR';
2088  // Norwegian Bokmaal
2089  $localeMap['no'] = 'no_BO';
2090  // Swedish
2091  $localeMap['se'] = 'se_SV';
2092  $extJsLang = isset($localeMap[$this->lang]) ? $localeMap[$this->lang] : $this->lang;
2093  $extJsLocaleFile = $this->extJsPath . 'locale/ext-lang-' . $extJsLang . '.js';
2094  if (file_exists(PATH_site . $extJsLocaleFile)) {
2095  $out .= '<script src="' . $this->processJsFile($extJsLocaleFile) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2096  }
2097  // Remove extjs from JScodeLibArray
2098  unset($this->jsFiles[$this->extJsPath . 'ext-all.js'], $this->jsFiles[$this->extJsPath . 'ext-all-debug.js']);
2099  }
2101  if (TYPO3_MODE === 'BE') {
2102  $this->addAjaxUrlsToInlineSettings();
2103  }
2104  $inlineSettings = $this->inlineLanguageLabels ? 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' : '';
2105  $inlineSettings .= $this->inlineSettings ? 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' : '';
2106  if ($this->addExtJS) {
2107  // Set clear.gif, move it on top, add handler code
2108  $code = '';
2109  if (!empty($this->extOnReadyCode)) {
2110  foreach ($this->extOnReadyCode as $block) {
2111  $code .= $block;
2112  }
2113  }
2114  $clearGifPath = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Public/Images/clear.gif');
2115  $clearGifPath = htmlspecialchars(PathUtility::getAbsoluteWebPath($clearGifPath));
2116  $out .= $this->inlineJavascriptWrap[0] . '
2117  Ext.ns("TYPO3");
2118  Ext.BLANK_IMAGE_URL = "' . $clearGifPath . '";
2119  Ext.SSL_SECURE_URL = "' . $clearGifPath . '";' . LF
2120  . $inlineSettings
2121  . 'Ext.onReady(function() {'
2122  . $code
2123  . ' });'
2124  . $this->inlineJavascriptWrap[1];
2125  $this->extOnReadyCode = [];
2126  // Include TYPO3.l10n object
2127  if (TYPO3_MODE === 'BE') {
2128  $out .= '<script src="' . $this->processJsFile('EXT:lang/Resources/Public/JavaScript/Typo3Lang.js') . '" type="text/javascript" charset="utf-8"></script>' . LF;
2129  }
2130  if ($this->extJScss) {
2131  if (isset($GLOBALS['TBE_STYLES']['extJS']['all'])) {
2132  $this->addCssLibrary($GLOBALS['TBE_STYLES']['extJS']['all'], 'stylesheet', 'all', '', true);
2133  } else {
2134  $this->addCssLibrary($this->extJsPath . 'resources/css/ext-all-notheme.css', 'stylesheet', 'all', '', true);
2135  }
2136  }
2137  if ($this->extJStheme) {
2138  if (isset($GLOBALS['TBE_STYLES']['extJS']['theme'])) {
2139  $this->addCssLibrary($GLOBALS['TBE_STYLES']['extJS']['theme'], 'stylesheet', 'all', '', true);
2140  } else {
2141  $this->addCssLibrary($this->extJsPath . 'resources/css/xtheme-blue.css', 'stylesheet', 'all', '', true);
2142  }
2143  }
2144  } else {
2145  // no extJS loaded, but still inline settings
2146  if ($inlineSettings !== '') {
2147  // make sure the global TYPO3 is available
2148  $inlineSettings = 'var TYPO3 = TYPO3 || {};' . CRLF . $inlineSettings;
2149  $out .= $this->inlineJavascriptWrap[0] . $inlineSettings . $this->inlineJavascriptWrap[1];
2150  // Add language module only if also jquery is guaranteed to be there
2151  if (TYPO3_MODE === 'BE' && !empty($this->jQueryVersions)) {
2152  $this->loadRequireJsModule('TYPO3/CMS/Lang/Lang');
2153  }
2154  }
2155  }
2156  return $out;
2157  }
2158 
2162  protected function loadJavaScriptLanguageStrings()
2163  {
2164  if (!empty($this->inlineLanguageLabelFiles)) {
2165  foreach ($this->inlineLanguageLabelFiles as $languageLabelFile) {
2166  $this->includeLanguageFileForInline($languageLabelFile['fileRef'], $languageLabelFile['selectionPrefix'], $languageLabelFile['stripFromSelectionName'], $languageLabelFile['errorMode']);
2167  }
2168  }
2169  $this->inlineLanguageLabelFiles = [];
2170  // Convert settings back to UTF-8 since json_encode() only works with UTF-8:
2171  if (TYPO3_MODE === 'FE' && $this->getCharSet() !== 'utf-8') {
2172  if ($this->inlineSettings) {
2173  $this->csConvObj->convArray($this->inlineSettings, $this->getCharSet(), 'utf-8');
2174  }
2175  }
2176  }
2177 
2181  protected function addAjaxUrlsToInlineSettings()
2182  {
2183  $ajaxUrls = [];
2184  // Note: this method of adding Ajax URLs is @deprecated as of TYPO3 v8, and will be removed in TYPO3 v9
2185  foreach ($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'] as $ajaxHandler => $_) {
2186  $ajaxUrls[$ajaxHandler] = BackendUtility::getAjaxUrl($ajaxHandler);
2187  }
2188 
2189  // also add the ajax-based routes
2191  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2193  $router = GeneralUtility::makeInstance(Router::class);
2194  $routes = $router->getRoutes();
2195  foreach ($routes as $routeIdentifier => $route) {
2196  if ($route->getOption('ajax')) {
2197  $uri = (string)$uriBuilder->buildUriFromRoute($routeIdentifier);
2198  // use the shortened value in order to use this in JavaScript
2199  $routeIdentifier = str_replace('ajax_', '', $routeIdentifier);
2200  $ajaxUrls[$routeIdentifier] = $uri;
2201  }
2202  }
2203 
2204  $this->inlineSettings['ajaxUrls'] = $ajaxUrls;
2205  }
2206 
2215  protected function renderJqueryScriptTag($version, $source, $namespace)
2216  {
2217  switch (true) {
2218  case isset($this->jQueryCdnUrls[$source]):
2219  if ($this->enableJqueryDebug) {
2220  $minifyPart = '';
2221  } else {
2222  $minifyPart = '.min';
2223  }
2224  $jQueryFileName = sprintf($this->jQueryCdnUrls[$source], $version, $minifyPart);
2225  break;
2226  case $source === 'local':
2227  $jQueryFileName = $this->jQueryPath . 'jquery-' . rawurlencode($version);
2228  if ($this->enableJqueryDebug) {
2229  $jQueryFileName .= '.js';
2230  } else {
2231  $jQueryFileName .= '.min.js';
2232  }
2233  $jQueryFileName = $this->processJsFile($jQueryFileName);
2234  break;
2235  default:
2236  $jQueryFileName = $source;
2237  }
2238  // Include the jQuery Core
2239  $scriptTag = '<script src="' . htmlspecialchars($jQueryFileName) . '" type="text/javascript"></script>' . LF;
2240  // Set the noConflict mode to be available via "TYPO3.jQuery" in all installations
2241  switch ($namespace) {
2242  case self::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT:
2243  $scriptTag .= GeneralUtility::wrapJS('jQuery.noConflict();') . LF;
2244  break;
2245  case self::JQUERY_NAMESPACE_NONE:
2246  break;
2247  case self::JQUERY_NAMESPACE_DEFAULT:
2248 
2249  default:
2250  $scriptTag .= GeneralUtility::wrapJS('var TYPO3 = TYPO3 || {}; TYPO3.' . $namespace . ' = jQuery.noConflict(true);') . LF;
2251  }
2252  return $scriptTag;
2253  }
2254 
2260  protected function renderCssLibraries()
2261  {
2262  $cssFiles = '';
2263  if (!empty($this->cssLibs)) {
2264  foreach ($this->cssLibs as $file => $properties) {
2265  $file = $this->getStreamlinedFileName($file);
2266  $tag = '<link rel="' . htmlspecialchars($properties['rel'])
2267  . '" type="text/css" href="' . htmlspecialchars($file)
2268  . '" media="' . htmlspecialchars($properties['media']) . '"'
2269  . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
2270  . $this->endingSlash . '>';
2271  if ($properties['allWrap']) {
2272  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2273  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2274  }
2275  $tag .= LF;
2276  if ($properties['forceOnTop']) {
2277  $cssFiles = $tag . $cssFiles;
2278  } else {
2279  $cssFiles .= $tag;
2280  }
2281  }
2282  }
2283  return $cssFiles;
2284  }
2285 
2291  protected function renderCssFiles()
2292  {
2293  $cssFiles = '';
2294  if (!empty($this->cssFiles)) {
2295  foreach ($this->cssFiles as $file => $properties) {
2296  $file = $this->getStreamlinedFileName($file);
2297  $tag = '<link rel="' . htmlspecialchars($properties['rel'])
2298  . '" type="text/css" href="' . htmlspecialchars($file)
2299  . '" media="' . htmlspecialchars($properties['media']) . '"'
2300  . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
2301  . $this->endingSlash . '>';
2302  if ($properties['allWrap']) {
2303  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2304  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2305  }
2306  $tag .= LF;
2307  if ($properties['forceOnTop']) {
2308  $cssFiles = $tag . $cssFiles;
2309  } else {
2310  $cssFiles .= $tag;
2311  }
2312  }
2313  }
2314  return $cssFiles;
2315  }
2316 
2322  protected function renderCssInline()
2323  {
2324  $cssInline = '';
2325  if (!empty($this->cssInline)) {
2326  foreach ($this->cssInline as $name => $properties) {
2327  $cssCode = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2328  if ($properties['forceOnTop']) {
2329  $cssInline = $cssCode . $cssInline;
2330  } else {
2331  $cssInline .= $cssCode;
2332  }
2333  }
2334  $cssInline = $this->inlineCssWrap[0] . $cssInline . $this->inlineCssWrap[1];
2335  }
2336  return $cssInline;
2337  }
2338 
2345  {
2346  $jsLibs = '';
2347  $jsFooterLibs = '';
2348  if (!empty($this->jsLibs)) {
2349  foreach ($this->jsLibs as $properties) {
2350  $properties['file'] = $this->getStreamlinedFileName($properties['file']);
2351  $async = ($properties['async']) ? ' async="async"' : '';
2352  $integrity = ($properties['integrity']) ? ' integrity="' . htmlspecialchars($properties['integrity']) . '" crossorigin="anonymous"' : '';
2353  $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . $integrity . '></script>';
2354  if ($properties['allWrap']) {
2355  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2356  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2357  }
2358  $tag .= LF;
2359  if ($properties['forceOnTop']) {
2360  if ($properties['section'] === self::PART_HEADER) {
2361  $jsLibs = $tag . $jsLibs;
2362  } else {
2363  $jsFooterLibs = $tag . $jsFooterLibs;
2364  }
2365  } else {
2366  if ($properties['section'] === self::PART_HEADER) {
2367  $jsLibs .= $tag;
2368  } else {
2369  $jsFooterLibs .= $tag;
2370  }
2371  }
2372  }
2373  }
2374  if ($this->moveJsFromHeaderToFooter) {
2376  $jsLibs = '';
2377  }
2378  return [$jsLibs, $jsFooterLibs];
2379  }
2380 
2386  protected function renderJavaScriptFiles()
2387  {
2388  $jsFiles = '';
2389  $jsFooterFiles = '';
2390  if (!empty($this->jsFiles)) {
2391  foreach ($this->jsFiles as $file => $properties) {
2392  $file = $this->getStreamlinedFileName($file);
2393  $async = ($properties['async']) ? ' async="async"' : '';
2394  $integrity = ($properties['integrity']) ? ' integrity="' . htmlspecialchars($properties['integrity']) . '" crossorigin="anonymous"' : '';
2395  $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . $integrity . '></script>';
2396  if ($properties['allWrap']) {
2397  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2398  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2399  }
2400  $tag .= LF;
2401  if ($properties['forceOnTop']) {
2402  if ($properties['section'] === self::PART_HEADER) {
2403  $jsFiles = $tag . $jsFiles;
2404  } else {
2405  $jsFooterFiles = $tag . $jsFooterFiles;
2406  }
2407  } else {
2408  if ($properties['section'] === self::PART_HEADER) {
2409  $jsFiles .= $tag;
2410  } else {
2411  $jsFooterFiles .= $tag;
2412  }
2413  }
2414  }
2415  }
2416  if ($this->moveJsFromHeaderToFooter) {
2418  $jsFiles = '';
2419  }
2420  return [$jsFiles, $jsFooterFiles];
2421  }
2422 
2428  protected function renderInlineJavaScript()
2429  {
2430  $jsInline = '';
2431  $jsFooterInline = '';
2432  if (!empty($this->jsInline)) {
2433  foreach ($this->jsInline as $name => $properties) {
2434  $jsCode = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2435  if ($properties['forceOnTop']) {
2436  if ($properties['section'] === self::PART_HEADER) {
2437  $jsInline = $jsCode . $jsInline;
2438  } else {
2439  $jsFooterInline = $jsCode . $jsFooterInline;
2440  }
2441  } else {
2442  if ($properties['section'] === self::PART_HEADER) {
2443  $jsInline .= $jsCode;
2444  } else {
2445  $jsFooterInline .= $jsCode;
2446  }
2447  }
2448  }
2449  }
2450  if ($jsInline) {
2451  $jsInline = $this->inlineJavascriptWrap[0] . $jsInline . $this->inlineJavascriptWrap[1];
2452  }
2453  if ($jsFooterInline) {
2454  $jsFooterInline = $this->inlineJavascriptWrap[0] . $jsFooterInline . $this->inlineJavascriptWrap[1];
2455  }
2456  if ($this->moveJsFromHeaderToFooter) {
2458  $jsInline = '';
2459  }
2460  return [$jsInline, $jsFooterInline];
2461  }
2462 
2473  protected function includeLanguageFileForInline($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0)
2474  {
2475  if (!isset($this->lang) || !isset($this->charSet)) {
2476  throw new \RuntimeException('Language and character encoding are not set.', 1284906026);
2477  }
2478  $labelsFromFile = [];
2479  $allLabels = $this->readLLfile($fileRef, $errorMode);
2480  if ($allLabels !== false) {
2481  // Merge language specific translations:
2482  if ($this->lang !== 'default' && isset($allLabels[$this->lang])) {
2483  $labels = array_merge($allLabels['default'], $allLabels[$this->lang]);
2484  } else {
2485  $labels = $allLabels['default'];
2486  }
2487  // Iterate through all locallang labels:
2488  foreach ($labels as $label => $value) {
2489  // If $selectionPrefix is set, only respect labels that start with $selectionPrefix
2490  if ($selectionPrefix === '' || strpos($label, $selectionPrefix) === 0) {
2491  // Remove substring $stripFromSelectionName from label
2492  $label = str_replace($stripFromSelectionName, '', $label);
2493  $labelsFromFile[$label] = $value;
2494  }
2495  }
2496  $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $labelsFromFile);
2497  }
2498  }
2499 
2507  protected function readLLfile($fileRef, $errorMode = 0)
2508  {
2510  $languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
2511 
2512  if ($this->lang !== 'default') {
2513  $languages = array_reverse($this->languageDependencies);
2514  // At least we need to have English
2515  if (empty($languages)) {
2516  $languages[] = 'default';
2517  }
2518  } else {
2519  $languages = ['default'];
2520  }
2521 
2522  $localLanguage = [];
2523  foreach ($languages as $language) {
2524  $tempLL = $languageFactory->getParsedData($fileRef, $language, $this->charSet, $errorMode);
2525 
2526  $localLanguage['default'] = $tempLL['default'];
2527  if (!isset($localLanguage[$this->lang])) {
2528  $localLanguage[$this->lang] = $localLanguage['default'];
2529  }
2530  if ($this->lang !== 'default' && isset($tempLL[$language])) {
2531  // Merge current language labels onto labels from previous language
2532  // This way we have a labels with fall back applied
2533  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$this->lang], $tempLL[$language], true, false);
2534  }
2535  }
2536 
2537  return $localLanguage;
2538  }
2539 
2540  /*****************************************************/
2541  /* */
2542  /* Tools */
2543  /* */
2544  /*****************************************************/
2551  protected function doConcatenate()
2552  {
2553  $this->doConcatenateCss();
2554  $this->doConcatenateJavaScript();
2555  }
2556 
2562  protected function doConcatenateJavaScript()
2563  {
2564  if ($this->concatenateFiles || $this->concatenateJavascript) {
2565  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'])) {
2566  // use external concatenation routine
2567  $params = [
2568  'jsLibs' => &$this->jsLibs,
2569  'jsFiles' => &$this->jsFiles,
2570  'jsFooterFiles' => &$this->jsFooterFiles,
2571  'headerData' => &$this->headerData,
2572  'footerData' => &$this->footerData
2573  ];
2574  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'], $params, $this);
2575  } else {
2576  $this->jsLibs = $this->getCompressor()->concatenateJsFiles($this->jsLibs);
2577  $this->jsFiles = $this->getCompressor()->concatenateJsFiles($this->jsFiles);
2578  $this->jsFooterFiles = $this->getCompressor()->concatenateJsFiles($this->jsFooterFiles);
2579  }
2580  }
2581  }
2582 
2588  protected function doConcatenateCss()
2589  {
2590  if ($this->concatenateFiles || $this->concatenateCss) {
2591  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'])) {
2592  // use external concatenation routine
2593  $params = [
2594  'cssFiles' => &$this->cssFiles,
2595  'cssLibs' => &$this->cssLibs,
2596  'headerData' => &$this->headerData,
2597  'footerData' => &$this->footerData
2598  ];
2599  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'], $params, $this);
2600  } else {
2601  $cssOptions = [];
2602  if (TYPO3_MODE === 'BE') {
2603  $cssOptions = ['baseDirectories' => $GLOBALS['TBE_TEMPLATE']->getSkinStylesheetDirectories()];
2604  }
2605  $this->cssLibs = $this->getCompressor()->concatenateCssFiles($this->cssLibs, $cssOptions);
2606  $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles, $cssOptions);
2607  }
2608  }
2609  }
2610 
2616  protected function doCompress()
2617  {
2618  $this->doCompressJavaScript();
2619  $this->doCompressCss();
2620  }
2621 
2627  protected function doCompressCss()
2628  {
2629  if ($this->compressCss) {
2630  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'])) {
2631  // Use external compression routine
2632  $params = [
2633  'cssInline' => &$this->cssInline,
2634  'cssFiles' => &$this->cssFiles,
2635  'cssLibs' => &$this->cssLibs,
2636  'headerData' => &$this->headerData,
2637  'footerData' => &$this->footerData
2638  ];
2639  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'], $params, $this);
2640  } else {
2641  $this->cssLibs = $this->getCompressor()->compressCssFiles($this->cssLibs);
2642  $this->cssFiles = $this->getCompressor()->compressCssFiles($this->cssFiles);
2643  }
2644  }
2645  }
2646 
2652  protected function doCompressJavaScript()
2653  {
2654  if ($this->compressJavascript) {
2655  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'])) {
2656  // Use external compression routine
2657  $params = [
2658  'jsInline' => &$this->jsInline,
2659  'jsFooterInline' => &$this->jsFooterInline,
2660  'jsLibs' => &$this->jsLibs,
2661  'jsFiles' => &$this->jsFiles,
2662  'jsFooterFiles' => &$this->jsFooterFiles,
2663  'headerData' => &$this->headerData,
2664  'footerData' => &$this->footerData
2665  ];
2666  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'], $params, $this);
2667  } else {
2668  // Traverse the arrays, compress files
2669  if (!empty($this->jsInline)) {
2670  foreach ($this->jsInline as $name => $properties) {
2671  if ($properties['compress']) {
2672  $error = '';
2673  $this->jsInline[$name]['code'] = GeneralUtility::minifyJavaScript($properties['code'], $error);
2674  if ($error) {
2675  $this->compressError .= 'Error with minify JS Inline Block "' . $name . '": ' . $error . LF;
2676  }
2677  }
2678  }
2679  }
2680  $this->jsLibs = $this->getCompressor()->compressJsFiles($this->jsLibs);
2681  $this->jsFiles = $this->getCompressor()->compressJsFiles($this->jsFiles);
2682  $this->jsFooterFiles = $this->getCompressor()->compressJsFiles($this->jsFooterFiles);
2683  }
2684  }
2685  }
2686 
2692  protected function getCompressor()
2693  {
2694  if ($this->compressor === null) {
2695  $this->compressor = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\ResourceCompressor::class);
2696  }
2697  return $this->compressor;
2698  }
2699 
2708  protected function processJsFile($filename)
2709  {
2710  $filename = $this->getStreamlinedFileName($filename, false);
2711  if ($this->compressJavascript) {
2712  $filename = $this->getCompressor()->compressJsFile($filename);
2713  } elseif (TYPO3_MODE === 'FE') {
2714  $filename = GeneralUtility::createVersionNumberedFilename($filename);
2715  }
2716  return PathUtility::getAbsoluteWebPath($filename);
2717  }
2718 
2731  protected function getStreamlinedFileName($file, $prepareForOutput = true)
2732  {
2733  if (strpos($file, 'EXT:') === 0) {
2734  $file = GeneralUtility::getFileAbsFileName($file);
2735  // as the path is now absolute, make it "relative" to the current script to stay compatible
2736  $file = PathUtility::getRelativePathTo($file);
2737  $file = rtrim($file, '/');
2738  } else {
2739  $file = GeneralUtility::resolveBackPath($file);
2740  }
2741  if ($prepareForOutput) {
2743  $file = PathUtility::getAbsoluteWebPath($file);
2744  }
2745  return $file;
2746  }
2747 
2753  protected function getTypoScriptFrontendController()
2754  {
2755  return $GLOBALS['TSFE'];
2756  }
2757 
2763  protected function getLanguageService()
2764  {
2765  return $GLOBALS['LANG'];
2766  }
2767 
2768  /*****************************************************/
2769  /* */
2770  /* Hooks */
2771  /* */
2772  /*****************************************************/
2778  protected function executePreRenderHook()
2779  {
2780  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'])) {
2781  $params = [
2782  'jsLibs' => &$this->jsLibs,
2783  'jsFooterLibs' => &$this->jsFooterLibs,
2784  'jsFiles' => &$this->jsFiles,
2785  'jsFooterFiles' => &$this->jsFooterFiles,
2786  'cssLibs' => &$this->cssLibs,
2787  'cssFiles' => &$this->cssFiles,
2788  'headerData' => &$this->headerData,
2789  'footerData' => &$this->footerData,
2790  'jsInline' => &$this->jsInline,
2791  'jsFooterInline' => &$this->jsFooterInline,
2792  'cssInline' => &$this->cssInline
2793  ];
2794  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'] as $hook) {
2795  GeneralUtility::callUserFunction($hook, $params, $this);
2796  }
2797  }
2798  }
2799 
2805  protected function executeRenderPostTransformHook()
2806  {
2807  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'])) {
2808  $params = [
2809  'jsLibs' => &$this->jsLibs,
2810  'jsFooterLibs' => &$this->jsFooterLibs,
2811  'jsFiles' => &$this->jsFiles,
2812  'jsFooterFiles' => &$this->jsFooterFiles,
2813  'cssLibs' => &$this->cssLibs,
2814  'cssFiles' => &$this->cssFiles,
2815  'headerData' => &$this->headerData,
2816  'footerData' => &$this->footerData,
2817  'jsInline' => &$this->jsInline,
2818  'jsFooterInline' => &$this->jsFooterInline,
2819  'cssInline' => &$this->cssInline
2820  ];
2821  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'] as $hook) {
2822  GeneralUtility::callUserFunction($hook, $params, $this);
2823  }
2824  }
2825  }
2826 
2842  {
2843  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'])) {
2844  $params = [
2845  'jsLibs' => &$jsLibs,
2846  'jsFiles' => &$jsFiles,
2847  'jsFooterFiles' => &$jsFooterFiles,
2848  'cssLibs' => &$cssLibs,
2849  'cssFiles' => &$cssFiles,
2850  'headerData' => &$this->headerData,
2851  'footerData' => &$this->footerData,
2852  'jsInline' => &$jsInline,
2853  'cssInline' => &$cssInline,
2854  'xmlPrologAndDocType' => &$this->xmlPrologAndDocType,
2855  'htmlTag' => &$this->htmlTag,
2856  'headTag' => &$this->headTag,
2857  'charSet' => &$this->charSet,
2858  'metaCharsetTag' => &$this->metaCharsetTag,
2859  'shortcutTag' => &$this->shortcutTag,
2860  'inlineComments' => &$this->inlineComments,
2861  'baseUrl' => &$this->baseUrl,
2862  'baseUrlTag' => &$this->baseUrlTag,
2863  'favIcon' => &$this->favIcon,
2864  'iconMimeType' => &$this->iconMimeType,
2865  'titleTag' => &$this->titleTag,
2866  'title' => &$this->title,
2867  'metaTags' => &$this->metaTags,
2868  'jsFooterInline' => &$jsFooterInline,
2869  'jsFooterLibs' => &$jsFooterLibs,
2870  'bodyContent' => &$this->bodyContent
2871  ];
2872  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'] as $hook) {
2873  GeneralUtility::callUserFunction($hook, $params, $this);
2874  }
2875  }
2876  }
2877 }
static minifyJavaScript($script, &$error= '')
addInlineLanguageLabelArray(array $array, $parseWithLanguageService=false)
loadJquery($version=null, $source=null, $namespace=self::JQUERY_NAMESPACE_DEFAULT)
getStreamlinedFileName($file, $prepareForOutput=true)
addCssLibrary($file, $rel= 'stylesheet', $media= 'all', $title= '', $compress=true, $forceOnTop=false, $allWrap= '', $excludeFromConcatenation=false, $splitChar= '|')
static getRelativePathTo($targetPath)
Definition: PathUtility.php:29
setXmlPrologAndDocType($xmlPrologAndDocType)
addJsFooterInlineCode($name, $block, $compress=true, $forceOnTop=false)
addRequireJsConfiguration(array $configuration)
addExtOnReadyCode($block, $forceOnTop=false)
renderJqueryScriptTag($version, $source, $namespace)
includeLanguageFileForInline($fileRef, $selectionPrefix= '', $stripFromSelectionName= '', $errorMode=0)
executePostRenderHook(&$jsLibs, &$jsFiles, &$jsFooterFiles, &$cssLibs, &$cssFiles, &$jsInline, &$cssInline, &$jsFooterInline, &$jsFooterLibs)
static get($classNameOrType= 'default',...$constructorArguments)
computeRequireJsConfig($isDevelopment, array $loadedExtensions)
addJsInlineCode($name, $block, $compress=true, $forceOnTop=false)
loadExtJS($css=true, $theme=true)
renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash)
getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags)
addInlineLanguageLabelFile($fileRef, $selectionPrefix= '', $stripFromSelectionName= '', $errorMode=0)
addJsFooterFile($file, $type= 'text/javascript', $compress=true, $forceOnTop=false, $allWrap= '', $excludeFromConcatenation=false, $splitChar= '|', $async=false, $integrity= '')
addCssFile($file, $rel= 'stylesheet', $media= 'all', $title= '', $compress=true, $forceOnTop=false, $allWrap= '', $excludeFromConcatenation=false, $splitChar= '|')
addJsLibrary($name, $file, $type= 'text/javascript', $compress=false, $forceOnTop=false, $allWrap= '', $excludeFromConcatenation=false, $splitChar= '|', $async=false, $integrity= '')
addJsFile($file, $type= 'text/javascript', $compress=true, $forceOnTop=false, $allWrap= '', $excludeFromConcatenation=false, $splitChar= '|', $async=false, $integrity= '')
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
render($part=self::PART_COMPLETE)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
addJsFooterLibrary($name, $file, $type= 'text/javascript', $compress=false, $forceOnTop=false, $allWrap= '', $excludeFromConcatenation=false, $splitChar= '|', $async=false, $integrity= '')
loadRequireJsModule($mainModuleName, $callBackFunction=null)
static getFileAbsFileName($filename, $_=null, $_2=null)
static getAbsoluteWebPath($targetPath)
Definition: PathUtility.php:40
renderPageWithUncachedObjects($substituteHash)
static hmac($input, $additionalSecret= '')
static callUserFunction($funcName, &$params, &$ref, $_= '', $errorMode=0)
addInlineSettingArray($namespace, array $array)
getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash)
addInlineSetting($namespace, $key, $value)
addCssInlineBlock($name, $block, $compress=false, $forceOnTop=false)