TYPO3 CMS  TYPO3_7-6
PageRenderer.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
25 
31 {
32  // Constants for the part to be rendered
33  const PART_COMPLETE = 0;
34  const PART_HEADER = 1;
35  const PART_FOOTER = 2;
36  // jQuery Core version that is shipped with TYPO3
37  const JQUERY_VERSION_LATEST = '2.1.4';
38  // jQuery namespace options
39  const JQUERY_NAMESPACE_NONE = 'none';
40  const JQUERY_NAMESPACE_DEFAULT = 'jQuery';
41  const JQUERY_NAMESPACE_DEFAULT_NOCONFLICT = 'defaultNoConflict';
42 
46  protected $compressJavascript = false;
47 
51  protected $compressCss = false;
52 
56  protected $removeLineBreaksFromTemplate = false;
57 
61  protected $concatenateFiles = false;
62 
66  protected $concatenateJavascript = false;
67 
71  protected $concatenateCss = false;
72 
76  protected $moveJsFromHeaderToFooter = false;
77 
81  protected $csConvObj;
82 
86  protected $locales;
87 
94  protected $lang;
95 
102  protected $languageDependencies = [];
103 
107  protected $compressor;
108 
109  // Arrays containing associative array for the included files
113  protected $jsFiles = [];
114 
118  protected $jsFooterFiles = [];
119 
123  protected $jsLibs = [];
124 
128  protected $jsFooterLibs = [];
129 
133  protected $cssFiles = [];
134 
138  protected $cssLibs = [];
139 
145  protected $title;
146 
152  protected $charSet;
153 
157  protected $favIcon;
158 
162  protected $baseUrl;
163 
167  protected $renderXhtml = true;
168 
169  // Static header blocks
173  protected $xmlPrologAndDocType = '';
174 
178  protected $metaTags = [];
179 
183  protected $inlineComments = [];
184 
188  protected $headerData = [];
189 
193  protected $footerData = [];
194 
198  protected $titleTag = '<title>|</title>';
199 
203  protected $metaCharsetTag = '<meta http-equiv="Content-Type" content="text/html; charset=|" />';
204 
208  protected $htmlTag = '<html>';
209 
213  protected $headTag = '<head>';
214 
218  protected $baseUrlTag = '<base href="|" />';
219 
223  protected $iconMimeType = '';
224 
228  protected $shortcutTag = '<link rel="shortcut icon" href="%1$s"%2$s />';
229 
230  // Static inline code blocks
234  protected $jsInline = [];
235 
239  protected $jsFooterInline = [];
240 
244  protected $extOnReadyCode = [];
245 
249  protected $cssInline = [];
250 
254  protected $bodyContent;
255 
259  protected $templateFile;
260 
264  protected $jsLibraryNames = ['extjs'];
265 
266  // Paths to contibuted libraries
267 
272  protected $requireJsPath = 'Resources/Public/JavaScript/Contrib/';
273 
277  protected $extJsPath = 'Resources/Public/JavaScript/Contrib/extjs/';
278 
284  protected $jQueryPath = 'Resources/Public/JavaScript/Contrib/jquery/';
285 
286  // Internal flags for JS-libraries
304  protected $jQueryVersions = [];
305 
312  self::JQUERY_VERSION_LATEST
313  ];
314 
320  protected $jQueryCdnUrls = [
321  'google' => 'https://ajax.googleapis.com/ajax/libs/jquery/%1$s/jquery%2$s.js',
322  'msn' => 'https://ajax.aspnetcdn.com/ajax/jQuery/jquery-%1$s%2$s.js',
323  'jquery' => 'https://code.jquery.com/jquery-%1$s%2$s.js',
324  'cloudflare' => 'https://cdnjs.cloudflare.com/ajax/libs/jquery/%1$s/jquery%2$s.js'
325  ];
326 
331  protected $addRequireJs = false;
332 
337  protected $requireJsConfig = [];
338 
342  protected $addExtJS = false;
343 
347  protected $extDirectCodeAdded = false;
348 
352  protected $enableExtJsDebug = false;
353 
357  protected $enableJqueryDebug = false;
358 
362  protected $extJStheme = true;
363 
367  protected $extJScss = true;
368 
372  protected $inlineLanguageLabels = [];
373 
378 
382  protected $inlineSettings = [];
383 
387  protected $inlineJavascriptWrap = [];
388 
394  protected $compressError = '';
395 
401  protected $endingSlash = '';
402 
408  public $backPath;
409 
414  public function __construct($templateFile = '', $backPath = null)
415  {
416  $this->reset();
417 
418  $coreRelPath = ExtensionManagementUtility::extRelPath('core');
419  $this->requireJsPath = $coreRelPath . $this->requireJsPath;
420  $this->extJsPath = $coreRelPath . $this->extJsPath;
421  $this->jQueryPath = $coreRelPath . $this->jQueryPath;
422 
423  $this->csConvObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Charset\CharsetConverter::class);
424  $this->locales = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\Locales::class);
425  if ($templateFile !== '') {
426  $this->templateFile = $templateFile;
427  }
428  $this->backPath = isset($backPath) ? $backPath : $GLOBALS['BACK_PATH'];
429  $this->inlineJavascriptWrap = [
430  '<script type="text/javascript">' . LF . '/*<![CDATA[*/' . LF,
431  '/*]]>*/' . LF . '</script>' . LF
432  ];
433  $this->inlineCssWrap = [
434  '<style type="text/css">' . LF . '/*<![CDATA[*/' . LF . '<!-- ' . LF,
435  '-->' . LF . '/*]]>*/' . LF . '</style>' . LF
436  ];
437  }
438 
444  protected function reset()
445  {
446  $this->templateFile = 'EXT:core/Resources/Private/Templates/PageRenderer.html';
447  $this->jsFiles = [];
448  $this->jsFooterFiles = [];
449  $this->jsInline = [];
450  $this->jsFooterInline = [];
451  $this->jsLibs = [];
452  $this->cssFiles = [];
453  $this->cssInline = [];
454  $this->metaTags = [];
455  $this->inlineComments = [];
456  $this->headerData = [];
457  $this->footerData = [];
458  $this->extOnReadyCode = [];
459  $this->jQueryVersions = [];
460  }
461 
462  /*****************************************************/
463  /* */
464  /* Public Setters */
465  /* */
466  /* */
467  /*****************************************************/
474  public function setTitle($title)
475  {
476  $this->title = $title;
477  }
478 
485  public function setRenderXhtml($enable)
486  {
487  $this->renderXhtml = $enable;
488  }
489 
497  {
498  $this->xmlPrologAndDocType = $xmlPrologAndDocType;
499  }
500 
507  public function setCharSet($charSet)
508  {
509  $this->charSet = $charSet;
510  }
511 
518  public function setLanguage($lang)
519  {
520  $this->lang = $lang;
521  $this->languageDependencies = [];
522 
523  // Language is found. Configure it:
524  if (in_array($this->lang, $this->locales->getLocales())) {
525  $this->languageDependencies[] = $this->lang;
526  foreach ($this->locales->getLocaleDependencies($this->lang) as $language) {
527  $this->languageDependencies[] = $language;
528  }
529  }
530  }
531 
539  {
540  $this->metaCharsetTag = $metaCharsetTag;
541  }
542 
549  public function setHtmlTag($htmlTag)
550  {
551  $this->htmlTag = $htmlTag;
552  }
553 
560  public function setHeadTag($headTag)
561  {
562  $this->headTag = $headTag;
563  }
564 
571  public function setFavIcon($favIcon)
572  {
573  $this->favIcon = $favIcon;
574  }
575 
583  {
584  $this->iconMimeType = $iconMimeType;
585  }
586 
593  public function setBaseUrl($baseUrl)
594  {
595  $this->baseUrl = $baseUrl;
596  }
597 
604  public function setTemplateFile($file)
605  {
606  $this->templateFile = $file;
607  }
608 
615  public function setBackPath($backPath)
616  {
617  $this->backPath = $backPath;
618  }
619 
626  public function setBodyContent($content)
627  {
628  $this->bodyContent = $content;
629  }
630 
637  public function setRequireJsPath($path)
638  {
639  $this->requireJsPath = $path;
640  }
641 
648  public function setExtJsPath($path)
649  {
650  $this->extJsPath = $path;
651  }
652 
653  /*****************************************************/
654  /* */
655  /* Public Enablers / Disablers */
656  /* */
657  /* */
658  /*****************************************************/
665  {
666  $this->moveJsFromHeaderToFooter = true;
667  }
668 
675  {
676  $this->moveJsFromHeaderToFooter = false;
677  }
678 
684  public function enableCompressJavascript()
685  {
686  $this->compressJavascript = true;
687  }
688 
694  public function disableCompressJavascript()
695  {
696  $this->compressJavascript = false;
697  }
698 
704  public function enableCompressCss()
705  {
706  $this->compressCss = true;
707  }
708 
714  public function disableCompressCss()
715  {
716  $this->compressCss = false;
717  }
718 
724  public function enableConcatenateFiles()
725  {
726  $this->concatenateFiles = true;
727  }
728 
734  public function disableConcatenateFiles()
735  {
736  $this->concatenateFiles = false;
737  }
738 
744  public function enableConcatenateJavascript()
745  {
746  $this->concatenateJavascript = true;
747  }
748 
755  {
756  $this->concatenateJavascript = false;
757  }
758 
764  public function enableConcatenateCss()
765  {
766  $this->concatenateCss = true;
767  }
768 
774  public function disableConcatenateCss()
775  {
776  $this->concatenateCss = false;
777  }
778 
785  {
786  $this->removeLineBreaksFromTemplate = true;
787  }
788 
795  {
796  $this->removeLineBreaksFromTemplate = false;
797  }
798 
805  public function enableDebugMode()
806  {
807  $this->compressJavascript = false;
808  $this->compressCss = false;
809  $this->concatenateFiles = false;
810  $this->removeLineBreaksFromTemplate = false;
811  $this->enableExtJsDebug = true;
812  $this->enableJqueryDebug = true;
813  }
814 
815  /*****************************************************/
816  /* */
817  /* Public Getters */
818  /* */
819  /* */
820  /*****************************************************/
826  public function getTitle()
827  {
828  return $this->title;
829  }
830 
836  public function getCharSet()
837  {
838  return $this->charSet;
839  }
840 
846  public function getLanguage()
847  {
848  return $this->lang;
849  }
850 
856  public function getRenderXhtml()
857  {
858  return $this->renderXhtml;
859  }
860 
866  public function getHtmlTag()
867  {
868  return $this->htmlTag;
869  }
870 
876  public function getMetaCharsetTag()
877  {
878  return $this->metaCharsetTag;
879  }
880 
886  public function getHeadTag()
887  {
888  return $this->headTag;
889  }
890 
896  public function getFavIcon()
897  {
898  return $this->favIcon;
899  }
900 
906  public function getIconMimeType()
907  {
908  return $this->iconMimeType;
909  }
910 
916  public function getBaseUrl()
917  {
918  return $this->baseUrl;
919  }
920 
926  public function getTemplateFile()
927  {
928  return $this->templateFile;
929  }
930 
936  public function getMoveJsFromHeaderToFooter()
937  {
939  }
940 
946  public function getCompressJavascript()
947  {
949  }
950 
956  public function getCompressCss()
957  {
958  return $this->compressCss;
959  }
960 
966  public function getConcatenateFiles()
967  {
969  }
970 
976  public function getConcatenateJavascript()
977  {
979  }
980 
986  public function getConcatenateCss()
987  {
988  return $this->concatenateCss;
989  }
990 
997  {
999  }
1000 
1006  public function getBodyContent()
1007  {
1008  return $this->bodyContent;
1009  }
1010 
1016  public function getExtJsPath()
1017  {
1018  return $this->extJsPath;
1019  }
1020 
1026  public function getInlineLanguageLabels()
1027  {
1029  }
1030 
1037  {
1039  }
1040 
1041  /*****************************************************/
1042  /* */
1043  /* Public Functions to add Data */
1044  /* */
1045  /* */
1046  /*****************************************************/
1053  public function addMetaTag($meta)
1054  {
1055  if (!in_array($meta, $this->metaTags)) {
1056  $this->metaTags[] = $meta;
1057  }
1058  }
1059 
1066  public function addInlineComment($comment)
1067  {
1068  if (!in_array($comment, $this->inlineComments)) {
1069  $this->inlineComments[] = $comment;
1070  }
1071  }
1072 
1079  public function addHeaderData($data)
1080  {
1081  if (!in_array($data, $this->headerData)) {
1082  $this->headerData[] = $data;
1083  }
1084  }
1085 
1092  public function addFooterData($data)
1093  {
1094  if (!in_array($data, $this->footerData)) {
1095  $this->footerData[] = $data;
1096  }
1097  }
1098 
1114  public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1115  {
1116  if (!$type) {
1117  $type = 'text/javascript';
1118  }
1119  if (!in_array(strtolower($name), $this->jsLibs)) {
1120  $this->jsLibs[strtolower($name)] = [
1121  'file' => $file,
1122  'type' => $type,
1123  'section' => self::PART_HEADER,
1124  'compress' => $compress,
1125  'forceOnTop' => $forceOnTop,
1126  'allWrap' => $allWrap,
1127  'excludeFromConcatenation' => $excludeFromConcatenation,
1128  'splitChar' => $splitChar,
1129  'async' => $async,
1130  'integrity' => $integrity,
1131  ];
1132  }
1133  }
1134 
1150  public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = false, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1151  {
1152  if (!$type) {
1153  $type = 'text/javascript';
1154  }
1155  if (!in_array(strtolower($name), $this->jsLibs)) {
1156  $this->jsLibs[strtolower($name)] = [
1157  'file' => $file,
1158  'type' => $type,
1159  'section' => self::PART_FOOTER,
1160  'compress' => $compress,
1161  'forceOnTop' => $forceOnTop,
1162  'allWrap' => $allWrap,
1163  'excludeFromConcatenation' => $excludeFromConcatenation,
1164  'splitChar' => $splitChar,
1165  'async' => $async,
1166  'integrity' => $integrity,
1167  ];
1168  }
1169  }
1170 
1185  public function addJsFile($file, $type = 'text/javascript', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1186  {
1187  if (!$type) {
1188  $type = 'text/javascript';
1189  }
1190  if (!isset($this->jsFiles[$file])) {
1191  $this->jsFiles[$file] = [
1192  'file' => $file,
1193  'type' => $type,
1194  'section' => self::PART_HEADER,
1195  'compress' => $compress,
1196  'forceOnTop' => $forceOnTop,
1197  'allWrap' => $allWrap,
1198  'excludeFromConcatenation' => $excludeFromConcatenation,
1199  'splitChar' => $splitChar,
1200  'async' => $async,
1201  'integrity' => $integrity,
1202  ];
1203  }
1204  }
1205 
1220  public function addJsFooterFile($file, $type = 'text/javascript', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $async = false, $integrity = '')
1221  {
1222  if (!$type) {
1223  $type = 'text/javascript';
1224  }
1225  if (!isset($this->jsFiles[$file])) {
1226  $this->jsFiles[$file] = [
1227  'file' => $file,
1228  'type' => $type,
1229  'section' => self::PART_FOOTER,
1230  'compress' => $compress,
1231  'forceOnTop' => $forceOnTop,
1232  'allWrap' => $allWrap,
1233  'excludeFromConcatenation' => $excludeFromConcatenation,
1234  'splitChar' => $splitChar,
1235  'async' => $async,
1236  'integrity' => $integrity,
1237  ];
1238  }
1239  }
1240 
1250  public function addJsInlineCode($name, $block, $compress = true, $forceOnTop = false)
1251  {
1252  if (!isset($this->jsInline[$name]) && !empty($block)) {
1253  $this->jsInline[$name] = [
1254  'code' => $block . LF,
1255  'section' => self::PART_HEADER,
1256  'compress' => $compress,
1257  'forceOnTop' => $forceOnTop
1258  ];
1259  }
1260  }
1261 
1271  public function addJsFooterInlineCode($name, $block, $compress = true, $forceOnTop = false)
1272  {
1273  if (!isset($this->jsInline[$name]) && !empty($block)) {
1274  $this->jsInline[$name] = [
1275  'code' => $block . LF,
1276  'section' => self::PART_FOOTER,
1277  'compress' => $compress,
1278  'forceOnTop' => $forceOnTop
1279  ];
1280  }
1281  }
1282 
1290  public function addExtOnReadyCode($block, $forceOnTop = false)
1291  {
1292  if (!in_array($block, $this->extOnReadyCode)) {
1293  if ($forceOnTop) {
1294  array_unshift($this->extOnReadyCode, $block);
1295  } else {
1296  $this->extOnReadyCode[] = $block;
1297  }
1298  }
1299  }
1300 
1307  public function addExtDirectCode(array $filterNamespaces = [])
1308  {
1309  if ($this->extDirectCodeAdded) {
1310  return;
1311  }
1312  $this->extDirectCodeAdded = true;
1313  if (empty($filterNamespaces)) {
1314  $filterNamespaces = ['TYPO3'];
1315  }
1316  // @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8
1317  // add compatibility mapping for the old flashmessage API
1318  $this->addJsFile(GeneralUtility::resolveBackPath($this->backPath .
1319  ExtensionManagementUtility::extRelPath('backend') . 'Resources/Public/JavaScript/flashmessage_compatibility.js'));
1320 
1321  // Add language labels for ExtDirect
1322  if (TYPO3_MODE === 'FE') {
1324  'extDirect_timeoutHeader' => $this->getTypoScriptFrontendController()->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutHeader'),
1325  'extDirect_timeoutMessage' => $this->getTypoScriptFrontendController()->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutMessage')
1326  ]);
1327  } else {
1329  'extDirect_timeoutHeader' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutHeader'),
1330  'extDirect_timeoutMessage' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_misc.xlf:extDirect_timeoutMessage')
1331  ]);
1332  }
1333 
1334  $token = ($api = '');
1335  if (TYPO3_MODE === 'BE') {
1337  $token = $formprotection->generateToken('extDirect');
1338 
1339  // Debugger Console strings
1340  $this->addInlineLanguageLabelFile('EXT:core/Resources/Private/Language/debugger.xlf');
1341  }
1343  $extDirect = GeneralUtility::makeInstance(\TYPO3\CMS\Core\ExtDirect\ExtDirectApi::class);
1344  $api = $extDirect->getApiPhp($filterNamespaces);
1345  if ($api) {
1346  $this->addJsInlineCode('TYPO3ExtDirectAPI', $api, false);
1347  }
1348  // Note: we need to iterate thru the object, because the addProvider method
1349  // does this only with multiple arguments
1350  $this->addExtOnReadyCode('
1351  (function() {
1352  TYPO3.ExtDirectToken = "' . $token . '";
1353  for (var api in Ext.app.ExtDirectAPI) {
1354  var provider = Ext.Direct.addProvider(Ext.app.ExtDirectAPI[api]);
1355  provider.on("beforecall", function(provider, transaction, meta) {
1356  if (transaction.data) {
1357  transaction.data[transaction.data.length] = TYPO3.ExtDirectToken;
1358  } else {
1359  transaction.data = [TYPO3.ExtDirectToken];
1360  }
1361  });
1362 
1363  provider.on("call", function(provider, transaction, meta) {
1364  if (transaction.isForm) {
1365  transaction.params.securityToken = TYPO3.ExtDirectToken;
1366  }
1367  });
1368  }
1369  })();
1370 
1371  var extDirectDebug = function(message, header, group) {
1372  var DebugConsole = null;
1373 
1374  if (top && top.TYPO3 && typeof top.TYPO3.DebugConsole === "object") {
1375  DebugConsole = top.TYPO3.DebugConsole;
1376  } else if (typeof TYPO3 === "object" && typeof TYPO3.DebugConsole === "object") {
1377  DebugConsole = TYPO3.DebugConsole;
1378  }
1379 
1380  if (DebugConsole !== null) {
1381  DebugConsole.add(message, header, group);
1382  } else if (typeof console === "object") {
1383  console.log(message);
1384  } else {
1385  document.write(message);
1386  }
1387  };
1388 
1389  Ext.Direct.on("exception", function(event) {
1390  if (event.code === Ext.Direct.exceptions.TRANSPORT && !event.where) {
1391  top.TYPO3.Notification.error(
1392  TYPO3.l10n.localize("extDirect_timeoutHeader"),
1393  TYPO3.l10n.localize("extDirect_timeoutMessage")
1394  );
1395  } else {
1396  var backtrace = "";
1397  if (event.code === "parse") {
1398  extDirectDebug(
1399  "<p>" + event.xhr.responseText + "<\\/p>",
1400  event.type,
1401  "ExtDirect - Exception"
1402  );
1403  } else if (event.code === "router") {
1404  top.TYPO3.Notification.error(
1405  event.code,
1406  event.message
1407  );
1408  } else if (event.where) {
1409  backtrace = "<p style=\\"margin-top: 20px;\\">" +
1410  "<strong>Backtrace:<\\/strong><br \\/>" +
1411  event.where.replace(/#/g, "<br \\/>#") +
1412  "<\\/p>";
1413  extDirectDebug(
1414  "<p>" + event.message + "<\\/p>" + backtrace,
1415  event.method,
1416  "ExtDirect - Exception"
1417  );
1418  }
1419 
1420 
1421  }
1422  });
1423 
1424  Ext.Direct.on("event", function(event, provider) {
1425  if (typeof event.debug !== "undefined" && event.debug !== "") {
1426  extDirectDebug(event.debug, event.method, "ExtDirect - Debug");
1427  }
1428  });
1429  ', true);
1430  }
1431 
1446  public function addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|')
1447  {
1448  if (!isset($this->cssFiles[$file])) {
1449  $this->cssFiles[$file] = [
1450  'file' => $file,
1451  'rel' => $rel,
1452  'media' => $media,
1453  'title' => $title,
1454  'compress' => $compress,
1455  'forceOnTop' => $forceOnTop,
1456  'allWrap' => $allWrap,
1457  'excludeFromConcatenation' => $excludeFromConcatenation,
1458  'splitChar' => $splitChar
1459  ];
1460  }
1461  }
1462 
1477  public function addCssLibrary($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|')
1478  {
1479  if (!isset($this->cssLibs[$file])) {
1480  $this->cssLibs[$file] = [
1481  'file' => $file,
1482  'rel' => $rel,
1483  'media' => $media,
1484  'title' => $title,
1485  'compress' => $compress,
1486  'forceOnTop' => $forceOnTop,
1487  'allWrap' => $allWrap,
1488  'excludeFromConcatenation' => $excludeFromConcatenation,
1489  'splitChar' => $splitChar
1490  ];
1491  }
1492  }
1493 
1503  public function addCssInlineBlock($name, $block, $compress = false, $forceOnTop = false)
1504  {
1505  if (!isset($this->cssInline[$name]) && !empty($block)) {
1506  $this->cssInline[$name] = [
1507  'code' => $block,
1508  'compress' => $compress,
1509  'forceOnTop' => $forceOnTop
1510  ];
1511  }
1512  }
1513 
1523  public function loadJquery($version = null, $source = null, $namespace = self::JQUERY_NAMESPACE_DEFAULT)
1524  {
1525  // Set it to the version that is shipped with the TYPO3 core
1526  if ($version === null || $version === 'latest') {
1527  $version = self::JQUERY_VERSION_LATEST;
1528  }
1529  // Check if the source is set, otherwise set it to "default"
1530  if ($source === null) {
1531  $source = 'local';
1532  }
1533  if ($source === 'local' && !in_array($version, $this->availableLocalJqueryVersions)) {
1534  throw new \UnexpectedValueException('The requested jQuery version is not available in the local filesystem.', 1341505305);
1535  }
1536  if (!preg_match('/^[a-zA-Z0-9]+$/', $namespace)) {
1537  throw new \UnexpectedValueException('The requested namespace contains non alphanumeric characters.', 1341571604);
1538  }
1539  $this->jQueryVersions[$namespace] = [
1540  'version' => $version,
1541  'source' => $source
1542  ];
1543  }
1544 
1553  public function loadRequireJs()
1554  {
1555 
1556  // load all paths to map to package names / namespaces
1557  if (empty($this->requireJsConfig)) {
1558  // In order to avoid browser caching of JS files, adding a GET parameter to the files loaded via requireJS
1559  if (GeneralUtility::getApplicationContext()->isDevelopment()) {
1560  $this->requireJsConfig['urlArgs'] = 'bust=' . $GLOBALS['EXEC_TIME'];
1561  } else {
1562  $this->requireJsConfig['urlArgs'] = 'bust=' . GeneralUtility::hmac(TYPO3_version . PATH_site);
1563  }
1564  $coreRelPath = ExtensionManagementUtility::extRelPath('core');
1565  // first, load all paths for the namespaces, and configure contrib libs.
1566  $this->requireJsConfig['paths'] = [
1567  'jquery-ui' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/jquery-ui',
1568  'datatables' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/jquery.dataTables',
1569  'nprogress' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/nprogress',
1570  'moment' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/moment',
1571  'cropper' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/cropper.min',
1572  'imagesloaded' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/imagesloaded.pkgd.min',
1573  'bootstrap' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/bootstrap/bootstrap',
1574  'twbs/bootstrap-datetimepicker' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/bootstrap-datetimepicker',
1575  'autosize' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/autosize',
1576  'taboverride' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/taboverride.min',
1577  'twbs/bootstrap-slider' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/bootstrap-slider.min',
1578  'jquery/autocomplete' => $this->backPath . $coreRelPath . 'Resources/Public/JavaScript/Contrib/jquery.autocomplete',
1579  ];
1580  // get all extensions that are loaded
1582  foreach ($loadedExtensions as $packageName) {
1583  $fullJsPath = 'EXT:' . $packageName . '/Resources/Public/JavaScript/';
1584  $fullJsPath = GeneralUtility::getFileAbsFileName($fullJsPath);
1585  $fullJsPath = \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath(PATH_typo3, $fullJsPath);
1586  $fullJsPath = rtrim($fullJsPath, '/');
1587  if ($fullJsPath) {
1588  $this->requireJsConfig['paths']['TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($packageName)] = $this->backPath . $fullJsPath;
1589  }
1590  }
1591 
1592  // check if additional AMD modules need to be loaded if a single AMD module is initialized
1593  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules'])) {
1594  $this->addInlineSettingArray('RequireJS.PostInitializationModules', $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['RequireJS']['postInitializationModules']);
1595  }
1596  }
1597 
1598  $this->addRequireJs = true;
1599  }
1600 
1614  public function addRequireJsConfiguration(array $configuration)
1615  {
1616  if (TYPO3_MODE === 'BE') {
1617  // Load RequireJS in backend context at first. Doing this in FE could break the output
1618  $this->loadRequireJs();
1619  }
1620  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($this->requireJsConfig, $configuration);
1621  }
1622 
1640  public function loadRequireJsModule($mainModuleName, $callBackFunction = null)
1641  {
1642  $inlineCodeKey = $mainModuleName;
1643  // make sure requireJS is initialized
1644  $this->loadRequireJs();
1645 
1646  // execute the main module, and load a possible callback function
1647  $javaScriptCode = 'require(["' . $mainModuleName . '"]';
1648  if ($callBackFunction !== null) {
1649  $inlineCodeKey .= sha1($callBackFunction);
1650  $javaScriptCode .= ', ' . $callBackFunction;
1651  }
1652  $javaScriptCode .= ');';
1653  $this->addJsInlineCode('RequireJS-Module-' . $inlineCodeKey, $javaScriptCode);
1654  }
1655 
1663  public function loadExtJS($css = true, $theme = true)
1664  {
1665  $this->addExtJS = true;
1666  $this->extJStheme = $theme;
1667  $this->extJScss = $css;
1668  }
1669 
1675  public function enableExtJsDebug()
1676  {
1677  $this->enableExtJsDebug = true;
1678  }
1679 
1689  public function addInlineLanguageLabel($key, $value)
1690  {
1691  $this->inlineLanguageLabels[$key] = $value;
1692  }
1693 
1704  public function addInlineLanguageLabelArray(array $array, $parseWithLanguageService = false)
1705  {
1706  if ($parseWithLanguageService === true) {
1707  foreach ($array as $key => $value) {
1708  if (TYPO3_MODE === 'FE') {
1709  $array[$key] = $this->getTypoScriptFrontendController()->sL($value);
1710  } else {
1711  $array[$key] = $this->getLanguageService()->sL($value);
1712  }
1713  }
1714  }
1715 
1716  $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $array);
1717  }
1718 
1728  public function addInlineLanguageLabelFile($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0)
1729  {
1730  $index = md5($fileRef . $selectionPrefix . $stripFromSelectionName);
1731  if ($fileRef && !isset($this->inlineLanguageLabelFiles[$index])) {
1732  $this->inlineLanguageLabelFiles[$index] = [
1733  'fileRef' => $fileRef,
1734  'selectionPrefix' => $selectionPrefix,
1735  'stripFromSelectionName' => $stripFromSelectionName,
1736  'errorMode' => $errorMode
1737  ];
1738  }
1739  }
1740 
1751  public function addInlineSetting($namespace, $key, $value)
1752  {
1753  if ($namespace) {
1754  if (strpos($namespace, '.')) {
1755  $parts = explode('.', $namespace);
1757  foreach ($parts as $part) {
1758  $a = &$a[$part];
1759  }
1760  $a[$key] = $value;
1761  } else {
1762  $this->inlineSettings[$namespace][$key] = $value;
1763  }
1764  } else {
1765  $this->inlineSettings[$key] = $value;
1766  }
1767  }
1768 
1779  public function addInlineSettingArray($namespace, array $array)
1780  {
1781  if ($namespace) {
1782  if (strpos($namespace, '.')) {
1783  $parts = explode('.', $namespace);
1785  foreach ($parts as $part) {
1786  $a = &$a[$part];
1787  }
1788  $a = array_merge((array)$a, $array);
1789  } else {
1790  $this->inlineSettings[$namespace] = array_merge((array)$this->inlineSettings[$namespace], $array);
1791  }
1792  } else {
1793  $this->inlineSettings = array_merge($this->inlineSettings, $array);
1794  }
1795  }
1796 
1803  public function addBodyContent($content)
1804  {
1805  $this->bodyContent .= $content;
1806  }
1807 
1808  /*****************************************************/
1809  /* */
1810  /* Render Functions */
1811  /* */
1812  /*****************************************************/
1819  public function render($part = self::PART_COMPLETE)
1820  {
1821  $this->prepareRendering();
1823  $metaTags = implode(LF, $this->metaTags);
1825  $template = $this->getTemplateForPart($part);
1826 
1827  // The page renderer needs a full reset, even when only rendering one part of the page
1828  // This means that you can only register footer files *after* the header has been already rendered.
1829  // In case you render the footer part first, header files can only be added *after* the footer has been rendered
1830  $this->reset();
1831  $templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
1832  return trim($templateService->substituteMarkerArray($template, $markerArray, '###|###'));
1833  }
1834 
1842  public function renderPageWithUncachedObjects($substituteHash)
1843  {
1844  $this->prepareRendering();
1845  $markerArray = $this->getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash);
1846  $template = $this->getTemplateForPart(self::PART_COMPLETE);
1847  $templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
1848  return trim($templateService->substituteMarkerArray($template, $markerArray, '###|###'));
1849  }
1850 
1860  public function renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash)
1861  {
1862  $this->prepareRendering();
1864  $title = $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '';
1865  $markerArray = [
1866  '<!-- ###TITLE' . $substituteHash . '### -->' => $title,
1867  '<!-- ###CSS_LIBS' . $substituteHash . '### -->' => $cssLibs,
1868  '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->' => $cssFiles,
1869  '<!-- ###CSS_INLINE' . $substituteHash . '### -->' => $cssInline,
1870  '<!-- ###JS_INLINE' . $substituteHash . '### -->' => $jsInline,
1871  '<!-- ###JS_INCLUDE' . $substituteHash . '### -->' => $jsFiles,
1872  '<!-- ###JS_LIBS' . $substituteHash . '### -->' => $jsLibs,
1873  '<!-- ###META' . $substituteHash . '### -->' => implode(LF, $this->metaTags),
1874  '<!-- ###HEADERDATA' . $substituteHash . '### -->' => implode(LF, $this->headerData),
1875  '<!-- ###FOOTERDATA' . $substituteHash . '### -->' => implode(LF, $this->footerData),
1876  '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->' => $jsFooterLibs,
1877  '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->' => $jsFooterFiles,
1878  '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->' => $jsFooterInline
1879  ];
1880  foreach ($markerArray as $placeHolder => $content) {
1881  $cachedPageContent = str_replace($placeHolder, $content, $cachedPageContent);
1882  }
1883  $this->reset();
1884  return $cachedPageContent;
1885  }
1886 
1894  protected function prepareRendering()
1895  {
1896  if ($this->getRenderXhtml()) {
1897  $this->endingSlash = ' /';
1898  } else {
1899  $this->metaCharsetTag = str_replace(' />', '>', $this->metaCharsetTag);
1900  $this->baseUrlTag = str_replace(' />', '>', $this->baseUrlTag);
1901  $this->shortcutTag = str_replace(' />', '>', $this->shortcutTag);
1902  $this->endingSlash = '';
1903  }
1904  }
1905 
1911  protected function renderJavaScriptAndCss()
1912  {
1913  $this->executePreRenderHook();
1914  $mainJsLibs = $this->renderMainJavaScriptLibraries();
1915  if ($this->concatenateFiles || $this->concatenateJavascript || $this->concatenateCss) {
1916  // Do the file concatenation
1917  $this->doConcatenate();
1918  }
1919  if ($this->compressCss || $this->compressJavascript) {
1920  // Do the file compression
1921  $this->doCompress();
1922  }
1924  $cssLibs = $this->renderCssLibraries();
1925  $cssFiles = $this->renderCssFiles();
1926  $cssInline = $this->renderCssInline();
1928  list($jsFiles, $jsFooterFiles) = $this->renderJavaScriptFiles();
1930  $jsLibs = $mainJsLibs . $jsLibs;
1931  if ($this->moveJsFromHeaderToFooter) {
1933  $jsLibs = '';
1935  $jsFiles = '';
1937  $jsInline = '';
1938  }
1941  }
1942 
1959  {
1960  $markerArray = [
1961  'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
1962  'HTMLTAG' => $this->htmlTag,
1963  'HEADTAG' => $this->headTag,
1964  'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
1965  'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
1966  'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
1967  'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
1968  'CSS_LIBS' => $cssLibs,
1969  'CSS_INCLUDE' => $cssFiles,
1970  'CSS_INLINE' => $cssInline,
1971  'JS_INLINE' => $jsInline,
1972  'JS_INCLUDE' => $jsFiles,
1973  'JS_LIBS' => $jsLibs,
1974  'TITLE' => $this->title ? str_replace('|', htmlspecialchars($this->title), $this->titleTag) : '',
1975  'META' => $metaTags,
1976  'HEADERDATA' => $this->headerData ? implode(LF, $this->headerData) : '',
1977  'FOOTERDATA' => $this->footerData ? implode(LF, $this->footerData) : '',
1978  'JS_LIBS_FOOTER' => $jsFooterLibs,
1979  'JS_INCLUDE_FOOTER' => $jsFooterFiles,
1980  'JS_INLINE_FOOTER' => $jsFooterInline,
1981  'BODY' => $this->bodyContent
1982  ];
1983  $markerArray = array_map('trim', $markerArray);
1984  return $markerArray;
1985  }
1986 
1993  protected function getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash)
1994  {
1995  $markerArray = [
1996  'XMLPROLOG_DOCTYPE' => $this->xmlPrologAndDocType,
1997  'HTMLTAG' => $this->htmlTag,
1998  'HEADTAG' => $this->headTag,
1999  'METACHARSET' => $this->charSet ? str_replace('|', htmlspecialchars($this->charSet), $this->metaCharsetTag) : '',
2000  'INLINECOMMENT' => $this->inlineComments ? LF . LF . '<!-- ' . LF . implode(LF, $this->inlineComments) . '-->' . LF . LF : '',
2001  'BASEURL' => $this->baseUrl ? str_replace('|', $this->baseUrl, $this->baseUrlTag) : '',
2002  'SHORTCUT' => $this->favIcon ? sprintf($this->shortcutTag, htmlspecialchars($this->favIcon), $this->iconMimeType) : '',
2003  'META' => '<!-- ###META' . $substituteHash . '### -->',
2004  'BODY' => $this->bodyContent,
2005  'TITLE' => '<!-- ###TITLE' . $substituteHash . '### -->',
2006  'CSS_LIBS' => '<!-- ###CSS_LIBS' . $substituteHash . '### -->',
2007  'CSS_INCLUDE' => '<!-- ###CSS_INCLUDE' . $substituteHash . '### -->',
2008  'CSS_INLINE' => '<!-- ###CSS_INLINE' . $substituteHash . '### -->',
2009  'JS_INLINE' => '<!-- ###JS_INLINE' . $substituteHash . '### -->',
2010  'JS_INCLUDE' => '<!-- ###JS_INCLUDE' . $substituteHash . '### -->',
2011  'JS_LIBS' => '<!-- ###JS_LIBS' . $substituteHash . '### -->',
2012  'HEADERDATA' => '<!-- ###HEADERDATA' . $substituteHash . '### -->',
2013  'FOOTERDATA' => '<!-- ###FOOTERDATA' . $substituteHash . '### -->',
2014  'JS_LIBS_FOOTER' => '<!-- ###JS_LIBS_FOOTER' . $substituteHash . '### -->',
2015  'JS_INCLUDE_FOOTER' => '<!-- ###JS_INCLUDE_FOOTER' . $substituteHash . '### -->',
2016  'JS_INLINE_FOOTER' => '<!-- ###JS_INLINE_FOOTER' . $substituteHash . '### -->'
2017  ];
2018  $markerArray = array_map('trim', $markerArray);
2019  return $markerArray;
2020  }
2021 
2028  protected function getTemplateForPart($part)
2029  {
2030  $templateFile = GeneralUtility::getFileAbsFileName($this->templateFile, true);
2032  if ($this->removeLineBreaksFromTemplate) {
2033  $template = strtr($template, [LF => '', CR => '']);
2034  }
2035  if ($part !== self::PART_COMPLETE) {
2036  $templatePart = explode('###BODY###', $template);
2037  $template = $templatePart[$part - 1];
2038  }
2039  return $template;
2040  }
2041 
2048  protected function renderMainJavaScriptLibraries()
2049  {
2050  $out = '';
2051 
2052  // Include RequireJS
2053  if ($this->addRequireJs) {
2054  // load the paths of the requireJS configuration
2055  $out .= GeneralUtility::wrapJS('var require = ' . json_encode($this->requireJsConfig)) . LF;
2056  // directly after that, include the require.js file
2057  $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->requireJsPath . 'require.js')) . '" type="text/javascript"></script>' . LF;
2058  }
2059 
2060  // Include jQuery Core for each namespace, depending on the version and source
2061  if (!empty($this->jQueryVersions)) {
2062  foreach ($this->jQueryVersions as $namespace => $jQueryVersion) {
2063  $out .= $this->renderJqueryScriptTag($jQueryVersion['version'], $jQueryVersion['source'], $namespace);
2064  }
2065  }
2066  // Include extJS
2067  if ($this->addExtJS) {
2068  // Use the base adapter all the time
2069  $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extJsPath . 'adapter/ext-base' . ($this->enableExtJsDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2070  $out .= '<script src="' . $this->processJsFile(($this->backPath . $this->extJsPath . 'ext-all' . ($this->enableExtJsDebug ? '-debug' : '') . '.js')) . '" type="text/javascript"></script>' . LF;
2071  // Add extJS localization
2072  // Load standard ISO mapping and modify for use with ExtJS
2073  $localeMap = $this->locales->getIsoMapping();
2074  $localeMap[''] = 'en';
2075  $localeMap['default'] = 'en';
2076  // Greek
2077  $localeMap['gr'] = 'el_GR';
2078  // Norwegian Bokmaal
2079  $localeMap['no'] = 'no_BO';
2080  // Swedish
2081  $localeMap['se'] = 'se_SV';
2082  $extJsLang = isset($localeMap[$this->lang]) ? $localeMap[$this->lang] : $this->lang;
2083  // @todo autoconvert file from UTF8 to current BE charset if necessary!!!!
2084  $extJsLocaleFile = $this->extJsPath . 'locale/ext-lang-' . $extJsLang . '.js';
2085  if (file_exists(PATH_typo3 . $extJsLocaleFile)) {
2086  $out .= '<script src="' . $this->processJsFile(($this->backPath . $extJsLocaleFile)) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2087  }
2088  // Remove extjs from JScodeLibArray
2089  unset($this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all.js'], $this->jsFiles[$this->backPath . $this->extJsPath . 'ext-all-debug.js']);
2090  }
2092  if (TYPO3_MODE === 'BE') {
2093  $this->addAjaxUrlsToInlineSettings();
2094  }
2095  $inlineSettings = $this->inlineLanguageLabels ? 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' : '';
2096  $inlineSettings .= $this->inlineSettings ? 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' : '';
2097  if ($this->addExtJS) {
2098  // Set clear.gif, move it on top, add handler code
2099  $code = '';
2100  if (!empty($this->extOnReadyCode)) {
2101  foreach ($this->extOnReadyCode as $block) {
2102  $code .= $block;
2103  }
2104  }
2105  $clearGifPath = htmlspecialchars(GeneralUtility::locationHeaderUrl($this->backPath . ExtensionManagementUtility::extRelPath('backend') . 'Resources/Public/Images/clear.gif'));
2106  $out .= $this->inlineJavascriptWrap[0] . '
2107  Ext.ns("TYPO3");
2108  Ext.BLANK_IMAGE_URL = "' . $clearGifPath . '";
2109  Ext.SSL_SECURE_URL = "' . $clearGifPath . '";' . LF
2110  . $inlineSettings
2111  . 'Ext.onReady(function() {'
2112  . $code
2113  . ' });'
2114  . $this->inlineJavascriptWrap[1];
2115  $this->extOnReadyCode = [];
2116  // Include TYPO3.l10n object
2117  if (TYPO3_MODE === 'BE') {
2118  $out .= '<script src="' . $this->processJsFile(($this->backPath . ExtensionManagementUtility::extRelPath('lang') . 'Resources/Public/JavaScript/Typo3Lang.js')) . '" type="text/javascript" charset="utf-8"></script>' . LF;
2119  }
2120  if ($this->extJScss) {
2121  if (isset($GLOBALS['TBE_STYLES']['extJS']['all'])) {
2122  $this->addCssLibrary($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['all'], 'stylesheet', 'all', '', true);
2123  } else {
2124  $this->addCssLibrary($this->backPath . $this->extJsPath . 'resources/css/ext-all-notheme.css', 'stylesheet', 'all', '', true);
2125  }
2126  }
2127  if ($this->extJStheme) {
2128  if (isset($GLOBALS['TBE_STYLES']['extJS']['theme'])) {
2129  $this->addCssLibrary($this->backPath . $GLOBALS['TBE_STYLES']['extJS']['theme'], 'stylesheet', 'all', '', true);
2130  } else {
2131  $this->addCssLibrary($this->backPath . $this->extJsPath . 'resources/css/xtheme-blue.css', 'stylesheet', 'all', '', true);
2132  }
2133  }
2134  } else {
2135  // no extJS loaded, but still inline settings
2136  if ($inlineSettings !== '') {
2137  // make sure the global TYPO3 is available
2138  $inlineSettings = 'var TYPO3 = TYPO3 || {};' . CRLF . $inlineSettings;
2139  $out .= $this->inlineJavascriptWrap[0] . $inlineSettings . $this->inlineJavascriptWrap[1];
2140  // Add language module only if also jquery is guaranteed to be there
2141  if (TYPO3_MODE === 'BE' && !empty($this->jQueryVersions)) {
2142  $this->loadRequireJsModule('TYPO3/CMS/Lang/Lang');
2143  }
2144  }
2145  }
2146  return $out;
2147  }
2148 
2152  protected function loadJavaScriptLanguageStrings()
2153  {
2154  if (!empty($this->inlineLanguageLabelFiles)) {
2155  foreach ($this->inlineLanguageLabelFiles as $languageLabelFile) {
2156  $this->includeLanguageFileForInline($languageLabelFile['fileRef'], $languageLabelFile['selectionPrefix'], $languageLabelFile['stripFromSelectionName'], $languageLabelFile['errorMode']);
2157  }
2158  }
2159  $this->inlineLanguageLabelFiles = [];
2160  // Convert labels/settings back to UTF-8 since json_encode() only works with UTF-8:
2161  if (TYPO3_MODE === 'FE' && $this->getCharSet() !== 'utf-8') {
2162  if ($this->inlineLanguageLabels) {
2163  $this->csConvObj->convArray($this->inlineLanguageLabels, $this->getCharSet(), 'utf-8');
2164  }
2165  if ($this->inlineSettings) {
2166  $this->csConvObj->convArray($this->inlineSettings, $this->getCharSet(), 'utf-8');
2167  }
2168  }
2169  }
2170 
2174  protected function addAjaxUrlsToInlineSettings()
2175  {
2176  $ajaxUrls = [];
2177  foreach ($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'] as $ajaxHandler => $_) {
2178  $ajaxUrls[$ajaxHandler] = BackendUtility::getAjaxUrl($ajaxHandler);
2179  }
2180 
2181  // also add the ajax-based routes
2183  $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
2185  $router = GeneralUtility::makeInstance(Router::class);
2186  $routes = $router->getRoutes();
2187  foreach ($routes as $routeIdentifier => $route) {
2188  if ($route->getOption('ajax')) {
2189  $uri = (string)$uriBuilder->buildUriFromRoute($routeIdentifier);
2190  // use the shortened value in order to use this in JavaScript
2191  $routeIdentifier = str_replace('ajax_', '', $routeIdentifier);
2192  $ajaxUrls[$routeIdentifier] = $uri;
2193  }
2194  }
2195 
2196  $this->inlineSettings['ajaxUrls'] = $ajaxUrls;
2197  }
2198 
2207  protected function renderJqueryScriptTag($version, $source, $namespace)
2208  {
2209  switch (true) {
2210  case isset($this->jQueryCdnUrls[$source]):
2211  if ($this->enableJqueryDebug) {
2212  $minifyPart = '';
2213  } else {
2214  $minifyPart = '.min';
2215  }
2216  $jQueryFileName = sprintf($this->jQueryCdnUrls[$source], $version, $minifyPart);
2217  break;
2218  case $source === 'local':
2219  $jQueryFileName = $this->backPath . $this->jQueryPath . 'jquery-' . rawurlencode($version);
2220  if ($this->enableJqueryDebug) {
2221  $jQueryFileName .= '.js';
2222  } else {
2223  $jQueryFileName .= '.min.js';
2224  }
2225  break;
2226  default:
2227  $jQueryFileName = $source;
2228  }
2229  // Include the jQuery Core
2230  $scriptTag = '<script src="' . htmlspecialchars($jQueryFileName) . '" type="text/javascript"></script>' . LF;
2231  // Set the noConflict mode to be available via "TYPO3.jQuery" in all installations
2232  switch ($namespace) {
2233  case self::JQUERY_NAMESPACE_DEFAULT_NOCONFLICT:
2234  $scriptTag .= GeneralUtility::wrapJS('jQuery.noConflict();') . LF;
2235  break;
2236  case self::JQUERY_NAMESPACE_NONE:
2237  break;
2238  case self::JQUERY_NAMESPACE_DEFAULT:
2239 
2240  default:
2241  $scriptTag .= GeneralUtility::wrapJS('var TYPO3 = TYPO3 || {}; TYPO3.' . $namespace . ' = jQuery.noConflict(true);') . LF;
2242  }
2243  return $scriptTag;
2244  }
2245 
2251  protected function renderCssLibraries()
2252  {
2253  $cssFiles = '';
2254  if (!empty($this->cssLibs)) {
2255  foreach ($this->cssLibs as $file => $properties) {
2256  $file = GeneralUtility::resolveBackPath($file);
2258  $tag = '<link rel="' . htmlspecialchars($properties['rel'])
2259  . '" type="text/css" href="' . htmlspecialchars($file)
2260  . '" media="' . htmlspecialchars($properties['media']) . '"'
2261  . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
2262  . $this->endingSlash . '>';
2263  if ($properties['allWrap']) {
2264  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2265  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2266  }
2267  $tag .= LF;
2268  if ($properties['forceOnTop']) {
2269  $cssFiles = $tag . $cssFiles;
2270  } else {
2271  $cssFiles .= $tag;
2272  }
2273  }
2274  }
2275  return $cssFiles;
2276  }
2277 
2283  protected function renderCssFiles()
2284  {
2285  $cssFiles = '';
2286  if (!empty($this->cssFiles)) {
2287  foreach ($this->cssFiles as $file => $properties) {
2288  $file = GeneralUtility::resolveBackPath($file);
2290  $tag = '<link rel="' . htmlspecialchars($properties['rel'])
2291  . '" type="text/css" href="' . htmlspecialchars($file)
2292  . '" media="' . htmlspecialchars($properties['media']) . '"'
2293  . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
2294  . $this->endingSlash . '>';
2295  if ($properties['allWrap']) {
2296  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2297  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2298  }
2299  $tag .= LF;
2300  if ($properties['forceOnTop']) {
2301  $cssFiles = $tag . $cssFiles;
2302  } else {
2303  $cssFiles .= $tag;
2304  }
2305  }
2306  }
2307  return $cssFiles;
2308  }
2309 
2315  protected function renderCssInline()
2316  {
2317  $cssInline = '';
2318  if (!empty($this->cssInline)) {
2319  foreach ($this->cssInline as $name => $properties) {
2320  $cssCode = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2321  if ($properties['forceOnTop']) {
2322  $cssInline = $cssCode . $cssInline;
2323  } else {
2324  $cssInline .= $cssCode;
2325  }
2326  }
2327  $cssInline = $this->inlineCssWrap[0] . $cssInline . $this->inlineCssWrap[1];
2328  }
2329  return $cssInline;
2330  }
2331 
2338  {
2339  $jsLibs = '';
2340  $jsFooterLibs = '';
2341  if (!empty($this->jsLibs)) {
2342  foreach ($this->jsLibs as $properties) {
2343  $properties['file'] = GeneralUtility::resolveBackPath($properties['file']);
2344  $properties['file'] = GeneralUtility::createVersionNumberedFilename($properties['file']);
2345  $async = ($properties['async']) ? ' async="async"' : '';
2346  $integrity = ($properties['integrity']) ? ' integrity="' . htmlspecialchars($properties['integrity']) . '" crossorigin="anonymous"' : '';
2347  $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . $integrity . '></script>';
2348  if ($properties['allWrap']) {
2349  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2350  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2351  }
2352  $tag .= LF;
2353  if ($properties['forceOnTop']) {
2354  if ($properties['section'] === self::PART_HEADER) {
2355  $jsLibs = $tag . $jsLibs;
2356  } else {
2357  $jsFooterLibs = $tag . $jsFooterLibs;
2358  }
2359  } else {
2360  if ($properties['section'] === self::PART_HEADER) {
2361  $jsLibs .= $tag;
2362  } else {
2363  $jsFooterLibs .= $tag;
2364  }
2365  }
2366  }
2367  }
2368  if ($this->moveJsFromHeaderToFooter) {
2370  $jsLibs = '';
2371  }
2372  return [$jsLibs, $jsFooterLibs];
2373  }
2374 
2380  protected function renderJavaScriptFiles()
2381  {
2382  $jsFiles = '';
2383  $jsFooterFiles = '';
2384  if (!empty($this->jsFiles)) {
2385  foreach ($this->jsFiles as $file => $properties) {
2386  $file = GeneralUtility::resolveBackPath($file);
2388  $async = ($properties['async']) ? ' async="async"' : '';
2389  $integrity = ($properties['integrity']) ? ' integrity="' . htmlspecialchars($properties['integrity']) . '" crossorigin="anonymous"' : '';
2390  $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . $integrity . '></script>';
2391  if ($properties['allWrap']) {
2392  $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
2393  $tag = $wrapArr[0] . $tag . $wrapArr[1];
2394  }
2395  $tag .= LF;
2396  if ($properties['forceOnTop']) {
2397  if ($properties['section'] === self::PART_HEADER) {
2398  $jsFiles = $tag . $jsFiles;
2399  } else {
2400  $jsFooterFiles = $tag . $jsFooterFiles;
2401  }
2402  } else {
2403  if ($properties['section'] === self::PART_HEADER) {
2404  $jsFiles .= $tag;
2405  } else {
2406  $jsFooterFiles .= $tag;
2407  }
2408  }
2409  }
2410  }
2411  if ($this->moveJsFromHeaderToFooter) {
2413  $jsFiles = '';
2414  }
2415  return [$jsFiles, $jsFooterFiles];
2416  }
2417 
2423  protected function renderInlineJavaScript()
2424  {
2425  $jsInline = '';
2426  $jsFooterInline = '';
2427  if (!empty($this->jsInline)) {
2428  foreach ($this->jsInline as $name => $properties) {
2429  $jsCode = '/*' . htmlspecialchars($name) . '*/' . LF . $properties['code'] . LF;
2430  if ($properties['forceOnTop']) {
2431  if ($properties['section'] === self::PART_HEADER) {
2432  $jsInline = $jsCode . $jsInline;
2433  } else {
2434  $jsFooterInline = $jsCode . $jsFooterInline;
2435  }
2436  } else {
2437  if ($properties['section'] === self::PART_HEADER) {
2438  $jsInline .= $jsCode;
2439  } else {
2440  $jsFooterInline .= $jsCode;
2441  }
2442  }
2443  }
2444  }
2445  if ($jsInline) {
2446  $jsInline = $this->inlineJavascriptWrap[0] . $jsInline . $this->inlineJavascriptWrap[1];
2447  }
2448  if ($jsFooterInline) {
2449  $jsFooterInline = $this->inlineJavascriptWrap[0] . $jsFooterInline . $this->inlineJavascriptWrap[1];
2450  }
2451  if ($this->moveJsFromHeaderToFooter) {
2453  $jsInline = '';
2454  }
2455  return [$jsInline, $jsFooterInline];
2456  }
2457 
2468  protected function includeLanguageFileForInline($fileRef, $selectionPrefix = '', $stripFromSelectionName = '', $errorMode = 0)
2469  {
2470  if (!isset($this->lang) || !isset($this->charSet)) {
2471  throw new \RuntimeException('Language and character encoding are not set.', 1284906026);
2472  }
2473  $labelsFromFile = [];
2474  $allLabels = $this->readLLfile($fileRef, $errorMode);
2475  if ($allLabels !== false) {
2476  // Merge language specific translations:
2477  if ($this->lang !== 'default' && isset($allLabels[$this->lang])) {
2478  $labels = array_merge($allLabels['default'], $allLabels[$this->lang]);
2479  } else {
2480  $labels = $allLabels['default'];
2481  }
2482  // Iterate through all locallang labels:
2483  foreach ($labels as $label => $value) {
2484  // If $selectionPrefix is set, only respect labels that start with $selectionPrefix
2485  if ($selectionPrefix === '' || strpos($label, $selectionPrefix) === 0) {
2486  // Remove substring $stripFromSelectionName from label
2487  $label = str_replace($stripFromSelectionName, '', $label);
2488  $labelsFromFile[$label] = $value;
2489  }
2490  }
2491  $this->inlineLanguageLabels = array_merge($this->inlineLanguageLabels, $labelsFromFile);
2492  }
2493  }
2494 
2502  protected function readLLfile($fileRef, $errorMode = 0)
2503  {
2505  $languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
2506 
2507  if ($this->lang !== 'default') {
2508  $languages = array_reverse($this->languageDependencies);
2509  // At least we need to have English
2510  if (empty($languages)) {
2511  $languages[] = 'default';
2512  }
2513  } else {
2514  $languages = ['default'];
2515  }
2516 
2517  $localLanguage = [];
2518  foreach ($languages as $language) {
2519  $tempLL = $languageFactory->getParsedData($fileRef, $language, $this->charSet, $errorMode);
2520 
2521  $localLanguage['default'] = $tempLL['default'];
2522  if (!isset($localLanguage[$this->lang])) {
2523  $localLanguage[$this->lang] = $localLanguage['default'];
2524  }
2525  if ($this->lang !== 'default' && isset($tempLL[$language])) {
2526  // Merge current language labels onto labels from previous language
2527  // This way we have a labels with fall back applied
2528  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$this->lang], $tempLL[$language], true, false);
2529  }
2530  }
2531 
2532  return $localLanguage;
2533  }
2534 
2535  /*****************************************************/
2536  /* */
2537  /* Tools */
2538  /* */
2539  /*****************************************************/
2546  protected function doConcatenate()
2547  {
2548  $this->doConcatenateCss();
2549  $this->doConcatenateJavaScript();
2550  }
2551 
2557  protected function doConcatenateJavaScript()
2558  {
2559  if ($this->concatenateFiles || $this->concatenateJavascript) {
2560  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'])) {
2561  // use external concatenation routine
2562  $params = [
2563  'jsLibs' => &$this->jsLibs,
2564  'jsFiles' => &$this->jsFiles,
2565  'jsFooterFiles' => &$this->jsFooterFiles,
2566  'headerData' => &$this->headerData,
2567  'footerData' => &$this->footerData
2568  ];
2569  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsConcatenateHandler'], $params, $this);
2570  } else {
2571  $this->jsLibs = $this->getCompressor()->concatenateJsFiles($this->jsLibs);
2572  $this->jsFiles = $this->getCompressor()->concatenateJsFiles($this->jsFiles);
2573  $this->jsFooterFiles = $this->getCompressor()->concatenateJsFiles($this->jsFooterFiles);
2574  }
2575  }
2576  }
2577 
2583  protected function doConcatenateCss()
2584  {
2585  if ($this->concatenateFiles || $this->concatenateCss) {
2586  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'])) {
2587  // use external concatenation routine
2588  $params = [
2589  'cssFiles' => &$this->cssFiles,
2590  'cssLibs' => &$this->cssLibs,
2591  'headerData' => &$this->headerData,
2592  'footerData' => &$this->footerData
2593  ];
2594  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssConcatenateHandler'], $params, $this);
2595  } else {
2596  $cssOptions = [];
2597  if (TYPO3_MODE === 'BE') {
2598  $cssOptions = ['baseDirectories' => $GLOBALS['TBE_TEMPLATE']->getSkinStylesheetDirectories()];
2599  }
2600  $this->cssLibs = $this->getCompressor()->concatenateCssFiles($this->cssLibs, $cssOptions);
2601  $this->cssFiles = $this->getCompressor()->concatenateCssFiles($this->cssFiles, $cssOptions);
2602  }
2603  }
2604  }
2605 
2611  protected function doCompress()
2612  {
2613  $this->doCompressJavaScript();
2614  $this->doCompressCss();
2615  }
2616 
2622  protected function doCompressCss()
2623  {
2624  if ($this->compressCss) {
2625  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'])) {
2626  // Use external compression routine
2627  $params = [
2628  'cssInline' => &$this->cssInline,
2629  'cssFiles' => &$this->cssFiles,
2630  'cssLibs' => &$this->cssLibs,
2631  'headerData' => &$this->headerData,
2632  'footerData' => &$this->footerData
2633  ];
2634  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['cssCompressHandler'], $params, $this);
2635  } else {
2636  $this->cssLibs = $this->getCompressor()->compressCssFiles($this->cssLibs);
2637  $this->cssFiles = $this->getCompressor()->compressCssFiles($this->cssFiles);
2638  }
2639  }
2640  }
2641 
2647  protected function doCompressJavaScript()
2648  {
2649  if ($this->compressJavascript) {
2650  if (!empty($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'])) {
2651  // Use external compression routine
2652  $params = [
2653  'jsInline' => &$this->jsInline,
2654  'jsFooterInline' => &$this->jsFooterInline,
2655  'jsLibs' => &$this->jsLibs,
2656  'jsFiles' => &$this->jsFiles,
2657  'jsFooterFiles' => &$this->jsFooterFiles,
2658  'headerData' => &$this->headerData,
2659  'footerData' => &$this->footerData
2660  ];
2661  GeneralUtility::callUserFunction($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['jsCompressHandler'], $params, $this);
2662  } else {
2663  // Traverse the arrays, compress files
2664  if (!empty($this->jsInline)) {
2665  foreach ($this->jsInline as $name => $properties) {
2666  if ($properties['compress']) {
2667  $error = '';
2668  $this->jsInline[$name]['code'] = GeneralUtility::minifyJavaScript($properties['code'], $error);
2669  if ($error) {
2670  $this->compressError .= 'Error with minify JS Inline Block "' . $name . '": ' . $error . LF;
2671  }
2672  }
2673  }
2674  }
2675  $this->jsLibs = $this->getCompressor()->compressJsFiles($this->jsLibs);
2676  $this->jsFiles = $this->getCompressor()->compressJsFiles($this->jsFiles);
2677  $this->jsFooterFiles = $this->getCompressor()->compressJsFiles($this->jsFooterFiles);
2678  }
2679  }
2680  }
2681 
2687  protected function getCompressor()
2688  {
2689  if ($this->compressor === null) {
2690  $this->compressor = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\ResourceCompressor::class);
2691  }
2692  return $this->compressor;
2693  }
2694 
2703  protected function processJsFile($filename)
2704  {
2705  switch (TYPO3_MODE) {
2706  case 'FE':
2707  if ($this->compressJavascript) {
2708  $filename = $this->getCompressor()->compressJsFile($filename);
2709  } else {
2710  $filename = GeneralUtility::createVersionNumberedFilename($filename);
2711  }
2712  break;
2713  case 'BE':
2714  if ($this->compressJavascript) {
2715  $filename = $this->getCompressor()->compressJsFile($filename);
2716  }
2717  break;
2718  }
2719  return $filename;
2720  }
2721 
2727  protected function getTypoScriptFrontendController()
2728  {
2729  return $GLOBALS['TSFE'];
2730  }
2731 
2737  protected function getLanguageService()
2738  {
2739  return $GLOBALS['LANG'];
2740  }
2741 
2742  /*****************************************************/
2743  /* */
2744  /* Hooks */
2745  /* */
2746  /*****************************************************/
2752  protected function executePreRenderHook()
2753  {
2754  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'])) {
2755  $params = [
2756  'jsLibs' => &$this->jsLibs,
2757  'jsFooterLibs' => &$this->jsFooterLibs,
2758  'jsFiles' => &$this->jsFiles,
2759  'jsFooterFiles' => &$this->jsFooterFiles,
2760  'cssLibs' => &$this->cssLibs,
2761  'cssFiles' => &$this->cssFiles,
2762  'headerData' => &$this->headerData,
2763  'footerData' => &$this->footerData,
2764  'jsInline' => &$this->jsInline,
2765  'jsFooterInline' => &$this->jsFooterInline,
2766  'cssInline' => &$this->cssInline
2767  ];
2768  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'] as $hook) {
2770  }
2771  }
2772  }
2773 
2779  protected function executeRenderPostTransformHook()
2780  {
2781  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'])) {
2782  $params = [
2783  'jsLibs' => &$this->jsLibs,
2784  'jsFooterLibs' => &$this->jsFooterLibs,
2785  'jsFiles' => &$this->jsFiles,
2786  'jsFooterFiles' => &$this->jsFooterFiles,
2787  'cssLibs' => &$this->cssLibs,
2788  'cssFiles' => &$this->cssFiles,
2789  'headerData' => &$this->headerData,
2790  'footerData' => &$this->footerData,
2791  'jsInline' => &$this->jsInline,
2792  'jsFooterInline' => &$this->jsFooterInline,
2793  'cssInline' => &$this->cssInline
2794  ];
2795  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postTransform'] as $hook) {
2797  }
2798  }
2799  }
2800 
2816  {
2817  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'])) {
2818  $params = [
2819  'jsLibs' => &$jsLibs,
2820  'jsFiles' => &$jsFiles,
2821  'jsFooterFiles' => &$jsFooterFiles,
2822  'cssLibs' => &$cssLibs,
2823  'cssFiles' => &$cssFiles,
2824  'headerData' => &$this->headerData,
2825  'footerData' => &$this->footerData,
2826  'jsInline' => &$jsInline,
2827  'cssInline' => &$cssInline,
2828  'xmlPrologAndDocType' => &$this->xmlPrologAndDocType,
2829  'htmlTag' => &$this->htmlTag,
2830  'headTag' => &$this->headTag,
2831  'charSet' => &$this->charSet,
2832  'metaCharsetTag' => &$this->metaCharsetTag,
2833  'shortcutTag' => &$this->shortcutTag,
2834  'inlineComments' => &$this->inlineComments,
2835  'baseUrl' => &$this->baseUrl,
2836  'baseUrlTag' => &$this->baseUrlTag,
2837  'favIcon' => &$this->favIcon,
2838  'iconMimeType' => &$this->iconMimeType,
2839  'titleTag' => &$this->titleTag,
2840  'title' => &$this->title,
2841  'metaTags' => &$this->metaTags,
2842  'jsFooterInline' => &$jsFooterInline,
2843  'jsFooterLibs' => &$jsFooterLibs,
2844  'bodyContent' => &$this->bodyContent
2845  ];
2846  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-postProcess'] as $hook) {
2848  }
2849  }
2850  }
2851 }
static minifyJavaScript($script, &$error='')
loadJquery($version=null, $source=null, $namespace=self::JQUERY_NAMESPACE_DEFAULT)
renderJavaScriptAndCssForProcessingOfUncachedContentObjects($cachedPageContent, $substituteHash)
renderPageWithUncachedObjects($substituteHash)
addInlineSettingArray($namespace, array $array)
getPreparedMarkerArrayForPageWithUncachedObjects($substituteHash)
renderJqueryScriptTag($version, $source, $namespace)
addJsFooterInlineCode($name, $block, $compress=true, $forceOnTop=false)
addJsFooterLibrary($name, $file, $type='text/javascript', $compress=false, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $async=false, $integrity='')
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='|')
setXmlPrologAndDocType($xmlPrologAndDocType)
addInlineSetting($namespace, $key, $value)
static hmac($input, $additionalSecret='')
render($part=self::PART_COMPLETE)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
getPreparedMarkerArray($jsLibs, $jsFiles, $jsFooterFiles, $cssLibs, $cssFiles, $jsInline, $cssInline, $jsFooterInline, $jsFooterLibs, $metaTags)
addCssInlineBlock($name, $block, $compress=false, $forceOnTop=false)
loadExtJS($css=true, $theme=true)
includeLanguageFileForInline($fileRef, $selectionPrefix='', $stripFromSelectionName='', $errorMode=0)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
__construct($templateFile='', $backPath=null)
static getUrl($url, $includeHeader=0, $requestHeaders=false, &$report=null)
addJsInlineCode($name, $block, $compress=true, $forceOnTop=false)
addInlineLanguageLabelFile($fileRef, $selectionPrefix='', $stripFromSelectionName='', $errorMode=0)
static getFileAbsFileName($filename, $onlyRelative=true, $relToTYPO3_mainDir=false)
static getRelativePath($sourcePath, $targetPath)
Definition: PathUtility.php:70
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
loadRequireJsModule($mainModuleName, $callBackFunction=null)
addInlineLanguageLabelArray(array $array, $parseWithLanguageService=false)
static wrapJS($string, $linebreak=true)
addCssLibrary($file, $rel='stylesheet', $media='all', $title='', $compress=true, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|')
addExtOnReadyCode($block, $forceOnTop=false)
addJsFile($file, $type='text/javascript', $compress=true, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $async=false, $integrity='')
addJsLibrary($name, $file, $type='text/javascript', $compress=false, $forceOnTop=false, $allWrap='', $excludeFromConcatenation=false, $splitChar='|', $async=false, $integrity='')
executePostRenderHook(&$jsLibs, &$jsFiles, &$jsFooterFiles, &$cssLibs, &$cssFiles, &$jsInline, &$cssInline, &$jsFooterInline, &$jsFooterLibs)
addRequireJsConfiguration(array $configuration)